Linux Sound subsystem development
 help / color / mirror / Atom feed
* [PATCH] ASoC: fsl_utils: Tolerate fractional PLL rate residue
@ 2026-10-19 22:47 Fabio Estevam
  0 siblings, 0 replies; only message in thread
From: Fabio Estevam @ 2026-10-19 22:47 UTC (permalink / raw)
  To: broonie; +Cc: shengjiu.wang, linux-sound, Fabio Estevam

fsl_asoc_constrain_rates() admits a sample rate only when an audio PLL
divides it exactly. On i.MX8M Plus, fractional audio PLLs may read a few
hertz off their nominal rate after clk_set_rate(). For example,
audio_pll1 can read 393215997 Hz after restoring 393216000 Hz.

This residue can make the helper exclude a valid sample-rate family,
causing a 48 kHz stream to fail or be resampled after PLL trimming.
Accept remainders within 100 Hz of either end of the divisor range.
The other rate family differs by tens of kilohertz, so the tolerance
does not make the families overlap.

Observed on a custom i.MX8MP-based board: after 44.1 kHz playback and
PLL trimming, subsequent 48 kHz playback was silently resampled.

Signed-off-by: Fabio Estevam <festevam@gmail.com>
---
 sound/soc/fsl/fsl_utils.c | 25 ++++++++++++++++++++++---
 1 file changed, 22 insertions(+), 3 deletions(-)

diff --git a/sound/soc/fsl/fsl_utils.c b/sound/soc/fsl/fsl_utils.c
index 7651c64bc837..be874eab0a81 100644
--- a/sound/soc/fsl/fsl_utils.c
+++ b/sound/soc/fsl/fsl_utils.c
@@ -153,6 +153,9 @@ void fsl_asoc_reparent_pll_clocks(struct device *dev, struct clk *clk,
 }
 EXPORT_SYMBOL(fsl_asoc_reparent_pll_clocks);
 
+/* Fractional audio PLLs may sit a few Hz off nominal */
+#define FSL_RATE_CONSTR_TOL_HZ	100
+
 /**
  * fsl_asoc_constrain_rates - constrain rates according to clocks
  *
@@ -172,6 +175,7 @@ void fsl_asoc_constrain_rates(struct snd_pcm_hw_constraint_list *target_constr,
 {
 	int i, j, k = 0;
 	u64 clk_rate[3];
+	u32 rate, rem;
 
 	*target_constr = *original_constr;
 	if (pll8k_clk || pll11k_clk || ext_clk) {
@@ -181,10 +185,25 @@ void fsl_asoc_constrain_rates(struct snd_pcm_hw_constraint_list *target_constr,
 			clk_rate[0] = clk_get_rate(pll8k_clk);
 			clk_rate[1] = clk_get_rate(pll11k_clk);
 			clk_rate[2] = clk_get_rate(ext_clk);
+			rate = original_constr->list[i];
 			for (j = 0; j < 3; j++) {
-				if (clk_rate[j] != 0 &&
-				    do_div(clk_rate[j], original_constr->list[i]) == 0) {
-					target_rates[k++] = original_constr->list[i];
+				if (clk_rate[j] == 0)
+					continue;
+				rem = do_div(clk_rate[j], rate);
+				/*
+				 * The audio PLLs are fractional and cannot
+				 * always reproduce their nominal rate: after
+				 * any clk_set_rate() they may sit a few Hz
+				 * off (observed on i.MX8M Plus: audio_pll1
+				 * reads 393215997 after restoring 393216000),
+				 * which must not disqualify the entire rate
+				 * family. Accept near-integer ratios; the
+				 * other family misses by tens of kHz, so a
+				 * small tolerance cannot mix families.
+				 */
+				if (rem <= FSL_RATE_CONSTR_TOL_HZ ||
+				    rem >= rate - FSL_RATE_CONSTR_TOL_HZ) {
+					target_rates[k++] = rate;
 					target_constr->count++;
 					break;
 				}
-- 
2.43.0


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2026-10-19 22:47 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-19 22:47 [PATCH] ASoC: fsl_utils: Tolerate fractional PLL rate residue Fabio Estevam

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox