Skip to content

Commit

Permalink
[media] soc-camera: Add and use soc_camera_power_[on|off]() helper fu…
Browse files Browse the repository at this point in the history
…nctions

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.pinchart@ideasonboard.com>
[g.liakhovetski@gmx.de: fix compile breakage]
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
  • Loading branch information
Laurent Pinchart authored and Mauro Carvalho Chehab committed Aug 15, 2012
1 parent 24592ad commit 4ec10ba
Show file tree
Hide file tree
Showing 17 changed files with 229 additions and 69 deletions.
9 changes: 9 additions & 0 deletions drivers/media/i2c/soc_camera/imx074.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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 = {
Expand Down
9 changes: 9 additions & 0 deletions drivers/media/i2c/soc_camera/mt9m001.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
52 changes: 37 additions & 15 deletions drivers/media/i2c/soc_camera/mt9m111.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
if (ret) {
dev_err(&client->dev,
"Failed to resume the sensor: %d\n", ret);
goto out;
}
} else {
mt9m111_suspend(mt9m111);
}
if (on)
ret = mt9m111_power_on(mt9m111);
else
mt9m111_power_off(mt9m111);
}

/* Update the power count. */
mt9m111->power_count += on ? 1 : -1;
WARN_ON(mt9m111->power_count < 0);
if (!ret) {
/* Update the power count. */
mt9m111->power_count += on ? 1 : -1;
WARN_ON(mt9m111->power_count < 0);
}

out:
mutex_unlock(&mt9m111->power_lock);
return ret;
}
Expand Down
11 changes: 9 additions & 2 deletions drivers/media/i2c/soc_camera/mt9t031.c
Original file line number Diff line number Diff line change
Expand Up @@ -616,12 +616,19 @@ static struct device_type mt9t031_dev_type = {
static int mt9t031_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);
struct video_device *vdev = soc_camera_i2c_to_vdev(client);
int ret;

if (on)
if (on) {
ret = soc_camera_power_on(&client->dev, icl);
if (ret < 0)
return ret;
vdev->dev.type = &mt9t031_dev_type;
else
} else {
vdev->dev.type = NULL;
soc_camera_power_off(&client->dev, icl);
}

return 0;
}
Expand Down
9 changes: 9 additions & 0 deletions drivers/media/i2c/soc_camera/mt9t112.c
Original file line number Diff line number Diff line change
Expand Up @@ -776,12 +776,21 @@ static int mt9t112_s_register(struct v4l2_subdev *sd,
}
#endif

static int mt9t112_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 struct v4l2_subdev_core_ops mt9t112_subdev_core_ops = {
.g_chip_ident = mt9t112_g_chip_ident,
#ifdef CONFIG_VIDEO_ADV_DEBUG
.g_register = mt9t112_g_register,
.s_register = mt9t112_s_register,
#endif
.s_power = mt9t112_s_power,
};


Expand Down
9 changes: 9 additions & 0 deletions drivers/media/i2c/soc_camera/mt9v022.c
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,14 @@ static int mt9v022_s_register(struct v4l2_subdev *sd,
}
#endif

static int mt9v022_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 mt9v022_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
{
struct mt9v022 *mt9v022 = container_of(ctrl->handler,
Expand Down Expand Up @@ -664,6 +672,7 @@ static struct v4l2_subdev_core_ops mt9v022_subdev_core_ops = {
.g_register = mt9v022_g_register,
.s_register = mt9v022_s_register,
#endif
.s_power = mt9v022_s_power,
};

static int mt9v022_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
Expand Down
9 changes: 9 additions & 0 deletions drivers/media/i2c/soc_camera/ov2640.c
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,14 @@ static int ov2640_s_register(struct v4l2_subdev *sd,
}
#endif

static int ov2640_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);
}

/* Select the nearest higher resolution for capture */
static const struct ov2640_win_size *ov2640_select_win(u32 *width, u32 *height)
{
Expand Down Expand Up @@ -988,6 +996,7 @@ static struct v4l2_subdev_core_ops ov2640_subdev_core_ops = {
.g_register = ov2640_g_register,
.s_register = ov2640_s_register,
#endif
.s_power = ov2640_s_power,
};

static int ov2640_g_mbus_config(struct v4l2_subdev *sd,
Expand Down
10 changes: 7 additions & 3 deletions drivers/media/i2c/soc_camera/ov5642.c
Original file line number Diff line number Diff line change
Expand Up @@ -933,13 +933,17 @@ static int ov5642_g_mbus_config(struct v4l2_subdev *sd,

static int ov5642_s_power(struct v4l2_subdev *sd, int on)
{
struct i2c_client *client;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
int ret;

if (!on)
return 0;
return soc_camera_power_off(&client->dev, icl);

ret = soc_camera_power_on(&client->dev, icl);
if (ret < 0)
return ret;

client = v4l2_get_subdevdata(sd);
ret = ov5642_write_array(client, ov5642_default_regs_init);
if (!ret)
ret = ov5642_set_resolution(sd);
Expand Down
9 changes: 9 additions & 0 deletions drivers/media/i2c/soc_camera/ov6650.c
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,14 @@ static int ov6650_set_register(struct v4l2_subdev *sd,
}
#endif

static int ov6650_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 ov6650_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
Expand Down Expand Up @@ -866,6 +874,7 @@ static struct v4l2_subdev_core_ops ov6650_core_ops = {
.g_register = ov6650_get_register,
.s_register = ov6650_set_register,
#endif
.s_power = ov6650_s_power,
};

/* Request bus settings on camera side */
Expand Down
9 changes: 9 additions & 0 deletions drivers/media/i2c/soc_camera/ov772x.c
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,14 @@ static int ov772x_s_register(struct v4l2_subdev *sd,
}
#endif

static int ov772x_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 const struct ov772x_win_size *ov772x_select_win(u32 width, u32 height)
{
__u32 diff;
Expand Down Expand Up @@ -996,6 +1004,7 @@ static struct v4l2_subdev_core_ops ov772x_subdev_core_ops = {
.g_register = ov772x_g_register,
.s_register = ov772x_s_register,
#endif
.s_power = ov772x_s_power,
};

static int ov772x_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
Expand Down
10 changes: 9 additions & 1 deletion drivers/media/i2c/soc_camera/ov9640.c
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,14 @@ static int ov9640_set_register(struct v4l2_subdev *sd,
}
#endif

static int ov9640_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);
}

/* select nearest higher resolution for capture */
static void ov9640_res_roundup(u32 *width, u32 *height)
{
Expand Down Expand Up @@ -632,7 +640,7 @@ static struct v4l2_subdev_core_ops ov9640_core_ops = {
.g_register = ov9640_get_register,
.s_register = ov9640_set_register,
#endif

.s_power = ov9640_s_power,
};

/* Request bus settings on camera side */
Expand Down
24 changes: 17 additions & 7 deletions drivers/media/i2c/soc_camera/ov9740.c
Original file line number Diff line number Diff line change
Expand Up @@ -786,17 +786,27 @@ static int ov9740_g_chip_ident(struct v4l2_subdev *sd,

static int ov9740_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);
struct ov9740_priv *priv = to_ov9740(sd);

if (!priv->current_enable)
return 0;
int ret;

if (on) {
ov9740_s_fmt(sd, &priv->current_mf);
ov9740_s_stream(sd, priv->current_enable);
ret = soc_camera_power_on(&client->dev, icl);
if (ret < 0)
return ret;

if (priv->current_enable) {
ov9740_s_fmt(sd, &priv->current_mf);
ov9740_s_stream(sd, 1);
}
} else {
ov9740_s_stream(sd, 0);
priv->current_enable = true;
if (priv->current_enable) {
ov9740_s_stream(sd, 0);
priv->current_enable = true;
}

soc_camera_power_off(&client->dev, icl);
}

return 0;
Expand Down
9 changes: 9 additions & 0 deletions drivers/media/i2c/soc_camera/rj54n1cb0c.c
Original file line number Diff line number Diff line change
Expand Up @@ -1180,6 +1180,14 @@ static int rj54n1_s_register(struct v4l2_subdev *sd,
}
#endif

static int rj54n1_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 rj54n1_s_ctrl(struct v4l2_ctrl *ctrl)
{
struct rj54n1 *rj54n1 = container_of(ctrl->handler, struct rj54n1, hdl);
Expand Down Expand Up @@ -1230,6 +1238,7 @@ static struct v4l2_subdev_core_ops rj54n1_subdev_core_ops = {
.g_register = rj54n1_g_register,
.s_register = rj54n1_s_register,
#endif
.s_power = rj54n1_s_power,
};

static int rj54n1_g_mbus_config(struct v4l2_subdev *sd,
Expand Down
9 changes: 9 additions & 0 deletions drivers/media/i2c/soc_camera/tw9910.c
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,14 @@ static int tw9910_s_register(struct v4l2_subdev *sd,
}
#endif

static int tw9910_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 tw9910_set_frame(struct v4l2_subdev *sd, u32 *width, u32 *height)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
Expand Down Expand Up @@ -814,6 +822,7 @@ static struct v4l2_subdev_core_ops tw9910_subdev_core_ops = {
.g_register = tw9910_g_register,
.s_register = tw9910_s_register,
#endif
.s_power = tw9910_s_power,
};

static int tw9910_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
Expand Down
Loading

0 comments on commit 4ec10ba

Please sign in to comment.