Commit 4f9fb5ed authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab

V4L/DVB: soc-camera: add runtime pm support for subdevices

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.
Signed-off-by: default avatarGuennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent e26b3144
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/pm_runtime.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <media/soc_camera.h> #include <media/soc_camera.h>
...@@ -388,6 +389,11 @@ static int soc_camera_open(struct file *file) ...@@ -388,6 +389,11 @@ static int soc_camera_open(struct file *file)
goto eiciadd; 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 * Try to configure with default parameters. Notice: this is the
* very first open, so, we cannot race against other calls, * very first open, so, we cannot race against other calls,
...@@ -409,10 +415,12 @@ static int soc_camera_open(struct file *file) ...@@ -409,10 +415,12 @@ static int soc_camera_open(struct file *file)
return 0; 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 * and use_count == 1
*/ */
esfmt: esfmt:
pm_runtime_disable(&icd->vdev->dev);
eresume:
ici->ops->remove(icd); ici->ops->remove(icd);
eiciadd: eiciadd:
if (icl->power) if (icl->power)
...@@ -437,7 +445,11 @@ static int soc_camera_close(struct file *file) ...@@ -437,7 +445,11 @@ static int soc_camera_close(struct file *file)
if (!icd->use_count) { if (!icd->use_count) {
struct soc_camera_link *icl = to_soc_camera_link(icd); 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); ici->ops->remove(icd);
if (icl->power) if (icl->power)
icl->power(icd->pdev, 0); icl->power(icd->pdev, 0);
} }
...@@ -1319,6 +1331,7 @@ static int video_dev_create(struct soc_camera_device *icd) ...@@ -1319,6 +1331,7 @@ static int video_dev_create(struct soc_camera_device *icd)
*/ */
static int soc_camera_video_start(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; int ret;
if (!icd->dev.parent) if (!icd->dev.parent)
...@@ -1335,6 +1348,9 @@ static int soc_camera_video_start(struct soc_camera_device *icd) ...@@ -1335,6 +1348,9 @@ static int soc_camera_video_start(struct soc_camera_device *icd)
return ret; return ret;
} }
/* Restore device type, possibly set by the subdevice driver */
icd->vdev->dev.type = type;
return 0; return 0;
} }
......
...@@ -284,4 +284,12 @@ static inline void soc_camera_limit_side(int *start, int *length, ...@@ -284,4 +284,12 @@ static inline void soc_camera_limit_side(int *start, int *length,
extern unsigned long soc_camera_apply_sensor_flags(struct soc_camera_link *icl, extern unsigned long soc_camera_apply_sensor_flags(struct soc_camera_link *icl,
unsigned long flags); 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 #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment