From patchwork Wed Oct 28 22:57:04 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 315151 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 904E3C4363A for ; Wed, 28 Oct 2020 22:57:59 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2F92C20759 for ; Wed, 28 Oct 2020 22:57:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2389873AbgJ1W5z (ORCPT ); Wed, 28 Oct 2020 18:57:55 -0400 Received: from relay3-d.mail.gandi.net ([217.70.183.195]:43341 "EHLO relay3-d.mail.gandi.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2389867AbgJ1W5Z (ORCPT ); Wed, 28 Oct 2020 18:57:25 -0400 X-Originating-IP: 2.224.242.101 Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id AC2106000B; Wed, 28 Oct 2020 22:57:22 +0000 (UTC) From: Jacopo Mondi To: hugues.fruchet@st.com, tomi.valkeinen@ti.com, sam@elite-embedded.com Cc: Jacopo Mondi , slongerbeam@gmail.com, linux-media@vger.kernel.org, Jacopo Mondi Subject: [RFC 1/3] media: i2c: ov5640: Adjust htot Date: Wed, 28 Oct 2020 23:57:04 +0100 Message-Id: <20201028225706.110078-2-jacopo+renesas@jmondi.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201028225706.110078-1-jacopo+renesas@jmondi.org> References: <20201028225706.110078-1-jacopo+renesas@jmondi.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org From: Tomi Valkeinen Adjust htot for most of the modes. The numbers are from the OV5640 datasheet, and with these the driver works more reliably on DRA76 EVM + OV5640, using 2 datalanes. Without the patch, I see often ComplexIO (i.e. PHY) errors when starting the streaming, and 1280x720 does not work at all without this change. Signed-off-by: Tomi Valkeinen Signed-off-by: Jacopo Mondi --- drivers/media/i2c/ov5640.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c index 8d0254d0e5ea..117ac22683ad 100644 --- a/drivers/media/i2c/ov5640.c +++ b/drivers/media/i2c/ov5640.c @@ -553,42 +553,42 @@ static const struct ov5640_mode_info ov5640_mode_init_data = { static const struct ov5640_mode_info ov5640_mode_data[OV5640_NUM_MODES] = { {OV5640_MODE_QCIF_176_144, SUBSAMPLING, - 176, 1896, 144, 984, + 176, 2844, 144, 984, ov5640_setting_QCIF_176_144, ARRAY_SIZE(ov5640_setting_QCIF_176_144), OV5640_30_FPS}, {OV5640_MODE_QVGA_320_240, SUBSAMPLING, - 320, 1896, 240, 984, + 320, 2844, 240, 984, ov5640_setting_QVGA_320_240, ARRAY_SIZE(ov5640_setting_QVGA_320_240), OV5640_30_FPS}, {OV5640_MODE_VGA_640_480, SUBSAMPLING, - 640, 1896, 480, 1080, + 640, 2844, 480, 1080, ov5640_setting_VGA_640_480, ARRAY_SIZE(ov5640_setting_VGA_640_480), OV5640_60_FPS}, {OV5640_MODE_NTSC_720_480, SUBSAMPLING, - 720, 1896, 480, 984, + 720, 2844, 480, 984, ov5640_setting_NTSC_720_480, ARRAY_SIZE(ov5640_setting_NTSC_720_480), OV5640_30_FPS}, {OV5640_MODE_PAL_720_576, SUBSAMPLING, - 720, 1896, 576, 984, + 720, 2844, 576, 984, ov5640_setting_PAL_720_576, ARRAY_SIZE(ov5640_setting_PAL_720_576), OV5640_30_FPS}, {OV5640_MODE_XGA_1024_768, SUBSAMPLING, - 1024, 1896, 768, 1080, + 1024, 2844, 768, 1080, ov5640_setting_XGA_1024_768, ARRAY_SIZE(ov5640_setting_XGA_1024_768), OV5640_30_FPS}, {OV5640_MODE_720P_1280_720, SUBSAMPLING, - 1280, 1892, 720, 740, + 1280, 2844, 720, 740, ov5640_setting_720P_1280_720, ARRAY_SIZE(ov5640_setting_720P_1280_720), OV5640_30_FPS}, {OV5640_MODE_1080P_1920_1080, SCALING, - 1920, 2500, 1080, 1120, + 1920, 2844, 1080, 1120, ov5640_setting_1080P_1920_1080, ARRAY_SIZE(ov5640_setting_1080P_1920_1080), OV5640_30_FPS}, From patchwork Wed Oct 28 22:57:05 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 315152 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id AD456C4363A for ; Wed, 28 Oct 2020 22:57:56 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5F3D72076B for ; Wed, 28 Oct 2020 22:57:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2389933AbgJ1W5z (ORCPT ); Wed, 28 Oct 2020 18:57:55 -0400 Received: from relay3-d.mail.gandi.net ([217.70.183.195]:34999 "EHLO relay3-d.mail.gandi.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2389866AbgJ1W51 (ORCPT ); Wed, 28 Oct 2020 18:57:27 -0400 X-Originating-IP: 2.224.242.101 Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 295966000C; Wed, 28 Oct 2020 22:57:23 +0000 (UTC) From: Jacopo Mondi To: hugues.fruchet@st.com, tomi.valkeinen@ti.com, sam@elite-embedded.com Cc: Jacopo Mondi , slongerbeam@gmail.com, linux-media@vger.kernel.org Subject: [RFC 2/3] media: i2c: ov5640: Rework CSI-2 clock tree Date: Wed, 28 Oct 2020 23:57:05 +0100 Message-Id: <20201028225706.110078-3-jacopo+renesas@jmondi.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201028225706.110078-1-jacopo+renesas@jmondi.org> References: <20201028225706.110078-1-jacopo+renesas@jmondi.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Re-work the ov5640_set_mipi_pclk() function to calculate the SYSCLK function based on the CSI-2 link frequency. Take into account and more clearly document the clock tree constraints reported in the PLL diagrams. Most values are still fixed and only tested with 16bpp YUYV formats with a 2 lanes CSI-2 setup. Tested by capturing and validating images in all the sensor supported resolutions except full resolution 2592x1944. Signed-off-by: Jacopo Mondi --- drivers/media/i2c/ov5640.c | 125 ++++++++++++++++++++++--------------- 1 file changed, 75 insertions(+), 50 deletions(-) -- 2.28.0 diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c index 117ac22683ad..236c684ca20b 100644 --- a/drivers/media/i2c/ov5640.c +++ b/drivers/media/i2c/ov5640.c @@ -88,6 +88,7 @@ #define OV5640_REG_POLARITY_CTRL00 0x4740 #define OV5640_REG_MIPI_CTRL00 0x4800 #define OV5640_REG_DEBUG_MODE 0x4814 +#define OV5640_REG_PCLK_PERIOD 0x4837 #define OV5640_REG_ISP_FORMAT_MUX_CTRL 0x501f #define OV5640_REG_PRE_ISP_TEST_SET1 0x503d #define OV5640_REG_SDE_CTRL0 0x5580 @@ -919,67 +920,88 @@ static unsigned long ov5640_calc_sys_clk(struct ov5640_dev *sensor, /* * ov5640_set_mipi_pclk() - Calculate the clock tree configuration values * for the MIPI CSI-2 output. - * - * @rate: The requested bandwidth per lane in bytes per second. - * 'Bandwidth Per Lane' is calculated as: - * bpl = HTOT * VTOT * FPS * bpp / num_lanes; - * - * This function use the requested bandwidth to calculate: - * - sample_rate = bpl / (bpp / num_lanes); - * = bpl / (PLL_RDIV * BIT_DIV * PCLK_DIV * MIPI_DIV / num_lanes); - * - * - mipi_sclk = bpl / MIPI_DIV / 2; ( / 2 is for CSI-2 DDR) - * - * with these fixed parameters: - * PLL_RDIV = 2; - * BIT_DIVIDER = 2; (MIPI_BIT_MODE == 8 ? 2 : 2,5); - * PCLK_DIV = 1; - * - * The MIPI clock generation differs for modes that use the scaler and modes - * that do not. In case the scaler is in use, the MIPI_SCLK generates the MIPI - * BIT CLk, and thus: - * - * - mipi_sclk = bpl / MIPI_DIV / 2; - * MIPI_DIV = 1; - * - * For modes that do not go through the scaler, the MIPI BIT CLOCK is generated - * from the pixel clock, and thus: - * - * - sample_rate = bpl / (bpp / num_lanes); - * = bpl / (2 * 2 * 1 * MIPI_DIV / num_lanes); - * = bpl / (4 * MIPI_DIV / num_lanes); - * - MIPI_DIV = bpp / (4 * num_lanes); + * @rate: The requested bitrate in bits per second. * * FIXME: this have been tested with 16bpp and 2 lanes setup only. - * MIPI_DIV is fixed to value 2, but it -might- be changed according to the - * above formula for setups with 1 lane or image formats with different bpp. - * - * FIXME: this deviates from the sensor manual documentation which is quite - * thin on the MIPI clock tree generation part. */ static int ov5640_set_mipi_pclk(struct ov5640_dev *sensor, unsigned long rate) { - const struct ov5640_mode_info *mode = sensor->current_mode; + u8 bit_div, mipi_div, pclk_div, sclk_div, sclk2x_div, root_div; u8 prediv, mult, sysdiv; - u8 mipi_div; + unsigned long link_freq; + unsigned long sysclk; + u8 pclk_period; int ret; /* - * 1280x720 is reported to use 'SUBSAMPLING' only, - * but according to the sensor manual it goes through the - * scaler before subsampling. + * The 'rate' parameter is the bitrate = VTOT * HTOT * FPS * BPP + * + * Adjust it to represent the CSI-2 link frequency and use it to + * update the associated control. */ - if (mode->dn_mode == SCALING || - (mode->id == OV5640_MODE_720P_1280_720)) - mipi_div = OV5640_MIPI_DIV_SCLK; + link_freq = rate / sensor->ep.bus.mipi_csi2.num_data_lanes / 2; + + /* + * - mipi_div - Assumptions not supported by documentation + * + * The MIPI clock generation differs for modes that use the scaler and + * modes that do not. + */ + if (sensor->current_mode->dn_mode == SCALING) + mipi_div = 1; else - mipi_div = OV5640_MIPI_DIV_PCLK; + mipi_div = 2; + + sysclk = link_freq * 2 * mipi_div; + ov5640_calc_sys_clk(sensor, sysclk, &prediv, &mult, &sysdiv); + + /* + * Adjust PLL parameters to maintain the MIPI_SCLK-to-PCLK ratio; + * + * - root_div = 2 (fixed) + * - bit_div : MIPI 8-bit = 2 + * MIPI 10-bit = 2,5 + * - pclk_div = 1 (fixed) + * - pll_div = (2 lanes ? mipi_div : 2 * mipi_div) + * 2 lanes: MIPI_SCLK = (4 or 5) * PCLK + * 1 lanes: MIPI_SCLK = (8 or 10) * PCLK + * + * TODO: support 10-bit formats + * TODO: support 1 lane + */ + root_div = OV5640_PLL_CTRL3_PLL_ROOT_DIV_2; + bit_div = OV5640_PLL_CTRL0_MIPI_MODE_8BIT; + pclk_div = OV5640_PLL_SYS_ROOT_DIVIDER_BYPASS; - ov5640_calc_sys_clk(sensor, rate, &prediv, &mult, &sysdiv); + /* + * Scaler clock: + * - YUV: PCLK >= 2 * SCLK + * - RAW or JPEG: PCLK >= SCLK + * - sclk2x_div = sclk_div / 2 + * + * TODO: add support for RAW and JPEG modes. To maintain the + * SCLK to PCLK ratio, the sclk_div should probably be + * adjusted. + */ + sclk_div = ilog2(OV5640_SCLK_ROOT_DIV); + sclk2x_div = ilog2(OV5640_SCLK2X_ROOT_DIV); + + /* + * This is called pclk period, but it actually represents the + * sample period expressed in ns with 1-bit decimal (0x01=0.5ns). + * + * - pclk = link_freq * 2 * lanes / bpp + * + * TODO: support 1 data lane; support modes with bpp != 16. + */ + pclk_period = 2000000000UL / (link_freq / 2); + /* Program the clock tree registers. */ ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL0, - 0x0f, OV5640_PLL_CTRL0_MIPI_MODE_8BIT); + 0x0f, bit_div); + if (ret) + return ret; ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL1, 0xff, sysdiv << 4 | mipi_div); @@ -991,12 +1013,16 @@ static int ov5640_set_mipi_pclk(struct ov5640_dev *sensor, return ret; ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL3, - 0x1f, OV5640_PLL_CTRL3_PLL_ROOT_DIV_2 | prediv); + 0x1f, root_div | prediv); + if (ret) + return ret; + + ret = ov5640_mod_reg(sensor, OV5640_REG_SYS_ROOT_DIVIDER, 0x3f, + (pclk_div << 4) | (sclk2x_div << 2) | sclk_div); if (ret) return ret; - return ov5640_mod_reg(sensor, OV5640_REG_SYS_ROOT_DIVIDER, - 0x30, OV5640_PLL_SYS_ROOT_DIVIDER_BYPASS); + return ov5640_write_reg(sensor, OV5640_REG_PCLK_PERIOD, pclk_period); } static unsigned long ov5640_calc_pclk(struct ov5640_dev *sensor, @@ -1775,7 +1801,6 @@ static int ov5640_set_mode(struct ov5640_dev *sensor) */ rate = ov5640_calc_pixel_rate(sensor) * 16; if (sensor->ep.bus_type == V4L2_MBUS_CSI2_DPHY) { - rate = rate / sensor->ep.bus.mipi_csi2.num_data_lanes; ret = ov5640_set_mipi_pclk(sensor, rate); } else { rate = rate / sensor->ep.bus.parallel.bus_width; From patchwork Wed Oct 28 22:57:06 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 310977 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A3CA5C55179 for ; Wed, 28 Oct 2020 22:58:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5841D20757 for ; Wed, 28 Oct 2020 22:58:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387581AbgJ1W5z (ORCPT ); Wed, 28 Oct 2020 18:57:55 -0400 Received: from relay3-d.mail.gandi.net ([217.70.183.195]:46037 "EHLO relay3-d.mail.gandi.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2389868AbgJ1W52 (ORCPT ); Wed, 28 Oct 2020 18:57:28 -0400 X-Originating-IP: 2.224.242.101 Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 789716000E; Wed, 28 Oct 2020 22:57:25 +0000 (UTC) From: Jacopo Mondi To: hugues.fruchet@st.com, tomi.valkeinen@ti.com, sam@elite-embedded.com Cc: Jacopo Mondi , slongerbeam@gmail.com, linux-media@vger.kernel.org Subject: [RFC 3/3] media: i2c: ov5640: Add V4L2_CID_LINK_FREQ support Date: Wed, 28 Oct 2020 23:57:06 +0100 Message-Id: <20201028225706.110078-4-jacopo+renesas@jmondi.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201028225706.110078-1-jacopo+renesas@jmondi.org> References: <20201028225706.110078-1-jacopo+renesas@jmondi.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Add support for the V4L2_CID_LINK_FREQ control in the ov5640 driver. Unfortunately V4L2_CID_LINK_FREQ is a menu control and its supported values has to be pre-calculated. Signed-off-by: Jacopo Mondi --- drivers/media/i2c/ov5640.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c index 236c684ca20b..8429269b9d7d 100644 --- a/drivers/media/i2c/ov5640.c +++ b/drivers/media/i2c/ov5640.c @@ -144,6 +144,20 @@ static const struct ov5640_pixfmt ov5640_formats[] = { { MEDIA_BUS_FMT_SRGGB8_1X8, V4L2_COLORSPACE_SRGB, }, }; +static const s64 ov5640_link_freqs[] = { + 126273600, + 191116800, + 184291200, + 167909760, + 252547200, + 331724160, + 335819520, + 368582400, + 382233600, + 737164800, +}; +#define OV5640_LINK_FREQS_NUM ARRAY_SIZE(ov5640_link_freqs) + /* * FIXME: remove this when a subdev API becomes available * to set the MIPI CSI-2 virtual channel. @@ -220,6 +234,7 @@ struct ov5640_ctrls { struct v4l2_ctrl *test_pattern; struct v4l2_ctrl *hflip; struct v4l2_ctrl *vflip; + struct v4l2_ctrl *link_freq; }; struct ov5640_dev { @@ -928,6 +943,7 @@ static int ov5640_set_mipi_pclk(struct ov5640_dev *sensor, unsigned long rate) { u8 bit_div, mipi_div, pclk_div, sclk_div, sclk2x_div, root_div; + unsigned int freq_index, i; u8 prediv, mult, sysdiv; unsigned long link_freq; unsigned long sysclk; @@ -941,6 +957,19 @@ static int ov5640_set_mipi_pclk(struct ov5640_dev *sensor, * update the associated control. */ link_freq = rate / sensor->ep.bus.mipi_csi2.num_data_lanes / 2; + freq_index = OV5640_LINK_FREQS_NUM - 1; + for (i = 0; i < OV5640_LINK_FREQS_NUM; ++i) { + if (ov5640_link_freqs[i] == link_freq) { + freq_index = i; + break; + } + } + WARN_ONCE(i == OV5640_LINK_FREQS_NUM, + "Link frequency %ld not supported", link_freq); + + ret = __v4l2_ctrl_s_ctrl(sensor->ctrls.link_freq, freq_index); + if (ret < 0) + return ret; /* * - mipi_div - Assumptions not supported by documentation @@ -2787,6 +2816,12 @@ static int ov5640_init_controls(struct ov5640_dev *sensor) V4L2_CID_POWER_LINE_FREQUENCY_AUTO, 0, V4L2_CID_POWER_LINE_FREQUENCY_50HZ); + ctrls->link_freq = v4l2_ctrl_new_int_menu(hdl, ops, V4L2_CID_LINK_FREQ, + OV5640_LINK_FREQS_NUM - 1, + 0, ov5640_link_freqs); + if (ctrls->link_freq) + ctrls->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; + if (hdl->error) { ret = hdl->error; goto free_ctrls;