[PATCH RFC 0/4] arm64: rockchip: The hunt for exact pixel clocks on RK3576

Alexey Charkov alchark at flipper.net
Wed Apr 22 01:11:21 PDT 2026


Hi Sebastian, Brian, Maxime,

Thanks a lot for your inputs!

On Tue, Apr 21, 2026 at 8:10 PM Maxime Ripard <mripard at kernel.org> wrote:
>
> Hi Brian, Alexey,
>
> On Mon, Apr 20, 2026 at 12:02:58PM -0400, Brian Masney wrote:
> > On Sat, Apr 18, 2026 at 12:24:57AM +0200, Sebastian Reichel wrote:
> > > On Fri, Apr 17, 2026 at 07:11:43PM +0400, Alexey Charkov wrote:
> > > > Dear all,
> > > >
> > > > Need the help of the collective wisdom of the community.
> > > >
> > > > The problem I'm trying to solve is reliably obtaining the exact pixel
> > > > clock for arbitrary display modes supported by the RK3576 SoC.
> > > >
> > > > Rockchip RK3576 has three display output processors VP0~VP2, each
> > > > supporting different ranges of display modes, roughly as follows:
> > > > - VP0: 4K 120Hz
> > > > - VP1: 2.5k 60Hz
> > > > - VP2: 1080p 60Hz
>
> Do any of those have an additional multiplier or divider after the PLL?
>
> I'm asking because 4k at 120Hz is 1188MHz, and 1080p at 60Hz is 148.5 (so 1188
> / 8). 2.5k @ 60 might be a bit more problematic, but my point is that
> for HDMI/DP, most resolutions all have a pixel clock that are multiples
> of 148.5MHz.
>
> If you manage to get the PLL to the highest you need (1188MHz), and then
> apply dividers, you don't need to change the PLL frequency anymore.

Yes, each of them has an (integer-only) divider between the PLL and
the respective mux. The problem though is that displays' EDIDs want
modes that are all over the place and don't seem to converge to any
common numbers generally (it looks like display manufacturers haven't
heard of VESA modes these days).

Following Heiko's nudge from the other sub-thread (thanks for the
pointers Heiko!), I derived the fractional PLL parameters for the
modes which couldn't be obtained cleanly from existing PLL values. It
ended up being 35(!) different rates for just the 7 displays my
colleagues and I could get our hands on, majority of which only
representable with the fractional delta-sigma component. That's after
consolidating the clocks which can be driven from the same
higher-frequency PLL configuration with small integer dividers. Seeing
all of that I couldn't help but think, "Surely those should be
possible to consolidate further by allowing for some error margin!" -
but had to guess again. Even a deviation as small as 0.2% of the
effective clock from the requested rate causes blank screens in my
sample - sometimes less than that.

This further leads me to believe that Brian's rate negotiation series
won't save me here, as the chances of two different displays at two
different weird modes magically agreeing on a PLL rate that is a
common multiple of their respective pixel clocks seem infinitesimal.
And their modes will most likely differ, as VP outputs are asymmetric.
Unless of course everything is 1920x1080 at 60 with a standard 148.5 MHz
pixel clock or its integer multiple - then the problem doesn't exist,
as this particular mode works even in the current configuration on all
VPs.

> > > > Each one obviously needs a pixel clock. The required frequencies for the
> > > > pixel clocks vary greatly depending on the display mode, and need to be
> > > > matched within a tight tolerance, or else many displays will refuse to
> > > > work. E.g. the preferred (maximum) display mode out of VP1 is particularly
> > > > awkward, because it requires a pixel clock of 248.88 MHz, which cannot
> > > > be obtained using integer dividers from its default clock source (GPLL
> > > > at 1188 MHz), and the nearest approximation is 237.6 MHz, which is well
> > > > outside the tolerance of e.g. DP specification, resulting in a blank
> > > > screen on most displays by default.
> > > >
> > > > The clock sources are of course configurable, in particular there are muxes
> > > > connected to each VP for selecting the source of the pixel clock:
> > > > - Each VP can take the clock either from the (single!) HDMI PHY or from
> > > >   its dedicated dclk_vpX_src mux
> > > > - The dclk_vpX_src mux can select the clock from a number of system PLLs
> > > >   (GPLL, CPLL, VPLL, BPLL, LPLL)
> > > >
> > > > While the system PLLs can be configured to output a wide range of
> > > > frequencies, they are shared between many system components. E.g. on the
> > > > current mainline kernel on one of my RK3576 boards I've got the following:
> > > > GPLL: 1188 MHz, enable count 20
> > > > CPLL: 1000 MHz, enable count 17
> > > > VPLL: 594 MHz, enable count 0 (yaay!)
> > > > BPLL, LPLL: 816 MHz, enable count 0 (but these last ones don't have
> > > >             predividers, so are less flexible)
> > > >
> > > > So ultimately there is exactly one free fractional PLL (VPLL) which can be
> > > > used to generate arbitrary pixel clocks, but we have up to three consumers
> > > > trying to drive different display modes from it (e.g. HDMI on VP0, DP on
> > > > VP1 and MIPI DSI on VP2). We also want to be able to adjust the PLL output
> > > > frequency on the fly to satisfy the requirements of the selected display
> > > > mode.
> > > >
> > > > And this is where I'm stuck. Trying to satisfy the requirements of up to
> > > > three consumers while changing the PLL frequency on the fly sounds like
> > > > a poorly tractable mathematical problem (is it 3-SAT?). We can take the
> > > > HDMI output out of the equation, because it can be driven from the HDMI
> > > > PHY (which is capable of arbitrary rates) instead of the mux, but that
> > > > makes the decision of which dclk source to use for a VP block dependent on
> > > > which downstream consumer is connected to it (HDMI vs. something else).
> > >
> > > It becomes more messy: The HDMI PHY cannot be used as clock source
> > > for modes exceeding 4K at 60Hz.

Thanks for the pointer! I've checked, and indeed it automatically
switches to the PHY clock for anything below 600 MHz.

This is in fact a notable improvement, because then only a handful of
higher-rate modes out of my modest sample need a dedicated PLL for the
VP0+HDMI setup: specifically, 3840x2160 at 160 (1478740 kHz),
3840x2160 at 144 (1275830 kHz), 3840x2160 at 119.88 (1186813 kHz - this one
might work with 1188000 if CCF allows returning higher-than-requested
effective rates) and 2560x1440 at 165.08 (645000 kHz).

3840x2160 at 120 can be driven from the current GPLL, as it's exactly 1188 MHz.

The configuration / policy to enable that transparently for the user
seems non-trivial though:
- If the output is HDMI and the display clock is <=600 MHz, always
source it from HDMI PHY (easy)
- Otherwise, if the display clock is 1188 MHz or its integer quotient,
always source it from GPLL, and disallow parent rate changes
- Otherwise, reparent to any active PLL whose current rate is an
integer multiple of the required display clock, and disallow parent
rate changes
- Otherwise, see if VPLL is free. If it is, reparent to it and request
its rate change to the required display clock (or its integer
multiple)
- Otherwise, tell the user the mode set failed (and let them retry
with a different mode, or own the pieces)

I'd love to learn if the above (or anything close) is representable in
the kernel, although I suspect it's not:
- Allowing or disallowing parent rate changes depends on the selected
parent here, while in the current clock implementation it's an
attribute of the child
- All PLLs are equal, but one (VPLL) is more equal than the others by
the virtue of being free more often, and also having the required
delta-sigma component
- Reparenting to an already running PLL if its rate permits should be
preferred to monopolizing the VPLL

> > > > Even then we somehow need two devices to cooperate in picking a PLL
> > > > frequency that satisfies the requirements of both of them, and change to it
> > > > without display corruption. I'm not even sure if the CCF has mechanisms
> > > > for that?..
>
> It's not *just* the CCF though. You will disrupt the other, already
> active display, which might affect the user because the screen will
> blank, throw off the vblank timings and thus userspace, etc.

Indeed. Changing the rate of a PLL while it's in use sounds scary,
even if a solution for the rate exists and can be found in reasonable
time.

> Brian's solution is great progress on that front already, but if you can
> just save yourself the trouble, I'd advise you to do that instead :)

I'd love to, but it seems that displays won't let me :-D

It might be helpful to pre-filter the allowed display modes to only
offer those which can be derived from the currently available PLL
frequencies. The problem is that it makes an extremely limited subset
on real-world displays.

Best regards,
Alexey



More information about the Linux-rockchip mailing list