From patchwork Wed Oct 17 19:37:18 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 10646035 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 12FE9109C for ; Wed, 17 Oct 2018 19:37:37 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0279228750 for ; Wed, 17 Oct 2018 19:37:37 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id EAEBA28762; Wed, 17 Oct 2018 19:37:36 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 72A2F28750 for ; Wed, 17 Oct 2018 19:37:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728397AbeJRDeq (ORCPT ); Wed, 17 Oct 2018 23:34:46 -0400 Received: from relay10.mail.gandi.net ([217.70.178.230]:47481 "EHLO relay10.mail.gandi.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728129AbeJRDeq (ORCPT ); Wed, 17 Oct 2018 23:34:46 -0400 Received: from w540.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay10.mail.gandi.net (Postfix) with ESMTPSA id 559B724000E; Wed, 17 Oct 2018 19:37:32 +0000 (UTC) From: Jacopo Mondi To: maxime.ripard@bootlin.com, sam@elite-embedded.com, mchehab@kernel.org Cc: Jacopo Mondi , laurent.pinchart@ideasonboard.com, hans.verkuil@cisco.com, sakari.ailus@linux.intel.com, linux-media@vger.kernel.org, hugues.fruchet@st.com, loic.poulain@linaro.org, daniel@zonque.org Subject: [PATCH 2/2] media: ov5640: Re-implement MIPI clock configuration Date: Wed, 17 Oct 2018 21:37:18 +0200 Message-Id: <1539805038-22321-3-git-send-email-jacopo+renesas@jmondi.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1539805038-22321-1-git-send-email-jacopo+renesas@jmondi.org> References: <1539805038-22321-1-git-send-email-jacopo+renesas@jmondi.org> Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Modify the MIPI clock tree calculation procedure. The implemented function receives the total bandwidth required in bytes and calculate the sample rate and the MIPI clock rate accordingly. Tested with capture at 1080p, 720p, VGA and QVGA. Signed-off-by: Jacopo Mondi --- drivers/media/i2c/ov5640.c | 101 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 80 insertions(+), 21 deletions(-) diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c index 1f2e72d..8a0ead9 100644 --- a/drivers/media/i2c/ov5640.c +++ b/drivers/media/i2c/ov5640.c @@ -720,6 +720,9 @@ static int ov5640_mod_reg(struct ov5640_dev *sensor, u16 reg, * +->| MIPI Divider | - reg 0x3035, bits 0-3 * | +-+------------+ * | +----------------> MIPI SCLK + * | + +-----+ + * | +->| / 2 |-------> MIPI BIT CLK + * | +-----+ * | +--------------+ * +->| PLL Root Div | - reg 0x3037, bit 4 * +-+------------+ @@ -782,13 +785,14 @@ static int ov5640_mod_reg(struct ov5640_dev *sensor, u16 reg, * This is supposed to be ranging from 1 to 2, but the value is always * set to 2 in the vendor kernels. */ -#define OV5640_PLL_ROOT_DIV 2 +#define OV5640_PLL_ROOT_DIV 2 +#define OV5640_PLL_CTRL3_PLL_ROOT_DIV_2 BIT(4) /* - * This is supposed to be either 1, 2 or 2.5, but the value is always - * set to 2 in the vendor kernels. + * We only supports 8-bit formats at the moment */ -#define OV5640_BIT_DIV 2 +#define OV5640_BIT_DIV 2 +#define OV5640_PLL_CTRL0_MIPI_MODE_8BIT 0x08 /* * This is supposed to be ranging from 1 to 8, but the value is always @@ -874,32 +878,81 @@ static unsigned long ov5640_calc_sys_clk(struct ov5640_dev *sensor, *sysdiv = best_sysdiv; *pll_prediv = OV5640_PLL_PREDIV; *pll_mult = best_mult; + return best; } -static unsigned long ov5640_calc_mipi_clk(struct ov5640_dev *sensor, - unsigned long rate, - u8 *pll_prediv, u8 *pll_mult, - u8 *sysdiv, u8 *mipi_div) +/* + * ov5640_set_mipi_pclk() - Calculate the clock tree configuration values + * for the MIPI CSI-2 output. + * + * @rate: The requested bandwidth in bytes per second. + * It is calculated as: HTOT * VTOT * FPS * bpp + * + * This function use the requested bandwidth to calculate: + * - sample_rate = bandwidth / bpp; + * - mipi_clk = bandwidth / num_lanes / 2; ( / 2 for CSI-2 DDR) + * + * The bandwidth corresponds to the SYSCLK frequency generated by the + * PLL pre-divider, the PLL multiplier and the SYS divider (see the clock + * tree documented here above). + * + * From the SYSCLK frequency, the MIPI CSI-2 clock tree generates the + * pixel clock and the MIPI BIT clock as follows: + * + * MIPI_BIT_CLK = SYSCLK / MIPI_DIV / 2; + * PIXEL_CLK = SYSCLK / PLL_RDVI / BIT_DIVIDER / PCLK_DIV / MIPI_DIV + * + * with this fixed parameters: + * PLL_RDIV = 2; + * BIT_DIVIDER = 2; (MIPI_BIT_MODE == 8 ? 2 : 2,5); + * PCLK_DIV = 1; + * + * With these values we have: + * + * pixel_clock = bandwidth / bpp + * = bandwidth / 4 / MIPI_DIV; + * + * And so we can calculate MIPI_DIV as: + * MIPI_DIV = bpp / 4; + */ +static int ov5640_set_mipi_pclk(struct ov5640_dev *sensor, + unsigned long rate) { - unsigned long _rate = rate * OV5640_MIPI_DIV; + const struct ov5640_mode_info *mode = sensor->current_mode; + u8 mipi_div = OV5640_MIPI_DIV; + u8 prediv, mult, sysdiv; + int ret; - _rate = ov5640_calc_sys_clk(sensor, _rate, pll_prediv, pll_mult, - sysdiv); - *mipi_div = OV5640_MIPI_DIV; + /* FIXME: + * Practical experience shows we get a correct frame rate by + * halving the bandwidth rate by 2, to slow down SYSCLK frequency. + * Divide both SYSCLK and MIPI_DIV by two (with OV5640_MIPI_DIV + * currently fixed at value '2', while according to the above + * formula it should have been = bpp / 4 = 4). + * + * So that: + * pixel_clock = bandwidth / 2 / bpp + * = bandwidth / 2 / 4 / MIPI_DIV; + * MIPI_DIV = bpp / 4 / 2; + */ + rate /= 2; - return _rate / *mipi_div; -} + /* FIXME: + * High resolution modes (1280x720, 1920x1080) requires an higher + * clock speed. Half the MIPI_DIVIDER value to double the output + * pixel clock and MIPI_CLK speeds. + */ + if (mode->hact > 1024) + mipi_div /= 2; -static int ov5640_set_mipi_pclk(struct ov5640_dev *sensor, unsigned long rate) -{ - u8 prediv, mult, sysdiv, mipi_div; - int ret; + ov5640_calc_sys_clk(sensor, rate, &prediv, &mult, &sysdiv); - ov5640_calc_mipi_clk(sensor, rate, &prediv, &mult, &sysdiv, &mipi_div); + ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL0, + 0x0f, OV5640_PLL_CTRL0_MIPI_MODE_8BIT); ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL1, - 0xff, sysdiv << 4 | (mipi_div - 1)); + 0xff, sysdiv << 4 | mipi_div); if (ret) return ret; @@ -907,7 +960,13 @@ static int ov5640_set_mipi_pclk(struct ov5640_dev *sensor, unsigned long rate) if (ret) return ret; - return ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL3, 0xf, prediv); + ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL3, + 0x1f, OV5640_PLL_CTRL3_PLL_ROOT_DIV_2 | prediv); + if (ret) + return ret; + + return ov5640_mod_reg(sensor, OV5640_REG_SYS_ROOT_DIVIDER, + 0x30, OV5640_PLL_SYS_ROOT_DIVIDER_BYPASS); } static unsigned long ov5640_calc_pclk(struct ov5640_dev *sensor,