Skip to content

Commit 92283c8

Browse files
tiwaibroonie
authored andcommitted
ASoC: nau8824: Implement hw constraint for rates
nau8824 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 5628560 commit 92283c8

File tree

1 file changed

+38
-29
lines changed

1 file changed

+38
-29
lines changed

sound/soc/codecs/nau8824.c

Lines changed: 38 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1014,35 +1014,51 @@ static irqreturn_t nau8824_interrupt(int irq, void *data)
10141014
return IRQ_HANDLED;
10151015
}
10161016

1017-
static int nau8824_clock_check(struct nau8824 *nau8824,
1018-
int stream, int rate, int osr)
1017+
static const struct nau8824_osr_attr *
1018+
nau8824_get_osr(struct nau8824 *nau8824, int stream)
10191019
{
1020-
int osrate;
1020+
unsigned int osr;
10211021

10221022
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
1023+
regmap_read(nau8824->regmap,
1024+
NAU8824_REG_DAC_FILTER_CTRL_1, &osr);
1025+
osr &= NAU8824_DAC_OVERSAMPLE_MASK;
10231026
if (osr >= ARRAY_SIZE(osr_dac_sel))
1024-
return -EINVAL;
1025-
osrate = osr_dac_sel[osr].osr;
1027+
return NULL;
1028+
return &osr_dac_sel[osr];
10261029
} else {
1030+
regmap_read(nau8824->regmap,
1031+
NAU8824_REG_ADC_FILTER_CTRL, &osr);
1032+
osr &= NAU8824_ADC_SYNC_DOWN_MASK;
10271033
if (osr >= ARRAY_SIZE(osr_adc_sel))
1028-
return -EINVAL;
1029-
osrate = osr_adc_sel[osr].osr;
1034+
return NULL;
1035+
return &osr_adc_sel[osr];
10301036
}
1037+
}
10311038

1032-
if (!osrate || rate * osr > CLK_DA_AD_MAX) {
1033-
dev_err(nau8824->dev, "exceed the maximum frequency of CLK_ADC or CLK_DAC\n");
1039+
static int nau8824_dai_startup(struct snd_pcm_substream *substream,
1040+
struct snd_soc_dai *dai)
1041+
{
1042+
struct snd_soc_component *component = dai->component;
1043+
struct nau8824 *nau8824 = snd_soc_component_get_drvdata(component);
1044+
const struct nau8824_osr_attr *osr;
1045+
1046+
osr = nau8824_get_osr(nau8824, substream->stream);
1047+
if (!osr || !osr->osr)
10341048
return -EINVAL;
1035-
}
10361049

1037-
return 0;
1050+
return snd_pcm_hw_constraint_minmax(substream->runtime,
1051+
SNDRV_PCM_HW_PARAM_RATE,
1052+
0, CLK_DA_AD_MAX / osr->osr);
10381053
}
10391054

10401055
static int nau8824_hw_params(struct snd_pcm_substream *substream,
10411056
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
10421057
{
10431058
struct snd_soc_component *component = dai->component;
10441059
struct nau8824 *nau8824 = snd_soc_component_get_drvdata(component);
1045-
unsigned int val_len = 0, osr, ctrl_val, bclk_fs, bclk_div;
1060+
unsigned int val_len = 0, ctrl_val, bclk_fs, bclk_div;
1061+
const struct nau8824_osr_attr *osr;
10461062
int err = -EINVAL;
10471063

10481064
nau8824_sema_acquire(nau8824, HZ);
@@ -1054,27 +1070,19 @@ static int nau8824_hw_params(struct snd_pcm_substream *substream,
10541070
* than 6.144 MHz.
10551071
*/
10561072
nau8824->fs = params_rate(params);
1057-
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
1058-
regmap_read(nau8824->regmap,
1059-
NAU8824_REG_DAC_FILTER_CTRL_1, &osr);
1060-
osr &= NAU8824_DAC_OVERSAMPLE_MASK;
1061-
if (nau8824_clock_check(nau8824, substream->stream,
1062-
nau8824->fs, osr))
1063-
goto error;
1073+
osr = nau8824_get_osr(nau8824, substream->stream);
1074+
if (!osr || !osr->osr)
1075+
goto error;
1076+
if (nau8824->fs * osr->osr > CLK_DA_AD_MAX)
1077+
goto error;
1078+
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
10641079
regmap_update_bits(nau8824->regmap, NAU8824_REG_CLK_DIVIDER,
10651080
NAU8824_CLK_DAC_SRC_MASK,
1066-
osr_dac_sel[osr].clk_src << NAU8824_CLK_DAC_SRC_SFT);
1067-
} else {
1068-
regmap_read(nau8824->regmap,
1069-
NAU8824_REG_ADC_FILTER_CTRL, &osr);
1070-
osr &= NAU8824_ADC_SYNC_DOWN_MASK;
1071-
if (nau8824_clock_check(nau8824, substream->stream,
1072-
nau8824->fs, osr))
1073-
goto error;
1081+
osr->clk_src << NAU8824_CLK_DAC_SRC_SFT);
1082+
else
10741083
regmap_update_bits(nau8824->regmap, NAU8824_REG_CLK_DIVIDER,
10751084
NAU8824_CLK_ADC_SRC_MASK,
1076-
osr_adc_sel[osr].clk_src << NAU8824_CLK_ADC_SRC_SFT);
1077-
}
1085+
osr->clk_src << NAU8824_CLK_ADC_SRC_SFT);
10781086

10791087
/* make BCLK and LRC divde configuration if the codec as master. */
10801088
regmap_read(nau8824->regmap,
@@ -1550,6 +1558,7 @@ static const struct snd_soc_component_driver nau8824_component_driver = {
15501558
};
15511559

15521560
static const struct snd_soc_dai_ops nau8824_dai_ops = {
1561+
.startup = nau8824_dai_startup,
15531562
.hw_params = nau8824_hw_params,
15541563
.set_fmt = nau8824_set_fmt,
15551564
.set_tdm_slot = nau8824_set_tdm_slot,

0 commit comments

Comments
 (0)