Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9aea470b authored by Guennadi Liakhovetski's avatar Guennadi Liakhovetski Committed by Mauro Carvalho Chehab
Browse files

[media] soc-camera: switch I2C subdevice drivers to use v4l2-clk



Instead of centrally enabling and disabling subdevice master clocks in
soc-camera core, let subdevice drivers do that themselves, using the
V4L2 clock API and soc-camera convenience wrappers.

Signed-off-by: default avatarGuennadi Liakhovetski <g.liakhovetski@gmx.de>
Acked-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Acked-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent e9e31049
Loading
Loading
Loading
Loading
+16 −2
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include <linux/module.h>

#include <media/soc_camera.h>
#include <media/v4l2-clk.h>
#include <media/v4l2-subdev.h>

/* IMX074 registers */
@@ -76,6 +77,7 @@ struct imx074_datafmt {
struct imx074 {
	struct v4l2_subdev		subdev;
	const struct imx074_datafmt	*fmt;
	struct v4l2_clk			*clk;
};

static const struct imx074_datafmt imx074_colour_fmts[] = {
@@ -254,8 +256,9 @@ static int imx074_s_power(struct v4l2_subdev *sd, int on)
{
	struct i2c_client *client = v4l2_get_subdevdata(sd);
	struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
	struct imx074 *priv = to_imx074(client);

	return soc_camera_set_power(&client->dev, ssdd, on);
	return soc_camera_set_power(&client->dev, ssdd, priv->clk, on);
}

static int imx074_g_mbus_config(struct v4l2_subdev *sd,
@@ -412,6 +415,7 @@ static int imx074_probe(struct i2c_client *client,
	struct imx074 *priv;
	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
	struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
	int ret;

	if (!ssdd) {
		dev_err(&client->dev, "IMX074: missing platform data!\n");
@@ -432,13 +436,23 @@ static int imx074_probe(struct i2c_client *client,

	priv->fmt	= &imx074_colour_fmts[0];

	return imx074_video_probe(client);
	priv->clk = v4l2_clk_get(&client->dev, "mclk");
	if (IS_ERR(priv->clk))
		return PTR_ERR(priv->clk);

	ret = imx074_video_probe(client);
	if (ret < 0)
		v4l2_clk_put(priv->clk);

	return ret;
}

static int imx074_remove(struct i2c_client *client)
{
	struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
	struct imx074 *priv = to_imx074(client);

	v4l2_clk_put(priv->clk);
	if (ssdd->free_bus)
		ssdd->free_bus(ssdd);

+15 −2
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

#include <media/soc_camera.h>
#include <media/soc_mediabus.h>
#include <media/v4l2-clk.h>
#include <media/v4l2-subdev.h>
#include <media/v4l2-ctrls.h>

@@ -93,6 +94,7 @@ struct mt9m001 {
		struct v4l2_ctrl *exposure;
	};
	struct v4l2_rect rect;	/* Sensor window */
	struct v4l2_clk *clk;
	const struct mt9m001_datafmt *fmt;
	const struct mt9m001_datafmt *fmts;
	int num_fmts;
@@ -355,8 +357,9 @@ static int mt9m001_s_power(struct v4l2_subdev *sd, int on)
{
	struct i2c_client *client = v4l2_get_subdevdata(sd);
	struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
	struct mt9m001 *mt9m001 = to_mt9m001(client);

	return soc_camera_set_power(&client->dev, ssdd, on);
	return soc_camera_set_power(&client->dev, ssdd, mt9m001->clk, on);
}

static int mt9m001_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
@@ -681,9 +684,18 @@ static int mt9m001_probe(struct i2c_client *client,
	mt9m001->rect.width	= MT9M001_MAX_WIDTH;
	mt9m001->rect.height	= MT9M001_MAX_HEIGHT;

	mt9m001->clk = v4l2_clk_get(&client->dev, "mclk");
	if (IS_ERR(mt9m001->clk)) {
		ret = PTR_ERR(mt9m001->clk);
		goto eclkget;
	}

	ret = mt9m001_video_probe(ssdd, client);
	if (ret)
	if (ret) {
		v4l2_clk_put(mt9m001->clk);
eclkget:
		v4l2_ctrl_handler_free(&mt9m001->hdl);
	}

	return ret;
}
@@ -693,6 +705,7 @@ static int mt9m001_remove(struct i2c_client *client)
	struct mt9m001 *mt9m001 = to_mt9m001(client);
	struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);

	v4l2_clk_put(mt9m001->clk);
	v4l2_device_unregister_subdev(&mt9m001->subdev);
	v4l2_ctrl_handler_free(&mt9m001->hdl);
	mt9m001_video_remove(ssdd);
+16 −4
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include <linux/module.h>

#include <media/soc_camera.h>
#include <media/v4l2-clk.h>
#include <media/v4l2-common.h>
#include <media/v4l2-ctrls.h>

@@ -206,6 +207,7 @@ struct mt9m111 {
	struct v4l2_ctrl *gain;
	struct mt9m111_context *ctx;
	struct v4l2_rect rect;	/* cropping rectangle */
	struct v4l2_clk *clk;
	int width;		/* output */
	int height;		/* sizes */
	struct mutex power_lock; /* lock to protect power_count */
@@ -775,14 +777,14 @@ static int mt9m111_power_on(struct mt9m111 *mt9m111)
	struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
	int ret;

	ret = soc_camera_power_on(&client->dev, ssdd);
	ret = soc_camera_power_on(&client->dev, ssdd, mt9m111->clk);
	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, ssdd);
		soc_camera_power_off(&client->dev, ssdd, mt9m111->clk);
	}

	return ret;
@@ -794,7 +796,7 @@ static void mt9m111_power_off(struct mt9m111 *mt9m111)
	struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);

	mt9m111_suspend(mt9m111);
	soc_camera_power_off(&client->dev, ssdd);
	soc_camera_power_off(&client->dev, ssdd, mt9m111->clk);
}

static int mt9m111_s_power(struct v4l2_subdev *sd, int on)
@@ -973,9 +975,18 @@ static int mt9m111_probe(struct i2c_client *client,
	mt9m111->lastpage	= -1;
	mutex_init(&mt9m111->power_lock);

	mt9m111->clk = v4l2_clk_get(&client->dev, "mclk");
	if (IS_ERR(mt9m111->clk)) {
		ret = PTR_ERR(mt9m111->clk);
		goto eclkget;
	}

	ret = mt9m111_video_probe(client);
	if (ret)
	if (ret) {
		v4l2_clk_put(mt9m111->clk);
eclkget:
		v4l2_ctrl_handler_free(&mt9m111->hdl);
	}

	return ret;
}
@@ -984,6 +995,7 @@ static int mt9m111_remove(struct i2c_client *client)
{
	struct mt9m111 *mt9m111 = to_mt9m111(client);

	v4l2_clk_put(mt9m111->clk);
	v4l2_device_unregister_subdev(&mt9m111->subdev);
	v4l2_ctrl_handler_free(&mt9m111->hdl);

+16 −3
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include <linux/module.h>

#include <media/soc_camera.h>
#include <media/v4l2-clk.h>
#include <media/v4l2-subdev.h>
#include <media/v4l2-ctrls.h>

@@ -75,6 +76,7 @@ struct mt9t031 {
		struct v4l2_ctrl *exposure;
	};
	struct v4l2_rect rect;	/* Sensor window */
	struct v4l2_clk *clk;
	u16 xskip;
	u16 yskip;
	unsigned int total_h;
@@ -585,16 +587,17 @@ static int mt9t031_s_power(struct v4l2_subdev *sd, int on)
	struct i2c_client *client = v4l2_get_subdevdata(sd);
	struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
	struct video_device *vdev = soc_camera_i2c_to_vdev(client);
	struct mt9t031 *mt9t031 = to_mt9t031(client);
	int ret;

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

	return 0;
@@ -785,9 +788,18 @@ static int mt9t031_probe(struct i2c_client *client,
	mt9t031->xskip = 1;
	mt9t031->yskip = 1;

	mt9t031->clk = v4l2_clk_get(&client->dev, "mclk");
	if (IS_ERR(mt9t031->clk)) {
		ret = PTR_ERR(mt9t031->clk);
		goto eclkget;
	}

	ret = mt9t031_video_probe(client);
	if (ret)
	if (ret) {
		v4l2_clk_put(mt9t031->clk);
eclkget:
		v4l2_ctrl_handler_free(&mt9t031->hdl);
	}

	return ret;
}
@@ -796,6 +808,7 @@ static int mt9t031_remove(struct i2c_client *client)
{
	struct mt9t031 *mt9t031 = to_mt9t031(client);

	v4l2_clk_put(mt9t031->clk);
	v4l2_device_unregister_subdev(&mt9t031->subdev);
	v4l2_ctrl_handler_free(&mt9t031->hdl);

+21 −4
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@

#include <media/mt9t112.h>
#include <media/soc_camera.h>
#include <media/v4l2-clk.h>
#include <media/v4l2-common.h>

/* you can check PLL/clock info */
@@ -89,6 +90,7 @@ struct mt9t112_priv {
	struct mt9t112_camera_info	*info;
	struct i2c_client		*client;
	struct v4l2_rect		 frame;
	struct v4l2_clk			*clk;
	const struct mt9t112_format	*format;
	int				 num_formats;
	u32				 flags;
@@ -768,8 +770,9 @@ static int mt9t112_s_power(struct v4l2_subdev *sd, int on)
{
	struct i2c_client *client = v4l2_get_subdevdata(sd);
	struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
	struct mt9t112_priv *priv = to_mt9t112(client);

	return soc_camera_set_power(&client->dev, ssdd, on);
	return soc_camera_set_power(&client->dev, ssdd, priv->clk, on);
}

static struct v4l2_subdev_core_ops mt9t112_subdev_core_ops = {
@@ -1092,16 +1095,29 @@ static int mt9t112_probe(struct i2c_client *client,

	v4l2_i2c_subdev_init(&priv->subdev, client, &mt9t112_subdev_ops);

	priv->clk = v4l2_clk_get(&client->dev, "mclk");
	if (IS_ERR(priv->clk))
		return PTR_ERR(priv->clk);

	ret = mt9t112_camera_probe(client);
	if (ret)
		return ret;

	/* Cannot fail: using the default supported pixel code */
	if (!ret)
		mt9t112_set_params(priv, &rect, V4L2_MBUS_FMT_UYVY8_2X8);
	else
		v4l2_clk_put(priv->clk);

	return ret;
}

static int mt9t112_remove(struct i2c_client *client)
{
	struct mt9t112_priv *priv = to_mt9t112(client);

	v4l2_clk_put(priv->clk);
	return 0;
}

static const struct i2c_device_id mt9t112_id[] = {
	{ "mt9t112", 0 },
	{ }
@@ -1113,6 +1129,7 @@ static struct i2c_driver mt9t112_i2c_driver = {
		.name = "mt9t112",
	},
	.probe    = mt9t112_probe,
	.remove   = mt9t112_remove,
	.id_table = mt9t112_id,
};

Loading