Skip to content

Commit be91923

Browse files
tiwaibroonie
authored andcommitted
ASoC: nau8540: Implement hw constraint for rates
nau8540 driver restricts the sample rate with over sampling rate, but currently it barely bails out at hw_params with -EINVAL error (with a kernel message); this doesn't help for user-space to recognize which rate can be actually used. This patch introduces the proper hw constraint for adjusting the available range of the sample rate depending on the OSR setup, as well as some code cleanup, for improving the communication with user-space. Now applications can know the valid rate beforehand and reduces the rate appropriately without errors. Signed-off-by: Takashi Iwai <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent bed41de commit be91923

File tree

1 file changed

+29
-11
lines changed

1 file changed

+29
-11
lines changed

sound/soc/codecs/nau8540.c

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -357,39 +357,56 @@ static const struct snd_soc_dapm_route nau8540_dapm_routes[] = {
357357
{"AIFTX", NULL, "Digital CH4 Mux"},
358358
};
359359

360-
static int nau8540_clock_check(struct nau8540 *nau8540, int rate, int osr)
360+
static const struct nau8540_osr_attr *
361+
nau8540_get_osr(struct nau8540 *nau8540)
361362
{
363+
unsigned int osr;
364+
365+
regmap_read(nau8540->regmap, NAU8540_REG_ADC_SAMPLE_RATE, &osr);
366+
osr &= NAU8540_ADC_OSR_MASK;
362367
if (osr >= ARRAY_SIZE(osr_adc_sel))
363-
return -EINVAL;
368+
return NULL;
369+
return &osr_adc_sel[osr];
370+
}
371+
372+
static int nau8540_dai_startup(struct snd_pcm_substream *substream,
373+
struct snd_soc_dai *dai)
374+
{
375+
struct snd_soc_component *component = dai->component;
376+
struct nau8540 *nau8540 = snd_soc_component_get_drvdata(component);
377+
const struct nau8540_osr_attr *osr;
364378

365-
if (rate * osr > CLK_ADC_MAX) {
366-
dev_err(nau8540->dev, "exceed the maximum frequency of CLK_ADC\n");
379+
osr = nau8540_get_osr(nau8540);
380+
if (!osr || !osr->osr)
367381
return -EINVAL;
368-
}
369382

370-
return 0;
383+
return snd_pcm_hw_constraint_minmax(substream->runtime,
384+
SNDRV_PCM_HW_PARAM_RATE,
385+
0, CLK_ADC_MAX / osr->osr);
371386
}
372387

373388
static int nau8540_hw_params(struct snd_pcm_substream *substream,
374389
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
375390
{
376391
struct snd_soc_component *component = dai->component;
377392
struct nau8540 *nau8540 = snd_soc_component_get_drvdata(component);
378-
unsigned int val_len = 0, osr;
393+
unsigned int val_len = 0;
394+
const struct nau8540_osr_attr *osr;
379395

380396
/* CLK_ADC = OSR * FS
381397
* ADC clock frequency is defined as Over Sampling Rate (OSR)
382398
* multiplied by the audio sample rate (Fs). Note that the OSR and Fs
383399
* values must be selected such that the maximum frequency is less
384400
* than 6.144 MHz.
385401
*/
386-
regmap_read(nau8540->regmap, NAU8540_REG_ADC_SAMPLE_RATE, &osr);
387-
osr &= NAU8540_ADC_OSR_MASK;
388-
if (nau8540_clock_check(nau8540, params_rate(params), osr))
402+
osr = nau8540_get_osr(nau8540);
403+
if (!osr || !osr->osr)
404+
return -EINVAL;
405+
if (params_rate(params) * osr->osr > CLK_ADC_MAX)
389406
return -EINVAL;
390407
regmap_update_bits(nau8540->regmap, NAU8540_REG_CLOCK_SRC,
391408
NAU8540_CLK_ADC_SRC_MASK,
392-
osr_adc_sel[osr].clk_src << NAU8540_CLK_ADC_SRC_SFT);
409+
osr->clk_src << NAU8540_CLK_ADC_SRC_SFT);
393410

394411
switch (params_width(params)) {
395412
case 16:
@@ -515,6 +532,7 @@ static int nau8540_set_tdm_slot(struct snd_soc_dai *dai,
515532

516533

517534
static const struct snd_soc_dai_ops nau8540_dai_ops = {
535+
.startup = nau8540_dai_startup,
518536
.hw_params = nau8540_hw_params,
519537
.set_fmt = nau8540_set_fmt,
520538
.set_tdm_slot = nau8540_set_tdm_slot,

0 commit comments

Comments
 (0)