This adds support for V4L2 clock and asynchronous subdevice probing. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@xxxxxx> --- drivers/media/i2c/mt9p031.c | 31 +++++++++++++++++++++++++++++-- 1 files changed, 29 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/mt9p031.c b/drivers/media/i2c/mt9p031.c index e328332..9ba38f5 100644 --- a/drivers/media/i2c/mt9p031.c +++ b/drivers/media/i2c/mt9p031.c @@ -23,7 +23,9 @@ #include <linux/videodev2.h> #include <media/mt9p031.h> +#include <media/v4l2-async.h> #include <media/v4l2-chip-ident.h> +#include <media/v4l2-clk.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-subdev.h> @@ -117,6 +119,7 @@ struct mt9p031 { struct media_pad pad; struct v4l2_rect crop; /* Sensor window */ struct v4l2_mbus_framefmt format; + struct v4l2_clk *clk; struct mt9p031_platform_data *pdata; struct mutex power_lock; /* lock to protect power_count */ int power_count; @@ -258,6 +261,10 @@ static inline int mt9p031_pll_disable(struct mt9p031 *mt9p031) static int mt9p031_power_on(struct mt9p031 *mt9p031) { + int ret = v4l2_clk_enable(mt9p031->clk); + if (ret < 0) + return ret; + /* Ensure RESET_BAR is low */ if (mt9p031->reset != -1) { gpio_set_value(mt9p031->reset, 0); @@ -287,6 +294,8 @@ static void mt9p031_power_off(struct mt9p031 *mt9p031) if (mt9p031->pdata->set_xclk) mt9p031->pdata->set_xclk(&mt9p031->subdev, 0); + + v4l2_clk_disable(mt9p031->clk); } static int __mt9p031_set_power(struct mt9p031 *mt9p031, bool on) @@ -912,6 +921,7 @@ static int mt9p031_probe(struct i2c_client *client, { struct mt9p031_platform_data *pdata = client->dev.platform_data; struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); + struct v4l2_clk *clk; struct mt9p031 *mt9p031; unsigned int i; int ret; @@ -927,11 +937,20 @@ static int mt9p031_probe(struct i2c_client *client, return -EIO; } + clk = v4l2_clk_get(&client->dev, "mclk"); + if (IS_ERR(clk)) { + dev_info(&client->dev, "Error %ld getting clock\n", PTR_ERR(clk)); + return -EPROBE_DEFER; + } + mt9p031 = kzalloc(sizeof(*mt9p031), GFP_KERNEL); - if (mt9p031 == NULL) - return -ENOMEM; + if (mt9p031 == NULL) { + ret = -ENOMEM; + goto done; + } mt9p031->pdata = pdata; + mt9p031->clk = clk; mt9p031->output_control = MT9P031_OUTPUT_CONTROL_DEF; mt9p031->mode2 = MT9P031_READ_MODE_2_ROW_BLC; mt9p031->model = did->driver_data; @@ -1010,6 +1029,11 @@ static int mt9p031_probe(struct i2c_client *client, } ret = mt9p031_pll_setup(mt9p031); + if (ret < 0) + goto done; + + mt9p031->subdev.dev = &client->dev; + ret = v4l2_async_register_subdev(&mt9p031->subdev); done: if (ret < 0) { @@ -1019,6 +1043,7 @@ done: v4l2_ctrl_handler_free(&mt9p031->ctrls); media_entity_cleanup(&mt9p031->subdev.entity); kfree(mt9p031); + v4l2_clk_put(clk); } return ret; @@ -1029,11 +1054,13 @@ static int mt9p031_remove(struct i2c_client *client) struct v4l2_subdev *subdev = i2c_get_clientdata(client); struct mt9p031 *mt9p031 = to_mt9p031(subdev); + v4l2_async_unregister_subdev(subdev); v4l2_ctrl_handler_free(&mt9p031->ctrls); v4l2_device_unregister_subdev(subdev); media_entity_cleanup(&subdev->entity); if (mt9p031->reset != -1) gpio_free(mt9p031->reset); + v4l2_clk_put(mt9p031->clk); kfree(mt9p031); return 0; -- 1.7.2.5 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html