ASoC: pcm3168a: Add support for multi DIN/DOUT with TDM slots parameter
authorPeter Ujfalusi <peter.ujfalusi@ti.com>
Thu, 20 Jun 2019 09:26:56 +0000 (12:26 +0300)
committerMark Brown <broonie@kernel.org>
Thu, 20 Jun 2019 12:00:19 +0000 (13:00 +0100)
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>
sound/soc/codecs/pcm3168a.c

index e165894..d4e3721 100644 (file)
@@ -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: