aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>2009-03-13 05:08:20 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-03-30 11:43:21 -0400
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 fcd6b2ce9c19..6d8bfd4d97e2 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,
286 286
287 icd->width = pix->width; 287 icd->width = pix->width;
288 icd->height = pix->height; 288 icd->height = pix->height;
289 icf->vb_vidq.field = pix->field; 289 icf->vb_vidq.field =
290 icd->field = pix->field;
291
290 if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 292 if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
291 dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n", 293 dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n",
292 f->type); 294 f->type);
@@ -339,27 +341,24 @@ static int soc_camera_open(struct file *file)
339 341
340 /* Now we really have to activate the camera */ 342 /* Now we really have to activate the camera */
341 if (icd->use_count == 1) { 343 if (icd->use_count == 1) {
344 /* Restore parameters before the last close() per V4L2 API */
342 struct v4l2_format f = { 345 struct v4l2_format f = {
343 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, 346 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
344 .fmt.pix = { 347 .fmt.pix = {
345 .width = DEFAULT_WIDTH, 348 .width = icd->width,
346 .height = DEFAULT_HEIGHT, 349 .height = icd->height,
347 .field = V4L2_FIELD_ANY, 350 .field = icd->field,
351 .pixelformat = icd->current_fmt->fourcc,
352 .colorspace = icd->current_fmt->colorspace,
348 }, 353 },
349 }; 354 };
350 355
351 ret = soc_camera_init_user_formats(icd);
352 if (ret < 0)
353 goto eiufmt;
354 ret = ici->ops->add(icd); 356 ret = ici->ops->add(icd);
355 if (ret < 0) { 357 if (ret < 0) {
356 dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret); 358 dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret);
357 goto eiciadd; 359 goto eiciadd;
358 } 360 }
359 361
360 f.fmt.pix.pixelformat = icd->current_fmt->fourcc;
361 f.fmt.pix.colorspace = icd->current_fmt->colorspace;
362
363 /* Try to configure with default parameters */ 362 /* Try to configure with default parameters */
364 ret = soc_camera_set_fmt(icf, &f); 363 ret = soc_camera_set_fmt(icf, &f);
365 if (ret < 0) 364 if (ret < 0)
@@ -382,8 +381,6 @@ static int soc_camera_open(struct file *file)
382esfmt: 381esfmt:
383 ici->ops->remove(icd); 382 ici->ops->remove(icd);
384eiciadd: 383eiciadd:
385 soc_camera_free_user_formats(icd);
386eiufmt:
387 icd->use_count--; 384 icd->use_count--;
388 mutex_unlock(&icd->video_lock); 385 mutex_unlock(&icd->video_lock);
389 module_put(ici->ops->owner); 386 module_put(ici->ops->owner);
@@ -403,10 +400,9 @@ static int soc_camera_close(struct file *file)
403 400
404 mutex_lock(&icd->video_lock); 401 mutex_lock(&icd->video_lock);
405 icd->use_count--; 402 icd->use_count--;
406 if (!icd->use_count) { 403 if (!icd->use_count)
407 ici->ops->remove(icd); 404 ici->ops->remove(icd);
408 soc_camera_free_user_formats(icd); 405
409 }
410 mutex_unlock(&icd->video_lock); 406 mutex_unlock(&icd->video_lock);
411 407
412 module_put(icd->ops->owner); 408 module_put(icd->ops->owner);
@@ -874,9 +870,18 @@ static int soc_camera_probe(struct device *dev)
874 qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); 870 qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE);
875 icd->exposure = qctrl ? qctrl->default_value : 871 icd->exposure = qctrl ? qctrl->default_value :
876 (unsigned short)~0; 872 (unsigned short)~0;
873
874 ret = soc_camera_init_user_formats(icd);
875 if (ret < 0)
876 goto eiufmt;
877
878 icd->height = DEFAULT_HEIGHT;
879 icd->width = DEFAULT_WIDTH;
880 icd->field = V4L2_FIELD_ANY;
877 } 881 }
878 ici->ops->remove(icd);
879 882
883eiufmt:
884 ici->ops->remove(icd);
880eiadd: 885eiadd:
881 mutex_unlock(&icd->video_lock); 886 mutex_unlock(&icd->video_lock);
882 module_put(ici->ops->owner); 887 module_put(ici->ops->owner);
@@ -895,6 +900,8 @@ static int soc_camera_remove(struct device *dev)
895 if (icd->ops->remove) 900 if (icd->ops->remove)
896 icd->ops->remove(icd); 901 icd->ops->remove(icd);
897 902
903 soc_camera_free_user_formats(icd);
904
898 return 0; 905 return 0;
899} 906}
900 907
diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h
index e9eb60740aaa..013c81875d76 100644
--- a/include/media/soc_camera.h
+++ b/include/media/soc_camera.h
@@ -45,6 +45,7 @@ struct soc_camera_device {
45 int num_formats; 45 int num_formats;
46 struct soc_camera_format_xlate *user_formats; 46 struct soc_camera_format_xlate *user_formats;
47 int num_user_formats; 47 int num_user_formats;
48 enum v4l2_field field; /* Preserve field over close() */
48 struct module *owner; 49 struct module *owner;
49 void *host_priv; /* Per-device host private data */ 50 void *host_priv; /* Per-device host private data */
50 /* soc_camera.c private count. Only accessed with .video_lock held */ 51 /* soc_camera.c private count. Only accessed with .video_lock held */