mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-13 16:50:05 +00:00
ASoC: ti: davinci-mcasp: Correct slot_width posed constraint
The slot_width is a property for the bus while the constraint for SNDRV_PCM_HW_PARAM_SAMPLE_BITS is for the in memory format. Applying slot_width constraint to sample_bits works most of the time, but it will blacklist valid formats in some cases. With slot_width 24 we can support S24_3LE and S24_LE formats as they both look the same on the bus, but a a 24 constraint on sample_bits would not allow S24_LE as it is stored in 32bits in memory. Implement a simple hw_rule function to allow all formats which require less or equal number of bits on the bus as slot_width (if configured). Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com> Link: https://lore.kernel.org/r/20190726064244.3762-2-peter.ujfalusi@ti.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
789e162a62
commit
1e112c35e3
@ -1257,6 +1257,28 @@ static int davinci_mcasp_trigger(struct snd_pcm_substream *substream,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int davinci_mcasp_hw_rule_slot_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, slot_width;
|
||||
|
||||
snd_mask_none(&nfmt);
|
||||
slot_width = rd->mcasp->slot_width;
|
||||
|
||||
for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) {
|
||||
if (snd_mask_test(fmt, i)) {
|
||||
if (snd_pcm_format_width(i) <= slot_width) {
|
||||
snd_mask_set(&nfmt, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return snd_mask_refine(fmt, &nfmt);
|
||||
}
|
||||
|
||||
static const unsigned int davinci_mcasp_dai_rates[] = {
|
||||
8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000,
|
||||
88200, 96000, 176400, 192000,
|
||||
@ -1378,7 +1400,7 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
|
||||
struct davinci_mcasp_ruledata *ruledata =
|
||||
&mcasp->ruledata[substream->stream];
|
||||
u32 max_channels = 0;
|
||||
int i, dir;
|
||||
int i, dir, ret;
|
||||
int tdm_slots = mcasp->tdm_slots;
|
||||
|
||||
/* Do not allow more then one stream per direction */
|
||||
@ -1407,6 +1429,7 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
|
||||
max_channels++;
|
||||
}
|
||||
ruledata->serializers = max_channels;
|
||||
ruledata->mcasp = mcasp;
|
||||
max_channels *= tdm_slots;
|
||||
/*
|
||||
* If the already active stream has less channels than the calculated
|
||||
@ -1432,20 +1455,22 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
|
||||
0, SNDRV_PCM_HW_PARAM_CHANNELS,
|
||||
&mcasp->chconstr[substream->stream]);
|
||||
|
||||
if (mcasp->slot_width)
|
||||
snd_pcm_hw_constraint_minmax(substream->runtime,
|
||||
SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
|
||||
8, mcasp->slot_width);
|
||||
if (mcasp->slot_width) {
|
||||
/* Only allow formats require <= slot_width bits on the bus */
|
||||
ret = snd_pcm_hw_rule_add(substream->runtime, 0,
|
||||
SNDRV_PCM_HW_PARAM_FORMAT,
|
||||
davinci_mcasp_hw_rule_slot_width,
|
||||
ruledata,
|
||||
SNDRV_PCM_HW_PARAM_FORMAT, -1);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we rely on implicit BCLK divider setting we should
|
||||
* set constraints based on what we can provide.
|
||||
*/
|
||||
if (mcasp->bclk_master && mcasp->bclk_div == 0 && mcasp->sysclk_freq) {
|
||||
int ret;
|
||||
|
||||
ruledata->mcasp = mcasp;
|
||||
|
||||
ret = snd_pcm_hw_rule_add(substream->runtime, 0,
|
||||
SNDRV_PCM_HW_PARAM_RATE,
|
||||
davinci_mcasp_hw_rule_rate,
|
||||
|
Loading…
x
Reference in New Issue
Block a user