Re: [PATCH v3 8/9] soc-camera: Add and use soc_camera_power_[on|off]() helper functions
On Wed, 18 Jul 2012, Laurent Pinchart wrote: Instead of forcing all soc-camera drivers to go through the mid-layer to handle power management, create soc_camera_power_[on|off]() functions that can be called from the subdev .s_power() operation to manage regulators and platform-specific power handling. This allows non soc-camera hosts to use soc-camera-aware clients. Signed-off-by: Laurent Pinchart laurent.pinch...@ideasonboard.com --- drivers/media/video/imx074.c |9 +++ drivers/media/video/mt9m001.c |9 +++ drivers/media/video/mt9m111.c | 52 +- drivers/media/video/mt9t031.c | 11 +++- drivers/media/video/mt9t112.c |9 +++ drivers/media/video/mt9v022.c |9 +++ drivers/media/video/ov2640.c |9 +++ drivers/media/video/ov5642.c | 10 +++- drivers/media/video/ov6650.c |9 +++ drivers/media/video/ov772x.c |9 +++ drivers/media/video/ov9640.c | 10 +++- drivers/media/video/ov9740.c | 24 ++--- drivers/media/video/rj54n1cb0c.c |9 +++ drivers/media/video/soc_camera.c | 82 + drivers/media/video/soc_camera_platform.c | 11 - drivers/media/video/tw9910.c |9 +++ include/media/soc_camera.h| 10 17 files changed, 229 insertions(+), 62 deletions(-) [snip] diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 7bf21da..6abeae2 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -50,43 +50,30 @@ static LIST_HEAD(hosts); static LIST_HEAD(devices); static DEFINE_MUTEX(list_lock); /* Protects the list of hosts */ -static int soc_camera_power_on(struct soc_camera_device *icd, -struct soc_camera_link *icl) +int soc_camera_power_on(struct device *dev, struct soc_camera_link *icl) { - struct v4l2_subdev *sd = soc_camera_to_subdev(icd); int ret = regulator_bulk_enable(icl-num_regulators, icl-regulators); if (ret 0) { - dev_err(icd-pdev, Cannot enable regulators\n); + dev_err(dev, Cannot enable regulators\n); return ret; } if (icl-power) { - ret = icl-power(icd-control, 1); + ret = icl-power(dev, 1); if (ret 0) { - dev_err(icd-pdev, + dev_err(dev, Platform failed to power-on the camera.\n); - goto elinkpwr; + regulator_bulk_disable(icl-num_regulators, +icl-regulators); } } - ret = v4l2_subdev_call(sd, core, s_power, 1); - if (ret 0 ret != -ENOIOCTLCMD ret != -ENODEV) - goto esdpwr; - - return 0; - -esdpwr: - if (icl-power) - icl-power(icd-control, 0); -elinkpwr: - regulator_bulk_disable(icl-num_regulators, -icl-regulators); return ret; } +EXPORT_SYMBOL(soc_camera_power_on); -static int soc_camera_power_off(struct soc_camera_device *icd, - struct soc_camera_link *icl) +int soc_camera_power_off(struct device *dev, struct soc_camera_link *icl) { struct v4l2_subdev *sd = soc_camera_to_subdev(icd); int ret = 0; Oops... Looks like this part went missing during the merge: - v4l2_subdev_call(sd, core, s_power, 0); - Could you please fix and resend just this patch? Thanks Guennadi @@ -94,14 +81,14 @@ static int soc_camera_power_off(struct soc_camera_device *icd, err = v4l2_subdev_call(sd, core, s_power, 0); if (err 0 err != -ENOIOCTLCMD err != -ENODEV) { - dev_err(icd-pdev, Subdev failed to power-off the camera.\n); + dev_err(dev, Subdev failed to power-off the camera.\n); ret = err; } if (icl-power) { - err = icl-power(icd-control, 0); + err = icl-power(dev, 0); if (err 0) { - dev_err(icd-pdev, + dev_err(dev, Platform failed to power-off the camera.\n); ret = ret ? : err; } @@ -110,12 +97,37 @@ static int soc_camera_power_off(struct soc_camera_device *icd, err = regulator_bulk_disable(icl-num_regulators, icl-regulators); if (err 0) { - dev_err(icd-pdev, Cannot disable regulators\n); + dev_err(dev, Cannot disable regulators\n); ret = ret ? : err; } return ret; } +EXPORT_SYMBOL(soc_camera_power_off); + +static int
[PATCH v3 8/9] soc-camera: Add and use soc_camera_power_[on|off]() helper functions
Instead of forcing all soc-camera drivers to go through the mid-layer to handle power management, create soc_camera_power_[on|off]() functions that can be called from the subdev .s_power() operation to manage regulators and platform-specific power handling. This allows non soc-camera hosts to use soc-camera-aware clients. Signed-off-by: Laurent Pinchart laurent.pinch...@ideasonboard.com --- drivers/media/video/imx074.c |9 +++ drivers/media/video/mt9m001.c |9 +++ drivers/media/video/mt9m111.c | 52 +- drivers/media/video/mt9t031.c | 11 +++- drivers/media/video/mt9t112.c |9 +++ drivers/media/video/mt9v022.c |9 +++ drivers/media/video/ov2640.c |9 +++ drivers/media/video/ov5642.c | 10 +++- drivers/media/video/ov6650.c |9 +++ drivers/media/video/ov772x.c |9 +++ drivers/media/video/ov9640.c | 10 +++- drivers/media/video/ov9740.c | 24 ++--- drivers/media/video/rj54n1cb0c.c |9 +++ drivers/media/video/soc_camera.c | 82 + drivers/media/video/soc_camera_platform.c | 11 - drivers/media/video/tw9910.c |9 +++ include/media/soc_camera.h| 10 17 files changed, 229 insertions(+), 62 deletions(-) diff --git a/drivers/media/video/imx074.c b/drivers/media/video/imx074.c index 351e9ba..ade1987 100644 --- a/drivers/media/video/imx074.c +++ b/drivers/media/video/imx074.c @@ -268,6 +268,14 @@ static int imx074_g_chip_ident(struct v4l2_subdev *sd, return 0; } +static int imx074_s_power(struct v4l2_subdev *sd, int on) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct soc_camera_link *icl = soc_camera_i2c_to_link(client); + + return soc_camera_set_power(client-dev, icl, on); +} + static int imx074_g_mbus_config(struct v4l2_subdev *sd, struct v4l2_mbus_config *cfg) { @@ -292,6 +300,7 @@ static struct v4l2_subdev_video_ops imx074_subdev_video_ops = { static struct v4l2_subdev_core_ops imx074_subdev_core_ops = { .g_chip_ident = imx074_g_chip_ident, + .s_power= imx074_s_power, }; static struct v4l2_subdev_ops imx074_subdev_ops = { diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c index 00583f5..cd71230 100644 --- a/drivers/media/video/mt9m001.c +++ b/drivers/media/video/mt9m001.c @@ -377,6 +377,14 @@ static int mt9m001_s_register(struct v4l2_subdev *sd, } #endif +static int mt9m001_s_power(struct v4l2_subdev *sd, int on) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct soc_camera_link *icl = soc_camera_i2c_to_link(client); + + return soc_camera_set_power(client-dev, icl, on); +} + static int mt9m001_g_volatile_ctrl(struct v4l2_ctrl *ctrl) { struct mt9m001 *mt9m001 = container_of(ctrl-handler, @@ -566,6 +574,7 @@ static struct v4l2_subdev_core_ops mt9m001_subdev_core_ops = { .g_register = mt9m001_g_register, .s_register = mt9m001_s_register, #endif + .s_power= mt9m001_s_power, }; static int mt9m001_enum_fmt(struct v4l2_subdev *sd, unsigned int index, diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c index 863d722..e555f77 100644 --- a/drivers/media/video/mt9m111.c +++ b/drivers/media/video/mt9m111.c @@ -831,10 +831,37 @@ static int mt9m111_video_probe(struct i2c_client *client) return v4l2_ctrl_handler_setup(mt9m111-hdl); } +static int mt9m111_power_on(struct mt9m111 *mt9m111) +{ + struct i2c_client *client = v4l2_get_subdevdata(mt9m111-subdev); + struct soc_camera_link *icl = soc_camera_i2c_to_link(client); + int ret; + + ret = soc_camera_power_on(client-dev, icl); + if (ret 0) + return ret; + + ret = mt9m111_resume(mt9m111); + if (ret 0) { + dev_err(client-dev, Failed to resume the sensor: %d\n, ret); + soc_camera_power_off(client-dev, icl); + } + + return ret; +} + +static void mt9m111_power_off(struct mt9m111 *mt9m111) +{ + struct i2c_client *client = v4l2_get_subdevdata(mt9m111-subdev); + struct soc_camera_link *icl = soc_camera_i2c_to_link(client); + + mt9m111_suspend(mt9m111); + soc_camera_power_off(client-dev, icl); +} + static int mt9m111_s_power(struct v4l2_subdev *sd, int on) { struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev); - struct i2c_client *client = v4l2_get_subdevdata(sd); int ret = 0; mutex_lock(mt9m111-power_lock); @@ -844,23 +871,18 @@ static int mt9m111_s_power(struct v4l2_subdev *sd, int on) * update the power state. */ if (mt9m111-power_count == !on) { - if (on) { - ret = mt9m111_resume(mt9m111); -