From patchwork Sat Apr 2 00:41:18 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Vasut X-Patchwork-Id: 12798882 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 9706DC433EF for ; Sat, 2 Apr 2022 00:41:43 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id D799D10E105; Sat, 2 Apr 2022 00:41:42 +0000 (UTC) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) by gabe.freedesktop.org (Postfix) with ESMTPS id CEFA110E105 for ; Sat, 2 Apr 2022 00:41:40 +0000 (UTC) Received: from tr.lan (ip-89-176-112-137.net.upcbroadband.cz [89.176.112.137]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) (Authenticated sender: marex@denx.de) by phobos.denx.de (Postfix) with ESMTPSA id 775C4805EB; Sat, 2 Apr 2022 02:41:32 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=denx.de; s=phobos-20191101; t=1648860098; bh=F38w9oe74g8LpG4yXDFeWuiLAwoG7St19FQz+elXdQc=; h=From:To:Cc:Subject:Date:From; b=ugPH1cwUE0Yp7oniDU/1vtxxor1CfYWwkfJj8BwPdDZXIuAGLspA0/AGTOdrb0gSi luQCu79hzihh5mP63xt0DK2Bu8yF5K/xorJjay+aLxXmhlHswQFERFDQMyjGYm1bWt Do6y0ZivY/Gm6eCdXO3NEU9YPP+toDlQFM3XZF9NzD67z0e1zZHa3xwD4Bf8QoOYoB lr4WN5+v5DAV1ymocBHKRdf36035RXsEtOQhCLgJtSIZjxAT12x0v1TaRr/6GygjBA CnERMn9u13TiMNblkybKvF4ZkjdyNJJIpcSd4k48r9tdRJovaEnqHymxNm0iM01K6D UmvsJdk4oukPw== From: Marek Vasut To: dri-devel@lists.freedesktop.org Subject: [PATCH] drm: bridge: icn6211: Fix DSI-to-DPI PLL configuration Date: Sat, 2 Apr 2022 02:41:18 +0200 Message-Id: <20220402004118.897014-1-marex@denx.de> X-Mailer: git-send-email 2.35.1 MIME-Version: 1.0 X-Virus-Scanned: clamav-milter 0.103.5 at phobos.denx.de X-Virus-Status: Clean X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Marek Vasut , robert.foss@linaro.org, Jagan Teki , Thomas Zimmermann , Sam Ravnborg , Maxime Ripard Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" The datasheet for this bridge is not available, the PLL behavior has been inferred from [1] and [2] and by analyzing the DPI pixel clock with scope. After further testing with other displays and different DSI data lane count, it turns out the P-factor is not 1/2^N divider, but rather only 1/N divider. It also turns out the input into the PLL seem to be ByteClock instead of DSI HS clock. Rework the P-factor calculation such that the PLL calculation code handles P-factor from 1..32 with P-factors above 16 must be even. In case P-factor is even, enable built-in 1:2 divider and program P-factor/2 to PLL_REF_DIV, otherwise configure only the P-factor into PLL_REF_DIV register. Switch the PLL factor calculation from kHz to Hz to maintain precision. [1] https://github.com/rockchip-linux/kernel/blob/develop-4.19/drivers/gpu/drm/bridge/icn6211.c [2] https://github.com/tdjastrzebski/ICN6211-Configurator Fixes: f30cf0ece691 ("drm: bridge: icn6211: Add generic DSI-to-DPI PLL configuration") Signed-off-by: Marek Vasut Cc: Jagan Teki Cc: Maxime Ripard Cc: Robert Foss Cc: Sam Ravnborg Cc: Thomas Zimmermann To: dri-devel@lists.freedesktop.org Acked-by: Maxime Ripard --- drivers/gpu/drm/bridge/chipone-icn6211.c | 47 ++++++++++++++---------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/bridge/chipone-icn6211.c b/drivers/gpu/drm/bridge/chipone-icn6211.c index b7728dffbdc1..f4b152901d0e 100644 --- a/drivers/gpu/drm/bridge/chipone-icn6211.c +++ b/drivers/gpu/drm/bridge/chipone-icn6211.c @@ -171,22 +171,24 @@ static void chipone_configure_pll(struct chipone *icn, const struct drm_display_mode *mode) { unsigned int best_p = 0, best_m = 0, best_s = 0; + unsigned int mode_clock = mode->clock * 1000; unsigned int delta, min_delta = 0xffffffff; unsigned int freq_p, freq_s, freq_out; unsigned int p_min, p_max; unsigned int p, m, s; unsigned int fin; + bool best_p_pot; + u8 ref_div; /* - * DSI clock lane frequency (input into PLL) is calculated as: - * DSI_CLK = mode clock * bpp / dsi_data_lanes / 2 - * the 2 is there because the bus is DDR. + * DSI byte clock frequency (input into PLL) is calculated as: + * DSI_CLK = mode clock * bpp / dsi_data_lanes / 8 * * DPI pixel clock frequency (output from PLL) is mode clock. * * The chip contains fractional PLL which works as follows: * DPI_CLK = ((DSI_CLK / P) * M) / S - * P is pre-divider, register PLL_REF_DIV[3:0] is 2^(n+1) divider + * P is pre-divider, register PLL_REF_DIV[3:0] is 1:n divider * register PLL_REF_DIV[4] is extra 1:2 divider * M is integer multiplier, register PLL_INT(0) is multiplier * S is post-divider, register PLL_REF_DIV[7:5] is 2^(n+1) divider @@ -194,15 +196,17 @@ static void chipone_configure_pll(struct chipone *icn, * It seems the PLL input clock after applying P pre-divider have * to be lower than 20 MHz. */ - fin = mode->clock * mipi_dsi_pixel_format_to_bpp(icn->dsi->format) / - icn->dsi->lanes / 2; /* in kHz */ + fin = mode_clock * mipi_dsi_pixel_format_to_bpp(icn->dsi->format) / + icn->dsi->lanes / 8; /* in Hz */ /* Minimum value of P predivider for PLL input in 5..20 MHz */ - p_min = ffs(fin / 20000); - p_max = (fls(fin / 5000) - 1) & 0x1f; + p_min = clamp(DIV_ROUND_UP(fin, 20000000), 1U, 31U); + p_max = clamp(fin / 5000000, 1U, 31U); for (p = p_min; p < p_max; p++) { /* PLL_REF_DIV[4,3:0] */ - freq_p = fin / BIT(p + 1); + if (p > 16 && p & 1) /* P > 16 uses extra /2 */ + continue; + freq_p = fin / p; if (freq_p == 0) /* Divider too high */ break; @@ -211,21 +215,21 @@ static void chipone_configure_pll(struct chipone *icn, if (freq_s == 0) /* Divider too high */ break; - m = mode->clock / freq_s; + m = mode_clock / freq_s; /* Multiplier is 8 bit */ if (m > 0xff) continue; /* Limit PLL VCO frequency to 1 GHz */ - freq_out = (fin * m) / BIT(p + 1); - if (freq_out > 1000000) + freq_out = (fin * m) / p; + if (freq_out > 1000000000) continue; /* Apply post-divider */ freq_out /= BIT(s + 1); - delta = abs(mode->clock - freq_out); + delta = abs(mode_clock - freq_out); if (delta < min_delta) { best_p = p; best_m = m; @@ -235,17 +239,20 @@ static void chipone_configure_pll(struct chipone *icn, } } + best_p_pot = !(best_p & 1); + dev_dbg(icn->dev, - "PLL: P[3:0]=2^%d P[4]=2*%d M=%d S[7:5]=2^%d delta=%d => DSI f_in=%d kHz ; DPI f_out=%ld kHz\n", - best_p, !!best_p, best_m, best_s + 1, min_delta, fin, - (fin * best_m) / BIT(best_p + best_s + 2)); + "PLL: P[3:0]=%d P[4]=2*%d M=%d S[7:5]=2^%d delta=%d => DSI f_in=%d Hz ; DPI f_out=%d Hz\n", + best_p >> best_p_pot, best_p_pot, best_m, best_s + 1, + min_delta, fin, (fin * best_m) / (best_p << (best_s + 1))); + + ref_div = PLL_REF_DIV_P(best_p >> best_p_pot) | PLL_REF_DIV_S(best_s); + if (best_p_pot) /* Prefer /2 pre-divider */ + ref_div |= PLL_REF_DIV_Pe; /* Clock source selection fixed to MIPI DSI clock lane */ chipone_writeb(icn, PLL_CTRL(6), PLL_CTRL_6_MIPI_CLK); - chipone_writeb(icn, PLL_REF_DIV, - /* Prefer /2 pre-divider */ - (best_p ? PLL_REF_DIV_Pe : 0) | - PLL_REF_DIV_P(best_p) | PLL_REF_DIV_S(best_s)); + chipone_writeb(icn, PLL_REF_DIV, ref_div); chipone_writeb(icn, PLL_INT(0), best_m); }