* [PATCH] clk: rockchip: rk3588: Allow I2S5 TX and I2S6 RX frac to set parent rate
@ 2026-11-11 22:06 Tim Surber
2026-11-11 22:18 ` Heiko Stübner
0 siblings, 1 reply; 2+ messages in thread
From: Tim Surber @ 2026-11-11 22:06 UTC (permalink / raw)
To: Heiko Stuebner, Stephen Boyd
Cc: Tim Surber, Brian Masney, Jerome Brunet, Elaine Zhang,
Sebastian Reichel, linux-clk, linux-rockchip, linux-arm-kernel,
linux-kernel
All RK3588 audio fractional dividers except clk_i2s5_8ch_tx_frac and
clk_i2s6_8ch_rx_frac are registered with CLK_SET_RATE_PARENT. Without it
the divider cannot raise the rate of its *_src parent again once the
parent has been lowered.
That happens on HDMI0 (i2s5_8ch) after a 192 kHz stream. Its MCLK of
24.576 MHz (128 * fs) is an integer divisor of AUPLL (786.432 MHz / 32),
so the mux selects clk_i2s5_8ch_tx_src directly and sets its divider to
32. For a following 176.4 kHz stream the mux selects the fractional
divider. rockchip_fractional_approximation() sees that the parent is
less than 20 times the requested rate and computes m/n against the
grandparent (AUPLL) rate, but the parent is never changed. The divider
is then programmed with m/n = 147/160 from 24.576 MHz. The clock
framework reports the requested 22.5792 MHz, but the fractional divider
does not work at such a ratio and the I2S runs at about 54% of the
nominal rate (96000 instead of 176400 frames/s).
Add CLK_SET_RATE_PARENT to both dividers, as on all other I2S and SPDIF
fractional dividers of the RK3588 and as in the vendor kernel:
https://github.com/rockchip-linux/kernel/blob/470f9dccbdc42e7b8a824d0a5c5640a10e9457d2/drivers/clk/rockchip/clk-rk3588.c#L2037
https://github.com/rockchip-linux/kernel/blob/470f9dccbdc42e7b8a824d0a5c5640a10e9457d2/drivers/clk/rockchip/clk-rk3588.c#L2055
To reproduce, on any RK3588 board with HDMI0 audio enabled and a sink
that accepts 192 and 176.4 kHz LPCM: play 192 kHz, then time two
seconds of 176.4 kHz:
aplay -q -D hw:HDMI0 -t raw -f S16_LE -c 2 -r 192000 -d 1 /dev/zero
time aplay -q -D hw:HDMI0 -t raw -f S16_LE -c 2 -r 176400 -d 2 /dev/zero
On linux-rockchip for-next the second command takes 3.7 s instead of
2.0 s, and clk_i2s5_8ch_tx_src stays at 24.576 MHz.
Tested on a FriendlyElec CM3588 NAS with HDMI0 cabled into its HDMI
receiver, the receiver's EDID advertising 192 and 176.4 kHz, and the
HDMI sound cards enabled in the device tree. Two 176.4 kHz runs after
boot, then three runs each preceded by a 192 kHz stream:
176.4 kHz frames/s clk_i2s5_8ch_tx_src
after boot / after after the 176.4 kHz
192 kHz stream (Hz)
for-next 175500 / 95600 (3x) 24576000
for-next + this patch 175500 / 174800 (3x) 786431991
With this patch the 32 to 192 kHz rates still play at their nominal
rate, and a frame counter played at 176.4 kHz after a 192 kHz stream
was captured bit-exact by the HDMI receiver. I2S6 RX is not used on
this board and was not tested.
Fixes: f1c506d152ff ("clk: rockchip: add clock controller for the RK3588")
Signed-off-by: Tim Surber <me@timsurber.de>
---
drivers/clk/rockchip/clk-rk3588.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/clk/rockchip/clk-rk3588.c b/drivers/clk/rockchip/clk-rk3588.c
index 24baa0ef9..63aeeb501 100644
--- a/drivers/clk/rockchip/clk-rk3588.c
+++ b/drivers/clk/rockchip/clk-rk3588.c
@@ -2024,7 +2024,8 @@ static struct rockchip_clk_branch rk3588_early_clk_branches[] __initdata = {
COMPOSITE(CLK_I2S5_8CH_TX_SRC, "clk_i2s5_8ch_tx_src", gpll_aupll_p, 0,
RK3588_CLKSEL_CON(140), 10, 1, MFLAGS, 5, 5, DFLAGS,
RK3588_CLKGATE_CON(62), 6, GFLAGS),
- COMPOSITE_FRACMUX(CLK_I2S5_8CH_TX_FRAC, "clk_i2s5_8ch_tx_frac", "clk_i2s5_8ch_tx_src", 0,
+ COMPOSITE_FRACMUX(CLK_I2S5_8CH_TX_FRAC, "clk_i2s5_8ch_tx_frac", "clk_i2s5_8ch_tx_src",
+ CLK_SET_RATE_PARENT,
RK3588_CLKSEL_CON(141), 0,
RK3588_CLKGATE_CON(62), 7, GFLAGS,
&rk3588_i2s5_8ch_tx_fracmux),
@@ -2043,7 +2044,8 @@ static struct rockchip_clk_branch rk3588_early_clk_branches[] __initdata = {
COMPOSITE(CLK_I2S6_8CH_RX_SRC, "clk_i2s6_8ch_rx_src", gpll_aupll_p, 0,
RK3588_CLKSEL_CON(146), 7, 1, MFLAGS, 2, 5, DFLAGS,
RK3588_CLKGATE_CON(63), 0, GFLAGS),
- COMPOSITE_FRACMUX(CLK_I2S6_8CH_RX_FRAC, "clk_i2s6_8ch_rx_frac", "clk_i2s6_8ch_rx_src", 0,
+ COMPOSITE_FRACMUX(CLK_I2S6_8CH_RX_FRAC, "clk_i2s6_8ch_rx_frac", "clk_i2s6_8ch_rx_src",
+ CLK_SET_RATE_PARENT,
RK3588_CLKSEL_CON(147), 0,
RK3588_CLKGATE_CON(63), 1, GFLAGS,
&rk3588_i2s6_8ch_rx_fracmux),
base-commit: c3baae5f1a15645cddadcb2b9abddef5df291f59
--
2.55.0
^ permalink raw reply [flat|nested] 2+ messages in thread* Re: [PATCH] clk: rockchip: rk3588: Allow I2S5 TX and I2S6 RX frac to set parent rate
2026-11-11 22:06 [PATCH] clk: rockchip: rk3588: Allow I2S5 TX and I2S6 RX frac to set parent rate Tim Surber
@ 2026-11-11 22:18 ` Heiko Stübner
0 siblings, 0 replies; 2+ messages in thread
From: Heiko Stübner @ 2026-11-11 22:18 UTC (permalink / raw)
To: Stephen Boyd, Tim Surber
Cc: Tim Surber, Brian Masney, Jerome Brunet, Elaine Zhang,
Sebastian Reichel, linux-clk, linux-rockchip, linux-arm-kernel,
linux-kernel
Am Mittwoch, 11. November 2026, 23:06:53 Mitteleuropäische Normalzeit schrieb Tim Surber:
> All RK3588 audio fractional dividers except clk_i2s5_8ch_tx_frac and
> clk_i2s6_8ch_rx_frac are registered with CLK_SET_RATE_PARENT. Without it
> the divider cannot raise the rate of its *_src parent again once the
> parent has been lowered.
>
> That happens on HDMI0 (i2s5_8ch) after a 192 kHz stream. Its MCLK of
> 24.576 MHz (128 * fs) is an integer divisor of AUPLL (786.432 MHz / 32),
> so the mux selects clk_i2s5_8ch_tx_src directly and sets its divider to
> 32. For a following 176.4 kHz stream the mux selects the fractional
> divider. rockchip_fractional_approximation() sees that the parent is
> less than 20 times the requested rate and computes m/n against the
> grandparent (AUPLL) rate, but the parent is never changed. The divider
> is then programmed with m/n = 147/160 from 24.576 MHz. The clock
> framework reports the requested 22.5792 MHz, but the fractional divider
> does not work at such a ratio and the I2S runs at about 54% of the
> nominal rate (96000 instead of 176400 frames/s).
>
> Add CLK_SET_RATE_PARENT to both dividers, as on all other I2S and SPDIF
> fractional dividers of the RK3588 and as in the vendor kernel:
>
> https://github.com/rockchip-linux/kernel/blob/470f9dccbdc42e7b8a824d0a5c5640a10e9457d2/drivers/clk/rockchip/clk-rk3588.c#L2037
> https://github.com/rockchip-linux/kernel/blob/470f9dccbdc42e7b8a824d0a5c5640a10e9457d2/drivers/clk/rockchip/clk-rk3588.c#L2055
>
> To reproduce, on any RK3588 board with HDMI0 audio enabled and a sink
> that accepts 192 and 176.4 kHz LPCM: play 192 kHz, then time two
> seconds of 176.4 kHz:
>
> aplay -q -D hw:HDMI0 -t raw -f S16_LE -c 2 -r 192000 -d 1 /dev/zero
> time aplay -q -D hw:HDMI0 -t raw -f S16_LE -c 2 -r 176400 -d 2 /dev/zero
>
> On linux-rockchip for-next the second command takes 3.7 s instead of
> 2.0 s, and clk_i2s5_8ch_tx_src stays at 24.576 MHz.
>
> Tested on a FriendlyElec CM3588 NAS with HDMI0 cabled into its HDMI
> receiver, the receiver's EDID advertising 192 and 176.4 kHz, and the
> HDMI sound cards enabled in the device tree. Two 176.4 kHz runs after
> boot, then three runs each preceded by a 192 kHz stream:
>
> 176.4 kHz frames/s clk_i2s5_8ch_tx_src
> after boot / after after the 176.4 kHz
> 192 kHz stream (Hz)
> for-next 175500 / 95600 (3x) 24576000
> for-next + this patch 175500 / 174800 (3x) 786431991
>
> With this patch the 32 to 192 kHz rates still play at their nominal
> rate, and a frame counter played at 176.4 kHz after a 192 kHz stream
> was captured bit-exact by the HDMI receiver. I2S6 RX is not used on
> this board and was not tested.
>
> Fixes: f1c506d152ff ("clk: rockchip: add clock controller for the RK3588")
> Signed-off-by: Tim Surber <me@timsurber.de>
This is waaaay too long for a siomple two line change. Please shorten
this to a sane level.
Thanks
Heiko
> ---
> drivers/clk/rockchip/clk-rk3588.c | 6 ++++--
> 1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/clk/rockchip/clk-rk3588.c b/drivers/clk/rockchip/clk-rk3588.c
> index 24baa0ef9..63aeeb501 100644
> --- a/drivers/clk/rockchip/clk-rk3588.c
> +++ b/drivers/clk/rockchip/clk-rk3588.c
> @@ -2024,7 +2024,8 @@ static struct rockchip_clk_branch rk3588_early_clk_branches[] __initdata = {
> COMPOSITE(CLK_I2S5_8CH_TX_SRC, "clk_i2s5_8ch_tx_src", gpll_aupll_p, 0,
> RK3588_CLKSEL_CON(140), 10, 1, MFLAGS, 5, 5, DFLAGS,
> RK3588_CLKGATE_CON(62), 6, GFLAGS),
> - COMPOSITE_FRACMUX(CLK_I2S5_8CH_TX_FRAC, "clk_i2s5_8ch_tx_frac", "clk_i2s5_8ch_tx_src", 0,
> + COMPOSITE_FRACMUX(CLK_I2S5_8CH_TX_FRAC, "clk_i2s5_8ch_tx_frac", "clk_i2s5_8ch_tx_src",
> + CLK_SET_RATE_PARENT,
> RK3588_CLKSEL_CON(141), 0,
> RK3588_CLKGATE_CON(62), 7, GFLAGS,
> &rk3588_i2s5_8ch_tx_fracmux),
> @@ -2043,7 +2044,8 @@ static struct rockchip_clk_branch rk3588_early_clk_branches[] __initdata = {
> COMPOSITE(CLK_I2S6_8CH_RX_SRC, "clk_i2s6_8ch_rx_src", gpll_aupll_p, 0,
> RK3588_CLKSEL_CON(146), 7, 1, MFLAGS, 2, 5, DFLAGS,
> RK3588_CLKGATE_CON(63), 0, GFLAGS),
> - COMPOSITE_FRACMUX(CLK_I2S6_8CH_RX_FRAC, "clk_i2s6_8ch_rx_frac", "clk_i2s6_8ch_rx_src", 0,
> + COMPOSITE_FRACMUX(CLK_I2S6_8CH_RX_FRAC, "clk_i2s6_8ch_rx_frac", "clk_i2s6_8ch_rx_src",
> + CLK_SET_RATE_PARENT,
> RK3588_CLKSEL_CON(147), 0,
> RK3588_CLKGATE_CON(63), 1, GFLAGS,
> &rk3588_i2s6_8ch_rx_fracmux),
>
> base-commit: c3baae5f1a15645cddadcb2b9abddef5df291f59
>
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-11-11 22:18 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-11 22:06 [PATCH] clk: rockchip: rk3588: Allow I2S5 TX and I2S6 RX frac to set parent rate Tim Surber
2026-11-11 22:18 ` Heiko Stübner
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®