Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ASoC: wm8524: enable constraints when sysclk is configured.

In some cases, the sysclk won't be configured on init, and sysclk can be
changed in hw_params() according to different sample rate, for example,
for 44kHz sample rate, the sysclk is 11.2896MHz, for 48kHz sample rate,
the sysclk is 12.288MHz.

In order to support the above case, only enable constraints when sysclk
is configured, and check the rate in hw_params.

So overall there are three cases that need to be considered:
- call set_sysclk() on init, then constraints will be initialized.
- don't call set_sysclk() on init, but call it after startup(), then
constraints will be configured, the constraints can be cleared with
call set_sysclk() again in shutdown().
- don't call set_sysclk() in the whole flow, then there are no any
constraints. The clocks depend on cpu dai.

Enlarge the WM8524_NUM_RATES to 12, as the supported rate range is 8kHz
to 192kHz.

Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
Reviewed-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Link: https://patch.msgid.link/20250620021403.624303-1-shengjiu.wang@nxp.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Shengjiu Wang and committed by
Mark Brown
17cc308b c4ca928a

+43 -14
+43 -14
sound/soc/codecs/wm8524.c
··· 21 21 #include <sound/soc.h> 22 22 #include <sound/initval.h> 23 23 24 - #define WM8524_NUM_RATES 7 24 + #define WM8524_NUM_RATES 12 25 25 26 26 /* codec private data */ 27 27 struct wm8524_priv { ··· 46 46 static const struct { 47 47 int value; 48 48 int ratio; 49 - } lrclk_ratios[WM8524_NUM_RATES] = { 49 + } lrclk_ratios[] = { 50 50 { 1, 128 }, 51 51 { 2, 192 }, 52 52 { 3, 256 }, ··· 63 63 struct wm8524_priv *wm8524 = snd_soc_component_get_drvdata(component); 64 64 65 65 /* The set of sample rates that can be supported depends on the 66 - * MCLK supplied to the CODEC - enforce this. 66 + * MCLK supplied to the CODEC. 67 67 */ 68 - if (!wm8524->sysclk) { 69 - dev_err(component->dev, 70 - "No MCLK configured, call set_sysclk() on init\n"); 71 - return -EINVAL; 72 - } 73 - 74 - snd_pcm_hw_constraint_list(substream->runtime, 0, 75 - SNDRV_PCM_HW_PARAM_RATE, 76 - &wm8524->rate_constraint); 68 + if (wm8524->sysclk) 69 + snd_pcm_hw_constraint_list(substream->runtime, 0, 70 + SNDRV_PCM_HW_PARAM_RATE, 71 + &wm8524->rate_constraint); 77 72 78 73 gpiod_set_value_cansleep(wm8524->mute, 1); 79 74 ··· 92 97 unsigned int val; 93 98 int i, j = 0; 94 99 95 - wm8524->sysclk = freq; 96 - 97 100 wm8524->rate_constraint.count = 0; 101 + wm8524->sysclk = freq; 102 + if (!wm8524->sysclk) 103 + return 0; 104 + 98 105 for (i = 0; i < ARRAY_SIZE(lrclk_ratios); i++) { 99 106 val = freq / lrclk_ratios[i].ratio; 100 107 /* Check that it's a standard rate since core can't ··· 105 108 */ 106 109 switch (val) { 107 110 case 8000: 111 + case 11025: 112 + case 16000: 113 + case 22050: 108 114 case 32000: 109 115 case 44100: 110 116 case 48000: 117 + case 64000: 111 118 case 88200: 112 119 case 96000: 113 120 case 176400: ··· 158 157 return 0; 159 158 } 160 159 160 + static int wm8524_hw_params(struct snd_pcm_substream *substream, 161 + struct snd_pcm_hw_params *params, 162 + struct snd_soc_dai *dai) 163 + { 164 + struct snd_soc_component *component = dai->component; 165 + struct wm8524_priv *wm8524 = snd_soc_component_get_drvdata(component); 166 + int i; 167 + 168 + /* If sysclk is not configured, no need to check the rate */ 169 + if (!wm8524->sysclk) 170 + return 0; 171 + 172 + /* Find a supported LRCLK rate */ 173 + for (i = 0; i < wm8524->rate_constraint.count; i++) { 174 + if (wm8524->rate_constraint.list[i] == params_rate(params)) 175 + break; 176 + } 177 + 178 + if (i == wm8524->rate_constraint.count) { 179 + dev_err(component->dev, "LRCLK %d unsupported with MCLK %d\n", 180 + params_rate(params), wm8524->sysclk); 181 + return -EINVAL; 182 + } 183 + 184 + return 0; 185 + } 186 + 161 187 #define WM8524_RATES SNDRV_PCM_RATE_8000_192000 162 188 163 189 #define WM8524_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ ··· 197 169 .set_sysclk = wm8524_set_dai_sysclk, 198 170 .set_fmt = wm8524_set_fmt, 199 171 .mute_stream = wm8524_mute_stream, 172 + .hw_params = wm8524_hw_params, 200 173 }; 201 174 202 175 static struct snd_soc_dai_driver wm8524_dai = {