d1: add new target
[openwrt/staging/mans0n.git] / target / linux / d1 / patches-6.1 / 0086-drm-sun4i-decouple-TCON_DCLK_DIV-value-from-pll_mipi.patch
1 From 9a7acb8f03346705d7420a490d95b32309d90e22 Mon Sep 17 00:00:00 2001
2 From: Roman Beranek <roman.beranek@prusa3d.com>
3 Date: Wed, 25 Nov 2020 13:07:35 +0100
4 Subject: [PATCH 086/117] drm/sun4i: decouple TCON_DCLK_DIV value from
5 pll_mipi/dotclock ratio
6
7 Observations showed that an actual refresh rate differs from the intended.
8 Specifically, in case of 4-lane panels it was reduced by 1/3, and in case of
9 2-lane panels by 2/3.
10
11 BSP code apparently distinguishes between a `dsi_div` and a 'tcon inner div'.
12 While this 'inner' divider is under DSI always 4, the `dsi_div` is defined
13 as a number of bits per pixel over a number of DSI lanes. This value is then
14 involved in setting the rate of PLL_MIPI.
15
16 I couldn't really figure out how to fit this into the dotclock driver,
17 so I opted for this hack where the requested rate is adjusted in such a way
18 that the sun4i_dotclock driver can remain untouched.
19
20 Signed-off-by: Roman Beranek <roman.beranek@prusa3d.com>
21 Signed-off-by: Samuel Holland <samuel@sholland.org>
22 ---
23 drivers/gpu/drm/sun4i/sun4i_tcon.c | 44 +++++++++++++++++-------------
24 1 file changed, 25 insertions(+), 19 deletions(-)
25
26 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
27 +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
28 @@ -291,18 +291,6 @@ static int sun4i_tcon_get_clk_delay(cons
29 return delay;
30 }
31
32 -static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
33 - const struct drm_display_mode *mode)
34 -{
35 - /* Configure the dot clock */
36 - clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
37 -
38 - /* Set the resolution */
39 - regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
40 - SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) |
41 - SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
42 -}
43 -
44 static void sun4i_tcon0_mode_set_dithering(struct sun4i_tcon *tcon,
45 const struct drm_connector *connector)
46 {
47 @@ -365,12 +353,18 @@ static void sun4i_tcon0_mode_set_cpu(str
48 u8 bpp = mipi_dsi_pixel_format_to_bpp(device->format);
49 u8 lanes = device->lanes;
50 u32 block_space, start_delay;
51 - u32 tcon_div;
52
53 tcon->dclk_min_div = SUN6I_DSI_TCON_DIV;
54 tcon->dclk_max_div = SUN6I_DSI_TCON_DIV;
55
56 - sun4i_tcon0_mode_set_common(tcon, mode);
57 + /* Configure the dot clock */
58 + clk_set_rate(tcon->dclk, mode->crtc_clock * 1000
59 + * bpp / (lanes * SUN6I_DSI_TCON_DIV));
60 +
61 + /* Set the resolution */
62 + regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
63 + SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) |
64 + SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
65
66 /* Set dithering if needed */
67 sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
68 @@ -394,9 +388,7 @@ static void sun4i_tcon0_mode_set_cpu(str
69 * The datasheet says that this should be set higher than 20 *
70 * pixel cycle, but it's not clear what a pixel cycle is.
71 */
72 - regmap_read(tcon->regs, SUN4I_TCON0_DCLK_REG, &tcon_div);
73 - tcon_div &= GENMASK(6, 0);
74 - block_space = mode->htotal * bpp / (tcon_div * lanes);
75 + block_space = mode->htotal * bpp / (SUN6I_DSI_TCON_DIV * lanes);
76 block_space -= mode->hdisplay + 40;
77
78 regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI0_REG,
79 @@ -438,7 +430,14 @@ static void sun4i_tcon0_mode_set_lvds(st
80
81 tcon->dclk_min_div = 7;
82 tcon->dclk_max_div = 7;
83 - sun4i_tcon0_mode_set_common(tcon, mode);
84 +
85 + /* Configure the dot clock */
86 + clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
87 +
88 + /* Set the resolution */
89 + regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
90 + SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) |
91 + SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
92
93 /* Set dithering if needed */
94 sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
95 @@ -515,7 +514,14 @@ static void sun4i_tcon0_mode_set_rgb(str
96
97 tcon->dclk_min_div = tcon->quirks->dclk_min_div;
98 tcon->dclk_max_div = 127;
99 - sun4i_tcon0_mode_set_common(tcon, mode);
100 +
101 + /* Configure the dot clock */
102 + clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
103 +
104 + /* Set the resolution */
105 + regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
106 + SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) |
107 + SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
108
109 /* Set dithering if needed */
110 sun4i_tcon0_mode_set_dithering(tcon, connector);