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 <mkumard@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/2080175
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Mohan Kumar
2019-03-24 19:13:19 +05:30
committed by Sameer Pujar
parent 95dd5b9e73
commit 834b540cf9

View File

@@ -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;
}
}