From patchwork Mon Feb 10 21:54:44 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 3623921 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 64B04BF418 for ; Mon, 10 Feb 2014 22:02:17 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 92337201CD for ; Mon, 10 Feb 2014 22:02:16 +0000 (UTC) Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id A2924201BC for ; Mon, 10 Feb 2014 22:02:15 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1WCyti-0000dz-59; Mon, 10 Feb 2014 22:00:15 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1WCyol-000893-Ul; Mon, 10 Feb 2014 21:55:07 +0000 Received: from perceval.ideasonboard.com ([95.142.166.194]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1WCyoY-00085j-Pn for linux-arm-kernel@lists.infradead.org; Mon, 10 Feb 2014 21:54:55 +0000 Received: from avalon.ideasonboard.com (214.131-246-81.adsl-dyn.isp.belgacom.be [81.246.131.214]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 72712363D0; Mon, 10 Feb 2014 22:52:47 +0100 (CET) From: Laurent Pinchart To: linux-media@vger.kernel.org Subject: [PATCH 5/5] mt9p031: Add support for PLL bypass Date: Mon, 10 Feb 2014 22:54:44 +0100 Message-Id: <1392069284-18024-6-git-send-email-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 1.8.3.2 In-Reply-To: <1392069284-18024-1-git-send-email-laurent.pinchart@ideasonboard.com> References: <1392069284-18024-1-git-send-email-laurent.pinchart@ideasonboard.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140210_165455_004490_5E847A33 X-CRM114-Status: GOOD ( 12.97 ) X-Spam-Score: -2.5 (--) Cc: linux-omap@vger.kernel.org, linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.8 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP When the input clock frequency is out of bounds for the PLL, bypass the PLL and just divide the input clock to achieve the requested output frequency. Signed-off-by: Laurent Pinchart --- drivers/media/i2c/mt9p031.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/drivers/media/i2c/mt9p031.c b/drivers/media/i2c/mt9p031.c index 14a616e..5483ab2 100644 --- a/drivers/media/i2c/mt9p031.c +++ b/drivers/media/i2c/mt9p031.c @@ -78,6 +78,9 @@ #define MT9P031_PLL_CONFIG_1 0x11 #define MT9P031_PLL_CONFIG_2 0x12 #define MT9P031_PIXEL_CLOCK_CONTROL 0x0a +#define MT9P031_PIXEL_CLOCK_INVERT (1 << 15) +#define MT9P031_PIXEL_CLOCK_SHIFT(n) ((n) << 8) +#define MT9P031_PIXEL_CLOCK_DIVIDE(n) ((n) << 0) #define MT9P031_FRAME_RESTART 0x0b #define MT9P031_SHUTTER_DELAY 0x0c #define MT9P031_RST 0x0d @@ -130,6 +133,8 @@ struct mt9p031 { enum mt9p031_model model; struct aptina_pll pll; + unsigned int clk_div; + bool use_pll; int reset; struct v4l2_ctrl_handler ctrls; @@ -198,6 +203,11 @@ static int mt9p031_reset(struct mt9p031 *mt9p031) if (ret < 0) return ret; + ret = mt9p031_write(client, MT9P031_PIXEL_CLOCK_CONTROL, + MT9P031_PIXEL_CLOCK_DIVIDE(mt9p031->clk_div)); + if (ret < 0) + return ret; + return mt9p031_set_output_control(mt9p031, MT9P031_OUTPUT_CONTROL_CEN, 0); } @@ -232,8 +242,24 @@ static int mt9p031_clk_setup(struct mt9p031 *mt9p031) if (ret < 0) return ret; + /* If the external clock frequency is out of bounds for the PLL use the + * pixel clock divider only and disable the PLL. + */ + if (pdata->ext_freq > limits.ext_clock_max) { + unsigned int div; + + div = DIV_ROUND_UP(pdata->ext_freq, pdata->target_freq); + div = roundup_pow_of_two(div) / 2; + + mt9p031->clk_div = max_t(unsigned int, div, 64); + mt9p031->use_pll = false; + + return 0; + } + mt9p031->pll.ext_clock = pdata->ext_freq; mt9p031->pll.pix_clock = pdata->target_freq; + mt9p031->use_pll = true; return aptina_pll_calculate(&client->dev, &limits, &mt9p031->pll); } @@ -243,6 +269,9 @@ static int mt9p031_pll_enable(struct mt9p031 *mt9p031) struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev); int ret; + if (!mt9p031->use_pll) + return 0; + ret = mt9p031_write(client, MT9P031_PLL_CONTROL, MT9P031_PLL_CONTROL_PWRON); if (ret < 0) @@ -268,6 +297,9 @@ static inline int mt9p031_pll_disable(struct mt9p031 *mt9p031) { struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev); + if (!mt9p031->use_pll) + return 0; + return mt9p031_write(client, MT9P031_PLL_CONTROL, MT9P031_PLL_CONTROL_PWROFF); }