Message ID | 1377705360-12197-5-git-send-email-s.nawrocki@samsung.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Hi Sylwester, Just one doubt below On Wed, 28 Aug 2013, Sylwester Nawrocki wrote: > This patch converts the driver to use v4l2 asynchronous subdev > registration API an the clock API to control the external master > clock directly. > > Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com> > Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> > --- > drivers/media/i2c/s5k6a3.c | 36 ++++++++++++++++++++++++++---------- > 1 file changed, 26 insertions(+), 10 deletions(-) > > diff --git a/drivers/media/i2c/s5k6a3.c b/drivers/media/i2c/s5k6a3.c > index ba86e24..f65a4f8 100644 > --- a/drivers/media/i2c/s5k6a3.c > +++ b/drivers/media/i2c/s5k6a3.c [snip] > @@ -282,7 +297,7 @@ static int s5k6a3_probe(struct i2c_client *client, > pm_runtime_no_callbacks(dev); > pm_runtime_enable(dev); > > - return 0; > + return v4l2_async_register_subdev(sd); If the above fails - don't you have to do any clean up? E.g. below you do disable runtime PM and clean up the media entity. Thanks Guennadi > } > > static int s5k6a3_remove(struct i2c_client *client) > @@ -290,6 +305,7 @@ static int s5k6a3_remove(struct i2c_client *client) > struct v4l2_subdev *sd = i2c_get_clientdata(client); > > pm_runtime_disable(&client->dev); > + v4l2_async_unregister_subdev(sd); > media_entity_cleanup(&sd->entity); > return 0; > } > -- > 1.7.9.5 > --- Guennadi Liakhovetski, Ph.D. Freelance Open-Source Software Developer http://www.open-technology.de/ -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 08/28/2013 06:21 PM, Guennadi Liakhovetski wrote: > Hi Sylwester, > > Just one doubt below > > On Wed, 28 Aug 2013, Sylwester Nawrocki wrote: > >> > This patch converts the driver to use v4l2 asynchronous subdev >> > registration API an the clock API to control the external master >> > clock directly. >> > >> > Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com> >> > Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> >> > --- >> > drivers/media/i2c/s5k6a3.c | 36 ++++++++++++++++++++++++++---------- >> > 1 file changed, 26 insertions(+), 10 deletions(-) >> > >> > diff --git a/drivers/media/i2c/s5k6a3.c b/drivers/media/i2c/s5k6a3.c >> > index ba86e24..f65a4f8 100644 >> > --- a/drivers/media/i2c/s5k6a3.c >> > +++ b/drivers/media/i2c/s5k6a3.c > [snip] > >> > @@ -282,7 +297,7 @@ static int s5k6a3_probe(struct i2c_client *client, >> > pm_runtime_no_callbacks(dev); >> > pm_runtime_enable(dev); >> > >> > - return 0; >> > + return v4l2_async_register_subdev(sd); > > If the above fails - don't you have to do any clean up? E.g. below you do > disable runtime PM and clean up the media entity. You're right, the clean up steps are missing. Thanks for pointing out, I've corrected this for the next iteration. Thanks, Sylwester -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/drivers/media/i2c/s5k6a3.c b/drivers/media/i2c/s5k6a3.c index ba86e24..f65a4f8 100644 --- a/drivers/media/i2c/s5k6a3.c +++ b/drivers/media/i2c/s5k6a3.c @@ -34,6 +34,7 @@ #define S5K6A3_DEFAULT_HEIGHT 732 #define S5K6A3_DRV_NAME "S5K6A3" +#define S5K6A3_CLK_NAME "extclk" #define S5K6A3_DEFAULT_CLK_FREQ 24000000U #define S5K6A3_NUM_SUPPLIES 2 @@ -56,6 +57,7 @@ struct s5k6a3 { int gpio_reset; struct mutex lock; struct v4l2_mbus_framefmt format; + struct clk *clock; u32 clock_frequency; }; @@ -181,19 +183,25 @@ static int s5k6a3_s_power(struct v4l2_subdev *sd, int on) { struct s5k6a3 *sensor = sd_to_s5k6a3(sd); int gpio = sensor->gpio_reset; - int ret; + int ret = 0; if (on) { + ret = clk_set_rate(sensor->clock, sensor->clock_frequency); + if (ret < 0) + return ret; + ret = pm_runtime_get(sensor->dev); if (ret < 0) return ret; ret = regulator_bulk_enable(S5K6A3_NUM_SUPPLIES, sensor->supplies); - if (ret < 0) { - pm_runtime_put(sensor->dev); - return ret; - } + if (ret < 0) + goto rpm_put; + + ret = clk_prepare_enable(sensor->clock); + if (ret < 0) + goto reg_dis; if (gpio_is_valid(gpio)) { gpio_set_value(gpio, 1); @@ -209,10 +217,12 @@ static int s5k6a3_s_power(struct v4l2_subdev *sd, int on) if (gpio_is_valid(gpio)) gpio_set_value(gpio, 0); - ret = regulator_bulk_disable(S5K6A3_NUM_SUPPLIES, - sensor->supplies); - if (!ret) - pm_runtime_put(sensor->dev); + clk_disable_unprepare(sensor->clock); +reg_dis: + regulator_bulk_disable(S5K6A3_NUM_SUPPLIES, + sensor->supplies); +rpm_put: + pm_runtime_put(sensor->dev); } return ret; } @@ -240,6 +250,7 @@ static int s5k6a3_probe(struct i2c_client *client, mutex_init(&sensor->lock); sensor->gpio_reset = -EINVAL; + sensor->clock = ERR_PTR(-EINVAL); sensor->dev = dev; gpio = of_get_gpio_flags(dev->of_node, 0, NULL); @@ -266,6 +277,10 @@ static int s5k6a3_probe(struct i2c_client *client, if (ret < 0) return ret; + sensor->clock = devm_clk_get(dev, S5K6A3_CLK_NAME); + if (IS_ERR(sensor->clock)) + return -EPROBE_DEFER; + sd = &sensor->subdev; v4l2_i2c_subdev_init(sd, client, &s5k6a3_subdev_ops); sensor->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; @@ -282,7 +297,7 @@ static int s5k6a3_probe(struct i2c_client *client, pm_runtime_no_callbacks(dev); pm_runtime_enable(dev); - return 0; + return v4l2_async_register_subdev(sd); } static int s5k6a3_remove(struct i2c_client *client) @@ -290,6 +305,7 @@ static int s5k6a3_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); pm_runtime_disable(&client->dev); + v4l2_async_unregister_subdev(sd); media_entity_cleanup(&sd->entity); return 0; }