summaryrefslogtreecommitdiff
path: root/sound/soc/codecs/pcm3168a.c
diff options
context:
space:
mode:
authorPeter Ujfalusi <peter.ujfalusi@ti.com>2019-06-20 12:26:56 +0300
committerMark Brown <broonie@kernel.org>2019-06-20 15:00:19 +0300
commit9700022109b6c495fb571f77324d34b294b29145 (patch)
treec87df2447cd647fc2b1b48812898743b5dcc998a /sound/soc/codecs/pcm3168a.c
parentb5d8dffb8cc9792c3bb4310e142932c8bc5c0387 (diff)
downloadlinux-9700022109b6c495fb571f77324d34b294b29145.tar.xz
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>
Diffstat (limited to 'sound/soc/codecs/pcm3168a.c')
-rw-r--r--sound/soc/codecs/pcm3168a.c31
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: