mirror of https://gitee.com/openkylin/linux.git
ASoC: ti: davinci-mcasp: Support for correct symmetric sample bits
Implement custom snd_pcm_hw_rule to filter the available formats for the second stream to make it symmetric and allow only formats which require the same amount of bits on the bus as the running stream. A simple constraint is not working correctly because for example: the first stream is started with S24_LE If we place 24 as constraint for the SAMPLE_BITS then the second stream can not use S24_LE as it is physically 32bits. If we would place 32 as constraint (physical width) then S32_LE would have been allowed, but S24_3LE is not. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com> Link: https://lore.kernel.org/r/20190726064244.3762-3-peter.ujfalusi@ti.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
3b46a67af2
commit
2448c813b1
|
@ -109,6 +109,7 @@ struct davinci_mcasp {
|
||||||
|
|
||||||
/* Used for comstraint setting on the second stream */
|
/* Used for comstraint setting on the second stream */
|
||||||
u32 channels;
|
u32 channels;
|
||||||
|
int max_format_width;
|
||||||
u8 active_serializers[2];
|
u8 active_serializers[2];
|
||||||
|
|
||||||
#ifdef CONFIG_GPIOLIB
|
#ifdef CONFIG_GPIOLIB
|
||||||
|
@ -766,6 +767,8 @@ static int davinci_config_channel_size(struct davinci_mcasp *mcasp,
|
||||||
|
|
||||||
if (mcasp->slot_width)
|
if (mcasp->slot_width)
|
||||||
slot_width = mcasp->slot_width;
|
slot_width = mcasp->slot_width;
|
||||||
|
else if (mcasp->max_format_width)
|
||||||
|
slot_width = mcasp->max_format_width;
|
||||||
else
|
else
|
||||||
slot_width = sample_width;
|
slot_width = sample_width;
|
||||||
/*
|
/*
|
||||||
|
@ -1233,8 +1236,11 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
|
||||||
|
|
||||||
davinci_config_channel_size(mcasp, word_length);
|
davinci_config_channel_size(mcasp, word_length);
|
||||||
|
|
||||||
if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE)
|
if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE) {
|
||||||
mcasp->channels = channels;
|
mcasp->channels = channels;
|
||||||
|
if (!mcasp->max_format_width)
|
||||||
|
mcasp->max_format_width = word_length;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1286,6 +1292,28 @@ static int davinci_mcasp_hw_rule_slot_width(struct snd_pcm_hw_params *params,
|
||||||
return snd_mask_refine(fmt, &nfmt);
|
return snd_mask_refine(fmt, &nfmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int davinci_mcasp_hw_rule_format_width(struct snd_pcm_hw_params *params,
|
||||||
|
struct snd_pcm_hw_rule *rule)
|
||||||
|
{
|
||||||
|
struct davinci_mcasp_ruledata *rd = rule->private;
|
||||||
|
struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
|
||||||
|
struct snd_mask nfmt;
|
||||||
|
int i, format_width;
|
||||||
|
|
||||||
|
snd_mask_none(&nfmt);
|
||||||
|
format_width = rd->mcasp->max_format_width;
|
||||||
|
|
||||||
|
for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) {
|
||||||
|
if (snd_mask_test(fmt, i)) {
|
||||||
|
if (snd_pcm_format_width(i) == format_width) {
|
||||||
|
snd_mask_set(&nfmt, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return snd_mask_refine(fmt, &nfmt);
|
||||||
|
}
|
||||||
|
|
||||||
static const unsigned int davinci_mcasp_dai_rates[] = {
|
static const unsigned int davinci_mcasp_dai_rates[] = {
|
||||||
8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000,
|
8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000,
|
||||||
88200, 96000, 176400, 192000,
|
88200, 96000, 176400, 192000,
|
||||||
|
@ -1463,7 +1491,20 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
|
||||||
0, SNDRV_PCM_HW_PARAM_CHANNELS,
|
0, SNDRV_PCM_HW_PARAM_CHANNELS,
|
||||||
&mcasp->chconstr[substream->stream]);
|
&mcasp->chconstr[substream->stream]);
|
||||||
|
|
||||||
if (mcasp->slot_width) {
|
if (mcasp->max_format_width) {
|
||||||
|
/*
|
||||||
|
* Only allow formats which require same amount of bits on the
|
||||||
|
* bus as the currently running stream
|
||||||
|
*/
|
||||||
|
ret = snd_pcm_hw_rule_add(substream->runtime, 0,
|
||||||
|
SNDRV_PCM_HW_PARAM_FORMAT,
|
||||||
|
davinci_mcasp_hw_rule_format_width,
|
||||||
|
ruledata,
|
||||||
|
SNDRV_PCM_HW_PARAM_FORMAT, -1);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
else if (mcasp->slot_width) {
|
||||||
/* Only allow formats require <= slot_width bits on the bus */
|
/* Only allow formats require <= slot_width bits on the bus */
|
||||||
ret = snd_pcm_hw_rule_add(substream->runtime, 0,
|
ret = snd_pcm_hw_rule_add(substream->runtime, 0,
|
||||||
SNDRV_PCM_HW_PARAM_FORMAT,
|
SNDRV_PCM_HW_PARAM_FORMAT,
|
||||||
|
@ -1514,8 +1555,10 @@ static void davinci_mcasp_shutdown(struct snd_pcm_substream *substream,
|
||||||
if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE)
|
if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!cpu_dai->active)
|
if (!cpu_dai->active) {
|
||||||
mcasp->channels = 0;
|
mcasp->channels = 0;
|
||||||
|
mcasp->max_format_width = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = {
|
static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = {
|
||||||
|
@ -1571,7 +1614,6 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = {
|
||||||
},
|
},
|
||||||
.ops = &davinci_mcasp_dai_ops,
|
.ops = &davinci_mcasp_dai_ops,
|
||||||
|
|
||||||
.symmetric_samplebits = 1,
|
|
||||||
.symmetric_rates = 1,
|
.symmetric_rates = 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue