diff options
author | Peter Ujfalusi <peter.ujfalusi@ti.com> | 2019-06-20 12:26:56 +0300 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2019-06-20 13:00:19 +0100 |
commit | 9700022109b6c495fb571f77324d34b294b29145 (patch) | |
tree | c87df2447cd647fc2b1b48812898743b5dcc998a | |
parent | b5d8dffb8cc9792c3bb4310e142932c8bc5c0387 (diff) | |
download | linux-stable-9700022109b6c495fb571f77324d34b294b29145.tar.gz linux-stable-9700022109b6c495fb571f77324d34b294b29145.tar.bz2 linux-stable-9700022109b6c495fb571f77324d34b294b29145.zip |
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>
-rw-r--r-- | sound/soc/codecs/pcm3168a.c | 31 |
1 files changed, 24 insertions, 7 deletions
diff --git a/sound/soc/codecs/pcm3168a.c b/sound/soc/codecs/pcm3168a.c index e1658947090b..d4e372182c55 100644 --- a/sound/soc/codecs/pcm3168a.c +++ b/sound/soc/codecs/pcm3168a.c @@ -411,9 +411,11 @@ static int pcm3168a_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, return -EINVAL; } - pcm3168a->tdm_slots = slots; - pcm3168a->tdm_mask[SNDRV_PCM_STREAM_PLAYBACK] = tx_mask; - pcm3168a->tdm_mask[SNDRV_PCM_STREAM_CAPTURE] = rx_mask; + if (pcm3168a->tdm_slots && pcm3168a->tdm_slots != slots) { + dev_err(component->dev, "Not matching slots %d vs %d\n", + pcm3168a->tdm_slots, slots); + return -EINVAL; + } if (pcm3168a->slot_width && pcm3168a->slot_width != slot_width) { 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; } + pcm3168a->tdm_slots = slots; 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; } @@ -434,11 +440,10 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream, bool tx, master_mode; u32 val, mask, shift, reg; unsigned int rate, fmt, ratio, max_ratio; - unsigned int chan; + unsigned int tdm_slots; int i, slot_width; rate = params_rate(params); - chan = params_channels(params); ratio = pcm3168a->sysclk / rate; @@ -495,8 +500,20 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - /* for TDM */ - if (chan > 2) { + if (pcm3168a->tdm_slots) + 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) { case PCM3168A_FMT_I2S: case PCM3168A_FMT_DSP_A: |