The patch number 11027 was added via Guennadi Liakhovetski 
<[email protected]>
to http://linuxtv.org/hg/v4l-dvb master development tree.

Kernel patches in this development tree may be modified to be backward
compatible with older kernels. Compatibility modifications will be
removed before inclusion into the mainstream Kernel

If anyone has any objections, please let us know by sending a message to:
        Linux Media Mailing List <[email protected]>

------

From: Guennadi Liakhovetski  <[email protected]>
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 <[email protected]>
---
 drivers/media/video/soc_camera.c |   39 ++++++++++++++++++++++---------------
 include/media/soc_camera.h       |    1 +
 2 files changed, 24 insertions(+), 16 deletions(-)


---

 linux/drivers/media/video/soc_camera.c |   41 ++++++++++++++-----------
 linux/include/media/soc_camera.h       |    1 
 2 files changed, 25 insertions(+), 17 deletions(-)

diff -r ed3e17bfb375 -r 00074e44c476 linux/drivers/media/video/soc_camera.c
--- a/linux/drivers/media/video/soc_camera.c    Fri Mar 13 10:08:20 2009 +0100
+++ b/linux/drivers/media/video/soc_camera.c    Fri Mar 13 10:08:20 2009 +0100
@@ -287,7 +287,9 @@ static int soc_camera_set_fmt(struct soc
 
        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);
@@ -340,26 +342,23 @@ static int soc_camera_open(struct 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);
@@ -383,8 +382,6 @@ esfmt:
 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);
@@ -404,10 +401,9 @@ static int soc_camera_close(struct 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);
@@ -875,9 +871,18 @@ static int soc_camera_probe(struct devic
                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;
+       }
+
+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 devi
 
        if (icd->ops->remove)
                icd->ops->remove(icd);
+
+       soc_camera_free_user_formats(icd);
 
        return 0;
 }
diff -r ed3e17bfb375 -r 00074e44c476 linux/include/media/soc_camera.h
--- a/linux/include/media/soc_camera.h  Fri Mar 13 10:08:20 2009 +0100
+++ b/linux/include/media/soc_camera.h  Fri Mar 13 10:08:20 2009 +0100
@@ -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 */


---

Patch is available at: 
http://linuxtv.org/hg/v4l-dvb/rev/00074e44c476aa00569e047393737bd04efb62ed

_______________________________________________
linuxtv-commits mailing list
[email protected]
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits

Reply via email to