From 834b540cf9520a39bbdc3e37b2d7e017c6af29fc Mon Sep 17 00:00:00 2001 From: Mohan Kumar Date: Sun, 24 Mar 2019 19:13:19 +0530 Subject: [PATCH] ASoC: tegra-alt: fix admaif mono/stereo conv The admaif cif conversion from mono to stereo and vise-versa config will take effect only when client/xbar channels are 1/2 or 2/1. If this condition doesn't satisfy, the configured bit-field for mono_conv and stereo_conv in cif ctrl register will not take effect. Considering this the current code needs to be fixed. - For Playback path: The Client and Audio channels won't be different as the data flows from external memory to ahub. So override channel control have no say on this path, for client_channel=1 and if "mono to stereo conv" control was set then override audio_channel=2 for stereo conversion. - For Capture path: The Client channel will be based on params_channels() and the xbar channels can be different from client channel as it comes from other ahub modules which can output different channel number compared to client, So the "ADMAIFx Channel" wil be used for capture path to feed proper xbar channel available. During stereo to mono conversion i.e when audio_channel=2 and client_channel=1, the configuration in the bitfield mono_conv will take effect. Bug 200500656 Change-Id: Ie61aed848eb35715414a7d8f0e00eae9066b32d3 Signed-off-by: Mohan Kumar Reviewed-on: https://git-master.nvidia.com/r/2080175 Reviewed-by: mobile promotions Tested-by: mobile promotions --- sound/soc/tegra-alt/tegra210_admaif_alt.c | 42 +++++++++++++---------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/sound/soc/tegra-alt/tegra210_admaif_alt.c b/sound/soc/tegra-alt/tegra210_admaif_alt.c index 92ab2eaf..840f9635 100644 --- a/sound/soc/tegra-alt/tegra210_admaif_alt.c +++ b/sound/soc/tegra-alt/tegra210_admaif_alt.c @@ -396,13 +396,6 @@ static int tegra_admaif_hw_params(struct snd_pcm_substream *substream, memset(&cif_conf, 0, sizeof(struct tegra210_xbar_cif_conf)); - channels = params_channels(params); - if (admaif->override_channels[dai->id] > 0) - channels = admaif->override_channels[dai->id]; - - cif_conf.audio_channels = channels; - cif_conf.client_channels = channels; - switch (params_format(params)) { case SNDRV_PCM_FORMAT_S8: cif_conf.audio_bits = TEGRA210_AUDIOCIF_BITS_8; @@ -429,30 +422,43 @@ static int tegra_admaif_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } + channels = params_channels(params); + cif_conf.client_channels = channels; + cif_conf.audio_channels = channels; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { reg = admaif->soc_data->tx_base + TEGRA_ADMAIF_CHAN_ACIF_TX_CTRL + (dai->id * TEGRA_ADMAIF_CHANNEL_REG_STRIDE); - /* For playback path, the mono input from client channel - * can be converted to stereo using cif controls. - */ - if (admaif->tx_mono_to_stereo[dai->id] > 0) { + /* For playback path, if client channel is 1 and mono to + * stereo control was non-zero, then audio channels will be + * set to 2 for mono to stereo conversion. + */ + if ((admaif->tx_mono_to_stereo[dai->id] > 0) && + (channels == 1)) { cif_conf.mono_conv = admaif->tx_mono_to_stereo[dai->id] - 1; cif_conf.audio_channels = 2; - cif_conf.client_channels = 1; } } else { reg = TEGRA_ADMAIF_CHAN_ACIF_RX_CTRL + (dai->id * TEGRA_ADMAIF_CHANNEL_REG_STRIDE); - /* For capture path, the stereo audio channel can be - * converted to mono using cif controls. - */ - if (admaif->rx_stereo_to_mono[dai->id] > 0) { + + /* The override channels are needed only for capture path as + * the audio and client channels can be different on RX path. + */ + if (admaif->override_channels[dai->id] > 0) { + cif_conf.audio_channels = + admaif->override_channels[dai->id]; + } + + /* For capture path, if client channel is 1 and audio channel + * is 2, only then stereo to mono settings will take effect. + */ + if ((admaif->rx_stereo_to_mono[dai->id] > 0) && + (cif_conf.audio_channels == 2) && (channels == 1)) { cif_conf.stereo_conv = admaif->rx_stereo_to_mono[dai->id] - 1; - cif_conf.audio_channels = 2; - cif_conf.client_channels = 1; } }