From c935ff0f9b9b683ac24cacecb6cdbfd368b5235f Mon Sep 17 00:00:00 2001 From: Jonathan Hunter Date: Mon, 21 Jan 2019 20:05:09 +0000 Subject: [PATCH] ASoC: tegra-alt: Fix I2S slot mask When the number of channels for an I2S interface is overridden from userspace, if the I2S interface is being used in TDM mode where there are more than 2 channels, the I2S SLOT_CTRL register may not be configured correctly. For example, if using the AMX to the multiplex 4 mono channels into a single 4 channel TDM stream that is then routed to an I2S interface, the number of channels seen by the I2S interface is 4 where as each input stream to the AMX only has a single channel. Therefore, the number of channels for the I2S interface needs to be manually set to 4 from userspace. However, when this is done the I2S SLOT_CTRL register is still configured with the default RX and TX slot mask. To fix this, if the number of channels for the I2S interface is overridden from userspace, then if using TDM modes, also override the RX and TX slot mask. Bug 2382530 Change-Id: I2df564c8e8ad5d7463a767a1e2197e26fe0c57e5 Signed-off-by: Jonathan Hunter Reviewed-on: https://git-master.nvidia.com/r/2000401 (cherry picked from commit b888cf568c726fed1e97882b9fe8deae4d6df6d9) Reviewed-on: https://git-master.nvidia.com/r/2002199 Reviewed-by: svc-mobile-coverity Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Bibek Basu Reviewed-by: mobile promotions Tested-by: mobile promotions --- sound/soc/tegra-alt/tegra210_i2s_alt.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/sound/soc/tegra-alt/tegra210_i2s_alt.c b/sound/soc/tegra-alt/tegra210_i2s_alt.c index 82c26b40..821aeb4b 100644 --- a/sound/soc/tegra-alt/tegra210_i2s_alt.c +++ b/sound/soc/tegra-alt/tegra210_i2s_alt.c @@ -542,7 +542,7 @@ static int tegra210_i2s_hw_params(struct snd_pcm_substream *substream, { struct device *dev = dai->dev; struct tegra210_i2s *i2s = snd_soc_dai_get_drvdata(dai); - unsigned int mask, val, reg, frame_format; + unsigned int mask, val, reg, frame_format, rx_mask, tx_mask; int ret, sample_size, channels, srate, i2sclock, bitcnt, max_th; struct tegra210_xbar_cif_conf cif_conf; @@ -598,16 +598,21 @@ static int tegra210_i2s_hw_params(struct snd_pcm_substream *substream, if (i2s->sample_rate_via_control) srate = i2s->sample_rate_via_control; - if (i2s->channels_via_control) + if (i2s->channels_via_control) { channels = i2s->channels_via_control; + rx_mask = tx_mask = (1 << channels) - 1; + } else { + rx_mask = i2s->rx_mask; + tx_mask = i2s->tx_mask; + } regmap_read(i2s->regmap, TEGRA210_I2S_CTRL, &val); frame_format = val & TEGRA210_I2S_CTRL_FRAME_FORMAT_MASK; if (frame_format == TEGRA210_I2S_CTRL_FRAME_FORMAT_FSYNC_MODE) { - i2s->soc_data->set_slot_ctrl(i2s->regmap, channels, - i2s->tx_mask, i2s->rx_mask); + i2s->soc_data->set_slot_ctrl(i2s->regmap, channels, tx_mask, + rx_mask); cif_conf.audio_channels = channels; cif_conf.client_channels = channels; } else {