Commit 4ec10bac authored by Laurent Pinchart's avatar Laurent Pinchart Committed by Mauro Carvalho Chehab
Browse files

[media] 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: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
[g.liakhovetski@gmx.de: fix compile breakage]
Signed-off-by: default avatarGuennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 24592adc
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -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 = {
+9 −0
Original line number Diff line number Diff line
@@ -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,
+37 −15
Original line number Diff line number Diff line
@@ -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);
			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);
	}

	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;
}
+9 −2
Original line number Diff line number Diff line
@@ -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;
}
+9 −0
Original line number Diff line number Diff line
@@ -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,
};


Loading