Web lists-archives.org

Re: [PATCH] soc-camera: deactivate cameras when not used




Do you have a git tree or patch series (maybe a mbox patch aggregate)
that I can apply? Also let me know the baseline to apply, I guess it
should apply happily on top of linux-v4l2's current head, but I'm not
sure


On Mon, Feb 25, 2008 at 8:12 PM, Guennadi Liakhovetski
<g.liakhovetski@xxxxxxxxxxxxxx> wrote:
> Only attach cameras to the host interface for probing, then detach until
>  open. This allows platforms with several cameras on an interface,
>  physically supporting only one camera, to handle multiple cameras and
>  activate them selectively after initial probing. The first attach during
>  probe is needed to activate the host interface to be able to physically
>  communicate with cameras.
>
>  Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@xxxxxxxxxxxxxx>
>
>  ---
>
>  Erik, would be nice if you could test this with one of your multi-camera
>  platforms.
>
>  diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
>  index 904e9df..e3f5a17 100644
>  --- a/drivers/media/video/soc_camera.c
>  +++ b/drivers/media/video/soc_camera.c
>  @@ -179,11 +179,9 @@ static int soc_camera_dqbuf(struct file *file, void *priv,
>
>   static int soc_camera_open(struct inode *inode, struct file *file)
>   {
>  -       struct video_device *vdev = video_devdata(file);
>  -       struct soc_camera_device *icd = container_of(vdev->dev,
>  -                                            struct soc_camera_device, dev);
>  -       struct soc_camera_host *ici =
>  -               to_soc_camera_host(icd->dev.parent);
>  +       struct video_device *vdev;
>  +       struct soc_camera_device *icd;
>  +       struct soc_camera_host *ici;
>         struct soc_camera_file *icf;
>         int ret;
>
>  @@ -191,7 +189,12 @@ static int soc_camera_open(struct inode *inode, struct file *file)
>         if (!icf)
>                 return -ENOMEM;
>
>  -       icf->icd = icd;
>  +       /* Protect against icd->remove() until we module_get() both drivers. */
>  +       mutex_lock(&video_lock);
>  +
>  +       vdev = video_devdata(file);
>  +       icd = container_of(vdev->dev, struct soc_camera_device, dev);
>  +       ici = to_soc_camera_host(icd->dev.parent);
>
>         if (!try_module_get(icd->ops->owner)) {
>                 dev_err(&icd->dev, "Couldn't lock sensor driver.\n");
>  @@ -205,6 +208,22 @@ static int soc_camera_open(struct inode *inode, struct file *file)
>                 goto emgi;
>         }
>
>  +       icd->use_count++;
>  +
>  +       icf->icd = icd;
>  +
>  +       /* Now we really have to activate the camera */
>  +       if (icd->use_count == 1) {
>  +               ret = ici->add(icd);
>  +               if (ret < 0) {
>  +                       dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret);
>  +                       icd->use_count--;
>  +                       goto eiciadd;
>  +               }
>  +       }
>  +
>  +       mutex_unlock(&video_lock);
>  +
>         file->private_data = icf;
>         dev_dbg(&icd->dev, "camera device open\n");
>
>  @@ -205,9 +208,13 @@ static int soc_camera_open(struct inode *inode, struct file *file)
>
>         return 0;
>
>  +       /* All errors are entered with the video_lock held */
>  +eiciadd:
>  +       module_put(ici->owner);
>   emgi:
>         module_put(icd->ops->owner);
>   emgd:
>  +       mutex_unlock(&video_lock);
>         vfree(icf);
>         return ret;
>   }
>  @@ -230,8 +253,14 @@ static int soc_camera_close(struct inode *inode, struct file *file)
>         struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
>         struct video_device *vdev = icd->vdev;
>
>  +       mutex_lock(&video_lock);
>  +       icd->use_count--;
>  +       if (!icd->use_count)
>  +               ici->remove(icd);
>         module_put(icd->ops->owner);
>         module_put(ici->owner);
>  +       mutex_unlock(&video_lock);
>  +
>         vfree(file->private_data);
>
>         dev_dbg(vdev->dev, "camera device close\n");
>  @@ -673,14 +702,14 @@ static int soc_camera_probe(struct device *dev)
>         if (!icd->probe)
>                 return -ENODEV;
>
>  +       /* We only call ->add() here to activate and probe the camera.
>  +        * We shall ->remove() and deactivate it immediately afterwards. */
>         ret = ici->add(icd);
>         if (ret < 0)
>                 return ret;
>
>         ret = icd->probe(icd);
>  -       if (ret < 0)
>  -               ici->remove(icd);
>  -       else {
>  +       if (ret >= 0) {
>                 const struct v4l2_queryctrl *qctrl;
>
>                 qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_GAIN);
>  @@ -689,6 +718,7 @@ static int soc_camera_probe(struct device *dev)
>                 icd->exposure = qctrl ? qctrl->default_value :
>                         (unsigned short)~0;
>         }
>  +       ici->remove(icd);
>
>         return ret;
>   }
>  @@ -698,13 +728,9 @@ static int soc_camera_probe(struct device *dev)
>   static int soc_camera_remove(struct device *dev)
>   {
>         struct soc_camera_device *icd = to_soc_camera_dev(dev);
>  -       struct soc_camera_host *ici =
>  -               to_soc_camera_host(icd->dev.parent);
>
>         if (icd->remove)
>                 icd->remove(icd);
>  -
>  -       ici->remove(icd);
>
>         return 0;
>   }
>  diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h
>  index 69aba71..c886b1e 100644
>  --- a/include/media/soc_camera.h
>  +++ b/include/media/soc_camera.h
>  @@ -41,6 +41,8 @@ struct soc_camera_device {
>         int (*probe)(struct soc_camera_device *icd);
>         void (*remove)(struct soc_camera_device *icd);
>         struct module *owner;
>  +       /* soc_camera.c private count. Only accessed with video_lock held */
>  +       int use_count;
>   };
>
>   struct soc_camera_file {
>



-- 
Cheers
- eric

--
video4linux-list mailing list
Unsubscribe mailto:video4linux-list-request@xxxxxxxxxx?subject=unsubscribe
https://www.redhat.com/mailman/listinfo/video4linux-list