ASoC: pcm3168a: Add support for multi DIN/DOUT with TDM slots parameter
The driver was wired to be only usable in DIN1/DOUT1 mode, switching between TDM and non TDM modes based on the number of channels. While keeping this functionality for compatibility add support for using all DIN1/2/3/4 and DOUT1/2/3 if it is needed by setting the TDM slots to 2. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com> Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
b5d8dffb8c
commit
9700022109
|
@ -411,9 +411,11 @@ static int pcm3168a_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
pcm3168a->tdm_slots = slots;
|
if (pcm3168a->tdm_slots && pcm3168a->tdm_slots != slots) {
|
||||||
pcm3168a->tdm_mask[SNDRV_PCM_STREAM_PLAYBACK] = tx_mask;
|
dev_err(component->dev, "Not matching slots %d vs %d\n",
|
||||||
pcm3168a->tdm_mask[SNDRV_PCM_STREAM_CAPTURE] = rx_mask;
|
pcm3168a->tdm_slots, slots);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
if (pcm3168a->slot_width && pcm3168a->slot_width != slot_width) {
|
if (pcm3168a->slot_width && pcm3168a->slot_width != slot_width) {
|
||||||
dev_err(component->dev, "Not matching slot_width %d vs %d\n",
|
dev_err(component->dev, "Not matching slot_width %d vs %d\n",
|
||||||
|
@ -421,7 +423,11 @@ static int pcm3168a_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pcm3168a->tdm_slots = slots;
|
||||||
pcm3168a->slot_width = slot_width;
|
pcm3168a->slot_width = slot_width;
|
||||||
|
pcm3168a->tdm_mask[SNDRV_PCM_STREAM_PLAYBACK] = tx_mask;
|
||||||
|
pcm3168a->tdm_mask[SNDRV_PCM_STREAM_CAPTURE] = rx_mask;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -434,11 +440,10 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream,
|
||||||
bool tx, master_mode;
|
bool tx, master_mode;
|
||||||
u32 val, mask, shift, reg;
|
u32 val, mask, shift, reg;
|
||||||
unsigned int rate, fmt, ratio, max_ratio;
|
unsigned int rate, fmt, ratio, max_ratio;
|
||||||
unsigned int chan;
|
unsigned int tdm_slots;
|
||||||
int i, slot_width;
|
int i, slot_width;
|
||||||
|
|
||||||
rate = params_rate(params);
|
rate = params_rate(params);
|
||||||
chan = params_channels(params);
|
|
||||||
|
|
||||||
ratio = pcm3168a->sysclk / rate;
|
ratio = pcm3168a->sysclk / rate;
|
||||||
|
|
||||||
|
@ -495,8 +500,20 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* for TDM */
|
if (pcm3168a->tdm_slots)
|
||||||
if (chan > 2) {
|
tdm_slots = pcm3168a->tdm_slots;
|
||||||
|
else
|
||||||
|
tdm_slots = params_channels(params);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Switch the codec to TDM mode when more than 2 TDM slots are needed
|
||||||
|
* for the stream.
|
||||||
|
* If pcm3168a->tdm_slots is not set or set to more than 2 (8/6 usually)
|
||||||
|
* then DIN1/DOUT1 is used in TDM mode.
|
||||||
|
* If pcm3168a->tdm_slots is set to 2 then DIN1/2/3/4 and DOUT1/2/3 is
|
||||||
|
* used in normal mode, no need to switch to TDM modes.
|
||||||
|
*/
|
||||||
|
if (tdm_slots > 2) {
|
||||||
switch (fmt) {
|
switch (fmt) {
|
||||||
case PCM3168A_FMT_I2S:
|
case PCM3168A_FMT_I2S:
|
||||||
case PCM3168A_FMT_DSP_A:
|
case PCM3168A_FMT_DSP_A:
|
||||||
|
|
Loading…
Reference in New Issue