summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>2009-03-13 06:08:20 -0300
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-03-30 12:43:21 -0300
commit025c18a19d7d7eb8745d25986f982a5f35a85157 (patch)
treeeeca0bd36addeddf1a123f9af26d132a2c94979c
parente802967c7079d2b4cfbd107dc90812605dbcad5a (diff)
V4L/DVB (11027): soc-camera: configure drivers with a default format 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>
-rw-r--r--drivers/media/video/soc_camera.c39
-rw-r--r--include/media/soc_camera.h1
2 files changed, 24 insertions, 16 deletions
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
index fcd6b2ce9c1..6d8bfd4d97e 100644
--- a/drivers/media/video/soc_camera.c
+++ b/drivers/media/video/soc_camera.c
@@ -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);
@@ -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)
@@ -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);
@@ -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);
@@ -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);
@@ -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;
}
diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h
index e9eb60740aa..013c81875d7 100644
--- a/include/media/soc_camera.h
+++ b/include/media/soc_camera.h
@@ -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 */