Received: by 2002:a25:e74b:0:0:0:0:0 with SMTP id e72csp2221333ybh; Fri, 17 Jul 2020 12:13:07 -0700 (PDT) X-Google-Smtp-Source: ABdhPJy/R3pcP852r18/H10nDSvr2RqRlJxF6VH83811p2O9fVxNJY41svH/U51hcE76VhD8r7PE X-Received: by 2002:a17:906:26c3:: with SMTP id u3mr9714614ejc.483.1595013186855; Fri, 17 Jul 2020 12:13:06 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1595013186; cv=none; d=google.com; s=arc-20160816; b=vx3PfPX+6w0d1w0+xd0nknBZQfAqhsL+z0tDrK/Y/ZQ/Q0OK9X8K0wvLXB9f5oqWFG dfwQe1oWb/fLfETW1W1Ck3ipbgPd0yGAgJnG18bojqYDoPs2aoETg+0TU6Hp22LfEIw2 Ydnx1L9mZ5jpfoWAU71F5No2dFEC5BCZuWHDIWtcxCYRWSAgVb2sV6MwMTHnQzD6Btye ZHs61vgoQq75vXVBO7mGcyFaJvYBKRT4NHoHknJ1ltGX9kO/gYy1ElyuDufnbgMYo4yx bCaltxeZaYclOzkkmHy/jCE8H+vx6gP7M40VmqauFTx1V8Gvn3ZEDEpt52j25febijgz htZw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:dkim-signature:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from; bh=boIvlrIG2qx41G9zjbey4MygAAMCqMjJQzTJ18Zg5mk=; b=KEQWn+5pdvFfj6XJRo3c1uej+yGguePCKCMSmLNyJk3IKypA/lS5U3KaLkQ2CgHVt+ +NISOU0dDxoX1Ln1yxduC/YryPB+bSeH6TKoDX+VKMA93u2tYDU/swbo2x0ohr+f8lxH IO1pqcC+8Ap1DpUPZLUIvYKGgI8FXPnP5LTZbuwGkLiCG0MRgL4wrDAz9g6or6T89pir wALOs772y3NC0GFohQR8TW/8JMUtKK+9WxnZ/Jn28t5htCtDikLSvY/xQoso7lsnR6kY YAgSFfCDNzl48Xf2vbIISZGKhyCJXQjeSOk6mmkVHMQh5mZGbbEFZ77nhZGrmZrefRjU zrrQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@nvidia.com header.s=n1 header.b=bJS9Y8xb; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=nvidia.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id cm10si5778139edb.208.2020.07.17.12.12.44; Fri, 17 Jul 2020 12:13:06 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@nvidia.com header.s=n1 header.b=bJS9Y8xb; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=nvidia.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728665AbgGQTMD (ORCPT + 99 others); Fri, 17 Jul 2020 15:12:03 -0400 Received: from hqnvemgate25.nvidia.com ([216.228.121.64]:1403 "EHLO hqnvemgate25.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728639AbgGQTMB (ORCPT ); Fri, 17 Jul 2020 15:12:01 -0400 Received: from hqpgpgate101.nvidia.com (Not Verified[216.228.121.13]) by hqnvemgate25.nvidia.com (using TLS: TLSv1.2, DES-CBC3-SHA) id ; Fri, 17 Jul 2020 12:11:00 -0700 Received: from hqmail.nvidia.com ([172.20.161.6]) by hqpgpgate101.nvidia.com (PGP Universal service); Fri, 17 Jul 2020 12:12:00 -0700 X-PGP-Universal: processed; by hqpgpgate101.nvidia.com on Fri, 17 Jul 2020 12:12:00 -0700 Received: from HQMAIL101.nvidia.com (172.20.187.10) by HQMAIL105.nvidia.com (172.20.187.12) with Microsoft SMTP Server (TLS) id 15.0.1473.3; Fri, 17 Jul 2020 19:11:59 +0000 Received: from rnnvemgw01.nvidia.com (10.128.109.123) by HQMAIL101.nvidia.com (172.20.187.10) with Microsoft SMTP Server (TLS) id 15.0.1473.3 via Frontend Transport; Fri, 17 Jul 2020 19:11:59 +0000 Received: from skomatineni-linux.nvidia.com (Not Verified[10.2.163.115]) by rnnvemgw01.nvidia.com with Trustwave SEG (v7,5,8,10121) id ; Fri, 17 Jul 2020 12:11:59 -0700 From: Sowjanya Komatineni To: , , , , , , , , , CC: , , Subject: [PATCH v2 3/3] media: i2c: imx274: Add IMX274 power on and off sequence Date: Fri, 17 Jul 2020 12:15:22 -0700 Message-ID: <1595013322-15077-3-git-send-email-skomatineni@nvidia.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1595013322-15077-1-git-send-email-skomatineni@nvidia.com> References: <1595013322-15077-1-git-send-email-skomatineni@nvidia.com> X-NVConfidentiality: public MIME-Version: 1.0 Content-Type: text/plain DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nvidia.com; s=n1; t=1595013060; bh=boIvlrIG2qx41G9zjbey4MygAAMCqMjJQzTJ18Zg5mk=; h=X-PGP-Universal:From:To:CC:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:X-NVConfidentiality:MIME-Version: Content-Type; b=bJS9Y8xb6VvtxfhFTwdZDiBJ6i32INrBvfuyigyXBuwjhoYX2BbDLm1hGxS9hxQve HRfme8lDSqahhvaSrXdkkH4VNEwztHGzi6Q1t8jpW/+TFFQHxkeP4p4FvMt9WGMBWq FqZTgeb0ic02lWjg7rRgDhOl4fSgvaC01ZFV+3GfHwCznUuezQphXSIZGuvLtfPz0P 5dj84UYgvKvQH7SuIItAiBevLel53dEFg9sw9W6CmB73aAz9S9P+MSY/Zv7PWpv7Us Q6nU1i6KyE2kIgdxy6G+tbQEFI3FM7kTGhiLcjMsm75ExF6LsssHx6shIHHtr+SxEH k0WF8SR1E1N4g== Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org IMX274 has VANA analog 2.8V supply, VDIG digital core 1.8V supply, and VDDL digital io 1.2V supply which are optional based on camera module design. IMX274 also need external 24Mhz clock and is optional based on camera module design. This patch adds support for IMX274 power on and off to enable and disable these supplies and external clock. Signed-off-by: Sowjanya Komatineni --- drivers/media/i2c/imx274.c | 135 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 132 insertions(+), 3 deletions(-) diff --git a/drivers/media/i2c/imx274.c b/drivers/media/i2c/imx274.c index 55869ff..c3f7bcd 100644 --- a/drivers/media/i2c/imx274.c +++ b/drivers/media/i2c/imx274.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -27,6 +28,8 @@ #include #include +#define IMX274_DEFAULT_CLK_FREQ 24000000 + /* * See "SHR, SVR Setting" in datasheet */ @@ -131,6 +134,15 @@ #define IMX274_TABLE_WAIT_MS 0 #define IMX274_TABLE_END 1 +/* regulator supplies */ +static const char * const imx274_supply_names[] = { + "VDDL", /* IF (1.2V) supply */ + "VDIG", /* Digital Core (1.8V) supply */ + "VANA", /* Analog (2.8V) supply */ +}; + +#define IMX274_NUM_SUPPLIES ARRAY_SIZE(imx274_supply_names) + /* * imx274 I2C operation related structure */ @@ -501,6 +513,8 @@ struct imx274_ctrls { * @frame_rate: V4L2 frame rate structure * @regmap: Pointer to regmap structure * @reset_gpio: Pointer to reset gpio + * @supplies: imx274 analog and digital supplies + * @inck: input clock to imx274 * @lock: Mutex structure * @mode: Parameters for the selected readout mode */ @@ -514,6 +528,8 @@ struct stimx274 { struct v4l2_fract frame_interval; struct regmap *regmap; struct gpio_desc *reset_gpio; + struct regulator *supplies[IMX274_NUM_SUPPLIES]; + struct clk *inck; struct mutex lock; /* mutex lock for operations */ const struct imx274_mode *mode; }; @@ -767,6 +783,98 @@ static void imx274_reset(struct stimx274 *priv, int rst) usleep_range(IMX274_RESET_DELAY1, IMX274_RESET_DELAY2); } +/* + * imx274_power_on - Function called to power on the sensor + * @imx274: Pointer to device structure + */ +static int imx274_power_on(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct stimx274 *imx274 = to_imx274(sd); + int i, ret; + + ret = clk_prepare_enable(imx274->inck); + if (ret) { + dev_err(&imx274->client->dev, "Failed to enable clock\n"); + return ret; + } + + for (i = 0; i < IMX274_NUM_SUPPLIES; i++) { + if (imx274->supplies[i]) { + ret = regulator_enable(imx274->supplies[i]); + if (ret < 0) { + dev_err(&imx274->client->dev, + "Failed to enable %s supply: %d\n", + imx274_supply_names[i], ret); + goto fail_reg; + } + } + } + + usleep_range(1, 2); + imx274_reset(imx274, 1); + + return 0; + +fail_reg: + for (--i; i >= 0; i--) { + if (imx274->supplies[i]) + regulator_disable(imx274->supplies[i]); + } + + clk_disable_unprepare(imx274->inck); + return ret; +} + +/* + * imx274_power_off - Function called to power off the sensor + * @imx274: Pointer to device structure + */ +static int imx274_power_off(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct stimx274 *imx274 = to_imx274(sd); + int i; + + imx274_reset(imx274, 0); + + for (i = 0; i < IMX274_NUM_SUPPLIES; i++) { + if (imx274->supplies[i]) + regulator_disable(imx274->supplies[i]); + } + + clk_disable_unprepare(imx274->inck); + + return 0; +} + +static int imx274_get_regulators(struct device *dev, struct stimx274 *imx274) +{ + int i, err; + const char *supply; + + for (i = 0; i < IMX274_NUM_SUPPLIES; i++) { + supply = imx274_supply_names[i]; + imx274->supplies[i] = devm_regulator_get_optional(dev, supply); + if (!IS_ERR(imx274->supplies[i])) + continue; + err = PTR_ERR(imx274->supplies[i]); + if (err != -ENODEV) { + if (err != -EPROBE_DEFER) + dev_err(&imx274->client->dev, + "Failed to get %s supply: %d\n", + supply, err); + return err; + } + + imx274->supplies[i] = NULL; + } + + return 0; +} + /** * imx274_s_ctrl - This is used to set the imx274 V4L2 controls * @ctrl: V4L2 control to be set @@ -1836,6 +1944,13 @@ static int imx274_probe(struct i2c_client *client) mutex_init(&imx274->lock); + imx274->inck = devm_clk_get_optional(&client->dev, "inck"); + ret = imx274_get_regulators(&client->dev, imx274); + if (ret) { + dev_err(&client->dev, "Failed to get power regulators, err: %d\n", ret); + return ret; + } + /* initialize format */ imx274->mode = &imx274_modes[IMX274_DEFAULT_BINNING]; imx274->crop.width = IMX274_MAX_WIDTH; @@ -1883,15 +1998,26 @@ static int imx274_probe(struct i2c_client *client) goto err_me; } - /* pull sensor out of reset */ - imx274_reset(imx274, 1); + /* power on the sensor */ + ret = imx274_power_on(&client->dev); + if (ret < 0) { + dev_err(&client->dev, + "%s : imx274 power on failed\n", __func__); + goto err_me; + } + + ret = clk_set_rate(imx274->inck, IMX274_DEFAULT_CLK_FREQ); + if (ret < 0) { + dev_err(&client->dev, "Failed to set INCK clock rate\n"); + return ret; + } /* initialize controls */ ret = v4l2_ctrl_handler_init(&imx274->ctrls.handler, 4); if (ret < 0) { dev_err(&client->dev, "%s : ctrl handler init Failed\n", __func__); - goto err_me; + goto err_power_off; } imx274->ctrls.handler.lock = &imx274->lock; @@ -1958,6 +2084,8 @@ static int imx274_probe(struct i2c_client *client) err_ctrls: v4l2_ctrl_handler_free(&imx274->ctrls.handler); +err_power_off: + imx274_power_off(&client->dev); err_me: media_entity_cleanup(&sd->entity); err_regmap: @@ -1975,6 +2103,7 @@ static int imx274_remove(struct i2c_client *client) v4l2_async_unregister_subdev(sd); v4l2_ctrl_handler_free(&imx274->ctrls.handler); + imx274_power_off(&client->dev); media_entity_cleanup(&sd->entity); mutex_destroy(&imx274->lock); return 0; -- 2.7.4