arch/arm64/boot/dts/rockchip/rk3576.dtsi | 2 ++ drivers/clk/rockchip/clk-pll.c | 16 ++++++++-------- drivers/clk/rockchip/clk-rk3576.c | 4 ++-- 3 files changed, 12 insertions(+), 10 deletions(-)
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
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).
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?..
What follows is a brief set of patches which illustrate a partial solution
for the case of "I just need 2.5k60Hz on VP1 via DP and don't care about
the rest". It switches the VP1 unconditionally to use VPLL as the source
for its dclk mux, allows changing the VPLL frequency on the fly, and also
changes the frequency calculation logic to allow for nearest-match
frequencies which are not necessarily rounded down. These are not meant
to be merged as-is, as I see the following issues:
- The flag allowing the PLL to change rate is in the clock driver, while
the reparenting to an unused PLL is in the device tree. If these go out
of sync, we might end up trying to change the frequency of a PLL which
is used by other consumers (I presume that could be dangerous)
- If VP0 happens to be driving DP output, it won't be able to produce the
2560x1440@60Hz mode for the same reasons as VP1 - then it must also be
reparented to VPLL and allowed to change its frequency on the fly
It does bring me from a state of "always blank screen on DP output until
the mode is switched to something magically working" to a state of
"most monitors work at the default preferred mode" though.
It is tempting to just reparent both VP0 and VP1 to VPLL and allow both of
them to change its frequency, while leaving VP2 on the default (fixed)
GPLL and relying on the fact that 148.5 MHz (the required frequency for
its maximum supported mode of 1920x1080@60Hz) is conveniently 1188/8 MHz -
just what GPLL can provide. Then also force whichever VP is driving HDMI
output to use the HDMI PHY as its clock source. But we still have the
problem of DT vs. driver coordination, and I'm not sure how to define
the policy for "if you've got HDMI connected, you must use the HDMI PHY
clock for the respective VP, whichever VP that is".
I would very much appreciate any thoughts on how to approach this.
Signed-off-by: Alexey Charkov <alchark@flipper.net>
---
Alexey Charkov (4):
arm64: dts: rockchip: rk3576: assign dclk_vp1_src to VPLL
clk: rockchip: pll: use round-nearest in determine_rate
clk: rockchip: rk3576: allow dclk_vp1_src to propagate rate to parent PLL
clk: rockchip: rk3576: add ROUND_CLOSEST to dclk_vp1_src divider
arch/arm64/boot/dts/rockchip/rk3576.dtsi | 2 ++
drivers/clk/rockchip/clk-pll.c | 16 ++++++++--------
drivers/clk/rockchip/clk-rk3576.c | 4 ++--
3 files changed, 12 insertions(+), 10 deletions(-)
---
base-commit: c7275b05bc428c7373d97aa2da02d3a7fa6b9f66
change-id: 20260417-rk3576-dclk-4c95bbb67581
Best regards,
--
Alexey Charkov <alchark@flipper.net>
Hello Alexey, 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 > > 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@60Hz. > 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?.. > > What follows is a brief set of patches which illustrate a partial solution > for the case of "I just need 2.5k60Hz on VP1 via DP and don't care about > the rest". It switches the VP1 unconditionally to use VPLL as the source > for its dclk mux, allows changing the VPLL frequency on the fly, and also > changes the frequency calculation logic to allow for nearest-match > frequencies which are not necessarily rounded down. These are not meant > to be merged as-is, as I see the following issues: > - The flag allowing the PLL to change rate is in the clock driver, while > the reparenting to an unused PLL is in the device tree. If these go out > of sync, we might end up trying to change the frequency of a PLL which > is used by other consumers (I presume that could be dangerous) It is a problem, see e.g. this patch from Heiko removing the flag for an RK3588 VOP source clock: https://lore.kernel.org/linux-rockchip/20251008133135.3745785-1-heiko@sntech.de/ Also note, that there is some more general ongoing work regarding this: See: https://lore.kernel.org/linux-clk/20260327-clk-scaling-v8-0-86cd0aba3c5f@redhat.com/ > - If VP0 happens to be driving DP output, it won't be able to produce the > 2560x1440@60Hz mode for the same reasons as VP1 - then it must also be > reparented to VPLL and allowed to change its frequency on the fly There is also the problem that nearest match might be sensible for the display, but is not generally safe. For other clocks you might effectively overclock, which shouldn't be done by default. > It does bring me from a state of "always blank screen on DP output until > the mode is switched to something magically working" to a state of > "most monitors work at the default preferred mode" though. > > It is tempting to just reparent both VP0 and VP1 to VPLL and allow both of > them to change its frequency, while leaving VP2 on the default (fixed) > GPLL and relying on the fact that 148.5 MHz (the required frequency for > its maximum supported mode of 1920x1080@60Hz) is conveniently 1188/8 MHz - > just what GPLL can provide. Then also force whichever VP is driving HDMI > output to use the HDMI PHY as its clock source. But we still have the > problem of DT vs. driver coordination, and I'm not sure how to define > the policy for "if you've got HDMI connected, you must use the HDMI PHY > clock for the respective VP, whichever VP that is". Sorry, I don't have any complete solutions - except that I can tell you that the VOP2 driver already automatically switches the clock source to the HDMI PHY for HDMI outputs if the pixel rates allows it: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c#n1757 Greetings, -- Sebastian > I would very much appreciate any thoughts on how to approach this. > > Signed-off-by: Alexey Charkov <alchark@flipper.net> > --- > Alexey Charkov (4): > arm64: dts: rockchip: rk3576: assign dclk_vp1_src to VPLL > clk: rockchip: pll: use round-nearest in determine_rate > clk: rockchip: rk3576: allow dclk_vp1_src to propagate rate to parent PLL > clk: rockchip: rk3576: add ROUND_CLOSEST to dclk_vp1_src divider > > arch/arm64/boot/dts/rockchip/rk3576.dtsi | 2 ++ > drivers/clk/rockchip/clk-pll.c | 16 ++++++++-------- > drivers/clk/rockchip/clk-rk3576.c | 4 ++-- > 3 files changed, 12 insertions(+), 10 deletions(-) > --- > base-commit: c7275b05bc428c7373d97aa2da02d3a7fa6b9f66 > change-id: 20260417-rk3576-dclk-4c95bbb67581 > > Best regards, > -- > Alexey Charkov <alchark@flipper.net> >
Hi Alexey,
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
> >
> > 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@60Hz.
>
> > 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?..
> >
> > What follows is a brief set of patches which illustrate a partial solution
> > for the case of "I just need 2.5k60Hz on VP1 via DP and don't care about
> > the rest". It switches the VP1 unconditionally to use VPLL as the source
> > for its dclk mux, allows changing the VPLL frequency on the fly, and also
> > changes the frequency calculation logic to allow for nearest-match
> > frequencies which are not necessarily rounded down. These are not meant
> > to be merged as-is, as I see the following issues:
> > - The flag allowing the PLL to change rate is in the clock driver, while
> > the reparenting to an unused PLL is in the device tree. If these go out
> > of sync, we might end up trying to change the frequency of a PLL which
> > is used by other consumers (I presume that could be dangerous)
>
> It is a problem, see e.g. this patch from Heiko removing the flag
> for an RK3588 VOP source clock:
>
> https://lore.kernel.org/linux-rockchip/20251008133135.3745785-1-heiko@sntech.de/
>
> Also note, that there is some more general ongoing work regarding
> this:
>
> See: https://lore.kernel.org/linux-clk/20260327-clk-scaling-v8-0-86cd0aba3c5f@redhat.com/
I'm working on the patch set above to fix the clk scaling issues. You'll
have issues on clks that have CLK_SET_RATE_PARENT enabled, and there are
multiple children under that parent. Patches 2 and 4 in my series has
kunit tests that demonstrates the current behavior.
I attached a patch to drivers/clk/rockchip/clk-pll.c that adds support
for the v2 rate negotiation logic. You'll need to apply this on top my
clk scaling patch set. I only compile tested this, however it should work
based on the changes that I made to clk-divider.c.
You'll also need to add the flag CLK_V2_RATE_NEGOTIATION to your three
display clks. Otherwise, without the flag, it will just fall back to the
existing behavior.
Hopefully this will let you be able to use one of the PLLs that has a
high enable count as the parent.
Feel free to reach out to me if you have any questions or issues with
my patch set.
Brian
From 66b44d756dba0152b415cc8eb8528b55c4253058 Mon Sep 17 00:00:00 2001
From: Brian Masney <bmasney@redhat.com>
Date: Mon, 20 Apr 2026 11:13:53 -0400
Subject: [PATCH] clk: rockchip: pll: add support for v2 rate negotiation logic
Content-type: text/plain
Signed-off-by: Brian Masney <bmasney@redhat.com>
---
drivers/clk/rockchip/clk-pll.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c
index 6b853800cb6b..30e0722f872f 100644
--- a/drivers/clk/rockchip/clk-pll.c
+++ b/drivers/clk/rockchip/clk-pll.c
@@ -66,8 +66,20 @@ static int rockchip_pll_determine_rate(struct clk_hw *hw,
{
struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
const struct rockchip_pll_rate_table *rate_table = pll->rate_table;
+ struct clk_hw *parent = req->best_parent_hw;
int i;
+ if (parent && (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) &&
+ clk_has_v2_rate_negotiation(parent->core)) {
+ unsigned long lcm_rate;
+
+ lcm_rate = clk_hw_get_children_lcm(parent, hw, req->rate);
+ if (lcm_rate > 0) {
+ lcm_rate = clk_hw_round_rate(parent, lcm_rate);
+ req->best_parent_rate = lcm_rate;
+ }
+ }
+
/* Assuming rate_table is in descending order */
for (i = 0; i < pll->rate_count; i++) {
if (req->rate >= rate_table[i].rate) {
--
2.53.0
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@120Hz is 1188MHz, and 1080p@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. > > > 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@60Hz. > > > > > 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. 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 :) Maxime
Hi Sebastian, Brian, Maxime, Thanks a lot for your inputs! On Tue, Apr 21, 2026 at 8:10 PM Maxime Ripard <mripard@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@120Hz is 1188MHz, and 1080p@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@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@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@160 (1478740 kHz), 3840x2160@144 (1275830 kHz), 3840x2160@119.88 (1186813 kHz - this one might work with 1188000 if CCF allows returning higher-than-requested effective rates) and 2560x1440@165.08 (645000 kHz). 3840x2160@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
© 2016 - 2026 Red Hat, Inc.