Skip to content

Commit bed41de

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

File tree

1 file changed

+45
-38
lines changed

1 file changed

+45
-38
lines changed

sound/soc/codecs/nau8825.c

Lines changed: 45 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1247,27 +1247,42 @@ static const struct snd_soc_dapm_route nau8825_dapm_routes[] = {
12471247
{"HPOR", NULL, "Class G"},
12481248
};
12491249

1250-
static int nau8825_clock_check(struct nau8825 *nau8825,
1251-
int stream, int rate, int osr)
1250+
static const struct nau8825_osr_attr *
1251+
nau8825_get_osr(struct nau8825 *nau8825, int stream)
12521252
{
1253-
int osrate;
1253+
unsigned int osr;
12541254

12551255
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
1256+
regmap_read(nau8825->regmap,
1257+
NAU8825_REG_DAC_CTRL1, &osr);
1258+
osr &= NAU8825_DAC_OVERSAMPLE_MASK;
12561259
if (osr >= ARRAY_SIZE(osr_dac_sel))
1257-
return -EINVAL;
1258-
osrate = osr_dac_sel[osr].osr;
1260+
return NULL;
1261+
return &osr_dac_sel[osr];
12591262
} else {
1263+
regmap_read(nau8825->regmap,
1264+
NAU8825_REG_ADC_RATE, &osr);
1265+
osr &= NAU8825_ADC_SYNC_DOWN_MASK;
12601266
if (osr >= ARRAY_SIZE(osr_adc_sel))
1261-
return -EINVAL;
1262-
osrate = osr_adc_sel[osr].osr;
1267+
return NULL;
1268+
return &osr_adc_sel[osr];
12631269
}
1270+
}
12641271

1265-
if (!osrate || rate * osr > CLK_DA_AD_MAX) {
1266-
dev_err(nau8825->dev, "exceed the maximum frequency of CLK_ADC or CLK_DAC\n");
1272+
static int nau8825_dai_startup(struct snd_pcm_substream *substream,
1273+
struct snd_soc_dai *dai)
1274+
{
1275+
struct snd_soc_component *component = dai->component;
1276+
struct nau8825 *nau8825 = snd_soc_component_get_drvdata(component);
1277+
const struct nau8825_osr_attr *osr;
1278+
1279+
osr = nau8825_get_osr(nau8825, substream->stream);
1280+
if (!osr || !osr->osr)
12671281
return -EINVAL;
1268-
}
12691282

1270-
return 0;
1283+
return snd_pcm_hw_constraint_minmax(substream->runtime,
1284+
SNDRV_PCM_HW_PARAM_RATE,
1285+
0, CLK_DA_AD_MAX / osr->osr);
12711286
}
12721287

12731288
static int nau8825_hw_params(struct snd_pcm_substream *substream,
@@ -1276,7 +1291,9 @@ static int nau8825_hw_params(struct snd_pcm_substream *substream,
12761291
{
12771292
struct snd_soc_component *component = dai->component;
12781293
struct nau8825 *nau8825 = snd_soc_component_get_drvdata(component);
1279-
unsigned int val_len = 0, osr, ctrl_val, bclk_fs, bclk_div;
1294+
unsigned int val_len = 0, ctrl_val, bclk_fs, bclk_div;
1295+
const struct nau8825_osr_attr *osr;
1296+
int err = -EINVAL;
12801297

12811298
nau8825_sema_acquire(nau8825, 3 * HZ);
12821299

@@ -1286,29 +1303,19 @@ static int nau8825_hw_params(struct snd_pcm_substream *substream,
12861303
* values must be selected such that the maximum frequency is less
12871304
* than 6.144 MHz.
12881305
*/
1289-
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
1290-
regmap_read(nau8825->regmap, NAU8825_REG_DAC_CTRL1, &osr);
1291-
osr &= NAU8825_DAC_OVERSAMPLE_MASK;
1292-
if (nau8825_clock_check(nau8825, substream->stream,
1293-
params_rate(params), osr)) {
1294-
nau8825_sema_release(nau8825);
1295-
return -EINVAL;
1296-
}
1306+
osr = nau8825_get_osr(nau8825, substream->stream);
1307+
if (!osr || !osr->osr)
1308+
goto error;
1309+
if (params_rate(params) * osr->osr > CLK_DA_AD_MAX)
1310+
goto error;
1311+
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
12971312
regmap_update_bits(nau8825->regmap, NAU8825_REG_CLK_DIVIDER,
12981313
NAU8825_CLK_DAC_SRC_MASK,
1299-
osr_dac_sel[osr].clk_src << NAU8825_CLK_DAC_SRC_SFT);
1300-
} else {
1301-
regmap_read(nau8825->regmap, NAU8825_REG_ADC_RATE, &osr);
1302-
osr &= NAU8825_ADC_SYNC_DOWN_MASK;
1303-
if (nau8825_clock_check(nau8825, substream->stream,
1304-
params_rate(params), osr)) {
1305-
nau8825_sema_release(nau8825);
1306-
return -EINVAL;
1307-
}
1314+
osr->clk_src << NAU8825_CLK_DAC_SRC_SFT);
1315+
else
13081316
regmap_update_bits(nau8825->regmap, NAU8825_REG_CLK_DIVIDER,
13091317
NAU8825_CLK_ADC_SRC_MASK,
1310-
osr_adc_sel[osr].clk_src << NAU8825_CLK_ADC_SRC_SFT);
1311-
}
1318+
osr->clk_src << NAU8825_CLK_ADC_SRC_SFT);
13121319

13131320
/* make BCLK and LRC divde configuration if the codec as master. */
13141321
regmap_read(nau8825->regmap, NAU8825_REG_I2S_PCM_CTRL2, &ctrl_val);
@@ -1321,10 +1328,8 @@ static int nau8825_hw_params(struct snd_pcm_substream *substream,
13211328
bclk_div = 1;
13221329
else if (bclk_fs <= 128)
13231330
bclk_div = 0;
1324-
else {
1325-
nau8825_sema_release(nau8825);
1326-
return -EINVAL;
1327-
}
1331+
else
1332+
goto error;
13281333
regmap_update_bits(nau8825->regmap, NAU8825_REG_I2S_PCM_CTRL2,
13291334
NAU8825_I2S_LRC_DIV_MASK | NAU8825_I2S_BLK_DIV_MASK,
13301335
((bclk_div + 1) << NAU8825_I2S_LRC_DIV_SFT) | bclk_div);
@@ -1344,17 +1349,18 @@ static int nau8825_hw_params(struct snd_pcm_substream *substream,
13441349
val_len |= NAU8825_I2S_DL_32;
13451350
break;
13461351
default:
1347-
nau8825_sema_release(nau8825);
1348-
return -EINVAL;
1352+
goto error;
13491353
}
13501354

13511355
regmap_update_bits(nau8825->regmap, NAU8825_REG_I2S_PCM_CTRL1,
13521356
NAU8825_I2S_DL_MASK, val_len);
1357+
err = 0;
13531358

1359+
error:
13541360
/* Release the semaphore. */
13551361
nau8825_sema_release(nau8825);
13561362

1357-
return 0;
1363+
return err;
13581364
}
13591365

13601366
static int nau8825_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
@@ -1420,6 +1426,7 @@ static int nau8825_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
14201426
}
14211427

14221428
static const struct snd_soc_dai_ops nau8825_dai_ops = {
1429+
.startup = nau8825_dai_startup,
14231430
.hw_params = nau8825_hw_params,
14241431
.set_fmt = nau8825_set_dai_fmt,
14251432
};

0 commit comments

Comments
 (0)