Skip to content

Commit

Permalink
V4L/DVB (11027): soc-camera: configure drivers with a default format …
Browse files Browse the repository at this point in the history
…at probe time

Currently soc-camera doesn't set up any image format without an explicit
S_FMT. According to the API this should be supported, for example,
capture-example.c from v4l2-apps by default doesn't issue an S_FMT. This
patch moves negotiating of available host-camera format translations to
probe() time, and restores the state from the last close() on the next
open(). This is needed for some drivers, which power down or reset
hardware after the last user closes the interface. This patch also has a
nice side-effect of avoiding multiple allocation anf freeing of format
translation tables.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
  • Loading branch information
Guennadi Liakhovetski authored and Mauro Carvalho Chehab committed Mar 30, 2009
1 parent e802967 commit 025c18a
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 16 deletions.
39 changes: 23 additions & 16 deletions drivers/media/video/soc_camera.c
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,9 @@ static int soc_camera_set_fmt(struct soc_camera_file *icf,

icd->width = pix->width;
icd->height = pix->height;
icf->vb_vidq.field = pix->field;
icf->vb_vidq.field =
icd->field = pix->field;

if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n",
f->type);
Expand Down Expand Up @@ -339,27 +341,24 @@ static int soc_camera_open(struct file *file)

/* Now we really have to activate the camera */
if (icd->use_count == 1) {
/* Restore parameters before the last close() per V4L2 API */
struct v4l2_format f = {
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
.fmt.pix = {
.width = DEFAULT_WIDTH,
.height = DEFAULT_HEIGHT,
.field = V4L2_FIELD_ANY,
.width = icd->width,
.height = icd->height,
.field = icd->field,
.pixelformat = icd->current_fmt->fourcc,
.colorspace = icd->current_fmt->colorspace,
},
};

ret = soc_camera_init_user_formats(icd);
if (ret < 0)
goto eiufmt;
ret = ici->ops->add(icd);
if (ret < 0) {
dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret);
goto eiciadd;
}

f.fmt.pix.pixelformat = icd->current_fmt->fourcc;
f.fmt.pix.colorspace = icd->current_fmt->colorspace;

/* Try to configure with default parameters */
ret = soc_camera_set_fmt(icf, &f);
if (ret < 0)
Expand All @@ -382,8 +381,6 @@ static int soc_camera_open(struct file *file)
esfmt:
ici->ops->remove(icd);
eiciadd:
soc_camera_free_user_formats(icd);
eiufmt:
icd->use_count--;
mutex_unlock(&icd->video_lock);
module_put(ici->ops->owner);
Expand All @@ -403,10 +400,9 @@ static int soc_camera_close(struct file *file)

mutex_lock(&icd->video_lock);
icd->use_count--;
if (!icd->use_count) {
if (!icd->use_count)
ici->ops->remove(icd);
soc_camera_free_user_formats(icd);
}

mutex_unlock(&icd->video_lock);

module_put(icd->ops->owner);
Expand Down Expand Up @@ -874,9 +870,18 @@ static int soc_camera_probe(struct device *dev)
qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE);
icd->exposure = qctrl ? qctrl->default_value :
(unsigned short)~0;

ret = soc_camera_init_user_formats(icd);
if (ret < 0)
goto eiufmt;

icd->height = DEFAULT_HEIGHT;
icd->width = DEFAULT_WIDTH;
icd->field = V4L2_FIELD_ANY;
}
ici->ops->remove(icd);

eiufmt:
ici->ops->remove(icd);
eiadd:
mutex_unlock(&icd->video_lock);
module_put(ici->ops->owner);
Expand All @@ -895,6 +900,8 @@ static int soc_camera_remove(struct device *dev)
if (icd->ops->remove)
icd->ops->remove(icd);

soc_camera_free_user_formats(icd);

return 0;
}

Expand Down
1 change: 1 addition & 0 deletions include/media/soc_camera.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ struct soc_camera_device {
int num_formats;
struct soc_camera_format_xlate *user_formats;
int num_user_formats;
enum v4l2_field field; /* Preserve field over close() */
struct module *owner;
void *host_priv; /* Per-device host private data */
/* soc_camera.c private count. Only accessed with .video_lock held */
Expand Down

0 comments on commit 025c18a

Please sign in to comment.