diff mbox series

[v6,11/22] clk: sunxi-ng: a64: Add minimum rate for PLL_MIPI

Message ID 20190124195900.22620-12-jagan@amarulasolutions.com (mailing list archive)
State New, archived
Headers show
Series drm/sun4i: Allwinner A64 MIPI-DSI support | expand

Commit Message

Jagan Teki Jan. 24, 2019, 7:58 p.m. UTC
Minimum PLL used for MIPI is 500MHz, as per manual, but
lowering the min rate by 300MHz can result proper working
nkms divider with the help of desired dclock rate from
panel driver.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
Acked-by: Stephen Boyd <sboyd@kernel.org>
---
 drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 1 +
 1 file changed, 1 insertion(+)

Comments

Maxime Ripard Jan. 25, 2019, 9:24 p.m. UTC | #1
On Fri, Jan 25, 2019 at 01:28:49AM +0530, Jagan Teki wrote:
> Minimum PLL used for MIPI is 500MHz, as per manual, but
> lowering the min rate by 300MHz can result proper working
> nkms divider with the help of desired dclock rate from
> panel driver.
> 
> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> Acked-by: Stephen Boyd <sboyd@kernel.org>

Going 200MHz below the minimum doesn't seem really reasonable. What
is the issue that you are trying to fix here?

It looks like it's picking bad dividers, but if that's the case, this
isn't the proper fix.

Maxime
Jagan Teki Jan. 28, 2019, 9:36 a.m. UTC | #2
On Sat, Jan 26, 2019 at 2:54 AM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
>
> On Fri, Jan 25, 2019 at 01:28:49AM +0530, Jagan Teki wrote:
> > Minimum PLL used for MIPI is 500MHz, as per manual, but
> > lowering the min rate by 300MHz can result proper working
> > nkms divider with the help of desired dclock rate from
> > panel driver.
> >
> > Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> > Acked-by: Stephen Boyd <sboyd@kernel.org>
>
> Going 200MHz below the minimum doesn't seem really reasonable. What
> is the issue that you are trying to fix here?
>
> It looks like it's picking bad dividers, but if that's the case, this
> isn't the proper fix.

As I stated in earlier patches, the whole idea is pick the desired
dclk divider based dclk rate. So the dotclock, sun4i_dclk_round_rate
is unable to get the proper dclk divider at the end, so it eventually
picking up wrong divider value and fired vblank timeout.

So, we come-up with optimal and working min_rate 300MHz in pll-mipi to
get the desired clock something like below.
[    2.415773] [drm] No driver support for vblank timestamp query.
[    2.424116] sun4i_dclk_round_rate: min_div = 4 max_div = 127, rate = 55000000
[    2.424172] ideal = 220000000, rounded = 0
[    2.424176] ideal = 275000000, rounded = 0
[    2.424194] ccu_nkm_round_rate: rate = 330000000
[    2.424197] ideal = 330000000, rounded = 330000000
[    2.424201] sun4i_dclk_round_rate: div = 6 rate = 55000000
[    2.424205] sun4i_dclk_round_rate: min_div = 4 max_div = 127, rate = 55000000
[    2.424209] ideal = 220000000, rounded = 0
[    2.424213] ideal = 275000000, rounded = 0
[    2.424230] ccu_nkm_round_rate: rate = 330000000
[    2.424233] ideal = 330000000, rounded = 330000000
[    2.424236] sun4i_dclk_round_rate: div = 6 rate = 55000000
[    2.424253] ccu_nkm_round_rate: rate = 330000000
[    2.424270] ccu_nkm_round_rate: rate = 330000000
[    2.424278] sun4i_dclk_recalc_rate: val = 1, rate = 330000000
[    2.424281] sun4i_dclk_recalc_rate: val = 1, rate = 330000000
[    2.424306] ccu_nkm_set_rate: rate = 330000000, parent_rate = 297000000
[    2.424309] ccu_nkm_set_rate: _nkm.n = 5
[    2.424311] ccu_nkm_set_rate: _nkm.k = 2
[    2.424313] ccu_nkm_set_rate: _nkm.m = 9
[    2.424661] sun4i_dclk_set_rate div 6
[    2.424668] sun4i_dclk_recalc_rate: val = 6, rate = 55000000

But look like this wouldn't valid for all other dclock rates, say BPI
panel has 30MHz clock that would failed with this logic.

On the other side Allwinner BSP calculating dclk divider based on the
SoC's. for A33 [1] it is fixed dclk divider of 4 and for A64 is is
calculated based on the bpp/lanes.

Since the above min_rate is not desired for possible panels clock, I
think we can rely on BSP to make a move here. I'm planning to do these
changes in next version.

Let me know if you have any comments here?

[1] https://patchwork.kernel.org/patch/10777519/
Maxime Ripard Jan. 29, 2019, 3:13 p.m. UTC | #3
On Mon, Jan 28, 2019 at 03:06:10PM +0530, Jagan Teki wrote:
> On Sat, Jan 26, 2019 at 2:54 AM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> >
> > On Fri, Jan 25, 2019 at 01:28:49AM +0530, Jagan Teki wrote:
> > > Minimum PLL used for MIPI is 500MHz, as per manual, but
> > > lowering the min rate by 300MHz can result proper working
> > > nkms divider with the help of desired dclock rate from
> > > panel driver.
> > >
> > > Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> > > Acked-by: Stephen Boyd <sboyd@kernel.org>
> >
> > Going 200MHz below the minimum doesn't seem really reasonable. What
> > is the issue that you are trying to fix here?
> >
> > It looks like it's picking bad dividers, but if that's the case, this
> > isn't the proper fix.
> 
> As I stated in earlier patches, the whole idea is pick the desired
> dclk divider based dclk rate. So the dotclock, sun4i_dclk_round_rate
> is unable to get the proper dclk divider at the end, so it eventually
> picking up wrong divider value and fired vblank timeout.
> 
> So, we come-up with optimal and working min_rate 300MHz in pll-mipi to
> get the desired clock something like below.
> [    2.415773] [drm] No driver support for vblank timestamp query.
> [    2.424116] sun4i_dclk_round_rate: min_div = 4 max_div = 127, rate = 55000000
> [    2.424172] ideal = 220000000, rounded = 0
> [    2.424176] ideal = 275000000, rounded = 0
> [    2.424194] ccu_nkm_round_rate: rate = 330000000
> [    2.424197] ideal = 330000000, rounded = 330000000
> [    2.424201] sun4i_dclk_round_rate: div = 6 rate = 55000000
> [    2.424205] sun4i_dclk_round_rate: min_div = 4 max_div = 127, rate = 55000000
> [    2.424209] ideal = 220000000, rounded = 0
> [    2.424213] ideal = 275000000, rounded = 0
> [    2.424230] ccu_nkm_round_rate: rate = 330000000
> [    2.424233] ideal = 330000000, rounded = 330000000
> [    2.424236] sun4i_dclk_round_rate: div = 6 rate = 55000000
> [    2.424253] ccu_nkm_round_rate: rate = 330000000
> [    2.424270] ccu_nkm_round_rate: rate = 330000000
> [    2.424278] sun4i_dclk_recalc_rate: val = 1, rate = 330000000
> [    2.424281] sun4i_dclk_recalc_rate: val = 1, rate = 330000000
> [    2.424306] ccu_nkm_set_rate: rate = 330000000, parent_rate = 297000000
> [    2.424309] ccu_nkm_set_rate: _nkm.n = 5
> [    2.424311] ccu_nkm_set_rate: _nkm.k = 2
> [    2.424313] ccu_nkm_set_rate: _nkm.m = 9
> [    2.424661] sun4i_dclk_set_rate div 6
> [    2.424668] sun4i_dclk_recalc_rate: val = 6, rate = 55000000
> 
> But look like this wouldn't valid for all other dclock rates, say BPI
> panel has 30MHz clock that would failed with this logic.
> 
> On the other side Allwinner BSP calculating dclk divider based on the
> SoC's. for A33 [1] it is fixed dclk divider of 4 and for A64 is is
> calculated based on the bpp/lanes.

It looks like the A64 has the same divider of 4:
https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c#L12

I think you're confusing it with the ratio between the pixel clock and
the dotclock, called dsi_div:
https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L198

Maxime
Jagan Teki Jan. 29, 2019, 5:31 p.m. UTC | #4
On Tue, Jan 29, 2019 at 8:43 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
>
> On Mon, Jan 28, 2019 at 03:06:10PM +0530, Jagan Teki wrote:
> > On Sat, Jan 26, 2019 at 2:54 AM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > >
> > > On Fri, Jan 25, 2019 at 01:28:49AM +0530, Jagan Teki wrote:
> > > > Minimum PLL used for MIPI is 500MHz, as per manual, but
> > > > lowering the min rate by 300MHz can result proper working
> > > > nkms divider with the help of desired dclock rate from
> > > > panel driver.
> > > >
> > > > Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> > > > Acked-by: Stephen Boyd <sboyd@kernel.org>
> > >
> > > Going 200MHz below the minimum doesn't seem really reasonable. What
> > > is the issue that you are trying to fix here?
> > >
> > > It looks like it's picking bad dividers, but if that's the case, this
> > > isn't the proper fix.
> >
> > As I stated in earlier patches, the whole idea is pick the desired
> > dclk divider based dclk rate. So the dotclock, sun4i_dclk_round_rate
> > is unable to get the proper dclk divider at the end, so it eventually
> > picking up wrong divider value and fired vblank timeout.
> >
> > So, we come-up with optimal and working min_rate 300MHz in pll-mipi to
> > get the desired clock something like below.
> > [    2.415773] [drm] No driver support for vblank timestamp query.
> > [    2.424116] sun4i_dclk_round_rate: min_div = 4 max_div = 127, rate = 55000000
> > [    2.424172] ideal = 220000000, rounded = 0
> > [    2.424176] ideal = 275000000, rounded = 0
> > [    2.424194] ccu_nkm_round_rate: rate = 330000000
> > [    2.424197] ideal = 330000000, rounded = 330000000
> > [    2.424201] sun4i_dclk_round_rate: div = 6 rate = 55000000
> > [    2.424205] sun4i_dclk_round_rate: min_div = 4 max_div = 127, rate = 55000000
> > [    2.424209] ideal = 220000000, rounded = 0
> > [    2.424213] ideal = 275000000, rounded = 0
> > [    2.424230] ccu_nkm_round_rate: rate = 330000000
> > [    2.424233] ideal = 330000000, rounded = 330000000
> > [    2.424236] sun4i_dclk_round_rate: div = 6 rate = 55000000
> > [    2.424253] ccu_nkm_round_rate: rate = 330000000
> > [    2.424270] ccu_nkm_round_rate: rate = 330000000
> > [    2.424278] sun4i_dclk_recalc_rate: val = 1, rate = 330000000
> > [    2.424281] sun4i_dclk_recalc_rate: val = 1, rate = 330000000
> > [    2.424306] ccu_nkm_set_rate: rate = 330000000, parent_rate = 297000000
> > [    2.424309] ccu_nkm_set_rate: _nkm.n = 5
> > [    2.424311] ccu_nkm_set_rate: _nkm.k = 2
> > [    2.424313] ccu_nkm_set_rate: _nkm.m = 9
> > [    2.424661] sun4i_dclk_set_rate div 6
> > [    2.424668] sun4i_dclk_recalc_rate: val = 6, rate = 55000000
> >
> > But look like this wouldn't valid for all other dclock rates, say BPI
> > panel has 30MHz clock that would failed with this logic.
> >
> > On the other side Allwinner BSP calculating dclk divider based on the
> > SoC's. for A33 [1] it is fixed dclk divider of 4 and for A64 is is
> > calculated based on the bpp/lanes.
>
> It looks like the A64 has the same divider of 4:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c#L12
>
> I think you're confusing it with the ratio between the pixel clock and
> the dotclock, called dsi_div:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L198

Ahh.. I thought this initially but as far as DSI clock computation is
concern, the L12 tcon_div is local variable which is used for edge0
computation in burst mode and not for the dsi clock computation. Since
the BSP is unable to get the tcon_div during edge0 computation, they
defined it locally I think.

You can see the lcd_clk_config() code [2], where we can see DSI clock
computation using dsi_div value.

Here is dump after the in Line 792 which is after computation[3]
[   10.800737] lcd_clk_config: dsi_div = 6, tcon_div = 4, lcd_div = 1
[   10.800743] lcd_clk_config: lcd_dclk_freq = 55, dclk_rate = 55000000
[   10.800749] lcd_clk_config: lcd_rate = 330000000, pll_rate = 330000000

The above dump the lcd_rate 330MHz is computed with panel clock, 55MHz
into dsi_div 6. So this can be our actual divider values dclk_min_div,
dclk_max_div in sun4i_dclk_round_rate (from
drivers/gpu/drm/sun4i/sun4i_dotclock.c)

We can even confirm this from Mainline code:
[    1.866128] sun4i_dclk_round_rate: min_div = 6 max_div = 6, rate = 55000000
[    1.873112] round_rate, parent = 330000000
[    1.877351] round_rate, rate = 330000000
[    1.881338] ideal = 330000000, rounded = 330000000, div = 6
[    1.887232] sun4i_dclk_round_rate: div = 6 rate = 55000000
[    1.887239] sun4i_dclk_round_rate: min_div = 6 max_div = 6, rate = 55000000
[    1.887243] round_rate, parent = 330000000
[    1.887259] round_rate, rate = 330000000
[    1.887264] ideal = 330000000, rounded = 330000000, div = 6
[    1.887267] sun4i_dclk_round_rate: div = 6 rate = 55000000
[    1.887270] round_rate, parent = 330000000
[    1.887286] round_rate, rate = 330000000
[    1.887292] round_rate, parent = 330000000
[    1.887307] round_rate, rate = 330000000
[    1.887320] sun4i_dclk_recalc_rate: val = 1, rate = 330000000
[    1.887324] sun4i_dclk_recalc_rate: val = 1, rate = 330000000
[    1.887350] rate = 330000000
[    1.887353] parent_rate = 297000000
[    1.887355] reg = 0x80c00000
[    1.887359] _nkm.n = 5, nkm->n.offset = 0x1, nkm->n.shift = 8
[    1.887362] _nkm.k = 2, nkm->k.offset = 0x1, nkm->k.shift = 4
[    1.887365] _nkm.m = 9, nkm->m.offset = 0x1, nkm->m.shift = 0
[    1.887712] sun4i_dclk_set_rate div 6
[    1.887720] sun4i_dclk_recalc_rate: val = 6, rate = 55000000

So, the dsi_div from AW BSP is our dclk_mini_div(and dclk_max_div) and
that can be computed as format/lanes in A64.

Hope this explaining clears the diff, let me know if I miss anything.

[2] https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L781
[3] https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L792
Maxime Ripard Feb. 1, 2019, 2:31 p.m. UTC | #5
On Tue, Jan 29, 2019 at 11:01:31PM +0530, Jagan Teki wrote:
> On Tue, Jan 29, 2019 at 8:43 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> >
> > On Mon, Jan 28, 2019 at 03:06:10PM +0530, Jagan Teki wrote:
> > > On Sat, Jan 26, 2019 at 2:54 AM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > > >
> > > > On Fri, Jan 25, 2019 at 01:28:49AM +0530, Jagan Teki wrote:
> > > > > Minimum PLL used for MIPI is 500MHz, as per manual, but
> > > > > lowering the min rate by 300MHz can result proper working
> > > > > nkms divider with the help of desired dclock rate from
> > > > > panel driver.
> > > > >
> > > > > Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> > > > > Acked-by: Stephen Boyd <sboyd@kernel.org>
> > > >
> > > > Going 200MHz below the minimum doesn't seem really reasonable. What
> > > > is the issue that you are trying to fix here?
> > > >
> > > > It looks like it's picking bad dividers, but if that's the case, this
> > > > isn't the proper fix.
> > >
> > > As I stated in earlier patches, the whole idea is pick the desired
> > > dclk divider based dclk rate. So the dotclock, sun4i_dclk_round_rate
> > > is unable to get the proper dclk divider at the end, so it eventually
> > > picking up wrong divider value and fired vblank timeout.
> > >
> > > So, we come-up with optimal and working min_rate 300MHz in pll-mipi to
> > > get the desired clock something like below.
> > > [    2.415773] [drm] No driver support for vblank timestamp query.
> > > [    2.424116] sun4i_dclk_round_rate: min_div = 4 max_div = 127, rate = 55000000
> > > [    2.424172] ideal = 220000000, rounded = 0
> > > [    2.424176] ideal = 275000000, rounded = 0
> > > [    2.424194] ccu_nkm_round_rate: rate = 330000000
> > > [    2.424197] ideal = 330000000, rounded = 330000000
> > > [    2.424201] sun4i_dclk_round_rate: div = 6 rate = 55000000
> > > [    2.424205] sun4i_dclk_round_rate: min_div = 4 max_div = 127, rate = 55000000
> > > [    2.424209] ideal = 220000000, rounded = 0
> > > [    2.424213] ideal = 275000000, rounded = 0
> > > [    2.424230] ccu_nkm_round_rate: rate = 330000000
> > > [    2.424233] ideal = 330000000, rounded = 330000000
> > > [    2.424236] sun4i_dclk_round_rate: div = 6 rate = 55000000
> > > [    2.424253] ccu_nkm_round_rate: rate = 330000000
> > > [    2.424270] ccu_nkm_round_rate: rate = 330000000
> > > [    2.424278] sun4i_dclk_recalc_rate: val = 1, rate = 330000000
> > > [    2.424281] sun4i_dclk_recalc_rate: val = 1, rate = 330000000
> > > [    2.424306] ccu_nkm_set_rate: rate = 330000000, parent_rate = 297000000
> > > [    2.424309] ccu_nkm_set_rate: _nkm.n = 5
> > > [    2.424311] ccu_nkm_set_rate: _nkm.k = 2
> > > [    2.424313] ccu_nkm_set_rate: _nkm.m = 9
> > > [    2.424661] sun4i_dclk_set_rate div 6
> > > [    2.424668] sun4i_dclk_recalc_rate: val = 6, rate = 55000000
> > >
> > > But look like this wouldn't valid for all other dclock rates, say BPI
> > > panel has 30MHz clock that would failed with this logic.
> > >
> > > On the other side Allwinner BSP calculating dclk divider based on the
> > > SoC's. for A33 [1] it is fixed dclk divider of 4 and for A64 is is
> > > calculated based on the bpp/lanes.
> >
> > It looks like the A64 has the same divider of 4:
> > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c#L12
> >
> > I think you're confusing it with the ratio between the pixel clock and
> > the dotclock, called dsi_div:
> > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L198
> 
> Ahh.. I thought this initially but as far as DSI clock computation is
> concern, the L12 tcon_div is local variable which is used for edge0
> computation in burst mode and not for the dsi clock computation. Since
> the BSP is unable to get the tcon_div during edge0 computation, they
> defined it locally I think.
> 
> You can see the lcd_clk_config() code [2], where we can see DSI clock
> computation using dsi_div value.
> 
> Here is dump after the in Line 792 which is after computation[3]
> [   10.800737] lcd_clk_config: dsi_div = 6, tcon_div = 4, lcd_div = 1
> [   10.800743] lcd_clk_config: lcd_dclk_freq = 55, dclk_rate = 55000000
> [   10.800749] lcd_clk_config: lcd_rate = 330000000, pll_rate = 330000000
> 
> The above dump the lcd_rate 330MHz is computed with panel clock, 55MHz
> into dsi_div 6. So this can be our actual divider values dclk_min_div,
> dclk_max_div in sun4i_dclk_round_rate (from
> drivers/gpu/drm/sun4i/sun4i_dotclock.c)

I wish it was in your commit log in the first place, instead of having
to exchange multiple mails over this.

However, I don't think that's quite true, and it might be a bug in
Allwinner's implementation (or rather something quite confusing).

You're right that the lcd_rate and pll_rate seem to be generated from
the pixel clock, and it indeed looks like the ratio between the pixel
clock and the TCON dotclock is defined through the number of bits per
lanes.

However, in this case, dsi_rate is actually the same than lcd_rate,
since pll_rate is going to be divided by dsi_div:
https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L791

Since lcd_div is 1, it also means that in this case, dsi_rate ==
dclk_rate.

The DSI module clock however, is always set to 148.5 MHz. Indeed, if
we look at:
https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L804

We can see that the rate in clk_info is used if it's different than
0. This is filled by disp_al_lcd_get_clk_info, which, in the case of a
DSI panel, will hardcode it to 148.5 MHz:
https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L164

So, the DSI clock is set to this here:
https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L805

The TCON *module* clock (the one in the clock controller) has been set
to lcd_rate (so the pixel clock times the number of bits per lane) here:
https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L800

And the PLL has been set to the same rate here:
https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L794

Let's take a step back now: that function we were looking at,
lcd_clk_config, is called by lcd_clk_enable, which is in turn called
by disp_lcd_enable here:
https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L1328

The next function being called is disp_al_lcd_cfg, and that function
will hardcode the TCON dotclock divider to 4, here:
https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L240

So, in the end, the dotclock divider is always 4, the DSI module clock
is set to 148.5 MHz, and the TCON module clock is set to 330MHz. Since
the TCON module clock doesn't have a divider, the PLL is set at that
same value but this is redundant.

I'll experiment with this and try to see how it works on the A33.

Maxime
Jagan Teki Feb. 1, 2019, 4:33 p.m. UTC | #6
On Fri, Feb 1, 2019 at 8:01 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
>
> On Tue, Jan 29, 2019 at 11:01:31PM +0530, Jagan Teki wrote:
> > On Tue, Jan 29, 2019 at 8:43 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > >
> > > On Mon, Jan 28, 2019 at 03:06:10PM +0530, Jagan Teki wrote:
> > > > On Sat, Jan 26, 2019 at 2:54 AM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > > > >
> > > > > On Fri, Jan 25, 2019 at 01:28:49AM +0530, Jagan Teki wrote:
> > > > > > Minimum PLL used for MIPI is 500MHz, as per manual, but
> > > > > > lowering the min rate by 300MHz can result proper working
> > > > > > nkms divider with the help of desired dclock rate from
> > > > > > panel driver.
> > > > > >
> > > > > > Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> > > > > > Acked-by: Stephen Boyd <sboyd@kernel.org>
> > > > >
> > > > > Going 200MHz below the minimum doesn't seem really reasonable. What
> > > > > is the issue that you are trying to fix here?
> > > > >
> > > > > It looks like it's picking bad dividers, but if that's the case, this
> > > > > isn't the proper fix.
> > > >
> > > > As I stated in earlier patches, the whole idea is pick the desired
> > > > dclk divider based dclk rate. So the dotclock, sun4i_dclk_round_rate
> > > > is unable to get the proper dclk divider at the end, so it eventually
> > > > picking up wrong divider value and fired vblank timeout.
> > > >
> > > > So, we come-up with optimal and working min_rate 300MHz in pll-mipi to
> > > > get the desired clock something like below.
> > > > [    2.415773] [drm] No driver support for vblank timestamp query.
> > > > [    2.424116] sun4i_dclk_round_rate: min_div = 4 max_div = 127, rate = 55000000
> > > > [    2.424172] ideal = 220000000, rounded = 0
> > > > [    2.424176] ideal = 275000000, rounded = 0
> > > > [    2.424194] ccu_nkm_round_rate: rate = 330000000
> > > > [    2.424197] ideal = 330000000, rounded = 330000000
> > > > [    2.424201] sun4i_dclk_round_rate: div = 6 rate = 55000000
> > > > [    2.424205] sun4i_dclk_round_rate: min_div = 4 max_div = 127, rate = 55000000
> > > > [    2.424209] ideal = 220000000, rounded = 0
> > > > [    2.424213] ideal = 275000000, rounded = 0
> > > > [    2.424230] ccu_nkm_round_rate: rate = 330000000
> > > > [    2.424233] ideal = 330000000, rounded = 330000000
> > > > [    2.424236] sun4i_dclk_round_rate: div = 6 rate = 55000000
> > > > [    2.424253] ccu_nkm_round_rate: rate = 330000000
> > > > [    2.424270] ccu_nkm_round_rate: rate = 330000000
> > > > [    2.424278] sun4i_dclk_recalc_rate: val = 1, rate = 330000000
> > > > [    2.424281] sun4i_dclk_recalc_rate: val = 1, rate = 330000000
> > > > [    2.424306] ccu_nkm_set_rate: rate = 330000000, parent_rate = 297000000
> > > > [    2.424309] ccu_nkm_set_rate: _nkm.n = 5
> > > > [    2.424311] ccu_nkm_set_rate: _nkm.k = 2
> > > > [    2.424313] ccu_nkm_set_rate: _nkm.m = 9
> > > > [    2.424661] sun4i_dclk_set_rate div 6
> > > > [    2.424668] sun4i_dclk_recalc_rate: val = 6, rate = 55000000
> > > >
> > > > But look like this wouldn't valid for all other dclock rates, say BPI
> > > > panel has 30MHz clock that would failed with this logic.
> > > >
> > > > On the other side Allwinner BSP calculating dclk divider based on the
> > > > SoC's. for A33 [1] it is fixed dclk divider of 4 and for A64 is is
> > > > calculated based on the bpp/lanes.
> > >
> > > It looks like the A64 has the same divider of 4:
> > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c#L12
> > >
> > > I think you're confusing it with the ratio between the pixel clock and
> > > the dotclock, called dsi_div:
> > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L198
> >
> > Ahh.. I thought this initially but as far as DSI clock computation is
> > concern, the L12 tcon_div is local variable which is used for edge0
> > computation in burst mode and not for the dsi clock computation. Since
> > the BSP is unable to get the tcon_div during edge0 computation, they
> > defined it locally I think.
> >
> > You can see the lcd_clk_config() code [2], where we can see DSI clock
> > computation using dsi_div value.
> >
> > Here is dump after the in Line 792 which is after computation[3]
> > [   10.800737] lcd_clk_config: dsi_div = 6, tcon_div = 4, lcd_div = 1
> > [   10.800743] lcd_clk_config: lcd_dclk_freq = 55, dclk_rate = 55000000
> > [   10.800749] lcd_clk_config: lcd_rate = 330000000, pll_rate = 330000000
> >
> > The above dump the lcd_rate 330MHz is computed with panel clock, 55MHz
> > into dsi_div 6. So this can be our actual divider values dclk_min_div,
> > dclk_max_div in sun4i_dclk_round_rate (from
> > drivers/gpu/drm/sun4i/sun4i_dotclock.c)
>
> I wish it was in your commit log in the first place, instead of having
> to exchange multiple mails over this.
>
> However, I don't think that's quite true, and it might be a bug in
> Allwinner's implementation (or rather something quite confusing).
>
> You're right that the lcd_rate and pll_rate seem to be generated from
> the pixel clock, and it indeed looks like the ratio between the pixel
> clock and the TCON dotclock is defined through the number of bits per
> lanes.
>
> However, in this case, dsi_rate is actually the same than lcd_rate,
> since pll_rate is going to be divided by dsi_div:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L791
>
> Since lcd_div is 1, it also means that in this case, dsi_rate ==
> dclk_rate.

Yes, but the lcd_rate and dsi_rate are not same, since dsi_rate is
again computed as dsi_div with pll_rate.

lcd_rate = dclk_rate * 6;
pll_rate = lcd_rate * 1;
dsi_rate = pll_rate / 6;

[   14.719981] tcon_div = 4, lcd_div = 1, dsi_div = 6, dsi_rate = 148500000
[   14.722666] dsi_div = 6, lcd_div = 1
[   14.722695] [DISP]disp_module_init finish
[   14.727699] lcd_rate = 180000000, pll_rate = 180000000
[   14.730269] dsi_rate = 30000000

> The DSI module clock however, is always set to 148.5 MHz. Indeed, if
> we look at:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L804
>
> We can see that the rate in clk_info is used if it's different than
> 0. This is filled by disp_al_lcd_get_clk_info, which, in the case of a
> DSI panel, will hardcode it to 148.5 MHz:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L164
>
> So, the DSI clock is set to this here:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L805
>
> The TCON *module* clock (the one in the clock controller) has been set
> to lcd_rate (so the pixel clock times the number of bits per lane) here:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L800
>
> And the PLL has been set to the same rate here:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L794
>
> Let's take a step back now: that function we were looking at,
> lcd_clk_config, is called by lcd_clk_enable, which is in turn called
> by disp_lcd_enable here:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L1328
>
> The next function being called is disp_al_lcd_cfg, and that function
> will hardcode the TCON dotclock divider to 4, here:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L240

Haa.. this is reason I have TCON_DCLK register value is 4 in BSP
# devmem 0x01c0c044
0xF0000004

> So, in the end, the dotclock divider is always 4, the DSI module clock
> is set to 148.5 MHz, and the TCON module clock is set to 330MHz. Since
> the TCON module clock doesn't have a divider, the PLL is set at that
> same value but this is redundant.

330 or 180MHz. if we have pixel clock 30MHz with 6 div value it's 180MHz.

>
> I'll experiment with this and try to see how it works on the A33.

OK, thanks. will try digging further on this from my side as well.
Jagan Teki Feb. 11, 2019, 2:07 p.m. UTC | #7
Hi Maxime,

On Fri, Feb 1, 2019 at 8:01 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
>
> On Tue, Jan 29, 2019 at 11:01:31PM +0530, Jagan Teki wrote:
> > On Tue, Jan 29, 2019 at 8:43 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > >
> > > On Mon, Jan 28, 2019 at 03:06:10PM +0530, Jagan Teki wrote:
> > > > On Sat, Jan 26, 2019 at 2:54 AM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > > > >
> > > > > On Fri, Jan 25, 2019 at 01:28:49AM +0530, Jagan Teki wrote:
> > > > > > Minimum PLL used for MIPI is 500MHz, as per manual, but
> > > > > > lowering the min rate by 300MHz can result proper working
> > > > > > nkms divider with the help of desired dclock rate from
> > > > > > panel driver.
> > > > > >
> > > > > > Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> > > > > > Acked-by: Stephen Boyd <sboyd@kernel.org>
> > > > >
> > > > > Going 200MHz below the minimum doesn't seem really reasonable. What
> > > > > is the issue that you are trying to fix here?
> > > > >
> > > > > It looks like it's picking bad dividers, but if that's the case, this
> > > > > isn't the proper fix.
> > > >
> > > > As I stated in earlier patches, the whole idea is pick the desired
> > > > dclk divider based dclk rate. So the dotclock, sun4i_dclk_round_rate
> > > > is unable to get the proper dclk divider at the end, so it eventually
> > > > picking up wrong divider value and fired vblank timeout.
> > > >
> > > > So, we come-up with optimal and working min_rate 300MHz in pll-mipi to
> > > > get the desired clock something like below.
> > > > [    2.415773] [drm] No driver support for vblank timestamp query.
> > > > [    2.424116] sun4i_dclk_round_rate: min_div = 4 max_div = 127, rate = 55000000
> > > > [    2.424172] ideal = 220000000, rounded = 0
> > > > [    2.424176] ideal = 275000000, rounded = 0
> > > > [    2.424194] ccu_nkm_round_rate: rate = 330000000
> > > > [    2.424197] ideal = 330000000, rounded = 330000000
> > > > [    2.424201] sun4i_dclk_round_rate: div = 6 rate = 55000000
> > > > [    2.424205] sun4i_dclk_round_rate: min_div = 4 max_div = 127, rate = 55000000
> > > > [    2.424209] ideal = 220000000, rounded = 0
> > > > [    2.424213] ideal = 275000000, rounded = 0
> > > > [    2.424230] ccu_nkm_round_rate: rate = 330000000
> > > > [    2.424233] ideal = 330000000, rounded = 330000000
> > > > [    2.424236] sun4i_dclk_round_rate: div = 6 rate = 55000000
> > > > [    2.424253] ccu_nkm_round_rate: rate = 330000000
> > > > [    2.424270] ccu_nkm_round_rate: rate = 330000000
> > > > [    2.424278] sun4i_dclk_recalc_rate: val = 1, rate = 330000000
> > > > [    2.424281] sun4i_dclk_recalc_rate: val = 1, rate = 330000000
> > > > [    2.424306] ccu_nkm_set_rate: rate = 330000000, parent_rate = 297000000
> > > > [    2.424309] ccu_nkm_set_rate: _nkm.n = 5
> > > > [    2.424311] ccu_nkm_set_rate: _nkm.k = 2
> > > > [    2.424313] ccu_nkm_set_rate: _nkm.m = 9
> > > > [    2.424661] sun4i_dclk_set_rate div 6
> > > > [    2.424668] sun4i_dclk_recalc_rate: val = 6, rate = 55000000
> > > >
> > > > But look like this wouldn't valid for all other dclock rates, say BPI
> > > > panel has 30MHz clock that would failed with this logic.
> > > >
> > > > On the other side Allwinner BSP calculating dclk divider based on the
> > > > SoC's. for A33 [1] it is fixed dclk divider of 4 and for A64 is is
> > > > calculated based on the bpp/lanes.
> > >
> > > It looks like the A64 has the same divider of 4:
> > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c#L12
> > >
> > > I think you're confusing it with the ratio between the pixel clock and
> > > the dotclock, called dsi_div:
> > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L198
> >
> > Ahh.. I thought this initially but as far as DSI clock computation is
> > concern, the L12 tcon_div is local variable which is used for edge0
> > computation in burst mode and not for the dsi clock computation. Since
> > the BSP is unable to get the tcon_div during edge0 computation, they
> > defined it locally I think.
> >
> > You can see the lcd_clk_config() code [2], where we can see DSI clock
> > computation using dsi_div value.
> >
> > Here is dump after the in Line 792 which is after computation[3]
> > [   10.800737] lcd_clk_config: dsi_div = 6, tcon_div = 4, lcd_div = 1
> > [   10.800743] lcd_clk_config: lcd_dclk_freq = 55, dclk_rate = 55000000
> > [   10.800749] lcd_clk_config: lcd_rate = 330000000, pll_rate = 330000000
> >
> > The above dump the lcd_rate 330MHz is computed with panel clock, 55MHz
> > into dsi_div 6. So this can be our actual divider values dclk_min_div,
> > dclk_max_div in sun4i_dclk_round_rate (from
> > drivers/gpu/drm/sun4i/sun4i_dotclock.c)
>
> I wish it was in your commit log in the first place, instead of having
> to exchange multiple mails over this.
>
> However, I don't think that's quite true, and it might be a bug in
> Allwinner's implementation (or rather something quite confusing).
>
> You're right that the lcd_rate and pll_rate seem to be generated from
> the pixel clock, and it indeed looks like the ratio between the pixel
> clock and the TCON dotclock is defined through the number of bits per
> lanes.
>
> However, in this case, dsi_rate is actually the same than lcd_rate,
> since pll_rate is going to be divided by dsi_div:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L791
>
> Since lcd_div is 1, it also means that in this case, dsi_rate ==
> dclk_rate.
>
> The DSI module clock however, is always set to 148.5 MHz. Indeed, if
> we look at:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L804
>
> We can see that the rate in clk_info is used if it's different than
> 0. This is filled by disp_al_lcd_get_clk_info, which, in the case of a
> DSI panel, will hardcode it to 148.5 MHz:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L164
>
> So, the DSI clock is set to this here:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L805
>
> The TCON *module* clock (the one in the clock controller) has been set
> to lcd_rate (so the pixel clock times the number of bits per lane) here:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L800
>
> And the PLL has been set to the same rate here:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L794
>
> Let's take a step back now: that function we were looking at,
> lcd_clk_config, is called by lcd_clk_enable, which is in turn called
> by disp_lcd_enable here:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L1328
>
> The next function being called is disp_al_lcd_cfg, and that function
> will hardcode the TCON dotclock divider to 4, here:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L240
>
> So, in the end, the dotclock divider is always 4, the DSI module clock
> is set to 148.5 MHz, and the TCON module clock is set to 330MHz. Since
> the TCON module clock doesn't have a divider, the PLL is set at that
> same value but this is redundant.
>
> I'll experiment with this and try to see how it works on the A33.

How is it with A33?
Maxime Ripard Feb. 12, 2019, 9:30 a.m. UTC | #8
On Mon, Feb 11, 2019 at 07:37:57PM +0530, Jagan Teki wrote:
> Hi Maxime,
> 
> On Fri, Feb 1, 2019 at 8:01 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> >
> > On Tue, Jan 29, 2019 at 11:01:31PM +0530, Jagan Teki wrote:
> > > On Tue, Jan 29, 2019 at 8:43 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > > >
> > > > On Mon, Jan 28, 2019 at 03:06:10PM +0530, Jagan Teki wrote:
> > > > > On Sat, Jan 26, 2019 at 2:54 AM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > > > > >
> > > > > > On Fri, Jan 25, 2019 at 01:28:49AM +0530, Jagan Teki wrote:
> > > > > > > Minimum PLL used for MIPI is 500MHz, as per manual, but
> > > > > > > lowering the min rate by 300MHz can result proper working
> > > > > > > nkms divider with the help of desired dclock rate from
> > > > > > > panel driver.
> > > > > > >
> > > > > > > Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> > > > > > > Acked-by: Stephen Boyd <sboyd@kernel.org>
> > > > > >
> > > > > > Going 200MHz below the minimum doesn't seem really reasonable. What
> > > > > > is the issue that you are trying to fix here?
> > > > > >
> > > > > > It looks like it's picking bad dividers, but if that's the case, this
> > > > > > isn't the proper fix.
> > > > >
> > > > > As I stated in earlier patches, the whole idea is pick the desired
> > > > > dclk divider based dclk rate. So the dotclock, sun4i_dclk_round_rate
> > > > > is unable to get the proper dclk divider at the end, so it eventually
> > > > > picking up wrong divider value and fired vblank timeout.
> > > > >
> > > > > So, we come-up with optimal and working min_rate 300MHz in pll-mipi to
> > > > > get the desired clock something like below.
> > > > > [    2.415773] [drm] No driver support for vblank timestamp query.
> > > > > [    2.424116] sun4i_dclk_round_rate: min_div = 4 max_div = 127, rate = 55000000
> > > > > [    2.424172] ideal = 220000000, rounded = 0
> > > > > [    2.424176] ideal = 275000000, rounded = 0
> > > > > [    2.424194] ccu_nkm_round_rate: rate = 330000000
> > > > > [    2.424197] ideal = 330000000, rounded = 330000000
> > > > > [    2.424201] sun4i_dclk_round_rate: div = 6 rate = 55000000
> > > > > [    2.424205] sun4i_dclk_round_rate: min_div = 4 max_div = 127, rate = 55000000
> > > > > [    2.424209] ideal = 220000000, rounded = 0
> > > > > [    2.424213] ideal = 275000000, rounded = 0
> > > > > [    2.424230] ccu_nkm_round_rate: rate = 330000000
> > > > > [    2.424233] ideal = 330000000, rounded = 330000000
> > > > > [    2.424236] sun4i_dclk_round_rate: div = 6 rate = 55000000
> > > > > [    2.424253] ccu_nkm_round_rate: rate = 330000000
> > > > > [    2.424270] ccu_nkm_round_rate: rate = 330000000
> > > > > [    2.424278] sun4i_dclk_recalc_rate: val = 1, rate = 330000000
> > > > > [    2.424281] sun4i_dclk_recalc_rate: val = 1, rate = 330000000
> > > > > [    2.424306] ccu_nkm_set_rate: rate = 330000000, parent_rate = 297000000
> > > > > [    2.424309] ccu_nkm_set_rate: _nkm.n = 5
> > > > > [    2.424311] ccu_nkm_set_rate: _nkm.k = 2
> > > > > [    2.424313] ccu_nkm_set_rate: _nkm.m = 9
> > > > > [    2.424661] sun4i_dclk_set_rate div 6
> > > > > [    2.424668] sun4i_dclk_recalc_rate: val = 6, rate = 55000000
> > > > >
> > > > > But look like this wouldn't valid for all other dclock rates, say BPI
> > > > > panel has 30MHz clock that would failed with this logic.
> > > > >
> > > > > On the other side Allwinner BSP calculating dclk divider based on the
> > > > > SoC's. for A33 [1] it is fixed dclk divider of 4 and for A64 is is
> > > > > calculated based on the bpp/lanes.
> > > >
> > > > It looks like the A64 has the same divider of 4:
> > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c#L12
> > > >
> > > > I think you're confusing it with the ratio between the pixel clock and
> > > > the dotclock, called dsi_div:
> > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L198
> > >
> > > Ahh.. I thought this initially but as far as DSI clock computation is
> > > concern, the L12 tcon_div is local variable which is used for edge0
> > > computation in burst mode and not for the dsi clock computation. Since
> > > the BSP is unable to get the tcon_div during edge0 computation, they
> > > defined it locally I think.
> > >
> > > You can see the lcd_clk_config() code [2], where we can see DSI clock
> > > computation using dsi_div value.
> > >
> > > Here is dump after the in Line 792 which is after computation[3]
> > > [   10.800737] lcd_clk_config: dsi_div = 6, tcon_div = 4, lcd_div = 1
> > > [   10.800743] lcd_clk_config: lcd_dclk_freq = 55, dclk_rate = 55000000
> > > [   10.800749] lcd_clk_config: lcd_rate = 330000000, pll_rate = 330000000
> > >
> > > The above dump the lcd_rate 330MHz is computed with panel clock, 55MHz
> > > into dsi_div 6. So this can be our actual divider values dclk_min_div,
> > > dclk_max_div in sun4i_dclk_round_rate (from
> > > drivers/gpu/drm/sun4i/sun4i_dotclock.c)
> >
> > I wish it was in your commit log in the first place, instead of having
> > to exchange multiple mails over this.
> >
> > However, I don't think that's quite true, and it might be a bug in
> > Allwinner's implementation (or rather something quite confusing).
> >
> > You're right that the lcd_rate and pll_rate seem to be generated from
> > the pixel clock, and it indeed looks like the ratio between the pixel
> > clock and the TCON dotclock is defined through the number of bits per
> > lanes.
> >
> > However, in this case, dsi_rate is actually the same than lcd_rate,
> > since pll_rate is going to be divided by dsi_div:
> > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L791
> >
> > Since lcd_div is 1, it also means that in this case, dsi_rate ==
> > dclk_rate.
> >
> > The DSI module clock however, is always set to 148.5 MHz. Indeed, if
> > we look at:
> > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L804
> >
> > We can see that the rate in clk_info is used if it's different than
> > 0. This is filled by disp_al_lcd_get_clk_info, which, in the case of a
> > DSI panel, will hardcode it to 148.5 MHz:
> > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L164
> >
> > So, the DSI clock is set to this here:
> > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L805
> >
> > The TCON *module* clock (the one in the clock controller) has been set
> > to lcd_rate (so the pixel clock times the number of bits per lane) here:
> > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L800
> >
> > And the PLL has been set to the same rate here:
> > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L794
> >
> > Let's take a step back now: that function we were looking at,
> > lcd_clk_config, is called by lcd_clk_enable, which is in turn called
> > by disp_lcd_enable here:
> > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L1328
> >
> > The next function being called is disp_al_lcd_cfg, and that function
> > will hardcode the TCON dotclock divider to 4, here:
> > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L240
> >
> > So, in the end, the dotclock divider is always 4, the DSI module clock
> > is set to 148.5 MHz, and the TCON module clock is set to 330MHz. Since
> > the TCON module clock doesn't have a divider, the PLL is set at that
> > same value but this is redundant.
> >
> > I'll experiment with this and try to see how it works on the A33.
> 
> How is it with A33?

The conclusions are the one I sent in my last series

Maxime
Jagan Teki Feb. 12, 2019, 9:38 a.m. UTC | #9
On Tue, Feb 12, 2019 at 3:00 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
>
> On Mon, Feb 11, 2019 at 07:37:57PM +0530, Jagan Teki wrote:
> > Hi Maxime,
> >
> > On Fri, Feb 1, 2019 at 8:01 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > >
> > > On Tue, Jan 29, 2019 at 11:01:31PM +0530, Jagan Teki wrote:
> > > > On Tue, Jan 29, 2019 at 8:43 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > > > >
> > > > > On Mon, Jan 28, 2019 at 03:06:10PM +0530, Jagan Teki wrote:
> > > > > > On Sat, Jan 26, 2019 at 2:54 AM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > > > > > >
> > > > > > > On Fri, Jan 25, 2019 at 01:28:49AM +0530, Jagan Teki wrote:
> > > > > > > > Minimum PLL used for MIPI is 500MHz, as per manual, but
> > > > > > > > lowering the min rate by 300MHz can result proper working
> > > > > > > > nkms divider with the help of desired dclock rate from
> > > > > > > > panel driver.
> > > > > > > >
> > > > > > > > Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> > > > > > > > Acked-by: Stephen Boyd <sboyd@kernel.org>
> > > > > > >
> > > > > > > Going 200MHz below the minimum doesn't seem really reasonable. What
> > > > > > > is the issue that you are trying to fix here?
> > > > > > >
> > > > > > > It looks like it's picking bad dividers, but if that's the case, this
> > > > > > > isn't the proper fix.
> > > > > >
> > > > > > As I stated in earlier patches, the whole idea is pick the desired
> > > > > > dclk divider based dclk rate. So the dotclock, sun4i_dclk_round_rate
> > > > > > is unable to get the proper dclk divider at the end, so it eventually
> > > > > > picking up wrong divider value and fired vblank timeout.
> > > > > >
> > > > > > So, we come-up with optimal and working min_rate 300MHz in pll-mipi to
> > > > > > get the desired clock something like below.
> > > > > > [    2.415773] [drm] No driver support for vblank timestamp query.
> > > > > > [    2.424116] sun4i_dclk_round_rate: min_div = 4 max_div = 127, rate = 55000000
> > > > > > [    2.424172] ideal = 220000000, rounded = 0
> > > > > > [    2.424176] ideal = 275000000, rounded = 0
> > > > > > [    2.424194] ccu_nkm_round_rate: rate = 330000000
> > > > > > [    2.424197] ideal = 330000000, rounded = 330000000
> > > > > > [    2.424201] sun4i_dclk_round_rate: div = 6 rate = 55000000
> > > > > > [    2.424205] sun4i_dclk_round_rate: min_div = 4 max_div = 127, rate = 55000000
> > > > > > [    2.424209] ideal = 220000000, rounded = 0
> > > > > > [    2.424213] ideal = 275000000, rounded = 0
> > > > > > [    2.424230] ccu_nkm_round_rate: rate = 330000000
> > > > > > [    2.424233] ideal = 330000000, rounded = 330000000
> > > > > > [    2.424236] sun4i_dclk_round_rate: div = 6 rate = 55000000
> > > > > > [    2.424253] ccu_nkm_round_rate: rate = 330000000
> > > > > > [    2.424270] ccu_nkm_round_rate: rate = 330000000
> > > > > > [    2.424278] sun4i_dclk_recalc_rate: val = 1, rate = 330000000
> > > > > > [    2.424281] sun4i_dclk_recalc_rate: val = 1, rate = 330000000
> > > > > > [    2.424306] ccu_nkm_set_rate: rate = 330000000, parent_rate = 297000000
> > > > > > [    2.424309] ccu_nkm_set_rate: _nkm.n = 5
> > > > > > [    2.424311] ccu_nkm_set_rate: _nkm.k = 2
> > > > > > [    2.424313] ccu_nkm_set_rate: _nkm.m = 9
> > > > > > [    2.424661] sun4i_dclk_set_rate div 6
> > > > > > [    2.424668] sun4i_dclk_recalc_rate: val = 6, rate = 55000000
> > > > > >
> > > > > > But look like this wouldn't valid for all other dclock rates, say BPI
> > > > > > panel has 30MHz clock that would failed with this logic.
> > > > > >
> > > > > > On the other side Allwinner BSP calculating dclk divider based on the
> > > > > > SoC's. for A33 [1] it is fixed dclk divider of 4 and for A64 is is
> > > > > > calculated based on the bpp/lanes.
> > > > >
> > > > > It looks like the A64 has the same divider of 4:
> > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c#L12
> > > > >
> > > > > I think you're confusing it with the ratio between the pixel clock and
> > > > > the dotclock, called dsi_div:
> > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L198
> > > >
> > > > Ahh.. I thought this initially but as far as DSI clock computation is
> > > > concern, the L12 tcon_div is local variable which is used for edge0
> > > > computation in burst mode and not for the dsi clock computation. Since
> > > > the BSP is unable to get the tcon_div during edge0 computation, they
> > > > defined it locally I think.
> > > >
> > > > You can see the lcd_clk_config() code [2], where we can see DSI clock
> > > > computation using dsi_div value.
> > > >
> > > > Here is dump after the in Line 792 which is after computation[3]
> > > > [   10.800737] lcd_clk_config: dsi_div = 6, tcon_div = 4, lcd_div = 1
> > > > [   10.800743] lcd_clk_config: lcd_dclk_freq = 55, dclk_rate = 55000000
> > > > [   10.800749] lcd_clk_config: lcd_rate = 330000000, pll_rate = 330000000
> > > >
> > > > The above dump the lcd_rate 330MHz is computed with panel clock, 55MHz
> > > > into dsi_div 6. So this can be our actual divider values dclk_min_div,
> > > > dclk_max_div in sun4i_dclk_round_rate (from
> > > > drivers/gpu/drm/sun4i/sun4i_dotclock.c)
> > >
> > > I wish it was in your commit log in the first place, instead of having
> > > to exchange multiple mails over this.
> > >
> > > However, I don't think that's quite true, and it might be a bug in
> > > Allwinner's implementation (or rather something quite confusing).
> > >
> > > You're right that the lcd_rate and pll_rate seem to be generated from
> > > the pixel clock, and it indeed looks like the ratio between the pixel
> > > clock and the TCON dotclock is defined through the number of bits per
> > > lanes.
> > >
> > > However, in this case, dsi_rate is actually the same than lcd_rate,
> > > since pll_rate is going to be divided by dsi_div:
> > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L791
> > >
> > > Since lcd_div is 1, it also means that in this case, dsi_rate ==
> > > dclk_rate.
> > >
> > > The DSI module clock however, is always set to 148.5 MHz. Indeed, if
> > > we look at:
> > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L804
> > >
> > > We can see that the rate in clk_info is used if it's different than
> > > 0. This is filled by disp_al_lcd_get_clk_info, which, in the case of a
> > > DSI panel, will hardcode it to 148.5 MHz:
> > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L164
> > >
> > > So, the DSI clock is set to this here:
> > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L805
> > >
> > > The TCON *module* clock (the one in the clock controller) has been set
> > > to lcd_rate (so the pixel clock times the number of bits per lane) here:
> > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L800
> > >
> > > And the PLL has been set to the same rate here:
> > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L794
> > >
> > > Let's take a step back now: that function we were looking at,
> > > lcd_clk_config, is called by lcd_clk_enable, which is in turn called
> > > by disp_lcd_enable here:
> > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L1328
> > >
> > > The next function being called is disp_al_lcd_cfg, and that function
> > > will hardcode the TCON dotclock divider to 4, here:
> > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L240
> > >
> > > So, in the end, the dotclock divider is always 4, the DSI module clock
> > > is set to 148.5 MHz, and the TCON module clock is set to 330MHz. Since
> > > the TCON module clock doesn't have a divider, the PLL is set at that
> > > same value but this is redundant.
> > >
> > > I'll experiment with this and try to see how it works on the A33.
> >
> > How is it with A33?
>
> The conclusions are the one I sent in my last series

In this series?
[PATCH v3 0/8] drm/sun4i: dsi: Add burst mode support
Jagan Teki May 24, 2019, 10:07 a.m. UTC | #10
On Fri, Feb 1, 2019 at 8:01 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
>
> On Tue, Jan 29, 2019 at 11:01:31PM +0530, Jagan Teki wrote:
> > On Tue, Jan 29, 2019 at 8:43 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > >
> > > On Mon, Jan 28, 2019 at 03:06:10PM +0530, Jagan Teki wrote:
> > > > On Sat, Jan 26, 2019 at 2:54 AM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > > > >
> > > > > On Fri, Jan 25, 2019 at 01:28:49AM +0530, Jagan Teki wrote:
> > > > > > Minimum PLL used for MIPI is 500MHz, as per manual, but
> > > > > > lowering the min rate by 300MHz can result proper working
> > > > > > nkms divider with the help of desired dclock rate from
> > > > > > panel driver.
> > > > > >
> > > > > > Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> > > > > > Acked-by: Stephen Boyd <sboyd@kernel.org>
> > > > >
> > > > > Going 200MHz below the minimum doesn't seem really reasonable. What
> > > > > is the issue that you are trying to fix here?
> > > > >
> > > > > It looks like it's picking bad dividers, but if that's the case, this
> > > > > isn't the proper fix.
> > > >
> > > > As I stated in earlier patches, the whole idea is pick the desired
> > > > dclk divider based dclk rate. So the dotclock, sun4i_dclk_round_rate
> > > > is unable to get the proper dclk divider at the end, so it eventually
> > > > picking up wrong divider value and fired vblank timeout.
> > > >
> > > > So, we come-up with optimal and working min_rate 300MHz in pll-mipi to
> > > > get the desired clock something like below.
> > > > [    2.415773] [drm] No driver support for vblank timestamp query.
> > > > [    2.424116] sun4i_dclk_round_rate: min_div = 4 max_div = 127, rate = 55000000
> > > > [    2.424172] ideal = 220000000, rounded = 0
> > > > [    2.424176] ideal = 275000000, rounded = 0
> > > > [    2.424194] ccu_nkm_round_rate: rate = 330000000
> > > > [    2.424197] ideal = 330000000, rounded = 330000000
> > > > [    2.424201] sun4i_dclk_round_rate: div = 6 rate = 55000000
> > > > [    2.424205] sun4i_dclk_round_rate: min_div = 4 max_div = 127, rate = 55000000
> > > > [    2.424209] ideal = 220000000, rounded = 0
> > > > [    2.424213] ideal = 275000000, rounded = 0
> > > > [    2.424230] ccu_nkm_round_rate: rate = 330000000
> > > > [    2.424233] ideal = 330000000, rounded = 330000000
> > > > [    2.424236] sun4i_dclk_round_rate: div = 6 rate = 55000000
> > > > [    2.424253] ccu_nkm_round_rate: rate = 330000000
> > > > [    2.424270] ccu_nkm_round_rate: rate = 330000000
> > > > [    2.424278] sun4i_dclk_recalc_rate: val = 1, rate = 330000000
> > > > [    2.424281] sun4i_dclk_recalc_rate: val = 1, rate = 330000000
> > > > [    2.424306] ccu_nkm_set_rate: rate = 330000000, parent_rate = 297000000
> > > > [    2.424309] ccu_nkm_set_rate: _nkm.n = 5
> > > > [    2.424311] ccu_nkm_set_rate: _nkm.k = 2
> > > > [    2.424313] ccu_nkm_set_rate: _nkm.m = 9
> > > > [    2.424661] sun4i_dclk_set_rate div 6
> > > > [    2.424668] sun4i_dclk_recalc_rate: val = 6, rate = 55000000
> > > >
> > > > But look like this wouldn't valid for all other dclock rates, say BPI
> > > > panel has 30MHz clock that would failed with this logic.
> > > >
> > > > On the other side Allwinner BSP calculating dclk divider based on the
> > > > SoC's. for A33 [1] it is fixed dclk divider of 4 and for A64 is is
> > > > calculated based on the bpp/lanes.
> > >
> > > It looks like the A64 has the same divider of 4:
> > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c#L12
> > >
> > > I think you're confusing it with the ratio between the pixel clock and
> > > the dotclock, called dsi_div:
> > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L198
> >
> > Ahh.. I thought this initially but as far as DSI clock computation is
> > concern, the L12 tcon_div is local variable which is used for edge0
> > computation in burst mode and not for the dsi clock computation. Since
> > the BSP is unable to get the tcon_div during edge0 computation, they
> > defined it locally I think.
> >
> > You can see the lcd_clk_config() code [2], where we can see DSI clock
> > computation using dsi_div value.
> >
> > Here is dump after the in Line 792 which is after computation[3]
> > [   10.800737] lcd_clk_config: dsi_div = 6, tcon_div = 4, lcd_div = 1
> > [   10.800743] lcd_clk_config: lcd_dclk_freq = 55, dclk_rate = 55000000
> > [   10.800749] lcd_clk_config: lcd_rate = 330000000, pll_rate = 330000000
> >
> > The above dump the lcd_rate 330MHz is computed with panel clock, 55MHz
> > into dsi_div 6. So this can be our actual divider values dclk_min_div,
> > dclk_max_div in sun4i_dclk_round_rate (from
> > drivers/gpu/drm/sun4i/sun4i_dotclock.c)
>
> I wish it was in your commit log in the first place, instead of having
> to exchange multiple mails over this.
>
> However, I don't think that's quite true, and it might be a bug in
> Allwinner's implementation (or rather something quite confusing).
>
> You're right that the lcd_rate and pll_rate seem to be generated from
> the pixel clock, and it indeed looks like the ratio between the pixel
> clock and the TCON dotclock is defined through the number of bits per
> lanes.
>
> However, in this case, dsi_rate is actually the same than lcd_rate,
> since pll_rate is going to be divided by dsi_div:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L791
>
> Since lcd_div is 1, it also means that in this case, dsi_rate ==
> dclk_rate.
>
> The DSI module clock however, is always set to 148.5 MHz. Indeed, if
> we look at:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L804
>
> We can see that the rate in clk_info is used if it's different than
> 0. This is filled by disp_al_lcd_get_clk_info, which, in the case of a
> DSI panel, will hardcode it to 148.5 MHz:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L164
>
> So, the DSI clock is set to this here:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L805
>
> The TCON *module* clock (the one in the clock controller) has been set
> to lcd_rate (so the pixel clock times the number of bits per lane) here:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L800
>
> And the PLL has been set to the same rate here:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L794

Let me explain, something more.

According to bsp there are clk_info.tcon_div which I will explain below.
clk_info.dsi_div which is dynamic and it depends on bpp/lanes, so it
is 6 for 24bpp and 4 lanes devices.

PLL rate here depends on dsi_div (not tcon_div)

Code here
https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L784

is computing the actual set rate, which depends on dsi_rate.

lcd_rate = dclk_rate * clk_info.dsi_div;
dsi_rate = pll_rate / clk_info.dsi_div;

Say if the dclk_rate 148MHz then the dsi_rate is 888MHz which set rate
for above link you mentioned.

Here are the evidence with some prints.

https://gist.github.com/openedev/9bae2d87d2fcc06b999fe48c998b7043
https://gist.github.com/openedev/700de2e3701b2bf3ad1aa0f0fa862c9a

>
> Let's take a step back now: that function we were looking at,
> lcd_clk_config, is called by lcd_clk_enable, which is in turn called
> by disp_lcd_enable here:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L1328
>
> The next function being called is disp_al_lcd_cfg, and that function
> will hardcode the TCON dotclock divider to 4, here:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L240

tcon_div from BSP point-of-view of there are two variants
00) clk_info.tcon_div which is 4 and same is set the divider position
in SUN4I_TCON0_DCLK_REG (like above link refer)
01) tcon_div which is 4 and used for edge timings computation
https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c#L12

The real reason for 01) is again 4 is they set the divider to 4 in 00)
which is technically wrong because the dividers which used during
dotclock in above (dsi_div) should be used here as well. Since there
is no dynamic way of doing this BSP hard-coding these values.

Patches 5,6,7 on this series doing this
https://patchwork.freedesktop.org/series/60847/

Hope this explanation helps?
Maxime Ripard June 5, 2019, 6:49 a.m. UTC | #11
Hi,

I've reordered the mail a bit to work on chunks

On Fri, May 24, 2019 at 03:37:42PM +0530, Jagan Teki wrote:
> > I wish it was in your commit log in the first place, instead of having
> > to exchange multiple mails over this.
> >
> > However, I don't think that's quite true, and it might be a bug in
> > Allwinner's implementation (or rather something quite confusing).
> >
> > You're right that the lcd_rate and pll_rate seem to be generated from
> > the pixel clock, and it indeed looks like the ratio between the pixel
> > clock and the TCON dotclock is defined through the number of bits per
> > lanes.
> >
> > However, in this case, dsi_rate is actually the same than lcd_rate,
> > since pll_rate is going to be divided by dsi_div:
> > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L791
> >
> > Since lcd_div is 1, it also means that in this case, dsi_rate ==
> > dclk_rate.
> >
> > The DSI module clock however, is always set to 148.5 MHz. Indeed, if
> > we look at:
> > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L804
> >
> > We can see that the rate in clk_info is used if it's different than
> > 0. This is filled by disp_al_lcd_get_clk_info, which, in the case of a
> > DSI panel, will hardcode it to 148.5 MHz:
> > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L164
>
> Let me explain, something more.
>
> According to bsp there are clk_info.tcon_div which I will explain below.
> clk_info.dsi_div which is dynamic and it depends on bpp/lanes, so it
> is 6 for 24bpp and 4 lanes devices.
>
> PLL rate here depends on dsi_div (not tcon_div)
>
> Code here
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L784
>
> is computing the actual set rate, which depends on dsi_rate.
>
> lcd_rate = dclk_rate * clk_info.dsi_div;
> dsi_rate = pll_rate / clk_info.dsi_div;
>
> Say if the dclk_rate 148MHz then the dsi_rate is 888MHz which set rate
> for above link you mentioned.
>
> Here are the evidence with some prints.
>
> https://gist.github.com/openedev/9bae2d87d2fcc06b999fe48c998b7043
> https://gist.github.com/openedev/700de2e3701b2bf3ad1aa0f0fa862c9a

Ok, so we agree up to this point, and the prints confirm that the
analysis above is the right one.

> > So, the DSI clock is set to this here:
> > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L805

Your patch doesn't address that, so let's leave that one alone.

> > The TCON *module* clock (the one in the clock controller) has been set
> > to lcd_rate (so the pixel clock times the number of bits per lane) here:
> > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L800
> >
> > And the PLL has been set to the same rate here:
> > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L794
> >
> > Let's take a step back now: that function we were looking at,
> > lcd_clk_config, is called by lcd_clk_enable, which is in turn called
> > by disp_lcd_enable here:
> > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L1328
> >
> > The next function being called is disp_al_lcd_cfg, and that function
> > will hardcode the TCON dotclock divider to 4, here:
> > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L240
>
> tcon_div from BSP point-of-view of there are two variants
> 00) clk_info.tcon_div which is 4 and same is set the divider position
> in SUN4I_TCON0_DCLK_REG (like above link refer)
> 01) tcon_div which is 4 and used for edge timings computation
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c#L12
>
> The real reason for 01) is again 4 is they set the divider to 4 in 00)
> which is technically wrong because the dividers which used during
> dotclock in above (dsi_div) should be used here as well. Since there
> is no dynamic way of doing this BSP hard-coding these values.
>
> Patches 5,6,7 on this series doing this
> https://patchwork.freedesktop.org/series/60847/
>
> Hope this explanation helps?

It doesn't.

The clock tree is this one:

PLL(s) -> TCON module clock -> TCON dotclock.

The links I mentioned above show that the clock set to lcd_rate is the
TCON module clocks (and it should be the one taking the bpp and lanes
into account), while the TCON dotclock uses a fixed divider of 4.

In your patches, you're using the bpp / lanes divider on the TCON
dotclock, ie, the wrong clock.

Again, I'm not saying that my analysis of the source code is correct
here. But you haven't said anything to prove it's wrong either.

Maxime

--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
Jagan Teki June 5, 2019, 7:33 a.m. UTC | #12
On Wed, Jun 5, 2019 at 12:19 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
>
> Hi,
>
> I've reordered the mail a bit to work on chunks
>
> On Fri, May 24, 2019 at 03:37:42PM +0530, Jagan Teki wrote:
> > > I wish it was in your commit log in the first place, instead of having
> > > to exchange multiple mails over this.
> > >
> > > However, I don't think that's quite true, and it might be a bug in
> > > Allwinner's implementation (or rather something quite confusing).
> > >
> > > You're right that the lcd_rate and pll_rate seem to be generated from
> > > the pixel clock, and it indeed looks like the ratio between the pixel
> > > clock and the TCON dotclock is defined through the number of bits per
> > > lanes.
> > >
> > > However, in this case, dsi_rate is actually the same than lcd_rate,
> > > since pll_rate is going to be divided by dsi_div:
> > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L791
> > >
> > > Since lcd_div is 1, it also means that in this case, dsi_rate ==
> > > dclk_rate.
> > >
> > > The DSI module clock however, is always set to 148.5 MHz. Indeed, if
> > > we look at:
> > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L804
> > >
> > > We can see that the rate in clk_info is used if it's different than
> > > 0. This is filled by disp_al_lcd_get_clk_info, which, in the case of a
> > > DSI panel, will hardcode it to 148.5 MHz:
> > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L164
> >
> > Let me explain, something more.
> >
> > According to bsp there are clk_info.tcon_div which I will explain below.
> > clk_info.dsi_div which is dynamic and it depends on bpp/lanes, so it
> > is 6 for 24bpp and 4 lanes devices.
> >
> > PLL rate here depends on dsi_div (not tcon_div)
> >
> > Code here
> > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L784
> >
> > is computing the actual set rate, which depends on dsi_rate.
> >
> > lcd_rate = dclk_rate * clk_info.dsi_div;
> > dsi_rate = pll_rate / clk_info.dsi_div;
> >
> > Say if the dclk_rate 148MHz then the dsi_rate is 888MHz which set rate
> > for above link you mentioned.
> >
> > Here are the evidence with some prints.
> >
> > https://gist.github.com/openedev/9bae2d87d2fcc06b999fe48c998b7043
> > https://gist.github.com/openedev/700de2e3701b2bf3ad1aa0f0fa862c9a
>
> Ok, so we agree up to this point, and the prints confirm that the
> analysis above is the right one.
>
> > > So, the DSI clock is set to this here:
> > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L805
>
> Your patch doesn't address that, so let's leave that one alone.

Basically this is final pll set rate when sun4i_dotclock.c called the
desired rate with ccu_nkm.c so it ended the final rate with parent as
Line 8 of
https://gist.github.com/openedev/700de2e3701b2bf3ad1aa0f0fa862c9a

>
> > > The TCON *module* clock (the one in the clock controller) has been set
> > > to lcd_rate (so the pixel clock times the number of bits per lane) here:
> > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L800
> > >
> > > And the PLL has been set to the same rate here:
> > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L794
> > >
> > > Let's take a step back now: that function we were looking at,
> > > lcd_clk_config, is called by lcd_clk_enable, which is in turn called
> > > by disp_lcd_enable here:
> > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L1328
> > >
> > > The next function being called is disp_al_lcd_cfg, and that function
> > > will hardcode the TCON dotclock divider to 4, here:
> > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L240
> >
> > tcon_div from BSP point-of-view of there are two variants
> > 00) clk_info.tcon_div which is 4 and same is set the divider position
> > in SUN4I_TCON0_DCLK_REG (like above link refer)
> > 01) tcon_div which is 4 and used for edge timings computation
> > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c#L12
> >
> > The real reason for 01) is again 4 is they set the divider to 4 in 00)
> > which is technically wrong because the dividers which used during
> > dotclock in above (dsi_div) should be used here as well. Since there
> > is no dynamic way of doing this BSP hard-coding these values.
> >
> > Patches 5,6,7 on this series doing this
> > https://patchwork.freedesktop.org/series/60847/
> >
> > Hope this explanation helps?
>
> It doesn't.
>
> The clock tree is this one:
>
> PLL(s) -> TCON module clock -> TCON dotclock.
>
> The links I mentioned above show that the clock set to lcd_rate is the
> TCON module clocks (and it should be the one taking the bpp and lanes
> into account), while the TCON dotclock uses a fixed divider of 4.

Sorry, I can argue much other-than giving some code snips, according to [1]

00) Line 785, 786 with dclk_rate 148000000

lcd_rate = dclk_rate * clk_info.dsi_div;
pll_rate = lcd_rate * clk_info.lcd_div;

Since dsi_div is 6 (bpp/lanes), lcd_div 1

lcd_rate = 888000000, pll_rate = 888000000

01)  Line 801, 804 are final rates computed as per clock driver (say
ccu_nkm in mainline)

lcd_rate_set=891000000

As per your comments if it would be 4 then the desired numbers are
would be 592000000 not 888000000.

This is what I'm trying to say in all mails, and same as verified with
2-lanes devices as well where the dsi_div is 12 so the final rate is
290MHz * 12

>
> In your patches, you're using the bpp / lanes divider on the TCON
> dotclock, ie, the wrong clock.
>
> Again, I'm not saying that my analysis of the source code is correct
> here. But you haven't said anything to prove it's wrong either.

Don't understand what proves are remaining, I have explained each line
from BSP and saying pll rate is depends on dsi_div which is bpp/lanes
not wrt tcon_div on BSP (which is set to default 4) and which indeed
verified in A33, R40. all the code using bpp/lanes.

Please let me know if you need any more information to look?

[1] https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L805
Maxime Ripard June 14, 2019, 2:24 p.m. UTC | #13
On Wed, Jun 05, 2019 at 01:03:16PM +0530, Jagan Teki wrote:
> On Wed, Jun 5, 2019 at 12:19 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> >
> > Hi,
> >
> > I've reordered the mail a bit to work on chunks
> >
> > On Fri, May 24, 2019 at 03:37:42PM +0530, Jagan Teki wrote:
> > > > I wish it was in your commit log in the first place, instead of having
> > > > to exchange multiple mails over this.
> > > >
> > > > However, I don't think that's quite true, and it might be a bug in
> > > > Allwinner's implementation (or rather something quite confusing).
> > > >
> > > > You're right that the lcd_rate and pll_rate seem to be generated from
> > > > the pixel clock, and it indeed looks like the ratio between the pixel
> > > > clock and the TCON dotclock is defined through the number of bits per
> > > > lanes.
> > > >
> > > > However, in this case, dsi_rate is actually the same than lcd_rate,
> > > > since pll_rate is going to be divided by dsi_div:
> > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L791
> > > >
> > > > Since lcd_div is 1, it also means that in this case, dsi_rate ==
> > > > dclk_rate.
> > > >
> > > > The DSI module clock however, is always set to 148.5 MHz. Indeed, if
> > > > we look at:
> > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L804
> > > >
> > > > We can see that the rate in clk_info is used if it's different than
> > > > 0. This is filled by disp_al_lcd_get_clk_info, which, in the case of a
> > > > DSI panel, will hardcode it to 148.5 MHz:
> > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L164
> > >
> > > Let me explain, something more.
> > >
> > > According to bsp there are clk_info.tcon_div which I will explain below.
> > > clk_info.dsi_div which is dynamic and it depends on bpp/lanes, so it
> > > is 6 for 24bpp and 4 lanes devices.
> > >
> > > PLL rate here depends on dsi_div (not tcon_div)
> > >
> > > Code here
> > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L784
> > >
> > > is computing the actual set rate, which depends on dsi_rate.
> > >
> > > lcd_rate = dclk_rate * clk_info.dsi_div;
> > > dsi_rate = pll_rate / clk_info.dsi_div;
> > >
> > > Say if the dclk_rate 148MHz then the dsi_rate is 888MHz which set rate
> > > for above link you mentioned.
> > >
> > > Here are the evidence with some prints.
> > >
> > > https://gist.github.com/openedev/9bae2d87d2fcc06b999fe48c998b7043
> > > https://gist.github.com/openedev/700de2e3701b2bf3ad1aa0f0fa862c9a
> >
> > Ok, so we agree up to this point, and the prints confirm that the
> > analysis above is the right one.
> >
> > > > So, the DSI clock is set to this here:
> > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L805
> >
> > Your patch doesn't address that, so let's leave that one alone.
>
> Basically this is final pll set rate when sun4i_dotclock.c called the
> desired rate with ccu_nkm.c so it ended the final rate with parent as
> Line 8 of
> https://gist.github.com/openedev/700de2e3701b2bf3ad1aa0f0fa862c9a

If that's important to the driver, it should be set explicitly then,
and not work by accident.

> > > > The TCON *module* clock (the one in the clock controller) has been set
> > > > to lcd_rate (so the pixel clock times the number of bits per lane) here:
> > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L800
> > > >
> > > > And the PLL has been set to the same rate here:
> > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L794
> > > >
> > > > Let's take a step back now: that function we were looking at,
> > > > lcd_clk_config, is called by lcd_clk_enable, which is in turn called
> > > > by disp_lcd_enable here:
> > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L1328
> > > >
> > > > The next function being called is disp_al_lcd_cfg, and that function
> > > > will hardcode the TCON dotclock divider to 4, here:
> > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L240
> > >
> > > tcon_div from BSP point-of-view of there are two variants
> > > 00) clk_info.tcon_div which is 4 and same is set the divider position
> > > in SUN4I_TCON0_DCLK_REG (like above link refer)
> > > 01) tcon_div which is 4 and used for edge timings computation
> > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c#L12
> > >
> > > The real reason for 01) is again 4 is they set the divider to 4 in 00)
> > > which is technically wrong because the dividers which used during
> > > dotclock in above (dsi_div) should be used here as well. Since there
> > > is no dynamic way of doing this BSP hard-coding these values.
> > >
> > > Patches 5,6,7 on this series doing this
> > > https://patchwork.freedesktop.org/series/60847/
> > >
> > > Hope this explanation helps?
> >
> > It doesn't.
> >
> > The clock tree is this one:
> >
> > PLL(s) -> TCON module clock -> TCON dotclock.
> >
> > The links I mentioned above show that the clock set to lcd_rate is the
> > TCON module clocks (and it should be the one taking the bpp and lanes
> > into account), while the TCON dotclock uses a fixed divider of 4.
>
> Sorry, I can argue much other-than giving some code snips, according to [1]
>
> 00) Line 785, 786 with dclk_rate 148000000
>
> lcd_rate = dclk_rate * clk_info.dsi_div;
> pll_rate = lcd_rate * clk_info.lcd_div;
>
> Since dsi_div is 6 (bpp/lanes), lcd_div 1
>
> lcd_rate = 888000000, pll_rate = 888000000
>
> 01)  Line 801, 804 are final rates computed as per clock driver (say
> ccu_nkm in mainline)
>
> lcd_rate_set=891000000
>
> As per your comments if it would be 4 then the desired numbers are
> would be 592000000 not 888000000.
>
> This is what I'm trying to say in all mails, and same as verified with
> 2-lanes devices as well where the dsi_div is 12 so the final rate is
> 290MHz * 12

In the code you sent, you're forcing a divider on the internal TCON
clock, while that one is fixed in the BSP.

There's indeed the bpp / lanes divider, but it's used in the *parent*
clock of the one you're changing.

And the dsi0_clk clock you pointed out in the code snippet is yet
another clock, the MIPI DSI module clock.

The analysis you have is probably correct, you're just not
implementing it properly in your patch.

Maxime

--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
Jagan Teki June 20, 2019, 6:27 p.m. UTC | #14
On Fri, Jun 14, 2019 at 7:54 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
>
> On Wed, Jun 05, 2019 at 01:03:16PM +0530, Jagan Teki wrote:
> > On Wed, Jun 5, 2019 at 12:19 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > >
> > > Hi,
> > >
> > > I've reordered the mail a bit to work on chunks
> > >
> > > On Fri, May 24, 2019 at 03:37:42PM +0530, Jagan Teki wrote:
> > > > > I wish it was in your commit log in the first place, instead of having
> > > > > to exchange multiple mails over this.
> > > > >
> > > > > However, I don't think that's quite true, and it might be a bug in
> > > > > Allwinner's implementation (or rather something quite confusing).
> > > > >
> > > > > You're right that the lcd_rate and pll_rate seem to be generated from
> > > > > the pixel clock, and it indeed looks like the ratio between the pixel
> > > > > clock and the TCON dotclock is defined through the number of bits per
> > > > > lanes.
> > > > >
> > > > > However, in this case, dsi_rate is actually the same than lcd_rate,
> > > > > since pll_rate is going to be divided by dsi_div:
> > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L791
> > > > >
> > > > > Since lcd_div is 1, it also means that in this case, dsi_rate ==
> > > > > dclk_rate.
> > > > >
> > > > > The DSI module clock however, is always set to 148.5 MHz. Indeed, if
> > > > > we look at:
> > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L804
> > > > >
> > > > > We can see that the rate in clk_info is used if it's different than
> > > > > 0. This is filled by disp_al_lcd_get_clk_info, which, in the case of a
> > > > > DSI panel, will hardcode it to 148.5 MHz:
> > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L164
> > > >
> > > > Let me explain, something more.
> > > >
> > > > According to bsp there are clk_info.tcon_div which I will explain below.
> > > > clk_info.dsi_div which is dynamic and it depends on bpp/lanes, so it
> > > > is 6 for 24bpp and 4 lanes devices.
> > > >
> > > > PLL rate here depends on dsi_div (not tcon_div)
> > > >
> > > > Code here
> > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L784
> > > >
> > > > is computing the actual set rate, which depends on dsi_rate.
> > > >
> > > > lcd_rate = dclk_rate * clk_info.dsi_div;
> > > > dsi_rate = pll_rate / clk_info.dsi_div;
> > > >
> > > > Say if the dclk_rate 148MHz then the dsi_rate is 888MHz which set rate
> > > > for above link you mentioned.
> > > >
> > > > Here are the evidence with some prints.
> > > >
> > > > https://gist.github.com/openedev/9bae2d87d2fcc06b999fe48c998b7043
> > > > https://gist.github.com/openedev/700de2e3701b2bf3ad1aa0f0fa862c9a
> > >
> > > Ok, so we agree up to this point, and the prints confirm that the
> > > analysis above is the right one.
> > >
> > > > > So, the DSI clock is set to this here:
> > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L805
> > >
> > > Your patch doesn't address that, so let's leave that one alone.
> >
> > Basically this is final pll set rate when sun4i_dotclock.c called the
> > desired rate with ccu_nkm.c so it ended the final rate with parent as
> > Line 8 of
> > https://gist.github.com/openedev/700de2e3701b2bf3ad1aa0f0fa862c9a
>
> If that's important to the driver, it should be set explicitly then,
> and not work by accident.
>
> > > > > The TCON *module* clock (the one in the clock controller) has been set
> > > > > to lcd_rate (so the pixel clock times the number of bits per lane) here:
> > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L800
> > > > >
> > > > > And the PLL has been set to the same rate here:
> > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L794
> > > > >
> > > > > Let's take a step back now: that function we were looking at,
> > > > > lcd_clk_config, is called by lcd_clk_enable, which is in turn called
> > > > > by disp_lcd_enable here:
> > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L1328
> > > > >
> > > > > The next function being called is disp_al_lcd_cfg, and that function
> > > > > will hardcode the TCON dotclock divider to 4, here:
> > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L240
> > > >
> > > > tcon_div from BSP point-of-view of there are two variants
> > > > 00) clk_info.tcon_div which is 4 and same is set the divider position
> > > > in SUN4I_TCON0_DCLK_REG (like above link refer)
> > > > 01) tcon_div which is 4 and used for edge timings computation
> > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c#L12
> > > >
> > > > The real reason for 01) is again 4 is they set the divider to 4 in 00)
> > > > which is technically wrong because the dividers which used during
> > > > dotclock in above (dsi_div) should be used here as well. Since there
> > > > is no dynamic way of doing this BSP hard-coding these values.
> > > >
> > > > Patches 5,6,7 on this series doing this
> > > > https://patchwork.freedesktop.org/series/60847/
> > > >
> > > > Hope this explanation helps?
> > >
> > > It doesn't.
> > >
> > > The clock tree is this one:
> > >
> > > PLL(s) -> TCON module clock -> TCON dotclock.
> > >
> > > The links I mentioned above show that the clock set to lcd_rate is the
> > > TCON module clocks (and it should be the one taking the bpp and lanes
> > > into account), while the TCON dotclock uses a fixed divider of 4.
> >
> > Sorry, I can argue much other-than giving some code snips, according to [1]
> >
> > 00) Line 785, 786 with dclk_rate 148000000
> >
> > lcd_rate = dclk_rate * clk_info.dsi_div;
> > pll_rate = lcd_rate * clk_info.lcd_div;
> >
> > Since dsi_div is 6 (bpp/lanes), lcd_div 1
> >
> > lcd_rate = 888000000, pll_rate = 888000000
> >
> > 01)  Line 801, 804 are final rates computed as per clock driver (say
> > ccu_nkm in mainline)
> >
> > lcd_rate_set=891000000
> >
> > As per your comments if it would be 4 then the desired numbers are
> > would be 592000000 not 888000000.
> >
> > This is what I'm trying to say in all mails, and same as verified with
> > 2-lanes devices as well where the dsi_div is 12 so the final rate is
> > 290MHz * 12
>
> In the code you sent, you're forcing a divider on the internal TCON
> clock, while that one is fixed in the BSP.
>
> There's indeed the bpp / lanes divider, but it's used in the *parent*
> clock of the one you're changing.
>
> And the dsi0_clk clock you pointed out in the code snippet is yet
> another clock, the MIPI DSI module clock.

Correct, look like I refereed wrong reference in the above mail. sorry
for the noise.

Actually I'm trying to explain about pll_rate here which indeed
depends on dsi.div
https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L786

lcd_rate = dclk_rate * clk_info.dsi_div;
pll_rate = lcd_rate * clk_info.lcd_div;

Say

1) For 148MHz dclk_rate with dsi_div is 6 (24/4) lcd_div is 1 which
resulting pll_rate is 888MHz.

2) For 30MHz dclk_rate with 4 lane and 24 RGB the resulting pll_rate is 180MHz

3) For 27.5MHz dclk_rate with 2 lane and 24 RGB the resulting pll_rate is 330MHz

Here is the few more logs in code, for case 2)

[    1.920441] sun4i_dclk_round_rate: min_div = 6 max_div = 6, rate = 30000000
[    1.920505] ideal = 180000000, rounded = 178200000
[    1.920509] sun4i_dclk_round_rate: div = 6 rate = 29700000
[    1.920514] sun4i_dclk_round_rate: min_div = 6 max_div = 6, rate = 30000000
[    1.920532] ideal = 180000000, rounded = 178200000
[    1.920535] sun4i_dclk_round_rate: div = 6 rate = 29700000
[    1.920572] sun4i_dclk_recalc_rate: val = 1, rate = 178200000
[    1.920576] sun4i_dclk_recalc_rate: val = 1, rate = 178200000
[    1.920597] rate = 178200000
[    1.920599] parent_rate = 297000000
[    1.920602] reg = 0x90c00000
[    1.920605] _nkm.n = 3, nkm->n.offset = 0x1, nkm->n.shift = 8
[    1.920609] _nkm.k = 2, nkm->k.offset = 0x1, nkm->k.shift = 4
[    1.920612] _nkm.m = 10, nkm->m.offset = 0x1, nkm->m.shift = 0
[    1.920958] sun4i_dclk_set_rate div 6
[    1.920966] sun4i_dclk_recalc_rate: val = 6, rate = 29700000

and clk_summary:

    pll-video0                        1        1        1   297000000
        0     0  50000
       hdmi                           0        0        0   297000000
        0     0  50000
       tcon1                          0        0        0   297000000
        0     0  50000
       pll-mipi                       1        1        1   178200000
        0     0  50000
          tcon0                       2        2        1   178200000
        0     0  50000
             tcon-pixel-clock         1        1        1    29700000
        0     0  50000
       pll-video0-2x                  0        0        0   594000000
        0     0  50000
Maxime Ripard June 25, 2019, 2:49 p.m. UTC | #15
On Thu, Jun 20, 2019 at 11:57:44PM +0530, Jagan Teki wrote:
> On Fri, Jun 14, 2019 at 7:54 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> >
> > On Wed, Jun 05, 2019 at 01:03:16PM +0530, Jagan Teki wrote:
> > > On Wed, Jun 5, 2019 at 12:19 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > > >
> > > > Hi,
> > > >
> > > > I've reordered the mail a bit to work on chunks
> > > >
> > > > On Fri, May 24, 2019 at 03:37:42PM +0530, Jagan Teki wrote:
> > > > > > I wish it was in your commit log in the first place, instead of having
> > > > > > to exchange multiple mails over this.
> > > > > >
> > > > > > However, I don't think that's quite true, and it might be a bug in
> > > > > > Allwinner's implementation (or rather something quite confusing).
> > > > > >
> > > > > > You're right that the lcd_rate and pll_rate seem to be generated from
> > > > > > the pixel clock, and it indeed looks like the ratio between the pixel
> > > > > > clock and the TCON dotclock is defined through the number of bits per
> > > > > > lanes.
> > > > > >
> > > > > > However, in this case, dsi_rate is actually the same than lcd_rate,
> > > > > > since pll_rate is going to be divided by dsi_div:
> > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L791
> > > > > >
> > > > > > Since lcd_div is 1, it also means that in this case, dsi_rate ==
> > > > > > dclk_rate.
> > > > > >
> > > > > > The DSI module clock however, is always set to 148.5 MHz. Indeed, if
> > > > > > we look at:
> > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L804
> > > > > >
> > > > > > We can see that the rate in clk_info is used if it's different than
> > > > > > 0. This is filled by disp_al_lcd_get_clk_info, which, in the case of a
> > > > > > DSI panel, will hardcode it to 148.5 MHz:
> > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L164
> > > > >
> > > > > Let me explain, something more.
> > > > >
> > > > > According to bsp there are clk_info.tcon_div which I will explain below.
> > > > > clk_info.dsi_div which is dynamic and it depends on bpp/lanes, so it
> > > > > is 6 for 24bpp and 4 lanes devices.
> > > > >
> > > > > PLL rate here depends on dsi_div (not tcon_div)
> > > > >
> > > > > Code here
> > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L784
> > > > >
> > > > > is computing the actual set rate, which depends on dsi_rate.
> > > > >
> > > > > lcd_rate = dclk_rate * clk_info.dsi_div;
> > > > > dsi_rate = pll_rate / clk_info.dsi_div;
> > > > >
> > > > > Say if the dclk_rate 148MHz then the dsi_rate is 888MHz which set rate
> > > > > for above link you mentioned.
> > > > >
> > > > > Here are the evidence with some prints.
> > > > >
> > > > > https://gist.github.com/openedev/9bae2d87d2fcc06b999fe48c998b7043
> > > > > https://gist.github.com/openedev/700de2e3701b2bf3ad1aa0f0fa862c9a
> > > >
> > > > Ok, so we agree up to this point, and the prints confirm that the
> > > > analysis above is the right one.
> > > >
> > > > > > So, the DSI clock is set to this here:
> > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L805
> > > >
> > > > Your patch doesn't address that, so let's leave that one alone.
> > >
> > > Basically this is final pll set rate when sun4i_dotclock.c called the
> > > desired rate with ccu_nkm.c so it ended the final rate with parent as
> > > Line 8 of
> > > https://gist.github.com/openedev/700de2e3701b2bf3ad1aa0f0fa862c9a
> >
> > If that's important to the driver, it should be set explicitly then,
> > and not work by accident.
> >
> > > > > > The TCON *module* clock (the one in the clock controller) has been set
> > > > > > to lcd_rate (so the pixel clock times the number of bits per lane) here:
> > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L800
> > > > > >
> > > > > > And the PLL has been set to the same rate here:
> > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L794
> > > > > >
> > > > > > Let's take a step back now: that function we were looking at,
> > > > > > lcd_clk_config, is called by lcd_clk_enable, which is in turn called
> > > > > > by disp_lcd_enable here:
> > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L1328
> > > > > >
> > > > > > The next function being called is disp_al_lcd_cfg, and that function
> > > > > > will hardcode the TCON dotclock divider to 4, here:
> > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L240
> > > > >
> > > > > tcon_div from BSP point-of-view of there are two variants
> > > > > 00) clk_info.tcon_div which is 4 and same is set the divider position
> > > > > in SUN4I_TCON0_DCLK_REG (like above link refer)
> > > > > 01) tcon_div which is 4 and used for edge timings computation
> > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c#L12
> > > > >
> > > > > The real reason for 01) is again 4 is they set the divider to 4 in 00)
> > > > > which is technically wrong because the dividers which used during
> > > > > dotclock in above (dsi_div) should be used here as well. Since there
> > > > > is no dynamic way of doing this BSP hard-coding these values.
> > > > >
> > > > > Patches 5,6,7 on this series doing this
> > > > > https://patchwork.freedesktop.org/series/60847/
> > > > >
> > > > > Hope this explanation helps?
> > > >
> > > > It doesn't.
> > > >
> > > > The clock tree is this one:
> > > >
> > > > PLL(s) -> TCON module clock -> TCON dotclock.
> > > >
> > > > The links I mentioned above show that the clock set to lcd_rate is the
> > > > TCON module clocks (and it should be the one taking the bpp and lanes
> > > > into account), while the TCON dotclock uses a fixed divider of 4.
> > >
> > > Sorry, I can argue much other-than giving some code snips, according to [1]
> > >
> > > 00) Line 785, 786 with dclk_rate 148000000
> > >
> > > lcd_rate = dclk_rate * clk_info.dsi_div;
> > > pll_rate = lcd_rate * clk_info.lcd_div;
> > >
> > > Since dsi_div is 6 (bpp/lanes), lcd_div 1
> > >
> > > lcd_rate = 888000000, pll_rate = 888000000
> > >
> > > 01)  Line 801, 804 are final rates computed as per clock driver (say
> > > ccu_nkm in mainline)
> > >
> > > lcd_rate_set=891000000
> > >
> > > As per your comments if it would be 4 then the desired numbers are
> > > would be 592000000 not 888000000.
> > >
> > > This is what I'm trying to say in all mails, and same as verified with
> > > 2-lanes devices as well where the dsi_div is 12 so the final rate is
> > > 290MHz * 12
> >
> > In the code you sent, you're forcing a divider on the internal TCON
> > clock, while that one is fixed in the BSP.
> >
> > There's indeed the bpp / lanes divider, but it's used in the *parent*
> > clock of the one you're changing.
> >
> > And the dsi0_clk clock you pointed out in the code snippet is yet
> > another clock, the MIPI DSI module clock.
>
> Correct, look like I refereed wrong reference in the above mail. sorry
> for the noise.
>
> Actually I'm trying to explain about pll_rate here which indeed
> depends on dsi.div
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L786
>
> lcd_rate = dclk_rate * clk_info.dsi_div;
> pll_rate = lcd_rate * clk_info.lcd_div;
>
> Say
>
> 1) For 148MHz dclk_rate with dsi_div is 6 (24/4) lcd_div is 1 which
> resulting pll_rate is 888MHz.
>
> 2) For 30MHz dclk_rate with 4 lane and 24 RGB the resulting pll_rate is 180MHz
>
> 3) For 27.5MHz dclk_rate with 2 lane and 24 RGB the resulting pll_rate is 330MHz
>
> Here is the few more logs in code, for case 2)
>
> [    1.920441] sun4i_dclk_round_rate: min_div = 6 max_div = 6, rate = 30000000
> [    1.920505] ideal = 180000000, rounded = 178200000
> [    1.920509] sun4i_dclk_round_rate: div = 6 rate = 29700000
> [    1.920514] sun4i_dclk_round_rate: min_div = 6 max_div = 6, rate = 30000000
> [    1.920532] ideal = 180000000, rounded = 178200000
> [    1.920535] sun4i_dclk_round_rate: div = 6 rate = 29700000
> [    1.920572] sun4i_dclk_recalc_rate: val = 1, rate = 178200000
> [    1.920576] sun4i_dclk_recalc_rate: val = 1, rate = 178200000
> [    1.920597] rate = 178200000
> [    1.920599] parent_rate = 297000000
> [    1.920602] reg = 0x90c00000
> [    1.920605] _nkm.n = 3, nkm->n.offset = 0x1, nkm->n.shift = 8
> [    1.920609] _nkm.k = 2, nkm->k.offset = 0x1, nkm->k.shift = 4
> [    1.920612] _nkm.m = 10, nkm->m.offset = 0x1, nkm->m.shift = 0
> [    1.920958] sun4i_dclk_set_rate div 6
> [    1.920966] sun4i_dclk_recalc_rate: val = 6, rate = 29700000
>
> and clk_summary:
>
>     pll-video0                        1        1        1   297000000
>         0     0  50000
>        hdmi                           0        0        0   297000000
>         0     0  50000
>        tcon1                          0        0        0   297000000
>         0     0  50000
>        pll-mipi                       1        1        1   178200000
>         0     0  50000
>           tcon0                       2        2        1   178200000
>         0     0  50000
>              tcon-pixel-clock         1        1        1    29700000
>         0     0  50000
>        pll-video0-2x                  0        0        0   594000000
>         0     0  50000

This discussion is going nowhere. I'm telling you that your patch
doesn't apply the divider you want on the proper clock, and you're
replying that indeed, you're applying it on the wrong clock.

It might work by accident in your case, but the board I have here
clearly indicates otherwise, so there's two possible way out here:

  - Either you apply that divider to the TCON *module* clock, and not
    the dclk

  - Or you point to somewhere in the allwinner code where the bpp /
    lanes divider is used for the dclk divider.


Maxim

--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
Jagan Teki June 25, 2019, 3:30 p.m. UTC | #16
On Tue, Jun 25, 2019 at 8:19 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
>
> On Thu, Jun 20, 2019 at 11:57:44PM +0530, Jagan Teki wrote:
> > On Fri, Jun 14, 2019 at 7:54 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > >
> > > On Wed, Jun 05, 2019 at 01:03:16PM +0530, Jagan Teki wrote:
> > > > On Wed, Jun 5, 2019 at 12:19 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > > > >
> > > > > Hi,
> > > > >
> > > > > I've reordered the mail a bit to work on chunks
> > > > >
> > > > > On Fri, May 24, 2019 at 03:37:42PM +0530, Jagan Teki wrote:
> > > > > > > I wish it was in your commit log in the first place, instead of having
> > > > > > > to exchange multiple mails over this.
> > > > > > >
> > > > > > > However, I don't think that's quite true, and it might be a bug in
> > > > > > > Allwinner's implementation (or rather something quite confusing).
> > > > > > >
> > > > > > > You're right that the lcd_rate and pll_rate seem to be generated from
> > > > > > > the pixel clock, and it indeed looks like the ratio between the pixel
> > > > > > > clock and the TCON dotclock is defined through the number of bits per
> > > > > > > lanes.
> > > > > > >
> > > > > > > However, in this case, dsi_rate is actually the same than lcd_rate,
> > > > > > > since pll_rate is going to be divided by dsi_div:
> > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L791
> > > > > > >
> > > > > > > Since lcd_div is 1, it also means that in this case, dsi_rate ==
> > > > > > > dclk_rate.
> > > > > > >
> > > > > > > The DSI module clock however, is always set to 148.5 MHz. Indeed, if
> > > > > > > we look at:
> > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L804
> > > > > > >
> > > > > > > We can see that the rate in clk_info is used if it's different than
> > > > > > > 0. This is filled by disp_al_lcd_get_clk_info, which, in the case of a
> > > > > > > DSI panel, will hardcode it to 148.5 MHz:
> > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L164
> > > > > >
> > > > > > Let me explain, something more.
> > > > > >
> > > > > > According to bsp there are clk_info.tcon_div which I will explain below.
> > > > > > clk_info.dsi_div which is dynamic and it depends on bpp/lanes, so it
> > > > > > is 6 for 24bpp and 4 lanes devices.
> > > > > >
> > > > > > PLL rate here depends on dsi_div (not tcon_div)
> > > > > >
> > > > > > Code here
> > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L784
> > > > > >
> > > > > > is computing the actual set rate, which depends on dsi_rate.
> > > > > >
> > > > > > lcd_rate = dclk_rate * clk_info.dsi_div;
> > > > > > dsi_rate = pll_rate / clk_info.dsi_div;
> > > > > >
> > > > > > Say if the dclk_rate 148MHz then the dsi_rate is 888MHz which set rate
> > > > > > for above link you mentioned.
> > > > > >
> > > > > > Here are the evidence with some prints.
> > > > > >
> > > > > > https://gist.github.com/openedev/9bae2d87d2fcc06b999fe48c998b7043
> > > > > > https://gist.github.com/openedev/700de2e3701b2bf3ad1aa0f0fa862c9a
> > > > >
> > > > > Ok, so we agree up to this point, and the prints confirm that the
> > > > > analysis above is the right one.
> > > > >
> > > > > > > So, the DSI clock is set to this here:
> > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L805
> > > > >
> > > > > Your patch doesn't address that, so let's leave that one alone.
> > > >
> > > > Basically this is final pll set rate when sun4i_dotclock.c called the
> > > > desired rate with ccu_nkm.c so it ended the final rate with parent as
> > > > Line 8 of
> > > > https://gist.github.com/openedev/700de2e3701b2bf3ad1aa0f0fa862c9a
> > >
> > > If that's important to the driver, it should be set explicitly then,
> > > and not work by accident.
> > >
> > > > > > > The TCON *module* clock (the one in the clock controller) has been set
> > > > > > > to lcd_rate (so the pixel clock times the number of bits per lane) here:
> > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L800
> > > > > > >
> > > > > > > And the PLL has been set to the same rate here:
> > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L794
> > > > > > >
> > > > > > > Let's take a step back now: that function we were looking at,
> > > > > > > lcd_clk_config, is called by lcd_clk_enable, which is in turn called
> > > > > > > by disp_lcd_enable here:
> > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L1328
> > > > > > >
> > > > > > > The next function being called is disp_al_lcd_cfg, and that function
> > > > > > > will hardcode the TCON dotclock divider to 4, here:
> > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L240
> > > > > >
> > > > > > tcon_div from BSP point-of-view of there are two variants
> > > > > > 00) clk_info.tcon_div which is 4 and same is set the divider position
> > > > > > in SUN4I_TCON0_DCLK_REG (like above link refer)
> > > > > > 01) tcon_div which is 4 and used for edge timings computation
> > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c#L12
> > > > > >
> > > > > > The real reason for 01) is again 4 is they set the divider to 4 in 00)
> > > > > > which is technically wrong because the dividers which used during
> > > > > > dotclock in above (dsi_div) should be used here as well. Since there
> > > > > > is no dynamic way of doing this BSP hard-coding these values.
> > > > > >
> > > > > > Patches 5,6,7 on this series doing this
> > > > > > https://patchwork.freedesktop.org/series/60847/
> > > > > >
> > > > > > Hope this explanation helps?
> > > > >
> > > > > It doesn't.
> > > > >
> > > > > The clock tree is this one:
> > > > >
> > > > > PLL(s) -> TCON module clock -> TCON dotclock.
> > > > >
> > > > > The links I mentioned above show that the clock set to lcd_rate is the
> > > > > TCON module clocks (and it should be the one taking the bpp and lanes
> > > > > into account), while the TCON dotclock uses a fixed divider of 4.
> > > >
> > > > Sorry, I can argue much other-than giving some code snips, according to [1]
> > > >
> > > > 00) Line 785, 786 with dclk_rate 148000000
> > > >
> > > > lcd_rate = dclk_rate * clk_info.dsi_div;
> > > > pll_rate = lcd_rate * clk_info.lcd_div;
> > > >
> > > > Since dsi_div is 6 (bpp/lanes), lcd_div 1
> > > >
> > > > lcd_rate = 888000000, pll_rate = 888000000
> > > >
> > > > 01)  Line 801, 804 are final rates computed as per clock driver (say
> > > > ccu_nkm in mainline)
> > > >
> > > > lcd_rate_set=891000000
> > > >
> > > > As per your comments if it would be 4 then the desired numbers are
> > > > would be 592000000 not 888000000.
> > > >
> > > > This is what I'm trying to say in all mails, and same as verified with
> > > > 2-lanes devices as well where the dsi_div is 12 so the final rate is
> > > > 290MHz * 12
> > >
> > > In the code you sent, you're forcing a divider on the internal TCON
> > > clock, while that one is fixed in the BSP.
> > >
> > > There's indeed the bpp / lanes divider, but it's used in the *parent*
> > > clock of the one you're changing.
> > >
> > > And the dsi0_clk clock you pointed out in the code snippet is yet
> > > another clock, the MIPI DSI module clock.
> >
> > Correct, look like I refereed wrong reference in the above mail. sorry
> > for the noise.
> >
> > Actually I'm trying to explain about pll_rate here which indeed
> > depends on dsi.div
> > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L786
> >
> > lcd_rate = dclk_rate * clk_info.dsi_div;
> > pll_rate = lcd_rate * clk_info.lcd_div;
> >
> > Say
> >
> > 1) For 148MHz dclk_rate with dsi_div is 6 (24/4) lcd_div is 1 which
> > resulting pll_rate is 888MHz.
> >
> > 2) For 30MHz dclk_rate with 4 lane and 24 RGB the resulting pll_rate is 180MHz
> >
> > 3) For 27.5MHz dclk_rate with 2 lane and 24 RGB the resulting pll_rate is 330MHz
> >
> > Here is the few more logs in code, for case 2)
> >
> > [    1.920441] sun4i_dclk_round_rate: min_div = 6 max_div = 6, rate = 30000000
> > [    1.920505] ideal = 180000000, rounded = 178200000
> > [    1.920509] sun4i_dclk_round_rate: div = 6 rate = 29700000
> > [    1.920514] sun4i_dclk_round_rate: min_div = 6 max_div = 6, rate = 30000000
> > [    1.920532] ideal = 180000000, rounded = 178200000
> > [    1.920535] sun4i_dclk_round_rate: div = 6 rate = 29700000
> > [    1.920572] sun4i_dclk_recalc_rate: val = 1, rate = 178200000
> > [    1.920576] sun4i_dclk_recalc_rate: val = 1, rate = 178200000
> > [    1.920597] rate = 178200000
> > [    1.920599] parent_rate = 297000000
> > [    1.920602] reg = 0x90c00000
> > [    1.920605] _nkm.n = 3, nkm->n.offset = 0x1, nkm->n.shift = 8
> > [    1.920609] _nkm.k = 2, nkm->k.offset = 0x1, nkm->k.shift = 4
> > [    1.920612] _nkm.m = 10, nkm->m.offset = 0x1, nkm->m.shift = 0
> > [    1.920958] sun4i_dclk_set_rate div 6
> > [    1.920966] sun4i_dclk_recalc_rate: val = 6, rate = 29700000
> >
> > and clk_summary:
> >
> >     pll-video0                        1        1        1   297000000
> >         0     0  50000
> >        hdmi                           0        0        0   297000000
> >         0     0  50000
> >        tcon1                          0        0        0   297000000
> >         0     0  50000
> >        pll-mipi                       1        1        1   178200000
> >         0     0  50000
> >           tcon0                       2        2        1   178200000
> >         0     0  50000
> >              tcon-pixel-clock         1        1        1    29700000
> >         0     0  50000
> >        pll-video0-2x                  0        0        0   594000000
> >         0     0  50000
>
> This discussion is going nowhere. I'm telling you that your patch
> doesn't apply the divider you want on the proper clock, and you're
> replying that indeed, you're applying it on the wrong clock.
>
> It might work by accident in your case, but the board I have here
> clearly indicates otherwise, so there's two possible way out here:
>
>   - Either you apply that divider to the TCON *module* clock, and not
>     the dclk
>
>   - Or you point to somewhere in the allwinner code where the bpp /
>     lanes divider is used for the dclk divider.

I don't know how to proceed further on this, as you say it might work
in accident but I have tested this in A33, A64 and R40 with 4
different DSI panels and one DSI-RGB bridge. All of them do use
PLL_MIPI (pll_rate) and it indeed depends on bpp/lanes

4-lane, 24-bit: Novatek NT35596 panel
4-lane, 24-bit: Feiyang, FY07024di26a30d panel
4-lane, 24-bit: Bananapi-s070wv20 panel
2-lane, 24-bit: Techstar,ts8550b panel

and

4-lane, 24-bit, ICN6211 DSI-to-RGB bridge panel

All above listed panels and bridges are working as per BSP and do
follow bpp/lanes and for DIVIDER 4 no panel is working.

The panels/bridges I have has tested in BSP and as you mentioned in
another mail, your panel is not tested in BSP - this is the only
difference. I did much reverse-engineering on PLL_MIPI clocking in BSP
so I'm afraid what can I do next on this, If you want to look further
on BSP I would suggest to verify on pll_rate side. If you feel
anything I'm missing please let me know.

Jagan.
Maxime Ripard July 3, 2019, 11:49 a.m. UTC | #17
On Tue, Jun 25, 2019 at 09:00:36PM +0530, Jagan Teki wrote:
> On Tue, Jun 25, 2019 at 8:19 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> >
> > On Thu, Jun 20, 2019 at 11:57:44PM +0530, Jagan Teki wrote:
> > > On Fri, Jun 14, 2019 at 7:54 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > > >
> > > > On Wed, Jun 05, 2019 at 01:03:16PM +0530, Jagan Teki wrote:
> > > > > On Wed, Jun 5, 2019 at 12:19 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > > > > >
> > > > > > Hi,
> > > > > >
> > > > > > I've reordered the mail a bit to work on chunks
> > > > > >
> > > > > > On Fri, May 24, 2019 at 03:37:42PM +0530, Jagan Teki wrote:
> > > > > > > > I wish it was in your commit log in the first place, instead of having
> > > > > > > > to exchange multiple mails over this.
> > > > > > > >
> > > > > > > > However, I don't think that's quite true, and it might be a bug in
> > > > > > > > Allwinner's implementation (or rather something quite confusing).
> > > > > > > >
> > > > > > > > You're right that the lcd_rate and pll_rate seem to be generated from
> > > > > > > > the pixel clock, and it indeed looks like the ratio between the pixel
> > > > > > > > clock and the TCON dotclock is defined through the number of bits per
> > > > > > > > lanes.
> > > > > > > >
> > > > > > > > However, in this case, dsi_rate is actually the same than lcd_rate,
> > > > > > > > since pll_rate is going to be divided by dsi_div:
> > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L791
> > > > > > > >
> > > > > > > > Since lcd_div is 1, it also means that in this case, dsi_rate ==
> > > > > > > > dclk_rate.
> > > > > > > >
> > > > > > > > The DSI module clock however, is always set to 148.5 MHz. Indeed, if
> > > > > > > > we look at:
> > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L804
> > > > > > > >
> > > > > > > > We can see that the rate in clk_info is used if it's different than
> > > > > > > > 0. This is filled by disp_al_lcd_get_clk_info, which, in the case of a
> > > > > > > > DSI panel, will hardcode it to 148.5 MHz:
> > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L164
> > > > > > >
> > > > > > > Let me explain, something more.
> > > > > > >
> > > > > > > According to bsp there are clk_info.tcon_div which I will explain below.
> > > > > > > clk_info.dsi_div which is dynamic and it depends on bpp/lanes, so it
> > > > > > > is 6 for 24bpp and 4 lanes devices.
> > > > > > >
> > > > > > > PLL rate here depends on dsi_div (not tcon_div)
> > > > > > >
> > > > > > > Code here
> > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L784
> > > > > > >
> > > > > > > is computing the actual set rate, which depends on dsi_rate.
> > > > > > >
> > > > > > > lcd_rate = dclk_rate * clk_info.dsi_div;
> > > > > > > dsi_rate = pll_rate / clk_info.dsi_div;
> > > > > > >
> > > > > > > Say if the dclk_rate 148MHz then the dsi_rate is 888MHz which set rate
> > > > > > > for above link you mentioned.
> > > > > > >
> > > > > > > Here are the evidence with some prints.
> > > > > > >
> > > > > > > https://gist.github.com/openedev/9bae2d87d2fcc06b999fe48c998b7043
> > > > > > > https://gist.github.com/openedev/700de2e3701b2bf3ad1aa0f0fa862c9a
> > > > > >
> > > > > > Ok, so we agree up to this point, and the prints confirm that the
> > > > > > analysis above is the right one.
> > > > > >
> > > > > > > > So, the DSI clock is set to this here:
> > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L805
> > > > > >
> > > > > > Your patch doesn't address that, so let's leave that one alone.
> > > > >
> > > > > Basically this is final pll set rate when sun4i_dotclock.c called the
> > > > > desired rate with ccu_nkm.c so it ended the final rate with parent as
> > > > > Line 8 of
> > > > > https://gist.github.com/openedev/700de2e3701b2bf3ad1aa0f0fa862c9a
> > > >
> > > > If that's important to the driver, it should be set explicitly then,
> > > > and not work by accident.
> > > >
> > > > > > > > The TCON *module* clock (the one in the clock controller) has been set
> > > > > > > > to lcd_rate (so the pixel clock times the number of bits per lane) here:
> > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L800
> > > > > > > >
> > > > > > > > And the PLL has been set to the same rate here:
> > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L794
> > > > > > > >
> > > > > > > > Let's take a step back now: that function we were looking at,
> > > > > > > > lcd_clk_config, is called by lcd_clk_enable, which is in turn called
> > > > > > > > by disp_lcd_enable here:
> > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L1328
> > > > > > > >
> > > > > > > > The next function being called is disp_al_lcd_cfg, and that function
> > > > > > > > will hardcode the TCON dotclock divider to 4, here:
> > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L240
> > > > > > >
> > > > > > > tcon_div from BSP point-of-view of there are two variants
> > > > > > > 00) clk_info.tcon_div which is 4 and same is set the divider position
> > > > > > > in SUN4I_TCON0_DCLK_REG (like above link refer)
> > > > > > > 01) tcon_div which is 4 and used for edge timings computation
> > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c#L12
> > > > > > >
> > > > > > > The real reason for 01) is again 4 is they set the divider to 4 in 00)
> > > > > > > which is technically wrong because the dividers which used during
> > > > > > > dotclock in above (dsi_div) should be used here as well. Since there
> > > > > > > is no dynamic way of doing this BSP hard-coding these values.
> > > > > > >
> > > > > > > Patches 5,6,7 on this series doing this
> > > > > > > https://patchwork.freedesktop.org/series/60847/
> > > > > > >
> > > > > > > Hope this explanation helps?
> > > > > >
> > > > > > It doesn't.
> > > > > >
> > > > > > The clock tree is this one:
> > > > > >
> > > > > > PLL(s) -> TCON module clock -> TCON dotclock.
> > > > > >
> > > > > > The links I mentioned above show that the clock set to lcd_rate is the
> > > > > > TCON module clocks (and it should be the one taking the bpp and lanes
> > > > > > into account), while the TCON dotclock uses a fixed divider of 4.
> > > > >
> > > > > Sorry, I can argue much other-than giving some code snips, according to [1]
> > > > >
> > > > > 00) Line 785, 786 with dclk_rate 148000000
> > > > >
> > > > > lcd_rate = dclk_rate * clk_info.dsi_div;
> > > > > pll_rate = lcd_rate * clk_info.lcd_div;
> > > > >
> > > > > Since dsi_div is 6 (bpp/lanes), lcd_div 1
> > > > >
> > > > > lcd_rate = 888000000, pll_rate = 888000000
> > > > >
> > > > > 01)  Line 801, 804 are final rates computed as per clock driver (say
> > > > > ccu_nkm in mainline)
> > > > >
> > > > > lcd_rate_set=891000000
> > > > >
> > > > > As per your comments if it would be 4 then the desired numbers are
> > > > > would be 592000000 not 888000000.
> > > > >
> > > > > This is what I'm trying to say in all mails, and same as verified with
> > > > > 2-lanes devices as well where the dsi_div is 12 so the final rate is
> > > > > 290MHz * 12
> > > >
> > > > In the code you sent, you're forcing a divider on the internal TCON
> > > > clock, while that one is fixed in the BSP.
> > > >
> > > > There's indeed the bpp / lanes divider, but it's used in the *parent*
> > > > clock of the one you're changing.
> > > >
> > > > And the dsi0_clk clock you pointed out in the code snippet is yet
> > > > another clock, the MIPI DSI module clock.
> > >
> > > Correct, look like I refereed wrong reference in the above mail. sorry
> > > for the noise.
> > >
> > > Actually I'm trying to explain about pll_rate here which indeed
> > > depends on dsi.div
> > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L786
> > >
> > > lcd_rate = dclk_rate * clk_info.dsi_div;
> > > pll_rate = lcd_rate * clk_info.lcd_div;
> > >
> > > Say
> > >
> > > 1) For 148MHz dclk_rate with dsi_div is 6 (24/4) lcd_div is 1 which
> > > resulting pll_rate is 888MHz.
> > >
> > > 2) For 30MHz dclk_rate with 4 lane and 24 RGB the resulting pll_rate is 180MHz
> > >
> > > 3) For 27.5MHz dclk_rate with 2 lane and 24 RGB the resulting pll_rate is 330MHz
> > >
> > > Here is the few more logs in code, for case 2)
> > >
> > > [    1.920441] sun4i_dclk_round_rate: min_div = 6 max_div = 6, rate = 30000000
> > > [    1.920505] ideal = 180000000, rounded = 178200000
> > > [    1.920509] sun4i_dclk_round_rate: div = 6 rate = 29700000
> > > [    1.920514] sun4i_dclk_round_rate: min_div = 6 max_div = 6, rate = 30000000
> > > [    1.920532] ideal = 180000000, rounded = 178200000
> > > [    1.920535] sun4i_dclk_round_rate: div = 6 rate = 29700000
> > > [    1.920572] sun4i_dclk_recalc_rate: val = 1, rate = 178200000
> > > [    1.920576] sun4i_dclk_recalc_rate: val = 1, rate = 178200000
> > > [    1.920597] rate = 178200000
> > > [    1.920599] parent_rate = 297000000
> > > [    1.920602] reg = 0x90c00000
> > > [    1.920605] _nkm.n = 3, nkm->n.offset = 0x1, nkm->n.shift = 8
> > > [    1.920609] _nkm.k = 2, nkm->k.offset = 0x1, nkm->k.shift = 4
> > > [    1.920612] _nkm.m = 10, nkm->m.offset = 0x1, nkm->m.shift = 0
> > > [    1.920958] sun4i_dclk_set_rate div 6
> > > [    1.920966] sun4i_dclk_recalc_rate: val = 6, rate = 29700000
> > >
> > > and clk_summary:
> > >
> > >     pll-video0                        1        1        1   297000000
> > >         0     0  50000
> > >        hdmi                           0        0        0   297000000
> > >         0     0  50000
> > >        tcon1                          0        0        0   297000000
> > >         0     0  50000
> > >        pll-mipi                       1        1        1   178200000
> > >         0     0  50000
> > >           tcon0                       2        2        1   178200000
> > >         0     0  50000
> > >              tcon-pixel-clock         1        1        1    29700000
> > >         0     0  50000
> > >        pll-video0-2x                  0        0        0   594000000
> > >         0     0  50000
> >
> > This discussion is going nowhere. I'm telling you that your patch
> > doesn't apply the divider you want on the proper clock, and you're
> > replying that indeed, you're applying it on the wrong clock.
> >
> > It might work by accident in your case, but the board I have here
> > clearly indicates otherwise, so there's two possible way out here:
> >
> >   - Either you apply that divider to the TCON *module* clock, and not
> >     the dclk
> >
> >   - Or you point to somewhere in the allwinner code where the bpp /
> >     lanes divider is used for the dclk divider.
>
> I don't know how to proceed further on this, as you say it might work
> in accident but I have tested this in A33, A64 and R40 with 4
> different DSI panels and one DSI-RGB bridge. All of them do use
> PLL_MIPI (pll_rate) and it indeed depends on bpp/lanes
>
> 4-lane, 24-bit: Novatek NT35596 panel
> 4-lane, 24-bit: Feiyang, FY07024di26a30d panel
> 4-lane, 24-bit: Bananapi-s070wv20 panel
> 2-lane, 24-bit: Techstar,ts8550b panel
>
> and
>
> 4-lane, 24-bit, ICN6211 DSI-to-RGB bridge panel
>
> All above listed panels and bridges are working as per BSP and do
> follow bpp/lanes and for DIVIDER 4 no panel is working.

Look. I'm not saying that there's no issue, I'm saying that your
patch, applied to the clock you're applying it to, doesn't make sense
and isn't what the BSP does.

You can keep on arguing that your patch is perfect as is, but the fact
that there's regressions proves otherwise.

> The panels/bridges I have has tested in BSP and as you mentioned in
> another mail, your panel is not tested in BSP - this is the only
> difference. I did much reverse-engineering on PLL_MIPI clocking in BSP
> so I'm afraid what can I do next on this, If you want to look further
> on BSP I would suggest to verify on pll_rate side. If you feel
> anything I'm missing please let me know.

I already told you how we can make some progress in the mail you
quoted, but you chose to ignore that.

Until there's been some progress on either points mentionned above,
I'm just going to stop answering on this topic.

Maxime

--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
Michael Nazzareno Trimarchi July 5, 2019, 5:52 p.m. UTC | #18
Hi Maxime

On Wed, Jul 3, 2019 at 1:49 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
>
> On Tue, Jun 25, 2019 at 09:00:36PM +0530, Jagan Teki wrote:
> > On Tue, Jun 25, 2019 at 8:19 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > >
> > > On Thu, Jun 20, 2019 at 11:57:44PM +0530, Jagan Teki wrote:
> > > > On Fri, Jun 14, 2019 at 7:54 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > > > >
> > > > > On Wed, Jun 05, 2019 at 01:03:16PM +0530, Jagan Teki wrote:
> > > > > > On Wed, Jun 5, 2019 at 12:19 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > > > > > >
> > > > > > > Hi,
> > > > > > >
> > > > > > > I've reordered the mail a bit to work on chunks
> > > > > > >
> > > > > > > On Fri, May 24, 2019 at 03:37:42PM +0530, Jagan Teki wrote:
> > > > > > > > > I wish it was in your commit log in the first place, instead of having
> > > > > > > > > to exchange multiple mails over this.
> > > > > > > > >
> > > > > > > > > However, I don't think that's quite true, and it might be a bug in
> > > > > > > > > Allwinner's implementation (or rather something quite confusing).
> > > > > > > > >
> > > > > > > > > You're right that the lcd_rate and pll_rate seem to be generated from
> > > > > > > > > the pixel clock, and it indeed looks like the ratio between the pixel
> > > > > > > > > clock and the TCON dotclock is defined through the number of bits per
> > > > > > > > > lanes.
> > > > > > > > >
> > > > > > > > > However, in this case, dsi_rate is actually the same than lcd_rate,
> > > > > > > > > since pll_rate is going to be divided by dsi_div:
> > > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L791
> > > > > > > > >
> > > > > > > > > Since lcd_div is 1, it also means that in this case, dsi_rate ==
> > > > > > > > > dclk_rate.
> > > > > > > > >
> > > > > > > > > The DSI module clock however, is always set to 148.5 MHz. Indeed, if
> > > > > > > > > we look at:
> > > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L804
> > > > > > > > >
> > > > > > > > > We can see that the rate in clk_info is used if it's different than
> > > > > > > > > 0. This is filled by disp_al_lcd_get_clk_info, which, in the case of a
> > > > > > > > > DSI panel, will hardcode it to 148.5 MHz:
> > > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L164
> > > > > > > >
> > > > > > > > Let me explain, something more.
> > > > > > > >
> > > > > > > > According to bsp there are clk_info.tcon_div which I will explain below.
> > > > > > > > clk_info.dsi_div which is dynamic and it depends on bpp/lanes, so it
> > > > > > > > is 6 for 24bpp and 4 lanes devices.
> > > > > > > >
> > > > > > > > PLL rate here depends on dsi_div (not tcon_div)
> > > > > > > >
> > > > > > > > Code here
> > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L784
> > > > > > > >
> > > > > > > > is computing the actual set rate, which depends on dsi_rate.
> > > > > > > >
> > > > > > > > lcd_rate = dclk_rate * clk_info.dsi_div;
> > > > > > > > dsi_rate = pll_rate / clk_info.dsi_div;
> > > > > > > >
> > > > > > > > Say if the dclk_rate 148MHz then the dsi_rate is 888MHz which set rate
> > > > > > > > for above link you mentioned.
> > > > > > > >
> > > > > > > > Here are the evidence with some prints.
> > > > > > > >
> > > > > > > > https://gist.github.com/openedev/9bae2d87d2fcc06b999fe48c998b7043
> > > > > > > > https://gist.github.com/openedev/700de2e3701b2bf3ad1aa0f0fa862c9a
> > > > > > >
> > > > > > > Ok, so we agree up to this point, and the prints confirm that the
> > > > > > > analysis above is the right one.
> > > > > > >
> > > > > > > > > So, the DSI clock is set to this here:
> > > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L805
> > > > > > >
> > > > > > > Your patch doesn't address that, so let's leave that one alone.
> > > > > >
> > > > > > Basically this is final pll set rate when sun4i_dotclock.c called the
> > > > > > desired rate with ccu_nkm.c so it ended the final rate with parent as
> > > > > > Line 8 of
> > > > > > https://gist.github.com/openedev/700de2e3701b2bf3ad1aa0f0fa862c9a
> > > > >
> > > > > If that's important to the driver, it should be set explicitly then,
> > > > > and not work by accident.
> > > > >
> > > > > > > > > The TCON *module* clock (the one in the clock controller) has been set
> > > > > > > > > to lcd_rate (so the pixel clock times the number of bits per lane) here:
> > > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L800
> > > > > > > > >
> > > > > > > > > And the PLL has been set to the same rate here:
> > > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L794
> > > > > > > > >
> > > > > > > > > Let's take a step back now: that function we were looking at,
> > > > > > > > > lcd_clk_config, is called by lcd_clk_enable, which is in turn called
> > > > > > > > > by disp_lcd_enable here:
> > > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L1328
> > > > > > > > >
> > > > > > > > > The next function being called is disp_al_lcd_cfg, and that function
> > > > > > > > > will hardcode the TCON dotclock divider to 4, here:
> > > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L240
> > > > > > > >
> > > > > > > > tcon_div from BSP point-of-view of there are two variants
> > > > > > > > 00) clk_info.tcon_div which is 4 and same is set the divider position
> > > > > > > > in SUN4I_TCON0_DCLK_REG (like above link refer)
> > > > > > > > 01) tcon_div which is 4 and used for edge timings computation
> > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c#L12
> > > > > > > >
> > > > > > > > The real reason for 01) is again 4 is they set the divider to 4 in 00)
> > > > > > > > which is technically wrong because the dividers which used during
> > > > > > > > dotclock in above (dsi_div) should be used here as well. Since there
> > > > > > > > is no dynamic way of doing this BSP hard-coding these values.
> > > > > > > >
> > > > > > > > Patches 5,6,7 on this series doing this
> > > > > > > > https://patchwork.freedesktop.org/series/60847/
> > > > > > > >
> > > > > > > > Hope this explanation helps?
> > > > > > >
> > > > > > > It doesn't.
> > > > > > >
> > > > > > > The clock tree is this one:
> > > > > > >
> > > > > > > PLL(s) -> TCON module clock -> TCON dotclock.
> > > > > > >
> > > > > > > The links I mentioned above show that the clock set to lcd_rate is the
> > > > > > > TCON module clocks (and it should be the one taking the bpp and lanes
> > > > > > > into account), while the TCON dotclock uses a fixed divider of 4.
> > > > > >
> > > > > > Sorry, I can argue much other-than giving some code snips, according to [1]
> > > > > >
> > > > > > 00) Line 785, 786 with dclk_rate 148000000
> > > > > >
> > > > > > lcd_rate = dclk_rate * clk_info.dsi_div;
> > > > > > pll_rate = lcd_rate * clk_info.lcd_div;
> > > > > >
> > > > > > Since dsi_div is 6 (bpp/lanes), lcd_div 1
> > > > > >
> > > > > > lcd_rate = 888000000, pll_rate = 888000000
> > > > > >
> > > > > > 01)  Line 801, 804 are final rates computed as per clock driver (say
> > > > > > ccu_nkm in mainline)
> > > > > >
> > > > > > lcd_rate_set=891000000
> > > > > >
> > > > > > As per your comments if it would be 4 then the desired numbers are
> > > > > > would be 592000000 not 888000000.
> > > > > >
> > > > > > This is what I'm trying to say in all mails, and same as verified with
> > > > > > 2-lanes devices as well where the dsi_div is 12 so the final rate is
> > > > > > 290MHz * 12
> > > > >
> > > > > In the code you sent, you're forcing a divider on the internal TCON
> > > > > clock, while that one is fixed in the BSP.
> > > > >
> > > > > There's indeed the bpp / lanes divider, but it's used in the *parent*
> > > > > clock of the one you're changing.
> > > > >
> > > > > And the dsi0_clk clock you pointed out in the code snippet is yet
> > > > > another clock, the MIPI DSI module clock.
> > > >
> > > > Correct, look like I refereed wrong reference in the above mail. sorry
> > > > for the noise.
> > > >
> > > > Actually I'm trying to explain about pll_rate here which indeed
> > > > depends on dsi.div
> > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L786
> > > >
> > > > lcd_rate = dclk_rate * clk_info.dsi_div;
> > > > pll_rate = lcd_rate * clk_info.lcd_div;
> > > >
> > > > Say
> > > >
> > > > 1) For 148MHz dclk_rate with dsi_div is 6 (24/4) lcd_div is 1 which
> > > > resulting pll_rate is 888MHz.
> > > >
> > > > 2) For 30MHz dclk_rate with 4 lane and 24 RGB the resulting pll_rate is 180MHz
> > > >
> > > > 3) For 27.5MHz dclk_rate with 2 lane and 24 RGB the resulting pll_rate is 330MHz
> > > >
> > > > Here is the few more logs in code, for case 2)
> > > >
> > > > [    1.920441] sun4i_dclk_round_rate: min_div = 6 max_div = 6, rate = 30000000
> > > > [    1.920505] ideal = 180000000, rounded = 178200000
> > > > [    1.920509] sun4i_dclk_round_rate: div = 6 rate = 29700000
> > > > [    1.920514] sun4i_dclk_round_rate: min_div = 6 max_div = 6, rate = 30000000
> > > > [    1.920532] ideal = 1800ls and one DSI-RGB bridge. All of them do use
> > PLL_MIPI (pll_rate) and it indeed depends on bpp/lanes
> >00000, rounded = 178200000
> > > > [    1.920535] sun4i_dclk_round_rate: div = 6 rate = 29700000
> > > > [    1.920572] sun4i_dclk_recalc_rate: val = 1, rate = 178200000
> > > > [    1.920576] sun4i_dclk_recalc_rate: val = 1, rate = 178200000
> > > > [    1.920597] rate = 178200000
> > > > [    1.920599] parent_rate = 297000000
> > > > [    1.920602] reg = 0x90c00000
> > > > [    1.920605] _nkm.n = 3, nkm->n.offset = 0x1, nkm->n.shift = 8
> > > > [    1.920609] _nkm.k = 2, nkm->k.offset = 0x1, nkm->k.shift = 4
> > > > [    1.920612] _nkm.m = 10, nkm->m.offset = 0x1, nkm->m.shift = 0
> > > > [    1.920958] sun4i_dclk_set_rate div 6
> > > > [    1.920966] sun4i_dclk_recalc_rate: val = 6, rate = 29700000
> > > >
> > > > and clk_summary:
> > > >
> > > >     pll-video0                        1        1        1   297000000
> > > >         0     0  50000
> > > >        hdmi                           0        0        0   297000000
> > > >         0     0  50000
> > > >        tcon1                          0        0        0   297000000
> > > >         0     0  50000
> > > >        pll-mipi                       1        1        1   178200000
> > > >         0     0  50000
> > > >           tcon0                       2        2        1   178200000
> > > >         0     0  50000
> > > >              tcon-pixel-clock         1        1        1    29700000
> > > >         0     0  50000
> > > >        pll-video0-2x                  0        0        0   594000000
> > > >         0     0  50000
> > >
> > > This discussion is going nowhere. I'm telling you that your patch
> > > doesn't apply the divider you want on the proper clock, and you're
> > > replying that indeed, you're applying it on the wrong clock.
> > >
> > > It might work by accident in your case, but the board I have here
> > > clearly indicates otherwise, so there's two possible way out here:
> > >
> > >   - Either you apply that divider to the TCON *module* clock, and not
> > >     the dclk
> > >
> > >   - Or you point to somewhere in the allwinner code where the bpp /
> > >     lanes divider is used for the dclk divider.
> >
> > I don't know how to proceed further on this, as you say it might work
> > in accident but I have tested this in A33, A64 and R40 with 4
> > different DSI panels and one DSI-RGB bridge. All of them do use
> > PLL_MIPI (pll_rate) and it indeed depends on bpp/lanes
> >
> > 4-lane, 24-bit: Novatek NT35596 panel
> > 4-lane, 24-bit: Feiyang, FY07024di26a30d panel
> > 4-lane, 24-bit: Bananapi-s070wv20 panel
> > 2-lane, 24-bit: Techstar,ts8550b panel
> >
> > and
> >
> > 4-lane, 24-bit, ICN6211 DSI-to-RGB bridge panel
> >
> > All above listed panels and bridges are working as per BSP and do
> > follow bpp/lanes and for DIVIDER 4 no panel is working.
>
> Look. I'm not saying that there's no issue, I'm saying that your
> patch, applied to the clock you're applying it to, doesn't make sense
> and isn't what the BSP does.

tcon-pixel clock is the rate that you want to achive on display side and
if you have 4 lanes 32bit or lanes and different bit number that you need
to have a clock that is able to put outside bits and speed equal to
pixel-clock * bits / lanes. so If you want a pixel-clock of 40 mhz
and you have 32bits and 4 lanes you need to have a clock of
40 * 32 / 4 in no-burst mode. I think that this is done but most of the display.
Now in burst mode I don't know how should work the calculation of the
clock for the
require bandwidth and even I understand your comment I would like to have your
clock tree after you boot on the display side and if it is possible I
want to assemble a kit
like you have.

>
> You can keep on arguing that your patch is perfect as is, but the fact
> that there's regressions proves otherwise.
>

Well when you push your code you said that you have tested on more
then one display.
Can I know where are the others?

> > The panels/bridges I have has tested in BSP and as you mentioned in

> > another mail, your panel is not tested in BSP - this is the only
> > difference. I did much reverse-engineering on PLL_MIPI clocking in BSP
> > so I'm afraid what can I do next on this, If you want to look further
> > on BSP I would suggest to verify on pll_rate side. If you feel
> > anything I'm missing please let me know.
>
> I already told you how we can make some progress in the mail you
> quoted, but you chose to ignore that.
>

Yes, the idea is to make progress. Thank you about your helping

Michael

> Until there's been some progress on either points mentionned above,
> I'm just going to stop answering on this topic.
>
> Maxime
>
> --
> Maxime Ripard, Bootlin
> Embedded Linux and Kernel engineering
> https://bootlin.com
Maxime Ripard July 11, 2019, 10:01 a.m. UTC | #19
On Fri, Jul 05, 2019 at 07:52:27PM +0200, Michael Nazzareno Trimarchi wrote:
> On Wed, Jul 3, 2019 at 1:49 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> >
> > On Tue, Jun 25, 2019 at 09:00:36PM +0530, Jagan Teki wrote:
> > > On Tue, Jun 25, 2019 at 8:19 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > > >
> > > > On Thu, Jun 20, 2019 at 11:57:44PM +0530, Jagan Teki wrote:
> > > > > On Fri, Jun 14, 2019 at 7:54 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > > > > >
> > > > > > On Wed, Jun 05, 2019 at 01:03:16PM +0530, Jagan Teki wrote:
> > > > > > > On Wed, Jun 5, 2019 at 12:19 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > > > > > > >
> > > > > > > > Hi,
> > > > > > > >
> > > > > > > > I've reordered the mail a bit to work on chunks
> > > > > > > >
> > > > > > > > On Fri, May 24, 2019 at 03:37:42PM +0530, Jagan Teki wrote:
> > > > > > > > > > I wish it was in your commit log in the first place, instead of having
> > > > > > > > > > to exchange multiple mails over this.
> > > > > > > > > >
> > > > > > > > > > However, I don't think that's quite true, and it might be a bug in
> > > > > > > > > > Allwinner's implementation (or rather something quite confusing).
> > > > > > > > > >
> > > > > > > > > > You're right that the lcd_rate and pll_rate seem to be generated from
> > > > > > > > > > the pixel clock, and it indeed looks like the ratio between the pixel
> > > > > > > > > > clock and the TCON dotclock is defined through the number of bits per
> > > > > > > > > > lanes.
> > > > > > > > > >
> > > > > > > > > > However, in this case, dsi_rate is actually the same than lcd_rate,
> > > > > > > > > > since pll_rate is going to be divided by dsi_div:
> > > > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L791
> > > > > > > > > >
> > > > > > > > > > Since lcd_div is 1, it also means that in this case, dsi_rate ==
> > > > > > > > > > dclk_rate.
> > > > > > > > > >
> > > > > > > > > > The DSI module clock however, is always set to 148.5 MHz. Indeed, if
> > > > > > > > > > we look at:
> > > > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L804
> > > > > > > > > >
> > > > > > > > > > We can see that the rate in clk_info is used if it's different than
> > > > > > > > > > 0. This is filled by disp_al_lcd_get_clk_info, which, in the case of a
> > > > > > > > > > DSI panel, will hardcode it to 148.5 MHz:
> > > > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L164
> > > > > > > > >
> > > > > > > > > Let me explain, something more.
> > > > > > > > >
> > > > > > > > > According to bsp there are clk_info.tcon_div which I will explain below.
> > > > > > > > > clk_info.dsi_div which is dynamic and it depends on bpp/lanes, so it
> > > > > > > > > is 6 for 24bpp and 4 lanes devices.
> > > > > > > > >
> > > > > > > > > PLL rate here depends on dsi_div (not tcon_div)
> > > > > > > > >
> > > > > > > > > Code here
> > > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L784
> > > > > > > > >
> > > > > > > > > is computing the actual set rate, which depends on dsi_rate.
> > > > > > > > >
> > > > > > > > > lcd_rate = dclk_rate * clk_info.dsi_div;
> > > > > > > > > dsi_rate = pll_rate / clk_info.dsi_div;
> > > > > > > > >
> > > > > > > > > Say if the dclk_rate 148MHz then the dsi_rate is 888MHz which set rate
> > > > > > > > > for above link you mentioned.
> > > > > > > > >
> > > > > > > > > Here are the evidence with some prints.
> > > > > > > > >
> > > > > > > > > https://gist.github.com/openedev/9bae2d87d2fcc06b999fe48c998b7043
> > > > > > > > > https://gist.github.com/openedev/700de2e3701b2bf3ad1aa0f0fa862c9a
> > > > > > > >
> > > > > > > > Ok, so we agree up to this point, and the prints confirm that the
> > > > > > > > analysis above is the right one.
> > > > > > > >
> > > > > > > > > > So, the DSI clock is set to this here:
> > > > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L805
> > > > > > > >
> > > > > > > > Your patch doesn't address that, so let's leave that one alone.
> > > > > > >
> > > > > > > Basically this is final pll set rate when sun4i_dotclock.c called the
> > > > > > > desired rate with ccu_nkm.c so it ended the final rate with parent as
> > > > > > > Line 8 of
> > > > > > > https://gist.github.com/openedev/700de2e3701b2bf3ad1aa0f0fa862c9a
> > > > > >
> > > > > > If that's important to the driver, it should be set explicitly then,
> > > > > > and not work by accident.
> > > > > >
> > > > > > > > > > The TCON *module* clock (the one in the clock controller) has been set
> > > > > > > > > > to lcd_rate (so the pixel clock times the number of bits per lane) here:
> > > > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L800
> > > > > > > > > >
> > > > > > > > > > And the PLL has been set to the same rate here:
> > > > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L794
> > > > > > > > > >
> > > > > > > > > > Let's take a step back now: that function we were looking at,
> > > > > > > > > > lcd_clk_config, is called by lcd_clk_enable, which is in turn called
> > > > > > > > > > by disp_lcd_enable here:
> > > > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L1328
> > > > > > > > > >
> > > > > > > > > > The next function being called is disp_al_lcd_cfg, and that function
> > > > > > > > > > will hardcode the TCON dotclock divider to 4, here:
> > > > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L240
> > > > > > > > >
> > > > > > > > > tcon_div from BSP point-of-view of there are two variants
> > > > > > > > > 00) clk_info.tcon_div which is 4 and same is set the divider position
> > > > > > > > > in SUN4I_TCON0_DCLK_REG (like above link refer)
> > > > > > > > > 01) tcon_div which is 4 and used for edge timings computation
> > > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c#L12
> > > > > > > > >
> > > > > > > > > The real reason for 01) is again 4 is they set the divider to 4 in 00)
> > > > > > > > > which is technically wrong because the dividers which used during
> > > > > > > > > dotclock in above (dsi_div) should be used here as well. Since there
> > > > > > > > > is no dynamic way of doing this BSP hard-coding these values.
> > > > > > > > >
> > > > > > > > > Patches 5,6,7 on this series doing this
> > > > > > > > > https://patchwork.freedesktop.org/series/60847/
> > > > > > > > >
> > > > > > > > > Hope this explanation helps?
> > > > > > > >
> > > > > > > > It doesn't.
> > > > > > > >
> > > > > > > > The clock tree is this one:
> > > > > > > >
> > > > > > > > PLL(s) -> TCON module clock -> TCON dotclock.
> > > > > > > >
> > > > > > > > The links I mentioned above show that the clock set to lcd_rate is the
> > > > > > > > TCON module clocks (and it should be the one taking the bpp and lanes
> > > > > > > > into account), while the TCON dotclock uses a fixed divider of 4.
> > > > > > >
> > > > > > > Sorry, I can argue much other-than giving some code snips, according to [1]
> > > > > > >
> > > > > > > 00) Line 785, 786 with dclk_rate 148000000
> > > > > > >
> > > > > > > lcd_rate = dclk_rate * clk_info.dsi_div;
> > > > > > > pll_rate = lcd_rate * clk_info.lcd_div;
> > > > > > >
> > > > > > > Since dsi_div is 6 (bpp/lanes), lcd_div 1
> > > > > > >
> > > > > > > lcd_rate = 888000000, pll_rate = 888000000
> > > > > > >
> > > > > > > 01)  Line 801, 804 are final rates computed as per clock driver (say
> > > > > > > ccu_nkm in mainline)
> > > > > > >
> > > > > > > lcd_rate_set=891000000
> > > > > > >
> > > > > > > As per your comments if it would be 4 then the desired numbers are
> > > > > > > would be 592000000 not 888000000.
> > > > > > >
> > > > > > > This is what I'm trying to say in all mails, and same as verified with
> > > > > > > 2-lanes devices as well where the dsi_div is 12 so the final rate is
> > > > > > > 290MHz * 12
> > > > > >
> > > > > > In the code you sent, you're forcing a divider on the internal TCON
> > > > > > clock, while that one is fixed in the BSP.
> > > > > >
> > > > > > There's indeed the bpp / lanes divider, but it's used in the *parent*
> > > > > > clock of the one you're changing.
> > > > > >
> > > > > > And the dsi0_clk clock you pointed out in the code snippet is yet
> > > > > > another clock, the MIPI DSI module clock.
> > > > >
> > > > > Correct, look like I refereed wrong reference in the above mail. sorry
> > > > > for the noise.
> > > > >
> > > > > Actually I'm trying to explain about pll_rate here which indeed
> > > > > depends on dsi.div
> > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L786
> > > > >
> > > > > lcd_rate = dclk_rate * clk_info.dsi_div;
> > > > > pll_rate = lcd_rate * clk_info.lcd_div;
> > > > >
> > > > > Say
> > > > >
> > > > > 1) For 148MHz dclk_rate with dsi_div is 6 (24/4) lcd_div is 1 which
> > > > > resulting pll_rate is 888MHz.
> > > > >
> > > > > 2) For 30MHz dclk_rate with 4 lane and 24 RGB the resulting pll_rate is 180MHz
> > > > >
> > > > > 3) For 27.5MHz dclk_rate with 2 lane and 24 RGB the resulting pll_rate is 330MHz
> > > > >
> > > > > Here is the few more logs in code, for case 2)
> > > > >
> > > > > [    1.920441] sun4i_dclk_round_rate: min_div = 6 max_div = 6, rate = 30000000
> > > > > [    1.920505] ideal = 180000000, rounded = 178200000
> > > > > [    1.920509] sun4i_dclk_round_rate: div = 6 rate = 29700000
> > > > > [    1.920514] sun4i_dclk_round_rate: min_div = 6 max_div = 6, rate = 30000000
> > > > > [    1.920532] ideal = 1800ls and one DSI-RGB bridge. All of them do use
> > > PLL_MIPI (pll_rate) and it indeed depends on bpp/lanes
> > >00000, rounded = 178200000
> > > > > [    1.920535] sun4i_dclk_round_rate: div = 6 rate = 29700000
> > > > > [    1.920572] sun4i_dclk_recalc_rate: val = 1, rate = 178200000
> > > > > [    1.920576] sun4i_dclk_recalc_rate: val = 1, rate = 178200000
> > > > > [    1.920597] rate = 178200000
> > > > > [    1.920599] parent_rate = 297000000
> > > > > [    1.920602] reg = 0x90c00000
> > > > > [    1.920605] _nkm.n = 3, nkm->n.offset = 0x1, nkm->n.shift = 8
> > > > > [    1.920609] _nkm.k = 2, nkm->k.offset = 0x1, nkm->k.shift = 4
> > > > > [    1.920612] _nkm.m = 10, nkm->m.offset = 0x1, nkm->m.shift = 0
> > > > > [    1.920958] sun4i_dclk_set_rate div 6
> > > > > [    1.920966] sun4i_dclk_recalc_rate: val = 6, rate = 29700000
> > > > >
> > > > > and clk_summary:
> > > > >
> > > > >     pll-video0                        1        1        1   297000000
> > > > >         0     0  50000
> > > > >        hdmi                           0        0        0   297000000
> > > > >         0     0  50000
> > > > >        tcon1                          0        0        0   297000000
> > > > >         0     0  50000
> > > > >        pll-mipi                       1        1        1   178200000
> > > > >         0     0  50000
> > > > >           tcon0                       2        2        1   178200000
> > > > >         0     0  50000
> > > > >              tcon-pixel-clock         1        1        1    29700000
> > > > >         0     0  50000
> > > > >        pll-video0-2x                  0        0        0   594000000
> > > > >         0     0  50000
> > > >
> > > > This discussion is going nowhere. I'm telling you that your patch
> > > > doesn't apply the divider you want on the proper clock, and you're
> > > > replying that indeed, you're applying it on the wrong clock.
> > > >
> > > > It might work by accident in your case, but the board I have here
> > > > clearly indicates otherwise, so there's two possible way out here:
> > > >
> > > >   - Either you apply that divider to the TCON *module* clock, and not
> > > >     the dclk
> > > >
> > > >   - Or you point to somewhere in the allwinner code where the bpp /
> > > >     lanes divider is used for the dclk divider.
> > >
> > > I don't know how to proceed further on this, as you say it might work
> > > in accident but I have tested this in A33, A64 and R40 with 4
> > > different DSI panels and one DSI-RGB bridge. All of them do use
> > > PLL_MIPI (pll_rate) and it indeed depends on bpp/lanes
> > >
> > > 4-lane, 24-bit: Novatek NT35596 panel
> > > 4-lane, 24-bit: Feiyang, FY07024di26a30d panel
> > > 4-lane, 24-bit: Bananapi-s070wv20 panel
> > > 2-lane, 24-bit: Techstar,ts8550b panel
> > >
> > > and
> > >
> > > 4-lane, 24-bit, ICN6211 DSI-to-RGB bridge panel
> > >
> > > All above listed panels and bridges are working as per BSP and do
> > > follow bpp/lanes and for DIVIDER 4 no panel is working.
> >
> > Look. I'm not saying that there's no issue, I'm saying that your
> > patch, applied to the clock you're applying it to, doesn't make sense
> > and isn't what the BSP does.
>
> tcon-pixel clock is the rate that you want to achive on display side
> and if you have 4 lanes 32bit or lanes and different bit number that
> you need to have a clock that is able to put outside bits and speed
> equal to pixel-clock * bits / lanes. so If you want a pixel-clock of
> 40 mhz and you have 32bits and 4 lanes you need to have a clock of
> 40 * 32 / 4 in no-burst mode. I think that this is done but most of
> the display.

So this is what the issue is then?

This one does make sense, and you should just change the rate in the
call to clk_set_rate in sun4i_tcon0_mode_set_cpu.

I'm still wondering why that hasn't been brought up in either the
discussion or the commit log before though.

> Now in burst mode I don't know how should work the calculation of
> the clock for the require bandwidth and even I understand your
> comment I would like to have your clock tree after you boot on the
> display side and if it is possible I want to assemble a kit like you
> have.

The setup is probably going to be a bit difficult to reproduce, it's a
prototype that I have that can't really be found anywhere. Jagan asked
me on IRC for the reference, and he found the part, but it's unclear
to me if it can be easily adapted to a common board.

However, I'm not even sure we need this. I'll test the next version
and let you know if it works.

Maxime

--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
Michael Nazzareno Trimarchi July 11, 2019, 5:43 p.m. UTC | #20
Hi Maxime

On Thu, Jul 11, 2019 at 2:23 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
>
> On Fri, Jul 05, 2019 at 07:52:27PM +0200, Michael Nazzareno Trimarchi wrote:
> > On Wed, Jul 3, 2019 at 1:49 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > >
> > > On Tue, Jun 25, 2019 at 09:00:36PM +0530, Jagan Teki wrote:
> > > > On Tue, Jun 25, 2019 at 8:19 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > > > >
> > > > > On Thu, Jun 20, 2019 at 11:57:44PM +0530, Jagan Teki wrote:
> > > > > > On Fri, Jun 14, 2019 at 7:54 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > > > > > >
> > > > > > > On Wed, Jun 05, 2019 at 01:03:16PM +0530, Jagan Teki wrote:
> > > > > > > > On Wed, Jun 5, 2019 at 12:19 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > > > > > > > >
> > > > > > > > > Hi,
> > > > > > > > >
> > > > > > > > > I've reordered the mail a bit to work on chunks
> > > > > > > > >
> > > > > > > > > On Fri, May 24, 2019 at 03:37:42PM +0530, Jagan Teki wrote:
> > > > > > > > > > > I wish it was in your commit log in the first place, instead of having
> > > > > > > > > > > to exchange multiple mails over this.
> > > > > > > > > > >
> > > > > > > > > > > However, I don't think that's quite true, and it might be a bug in
> > > > > > > > > > > Allwinner's implementation (or rather something quite confusing).
> > > > > > > > > > >
> > > > > > > > > > > You're right that the lcd_rate and pll_rate seem to be generated from
> > > > > > > > > > > the pixel clock, and it indeed looks like the ratio between the pixel
> > > > > > > > > > > clock and the TCON dotclock is defined through the number of bits per
> > > > > > > > > > > lanes.
> > > > > > > > > > >
> > > > > > > > > > > However, in this case, dsi_rate is actually the same than lcd_rate,
> > > > > > > > > > > since pll_rate is going to be divided by dsi_div:
> > > > > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L791
> > > > > > > > > > >
> > > > > > > > > > > Since lcd_div is 1, it also means that in this case, dsi_rate ==
> > > > > > > > > > > dclk_rate.
> > > > > > > > > > >
> > > > > > > > > > > The DSI module clock however, is always set to 148.5 MHz. Indeed, if
> > > > > > > > > > > we look at:
> > > > > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L804
> > > > > > > > > > >
> > > > > > > > > > > We can see that the rate in clk_info is used if it's different than
> > > > > > > > > > > 0. This is filled by disp_al_lcd_get_clk_info, which, in the case of a
> > > > > > > > > > > DSI panel, will hardcode it to 148.5 MHz:
> > > > > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L164
> > > > > > > > > >
> > > > > > > > > > Let me explain, something more.
> > > > > > > > > >
> > > > > > > > > > According to bsp there are clk_info.tcon_div which I will explain below.
> > > > > > > > > > clk_info.dsi_div which is dynamic and it depends on bpp/lanes, so it
> > > > > > > > > > is 6 for 24bpp and 4 lanes devices.
> > > > > > > > > >
> > > > > > > > > > PLL rate here depends on dsi_div (not tcon_div)
> > > > > > > > > >
> > > > > > > > > > Code here
> > > > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L784
> > > > > > > > > >
> > > > > > > > > > is computing the actual set rate, which depends on dsi_rate.
> > > > > > > > > >
> > > > > > > > > > lcd_rate = dclk_rate * clk_info.dsi_div;
> > > > > > > > > > dsi_rate = pll_rate / clk_info.dsi_div;
> > > > > > > > > >
> > > > > > > > > > Say if the dclk_rate 148MHz then the dsi_rate is 888MHz which set rate
> > > > > > > > > > for above link you mentioned.
> > > > > > > > > >
> > > > > > > > > > Here are the evidence with some prints.
> > > > > > > > > >
> > > > > > > > > > https://gist.github.com/openedev/9bae2d87d2fcc06b999fe48c998b7043
> > > > > > > > > > https://gist.github.com/openedev/700de2e3701b2bf3ad1aa0f0fa862c9a
> > > > > > > > >
> > > > > > > > > Ok, so we agree up to this point, and the prints confirm that the
> > > > > > > > > analysis above is the right one.
> > > > > > > > >
> > > > > > > > > > > So, the DSI clock is set to this here:
> > > > > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L805
> > > > > > > > >
> > > > > > > > > Your patch doesn't address that, so let's leave that one alone.
> > > > > > > >
> > > > > > > > Basically this is final pll set rate when sun4i_dotclock.c called the
> > > > > > > > desired rate with ccu_nkm.c so it ended the final rate with parent as
> > > > > > > > Line 8 of
> > > > > > > > https://gist.github.com/openedev/700de2e3701b2bf3ad1aa0f0fa862c9a
> > > > > > >
> > > > > > > If that's important to the driver, it should be set explicitly then,
> > > > > > > and not work by accident.
> > > > > > >
> > > > > > > > > > > The TCON *module* clock (the one in the clock controller) has been set
> > > > > > > > > > > to lcd_rate (so the pixel clock times the number of bits per lane) here:
> > > > > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L800
> > > > > > > > > > >
> > > > > > > > > > > And the PLL has been set to the same rate here:
> > > > > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L794
> > > > > > > > > > >
> > > > > > > > > > > Let's take a step back now: that function we were looking at,
> > > > > > > > > > > lcd_clk_config, is called by lcd_clk_enable, which is in turn called
> > > > > > > > > > > by disp_lcd_enable here:
> > > > > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L1328
> > > > > > > > > > >
> > > > > > > > > > > The next function being called is disp_al_lcd_cfg, and that function
> > > > > > > > > > > will hardcode the TCON dotclock divider to 4, here:
> > > > > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L240
> > > > > > > > > >
> > > > > > > > > > tcon_div from BSP point-of-view of there are two variants
> > > > > > > > > > 00) clk_info.tcon_div which is 4 and same is set the divider position
> > > > > > > > > > in SUN4I_TCON0_DCLK_REG (like above link refer)
> > > > > > > > > > 01) tcon_div which is 4 and used for edge timings computation
> > > > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c#L12
> > > > > > > > > >
> > > > > > > > > > The real reason for 01) is again 4 is they set the divider to 4 in 00)
> > > > > > > > > > which is technically wrong because the dividers which used during
> > > > > > > > > > dotclock in above (dsi_div) should be used here as well. Since there
> > > > > > > > > > is no dynamic way of doing this BSP hard-coding these values.
> > > > > > > > > >
> > > > > > > > > > Patches 5,6,7 on this series doing this
> > > > > > > > > > https://patchwork.freedesktop.org/series/60847/
> > > > > > > > > >
> > > > > > > > > > Hope this explanation helps?
> > > > > > > > >
> > > > > > > > > It doesn't.
> > > > > > > > >
> > > > > > > > > The clock tree is this one:
> > > > > > > > >
> > > > > > > > > PLL(s) -> TCON module clock -> TCON dotclock.
> > > > > > > > >
> > > > > > > > > The links I mentioned above show that the clock set to lcd_rate is the
> > > > > > > > > TCON module clocks (and it should be the one taking the bpp and lanes
> > > > > > > > > into account), while the TCON dotclock uses a fixed divider of 4.
> > > > > > > >
> > > > > > > > Sorry, I can argue much other-than giving some code snips, according to [1]
> > > > > > > >
> > > > > > > > 00) Line 785, 786 with dclk_rate 148000000
> > > > > > > >
> > > > > > > > lcd_rate = dclk_rate * clk_info.dsi_div;
> > > > > > > > pll_rate = lcd_rate * clk_info.lcd_div;
> > > > > > > >
> > > > > > > > Since dsi_div is 6 (bpp/lanes), lcd_div 1
> > > > > > > >
> > > > > > > > lcd_rate = 888000000, pll_rate = 888000000
> > > > > > > >
> > > > > > > > 01)  Line 801, 804 are final rates computed as per clock driver (say
> > > > > > > > ccu_nkm in mainline)
> > > > > > > >
> > > > > > > > lcd_rate_set=891000000
> > > > > > > >
> > > > > > > > As per your comments if it would be 4 then the desired numbers are
> > > > > > > > would be 592000000 not 888000000.
> > > > > > > >
> > > > > > > > This is what I'm trying to say in all mails, and same as verified with
> > > > > > > > 2-lanes devices as well where the dsi_div is 12 so the final rate is
> > > > > > > > 290MHz * 12
> > > > > > >
> > > > > > > In the code you sent, you're forcing a divider on the internal TCON
> > > > > > > clock, while that one is fixed in the BSP.
> > > > > > >
> > > > > > > There's indeed the bpp / lanes divider, but it's used in the *parent*
> > > > > > > clock of the one you're changing.
> > > > > > >
> > > > > > > And the dsi0_clk clock you pointed out in the code snippet is yet
> > > > > > > another clock, the MIPI DSI module clock.
> > > > > >
> > > > > > Correct, look like I refereed wrong reference in the above mail. sorry
> > > > > > for the noise.
> > > > > >
> > > > > > Actually I'm trying to explain about pll_rate here which indeed
> > > > > > depends on dsi.div
> > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L786
> > > > > >
> > > > > > lcd_rate = dclk_rate * clk_info.dsi_div;
> > > > > > pll_rate = lcd_rate * clk_info.lcd_div;
> > > > > >
> > > > > > Say
> > > > > >
> > > > > > 1) For 148MHz dclk_rate with dsi_div is 6 (24/4) lcd_div is 1 which
> > > > > > resulting pll_rate is 888MHz.
> > > > > >
> > > > > > 2) For 30MHz dclk_rate with 4 lane and 24 RGB the resulting pll_rate is 180MHz
> > > > > >
> > > > > > 3) For 27.5MHz dclk_rate with 2 lane and 24 RGB the resulting pll_rate is 330MHz
> > > > > >
> > > > > > Here is the few more logs in code, for case 2)
> > > > > >
> > > > > > [    1.920441] sun4i_dclk_round_rate: min_div = 6 max_div = 6, rate = 30000000
> > > > > > [    1.920505] ideal = 180000000, rounded = 178200000
> > > > > > [    1.920509] sun4i_dclk_round_rate: div = 6 rate = 29700000
> > > > > > [    1.920514] sun4i_dclk_round_rate: min_div = 6 max_div = 6, rate = 30000000
> > > > > > [    1.920532] ideal = 1800ls and one DSI-RGB bridge. All of them do use
> > > > PLL_MIPI (pll_rate) and it indeed depends on bpp/lanes
> > > >00000, rounded = 178200000
> > > > > > [    1.920535] sun4i_dclk_round_rate: div = 6 rate = 29700000
> > > > > > [    1.920572] sun4i_dclk_recalc_rate: val = 1, rate = 178200000
> > > > > > [    1.920576] sun4i_dclk_recalc_rate: val = 1, rate = 178200000
> > > > > > [    1.920597] rate = 178200000
> > > > > > [    1.920599] parent_rate = 297000000
> > > > > > [    1.920602] reg = 0x90c00000
> > > > > > [    1.920605] _nkm.n = 3, nkm->n.offset = 0x1, nkm->n.shift = 8
> > > > > > [    1.920609] _nkm.k = 2, nkm->k.offset = 0x1, nkm->k.shift = 4
> > > > > > [    1.920612] _nkm.m = 10, nkm->m.offset = 0x1, nkm->m.shift = 0
> > > > > > [    1.920958] sun4i_dclk_set_rate div 6
> > > > > > [    1.920966] sun4i_dclk_recalc_rate: val = 6, rate = 29700000
> > > > > >
> > > > > > and clk_summary:
> > > > > >
> > > > > >     pll-video0                        1        1        1   297000000
> > > > > >         0     0  50000
> > > > > >        hdmi                           0        0        0   297000000
> > > > > >         0     0  50000
> > > > > >        tcon1                          0        0        0   297000000
> > > > > >         0     0  50000
> > > > > >        pll-mipi                       1        1        1   178200000
> > > > > >         0     0  50000
> > > > > >           tcon0                       2        2        1   178200000
> > > > > >         0     0  50000
> > > > > >              tcon-pixel-clock         1        1        1    29700000
> > > > > >         0     0  50000
> > > > > >        pll-video0-2x                  0        0        0   594000000
> > > > > >         0     0  50000
> > > > >
> > > > > This discussion is going nowhere. I'm telling you that your patch
> > > > > doesn't apply the divider you want on the proper clock, and you're
> > > > > replying that indeed, you're applying it on the wrong clock.
> > > > >
> > > > > It might work by accident in your case, but the board I have here
> > > > > clearly indicates otherwise, so there's two possible way out here:
> > > > >
> > > > >   - Either you apply that divider to the TCON *module* clock, and not
> > > > >     the dclk
> > > > >
> > > > >   - Or you point to somewhere in the allwinner code where the bpp /
> > > > >     lanes divider is used for the dclk divider.
> > > >
> > > > I don't know how to proceed further on this, as you say it might work
> > > > in accident but I have tested this in A33, A64 and R40 with 4
> > > > different DSI panels and one DSI-RGB bridge. All of them do use
> > > > PLL_MIPI (pll_rate) and it indeed depends on bpp/lanes
> > > >
> > > > 4-lane, 24-bit: Novatek NT35596 panel
> > > > 4-lane, 24-bit: Feiyang, FY07024di26a30d panel
> > > > 4-lane, 24-bit: Bananapi-s070wv20 panel
> > > > 2-lane, 24-bit: Techstar,ts8550b panel
> > > >
> > > > and
> > > >
> > > > 4-lane, 24-bit, ICN6211 DSI-to-RGB bridge panel
> > > >
> > > > All above listed panels and bridges are working as per BSP and do
> > > > follow bpp/lanes and for DIVIDER 4 no panel is working.
> > >
> > > Look. I'm not saying that there's no issue, I'm saying that your
> > > patch, applied to the clock you're applying it to, doesn't make sense
> > > and isn't what the BSP does.
> >
> > tcon-pixel clock is the rate that you want to achive on display side
> > and if you have 4 lanes 32bit or lanes and different bit number that
> > you need to have a clock that is able to put outside bits and speed
> > equal to pixel-clock * bits / lanes. so If you want a pixel-clock of
> > 40 mhz and you have 32bits and 4 lanes you need to have a clock of
> > 40 * 32 / 4 in no-burst mode. I think that this is done but most of
> > the display.
>
> So this is what the issue is then?
>
> This one does make sense, and you should just change the rate in the
> call to clk_set_rate in sun4i_tcon0_mode_set_cpu.
>
> I'm still wondering why that hasn't been brought up in either the
> discussion or the commit log before though.
>
Something like this?

drivers/gpu/drm/sun4i/sun4i_tcon.c     | 20 +++++++++++---------
 drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h |  2 --
 2 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c
b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 64c43ee6bd92..42560d5c327c 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -263,10 +263,11 @@ static int sun4i_tcon_get_clk_delay(const struct
drm_display_mode *mode,
 }

 static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
-                                       const struct drm_display_mode *mode)
+                                       const struct drm_display_mode *mode,
+                                       u32 tcon_mul)
 {
        /* Configure the dot clock */
-       clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
+       clk_set_rate(tcon->dclk, mode->crtc_clock * tcon_mul * 1000);

        /* Set the resolution */
        regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
@@ -335,12 +336,13 @@ 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;
+       u32 tcon_div, tcon_mul;

-       tcon->dclk_min_div = SUN6I_DSI_TCON_DIV;
-       tcon->dclk_max_div = SUN6I_DSI_TCON_DIV;
+       tcon->dclk_min_div = 4;
+       tcon->dclk_max_div = 127;

-       sun4i_tcon0_mode_set_common(tcon, mode);
+       tcon_mul = bpp / lanes;
+       sun4i_tcon0_mode_set_common(tcon, mode, tcon_mul);

        /* Set dithering if needed */
        sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
@@ -366,7 +368,7 @@ static void sun4i_tcon0_mode_set_cpu(struct
sun4i_tcon *tcon,
         */
        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 * tcon_div * tcon_mul;
        block_space -= mode->hdisplay + 40;

        regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI0_REG,
@@ -408,7 +410,7 @@ 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);
+       sun4i_tcon0_mode_set_common(tcon, mode, 1);

        /* Set dithering if needed */
        sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
@@ -487,7 +489,7 @@ static void sun4i_tcon0_mode_set_rgb(struct
sun4i_tcon *tcon,

        tcon->dclk_min_div = 6;
        tcon->dclk_max_div = 127;
-       sun4i_tcon0_mode_set_common(tcon, mode);
+       sun4i_tcon0_mode_set_common(tcon, mode, 1);

        /* Set dithering if needed */
        sun4i_tcon0_mode_set_dithering(tcon, connector);
diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
index 5c3ad5be0690..a07090579f84 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
@@ -13,8 +13,6 @@
 #include <drm/drm_encoder.h>
 #include <drm/drm_mipi_dsi.h>

-#define SUN6I_DSI_TCON_DIV     4
-
 struct sun6i_dsi {
        struct drm_connector    connector;
        struct drm_encoder      encoder;


> > Now in burst mode I don't know how should work the calculation of
> > the clock for the require bandwidth and even I understand your
> > comment I would like to have your clock tree after you boot on the
> > display side and if it is possible I want to assemble a kit like you
> > have.
>
> The setup is probably going to be a bit difficult to reproduce, it's a
> prototype that I have that can't really be found anywhere. Jagan asked
> me on IRC for the reference, and he found the part, but it's unclear
> to me if it can be easily adapted to a common board.
>
> However, I'm not even sure we need this. I'll test the next version
> and let you know if it works.
>
> Maxime
>
> --
> Maxime Ripard, Bootlin
> Embedded Linux and Kernel engineering
> https://bootlin.com
Michael Nazzareno Trimarchi July 11, 2019, 7:34 p.m. UTC | #21
Hi

On Thu, Jul 11, 2019 at 7:43 PM Michael Nazzareno Trimarchi
<michael@amarulasolutions.com> wrote:
>
> Hi Maxime
>
> On Thu, Jul 11, 2019 at 2:23 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> >
> > On Fri, Jul 05, 2019 at 07:52:27PM +0200, Michael Nazzareno Trimarchi wrote:
> > > On Wed, Jul 3, 2019 at 1:49 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > > >
> > > > On Tue, Jun 25, 2019 at 09:00:36PM +0530, Jagan Teki wrote:
> > > > > On Tue, Jun 25, 2019 at 8:19 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > > > > >
> > > > > > On Thu, Jun 20, 2019 at 11:57:44PM +0530, Jagan Teki wrote:
> > > > > > > On Fri, Jun 14, 2019 at 7:54 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > > > > > > >
> > > > > > > > On Wed, Jun 05, 2019 at 01:03:16PM +0530, Jagan Teki wrote:
> > > > > > > > > On Wed, Jun 5, 2019 at 12:19 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > > > > > > > > >
> > > > > > > > > > Hi,
> > > > > > > > > >
> > > > > > > > > > I've reordered the mail a bit to work on chunks
> > > > > > > > > >
> > > > > > > > > > On Fri, May 24, 2019 at 03:37:42PM +0530, Jagan Teki wrote:
> > > > > > > > > > > > I wish it was in your commit log in the first place, instead of having
> > > > > > > > > > > > to exchange multiple mails over this.
> > > > > > > > > > > >
> > > > > > > > > > > > However, I don't think that's quite true, and it might be a bug in
> > > > > > > > > > > > Allwinner's implementation (or rather something quite confusing).
> > > > > > > > > > > >
> > > > > > > > > > > > You're right that the lcd_rate and pll_rate seem to be generated from
> > > > > > > > > > > > the pixel clock, and it indeed looks like the ratio between the pixel
> > > > > > > > > > > > clock and the TCON dotclock is defined through the number of bits per
> > > > > > > > > > > > lanes.
> > > > > > > > > > > >
> > > > > > > > > > > > However, in this case, dsi_rate is actually the same than lcd_rate,
> > > > > > > > > > > > since pll_rate is going to be divided by dsi_div:
> > > > > > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L791
> > > > > > > > > > > >
> > > > > > > > > > > > Since lcd_div is 1, it also means that in this case, dsi_rate ==
> > > > > > > > > > > > dclk_rate.
> > > > > > > > > > > >
> > > > > > > > > > > > The DSI module clock however, is always set to 148.5 MHz. Indeed, if
> > > > > > > > > > > > we look at:
> > > > > > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L804
> > > > > > > > > > > >
> > > > > > > > > > > > We can see that the rate in clk_info is used if it's different than
> > > > > > > > > > > > 0. This is filled by disp_al_lcd_get_clk_info, which, in the case of a
> > > > > > > > > > > > DSI panel, will hardcode it to 148.5 MHz:
> > > > > > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L164
> > > > > > > > > > >
> > > > > > > > > > > Let me explain, something more.
> > > > > > > > > > >
> > > > > > > > > > > According to bsp there are clk_info.tcon_div which I will explain below.
> > > > > > > > > > > clk_info.dsi_div which is dynamic and it depends on bpp/lanes, so it
> > > > > > > > > > > is 6 for 24bpp and 4 lanes devices.
> > > > > > > > > > >
> > > > > > > > > > > PLL rate here depends on dsi_div (not tcon_div)
> > > > > > > > > > >
> > > > > > > > > > > Code here
> > > > > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L784
> > > > > > > > > > >
> > > > > > > > > > > is computing the actual set rate, which depends on dsi_rate.
> > > > > > > > > > >
> > > > > > > > > > > lcd_rate = dclk_rate * clk_info.dsi_div;
> > > > > > > > > > > dsi_rate = pll_rate / clk_info.dsi_div;
> > > > > > > > > > >
> > > > > > > > > > > Say if the dclk_rate 148MHz then the dsi_rate is 888MHz which set rate
> > > > > > > > > > > for above link you mentioned.
> > > > > > > > > > >
> > > > > > > > > > > Here are the evidence with some prints.
> > > > > > > > > > >
> > > > > > > > > > > https://gist.github.com/openedev/9bae2d87d2fcc06b999fe48c998b7043
> > > > > > > > > > > https://gist.github.com/openedev/700de2e3701b2bf3ad1aa0f0fa862c9a
> > > > > > > > > >
> > > > > > > > > > Ok, so we agree up to this point, and the prints confirm that the
> > > > > > > > > > analysis above is the right one.
> > > > > > > > > >
> > > > > > > > > > > > So, the DSI clock is set to this here:
> > > > > > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L805
> > > > > > > > > >
> > > > > > > > > > Your patch doesn't address that, so let's leave that one alone.
> > > > > > > > >
> > > > > > > > > Basically this is final pll set rate when sun4i_dotclock.c called the
> > > > > > > > > desired rate with ccu_nkm.c so it ended the final rate with parent as
> > > > > > > > > Line 8 of
> > > > > > > > > https://gist.github.com/openedev/700de2e3701b2bf3ad1aa0f0fa862c9a
> > > > > > > >
> > > > > > > > If that's important to the driver, it should be set explicitly then,
> > > > > > > > and not work by accident.
> > > > > > > >
> > > > > > > > > > > > The TCON *module* clock (the one in the clock controller) has been set
> > > > > > > > > > > > to lcd_rate (so the pixel clock times the number of bits per lane) here:
> > > > > > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L800
> > > > > > > > > > > >
> > > > > > > > > > > > And the PLL has been set to the same rate here:
> > > > > > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L794
> > > > > > > > > > > >
> > > > > > > > > > > > Let's take a step back now: that function we were looking at,
> > > > > > > > > > > > lcd_clk_config, is called by lcd_clk_enable, which is in turn called
> > > > > > > > > > > > by disp_lcd_enable here:
> > > > > > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L1328
> > > > > > > > > > > >
> > > > > > > > > > > > The next function being called is disp_al_lcd_cfg, and that function
> > > > > > > > > > > > will hardcode the TCON dotclock divider to 4, here:
> > > > > > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L240
> > > > > > > > > > >
> > > > > > > > > > > tcon_div from BSP point-of-view of there are two variants
> > > > > > > > > > > 00) clk_info.tcon_div which is 4 and same is set the divider position
> > > > > > > > > > > in SUN4I_TCON0_DCLK_REG (like above link refer)
> > > > > > > > > > > 01) tcon_div which is 4 and used for edge timings computation
> > > > > > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c#L12
> > > > > > > > > > >
> > > > > > > > > > > The real reason for 01) is again 4 is they set the divider to 4 in 00)
> > > > > > > > > > > which is technically wrong because the dividers which used during
> > > > > > > > > > > dotclock in above (dsi_div) should be used here as well. Since there
> > > > > > > > > > > is no dynamic way of doing this BSP hard-coding these values.
> > > > > > > > > > >
> > > > > > > > > > > Patches 5,6,7 on this series doing this
> > > > > > > > > > > https://patchwork.freedesktop.org/series/60847/
> > > > > > > > > > >
> > > > > > > > > > > Hope this explanation helps?
> > > > > > > > > >
> > > > > > > > > > It doesn't.
> > > > > > > > > >
> > > > > > > > > > The clock tree is this one:
> > > > > > > > > >
> > > > > > > > > > PLL(s) -> TCON module clock -> TCON dotclock.
> > > > > > > > > >
> > > > > > > > > > The links I mentioned above show that the clock set to lcd_rate is the
> > > > > > > > > > TCON module clocks (and it should be the one taking the bpp and lanes
> > > > > > > > > > into account), while the TCON dotclock uses a fixed divider of 4.
> > > > > > > > >
> > > > > > > > > Sorry, I can argue much other-than giving some code snips, according to [1]
> > > > > > > > >
> > > > > > > > > 00) Line 785, 786 with dclk_rate 148000000
> > > > > > > > >
> > > > > > > > > lcd_rate = dclk_rate * clk_info.dsi_div;
> > > > > > > > > pll_rate = lcd_rate * clk_info.lcd_div;
> > > > > > > > >
> > > > > > > > > Since dsi_div is 6 (bpp/lanes), lcd_div 1
> > > > > > > > >
> > > > > > > > > lcd_rate = 888000000, pll_rate = 888000000
> > > > > > > > >
> > > > > > > > > 01)  Line 801, 804 are final rates computed as per clock driver (say
> > > > > > > > > ccu_nkm in mainline)
> > > > > > > > >
> > > > > > > > > lcd_rate_set=891000000
> > > > > > > > >
> > > > > > > > > As per your comments if it would be 4 then the desired numbers are
> > > > > > > > > would be 592000000 not 888000000.
> > > > > > > > >
> > > > > > > > > This is what I'm trying to say in all mails, and same as verified with
> > > > > > > > > 2-lanes devices as well where the dsi_div is 12 so the final rate is
> > > > > > > > > 290MHz * 12
> > > > > > > >
> > > > > > > > In the code you sent, you're forcing a divider on the internal TCON
> > > > > > > > clock, while that one is fixed in the BSP.
> > > > > > > >
> > > > > > > > There's indeed the bpp / lanes divider, but it's used in the *parent*
> > > > > > > > clock of the one you're changing.
> > > > > > > >
> > > > > > > > And the dsi0_clk clock you pointed out in the code snippet is yet
> > > > > > > > another clock, the MIPI DSI module clock.
> > > > > > >
> > > > > > > Correct, look like I refereed wrong reference in the above mail. sorry
> > > > > > > for the noise.
> > > > > > >
> > > > > > > Actually I'm trying to explain about pll_rate here which indeed
> > > > > > > depends on dsi.div
> > > > > > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L786
> > > > > > >
> > > > > > > lcd_rate = dclk_rate * clk_info.dsi_div;
> > > > > > > pll_rate = lcd_rate * clk_info.lcd_div;
> > > > > > >
> > > > > > > Say
> > > > > > >
> > > > > > > 1) For 148MHz dclk_rate with dsi_div is 6 (24/4) lcd_div is 1 which
> > > > > > > resulting pll_rate is 888MHz.
> > > > > > >
> > > > > > > 2) For 30MHz dclk_rate with 4 lane and 24 RGB the resulting pll_rate is 180MHz
> > > > > > >
> > > > > > > 3) For 27.5MHz dclk_rate with 2 lane and 24 RGB the resulting pll_rate is 330MHz
> > > > > > >
> > > > > > > Here is the few more logs in code, for case 2)
> > > > > > >
> > > > > > > [    1.920441] sun4i_dclk_round_rate: min_div = 6 max_div = 6, rate = 30000000
> > > > > > > [    1.920505] ideal = 180000000, rounded = 178200000
> > > > > > > [    1.920509] sun4i_dclk_round_rate: div = 6 rate = 29700000
> > > > > > > [    1.920514] sun4i_dclk_round_rate: min_div = 6 max_div = 6, rate = 30000000
> > > > > > > [    1.920532] ideal = 1800ls and one DSI-RGB bridge. All of them do use
> > > > > PLL_MIPI (pll_rate) and it indeed depends on bpp/lanes
> > > > >00000, rounded = 178200000
> > > > > > > [    1.920535] sun4i_dclk_round_rate: div = 6 rate = 29700000
> > > > > > > [    1.920572] sun4i_dclk_recalc_rate: val = 1, rate = 178200000
> > > > > > > [    1.920576] sun4i_dclk_recalc_rate: val = 1, rate = 178200000
> > > > > > > [    1.920597] rate = 178200000
> > > > > > > [    1.920599] parent_rate = 297000000
> > > > > > > [    1.920602] reg = 0x90c00000
> > > > > > > [    1.920605] _nkm.n = 3, nkm->n.offset = 0x1, nkm->n.shift = 8
> > > > > > > [    1.920609] _nkm.k = 2, nkm->k.offset = 0x1, nkm->k.shift = 4
> > > > > > > [    1.920612] _nkm.m = 10, nkm->m.offset = 0x1, nkm->m.shift = 0
> > > > > > > [    1.920958] sun4i_dclk_set_rate div 6
> > > > > > > [    1.920966] sun4i_dclk_recalc_rate: val = 6, rate = 29700000
> > > > > > >
> > > > > > > and clk_summary:
> > > > > > >
> > > > > > >     pll-video0                        1        1        1   297000000
> > > > > > >         0     0  50000
> > > > > > >        hdmi                           0        0        0   297000000
> > > > > > >         0     0  50000
> > > > > > >        tcon1                          0        0        0   297000000
> > > > > > >         0     0  50000
> > > > > > >        pll-mipi                       1        1        1   178200000
> > > > > > >         0     0  50000
> > > > > > >           tcon0                       2        2        1   178200000
> > > > > > >         0     0  50000
> > > > > > >              tcon-pixel-clock         1        1        1    29700000
> > > > > > >         0     0  50000
> > > > > > >        pll-video0-2x                  0        0        0   594000000
> > > > > > >         0     0  50000
> > > > > >
> > > > > > This discussion is going nowhere. I'm telling you that your patch
> > > > > > doesn't apply the divider you want on the proper clock, and you're
> > > > > > replying that indeed, you're applying it on the wrong clock.
> > > > > >
> > > > > > It might work by accident in your case, but the board I have here
> > > > > > clearly indicates otherwise, so there's two possible way out here:
> > > > > >
> > > > > >   - Either you apply that divider to the TCON *module* clock, and not
> > > > > >     the dclk
> > > > > >
> > > > > >   - Or you point to somewhere in the allwinner code where the bpp /
> > > > > >     lanes divider is used for the dclk divider.
> > > > >
> > > > > I don't know how to proceed further on this, as you say it might work
> > > > > in accident but I have tested this in A33, A64 and R40 with 4
> > > > > different DSI panels and one DSI-RGB bridge. All of them do use
> > > > > PLL_MIPI (pll_rate) and it indeed depends on bpp/lanes
> > > > >
> > > > > 4-lane, 24-bit: Novatek NT35596 panel
> > > > > 4-lane, 24-bit: Feiyang, FY07024di26a30d panel
> > > > > 4-lane, 24-bit: Bananapi-s070wv20 panel
> > > > > 2-lane, 24-bit: Techstar,ts8550b panel
> > > > >
> > > > > and
> > > > >
> > > > > 4-lane, 24-bit, ICN6211 DSI-to-RGB bridge panel
> > > > >
> > > > > All above listed panels and bridges are working as per BSP and do
> > > > > follow bpp/lanes and for DIVIDER 4 no panel is working.
> > > >
> > > > Look. I'm not saying that there's no issue, I'm saying that your
> > > > patch, applied to the clock you're applying it to, doesn't make sense
> > > > and isn't what the BSP does.
> > >
> > > tcon-pixel clock is the rate that you want to achive on display side
> > > and if you have 4 lanes 32bit or lanes and different bit number that
> > > you need to have a clock that is able to put outside bits and speed
> > > equal to pixel-clock * bits / lanes. so If you want a pixel-clock of
> > > 40 mhz and you have 32bits and 4 lanes you need to have a clock of
> > > 40 * 32 / 4 in no-burst mode. I think that this is done but most of
> > > the display.
> >
> > So this is what the issue is then?
> >
> > This one does make sense, and you should just change the rate in the
> > call to clk_set_rate in sun4i_tcon0_mode_set_cpu.
> >
> > I'm still wondering why that hasn't been brought up in either the
> > discussion or the commit log before though.
> >
> Something like this?
>
> drivers/gpu/drm/sun4i/sun4i_tcon.c     | 20 +++++++++++---------
>  drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h |  2 --
>  2 files changed, 11 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> index 64c43ee6bd92..42560d5c327c 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> @@ -263,10 +263,11 @@ static int sun4i_tcon_get_clk_delay(const struct
> drm_display_mode *mode,
>  }
>
>  static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
> -                                       const struct drm_display_mode *mode)
> +                                       const struct drm_display_mode *mode,
> +                                       u32 tcon_mul)
>  {
>         /* Configure the dot clock */
> -       clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
> +       clk_set_rate(tcon->dclk, mode->crtc_clock * tcon_mul * 1000);
>
>         /* Set the resolution */
>         regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
> @@ -335,12 +336,13 @@ 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;
> +       u32 tcon_div, tcon_mul;
>
> -       tcon->dclk_min_div = SUN6I_DSI_TCON_DIV;
> -       tcon->dclk_max_div = SUN6I_DSI_TCON_DIV;
> +       tcon->dclk_min_div = 4;
> +       tcon->dclk_max_div = 127;
>
> -       sun4i_tcon0_mode_set_common(tcon, mode);
> +       tcon_mul = bpp / lanes;
> +       sun4i_tcon0_mode_set_common(tcon, mode, tcon_mul);
>

Maybe wrong clock ;) but is this your idea?

Michael
>         /* Set dithering if needed */
>         sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
> @@ -366,7 +368,7 @@ static void sun4i_tcon0_mode_set_cpu(struct
> sun4i_tcon *tcon,
>          */
>         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 * tcon_div * tcon_mul;
>         block_space -= mode->hdisplay + 40;
>
>         regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI0_REG,
> @@ -408,7 +410,7 @@ 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);
> +       sun4i_tcon0_mode_set_common(tcon, mode, 1);
>
>         /* Set dithering if needed */
>         sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
> @@ -487,7 +489,7 @@ static void sun4i_tcon0_mode_set_rgb(struct
> sun4i_tcon *tcon,
>
>         tcon->dclk_min_div = 6;
>         tcon->dclk_max_div = 127;
> -       sun4i_tcon0_mode_set_common(tcon, mode);
> +       sun4i_tcon0_mode_set_common(tcon, mode, 1);
>
>         /* Set dithering if needed */
>         sun4i_tcon0_mode_set_dithering(tcon, connector);
> diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> index 5c3ad5be0690..a07090579f84 100644
> --- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> +++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> @@ -13,8 +13,6 @@
>  #include <drm/drm_encoder.h>
>  #include <drm/drm_mipi_dsi.h>
>
> -#define SUN6I_DSI_TCON_DIV     4
> -
>  struct sun6i_dsi {
>         struct drm_connector    connector;
>         struct drm_encoder      encoder;
>
>
> > > Now in burst mode I don't know how should work the calculation of
> > > the clock for the require bandwidth and even I understand your
> > > comment I would like to have your clock tree after you boot on the
> > > display side and if it is possible I want to assemble a kit like you
> > > have.
> >
> > The setup is probably going to be a bit difficult to reproduce, it's a
> > prototype that I have that can't really be found anywhere. Jagan asked
> > me on IRC for the reference, and he found the part, but it's unclear
> > to me if it can be easily adapted to a common board.
> >
> > However, I'm not even sure we need this. I'll test the next version
> > and let you know if it works.
> >
> > Maxime
> >
> > --
> > Maxime Ripard, Bootlin
> > Embedded Linux and Kernel engineering
> > https://bootlin.com
>
>
>
> --
> | Michael Nazzareno Trimarchi                     Amarula Solutions BV |
> | COO  -  Founder                                      Cruquiuskade 47 |
> | +31(0)851119172                                 Amsterdam 1018 AM NL |
> |                  [`as] http://www.amarulasolutions.com               |
Maxime Ripard July 20, 2019, 6:58 a.m. UTC | #22
On Thu, Jul 11, 2019 at 07:43:16PM +0200, Michael Nazzareno Trimarchi wrote:
> > > tcon-pixel clock is the rate that you want to achive on display side
> > > and if you have 4 lanes 32bit or lanes and different bit number that
> > > you need to have a clock that is able to put outside bits and speed
> > > equal to pixel-clock * bits / lanes. so If you want a pixel-clock of
> > > 40 mhz and you have 32bits and 4 lanes you need to have a clock of
> > > 40 * 32 / 4 in no-burst mode. I think that this is done but most of
> > > the display.
> >
> > So this is what the issue is then?
> >
> > This one does make sense, and you should just change the rate in the
> > call to clk_set_rate in sun4i_tcon0_mode_set_cpu.
> >
> > I'm still wondering why that hasn't been brought up in either the
> > discussion or the commit log before though.
> >
> Something like this?
>
> drivers/gpu/drm/sun4i/sun4i_tcon.c     | 20 +++++++++++---------
>  drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h |  2 --
>  2 files changed, 11 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> index 64c43ee6bd92..42560d5c327c 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> @@ -263,10 +263,11 @@ static int sun4i_tcon_get_clk_delay(const struct
> drm_display_mode *mode,
>  }
>
>  static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
> -                                       const struct drm_display_mode *mode)
> +                                       const struct drm_display_mode *mode,
> +                                       u32 tcon_mul)
>  {
>         /* Configure the dot clock */
> -       clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
> +       clk_set_rate(tcon->dclk, mode->crtc_clock * tcon_mul * 1000);
>
>         /* Set the resolution */
>         regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
> @@ -335,12 +336,13 @@ 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;
> +       u32 tcon_div, tcon_mul;
>
> -       tcon->dclk_min_div = SUN6I_DSI_TCON_DIV;
> -       tcon->dclk_max_div = SUN6I_DSI_TCON_DIV;
> +       tcon->dclk_min_div = 4;
> +       tcon->dclk_max_div = 127;
>
> -       sun4i_tcon0_mode_set_common(tcon, mode);
> +       tcon_mul = bpp / lanes;
> +       sun4i_tcon0_mode_set_common(tcon, mode, tcon_mul);
>
>         /* Set dithering if needed */
>         sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
> @@ -366,7 +368,7 @@ static void sun4i_tcon0_mode_set_cpu(struct
> sun4i_tcon *tcon,
>          */
>         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 * tcon_div * tcon_mul;
>         block_space -= mode->hdisplay + 40;
>
>         regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI0_REG,
> @@ -408,7 +410,7 @@ 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);
> +       sun4i_tcon0_mode_set_common(tcon, mode, 1);
>
>         /* Set dithering if needed */
>         sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
> @@ -487,7 +489,7 @@ static void sun4i_tcon0_mode_set_rgb(struct
> sun4i_tcon *tcon,
>
>         tcon->dclk_min_div = 6;
>         tcon->dclk_max_div = 127;
> -       sun4i_tcon0_mode_set_common(tcon, mode);
> +       sun4i_tcon0_mode_set_common(tcon, mode, 1);
>
>         /* Set dithering if needed */
>         sun4i_tcon0_mode_set_dithering(tcon, connector);
> diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> index 5c3ad5be0690..a07090579f84 100644
> --- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> +++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> @@ -13,8 +13,6 @@
>  #include <drm/drm_encoder.h>
>  #include <drm/drm_mipi_dsi.h>
>
> -#define SUN6I_DSI_TCON_DIV     4
> -
>  struct sun6i_dsi {
>         struct drm_connector    connector;
>         struct drm_encoder      encoder;

I had more something like this in mind:
http://code.bulix.org/nlp5a4-803511

You really don't need to change the divider range (or this is another
issue that the one you mentionned).

Maxime

--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
Jagan Teki July 20, 2019, 7:16 a.m. UTC | #23
On Sat, Jul 20, 2019 at 12:28 PM Maxime Ripard
<maxime.ripard@bootlin.com> wrote:
>
> On Thu, Jul 11, 2019 at 07:43:16PM +0200, Michael Nazzareno Trimarchi wrote:
> > > > tcon-pixel clock is the rate that you want to achive on display side
> > > > and if you have 4 lanes 32bit or lanes and different bit number that
> > > > you need to have a clock that is able to put outside bits and speed
> > > > equal to pixel-clock * bits / lanes. so If you want a pixel-clock of
> > > > 40 mhz and you have 32bits and 4 lanes you need to have a clock of
> > > > 40 * 32 / 4 in no-burst mode. I think that this is done but most of
> > > > the display.
> > >
> > > So this is what the issue is then?
> > >
> > > This one does make sense, and you should just change the rate in the
> > > call to clk_set_rate in sun4i_tcon0_mode_set_cpu.
> > >
> > > I'm still wondering why that hasn't been brought up in either the
> > > discussion or the commit log before though.
> > >
> > Something like this?
> >
> > drivers/gpu/drm/sun4i/sun4i_tcon.c     | 20 +++++++++++---------
> >  drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h |  2 --
> >  2 files changed, 11 insertions(+), 11 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > index 64c43ee6bd92..42560d5c327c 100644
> > --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > @@ -263,10 +263,11 @@ static int sun4i_tcon_get_clk_delay(const struct
> > drm_display_mode *mode,
> >  }
> >
> >  static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
> > -                                       const struct drm_display_mode *mode)
> > +                                       const struct drm_display_mode *mode,
> > +                                       u32 tcon_mul)
> >  {
> >         /* Configure the dot clock */
> > -       clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
> > +       clk_set_rate(tcon->dclk, mode->crtc_clock * tcon_mul * 1000);
> >
> >         /* Set the resolution */
> >         regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
> > @@ -335,12 +336,13 @@ 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;
> > +       u32 tcon_div, tcon_mul;
> >
> > -       tcon->dclk_min_div = SUN6I_DSI_TCON_DIV;
> > -       tcon->dclk_max_div = SUN6I_DSI_TCON_DIV;
> > +       tcon->dclk_min_div = 4;
> > +       tcon->dclk_max_div = 127;
> >
> > -       sun4i_tcon0_mode_set_common(tcon, mode);
> > +       tcon_mul = bpp / lanes;
> > +       sun4i_tcon0_mode_set_common(tcon, mode, tcon_mul);
> >
> >         /* Set dithering if needed */
> >         sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
> > @@ -366,7 +368,7 @@ static void sun4i_tcon0_mode_set_cpu(struct
> > sun4i_tcon *tcon,
> >          */
> >         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 * tcon_div * tcon_mul;
> >         block_space -= mode->hdisplay + 40;
> >
> >         regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI0_REG,
> > @@ -408,7 +410,7 @@ 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);
> > +       sun4i_tcon0_mode_set_common(tcon, mode, 1);
> >
> >         /* Set dithering if needed */
> >         sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
> > @@ -487,7 +489,7 @@ static void sun4i_tcon0_mode_set_rgb(struct
> > sun4i_tcon *tcon,
> >
> >         tcon->dclk_min_div = 6;
> >         tcon->dclk_max_div = 127;
> > -       sun4i_tcon0_mode_set_common(tcon, mode);
> > +       sun4i_tcon0_mode_set_common(tcon, mode, 1);
> >
> >         /* Set dithering if needed */
> >         sun4i_tcon0_mode_set_dithering(tcon, connector);
> > diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > index 5c3ad5be0690..a07090579f84 100644
> > --- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > +++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > @@ -13,8 +13,6 @@
> >  #include <drm/drm_encoder.h>
> >  #include <drm/drm_mipi_dsi.h>
> >
> > -#define SUN6I_DSI_TCON_DIV     4
> > -
> >  struct sun6i_dsi {
> >         struct drm_connector    connector;
> >         struct drm_encoder      encoder;
>
> I had more something like this in mind:
> http://code.bulix.org/nlp5a4-803511

Worth to look at it. was it working on your panel? meanwhile I will check it.

We have updated with below change [1], seems working on but is
actually checking the each divider as before start with 4... till 127.

This new approach, is start looking the best divider from 4.. based on
the idea vs rounded it will ended up best divider like [2]

https://gist.github.com/openedev/7e2c33248b372d29be9979e06d483673
https://gist.github.com/openedev/c72dfffc0ca59e7ec1edcd7ad360cdd1

Jagan.
Jagan Teki July 20, 2019, 7:34 a.m. UTC | #24
On Sat, Jul 20, 2019 at 12:46 PM Jagan Teki <jagan@amarulasolutions.com> wrote:
>
> On Sat, Jul 20, 2019 at 12:28 PM Maxime Ripard
> <maxime.ripard@bootlin.com> wrote:
> >
> > On Thu, Jul 11, 2019 at 07:43:16PM +0200, Michael Nazzareno Trimarchi wrote:
> > > > > tcon-pixel clock is the rate that you want to achive on display side
> > > > > and if you have 4 lanes 32bit or lanes and different bit number that
> > > > > you need to have a clock that is able to put outside bits and speed
> > > > > equal to pixel-clock * bits / lanes. so If you want a pixel-clock of
> > > > > 40 mhz and you have 32bits and 4 lanes you need to have a clock of
> > > > > 40 * 32 / 4 in no-burst mode. I think that this is done but most of
> > > > > the display.
> > > >
> > > > So this is what the issue is then?
> > > >
> > > > This one does make sense, and you should just change the rate in the
> > > > call to clk_set_rate in sun4i_tcon0_mode_set_cpu.
> > > >
> > > > I'm still wondering why that hasn't been brought up in either the
> > > > discussion or the commit log before though.
> > > >
> > > Something like this?
> > >
> > > drivers/gpu/drm/sun4i/sun4i_tcon.c     | 20 +++++++++++---------
> > >  drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h |  2 --
> > >  2 files changed, 11 insertions(+), 11 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > index 64c43ee6bd92..42560d5c327c 100644
> > > --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > @@ -263,10 +263,11 @@ static int sun4i_tcon_get_clk_delay(const struct
> > > drm_display_mode *mode,
> > >  }
> > >
> > >  static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
> > > -                                       const struct drm_display_mode *mode)
> > > +                                       const struct drm_display_mode *mode,
> > > +                                       u32 tcon_mul)
> > >  {
> > >         /* Configure the dot clock */
> > > -       clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
> > > +       clk_set_rate(tcon->dclk, mode->crtc_clock * tcon_mul * 1000);
> > >
> > >         /* Set the resolution */
> > >         regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
> > > @@ -335,12 +336,13 @@ 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;
> > > +       u32 tcon_div, tcon_mul;
> > >
> > > -       tcon->dclk_min_div = SUN6I_DSI_TCON_DIV;
> > > -       tcon->dclk_max_div = SUN6I_DSI_TCON_DIV;
> > > +       tcon->dclk_min_div = 4;
> > > +       tcon->dclk_max_div = 127;
> > >
> > > -       sun4i_tcon0_mode_set_common(tcon, mode);
> > > +       tcon_mul = bpp / lanes;
> > > +       sun4i_tcon0_mode_set_common(tcon, mode, tcon_mul);
> > >
> > >         /* Set dithering if needed */
> > >         sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
> > > @@ -366,7 +368,7 @@ static void sun4i_tcon0_mode_set_cpu(struct
> > > sun4i_tcon *tcon,
> > >          */
> > >         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 * tcon_div * tcon_mul;
> > >         block_space -= mode->hdisplay + 40;
> > >
> > >         regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI0_REG,
> > > @@ -408,7 +410,7 @@ 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);
> > > +       sun4i_tcon0_mode_set_common(tcon, mode, 1);
> > >
> > >         /* Set dithering if needed */
> > >         sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
> > > @@ -487,7 +489,7 @@ static void sun4i_tcon0_mode_set_rgb(struct
> > > sun4i_tcon *tcon,
> > >
> > >         tcon->dclk_min_div = 6;
> > >         tcon->dclk_max_div = 127;
> > > -       sun4i_tcon0_mode_set_common(tcon, mode);
> > > +       sun4i_tcon0_mode_set_common(tcon, mode, 1);
> > >
> > >         /* Set dithering if needed */
> > >         sun4i_tcon0_mode_set_dithering(tcon, connector);
> > > diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > index 5c3ad5be0690..a07090579f84 100644
> > > --- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > +++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > @@ -13,8 +13,6 @@
> > >  #include <drm/drm_encoder.h>
> > >  #include <drm/drm_mipi_dsi.h>
> > >
> > > -#define SUN6I_DSI_TCON_DIV     4
> > > -
> > >  struct sun6i_dsi {
> > >         struct drm_connector    connector;
> > >         struct drm_encoder      encoder;
> >
> > I had more something like this in mind:
> > http://code.bulix.org/nlp5a4-803511
>
> Worth to look at it. was it working on your panel? meanwhile I will check it.
>
> We have updated with below change [1], seems working on but is
> actually checking the each divider as before start with 4... till 127.
>
> This new approach, is start looking the best divider from 4.. based on
> the idea vs rounded it will ended up best divider like [2]
>
> https://gist.github.com/openedev/7e2c33248b372d29be9979e06d483673
> https://gist.github.com/openedev/c72dfffc0ca59e7ec1edcd7ad360cdd1

I made quick check on two possibilities.

1) with Maxime change
https://gist.github.com/openedev/3b0b3d35ced6d89f5be0831f1cc9d840
https://gist.github.com/openedev/dd6a9e528cde80ef0508cb54723f505d

2) with Maxime change along with min 4, max 127 divider values.
The outcome similar like 1)

This look it will depends on divider, need to check further on this page.

Jagan.
Maxime Ripard July 20, 2019, 9:32 a.m. UTC | #25
On Sat, Jul 20, 2019 at 12:46:27PM +0530, Jagan Teki wrote:
> On Sat, Jul 20, 2019 at 12:28 PM Maxime Ripard
> <maxime.ripard@bootlin.com> wrote:
> >
> > On Thu, Jul 11, 2019 at 07:43:16PM +0200, Michael Nazzareno Trimarchi wrote:
> > > > > tcon-pixel clock is the rate that you want to achive on display side
> > > > > and if you have 4 lanes 32bit or lanes and different bit number that
> > > > > you need to have a clock that is able to put outside bits and speed
> > > > > equal to pixel-clock * bits / lanes. so If you want a pixel-clock of
> > > > > 40 mhz and you have 32bits and 4 lanes you need to have a clock of
> > > > > 40 * 32 / 4 in no-burst mode. I think that this is done but most of
> > > > > the display.
> > > >
> > > > So this is what the issue is then?
> > > >
> > > > This one does make sense, and you should just change the rate in the
> > > > call to clk_set_rate in sun4i_tcon0_mode_set_cpu.
> > > >
> > > > I'm still wondering why that hasn't been brought up in either the
> > > > discussion or the commit log before though.
> > > >
> > > Something like this?
> > >
> > > drivers/gpu/drm/sun4i/sun4i_tcon.c     | 20 +++++++++++---------
> > >  drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h |  2 --
> > >  2 files changed, 11 insertions(+), 11 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > index 64c43ee6bd92..42560d5c327c 100644
> > > --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > @@ -263,10 +263,11 @@ static int sun4i_tcon_get_clk_delay(const struct
> > > drm_display_mode *mode,
> > >  }
> > >
> > >  static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
> > > -                                       const struct drm_display_mode *mode)
> > > +                                       const struct drm_display_mode *mode,
> > > +                                       u32 tcon_mul)
> > >  {
> > >         /* Configure the dot clock */
> > > -       clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
> > > +       clk_set_rate(tcon->dclk, mode->crtc_clock * tcon_mul * 1000);
> > >
> > >         /* Set the resolution */
> > >         regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
> > > @@ -335,12 +336,13 @@ 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;
> > > +       u32 tcon_div, tcon_mul;
> > >
> > > -       tcon->dclk_min_div = SUN6I_DSI_TCON_DIV;
> > > -       tcon->dclk_max_div = SUN6I_DSI_TCON_DIV;
> > > +       tcon->dclk_min_div = 4;
> > > +       tcon->dclk_max_div = 127;
> > >
> > > -       sun4i_tcon0_mode_set_common(tcon, mode);
> > > +       tcon_mul = bpp / lanes;
> > > +       sun4i_tcon0_mode_set_common(tcon, mode, tcon_mul);
> > >
> > >         /* Set dithering if needed */
> > >         sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
> > > @@ -366,7 +368,7 @@ static void sun4i_tcon0_mode_set_cpu(struct
> > > sun4i_tcon *tcon,
> > >          */
> > >         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 * tcon_div * tcon_mul;
> > >         block_space -= mode->hdisplay + 40;
> > >
> > >         regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI0_REG,
> > > @@ -408,7 +410,7 @@ 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);
> > > +       sun4i_tcon0_mode_set_common(tcon, mode, 1);
> > >
> > >         /* Set dithering if needed */
> > >         sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
> > > @@ -487,7 +489,7 @@ static void sun4i_tcon0_mode_set_rgb(struct
> > > sun4i_tcon *tcon,
> > >
> > >         tcon->dclk_min_div = 6;
> > >         tcon->dclk_max_div = 127;
> > > -       sun4i_tcon0_mode_set_common(tcon, mode);
> > > +       sun4i_tcon0_mode_set_common(tcon, mode, 1);
> > >
> > >         /* Set dithering if needed */
> > >         sun4i_tcon0_mode_set_dithering(tcon, connector);
> > > diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > index 5c3ad5be0690..a07090579f84 100644
> > > --- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > +++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > @@ -13,8 +13,6 @@
> > >  #include <drm/drm_encoder.h>
> > >  #include <drm/drm_mipi_dsi.h>
> > >
> > > -#define SUN6I_DSI_TCON_DIV     4
> > > -
> > >  struct sun6i_dsi {
> > >         struct drm_connector    connector;
> > >         struct drm_encoder      encoder;
> >
> > I had more something like this in mind:
> > http://code.bulix.org/nlp5a4-803511
>
> Worth to look at it. was it working on your panel? meanwhile I will check it.

I haven't tested it.

> We have updated with below change [1], seems working on but is
> actually checking the each divider as before start with 4... till 127.
>
> This new approach, is start looking the best divider from 4.. based on
> the idea vs rounded it will ended up best divider like [2]

But why?

I mean, it's not like it's the first time I'm asking this...

If the issue is what Micheal described, then the divider has nothing
to do with it. We've had that discussion over and over again.

So you need to come with some argument and proof that the divider of
that clock need to change. Otherwise, stop trying to make that happen:
it won't.

Maxime

--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
Michael Nazzareno Trimarchi July 20, 2019, 9:42 a.m. UTC | #26
Hi

On Sat, Jul 20, 2019 at 11:32 AM Maxime Ripard
<maxime.ripard@bootlin.com> wrote:
>
> On Sat, Jul 20, 2019 at 12:46:27PM +0530, Jagan Teki wrote:
> > On Sat, Jul 20, 2019 at 12:28 PM Maxime Ripard
> > <maxime.ripard@bootlin.com> wrote:
> > >
> > > On Thu, Jul 11, 2019 at 07:43:16PM +0200, Michael Nazzareno Trimarchi wrote:
> > > > > > tcon-pixel clock is the rate that you want to achive on display side
> > > > > > and if you have 4 lanes 32bit or lanes and different bit number that
> > > > > > you need to have a clock that is able to put outside bits and speed
> > > > > > equal to pixel-clock * bits / lanes. so If you want a pixel-clock of
> > > > > > 40 mhz and you have 32bits and 4 lanes you need to have a clock of
> > > > > > 40 * 32 / 4 in no-burst mode. I think that this is done but most of
> > > > > > the display.
> > > > >
> > > > > So this is what the issue is then?
> > > > >
> > > > > This one does make sense, and you should just change the rate in the
> > > > > call to clk_set_rate in sun4i_tcon0_mode_set_cpu.
> > > > >
> > > > > I'm still wondering why that hasn't been brought up in either the
> > > > > discussion or the commit log before though.
> > > > >
> > > > Something like this?
> > > >
> > > > drivers/gpu/drm/sun4i/sun4i_tcon.c     | 20 +++++++++++---------
> > > >  drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h |  2 --
> > > >  2 files changed, 11 insertions(+), 11 deletions(-)
> > > >
> > > > diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > index 64c43ee6bd92..42560d5c327c 100644
> > > > --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > @@ -263,10 +263,11 @@ static int sun4i_tcon_get_clk_delay(const struct
> > > > drm_display_mode *mode,
> > > >  }
> > > >
> > > >  static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
> > > > -                                       const struct drm_display_mode *mode)
> > > > +                                       const struct drm_display_mode *mode,
> > > > +                                       u32 tcon_mul)
> > > >  {
> > > >         /* Configure the dot clock */
> > > > -       clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
> > > > +       clk_set_rate(tcon->dclk, mode->crtc_clock * tcon_mul * 1000);
> > > >
> > > >         /* Set the resolution */
> > > >         regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
> > > > @@ -335,12 +336,13 @@ 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;
> > > > +       u32 tcon_div, tcon_mul;
> > > >
> > > > -       tcon->dclk_min_div = SUN6I_DSI_TCON_DIV;
> > > > -       tcon->dclk_max_div = SUN6I_DSI_TCON_DIV;
> > > > +       tcon->dclk_min_div = 4;
> > > > +       tcon->dclk_max_div = 127;
> > > >
> > > > -       sun4i_tcon0_mode_set_common(tcon, mode);
> > > > +       tcon_mul = bpp / lanes;
> > > > +       sun4i_tcon0_mode_set_common(tcon, mode, tcon_mul);
> > > >
> > > >         /* Set dithering if needed */
> > > >         sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
> > > > @@ -366,7 +368,7 @@ static void sun4i_tcon0_mode_set_cpu(struct
> > > > sun4i_tcon *tcon,
> > > >          */
> > > >         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 * tcon_div * tcon_mul;
> > > >         block_space -= mode->hdisplay + 40;
> > > >
> > > >         regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI0_REG,
> > > > @@ -408,7 +410,7 @@ 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);
> > > > +       sun4i_tcon0_mode_set_common(tcon, mode, 1);
> > > >
> > > >         /* Set dithering if needed */
> > > >         sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
> > > > @@ -487,7 +489,7 @@ static void sun4i_tcon0_mode_set_rgb(struct
> > > > sun4i_tcon *tcon,
> > > >
> > > >         tcon->dclk_min_div = 6;
> > > >         tcon->dclk_max_div = 127;
> > > > -       sun4i_tcon0_mode_set_common(tcon, mode);
> > > > +       sun4i_tcon0_mode_set_common(tcon, mode, 1);
> > > >
> > > >         /* Set dithering if needed */
> > > >         sun4i_tcon0_mode_set_dithering(tcon, connector);
> > > > diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > index 5c3ad5be0690..a07090579f84 100644
> > > > --- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > +++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > @@ -13,8 +13,6 @@
> > > >  #include <drm/drm_encoder.h>
> > > >  #include <drm/drm_mipi_dsi.h>
> > > >
> > > > -#define SUN6I_DSI_TCON_DIV     4
> > > > -
> > > >  struct sun6i_dsi {
> > > >         struct drm_connector    connector;
> > > >         struct drm_encoder      encoder;
> > >
> > > I had more something like this in mind:
> > > http://code.bulix.org/nlp5a4-803511
> >
> > Worth to look at it. was it working on your panel? meanwhile I will check it.
>
> I haven't tested it.
>
> > We have updated with below change [1], seems working on but is
> > actually checking the each divider as before start with 4... till 127.
> >
> > This new approach, is start looking the best divider from 4.. based on
> > the idea vs rounded it will ended up best divider like [2]
>
> But why?
>
> I mean, it's not like it's the first time I'm asking this...
>
> If the issue is what Micheal described, then the divider has nothing
> to do with it. We've had that discussion over and over again.
>

Sorry to quick copy and paste but my idea is somenthing like:

---
 drivers/gpu/drm/sun4i/sun4i_dotclock.c | 5 ++++-
 drivers/gpu/drm/sun4i/sun4i_tcon.c     | 9 ++++++---
 drivers/gpu/drm/sun4i/sun4i_tcon.h     | 1 +
 drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h | 2 --
 4 files changed, 11 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_dotclock.c
b/drivers/gpu/drm/sun4i/sun4i_dotclock.c
index 417ade3d2565..b8be67cbb037 100644
--- a/drivers/gpu/drm/sun4i/sun4i_dotclock.c
+++ b/drivers/gpu/drm/sun4i/sun4i_dotclock.c
@@ -74,12 +74,15 @@ static long sun4i_dclk_round_rate(struct clk_hw
*hw, unsigned long rate,
        struct sun4i_tcon *tcon = dclk->tcon;
        unsigned long best_parent = 0;
        u8 best_div = 1;
+       u64 ideal = (u64)rate * tcon->dclk_mul;
        int i;

        for (i = tcon->dclk_min_div; i <= tcon->dclk_max_div; i++) {
-               u64 ideal = (u64)rate * i;
                unsigned long rounded;

+               if (!tcon->dclk_mul)
+                       ideal = (u64)rate * i;
+
                /*
                 * ideal has overflowed the max value that can be stored in an
                 * unsigned long, and every clk operation we might do on a
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c
b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 64c43ee6bd92..3301952bcf32 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -337,8 +337,9 @@ static void sun4i_tcon0_mode_set_cpu(struct
sun4i_tcon *tcon,
        u32 block_space, start_delay;
        u32 tcon_div;

-       tcon->dclk_min_div = SUN6I_DSI_TCON_DIV;
-       tcon->dclk_max_div = SUN6I_DSI_TCON_DIV;
+       tcon->dclk_min_div = 4;
+       tcon->dclk_max_div = 127;
+       tcon->dclk_mul = bpp / lanes;

        sun4i_tcon0_mode_set_common(tcon, mode);

@@ -366,7 +367,7 @@ static void sun4i_tcon0_mode_set_cpu(struct
sun4i_tcon *tcon,
         */
        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 * tcon_div * tcon->dclk_mul;
        block_space -= mode->hdisplay + 40;

        regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI0_REG,
@@ -408,6 +409,7 @@ static void sun4i_tcon0_mode_set_lvds(struct
sun4i_tcon *tcon,

        tcon->dclk_min_div = 7;
        tcon->dclk_max_div = 7;
+       tcon->dclk_mul = 0;
        sun4i_tcon0_mode_set_common(tcon, mode);

        /* Set dithering if needed */
@@ -487,6 +489,7 @@ static void sun4i_tcon0_mode_set_rgb(struct
sun4i_tcon *tcon,

        tcon->dclk_min_div = 6;
        tcon->dclk_max_div = 127;
+       tcon->dclk_mul = 0;
        sun4i_tcon0_mode_set_common(tcon, mode);

        /* Set dithering if needed */
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h
b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index f9f1fe80b206..44b69533778e 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -248,6 +248,7 @@ struct sun4i_tcon {
        struct clk                      *dclk;
        u8                              dclk_max_div;
        u8                              dclk_min_div;
+       u8                              dclk_mul;

        /* Reset control */
        struct reset_control            *lcd_rst;
diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
index 5c3ad5be0690..a07090579f84 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
@@ -13,8 +13,6 @@
 #include <drm/drm_encoder.h>
 #include <drm/drm_mipi_dsi.h>

-#define SUN6I_DSI_TCON_DIV     4
-
 struct sun6i_dsi {
        struct drm_connector    connector;
        struct drm_encoder      encoder;
Jagan Teki July 22, 2019, 10:21 a.m. UTC | #27
Hi Maxime,

On Sat, Jul 20, 2019 at 3:02 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
>
> On Sat, Jul 20, 2019 at 12:46:27PM +0530, Jagan Teki wrote:
> > On Sat, Jul 20, 2019 at 12:28 PM Maxime Ripard
> > <maxime.ripard@bootlin.com> wrote:
> > >
> > > On Thu, Jul 11, 2019 at 07:43:16PM +0200, Michael Nazzareno Trimarchi wrote:
> > > > > > tcon-pixel clock is the rate that you want to achive on display side
> > > > > > and if you have 4 lanes 32bit or lanes and different bit number that
> > > > > > you need to have a clock that is able to put outside bits and speed
> > > > > > equal to pixel-clock * bits / lanes. so If you want a pixel-clock of
> > > > > > 40 mhz and you have 32bits and 4 lanes you need to have a clock of
> > > > > > 40 * 32 / 4 in no-burst mode. I think that this is done but most of
> > > > > > the display.
> > > > >
> > > > > So this is what the issue is then?
> > > > >
> > > > > This one does make sense, and you should just change the rate in the
> > > > > call to clk_set_rate in sun4i_tcon0_mode_set_cpu.
> > > > >
> > > > > I'm still wondering why that hasn't been brought up in either the
> > > > > discussion or the commit log before though.
> > > > >
> > > > Something like this?
> > > >
> > > > drivers/gpu/drm/sun4i/sun4i_tcon.c     | 20 +++++++++++---------
> > > >  drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h |  2 --
> > > >  2 files changed, 11 insertions(+), 11 deletions(-)
> > > >
> > > > diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > index 64c43ee6bd92..42560d5c327c 100644
> > > > --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > @@ -263,10 +263,11 @@ static int sun4i_tcon_get_clk_delay(const struct
> > > > drm_display_mode *mode,
> > > >  }
> > > >
> > > >  static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
> > > > -                                       const struct drm_display_mode *mode)
> > > > +                                       const struct drm_display_mode *mode,
> > > > +                                       u32 tcon_mul)
> > > >  {
> > > >         /* Configure the dot clock */
> > > > -       clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
> > > > +       clk_set_rate(tcon->dclk, mode->crtc_clock * tcon_mul * 1000);
> > > >
> > > >         /* Set the resolution */
> > > >         regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
> > > > @@ -335,12 +336,13 @@ 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;
> > > > +       u32 tcon_div, tcon_mul;
> > > >
> > > > -       tcon->dclk_min_div = SUN6I_DSI_TCON_DIV;
> > > > -       tcon->dclk_max_div = SUN6I_DSI_TCON_DIV;
> > > > +       tcon->dclk_min_div = 4;
> > > > +       tcon->dclk_max_div = 127;
> > > >
> > > > -       sun4i_tcon0_mode_set_common(tcon, mode);
> > > > +       tcon_mul = bpp / lanes;
> > > > +       sun4i_tcon0_mode_set_common(tcon, mode, tcon_mul);
> > > >
> > > >         /* Set dithering if needed */
> > > >         sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
> > > > @@ -366,7 +368,7 @@ static void sun4i_tcon0_mode_set_cpu(struct
> > > > sun4i_tcon *tcon,
> > > >          */
> > > >         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 * tcon_div * tcon_mul;
> > > >         block_space -= mode->hdisplay + 40;
> > > >
> > > >         regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI0_REG,
> > > > @@ -408,7 +410,7 @@ 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);
> > > > +       sun4i_tcon0_mode_set_common(tcon, mode, 1);
> > > >
> > > >         /* Set dithering if needed */
> > > >         sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
> > > > @@ -487,7 +489,7 @@ static void sun4i_tcon0_mode_set_rgb(struct
> > > > sun4i_tcon *tcon,
> > > >
> > > >         tcon->dclk_min_div = 6;
> > > >         tcon->dclk_max_div = 127;
> > > > -       sun4i_tcon0_mode_set_common(tcon, mode);
> > > > +       sun4i_tcon0_mode_set_common(tcon, mode, 1);
> > > >
> > > >         /* Set dithering if needed */
> > > >         sun4i_tcon0_mode_set_dithering(tcon, connector);
> > > > diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > index 5c3ad5be0690..a07090579f84 100644
> > > > --- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > +++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > @@ -13,8 +13,6 @@
> > > >  #include <drm/drm_encoder.h>
> > > >  #include <drm/drm_mipi_dsi.h>
> > > >
> > > > -#define SUN6I_DSI_TCON_DIV     4
> > > > -
> > > >  struct sun6i_dsi {
> > > >         struct drm_connector    connector;
> > > >         struct drm_encoder      encoder;
> > >
> > > I had more something like this in mind:
> > > http://code.bulix.org/nlp5a4-803511
> >
> > Worth to look at it. was it working on your panel? meanwhile I will check it.
>
> I haven't tested it.
>
> > We have updated with below change [1], seems working on but is
> > actually checking the each divider as before start with 4... till 127.
> >
> > This new approach, is start looking the best divider from 4.. based on
> > the idea vs rounded it will ended up best divider like [2]
>
> But why?
>
> I mean, it's not like it's the first time I'm asking this...
>
> If the issue is what Micheal described, then the divider has nothing
> to do with it. We've had that discussion over and over again.

This is what Michael is mentioned in above mail
"tcon-pixel clock is the rate that you want to achive on display side and
if you have 4 lanes 32bit or lanes and different bit number that you need
to have a clock that is able to put outside bits and speed equal to
pixel-clock * bits / lanes. so If you want a pixel-clock of 40 mhz
and you have 32bits and 4 lanes you need to have a clock of
40 * 32 / 4 in no-burst mode. "

He is trying to manage the bpp/lanes into dclk_mul (in last mail) and
it can multiply with pixel clock which is rate argument in
sun4i_dclk_round_rate.

The solution I have mentioned in dclk_min, max is bpp/lanes also
multiple rate in dotclock sun4i_dclk_round_rate.

In both cases the overall pll_rate depends on dividers, the one that I
have on this patch is based on BSP and the Michael one is more generic
way so-that it can not to touch other functionalities and looping
dividers to find the best one.

If dclk_min/max is bpp/lanes then dotclock directly using divider 6
(assuming 24-bit and 4 lanes) and return the pll_rate and divider 6
associated.

if dclk_mul is bpp/lanes, on Michael new change, the dividers start
with 4 and end with 127 but the constant ideal rate which rate *
bpp/lanes but the loop from sun4i_dclk_round_rate computed the divider
as 6 only, ie what I'm mentioned on the above mail.

Jagan.
Michael Nazzareno Trimarchi July 22, 2019, 10:25 a.m. UTC | #28
Hi Jagan

On Mon, Jul 22, 2019 at 12:21 PM Jagan Teki <jagan@amarulasolutions.com> wrote:
>
> Hi Maxime,
>
> On Sat, Jul 20, 2019 at 3:02 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> >
> > On Sat, Jul 20, 2019 at 12:46:27PM +0530, Jagan Teki wrote:
> > > On Sat, Jul 20, 2019 at 12:28 PM Maxime Ripard
> > > <maxime.ripard@bootlin.com> wrote:
> > > >
> > > > On Thu, Jul 11, 2019 at 07:43:16PM +0200, Michael Nazzareno Trimarchi wrote:
> > > > > > > tcon-pixel clock is the rate that you want to achive on display side
> > > > > > > and if you have 4 lanes 32bit or lanes and different bit number that
> > > > > > > you need to have a clock that is able to put outside bits and speed
> > > > > > > equal to pixel-clock * bits / lanes. so If you want a pixel-clock of
> > > > > > > 40 mhz and you have 32bits and 4 lanes you need to have a clock of
> > > > > > > 40 * 32 / 4 in no-burst mode. I think that this is done but most of
> > > > > > > the display.
> > > > > >
> > > > > > So this is what the issue is then?
> > > > > >
> > > > > > This one does make sense, and you should just change the rate in the
> > > > > > call to clk_set_rate in sun4i_tcon0_mode_set_cpu.
> > > > > >
> > > > > > I'm still wondering why that hasn't been brought up in either the
> > > > > > discussion or the commit log before though.
> > > > > >
> > > > > Something like this?
> > > > >
> > > > > drivers/gpu/drm/sun4i/sun4i_tcon.c     | 20 +++++++++++---------
> > > > >  drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h |  2 --
> > > > >  2 files changed, 11 insertions(+), 11 deletions(-)
> > > > >
> > > > > diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > > b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > > index 64c43ee6bd92..42560d5c327c 100644
> > > > > --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > > +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > > @@ -263,10 +263,11 @@ static int sun4i_tcon_get_clk_delay(const struct
> > > > > drm_display_mode *mode,
> > > > >  }
> > > > >
> > > > >  static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
> > > > > -                                       const struct drm_display_mode *mode)
> > > > > +                                       const struct drm_display_mode *mode,
> > > > > +                                       u32 tcon_mul)
> > > > >  {
> > > > >         /* Configure the dot clock */
> > > > > -       clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
> > > > > +       clk_set_rate(tcon->dclk, mode->crtc_clock * tcon_mul * 1000);
> > > > >
> > > > >         /* Set the resolution */
> > > > >         regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
> > > > > @@ -335,12 +336,13 @@ 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;
> > > > > +       u32 tcon_div, tcon_mul;
> > > > >
> > > > > -       tcon->dclk_min_div = SUN6I_DSI_TCON_DIV;
> > > > > -       tcon->dclk_max_div = SUN6I_DSI_TCON_DIV;
> > > > > +       tcon->dclk_min_div = 4;
> > > > > +       tcon->dclk_max_div = 127;
> > > > >
> > > > > -       sun4i_tcon0_mode_set_common(tcon, mode);
> > > > > +       tcon_mul = bpp / lanes;
> > > > > +       sun4i_tcon0_mode_set_common(tcon, mode, tcon_mul);
> > > > >
> > > > >         /* Set dithering if needed */
> > > > >         sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
> > > > > @@ -366,7 +368,7 @@ static void sun4i_tcon0_mode_set_cpu(struct
> > > > > sun4i_tcon *tcon,
> > > > >          */
> > > > >         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 * tcon_div * tcon_mul;
> > > > >         block_space -= mode->hdisplay + 40;
> > > > >
> > > > >         regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI0_REG,
> > > > > @@ -408,7 +410,7 @@ 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);
> > > > > +       sun4i_tcon0_mode_set_common(tcon, mode, 1);
> > > > >
> > > > >         /* Set dithering if needed */
> > > > >         sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
> > > > > @@ -487,7 +489,7 @@ static void sun4i_tcon0_mode_set_rgb(struct
> > > > > sun4i_tcon *tcon,
> > > > >
> > > > >         tcon->dclk_min_div = 6;
> > > > >         tcon->dclk_max_div = 127;
> > > > > -       sun4i_tcon0_mode_set_common(tcon, mode);
> > > > > +       sun4i_tcon0_mode_set_common(tcon, mode, 1);
> > > > >
> > > > >         /* Set dithering if needed */
> > > > >         sun4i_tcon0_mode_set_dithering(tcon, connector);
> > > > > diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > > b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > > index 5c3ad5be0690..a07090579f84 100644
> > > > > --- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > > +++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > > @@ -13,8 +13,6 @@
> > > > >  #include <drm/drm_encoder.h>
> > > > >  #include <drm/drm_mipi_dsi.h>
> > > > >
> > > > > -#define SUN6I_DSI_TCON_DIV     4
> > > > > -
> > > > >  struct sun6i_dsi {
> > > > >         struct drm_connector    connector;
> > > > >         struct drm_encoder      encoder;
> > > >
> > > > I had more something like this in mind:
> > > > http://code.bulix.org/nlp5a4-803511
> > >
> > > Worth to look at it. was it working on your panel? meanwhile I will check it.
> >
> > I haven't tested it.
> >
> > > We have updated with below change [1], seems working on but is
> > > actually checking the each divider as before start with 4... till 127.
> > >
> > > This new approach, is start looking the best divider from 4.. based on
> > > the idea vs rounded it will ended up best divider like [2]
> >
> > But why?
> >
> > I mean, it's not like it's the first time I'm asking this...
> >
> > If the issue is what Micheal described, then the divider has nothing
> > to do with it. We've had that discussion over and over again.
>
> This is what Michael is mentioned in above mail
> "tcon-pixel clock is the rate that you want to achive on display side and
> if you have 4 lanes 32bit or lanes and different bit number that you need
> to have a clock that is able to put outside bits and speed equal to
> pixel-clock * bits / lanes. so If you want a pixel-clock of 40 mhz
> and you have 32bits and 4 lanes you need to have a clock of
> 40 * 32 / 4 in no-burst mode. "
>
> He is trying to manage the bpp/lanes into dclk_mul (in last mail) and
> it can multiply with pixel clock which is rate argument in
> sun4i_dclk_round_rate.
>
> The solution I have mentioned in dclk_min, max is bpp/lanes also
> multiple rate in dotclock sun4i_dclk_round_rate.
>
> In both cases the overall pll_rate depends on dividers, the one that I
> have on this patch is based on BSP and the Michael one is more generic
> way so-that it can not to touch other functionalities and looping
> dividers to find the best one.
>
> If dclk_min/max is bpp/lanes then dotclock directly using divider 6
> (assuming 24-bit and 4 lanes) and return the pll_rate and divider 6
> associated.
>
> if dclk_mul is bpp/lanes, on Michael new change, the dividers start
> with 4 and end with 127 but the constant ideal rate which rate *
> bpp/lanes but the loop from sun4i_dclk_round_rate computed the divider
> as 6 only, ie what I'm mentioned on the above mail.
>

tcon-pixel clock and tcon are mutual connected. The code is done in a way
that optimal clock need to be search. Now the patch that I propose is more
connected to the description I gave.

I need some comment from Maxime, what he prefers or we need to search for
a different one. I don't had time to check Maxime proposal because I'm working
on other projects.

Michael

> Jagan.
Jagan Teki July 22, 2019, 10:38 a.m. UTC | #29
On Mon, Jul 22, 2019 at 3:55 PM Michael Nazzareno Trimarchi
<michael@amarulasolutions.com> wrote:
>
> Hi Jagan
>
> On Mon, Jul 22, 2019 at 12:21 PM Jagan Teki <jagan@amarulasolutions.com> wrote:
> >
> > Hi Maxime,
> >
> > On Sat, Jul 20, 2019 at 3:02 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > >
> > > On Sat, Jul 20, 2019 at 12:46:27PM +0530, Jagan Teki wrote:
> > > > On Sat, Jul 20, 2019 at 12:28 PM Maxime Ripard
> > > > <maxime.ripard@bootlin.com> wrote:
> > > > >
> > > > > On Thu, Jul 11, 2019 at 07:43:16PM +0200, Michael Nazzareno Trimarchi wrote:
> > > > > > > > tcon-pixel clock is the rate that you want to achive on display side
> > > > > > > > and if you have 4 lanes 32bit or lanes and different bit number that
> > > > > > > > you need to have a clock that is able to put outside bits and speed
> > > > > > > > equal to pixel-clock * bits / lanes. so If you want a pixel-clock of
> > > > > > > > 40 mhz and you have 32bits and 4 lanes you need to have a clock of
> > > > > > > > 40 * 32 / 4 in no-burst mode. I think that this is done but most of
> > > > > > > > the display.
> > > > > > >
> > > > > > > So this is what the issue is then?
> > > > > > >
> > > > > > > This one does make sense, and you should just change the rate in the
> > > > > > > call to clk_set_rate in sun4i_tcon0_mode_set_cpu.
> > > > > > >
> > > > > > > I'm still wondering why that hasn't been brought up in either the
> > > > > > > discussion or the commit log before though.
> > > > > > >
> > > > > > Something like this?
> > > > > >
> > > > > > drivers/gpu/drm/sun4i/sun4i_tcon.c     | 20 +++++++++++---------
> > > > > >  drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h |  2 --
> > > > > >  2 files changed, 11 insertions(+), 11 deletions(-)
> > > > > >
> > > > > > diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > > > b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > > > index 64c43ee6bd92..42560d5c327c 100644
> > > > > > --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > > > +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > > > @@ -263,10 +263,11 @@ static int sun4i_tcon_get_clk_delay(const struct
> > > > > > drm_display_mode *mode,
> > > > > >  }
> > > > > >
> > > > > >  static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
> > > > > > -                                       const struct drm_display_mode *mode)
> > > > > > +                                       const struct drm_display_mode *mode,
> > > > > > +                                       u32 tcon_mul)
> > > > > >  {
> > > > > >         /* Configure the dot clock */
> > > > > > -       clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
> > > > > > +       clk_set_rate(tcon->dclk, mode->crtc_clock * tcon_mul * 1000);
> > > > > >
> > > > > >         /* Set the resolution */
> > > > > >         regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
> > > > > > @@ -335,12 +336,13 @@ 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;
> > > > > > +       u32 tcon_div, tcon_mul;
> > > > > >
> > > > > > -       tcon->dclk_min_div = SUN6I_DSI_TCON_DIV;
> > > > > > -       tcon->dclk_max_div = SUN6I_DSI_TCON_DIV;
> > > > > > +       tcon->dclk_min_div = 4;
> > > > > > +       tcon->dclk_max_div = 127;
> > > > > >
> > > > > > -       sun4i_tcon0_mode_set_common(tcon, mode);
> > > > > > +       tcon_mul = bpp / lanes;
> > > > > > +       sun4i_tcon0_mode_set_common(tcon, mode, tcon_mul);
> > > > > >
> > > > > >         /* Set dithering if needed */
> > > > > >         sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
> > > > > > @@ -366,7 +368,7 @@ static void sun4i_tcon0_mode_set_cpu(struct
> > > > > > sun4i_tcon *tcon,
> > > > > >          */
> > > > > >         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 * tcon_div * tcon_mul;
> > > > > >         block_space -= mode->hdisplay + 40;
> > > > > >
> > > > > >         regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI0_REG,
> > > > > > @@ -408,7 +410,7 @@ 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);
> > > > > > +       sun4i_tcon0_mode_set_common(tcon, mode, 1);
> > > > > >
> > > > > >         /* Set dithering if needed */
> > > > > >         sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
> > > > > > @@ -487,7 +489,7 @@ static void sun4i_tcon0_mode_set_rgb(struct
> > > > > > sun4i_tcon *tcon,
> > > > > >
> > > > > >         tcon->dclk_min_div = 6;
> > > > > >         tcon->dclk_max_div = 127;
> > > > > > -       sun4i_tcon0_mode_set_common(tcon, mode);
> > > > > > +       sun4i_tcon0_mode_set_common(tcon, mode, 1);
> > > > > >
> > > > > >         /* Set dithering if needed */
> > > > > >         sun4i_tcon0_mode_set_dithering(tcon, connector);
> > > > > > diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > > > b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > > > index 5c3ad5be0690..a07090579f84 100644
> > > > > > --- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > > > +++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > > > @@ -13,8 +13,6 @@
> > > > > >  #include <drm/drm_encoder.h>
> > > > > >  #include <drm/drm_mipi_dsi.h>
> > > > > >
> > > > > > -#define SUN6I_DSI_TCON_DIV     4
> > > > > > -
> > > > > >  struct sun6i_dsi {
> > > > > >         struct drm_connector    connector;
> > > > > >         struct drm_encoder      encoder;
> > > > >
> > > > > I had more something like this in mind:
> > > > > http://code.bulix.org/nlp5a4-803511
> > > >
> > > > Worth to look at it. was it working on your panel? meanwhile I will check it.
> > >
> > > I haven't tested it.
> > >
> > > > We have updated with below change [1], seems working on but is
> > > > actually checking the each divider as before start with 4... till 127.
> > > >
> > > > This new approach, is start looking the best divider from 4.. based on
> > > > the idea vs rounded it will ended up best divider like [2]
> > >
> > > But why?
> > >
> > > I mean, it's not like it's the first time I'm asking this...
> > >
> > > If the issue is what Micheal described, then the divider has nothing
> > > to do with it. We've had that discussion over and over again.
> >
> > This is what Michael is mentioned in above mail
> > "tcon-pixel clock is the rate that you want to achive on display side and
> > if you have 4 lanes 32bit or lanes and different bit number that you need
> > to have a clock that is able to put outside bits and speed equal to
> > pixel-clock * bits / lanes. so If you want a pixel-clock of 40 mhz
> > and you have 32bits and 4 lanes you need to have a clock of
> > 40 * 32 / 4 in no-burst mode. "
> >
> > He is trying to manage the bpp/lanes into dclk_mul (in last mail) and
> > it can multiply with pixel clock which is rate argument in
> > sun4i_dclk_round_rate.
> >
> > The solution I have mentioned in dclk_min, max is bpp/lanes also
> > multiple rate in dotclock sun4i_dclk_round_rate.
> >
> > In both cases the overall pll_rate depends on dividers, the one that I
> > have on this patch is based on BSP and the Michael one is more generic
> > way so-that it can not to touch other functionalities and looping
> > dividers to find the best one.
> >
> > If dclk_min/max is bpp/lanes then dotclock directly using divider 6
> > (assuming 24-bit and 4 lanes) and return the pll_rate and divider 6
> > associated.
> >
> > if dclk_mul is bpp/lanes, on Michael new change, the dividers start
> > with 4 and end with 127 but the constant ideal rate which rate *
> > bpp/lanes but the loop from sun4i_dclk_round_rate computed the divider
> > as 6 only, ie what I'm mentioned on the above mail.
> >
>
> tcon-pixel clock and tcon are mutual connected. The code is done in a way
> that optimal clock need to be search. Now the patch that I propose is more
> connected to the description I gave.

True, ie what I'm trying to say in above mail.  My idea on the above
mail is to give more information on the both the solutions (one on the
this patch and another you mentioned on above mail) are depends on
divider value for computing desired pll_rate.

>
> I need some comment from Maxime, what he prefers or we need to search for
> a different one. I don't had time to check Maxime proposal because I'm working
> on other projects.

I already provide my logs on Maxime change.if you want you can have a look.
Maxime Ripard July 24, 2019, 9:05 a.m. UTC | #30
On Mon, Jul 22, 2019 at 03:51:04PM +0530, Jagan Teki wrote:
> Hi Maxime,
>
> On Sat, Jul 20, 2019 at 3:02 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> >
> > On Sat, Jul 20, 2019 at 12:46:27PM +0530, Jagan Teki wrote:
> > > On Sat, Jul 20, 2019 at 12:28 PM Maxime Ripard
> > > <maxime.ripard@bootlin.com> wrote:
> > > >
> > > > On Thu, Jul 11, 2019 at 07:43:16PM +0200, Michael Nazzareno Trimarchi wrote:
> > > > > > > tcon-pixel clock is the rate that you want to achive on display side
> > > > > > > and if you have 4 lanes 32bit or lanes and different bit number that
> > > > > > > you need to have a clock that is able to put outside bits and speed
> > > > > > > equal to pixel-clock * bits / lanes. so If you want a pixel-clock of
> > > > > > > 40 mhz and you have 32bits and 4 lanes you need to have a clock of
> > > > > > > 40 * 32 / 4 in no-burst mode. I think that this is done but most of
> > > > > > > the display.
> > > > > >
> > > > > > So this is what the issue is then?
> > > > > >
> > > > > > This one does make sense, and you should just change the rate in the
> > > > > > call to clk_set_rate in sun4i_tcon0_mode_set_cpu.
> > > > > >
> > > > > > I'm still wondering why that hasn't been brought up in either the
> > > > > > discussion or the commit log before though.
> > > > > >
> > > > > Something like this?
> > > > >
> > > > > drivers/gpu/drm/sun4i/sun4i_tcon.c     | 20 +++++++++++---------
> > > > >  drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h |  2 --
> > > > >  2 files changed, 11 insertions(+), 11 deletions(-)
> > > > >
> > > > > diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > > b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > > index 64c43ee6bd92..42560d5c327c 100644
> > > > > --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > > +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > > @@ -263,10 +263,11 @@ static int sun4i_tcon_get_clk_delay(const struct
> > > > > drm_display_mode *mode,
> > > > >  }
> > > > >
> > > > >  static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
> > > > > -                                       const struct drm_display_mode *mode)
> > > > > +                                       const struct drm_display_mode *mode,
> > > > > +                                       u32 tcon_mul)
> > > > >  {
> > > > >         /* Configure the dot clock */
> > > > > -       clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
> > > > > +       clk_set_rate(tcon->dclk, mode->crtc_clock * tcon_mul * 1000);
> > > > >
> > > > >         /* Set the resolution */
> > > > >         regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
> > > > > @@ -335,12 +336,13 @@ 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;
> > > > > +       u32 tcon_div, tcon_mul;
> > > > >
> > > > > -       tcon->dclk_min_div = SUN6I_DSI_TCON_DIV;
> > > > > -       tcon->dclk_max_div = SUN6I_DSI_TCON_DIV;
> > > > > +       tcon->dclk_min_div = 4;
> > > > > +       tcon->dclk_max_div = 127;
> > > > >
> > > > > -       sun4i_tcon0_mode_set_common(tcon, mode);
> > > > > +       tcon_mul = bpp / lanes;
> > > > > +       sun4i_tcon0_mode_set_common(tcon, mode, tcon_mul);
> > > > >
> > > > >         /* Set dithering if needed */
> > > > >         sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
> > > > > @@ -366,7 +368,7 @@ static void sun4i_tcon0_mode_set_cpu(struct
> > > > > sun4i_tcon *tcon,
> > > > >          */
> > > > >         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 * tcon_div * tcon_mul;
> > > > >         block_space -= mode->hdisplay + 40;
> > > > >
> > > > >         regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI0_REG,
> > > > > @@ -408,7 +410,7 @@ 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);
> > > > > +       sun4i_tcon0_mode_set_common(tcon, mode, 1);
> > > > >
> > > > >         /* Set dithering if needed */
> > > > >         sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
> > > > > @@ -487,7 +489,7 @@ static void sun4i_tcon0_mode_set_rgb(struct
> > > > > sun4i_tcon *tcon,
> > > > >
> > > > >         tcon->dclk_min_div = 6;
> > > > >         tcon->dclk_max_div = 127;
> > > > > -       sun4i_tcon0_mode_set_common(tcon, mode);
> > > > > +       sun4i_tcon0_mode_set_common(tcon, mode, 1);
> > > > >
> > > > >         /* Set dithering if needed */
> > > > >         sun4i_tcon0_mode_set_dithering(tcon, connector);
> > > > > diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > > b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > > index 5c3ad5be0690..a07090579f84 100644
> > > > > --- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > > +++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > > @@ -13,8 +13,6 @@
> > > > >  #include <drm/drm_encoder.h>
> > > > >  #include <drm/drm_mipi_dsi.h>
> > > > >
> > > > > -#define SUN6I_DSI_TCON_DIV     4
> > > > > -
> > > > >  struct sun6i_dsi {
> > > > >         struct drm_connector    connector;
> > > > >         struct drm_encoder      encoder;
> > > >
> > > > I had more something like this in mind:
> > > > http://code.bulix.org/nlp5a4-803511
> > >
> > > Worth to look at it. was it working on your panel? meanwhile I will check it.
> >
> > I haven't tested it.
> >
> > > We have updated with below change [1], seems working on but is
> > > actually checking the each divider as before start with 4... till 127.
> > >
> > > This new approach, is start looking the best divider from 4.. based on
> > > the idea vs rounded it will ended up best divider like [2]
> >
> > But why?
> >
> > I mean, it's not like it's the first time I'm asking this...
> >
> > If the issue is what Micheal described, then the divider has nothing
> > to do with it. We've had that discussion over and over again.
>
> This is what Michael is mentioned in above mail "tcon-pixel clock is
> the rate that you want to achive on display side and if you have 4
> lanes 32bit or lanes and different bit number that you need to have
> a clock that is able to put outside bits and speed equal to
> pixel-clock * bits / lanes. so If you want a pixel-clock of 40 mhz
> and you have 32bits and 4 lanes you need to have a clock of 40 * 32
> / 4 in no-burst mode. "

Yeah, so we need to change the clock rate.

> He is trying to manage the bpp/lanes into dclk_mul (in last mail)
> and it can multiply with pixel clock which is rate argument in
> sun4i_dclk_round_rate.
>
> The solution I have mentioned in dclk_min, max is bpp/lanes also
> multiple rate in dotclock sun4i_dclk_round_rate.
>
> In both cases the overall pll_rate depends on dividers, the one that I
> have on this patch is based on BSP and the Michael one is more generic
> way so-that it can not to touch other functionalities and looping
> dividers to find the best one.
>
> If dclk_min/max is bpp/lanes then dotclock directly using divider 6
> (assuming 24-bit and 4 lanes) and return the pll_rate and divider 6
> associated.
>
> if dclk_mul is bpp/lanes, on Michael new change, the dividers start
> with 4 and end with 127 but the constant ideal rate which rate *
> bpp/lanes but the loop from sun4i_dclk_round_rate computed the divider
> as 6 only, ie what I'm mentioned on the above mail.

We've been over this a couple of times already.

The clock is generated like this:

PLL -> TCON Module Clock -> TCON DCLK

You want the TCON DCLK to be at the pixel clock rate * bpp /
lanes. Fine, that makes sense.

Except that the patch you've sent, instead of changing the rate
itself, changes the ratio between the module clock and DCLK.

And this is where the issue lies. First, from a logical viewpoint, it
doesn't make sense. If you want to change the clock rate, then just do
it. Don't hack around the multipliers trying to fall back to something
that works for you.

Then, the ratio itself needs to be set to 4. This is the part that
we've discussed way too many times already, but in the Allwinner BSP,
that ratio is hardcoded to 4, and we've had panels that need it at
that value.

So, what you want to do is to have:

TCON DCLK = pixel clock * bpp / lanes
TCON Module Clock = DCLK * 4
PLL = Module Clock * Module Clock Divider (which I believe is 1 in most cases)

So you want to increase the PLL. Fortunately for use, this is exactly
what a call to clk_set_rate will end up doing.

Maxime

--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
Michael Nazzareno Trimarchi July 29, 2019, 6:59 a.m. UTC | #31
Hi

On Wed, Jul 24, 2019 at 11:05 AM Maxime Ripard
<maxime.ripard@bootlin.com> wrote:
>
> On Mon, Jul 22, 2019 at 03:51:04PM +0530, Jagan Teki wrote:
> > Hi Maxime,
> >
> > On Sat, Jul 20, 2019 at 3:02 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > >
> > > On Sat, Jul 20, 2019 at 12:46:27PM +0530, Jagan Teki wrote:
> > > > On Sat, Jul 20, 2019 at 12:28 PM Maxime Ripard
> > > > <maxime.ripard@bootlin.com> wrote:
> > > > >
> > > > > On Thu, Jul 11, 2019 at 07:43:16PM +0200, Michael Nazzareno Trimarchi wrote:
> > > > > > > > tcon-pixel clock is the rate that you want to achive on display side
> > > > > > > > and if you have 4 lanes 32bit or lanes and different bit number that
> > > > > > > > you need to have a clock that is able to put outside bits and speed
> > > > > > > > equal to pixel-clock * bits / lanes. so If you want a pixel-clock of
> > > > > > > > 40 mhz and you have 32bits and 4 lanes you need to have a clock of
> > > > > > > > 40 * 32 / 4 in no-burst mode. I think that this is done but most of
> > > > > > > > the display.
> > > > > > >
> > > > > > > So this is what the issue is then?
> > > > > > >
> > > > > > > This one does make sense, and you should just change the rate in the
> > > > > > > call to clk_set_rate in sun4i_tcon0_mode_set_cpu.
> > > > > > >
> > > > > > > I'm still wondering why that hasn't been brought up in either the
> > > > > > > discussion or the commit log before though.
> > > > > > >
> > > > > > Something like this?
> > > > > >
> > > > > > drivers/gpu/drm/sun4i/sun4i_tcon.c     | 20 +++++++++++---------
> > > > > >  drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h |  2 --
> > > > > >  2 files changed, 11 insertions(+), 11 deletions(-)
> > > > > >
> > > > > > diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > > > b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > > > index 64c43ee6bd92..42560d5c327c 100644
> > > > > > --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > > > +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > > > @@ -263,10 +263,11 @@ static int sun4i_tcon_get_clk_delay(const struct
> > > > > > drm_display_mode *mode,
> > > > > >  }
> > > > > >
> > > > > >  static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
> > > > > > -                                       const struct drm_display_mode *mode)
> > > > > > +                                       const struct drm_display_mode *mode,
> > > > > > +                                       u32 tcon_mul)
> > > > > >  {
> > > > > >         /* Configure the dot clock */
> > > > > > -       clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
> > > > > > +       clk_set_rate(tcon->dclk, mode->crtc_clock * tcon_mul * 1000);
> > > > > >
> > > > > >         /* Set the resolution */
> > > > > >         regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
> > > > > > @@ -335,12 +336,13 @@ 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;
> > > > > > +       u32 tcon_div, tcon_mul;
> > > > > >
> > > > > > -       tcon->dclk_min_div = SUN6I_DSI_TCON_DIV;
> > > > > > -       tcon->dclk_max_div = SUN6I_DSI_TCON_DIV;
> > > > > > +       tcon->dclk_min_div = 4;
> > > > > > +       tcon->dclk_max_div = 127;
> > > > > >
> > > > > > -       sun4i_tcon0_mode_set_common(tcon, mode);
> > > > > > +       tcon_mul = bpp / lanes;
> > > > > > +       sun4i_tcon0_mode_set_common(tcon, mode, tcon_mul);
> > > > > >
> > > > > >         /* Set dithering if needed */
> > > > > >         sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
> > > > > > @@ -366,7 +368,7 @@ static void sun4i_tcon0_mode_set_cpu(struct
> > > > > > sun4i_tcon *tcon,
> > > > > >          */
> > > > > >         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 * tcon_div * tcon_mul;
> > > > > >         block_space -= mode->hdisplay + 40;
> > > > > >
> > > > > >         regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI0_REG,
> > > > > > @@ -408,7 +410,7 @@ 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);
> > > > > > +       sun4i_tcon0_mode_set_common(tcon, mode, 1);
> > > > > >
> > > > > >         /* Set dithering if needed */
> > > > > >         sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
> > > > > > @@ -487,7 +489,7 @@ static void sun4i_tcon0_mode_set_rgb(struct
> > > > > > sun4i_tcon *tcon,
> > > > > >
> > > > > >         tcon->dclk_min_div = 6;
> > > > > >         tcon->dclk_max_div = 127;
> > > > > > -       sun4i_tcon0_mode_set_common(tcon, mode);
> > > > > > +       sun4i_tcon0_mode_set_common(tcon, mode, 1);
> > > > > >
> > > > > >         /* Set dithering if needed */
> > > > > >         sun4i_tcon0_mode_set_dithering(tcon, connector);
> > > > > > diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > > > b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > > > index 5c3ad5be0690..a07090579f84 100644
> > > > > > --- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > > > +++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > > > @@ -13,8 +13,6 @@
> > > > > >  #include <drm/drm_encoder.h>
> > > > > >  #include <drm/drm_mipi_dsi.h>
> > > > > >
> > > > > > -#define SUN6I_DSI_TCON_DIV     4
> > > > > > -
> > > > > >  struct sun6i_dsi {
> > > > > >         struct drm_connector    connector;
> > > > > >         struct drm_encoder      encoder;
> > > > >
> > > > > I had more something like this in mind:
> > > > > http://code.bulix.org/nlp5a4-803511
> > > >
> > > > Worth to look at it. was it working on your panel? meanwhile I will check it.
> > >
> > > I haven't tested it.
> > >
> > > > We have updated with below change [1], seems working on but is
> > > > actually checking the each divider as before start with 4... till 127.
> > > >
> > > > This new approach, is start looking the best divider from 4.. based on
> > > > the idea vs rounded it will ended up best divider like [2]
> > >
> > > But why?
> > >
> > > I mean, it's not like it's the first time I'm asking this...
> > >
> > > If the issue is what Micheal described, then the divider has nothing
> > > to do with it. We've had that discussion over and over again.
> >
> > This is what Michael is mentioned in above mail "tcon-pixel clock is
> > the rate that you want to achive on display side and if you have 4
> > lanes 32bit or lanes and different bit number that you need to have
> > a clock that is able to put outside bits and speed equal to
> > pixel-clock * bits / lanes. so If you want a pixel-clock of 40 mhz
> > and you have 32bits and 4 lanes you need to have a clock of 40 * 32
> > / 4 in no-burst mode. "
>
> Yeah, so we need to change the clock rate.
>
> > He is trying to manage the bpp/lanes into dclk_mul (in last mail)
> > and it can multiply with pixel clock which is rate argument in
> > sun4i_dclk_round_rate.
> >
> > The solution I have mentioned in dclk_min, max is bpp/lanes also
> > multiple rate in dotclock sun4i_dclk_round_rate.
> >
> > In both cases the overall pll_rate depends on dividers, the one that I
> > have on this patch is based on BSP and the Michael one is more generic
> > way so-that it can not to touch other functionalities and looping
> > dividers to find the best one.
> >
> > If dclk_min/max is bpp/lanes then dotclock directly using divider 6
> > (assuming 24-bit and 4 lanes) and return the pll_rate and divider 6
> > associated.
> >
> > if dclk_mul is bpp/lanes, on Michael new change, the dividers start
> > with 4 and end with 127 but the constant ideal rate which rate *
> > bpp/lanes but the loop from sun4i_dclk_round_rate computed the divider
> > as 6 only, ie what I'm mentioned on the above mail.
>
> We've been over this a couple of times already.
>
> The clock is generated like this:
>
> PLL -> TCON Module Clock -> TCON DCLK
>
> You want the TCON DCLK to be at the pixel clock rate * bpp /
> lanes. Fine, that makes sense.
>
> Except that the patch you've sent, instead of changing the rate
> itself, changes the ratio between the module clock and DCLK.
>
> And this is where the issue lies. First, from a logical viewpoint, it
> doesn't make sense. If you want to change the clock rate, then just do
> it. Don't hack around the multipliers trying to fall back to something
> that works for you.
>
> Then, the ratio itself needs to be set to 4. This is the part that
> we've discussed way too many times already, but in the Allwinner BSP,
> that ratio is hardcoded to 4, and we've had panels that need it at
> that value.
>
> So, what you want to do is to have:
>
> TCON DCLK = pixel clock * bpp / lanes
> TCON Module Clock = DCLK * 4
> PLL = Module Clock * Module Clock Divider (which I believe is 1 in most cases)

  pll-mipi                       1        1        1   178200000
   0     0  50000
          tcon0                       2        2        1   178200000
        0     0  50000
             tcon-pixel-clock         1        1        1    29700000
        0     0  50000

This is an english problem from my side:
tcon-pixel-clock is DCLK
tcon0 must be tcon-pixel-clock * bpp / lanes because the logic need to
put a bit every cycle.

One solution can be:
- set_rate_exclusive to tcon0 and calculate as display pixel clock *
bpp  / lanes
- calculate the tcon-pixel-clock using all divider

Problem is that the function that calculate tcon-pixel-clock does not
have any constrain on the ideal value. What you are
suggesting is not correct in my opinion or I'm not following your
suggesstion. What I know is that if we have a pixel-clock
of dvi display of 50Mhz and we have 4 lanes 32bit we need a clock in
the logic of 400Mhz (this is the ideal throughtput).
So tcon-pixel-clock is 50mhz and tcon0 is 400Mhz.

Michael


>
> So you want to increase the PLL. Fortunately for use, this is exactly
> what a call to clk_set_rate will end up doing.
>
> Maxime
>
> --
> Maxime Ripard, Bootlin
> Embedded Linux and Kernel engineering
> https://bootlin.com
Michael Nazzareno Trimarchi Aug. 2, 2019, 8:38 a.m. UTC | #32
Hi Maxime

On Mon, Jul 29, 2019 at 8:59 AM Michael Nazzareno Trimarchi
<michael@amarulasolutions.com> wrote:
>
> Hi
>
> On Wed, Jul 24, 2019 at 11:05 AM Maxime Ripard
> <maxime.ripard@bootlin.com> wrote:
> >
> > On Mon, Jul 22, 2019 at 03:51:04PM +0530, Jagan Teki wrote:
> > > Hi Maxime,
> > >
> > > On Sat, Jul 20, 2019 at 3:02 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > > >
> > > > On Sat, Jul 20, 2019 at 12:46:27PM +0530, Jagan Teki wrote:
> > > > > On Sat, Jul 20, 2019 at 12:28 PM Maxime Ripard
> > > > > <maxime.ripard@bootlin.com> wrote:
> > > > > >
> > > > > > On Thu, Jul 11, 2019 at 07:43:16PM +0200, Michael Nazzareno Trimarchi wrote:
> > > > > > > > > tcon-pixel clock is the rate that you want to achive on display side
> > > > > > > > > and if you have 4 lanes 32bit or lanes and different bit number that
> > > > > > > > > you need to have a clock that is able to put outside bits and speed
> > > > > > > > > equal to pixel-clock * bits / lanes. so If you want a pixel-clock of
> > > > > > > > > 40 mhz and you have 32bits and 4 lanes you need to have a clock of
> > > > > > > > > 40 * 32 / 4 in no-burst mode. I think that this is done but most of
> > > > > > > > > the display.
> > > > > > > >
> > > > > > > > So this is what the issue is then?
> > > > > > > >
> > > > > > > > This one does make sense, and you should just change the rate in the
> > > > > > > > call to clk_set_rate in sun4i_tcon0_mode_set_cpu.
> > > > > > > >
> > > > > > > > I'm still wondering why that hasn't been brought up in either the
> > > > > > > > discussion or the commit log before though.
> > > > > > > >
> > > > > > > Something like this?
> > > > > > >
> > > > > > > drivers/gpu/drm/sun4i/sun4i_tcon.c     | 20 +++++++++++---------
> > > > > > >  drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h |  2 --
> > > > > > >  2 files changed, 11 insertions(+), 11 deletions(-)
> > > > > > >
> > > > > > > diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > > > > b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > > > > index 64c43ee6bd92..42560d5c327c 100644
> > > > > > > --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > > > > +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > > > > @@ -263,10 +263,11 @@ static int sun4i_tcon_get_clk_delay(const struct
> > > > > > > drm_display_mode *mode,
> > > > > > >  }
> > > > > > >
> > > > > > >  static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
> > > > > > > -                                       const struct drm_display_mode *mode)
> > > > > > > +                                       const struct drm_display_mode *mode,
> > > > > > > +                                       u32 tcon_mul)
> > > > > > >  {
> > > > > > >         /* Configure the dot clock */
> > > > > > > -       clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
> > > > > > > +       clk_set_rate(tcon->dclk, mode->crtc_clock * tcon_mul * 1000);
> > > > > > >
> > > > > > >         /* Set the resolution */
> > > > > > >         regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
> > > > > > > @@ -335,12 +336,13 @@ 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;
> > > > > > > +       u32 tcon_div, tcon_mul;
> > > > > > >
> > > > > > > -       tcon->dclk_min_div = SUN6I_DSI_TCON_DIV;
> > > > > > > -       tcon->dclk_max_div = SUN6I_DSI_TCON_DIV;
> > > > > > > +       tcon->dclk_min_div = 4;
> > > > > > > +       tcon->dclk_max_div = 127;
> > > > > > >
> > > > > > > -       sun4i_tcon0_mode_set_common(tcon, mode);
> > > > > > > +       tcon_mul = bpp / lanes;
> > > > > > > +       sun4i_tcon0_mode_set_common(tcon, mode, tcon_mul);
> > > > > > >
> > > > > > >         /* Set dithering if needed */
> > > > > > >         sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
> > > > > > > @@ -366,7 +368,7 @@ static void sun4i_tcon0_mode_set_cpu(struct
> > > > > > > sun4i_tcon *tcon,
> > > > > > >          */
> > > > > > >         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 * tcon_div * tcon_mul;
> > > > > > >         block_space -= mode->hdisplay + 40;
> > > > > > >
> > > > > > >         regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI0_REG,
> > > > > > > @@ -408,7 +410,7 @@ 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);
> > > > > > > +       sun4i_tcon0_mode_set_common(tcon, mode, 1);
> > > > > > >
> > > > > > >         /* Set dithering if needed */
> > > > > > >         sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
> > > > > > > @@ -487,7 +489,7 @@ static void sun4i_tcon0_mode_set_rgb(struct
> > > > > > > sun4i_tcon *tcon,
> > > > > > >
> > > > > > >         tcon->dclk_min_div = 6;
> > > > > > >         tcon->dclk_max_div = 127;
> > > > > > > -       sun4i_tcon0_mode_set_common(tcon, mode);
> > > > > > > +       sun4i_tcon0_mode_set_common(tcon, mode, 1);
> > > > > > >
> > > > > > >         /* Set dithering if needed */
> > > > > > >         sun4i_tcon0_mode_set_dithering(tcon, connector);
> > > > > > > diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > > > > b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > > > > index 5c3ad5be0690..a07090579f84 100644
> > > > > > > --- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > > > > +++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > > > > @@ -13,8 +13,6 @@
> > > > > > >  #include <drm/drm_encoder.h>
> > > > > > >  #include <drm/drm_mipi_dsi.h>
> > > > > > >
> > > > > > > -#define SUN6I_DSI_TCON_DIV     4
> > > > > > > -
> > > > > > >  struct sun6i_dsi {
> > > > > > >         struct drm_connector    connector;
> > > > > > >         struct drm_encoder      encoder;
> > > > > >
> > > > > > I had more something like this in mind:
> > > > > > http://code.bulix.org/nlp5a4-803511
> > > > >
> > > > > Worth to look at it. was it working on your panel? meanwhile I will check it.
> > > >
> > > > I haven't tested it.
> > > >
> > > > > We have updated with below change [1], seems working on but is
> > > > > actually checking the each divider as before start with 4... till 127.
> > > > >
> > > > > This new approach, is start looking the best divider from 4.. based on
> > > > > the idea vs rounded it will ended up best divider like [2]
> > > >
> > > > But why?
> > > >
> > > > I mean, it's not like it's the first time I'm asking this...
> > > >
> > > > If the issue is what Micheal described, then the divider has nothing
> > > > to do with it. We've had that discussion over and over again.
> > >
> > > This is what Michael is mentioned in above mail "tcon-pixel clock is
> > > the rate that you want to achive on display side and if you have 4
> > > lanes 32bit or lanes and different bit number that you need to have
> > > a clock that is able to put outside bits and speed equal to
> > > pixel-clock * bits / lanes. so If you want a pixel-clock of 40 mhz
> > > and you have 32bits and 4 lanes you need to have a clock of 40 * 32
> > > / 4 in no-burst mode. "
> >
> > Yeah, so we need to change the clock rate.
> >
> > > He is trying to manage the bpp/lanes into dclk_mul (in last mail)
> > > and it can multiply with pixel clock which is rate argument in
> > > sun4i_dclk_round_rate.
> > >
> > > The solution I have mentioned in dclk_min, max is bpp/lanes also
> > > multiple rate in dotclock sun4i_dclk_round_rate.
> > >
> > > In both cases the overall pll_rate depends on dividers, the one that I
> > > have on this patch is based on BSP and the Michael one is more generic
> > > way so-that it can not to touch other functionalities and looping
> > > dividers to find the best one.
> > >
> > > If dclk_min/max is bpp/lanes then dotclock directly using divider 6
> > > (assuming 24-bit and 4 lanes) and return the pll_rate and divider 6
> > > associated.
> > >
> > > if dclk_mul is bpp/lanes, on Michael new change, the dividers start
> > > with 4 and end with 127 but the constant ideal rate which rate *
> > > bpp/lanes but the loop from sun4i_dclk_round_rate computed the divider
> > > as 6 only, ie what I'm mentioned on the above mail.
> >
> > We've been over this a couple of times already.
> >
> > The clock is generated like this:
> >
> > PLL -> TCON Module Clock -> TCON DCLK
> >
> > You want the TCON DCLK to be at the pixel clock rate * bpp /
> > lanes. Fine, that makes sense.
> >
> > Except that the patch you've sent, instead of changing the rate
> > itself, changes the ratio between the module clock and DCLK.
> >
> > And this is where the issue lies. First, from a logical viewpoint, it
> > doesn't make sense. If you want to change the clock rate, then just do
> > it. Don't hack around the multipliers trying to fall back to something
> > that works for you.
> >
> > Then, the ratio itself needs to be set to 4. This is the part that
> > we've discussed way too many times already, but in the Allwinner BSP,
> > that ratio is hardcoded to 4, and we've had panels that need it at
> > that value.
> >
> > So, what you want to do is to have:
> >
> > TCON DCLK = pixel clock * bpp / lanes
> > TCON Module Clock = DCLK * 4
> > PLL = Module Clock * Module Clock Divider (which I believe is 1 in most cases)
>
>   pll-mipi                       1        1        1   178200000
>    0     0  50000
>           tcon0                       2        2        1   178200000
>         0     0  50000
>              tcon-pixel-clock         1        1        1    29700000
>         0     0  50000
>
> This is an english problem from my side:
> tcon-pixel-clock is DCLK
> tcon0 must be tcon-pixel-clock * bpp / lanes because the logic need to
> put a bit every cycle.
>
> One solution can be:
> - set_rate_exclusive to tcon0 and calculate as display pixel clock *
> bpp  / lanes
> - calculate the tcon-pixel-clock using all divider
>
> Problem is that the function that calculate tcon-pixel-clock does not
> have any constrain on the ideal value. What you are
> suggesting is not correct in my opinion or I'm not following your
> suggesstion. What I know is that if we have a pixel-clock
> of dvi display of 50Mhz and we have 4 lanes 32bit we need a clock in
> the logic of 400Mhz (this is the ideal throughtput).
> So tcon-pixel-clock is 50mhz and tcon0 is 400Mhz.
>

diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c
b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 94f24c5e2dc5..ffb7906054e5 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -338,8 +338,9 @@ static void sun4i_tcon0_mode_set_cpu(struct
sun4i_tcon *tcon,
u32 block_space, start_delay;
u32 tcon_div;

- tcon->dclk_min_div = bpp/lanes;
- tcon->dclk_max_div = bpp/lanes;
+ tcon->dclk_min_div = 4;
+ tcon->dclk_max_div = 127;
+ clk_set_rate_exclusive(tcon->sclk0, mode->crtc_clock * 1000 * bpp / lanes);

sun4i_tcon0_mode_set_common(tcon, mode);

Something like this on top of jagan proposal

Michael

> Michael
>
>
> >
> > So you want to increase the PLL. Fortunately for use, this is exactly
> > what a call to clk_set_rate will end up doing.
> >
> > Maxime
> >
> > --
> > Maxime Ripard, Bootlin
> > Embedded Linux and Kernel engineering
> > https://bootlin.com
>
>
>
> --
> | Michael Nazzareno Trimarchi                     Amarula Solutions BV |
> | COO  -  Founder                                      Cruquiuskade 47 |
> | +31(0)851119172                                 Amsterdam 1018 AM NL |
> |                  [`as] http://www.amarulasolutions.com               |
Maxime Ripard Aug. 13, 2019, 6:05 a.m. UTC | #33
On Mon, Jul 29, 2019 at 08:59:04AM +0200, Michael Nazzareno Trimarchi wrote:
> Hi
>
> On Wed, Jul 24, 2019 at 11:05 AM Maxime Ripard
> <maxime.ripard@bootlin.com> wrote:
> >
> > On Mon, Jul 22, 2019 at 03:51:04PM +0530, Jagan Teki wrote:
> > > Hi Maxime,
> > >
> > > On Sat, Jul 20, 2019 at 3:02 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > > >
> > > > On Sat, Jul 20, 2019 at 12:46:27PM +0530, Jagan Teki wrote:
> > > > > On Sat, Jul 20, 2019 at 12:28 PM Maxime Ripard
> > > > > <maxime.ripard@bootlin.com> wrote:
> > > > > >
> > > > > > On Thu, Jul 11, 2019 at 07:43:16PM +0200, Michael Nazzareno Trimarchi wrote:
> > > > > > > > > tcon-pixel clock is the rate that you want to achive on display side
> > > > > > > > > and if you have 4 lanes 32bit or lanes and different bit number that
> > > > > > > > > you need to have a clock that is able to put outside bits and speed
> > > > > > > > > equal to pixel-clock * bits / lanes. so If you want a pixel-clock of
> > > > > > > > > 40 mhz and you have 32bits and 4 lanes you need to have a clock of
> > > > > > > > > 40 * 32 / 4 in no-burst mode. I think that this is done but most of
> > > > > > > > > the display.
> > > > > > > >
> > > > > > > > So this is what the issue is then?
> > > > > > > >
> > > > > > > > This one does make sense, and you should just change the rate in the
> > > > > > > > call to clk_set_rate in sun4i_tcon0_mode_set_cpu.
> > > > > > > >
> > > > > > > > I'm still wondering why that hasn't been brought up in either the
> > > > > > > > discussion or the commit log before though.
> > > > > > > >
> > > > > > > Something like this?
> > > > > > >
> > > > > > > drivers/gpu/drm/sun4i/sun4i_tcon.c     | 20 +++++++++++---------
> > > > > > >  drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h |  2 --
> > > > > > >  2 files changed, 11 insertions(+), 11 deletions(-)
> > > > > > >
> > > > > > > diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > > > > b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > > > > index 64c43ee6bd92..42560d5c327c 100644
> > > > > > > --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > > > > +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > > > > @@ -263,10 +263,11 @@ static int sun4i_tcon_get_clk_delay(const struct
> > > > > > > drm_display_mode *mode,
> > > > > > >  }
> > > > > > >
> > > > > > >  static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
> > > > > > > -                                       const struct drm_display_mode *mode)
> > > > > > > +                                       const struct drm_display_mode *mode,
> > > > > > > +                                       u32 tcon_mul)
> > > > > > >  {
> > > > > > >         /* Configure the dot clock */
> > > > > > > -       clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
> > > > > > > +       clk_set_rate(tcon->dclk, mode->crtc_clock * tcon_mul * 1000);
> > > > > > >
> > > > > > >         /* Set the resolution */
> > > > > > >         regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
> > > > > > > @@ -335,12 +336,13 @@ 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;
> > > > > > > +       u32 tcon_div, tcon_mul;
> > > > > > >
> > > > > > > -       tcon->dclk_min_div = SUN6I_DSI_TCON_DIV;
> > > > > > > -       tcon->dclk_max_div = SUN6I_DSI_TCON_DIV;
> > > > > > > +       tcon->dclk_min_div = 4;
> > > > > > > +       tcon->dclk_max_div = 127;
> > > > > > >
> > > > > > > -       sun4i_tcon0_mode_set_common(tcon, mode);
> > > > > > > +       tcon_mul = bpp / lanes;
> > > > > > > +       sun4i_tcon0_mode_set_common(tcon, mode, tcon_mul);
> > > > > > >
> > > > > > >         /* Set dithering if needed */
> > > > > > >         sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
> > > > > > > @@ -366,7 +368,7 @@ static void sun4i_tcon0_mode_set_cpu(struct
> > > > > > > sun4i_tcon *tcon,
> > > > > > >          */
> > > > > > >         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 * tcon_div * tcon_mul;
> > > > > > >         block_space -= mode->hdisplay + 40;
> > > > > > >
> > > > > > >         regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI0_REG,
> > > > > > > @@ -408,7 +410,7 @@ 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);
> > > > > > > +       sun4i_tcon0_mode_set_common(tcon, mode, 1);
> > > > > > >
> > > > > > >         /* Set dithering if needed */
> > > > > > >         sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
> > > > > > > @@ -487,7 +489,7 @@ static void sun4i_tcon0_mode_set_rgb(struct
> > > > > > > sun4i_tcon *tcon,
> > > > > > >
> > > > > > >         tcon->dclk_min_div = 6;
> > > > > > >         tcon->dclk_max_div = 127;
> > > > > > > -       sun4i_tcon0_mode_set_common(tcon, mode);
> > > > > > > +       sun4i_tcon0_mode_set_common(tcon, mode, 1);
> > > > > > >
> > > > > > >         /* Set dithering if needed */
> > > > > > >         sun4i_tcon0_mode_set_dithering(tcon, connector);
> > > > > > > diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > > > > b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > > > > index 5c3ad5be0690..a07090579f84 100644
> > > > > > > --- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > > > > +++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > > > > @@ -13,8 +13,6 @@
> > > > > > >  #include <drm/drm_encoder.h>
> > > > > > >  #include <drm/drm_mipi_dsi.h>
> > > > > > >
> > > > > > > -#define SUN6I_DSI_TCON_DIV     4
> > > > > > > -
> > > > > > >  struct sun6i_dsi {
> > > > > > >         struct drm_connector    connector;
> > > > > > >         struct drm_encoder      encoder;
> > > > > >
> > > > > > I had more something like this in mind:
> > > > > > http://code.bulix.org/nlp5a4-803511
> > > > >
> > > > > Worth to look at it. was it working on your panel? meanwhile I will check it.
> > > >
> > > > I haven't tested it.
> > > >
> > > > > We have updated with below change [1], seems working on but is
> > > > > actually checking the each divider as before start with 4... till 127.
> > > > >
> > > > > This new approach, is start looking the best divider from 4.. based on
> > > > > the idea vs rounded it will ended up best divider like [2]
> > > >
> > > > But why?
> > > >
> > > > I mean, it's not like it's the first time I'm asking this...
> > > >
> > > > If the issue is what Micheal described, then the divider has nothing
> > > > to do with it. We've had that discussion over and over again.
> > >
> > > This is what Michael is mentioned in above mail "tcon-pixel clock is
> > > the rate that you want to achive on display side and if you have 4
> > > lanes 32bit or lanes and different bit number that you need to have
> > > a clock that is able to put outside bits and speed equal to
> > > pixel-clock * bits / lanes. so If you want a pixel-clock of 40 mhz
> > > and you have 32bits and 4 lanes you need to have a clock of 40 * 32
> > > / 4 in no-burst mode. "
> >
> > Yeah, so we need to change the clock rate.
> >
> > > He is trying to manage the bpp/lanes into dclk_mul (in last mail)
> > > and it can multiply with pixel clock which is rate argument in
> > > sun4i_dclk_round_rate.
> > >
> > > The solution I have mentioned in dclk_min, max is bpp/lanes also
> > > multiple rate in dotclock sun4i_dclk_round_rate.
> > >
> > > In both cases the overall pll_rate depends on dividers, the one that I
> > > have on this patch is based on BSP and the Michael one is more generic
> > > way so-that it can not to touch other functionalities and looping
> > > dividers to find the best one.
> > >
> > > If dclk_min/max is bpp/lanes then dotclock directly using divider 6
> > > (assuming 24-bit and 4 lanes) and return the pll_rate and divider 6
> > > associated.
> > >
> > > if dclk_mul is bpp/lanes, on Michael new change, the dividers start
> > > with 4 and end with 127 but the constant ideal rate which rate *
> > > bpp/lanes but the loop from sun4i_dclk_round_rate computed the divider
> > > as 6 only, ie what I'm mentioned on the above mail.
> >
> > We've been over this a couple of times already.
> >
> > The clock is generated like this:
> >
> > PLL -> TCON Module Clock -> TCON DCLK
> >
> > You want the TCON DCLK to be at the pixel clock rate * bpp /
> > lanes. Fine, that makes sense.
> >
> > Except that the patch you've sent, instead of changing the rate
> > itself, changes the ratio between the module clock and DCLK.
> >
> > And this is where the issue lies. First, from a logical viewpoint, it
> > doesn't make sense. If you want to change the clock rate, then just do
> > it. Don't hack around the multipliers trying to fall back to something
> > that works for you.
> >
> > Then, the ratio itself needs to be set to 4. This is the part that
> > we've discussed way too many times already, but in the Allwinner BSP,
> > that ratio is hardcoded to 4, and we've had panels that need it at
> > that value.
> >
> > So, what you want to do is to have:
> >
> > TCON DCLK = pixel clock * bpp / lanes
> > TCON Module Clock = DCLK * 4
> > PLL = Module Clock * Module Clock Divider (which I believe is 1 in most cases)
>
>   pll-mipi                       1        1        1   178200000
>    0     0  50000
>           tcon0                       2        2        1   178200000
>         0     0  50000
>              tcon-pixel-clock         1        1        1    29700000
>         0     0  50000

Is this before or after your patches?

> This is an english problem from my side:
> tcon-pixel-clock is DCLK
> tcon0 must be tcon-pixel-clock * bpp / lanes, because the logic need to
> put a bit every cycle.

Again, I'm not saying this is wrong, but each time I've looked at it
the BSP was using a 4 divider between the tcon module clock and the
dotclock.

So, please prove me wrong here.

> One solution can be:
> - set_rate_exclusive to tcon0 and calculate as display pixel clock *
> bpp  / lanes

I'm not sure what set_rate_exclusive has to do with it. I mean, it's a
good idea to use it, but it shouldn't really change anything to the
discussion.

> - calculate the tcon-pixel-clock using all divider

I'm not sure what you mean by that.

> Problem is that the function that calculate tcon-pixel-clock does not
> have any constrain on the ideal value.

It does have constraints, but you're right that it will not try to
find an exact match and bail out if it can't do it, but will find the
closest match.

> What you are suggesting is not correct in my opinion or I'm not
> following your suggesstion.

Then prove me wrong.

> What I know is that if we have a pixel-clock of dvi display of 50Mhz
> and we have 4 lanes 32bit we need a clock in the logic of 400Mhz
> (this is the ideal throughtput).
> So tcon-pixel-clock is 50mhz and tcon0 is 400Mhz.

There's one thing to keep in mind though. The TCON dotclock in the
MIPI-DSI case isn't directly tied to the Bit Clock, it's simply an
internal clock in the pipeline to feed the FIFO of the MIPI-DSI
controller. The MIPI-DSI controller itself will generate that clock,
and only that one will have those constraints.

Maxime

--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
Michael Nazzareno Trimarchi Aug. 15, 2019, 12:25 p.m. UTC | #34
Hi Maxime

On Tue, Aug 13, 2019 at 8:05 AM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
>
> On Mon, Jul 29, 2019 at 08:59:04AM +0200, Michael Nazzareno Trimarchi wrote:
> > Hi
> >
> > On Wed, Jul 24, 2019 at 11:05 AM Maxime Ripard
> > <maxime.ripard@bootlin.com> wrote:
> > >
> > > On Mon, Jul 22, 2019 at 03:51:04PM +0530, Jagan Teki wrote:
> > > > Hi Maxime,
> > > >
> > > > On Sat, Jul 20, 2019 at 3:02 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > > > >
> > > > > On Sat, Jul 20, 2019 at 12:46:27PM +0530, Jagan Teki wrote:
> > > > > > On Sat, Jul 20, 2019 at 12:28 PM Maxime Ripard
> > > > > > <maxime.ripard@bootlin.com> wrote:
> > > > > > >
> > > > > > > On Thu, Jul 11, 2019 at 07:43:16PM +0200, Michael Nazzareno Trimarchi wrote:
> > > > > > > > > > tcon-pixel clock is the rate that you want to achive on display side
> > > > > > > > > > and if you have 4 lanes 32bit or lanes and different bit number that
> > > > > > > > > > you need to have a clock that is able to put outside bits and speed
> > > > > > > > > > equal to pixel-clock * bits / lanes. so If you want a pixel-clock of
> > > > > > > > > > 40 mhz and you have 32bits and 4 lanes you need to have a clock of
> > > > > > > > > > 40 * 32 / 4 in no-burst mode. I think that this is done but most of
> > > > > > > > > > the display.
> > > > > > > > >
> > > > > > > > > So this is what the issue is then?
> > > > > > > > >
> > > > > > > > > This one does make sense, and you should just change the rate in the
> > > > > > > > > call to clk_set_rate in sun4i_tcon0_mode_set_cpu.
> > > > > > > > >
> > > > > > > > > I'm still wondering why that hasn't been brought up in either the
> > > > > > > > > discussion or the commit log before though.
> > > > > > > > >
> > > > > > > > Something like this?
> > > > > > > >
> > > > > > > > drivers/gpu/drm/sun4i/sun4i_tcon.c     | 20 +++++++++++---------
> > > > > > > >  drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h |  2 --
> > > > > > > >  2 files changed, 11 insertions(+), 11 deletions(-)
> > > > > > > >
> > > > > > > > diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > > > > > b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > > > > > index 64c43ee6bd92..42560d5c327c 100644
> > > > > > > > --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > > > > > +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > > > > > @@ -263,10 +263,11 @@ static int sun4i_tcon_get_clk_delay(const struct
> > > > > > > > drm_display_mode *mode,
> > > > > > > >  }
> > > > > > > >
> > > > > > > >  static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
> > > > > > > > -                                       const struct drm_display_mode *mode)
> > > > > > > > +                                       const struct drm_display_mode *mode,
> > > > > > > > +                                       u32 tcon_mul)
> > > > > > > >  {
> > > > > > > >         /* Configure the dot clock */
> > > > > > > > -       clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
> > > > > > > > +       clk_set_rate(tcon->dclk, mode->crtc_clock * tcon_mul * 1000);
> > > > > > > >
> > > > > > > >         /* Set the resolution */
> > > > > > > >         regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
> > > > > > > > @@ -335,12 +336,13 @@ 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;
> > > > > > > > +       u32 tcon_div, tcon_mul;
> > > > > > > >
> > > > > > > > -       tcon->dclk_min_div = SUN6I_DSI_TCON_DIV;
> > > > > > > > -       tcon->dclk_max_div = SUN6I_DSI_TCON_DIV;
> > > > > > > > +       tcon->dclk_min_div = 4;
> > > > > > > > +       tcon->dclk_max_div = 127;
> > > > > > > >
> > > > > > > > -       sun4i_tcon0_mode_set_common(tcon, mode);
> > > > > > > > +       tcon_mul = bpp / lanes;
> > > > > > > > +       sun4i_tcon0_mode_set_common(tcon, mode, tcon_mul);
> > > > > > > >
> > > > > > > >         /* Set dithering if needed */
> > > > > > > >         sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
> > > > > > > > @@ -366,7 +368,7 @@ static void sun4i_tcon0_mode_set_cpu(struct
> > > > > > > > sun4i_tcon *tcon,
> > > > > > > >          */
> > > > > > > >         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 * tcon_div * tcon_mul;
> > > > > > > >         block_space -= mode->hdisplay + 40;
> > > > > > > >
> > > > > > > >         regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI0_REG,
> > > > > > > > @@ -408,7 +410,7 @@ 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);
> > > > > > > > +       sun4i_tcon0_mode_set_common(tcon, mode, 1);
> > > > > > > >
> > > > > > > >         /* Set dithering if needed */
> > > > > > > >         sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
> > > > > > > > @@ -487,7 +489,7 @@ static void sun4i_tcon0_mode_set_rgb(struct
> > > > > > > > sun4i_tcon *tcon,
> > > > > > > >
> > > > > > > >         tcon->dclk_min_div = 6;
> > > > > > > >         tcon->dclk_max_div = 127;
> > > > > > > > -       sun4i_tcon0_mode_set_common(tcon, mode);
> > > > > > > > +       sun4i_tcon0_mode_set_common(tcon, mode, 1);
> > > > > > > >
> > > > > > > >         /* Set dithering if needed */
> > > > > > > >         sun4i_tcon0_mode_set_dithering(tcon, connector);
> > > > > > > > diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > > > > > b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > > > > > index 5c3ad5be0690..a07090579f84 100644
> > > > > > > > --- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > > > > > +++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > > > > > @@ -13,8 +13,6 @@
> > > > > > > >  #include <drm/drm_encoder.h>
> > > > > > > >  #include <drm/drm_mipi_dsi.h>
> > > > > > > >
> > > > > > > > -#define SUN6I_DSI_TCON_DIV     4
> > > > > > > > -
> > > > > > > >  struct sun6i_dsi {
> > > > > > > >         struct drm_connector    connector;
> > > > > > > >         struct drm_encoder      encoder;
> > > > > > >
> > > > > > > I had more something like this in mind:
> > > > > > > http://code.bulix.org/nlp5a4-803511
> > > > > >
> > > > > > Worth to look at it. was it working on your panel? meanwhile I will check it.
> > > > >
> > > > > I haven't tested it.
> > > > >
> > > > > > We have updated with below change [1], seems working on but is
> > > > > > actually checking the each divider as before start with 4... till 127.
> > > > > >
> > > > > > This new approach, is start looking the best divider from 4.. based on
> > > > > > the idea vs rounded it will ended up best divider like [2]
> > > > >
> > > > > But why?
> > > > >
> > > > > I mean, it's not like it's the first time I'm asking this...
> > > > >
> > > > > If the issue is what Micheal described, then the divider has nothing
> > > > > to do with it. We've had that discussion over and over again.
> > > >
> > > > This is what Michael is mentioned in above mail "tcon-pixel clock is
> > > > the rate that you want to achive on display side and if you have 4
> > > > lanes 32bit or lanes and different bit number that you need to have
> > > > a clock that is able to put outside bits and speed equal to
> > > > pixel-clock * bits / lanes. so If you want a pixel-clock of 40 mhz
> > > > and you have 32bits and 4 lanes you need to have a clock of 40 * 32
> > > > / 4 in no-burst mode. "
> > >
> > > Yeah, so we need to change the clock rate.
> > >
> > > > He is trying to manage the bpp/lanes into dclk_mul (in last mail)
> > > > and it can multiply with pixel clock which is rate argument in
> > > > sun4i_dclk_round_rate.
> > > >
> > > > The solution I have mentioned in dclk_min, max is bpp/lanes also
> > > > multiple rate in dotclock sun4i_dclk_round_rate.
> > > >
> > > > In both cases the overall pll_rate depends on dividers, the one that I
> > > > have on this patch is based on BSP and the Michael one is more generic
> > > > way so-that it can not to touch other functionalities and looping
> > > > dividers to find the best one.
> > > >
> > > > If dclk_min/max is bpp/lanes then dotclock directly using divider 6
> > > > (assuming 24-bit and 4 lanes) and return the pll_rate and divider 6
> > > > associated.
> > > >
> > > > if dclk_mul is bpp/lanes, on Michael new change, the dividers start
> > > > with 4 and end with 127 but the constant ideal rate which rate *
> > > > bpp/lanes but the loop from sun4i_dclk_round_rate computed the divider
> > > > as 6 only, ie what I'm mentioned on the above mail.
> > >
> > > We've been over this a couple of times already.
> > >
> > > The clock is generated like this:
> > >
> > > PLL -> TCON Module Clock -> TCON DCLK
> > >
> > > You want the TCON DCLK to be at the pixel clock rate * bpp /
> > > lanes. Fine, that makes sense.
> > >
> > > Except that the patch you've sent, instead of changing the rate
> > > itself, changes the ratio between the module clock and DCLK.
> > >
> > > And this is where the issue lies. First, from a logical viewpoint, it
> > > doesn't make sense. If you want to change the clock rate, then just do
> > > it. Don't hack around the multipliers trying to fall back to something
> > > that works for you.
> > >
> > > Then, the ratio itself needs to be set to 4. This is the part that
> > > we've discussed way too many times already, but in the Allwinner BSP,
> > > that ratio is hardcoded to 4, and we've had panels that need it at
> > > that value.
> > >
> > > So, what you want to do is to have:
> > >
> > > TCON DCLK = pixel clock * bpp / lanes
> > > TCON Module Clock = DCLK * 4
> > > PLL = Module Clock * Module Clock Divider (which I believe is 1 in most cases)
> >
> >   pll-mipi                       1        1        1   178200000
> >    0     0  50000
> >           tcon0                       2        2        1   178200000
> >         0     0  50000
> >              tcon-pixel-clock         1        1        1    29700000
> >         0     0  50000
>
> Is this before or after your patches?
>

This is just an example of clock tree to be clear to everyone how they
are connected

> > This is an english problem from my side:
> > tcon-pixel-clock is DCLK
> > tcon0 must be tcon-pixel-clock * bpp / lanes, because the logic need to
> > put a bit every cycle.
>
> Again, I'm not saying this is wrong, but each time I've looked at it
> the BSP was using a 4 divider between the tcon module clock and the
> dotclock.
>

We have tested on 4-5 displays. Well I don't care on bsp but I care
about if it works
and if other SoC has similar approach on clock calculation.

> So, please prove me wrong here.
>

Having only 10 pages of documentation is a bit difficult.

> > One solution can be:
> > - set_rate_exclusive to tcon0 and calculate as display pixel clock *
> > bpp  / lanes
>
> I'm not sure what set_rate_exclusive has to do with it. I mean, it's a
> good idea to use it, but it shouldn't really change anything to the
> discussion.

Well, this will just do a minimal change on source code and put the constrains
to the tcon0

>
> > - calculate the tcon-pixel-clock using all divider
>
> I'm not sure what you mean by that.
>
> > Problem is that the function that calculate tcon-pixel-clock does not
> > have any constrain on the ideal value.
>
> It does have constraints, but you're right that it will not try to
> find an exact match and bail out if it can't do it, but will find the
> closest match.
>

We need to find the closest divider that match the pixel clock and be close
to the ideal tcon0 rate.


> > What you are suggesting is not correct in my opinion or I'm not
> > following your suggesstion.
>
> Then prove me wrong.
>
> > What I know is that if we have a pixel-clock of dvi display of 50Mhz
> > and we have 4 lanes 32bit we need a clock in the logic of 400Mhz
> > (this is the ideal throughtput).
> > So tcon-pixel-clock is 50mhz and tcon0 is 400Mhz.
>
> There's one thing to keep in mind though. The TCON dotclock in the
> MIPI-DSI case isn't directly tied to the Bit Clock, it's simply an
> internal clock in the pipeline to feed the FIFO of the MIPI-DSI
> controller. The MIPI-DSI controller itself will generate that clock,
> and only that one will have those constraints.
>

I have done the same thinking but because it works for us seems that
somehow is used
to internal logic too

Michael

> Maxime
>
> --
> Maxime Ripard, Bootlin
> Embedded Linux and Kernel engineering
> https://bootlin.com
Maxime Ripard Aug. 28, 2019, 1:03 p.m. UTC | #35
Hi,

On Thu, Aug 15, 2019 at 02:25:57PM +0200, Michael Nazzareno Trimarchi wrote:
> On Tue, Aug 13, 2019 at 8:05 AM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > On Mon, Jul 29, 2019 at 08:59:04AM +0200, Michael Nazzareno Trimarchi wrote:
> > > Hi
> > >
> > > On Wed, Jul 24, 2019 at 11:05 AM Maxime Ripard
> > > <maxime.ripard@bootlin.com> wrote:
> > > >
> > > > On Mon, Jul 22, 2019 at 03:51:04PM +0530, Jagan Teki wrote:
> > > > > Hi Maxime,
> > > > >
> > > > > On Sat, Jul 20, 2019 at 3:02 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > > > > >
> > > > > > On Sat, Jul 20, 2019 at 12:46:27PM +0530, Jagan Teki wrote:
> > > > > > > On Sat, Jul 20, 2019 at 12:28 PM Maxime Ripard
> > > > > > > <maxime.ripard@bootlin.com> wrote:
> > > > > > > >
> > > > > > > > On Thu, Jul 11, 2019 at 07:43:16PM +0200, Michael Nazzareno Trimarchi wrote:
> > > > > > > > > > > tcon-pixel clock is the rate that you want to achive on display side
> > > > > > > > > > > and if you have 4 lanes 32bit or lanes and different bit number that
> > > > > > > > > > > you need to have a clock that is able to put outside bits and speed
> > > > > > > > > > > equal to pixel-clock * bits / lanes. so If you want a pixel-clock of
> > > > > > > > > > > 40 mhz and you have 32bits and 4 lanes you need to have a clock of
> > > > > > > > > > > 40 * 32 / 4 in no-burst mode. I think that this is done but most of
> > > > > > > > > > > the display.
> > > > > > > > > >
> > > > > > > > > > So this is what the issue is then?
> > > > > > > > > >
> > > > > > > > > > This one does make sense, and you should just change the rate in the
> > > > > > > > > > call to clk_set_rate in sun4i_tcon0_mode_set_cpu.
> > > > > > > > > >
> > > > > > > > > > I'm still wondering why that hasn't been brought up in either the
> > > > > > > > > > discussion or the commit log before though.
> > > > > > > > > >
> > > > > > > > > Something like this?
> > > > > > > > >
> > > > > > > > > drivers/gpu/drm/sun4i/sun4i_tcon.c     | 20 +++++++++++---------
> > > > > > > > >  drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h |  2 --
> > > > > > > > >  2 files changed, 11 insertions(+), 11 deletions(-)
> > > > > > > > >
> > > > > > > > > diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > > > > > > b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > > > > > > index 64c43ee6bd92..42560d5c327c 100644
> > > > > > > > > --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > > > > > > +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > > > > > > @@ -263,10 +263,11 @@ static int sun4i_tcon_get_clk_delay(const struct
> > > > > > > > > drm_display_mode *mode,
> > > > > > > > >  }
> > > > > > > > >
> > > > > > > > >  static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
> > > > > > > > > -                                       const struct drm_display_mode *mode)
> > > > > > > > > +                                       const struct drm_display_mode *mode,
> > > > > > > > > +                                       u32 tcon_mul)
> > > > > > > > >  {
> > > > > > > > >         /* Configure the dot clock */
> > > > > > > > > -       clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
> > > > > > > > > +       clk_set_rate(tcon->dclk, mode->crtc_clock * tcon_mul * 1000);
> > > > > > > > >
> > > > > > > > >         /* Set the resolution */
> > > > > > > > >         regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
> > > > > > > > > @@ -335,12 +336,13 @@ 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;
> > > > > > > > > +       u32 tcon_div, tcon_mul;
> > > > > > > > >
> > > > > > > > > -       tcon->dclk_min_div = SUN6I_DSI_TCON_DIV;
> > > > > > > > > -       tcon->dclk_max_div = SUN6I_DSI_TCON_DIV;
> > > > > > > > > +       tcon->dclk_min_div = 4;
> > > > > > > > > +       tcon->dclk_max_div = 127;
> > > > > > > > >
> > > > > > > > > -       sun4i_tcon0_mode_set_common(tcon, mode);
> > > > > > > > > +       tcon_mul = bpp / lanes;
> > > > > > > > > +       sun4i_tcon0_mode_set_common(tcon, mode, tcon_mul);
> > > > > > > > >
> > > > > > > > >         /* Set dithering if needed */
> > > > > > > > >         sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
> > > > > > > > > @@ -366,7 +368,7 @@ static void sun4i_tcon0_mode_set_cpu(struct
> > > > > > > > > sun4i_tcon *tcon,
> > > > > > > > >          */
> > > > > > > > >         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 * tcon_div * tcon_mul;
> > > > > > > > >         block_space -= mode->hdisplay + 40;
> > > > > > > > >
> > > > > > > > >         regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI0_REG,
> > > > > > > > > @@ -408,7 +410,7 @@ 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);
> > > > > > > > > +       sun4i_tcon0_mode_set_common(tcon, mode, 1);
> > > > > > > > >
> > > > > > > > >         /* Set dithering if needed */
> > > > > > > > >         sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
> > > > > > > > > @@ -487,7 +489,7 @@ static void sun4i_tcon0_mode_set_rgb(struct
> > > > > > > > > sun4i_tcon *tcon,
> > > > > > > > >
> > > > > > > > >         tcon->dclk_min_div = 6;
> > > > > > > > >         tcon->dclk_max_div = 127;
> > > > > > > > > -       sun4i_tcon0_mode_set_common(tcon, mode);
> > > > > > > > > +       sun4i_tcon0_mode_set_common(tcon, mode, 1);
> > > > > > > > >
> > > > > > > > >         /* Set dithering if needed */
> > > > > > > > >         sun4i_tcon0_mode_set_dithering(tcon, connector);
> > > > > > > > > diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > > > > > > b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > > > > > > index 5c3ad5be0690..a07090579f84 100644
> > > > > > > > > --- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > > > > > > +++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > > > > > > @@ -13,8 +13,6 @@
> > > > > > > > >  #include <drm/drm_encoder.h>
> > > > > > > > >  #include <drm/drm_mipi_dsi.h>
> > > > > > > > >
> > > > > > > > > -#define SUN6I_DSI_TCON_DIV     4
> > > > > > > > > -
> > > > > > > > >  struct sun6i_dsi {
> > > > > > > > >         struct drm_connector    connector;
> > > > > > > > >         struct drm_encoder      encoder;
> > > > > > > >
> > > > > > > > I had more something like this in mind:
> > > > > > > > http://code.bulix.org/nlp5a4-803511
> > > > > > >
> > > > > > > Worth to look at it. was it working on your panel? meanwhile I will check it.
> > > > > >
> > > > > > I haven't tested it.
> > > > > >
> > > > > > > We have updated with below change [1], seems working on but is
> > > > > > > actually checking the each divider as before start with 4... till 127.
> > > > > > >
> > > > > > > This new approach, is start looking the best divider from 4.. based on
> > > > > > > the idea vs rounded it will ended up best divider like [2]
> > > > > >
> > > > > > But why?
> > > > > >
> > > > > > I mean, it's not like it's the first time I'm asking this...
> > > > > >
> > > > > > If the issue is what Micheal described, then the divider has nothing
> > > > > > to do with it. We've had that discussion over and over again.
> > > > >
> > > > > This is what Michael is mentioned in above mail "tcon-pixel clock is
> > > > > the rate that you want to achive on display side and if you have 4
> > > > > lanes 32bit or lanes and different bit number that you need to have
> > > > > a clock that is able to put outside bits and speed equal to
> > > > > pixel-clock * bits / lanes. so If you want a pixel-clock of 40 mhz
> > > > > and you have 32bits and 4 lanes you need to have a clock of 40 * 32
> > > > > / 4 in no-burst mode. "
> > > >
> > > > Yeah, so we need to change the clock rate.
> > > >
> > > > > He is trying to manage the bpp/lanes into dclk_mul (in last mail)
> > > > > and it can multiply with pixel clock which is rate argument in
> > > > > sun4i_dclk_round_rate.
> > > > >
> > > > > The solution I have mentioned in dclk_min, max is bpp/lanes also
> > > > > multiple rate in dotclock sun4i_dclk_round_rate.
> > > > >
> > > > > In both cases the overall pll_rate depends on dividers, the one that I
> > > > > have on this patch is based on BSP and the Michael one is more generic
> > > > > way so-that it can not to touch other functionalities and looping
> > > > > dividers to find the best one.
> > > > >
> > > > > If dclk_min/max is bpp/lanes then dotclock directly using divider 6
> > > > > (assuming 24-bit and 4 lanes) and return the pll_rate and divider 6
> > > > > associated.
> > > > >
> > > > > if dclk_mul is bpp/lanes, on Michael new change, the dividers start
> > > > > with 4 and end with 127 but the constant ideal rate which rate *
> > > > > bpp/lanes but the loop from sun4i_dclk_round_rate computed the divider
> > > > > as 6 only, ie what I'm mentioned on the above mail.
> > > >
> > > > We've been over this a couple of times already.
> > > >
> > > > The clock is generated like this:
> > > >
> > > > PLL -> TCON Module Clock -> TCON DCLK
> > > >
> > > > You want the TCON DCLK to be at the pixel clock rate * bpp /
> > > > lanes. Fine, that makes sense.
> > > >
> > > > Except that the patch you've sent, instead of changing the rate
> > > > itself, changes the ratio between the module clock and DCLK.
> > > >
> > > > And this is where the issue lies. First, from a logical viewpoint, it
> > > > doesn't make sense. If you want to change the clock rate, then just do
> > > > it. Don't hack around the multipliers trying to fall back to something
> > > > that works for you.
> > > >
> > > > Then, the ratio itself needs to be set to 4. This is the part that
> > > > we've discussed way too many times already, but in the Allwinner BSP,
> > > > that ratio is hardcoded to 4, and we've had panels that need it at
> > > > that value.
> > > >
> > > > So, what you want to do is to have:
> > > >
> > > > TCON DCLK = pixel clock * bpp / lanes
> > > > TCON Module Clock = DCLK * 4
> > > > PLL = Module Clock * Module Clock Divider (which I believe is 1 in most cases)
> > >
> > >   pll-mipi                       1        1        1   178200000
> > >    0     0  50000
> > >           tcon0                       2        2        1   178200000
> > >         0     0  50000
> > >              tcon-pixel-clock         1        1        1    29700000
> > >         0     0  50000
> >
> > Is this before or after your patches?
> >
>
> This is just an example of clock tree to be clear to everyone how they
> are connected
>
> > > This is an english problem from my side:
> > > tcon-pixel-clock is DCLK
> > > tcon0 must be tcon-pixel-clock * bpp / lanes, because the logic need to
> > > put a bit every cycle.
> >
> > Again, I'm not saying this is wrong, but each time I've looked at it
> > the BSP was using a 4 divider between the tcon module clock and the
> > dotclock.
>
> We have tested on 4-5 displays. Well I don't care on bsp but I care
> about if it works and if other SoC has similar approach on clock
> calculation.

Well, it's also breaking another panel.

> > So, please prove me wrong here.
>
> Having only 10 pages of documentation is a bit difficult.

The BSP source code will be a fine example too.

> > > One solution can be:
> > > - set_rate_exclusive to tcon0 and calculate as display pixel clock *
> > > bpp  / lanes
> >
> > I'm not sure what set_rate_exclusive has to do with it. I mean, it's a
> > good idea to use it, but it shouldn't really change anything to the
> > discussion.
>
> Well, this will just do a minimal change on source code and put the constrains
> to the tcon0

I agree, but again, this has nothing to do with the current discussion.

Maxime

--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
Michael Nazzareno Trimarchi Aug. 28, 2019, 1:09 p.m. UTC | #36
Hi Maxime

On Wed, Aug 28, 2019 at 3:03 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
>
> Hi,
>
> On Thu, Aug 15, 2019 at 02:25:57PM +0200, Michael Nazzareno Trimarchi wrote:
> > On Tue, Aug 13, 2019 at 8:05 AM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > > On Mon, Jul 29, 2019 at 08:59:04AM +0200, Michael Nazzareno Trimarchi wrote:
> > > > Hi
> > > >
> > > > On Wed, Jul 24, 2019 at 11:05 AM Maxime Ripard
> > > > <maxime.ripard@bootlin.com> wrote:
> > > > >
> > > > > On Mon, Jul 22, 2019 at 03:51:04PM +0530, Jagan Teki wrote:
> > > > > > Hi Maxime,
> > > > > >
> > > > > > On Sat, Jul 20, 2019 at 3:02 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > > > > > >
> > > > > > > On Sat, Jul 20, 2019 at 12:46:27PM +0530, Jagan Teki wrote:
> > > > > > > > On Sat, Jul 20, 2019 at 12:28 PM Maxime Ripard
> > > > > > > > <maxime.ripard@bootlin.com> wrote:
> > > > > > > > >
> > > > > > > > > On Thu, Jul 11, 2019 at 07:43:16PM +0200, Michael Nazzareno Trimarchi wrote:
> > > > > > > > > > > > tcon-pixel clock is the rate that you want to achive on display side
> > > > > > > > > > > > and if you have 4 lanes 32bit or lanes and different bit number that
> > > > > > > > > > > > you need to have a clock that is able to put outside bits and speed
> > > > > > > > > > > > equal to pixel-clock * bits / lanes. so If you want a pixel-clock of
> > > > > > > > > > > > 40 mhz and you have 32bits and 4 lanes you need to have a clock of
> > > > > > > > > > > > 40 * 32 / 4 in no-burst mode. I think that this is done but most of
> > > > > > > > > > > > the display.
> > > > > > > > > > >
> > > > > > > > > > > So this is what the issue is then?
> > > > > > > > > > >
> > > > > > > > > > > This one does make sense, and you should just change the rate in the
> > > > > > > > > > > call to clk_set_rate in sun4i_tcon0_mode_set_cpu.
> > > > > > > > > > >
> > > > > > > > > > > I'm still wondering why that hasn't been brought up in either the
> > > > > > > > > > > discussion or the commit log before though.
> > > > > > > > > > >
> > > > > > > > > > Something like this?
> > > > > > > > > >
> > > > > > > > > > drivers/gpu/drm/sun4i/sun4i_tcon.c     | 20 +++++++++++---------
> > > > > > > > > >  drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h |  2 --
> > > > > > > > > >  2 files changed, 11 insertions(+), 11 deletions(-)
> > > > > > > > > >
> > > > > > > > > > diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > > > > > > > b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > > > > > > > index 64c43ee6bd92..42560d5c327c 100644
> > > > > > > > > > --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > > > > > > > +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > > > > > > > > @@ -263,10 +263,11 @@ static int sun4i_tcon_get_clk_delay(const struct
> > > > > > > > > > drm_display_mode *mode,
> > > > > > > > > >  }
> > > > > > > > > >
> > > > > > > > > >  static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
> > > > > > > > > > -                                       const struct drm_display_mode *mode)
> > > > > > > > > > +                                       const struct drm_display_mode *mode,
> > > > > > > > > > +                                       u32 tcon_mul)
> > > > > > > > > >  {
> > > > > > > > > >         /* Configure the dot clock */
> > > > > > > > > > -       clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
> > > > > > > > > > +       clk_set_rate(tcon->dclk, mode->crtc_clock * tcon_mul * 1000);
> > > > > > > > > >
> > > > > > > > > >         /* Set the resolution */
> > > > > > > > > >         regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
> > > > > > > > > > @@ -335,12 +336,13 @@ 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;
> > > > > > > > > > +       u32 tcon_div, tcon_mul;
> > > > > > > > > >
> > > > > > > > > > -       tcon->dclk_min_div = SUN6I_DSI_TCON_DIV;
> > > > > > > > > > -       tcon->dclk_max_div = SUN6I_DSI_TCON_DIV;
> > > > > > > > > > +       tcon->dclk_min_div = 4;
> > > > > > > > > > +       tcon->dclk_max_div = 127;
> > > > > > > > > >
> > > > > > > > > > -       sun4i_tcon0_mode_set_common(tcon, mode);
> > > > > > > > > > +       tcon_mul = bpp / lanes;
> > > > > > > > > > +       sun4i_tcon0_mode_set_common(tcon, mode, tcon_mul);
> > > > > > > > > >
> > > > > > > > > >         /* Set dithering if needed */
> > > > > > > > > >         sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
> > > > > > > > > > @@ -366,7 +368,7 @@ static void sun4i_tcon0_mode_set_cpu(struct
> > > > > > > > > > sun4i_tcon *tcon,
> > > > > > > > > >          */
> > > > > > > > > >         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 * tcon_div * tcon_mul;
> > > > > > > > > >         block_space -= mode->hdisplay + 40;
> > > > > > > > > >
> > > > > > > > > >         regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI0_REG,
> > > > > > > > > > @@ -408,7 +410,7 @@ 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);
> > > > > > > > > > +       sun4i_tcon0_mode_set_common(tcon, mode, 1);
> > > > > > > > > >
> > > > > > > > > >         /* Set dithering if needed */
> > > > > > > > > >         sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
> > > > > > > > > > @@ -487,7 +489,7 @@ static void sun4i_tcon0_mode_set_rgb(struct
> > > > > > > > > > sun4i_tcon *tcon,
> > > > > > > > > >
> > > > > > > > > >         tcon->dclk_min_div = 6;
> > > > > > > > > >         tcon->dclk_max_div = 127;
> > > > > > > > > > -       sun4i_tcon0_mode_set_common(tcon, mode);
> > > > > > > > > > +       sun4i_tcon0_mode_set_common(tcon, mode, 1);
> > > > > > > > > >
> > > > > > > > > >         /* Set dithering if needed */
> > > > > > > > > >         sun4i_tcon0_mode_set_dithering(tcon, connector);
> > > > > > > > > > diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > > > > > > > b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > > > > > > > index 5c3ad5be0690..a07090579f84 100644
> > > > > > > > > > --- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > > > > > > > +++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
> > > > > > > > > > @@ -13,8 +13,6 @@
> > > > > > > > > >  #include <drm/drm_encoder.h>
> > > > > > > > > >  #include <drm/drm_mipi_dsi.h>
> > > > > > > > > >
> > > > > > > > > > -#define SUN6I_DSI_TCON_DIV     4
> > > > > > > > > > -
> > > > > > > > > >  struct sun6i_dsi {
> > > > > > > > > >         struct drm_connector    connector;
> > > > > > > > > >         struct drm_encoder      encoder;
> > > > > > > > >
> > > > > > > > > I had more something like this in mind:
> > > > > > > > > http://code.bulix.org/nlp5a4-803511
> > > > > > > >
> > > > > > > > Worth to look at it. was it working on your panel? meanwhile I will check it.
> > > > > > >
> > > > > > > I haven't tested it.
> > > > > > >
> > > > > > > > We have updated with below change [1], seems working on but is
> > > > > > > > actually checking the each divider as before start with 4... till 127.
> > > > > > > >
> > > > > > > > This new approach, is start looking the best divider from 4.. based on
> > > > > > > > the idea vs rounded it will ended up best divider like [2]
> > > > > > >
> > > > > > > But why?
> > > > > > >
> > > > > > > I mean, it's not like it's the first time I'm asking this...
> > > > > > >
> > > > > > > If the issue is what Micheal described, then the divider has nothing
> > > > > > > to do with it. We've had that discussion over and over again.
> > > > > >
> > > > > > This is what Michael is mentioned in above mail "tcon-pixel clock is
> > > > > > the rate that you want to achive on display side and if you have 4
> > > > > > lanes 32bit or lanes and different bit number that you need to have
> > > > > > a clock that is able to put outside bits and speed equal to
> > > > > > pixel-clock * bits / lanes. so If you want a pixel-clock of 40 mhz
> > > > > > and you have 32bits and 4 lanes you need to have a clock of 40 * 32
> > > > > > / 4 in no-burst mode. "
> > > > >
> > > > > Yeah, so we need to change the clock rate.
> > > > >
> > > > > > He is trying to manage the bpp/lanes into dclk_mul (in last mail)
> > > > > > and it can multiply with pixel clock which is rate argument in
> > > > > > sun4i_dclk_round_rate.
> > > > > >
> > > > > > The solution I have mentioned in dclk_min, max is bpp/lanes also
> > > > > > multiple rate in dotclock sun4i_dclk_round_rate.
> > > > > >
> > > > > > In both cases the overall pll_rate depends on dividers, the one that I
> > > > > > have on this patch is based on BSP and the Michael one is more generic
> > > > > > way so-that it can not to touch other functionalities and looping
> > > > > > dividers to find the best one.
> > > > > >
> > > > > > If dclk_min/max is bpp/lanes then dotclock directly using divider 6
> > > > > > (assuming 24-bit and 4 lanes) and return the pll_rate and divider 6
> > > > > > associated.
> > > > > >
> > > > > > if dclk_mul is bpp/lanes, on Michael new change, the dividers start
> > > > > > with 4 and end with 127 but the constant ideal rate which rate *
> > > > > > bpp/lanes but the loop from sun4i_dclk_round_rate computed the divider
> > > > > > as 6 only, ie what I'm mentioned on the above mail.
> > > > >
> > > > > We've been over this a couple of times already.
> > > > >
> > > > > The clock is generated like this:
> > > > >
> > > > > PLL -> TCON Module Clock -> TCON DCLK
> > > > >
> > > > > You want the TCON DCLK to be at the pixel clock rate * bpp /
> > > > > lanes. Fine, that makes sense.
> > > > >
> > > > > Except that the patch you've sent, instead of changing the rate
> > > > > itself, changes the ratio between the module clock and DCLK.
> > > > >
> > > > > And this is where the issue lies. First, from a logical viewpoint, it
> > > > > doesn't make sense. If you want to change the clock rate, then just do
> > > > > it. Don't hack around the multipliers trying to fall back to something
> > > > > that works for you.
> > > > >
> > > > > Then, the ratio itself needs to be set to 4. This is the part that
> > > > > we've discussed way too many times already, but in the Allwinner BSP,
> > > > > that ratio is hardcoded to 4, and we've had panels that need it at
> > > > > that value.
> > > > >
> > > > > So, what you want to do is to have:
> > > > >
> > > > > TCON DCLK = pixel clock * bpp / lanes
> > > > > TCON Module Clock = DCLK * 4
> > > > > PLL = Module Clock * Module Clock Divider (which I believe is 1 in most cases)
> > > >
> > > >   pll-mipi                       1        1        1   178200000
> > > >    0     0  50000
> > > >           tcon0                       2        2        1   178200000
> > > >         0     0  50000
> > > >              tcon-pixel-clock         1        1        1    29700000
> > > >         0     0  50000
> > >
> > > Is this before or after your patches?
> > >
> >
> > This is just an example of clock tree to be clear to everyone how they
> > are connected
> >
> > > > This is an english problem from my side:
> > > > tcon-pixel-clock is DCLK
> > > > tcon0 must be tcon-pixel-clock * bpp / lanes, because the logic need to
> > > > put a bit every cycle.
> > >
> > > Again, I'm not saying this is wrong, but each time I've looked at it
> > > the BSP was using a 4 divider between the tcon module clock and the
> > > dotclock.
> >
> > We have tested on 4-5 displays. Well I don't care on bsp but I care
> > about if it works and if other SoC has similar approach on clock
> > calculation.
>
> Well, it's also breaking another panel.
>

Agree but I need to have the panel. Do you know if we have users of this panel?
I don't want to break the users off course. Can I have your clk_tree
dbg of your devices
the panel datasheet?

> > > So, please prove me wrong here.
> >
> > Having only 10 pages of documentation is a bit difficult.
>
> The BSP source code will be a fine example too.
>

Do you have any contact in allwinner?

Let's be this last email, I don't want to bother the people more.
After I get the panel
info and datasheet I will come back if I found a solution that does not break it

Michael

> > > > One solution can be:
> > > > - set_rate_exclusive to tcon0 and calculate as display pixel clock *
> > > > bpp  / lanes
> > >
> > > I'm not sure what set_rate_exclusive has to do with it. I mean, it's a
> > > good idea to use it, but it shouldn't really change anything to the
> > > discussion.
> >
> > Well, this will just do a minimal change on source code and put the constrains
> > to the tcon0
>
> I agree, but again, this has nothing to do with the current discussion.
>
> Maxime
>
> --
> Maxime Ripard, Bootlin
> Embedded Linux and Kernel engineering
> https://bootlin.com
diff mbox series

Patch

diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
index 932836d26e2b..296d489aad6e 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
@@ -183,6 +183,7 @@  static struct ccu_nkm pll_mipi_clk = {
 	.n		= _SUNXI_CCU_MULT(8, 4),
 	.k		= _SUNXI_CCU_MULT_MIN(4, 2, 2),
 	.m		= _SUNXI_CCU_DIV(0, 4),
+	.min_rate	= 300000000,
 	.common		= {
 		.reg		= 0x040,
 		.hw.init	= CLK_HW_INIT("pll-mipi", "pll-video0",