ASoC: tegra-alt: Fix support for I2S mono playback

Mono playback via the RT5658 codec on the Jetson TX1/TX2/Xavier is
distorted. Although the RT5658 codec is configured for standard I2S
timings (implying 2 channels), the Tegra XBAR should convert the mono
audio track from one channel to two channels. The problem is caused
because the 'CHANNEL_BIT_CNT' field in the I2S Timing Register is
being configured incorrectly. For mono playback in I2S mode (or LRCK
mode) the CHANNEL_BIT_CNT is being set to 31 instead of 15 by fixing
this mono playback works as expected.

Please note that the 'bitcnt' value programmed into the I2S Timing
Register is verified to see that it is not bigger than the mask for
the CHANNEL_BIT_CNT field. However, this is done before we shift the
bitcnt by 1 for I2S mode. Therefore, ensure the bitcnt is shifted by
1 before we do the check.

Mono playback has been tested by playing the following audio clip ...

aplay -D hw:1,0 /usr/share/sounds/alsa/Front_Center.wav

Bug 2257806

Change-Id: I4d306ccef891282e96c300d90bad2a5b6efc9968
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1777096
Reviewed-by: Sameer Pujar <spujar@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Jon Hunter
2018-07-12 16:39:43 +01:00
committed by Sameer Pujar
parent cb3d3637bf
commit 5da3305cdf

View File

@@ -629,6 +629,9 @@ static int tegra210_i2s_hw_params(struct snd_pcm_substream *substream,
bitcnt = (i2sclock / srate) - 1;
if (frame_format == TEGRA210_I2S_FRAME_FORMAT_LRCK)
bitcnt >>= 1;
if ((bitcnt < 0) ||
(bitcnt > TEGRA210_I2S_TIMING_CHANNEL_BIT_CNT_MASK)) {
dev_err(dev, "Can't set channel bit count\n");
@@ -641,11 +644,7 @@ static int tegra210_i2s_hw_params(struct snd_pcm_substream *substream,
return ret;
}
if ((frame_format == TEGRA210_I2S_FRAME_FORMAT_LRCK) && (channels > 1)) {
val = (bitcnt >> 1) <<
TEGRA210_I2S_TIMING_CHANNEL_BIT_CNT_SHIFT;
} else
val = bitcnt << TEGRA210_I2S_TIMING_CHANNEL_BIT_CNT_SHIFT;
val = bitcnt << TEGRA210_I2S_TIMING_CHANNEL_BIT_CNT_SHIFT;
if (i2sclock % (2 * srate))
val |= TEGRA210_I2S_TIMING_NON_SYM_EN;