From patchwork Tue Jul 23 18:39:33 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sylwester Nawrocki X-Patchwork-Id: 19372 X-Patchwork-Delegate: sylvester.nawrocki@gmail.com Received: from mail.tu-berlin.de ([130.149.7.33]) by www.linuxtv.org with esmtp (Exim 4.72) (envelope-from ) id 1V1hWb-0002QG-JO; Tue, 23 Jul 2013 20:41:29 +0200 X-tubIT-Incoming-IP: 209.132.180.67 Received: from vger.kernel.org ([209.132.180.67]) by mail.tu-berlin.de (exim-4.72/mailfrontend-8) with esmtp id 1V1hWZ-0004r2-lB; Tue, 23 Jul 2013 20:41:29 +0200 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933814Ab3GWSlZ (ORCPT + 1 other); Tue, 23 Jul 2013 14:41:25 -0400 Received: from mailout4.samsung.com ([203.254.224.34]:38400 "EHLO mailout4.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933577Ab3GWSlY (ORCPT ); Tue, 23 Jul 2013 14:41:24 -0400 Received: from epcpsbgm2.samsung.com (epcpsbgm2 [203.254.230.27]) by mailout4.samsung.com (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0MQE00FMLJWUETD0@mailout4.samsung.com>; Wed, 24 Jul 2013 03:41:23 +0900 (KST) X-AuditID: cbfee61b-b7efe6d000007b11-d7-51eece53fd66 Received: from epmmp2 ( [203.254.227.17]) by epcpsbgm2.samsung.com (EPCPMTA) with SMTP id DB.E6.31505.35ECEE15; Wed, 24 Jul 2013 03:41:23 +0900 (KST) Received: from amdc1344.digital.local ([106.116.147.32]) by mmp2.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTPA id <0MQE0040KJU55Q10@mmp2.samsung.com>; Wed, 24 Jul 2013 03:41:23 +0900 (KST) From: Sylwester Nawrocki To: linux-media@vger.kernel.org Cc: kyungmin.park@samsung.com, linux-samsung-soc@vger.kernel.org, arun.kk@samsung.com, Sylwester Nawrocki Subject: [REVIEW PATCH 2/6] V4L: s5k6a3: Add support for asynchronous subdev registration Date: Tue, 23 Jul 2013 20:39:33 +0200 Message-id: <1374604777-15523-3-git-send-email-s.nawrocki@samsung.com> X-Mailer: git-send-email 1.7.9.5 In-reply-to: <1374604777-15523-1-git-send-email-s.nawrocki@samsung.com> References: <1374604777-15523-1-git-send-email-s.nawrocki@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrFJMWRmVeSWpSXmKPExsVy+t9jQd3gc+8CDf5cVrb4eOo2q8XZpjfs Fj0btrJazDi/j8ni8Jt2VgdWj74tqxg9Pm+SC2CK4rJJSc3JLEst0rdL4Mp4276aseCdfMWP jwENjEcluxg5OSQETCSeTX7FBGGLSVy4t56ti5GLQ0hgOqPE4zdX2CGcDiaJnru3GUGq2AQM JXqP9oHZIgLyEk96b4B1MAu0MEps//OGHSQhLBAt8frPJxYQm0VAVeLz/zawOK+Am8SRvTOB bA6gdQoScybZgIQ5Bdwl9qydAjZTCKik/W0r8wRG3gWMDKsYRVMLkguKk9JzjfSKE3OLS/PS 9ZLzczcxgkPkmfQOxlUNFocYBTgYlXh4C2a9CxRiTSwrrsw9xCjBwawkwrtUCijEm5JYWZVa lB9fVJqTWnyIUZqDRUmc92CrdaCQQHpiSWp2ampBahFMlomDU6qB0WVBkLEet9r+M08dpt24 sH/r09faqQ+sDk5x2rck6Mmm/EKr2saZqjkSqdMWvn2a8tqg6qaBdtxJ+RXRE75NWi0SyunO xvEi1NQl+T4D/1fNuUv3fNpoHv+snVfo9YJ9/7JUHLoyknsmqce6yGkZsTVN1WtOTnat4uiK ePVb9keK7/LvlbK9SizFGYmGWsxFxYkArq6Piw0CAAA= Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-PMX-Version: 6.0.0.2142326, Antispam-Engine: 2.7.2.2107409, Antispam-Data: 2013.7.23.183318 X-PMX-Spam: Gauge=IIIIIIII, Probability=8%, Report=' MULTIPLE_RCPTS 0.1, HTML_00_01 0.05, HTML_00_10 0.05, BODY_SIZE_4000_4999 0, BODY_SIZE_5000_LESS 0, BODY_SIZE_7000_LESS 0, URI_ENDS_IN_HTML 0, __ANY_URI 0, __CP_URI_IN_BODY 0, __HAS_FROM 0, __HAS_MSGID 0, __HAS_X_MAILER 0, __HAS_X_MAILING_LIST 0, __IN_REP_TO 0, __MIME_TEXT_ONLY 0, __MULTIPLE_RCPTS_CC_X2 0, __SANE_MSGID 0, __TO_MALFORMED_2 0, __TO_NO_NAME 0, __URI_NO_WWW 0, __URI_NS ' This patch converts the driver to use v4l2 asynchronous subdev registration API an the common clock API. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park --- drivers/media/i2c/s5k6a3.c | 63 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 52 insertions(+), 11 deletions(-) diff --git a/drivers/media/i2c/s5k6a3.c b/drivers/media/i2c/s5k6a3.c index 21680fa..ccbb4fc 100644 --- a/drivers/media/i2c/s5k6a3.c +++ b/drivers/media/i2c/s5k6a3.c @@ -34,6 +34,7 @@ #define S5K6A3_DEF_PIX_HEIGHT 732 #define S5K6A3_DRV_NAME "S5K6A3" +#define S5K6A3_CLK_NAME "mclk" #define S5K6A3_NUM_SUPPLIES 2 @@ -55,6 +56,7 @@ struct s5k6a3 { int gpio_reset; struct mutex lock; struct v4l2_mbus_framefmt format; + struct clk *clock; u32 clock_frequency; }; @@ -180,19 +182,29 @@ 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) { + sensor->clock = clk_get(sensor->dev, S5K6A3_CLK_NAME); + if (IS_ERR(sensor->clock)) + return PTR_ERR(sensor->clock); + + ret = clk_set_rate(sensor->clock, sensor->clock_frequency); + if (ret < 0) + goto clk_put; + ret = pm_runtime_get(sensor->dev); if (ret < 0) - return ret; + goto clk_put; 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); @@ -208,10 +220,14 @@ 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); +clk_put: + clk_put(sensor->clock); } return ret; } @@ -239,6 +255,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); @@ -250,6 +267,13 @@ static int s5k6a3_probe(struct i2c_client *client, } sensor->gpio_reset = gpio; + if (of_property_read_u32(dev->of_node, "clock-frequency", + &sensor->clock_frequency)) { + dev_err(dev, "clock-frequency property not found at %s\n", + dev->of_node->full_name); + return -EINVAL; + } + for (i = 0; i < S5K6A3_NUM_SUPPLIES; i++) sensor->supplies[i].supply = s5k6a3_supply_names[i]; @@ -258,6 +282,11 @@ static int s5k6a3_probe(struct i2c_client *client, if (ret < 0) return ret; + /* Defer probing if the clock is not available yet */ + sensor->clock = 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); snprintf(sd->name, sizeof(sd->name), S5K6A3_DRV_NAME); @@ -275,12 +304,24 @@ static int s5k6a3_probe(struct i2c_client *client, pm_runtime_no_callbacks(dev); pm_runtime_enable(dev); - return 0; + ret = v4l2_async_register_subdev(sd); + + /* + * Don't hold reference to the clock to avoid circular dependency + * between the subdev and the host driver, in case the host is + * a supplier of the clock. + * clk_get()/clk_put() will be called in s_power callback. + */ + clk_put(sensor->clock); + + return ret; } static int s5k6a3_remove(struct i2c_client *client) { struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_async_unregister_subdev(sd); media_entity_cleanup(&sd->entity); return 0; }