[PATCH] clk: rockchip: rk3588: let MCLK_SPDIF* rate requests reach the divider

Karl Asseily karl at asseily.com
Thu Aug 20 01:39:37 PDT 2026


Please drop this patch. It is a no-op and my analysis was wrong.

rockchip_clk_register_branch() adds CLK_SET_RATE_PARENT to every
branch_gate at registration:

case branch_gate:
flags |= CLK_SET_RATE_PARENT;

so the MCLK_SPDIF* gates already propagate and the flags column in the
branch table makes no difference.

The behaviour I was chasing was real, but the cause is elsewhere:
simple-audio-card only calls the CPU DAI's set_sysclk() when the card
node has an mclk-fs property, and rk_spdif_set_sysclk() is the only
caller of clk_set_rate() in the S/PDIF path. Without mclk-fs no rate
request is ever made, MCLK stays at whatever the bootloader left, and
44.1 kHz material goes out at 48 kHz. Adding mclk-fs to my card node
fixed it. The before/after rates I quoted belong to that change, not
to this one.

Sorry for the noise.

Karl

On Thu, Aug 20, 2026 at 10:54 AM Karl Asseily <karl at asseily.com> wrote:
>
> Every MCLK_SPDIFn gate is declared with flags 0, while the CLK_SPDIFn mux
> immediately above it already carries CLK_SET_RATE_PARENT. The rockchip
> S/PDIF driver calls clk_set_rate() on the gate, which has no .set_rate of
> its own and, without CLK_SET_RATE_PARENT, no way to pass the request up.
> The clock core therefore computes "new rate == current rate", returns 0,
> and changes nothing.
>
> The visible effect is that S/PDIF is stuck on whatever divider the
> bootloader left behind. On a board whose audio PLL is parked on the
> 48 kHz family, every 44.1 kHz source goes out at 48 kHz, silently, with
> nothing reporting an error. Measured on an RK3588 board playing 44.1 kHz
> material, before and after:
>
>   mclk_spdif0   12287999 Hz    48000 x 256
>   mclk_spdif0   11289598 Hz    44100 x 256
>
> Add CLK_SET_RATE_PARENT to all eight MCLK_SPDIF gates so the request
> propagates to the fractional divider that can satisfy it.
>
> Propagation stops there. Each chain terminates at CLK_SPDIFn_SRC, which
> is declared with flags 0, so a rate request cannot reach a shared PLL and
> pull unrelated consumers off frequency.
>
> Two pairs of gates share a divider - mclk_spdif2 and mclk_spdif2_dp0 both
> sit on clk_spdif2_dp0, and mclk_spdif5 and mclk_spdif5_dp1 on
> clk_spdif5_dp1 - so a rate set on one moves the other. That sharing is in
> the hardware and is not introduced here; before this change neither of
> them could set a rate at all.
>
> Signed-off-by: Karl Asseily <karl at asseily.com>
> ---
>
> Notes:
>     Generated against broonie/sound.git for-next. clk-rk3588.c
>     carries no ASoC changes, so this should apply to any current tree.
>
>     Tested on RK3588 hardware running 7.1.3: without this a 44.1 kHz stream leaves
>     the S/PDIF transmitter at 48 kHz; with it mclk_spdif0 retunes and the receiver
>     locks at 44.1 kHz.
>
>     checkpatch --strict reports "Alignment should match open parenthesis" on the
>     touched lines. That continuation indentation is unchanged by this patch and
>     matches every other clock entry in the file; realigning only these eight would
>     make them the inconsistent ones.
>
>  drivers/clk/rockchip/clk-rk3588.c | 16 ++++++++--------
>  1 file changed, 8 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/clk/rockchip/clk-rk3588.c b/drivers/clk/rockchip/clk-rk3588.c
> index 2ba9976654c..b3d577dccfc 100644
> --- a/drivers/clk/rockchip/clk-rk3588.c
> +++ b/drivers/clk/rockchip/clk-rk3588.c
> @@ -960,7 +960,7 @@ static struct rockchip_clk_branch rk3588_early_clk_branches[] __initdata = {
>                         RK3588_CLKSEL_CON(33), 0,
>                         RK3588_CLKGATE_CON(9), 0, GFLAGS,
>                         &rk3588_spdif0_fracmux),
> -       GATE(MCLK_SPDIF0, "mclk_spdif0", "clk_spdif0", 0,
> +       GATE(MCLK_SPDIF0, "mclk_spdif0", "clk_spdif0", CLK_SET_RATE_PARENT,
>                         RK3588_CLKGATE_CON(9), 1, GFLAGS),
>
>         GATE(HCLK_SPDIF1, "hclk_spdif1", "hclk_audio_root", 0,
> @@ -973,7 +973,7 @@ static struct rockchip_clk_branch rk3588_early_clk_branches[] __initdata = {
>                         RK3588_CLKSEL_CON(35), 0,
>                         RK3588_CLKGATE_CON(9), 4, GFLAGS,
>                         &rk3588_spdif1_fracmux),
> -       GATE(MCLK_SPDIF1, "mclk_spdif1", "clk_spdif1", 0,
> +       GATE(MCLK_SPDIF1, "mclk_spdif1", "clk_spdif1", CLK_SET_RATE_PARENT,
>                         RK3588_CLKGATE_CON(9), 5, GFLAGS),
>
>         COMPOSITE(ACLK_AV1_ROOT, "aclk_av1_root", gpll_cpll_aupll_p, 0,
> @@ -1868,9 +1868,9 @@ static struct rockchip_clk_branch rk3588_early_clk_branches[] __initdata = {
>                         RK3588_CLKSEL_CON(123), 0,
>                         RK3588_CLKGATE_CON(57), 4, GFLAGS,
>                         &rk3588_spdif2_dp0_fracmux),
> -       GATE(MCLK_SPDIF2_DP0, "mclk_spdif2_dp0", "clk_spdif2_dp0", 0,
> +       GATE(MCLK_SPDIF2_DP0, "mclk_spdif2_dp0", "clk_spdif2_dp0", CLK_SET_RATE_PARENT,
>                         RK3588_CLKGATE_CON(57), 5, GFLAGS),
> -       GATE(MCLK_SPDIF2, "mclk_spdif2", "clk_spdif2_dp0", 0,
> +       GATE(MCLK_SPDIF2, "mclk_spdif2", "clk_spdif2_dp0", CLK_SET_RATE_PARENT,
>                         RK3588_CLKGATE_CON(57), 6, GFLAGS),
>         COMPOSITE(CLK_SPDIF5_DP1_SRC, "clk_spdif5_dp1_src", gpll_aupll_p, 0,
>                         RK3588_CLKSEL_CON(124), 7, 1, MFLAGS, 2, 5, DFLAGS,
> @@ -1880,9 +1880,9 @@ static struct rockchip_clk_branch rk3588_early_clk_branches[] __initdata = {
>                         RK3588_CLKSEL_CON(125), 0,
>                         RK3588_CLKGATE_CON(57), 9, GFLAGS,
>                         &rk3588_spdif5_dp1_fracmux),
> -       GATE(MCLK_SPDIF5_DP1, "mclk_spdif5_dp1", "clk_spdif5_dp1", 0,
> +       GATE(MCLK_SPDIF5_DP1, "mclk_spdif5_dp1", "clk_spdif5_dp1", CLK_SET_RATE_PARENT,
>                         RK3588_CLKGATE_CON(57), 10, GFLAGS),
> -       GATE(MCLK_SPDIF5, "mclk_spdif5", "clk_spdif5_dp1", 0,
> +       GATE(MCLK_SPDIF5, "mclk_spdif5", "clk_spdif5_dp1", CLK_SET_RATE_PARENT,
>                         RK3588_CLKGATE_CON(57), 11, GFLAGS),
>         COMPOSITE_NOMUX(CLK_AUX16M_0, "clk_aux16m_0", "gpll", 0,
>                         RK3588_CLKSEL_CON(117), 0, 8, DFLAGS,
> @@ -2059,7 +2059,7 @@ static struct rockchip_clk_branch rk3588_early_clk_branches[] __initdata = {
>                         RK3588_CLKSEL_CON(149), 0,
>                         RK3588_CLKGATE_CON(63), 6, GFLAGS,
>                         &rk3588_spdif3_fracmux),
> -       GATE(MCLK_SPDIF3, "mclk_spdif3", "clk_spdif3", 0,
> +       GATE(MCLK_SPDIF3, "mclk_spdif3", "clk_spdif3", CLK_SET_RATE_PARENT,
>                         RK3588_CLKGATE_CON(63), 7, GFLAGS),
>         COMPOSITE(CLK_SPDIF4_SRC, "clk_spdif4_src", gpll_aupll_p, 0,
>                         RK3588_CLKSEL_CON(150), 7, 1, MFLAGS, 2, 5, DFLAGS,
> @@ -2069,7 +2069,7 @@ static struct rockchip_clk_branch rk3588_early_clk_branches[] __initdata = {
>                         RK3588_CLKSEL_CON(151), 0,
>                         RK3588_CLKGATE_CON(63), 10, GFLAGS,
>                         &rk3588_spdif4_fracmux),
> -       GATE(MCLK_SPDIF4, "mclk_spdif4", "clk_spdif4", 0,
> +       GATE(MCLK_SPDIF4, "mclk_spdif4", "clk_spdif4", CLK_SET_RATE_PARENT,
>                         RK3588_CLKGATE_CON(63), 11, GFLAGS),
>         COMPOSITE(MCLK_SPDIFRX0, "mclk_spdifrx0", gpll_cpll_aupll_p, 0,
>                         RK3588_CLKSEL_CON(152), 7, 2, MFLAGS, 2, 5, DFLAGS,
> --
> 2.34.1
>



More information about the Linux-rockchip mailing list