build/patch/kernel/archive/sunxi-5.10/megous/drm-sun4i-decouple-TCON_DCLK_DIV-value-from-pll_mipi.patch

113 lines
4.2 KiB
Diff

From 700e18844f140b24fd7362449fdb1c52dbcec7a0 Mon Sep 17 00:00:00 2001
From: Roman Beranek <roman.beranek@prusa3d.com>
Date: Wed, 25 Nov 2020 13:07:35 +0100
Subject: [PATCH 214/323] drm: sun4i: decouple TCON_DCLK_DIV value from
pll_mipi/dotclock ratio
Observations showed that an actual refresh rate differs from the intended.
Specifically, in case of 4-lane panels it was reduced by 1/3, and in case of
2-lane panels by 2/3.
BSP code apparently distinguishes between a `dsi_div` and a 'tcon inner div'.
While this 'inner' divider is under DSI always 4, the `dsi_div` is defined
as a number of bits per pixel over a number of DSI lanes. This value is then
involved in setting the rate of PLL_MIPI.
I couldn't really figure out how to fit this into the dotclock driver,
so I opted for this hack where the requested rate is adjusted in such a way
that the sun4i_dotclock driver can remain untouched.
---
drivers/gpu/drm/sun4i/sun4i_tcon.c | 44 +++++++++++++++++-------------
1 file changed, 25 insertions(+), 19 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 0af3f5060..5e751b80e 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -322,18 +322,6 @@ static int sun4i_tcon_get_clk_delay(const struct drm_display_mode *mode,
return delay;
}
-static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
- const struct drm_display_mode *mode)
-{
- /* Configure the dot clock */
- clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
-
- /* Set the resolution */
- regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
- SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) |
- SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
-}
-
static void sun4i_tcon0_mode_set_dithering(struct sun4i_tcon *tcon,
const struct drm_connector *connector)
{
@@ -396,12 +384,18 @@ static void sun4i_tcon0_mode_set_cpu(struct sun4i_tcon *tcon,
u8 bpp = mipi_dsi_pixel_format_to_bpp(device->format);
u8 lanes = device->lanes;
u32 block_space, start_delay;
- u32 tcon_div;
tcon->dclk_min_div = SUN6I_DSI_TCON_DIV;
tcon->dclk_max_div = SUN6I_DSI_TCON_DIV;
- sun4i_tcon0_mode_set_common(tcon, mode);
+ /* Configure the dot clock */
+ clk_set_rate(tcon->dclk, mode->crtc_clock * 1000
+ * bpp / (lanes * SUN6I_DSI_TCON_DIV));
+
+ /* Set the resolution */
+ regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
+ SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) |
+ SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
/* Set dithering if needed */
sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
@@ -425,9 +419,7 @@ static void sun4i_tcon0_mode_set_cpu(struct sun4i_tcon *tcon,
* The datasheet says that this should be set higher than 20 *
* pixel cycle, but it's not clear what a pixel cycle is.
*/
- regmap_read(tcon->regs, SUN4I_TCON0_DCLK_REG, &tcon_div);
- tcon_div &= GENMASK(6, 0);
- block_space = mode->htotal * bpp / (tcon_div * lanes);
+ block_space = mode->htotal * bpp / (SUN6I_DSI_TCON_DIV * lanes);
block_space -= mode->hdisplay + 40;
regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI0_REG,
@@ -469,7 +461,14 @@ static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon *tcon,
tcon->dclk_min_div = 7;
tcon->dclk_max_div = 7;
- sun4i_tcon0_mode_set_common(tcon, mode);
+
+ /* Configure the dot clock */
+ clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
+
+ /* Set the resolution */
+ regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
+ SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) |
+ SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
/* Set dithering if needed */
sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
@@ -548,7 +547,14 @@ static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
tcon->dclk_min_div = tcon->quirks->dclk_min_div;
tcon->dclk_max_div = 127;
- sun4i_tcon0_mode_set_common(tcon, mode);
+
+ /* Configure the dot clock */
+ clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
+
+ /* Set the resolution */
+ regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
+ SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) |
+ SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
/* Set dithering if needed */
sun4i_tcon0_mode_set_dithering(tcon, connector);
--
2.34.0