All of lore.kernel.org
 help / color / mirror / Atom feed
From: Karl Asseily <karl@asseily.com>
To: mturquette@baylibre.com, sboyd@kernel.org, heiko@sntech.de
Cc: bmasney@redhat.com, linux-clk@vger.kernel.org,
	linux-rockchip@lists.infradead.org,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, Karl Asseily <karl@asseily.com>
Subject: [PATCH] clk: rockchip: rk3588: let MCLK_SPDIF* rate requests reach the divider
Date: Thu, 20 Aug 2026 10:54:27 +0300	[thread overview]
Message-ID: <20260820075427.67050-1-karl@asseily.com> (raw)

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@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


WARNING: multiple messages have this Message-ID (diff)
From: Karl Asseily <karl@asseily.com>
To: mturquette@baylibre.com, sboyd@kernel.org, heiko@sntech.de
Cc: bmasney@redhat.com, linux-clk@vger.kernel.org,
	linux-rockchip@lists.infradead.org,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, Karl Asseily <karl@asseily.com>
Subject: [PATCH] clk: rockchip: rk3588: let MCLK_SPDIF* rate requests reach the divider
Date: Thu, 20 Aug 2026 10:54:27 +0300	[thread overview]
Message-ID: <20260820075427.67050-1-karl@asseily.com> (raw)

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@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


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

             reply	other threads:[~2026-08-20  7:54 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-20  7:54 Karl Asseily [this message]
2026-08-20  7:54 ` [PATCH] clk: rockchip: rk3588: let MCLK_SPDIF* rate requests reach the divider Karl Asseily
2026-08-20  8:05 ` sashiko-bot
2026-08-20  8:39 ` Karl Asseily
2026-08-20  8:39   ` Karl Asseily

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260820075427.67050-1-karl@asseily.com \
    --to=karl@asseily.com \
    --cc=bmasney@redhat.com \
    --cc=heiko@sntech.de \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-clk@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-rockchip@lists.infradead.org \
    --cc=mturquette@baylibre.com \
    --cc=sboyd@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.