On Monday 08 February 2010, Guennadi Liakhovetski wrote: > To save power soc-camera powers subdevices down, when they are not in use, > if this is supported by the platform. However, the V4L standard dictates, > that video nodes shall preserve configuration between uses. This requires > runtime power management, which is implemented by this patch. It allows > subdevice drivers to specify their runtime power-management methods, by > assigning a type to the video device. You need a support for that at the bus type/device type/device class level, because the core doesn't execute the driver callbacks directly. Rafael > > Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@xxxxxx> > --- > > I've posted this patch to linux-media earlier, but I'd also like to get > comments on linux-pm, sorry to linux-media falks for a duplicate. To > explain a bit - soc_camera.c is a management module, that binds video > interfaces on SoCs and sensor drivers. The calls, that I am adding to > soc_camera.c shall save and restore sensor registers before they are > powered down and after they are powered up. > > diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c > index 6b3fbcc..53201f3 100644 > --- a/drivers/media/video/soc_camera.c > +++ b/drivers/media/video/soc_camera.c > @@ -24,6 +24,7 @@ > #include <linux/mutex.h> > #include <linux/module.h> > #include <linux/platform_device.h> > +#include <linux/pm_runtime.h> > #include <linux/vmalloc.h> > > #include <media/soc_camera.h> > @@ -387,6 +388,11 @@ static int soc_camera_open(struct file *file) > goto eiciadd; > } > > + pm_runtime_enable(&icd->vdev->dev); > + ret = pm_runtime_resume(&icd->vdev->dev); > + if (ret < 0 && ret != -ENOSYS) > + goto eresume; > + > /* > * Try to configure with default parameters. Notice: this is the > * very first open, so, we cannot race against other calls, > @@ -408,10 +414,12 @@ static int soc_camera_open(struct file *file) > return 0; > > /* > - * First five errors are entered with the .video_lock held > + * First four errors are entered with the .video_lock held > * and use_count == 1 > */ > esfmt: > + pm_runtime_disable(&icd->vdev->dev); > +eresume: > ici->ops->remove(icd); > eiciadd: > if (icl->power) > @@ -436,7 +444,11 @@ static int soc_camera_close(struct file *file) > if (!icd->use_count) { > struct soc_camera_link *icl = to_soc_camera_link(icd); > > + pm_runtime_suspend(&icd->vdev->dev); > + pm_runtime_disable(&icd->vdev->dev); > + > ici->ops->remove(icd); > + > if (icl->power) > icl->power(icd->pdev, 0); > } > @@ -1294,6 +1306,7 @@ static int video_dev_create(struct soc_camera_device *icd) > */ > static int soc_camera_video_start(struct soc_camera_device *icd) > { > + struct device_type *type = icd->vdev->dev.type; > int ret; > > if (!icd->dev.parent) > @@ -1310,6 +1323,9 @@ static int soc_camera_video_start(struct soc_camera_device *icd) > return ret; > } > > + /* Restore device type, possibly set by the subdevice driver */ > + icd->vdev->dev.type = type; > + > return 0; > } > > diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h > index dcc5b86..58b39a9 100644 > --- a/include/media/soc_camera.h > +++ b/include/media/soc_camera.h > @@ -282,4 +282,12 @@ static inline void soc_camera_limit_side(unsigned int *start, > extern unsigned long soc_camera_apply_sensor_flags(struct soc_camera_link *icl, > unsigned long flags); > > +/* This is only temporary here - until v4l2-subdev begins to link to video_device */ > +#include <linux/i2c.h> > +static inline struct video_device *soc_camera_i2c_to_vdev(struct i2c_client *client) > +{ > + struct soc_camera_device *icd = client->dev.platform_data; > + return icd->vdev; > +} > + > #endif > _______________________________________________ _______________________________________________ linux-pm mailing list linux-pm@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linux-foundation.org/mailman/listinfo/linux-pm