mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-24 10:11:26 +03:00
tegra-alt: add controls for CIF channel config
Add controls for configuring CIF channels for AMX and ADMAIF. Add controls for CIF stereo/mono conversion for SFC. Remove non-zero check in put_byte_map() to update byte mask. Due to this check, byte 0 map wasn't getting updated for valid value of 0. Bug 200100724 Change-Id: I37b96594464f699db93552f5c1e148c51e963c5e Signed-off-by: Viraj Karandikar <vkarandikar@nvidia.com> Reviewed-on: http://git-master/r/760115 (cherry picked from commit 8c2d36d0303aac45553cc64c148d8c62a8bcf880) Reviewed-on: http://git-master/r/772770 (cherry picked from commit d17f88c03e55d8f0a250cd013b7d18a27c0d789c) Reviewed-on: http://git-master/r/781739 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Ravindra Lokhande <rlokhande@nvidia.com>
This commit is contained in:
committed by
Sameer Pujar
parent
3dca31ad46
commit
0fbbcc3bfe
@@ -32,10 +32,10 @@
|
||||
|
||||
#include "tegra_pcm_alt.h"
|
||||
#include "tegra210_xbar_alt.h"
|
||||
#include "tegra210_admaif_alt.h"
|
||||
#if defined(CONFIG_ARCH_TEGRA_18x_SOC)
|
||||
#include <sound/tegra_audio.h>
|
||||
#endif
|
||||
#include "tegra210_admaif_alt.h"
|
||||
|
||||
#define DRV_NAME "tegra210-ape-admaif"
|
||||
|
||||
@@ -300,8 +300,13 @@ static int tegra210_admaif_hw_params(struct snd_pcm_substream *substream,
|
||||
int valid_bit;
|
||||
|
||||
memset(&cif_conf, 0, sizeof(struct tegra210_xbar_cif_conf));
|
||||
cif_conf.audio_channels = params_channels(params);
|
||||
cif_conf.client_channels = params_channels(params);
|
||||
if (admaif->override_channels[dai->id] > 0) {
|
||||
cif_conf.audio_channels = admaif->override_channels[dai->id];
|
||||
cif_conf.client_channels = admaif->override_channels[dai->id];
|
||||
} else {
|
||||
cif_conf.audio_channels = params_channels(params);
|
||||
cif_conf.client_channels = params_channels(params);
|
||||
}
|
||||
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S8:
|
||||
@@ -462,6 +467,34 @@ static struct snd_soc_dai_ops tegra210_admaif_dai_ops = {
|
||||
.trigger = tegra210_admaif_trigger,
|
||||
};
|
||||
|
||||
static int tegra210_admaif_get_channels(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
struct soc_mixer_control *mc =
|
||||
(struct soc_mixer_control *)kcontrol->private_value;
|
||||
struct tegra210_admaif *admaif = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
ucontrol->value.integer.value[0] = admaif->override_channels[mc->reg];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_admaif_put_channels(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct soc_mixer_control *mc =
|
||||
(struct soc_mixer_control *)kcontrol->private_value;
|
||||
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
struct tegra210_admaif *admaif = snd_soc_codec_get_drvdata(codec);
|
||||
int value = ucontrol->value.integer.value[0];
|
||||
|
||||
if (value > 0 && value <= 16) {
|
||||
admaif->override_channels[mc->reg] = value;
|
||||
return 0;
|
||||
} else
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int tegra210_admaif_dai_probe(struct snd_soc_dai *dai)
|
||||
{
|
||||
struct tegra210_admaif *admaif = snd_soc_dai_get_drvdata(dai);
|
||||
@@ -680,6 +713,33 @@ static const struct snd_soc_dapm_route tegra210_admaif_routes[] = {
|
||||
ADMAIF_ROUTES(20)
|
||||
};
|
||||
|
||||
#define TEGRA210_ADMAIF_CHANNEL_CTRL(reg) \
|
||||
SOC_SINGLE_EXT("ADMAIF" #reg " Channels", reg - 1, 0, 16, 0, \
|
||||
tegra210_admaif_get_channels, tegra210_admaif_put_channels)
|
||||
|
||||
static struct snd_kcontrol_new tegra210_admaif_controls[] = {
|
||||
TEGRA210_ADMAIF_CHANNEL_CTRL(1),
|
||||
TEGRA210_ADMAIF_CHANNEL_CTRL(2),
|
||||
TEGRA210_ADMAIF_CHANNEL_CTRL(3),
|
||||
TEGRA210_ADMAIF_CHANNEL_CTRL(4),
|
||||
TEGRA210_ADMAIF_CHANNEL_CTRL(5),
|
||||
TEGRA210_ADMAIF_CHANNEL_CTRL(6),
|
||||
TEGRA210_ADMAIF_CHANNEL_CTRL(7),
|
||||
TEGRA210_ADMAIF_CHANNEL_CTRL(8),
|
||||
TEGRA210_ADMAIF_CHANNEL_CTRL(9),
|
||||
TEGRA210_ADMAIF_CHANNEL_CTRL(10),
|
||||
TEGRA210_ADMAIF_CHANNEL_CTRL(11),
|
||||
TEGRA210_ADMAIF_CHANNEL_CTRL(12),
|
||||
TEGRA210_ADMAIF_CHANNEL_CTRL(13),
|
||||
TEGRA210_ADMAIF_CHANNEL_CTRL(14),
|
||||
TEGRA210_ADMAIF_CHANNEL_CTRL(15),
|
||||
TEGRA210_ADMAIF_CHANNEL_CTRL(16),
|
||||
TEGRA210_ADMAIF_CHANNEL_CTRL(17),
|
||||
TEGRA210_ADMAIF_CHANNEL_CTRL(18),
|
||||
TEGRA210_ADMAIF_CHANNEL_CTRL(19),
|
||||
TEGRA210_ADMAIF_CHANNEL_CTRL(20)
|
||||
};
|
||||
|
||||
static int tegra210_admaif_codec_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct tegra210_admaif *admaif = snd_soc_codec_get_drvdata(codec);
|
||||
@@ -695,6 +755,8 @@ static struct snd_soc_codec_driver tegra210_admaif_codec = {
|
||||
.num_dapm_widgets = TEGRA210_ADMAIF_CHANNEL_COUNT * 4,
|
||||
.dapm_routes = tegra210_admaif_routes,
|
||||
.num_dapm_routes = TEGRA210_ADMAIF_CHANNEL_COUNT * 6,
|
||||
.controls = tegra210_admaif_controls,
|
||||
.num_controls = ARRAY_SIZE(tegra210_admaif_controls),
|
||||
.idle_bias_off = 1,
|
||||
};
|
||||
|
||||
@@ -748,7 +810,7 @@ static int tegra210_admaif_probe(struct platform_device *pdev)
|
||||
admaif->soc_data->num_ch,
|
||||
GFP_KERNEL);
|
||||
if (!admaif->capture_dma_data) {
|
||||
dev_err(&pdev->dev, "Can't allocate tegra_alt_pcm_dma_params\n");
|
||||
dev_err(&pdev->dev, "Can't allocate capture_dma_data\n");
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
@@ -758,7 +820,7 @@ static int tegra210_admaif_probe(struct platform_device *pdev)
|
||||
admaif->soc_data->num_ch,
|
||||
GFP_KERNEL);
|
||||
if (!admaif->playback_dma_data) {
|
||||
dev_err(&pdev->dev, "Can't allocate tegra_alt_pcm_dma_params\n");
|
||||
dev_err(&pdev->dev, "Can't allocate playback_dma_data\n");
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -311,16 +311,22 @@ static int tegra210_amx_suspend(struct device *dev)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int tegra210_amx_set_audio_cif(struct tegra210_amx *amx,
|
||||
static int tegra210_amx_set_audio_cif(struct snd_soc_dai *dai,
|
||||
struct snd_pcm_hw_params *params,
|
||||
unsigned int reg)
|
||||
{
|
||||
struct tegra210_amx *amx = snd_soc_dai_get_drvdata(dai);
|
||||
int channels, audio_bits;
|
||||
struct tegra210_xbar_cif_conf cif_conf;
|
||||
|
||||
memset(&cif_conf, 0, sizeof(struct tegra210_xbar_cif_conf));
|
||||
|
||||
channels = params_channels(params);
|
||||
if (strstr(dai->name, "OUT")) {
|
||||
channels = amx->output_channels > 0 ?
|
||||
amx->output_channels : params_channels(params);
|
||||
} else
|
||||
channels = params_channels(params);
|
||||
|
||||
if (channels < 1 || channels > 16)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -351,15 +357,13 @@ static int tegra210_amx_set_audio_cif(struct tegra210_amx *amx,
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int tegra210_amx_in_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct tegra210_amx *amx = snd_soc_dai_get_drvdata(dai);
|
||||
int ret;
|
||||
|
||||
ret = tegra210_amx_set_audio_cif(amx, params,
|
||||
ret = tegra210_amx_set_audio_cif(dai, params,
|
||||
TEGRA210_AMX_AXBAR_RX1_CIF_CTRL +
|
||||
(dai->id * TEGRA210_AMX_AUDIOCIF_CH_STRIDE));
|
||||
|
||||
@@ -394,17 +398,17 @@ static int tegra210_amx_out_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct tegra210_amx *amx = snd_soc_dai_get_drvdata(dai);
|
||||
int ret;
|
||||
if (tegra_platform_is_unit_fpga() || tegra_platform_is_fpga()) {
|
||||
/* update map ram */
|
||||
struct tegra210_amx *amx = snd_soc_dai_get_drvdata(dai);
|
||||
tegra210_amx_set_master_stream(amx, 0,
|
||||
TEGRA210_AMX_WAIT_ON_ANY);
|
||||
tegra210_amx_update_map_ram(amx);
|
||||
tegra210_amx_set_out_byte_mask(amx);
|
||||
}
|
||||
|
||||
ret = tegra210_amx_set_audio_cif(amx, params,
|
||||
ret = tegra210_amx_set_audio_cif(dai, params,
|
||||
TEGRA210_AMX_AXBAR_TX_CIF_CTRL);
|
||||
|
||||
return ret;
|
||||
@@ -493,24 +497,39 @@ static int tegra210_amx_put_byte_map(struct snd_kcontrol *kcontrol,
|
||||
/* update byte map */
|
||||
tegra210_amx_set_map_table(amx, reg, stream, channel, byte);
|
||||
|
||||
/* update byte_mask */
|
||||
if (value) {
|
||||
/* enable slot */
|
||||
if (reg > 31)
|
||||
amx->byte_mask[1] |= (1 << (reg - 32));
|
||||
else
|
||||
amx->byte_mask[0] |= (1 << reg);
|
||||
} else {
|
||||
/* disable slot */
|
||||
if (reg > 31)
|
||||
amx->byte_mask[1] &= ~(1 << (reg - 32));
|
||||
else
|
||||
amx->byte_mask[0] &= ~(1 << reg);
|
||||
}
|
||||
/* update byte_mask to enable slot */
|
||||
if (reg > 31)
|
||||
amx->byte_mask[1] |= (1 << (reg - 32));
|
||||
else
|
||||
amx->byte_mask[0] |= (1 << reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_amx_get_output_channels(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
struct tegra210_amx *amx = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
ucontrol->value.integer.value[0] = amx->output_channels;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_amx_put_output_channels(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
struct tegra210_amx *amx = snd_soc_codec_get_drvdata(codec);
|
||||
int value = ucontrol->value.integer.value[0];
|
||||
|
||||
if (value > 0 && value <= 16) {
|
||||
amx->output_channels = value;
|
||||
return 0;
|
||||
} else
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int tegra210_amx_codec_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct tegra210_amx *amx = snd_soc_codec_get_drvdata(codec);
|
||||
@@ -590,7 +609,12 @@ static const struct snd_soc_dapm_route tegra210_amx_routes[] = {
|
||||
SOC_SINGLE_EXT("Byte Map " #reg, reg, 0, 0xFF, 0, \
|
||||
tegra210_amx_get_byte_map, tegra210_amx_put_byte_map)
|
||||
|
||||
static struct snd_kcontrol_new tegra210_amx_map_controls[] = {
|
||||
#define TEGRA210_AMX_OUTPUT_CHANNELS_CTRL(reg) \
|
||||
SOC_SINGLE_EXT("Output Channels", reg, 0, 16, 0, \
|
||||
tegra210_amx_get_output_channels, \
|
||||
tegra210_amx_put_output_channels)
|
||||
|
||||
static struct snd_kcontrol_new tegra210_amx_controls[] = {
|
||||
TEGRA210_AMX_BYTE_MAP_CTRL(0),
|
||||
TEGRA210_AMX_BYTE_MAP_CTRL(1),
|
||||
TEGRA210_AMX_BYTE_MAP_CTRL(2),
|
||||
@@ -655,6 +679,8 @@ static struct snd_kcontrol_new tegra210_amx_map_controls[] = {
|
||||
TEGRA210_AMX_BYTE_MAP_CTRL(61),
|
||||
TEGRA210_AMX_BYTE_MAP_CTRL(62),
|
||||
TEGRA210_AMX_BYTE_MAP_CTRL(63),
|
||||
|
||||
TEGRA210_AMX_OUTPUT_CHANNELS_CTRL(1),
|
||||
};
|
||||
|
||||
static struct snd_soc_codec_driver tegra210_amx_codec = {
|
||||
@@ -663,8 +689,8 @@ static struct snd_soc_codec_driver tegra210_amx_codec = {
|
||||
.num_dapm_widgets = ARRAY_SIZE(tegra210_amx_widgets),
|
||||
.dapm_routes = tegra210_amx_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(tegra210_amx_routes),
|
||||
.controls = tegra210_amx_map_controls,
|
||||
.num_controls = ARRAY_SIZE(tegra210_amx_map_controls),
|
||||
.controls = tegra210_amx_controls,
|
||||
.num_controls = ARRAY_SIZE(tegra210_amx_controls),
|
||||
.idle_bias_off = 1,
|
||||
};
|
||||
|
||||
|
||||
@@ -311,8 +311,19 @@ static int tegra210_sfc_set_audio_cif(struct tegra210_sfc *sfc,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (sfc->stereo_conv_input > 0 && 2 == channels &&
|
||||
(reg == TEGRA210_SFC_AXBAR_RX_CIF_CTRL)) {
|
||||
cif_conf.stereo_conv = sfc->stereo_conv_input - 1;
|
||||
cif_conf.client_channels = 1;
|
||||
} else if (sfc->mono_conv_output > 0 && 2 == channels &&
|
||||
(reg == TEGRA210_SFC_AXBAR_TX_CIF_CTRL)) {
|
||||
cif_conf.mono_conv = sfc->mono_conv_output - 1;
|
||||
cif_conf.client_channels = 1;
|
||||
} else {
|
||||
cif_conf.client_channels = channels;
|
||||
}
|
||||
|
||||
cif_conf.audio_channels = channels;
|
||||
cif_conf.client_channels = channels;
|
||||
cif_conf.audio_bits = audio_bits;
|
||||
if (sfc->format_in && (reg == TEGRA210_SFC_AXBAR_RX_CIF_CTRL))
|
||||
cif_conf.audio_bits = tegra210_sfc_fmt_values[sfc->format_in];
|
||||
@@ -556,6 +567,46 @@ static int tegra210_sfc_init_put(struct snd_kcontrol *kcontrol,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_sfc_get_stereo_conv(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
struct tegra210_sfc *sfc = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
ucontrol->value.integer.value[0] = sfc->stereo_conv_input;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_sfc_put_stereo_conv(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
struct tegra210_sfc *sfc = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
sfc->stereo_conv_input = ucontrol->value.integer.value[0];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_sfc_get_mono_conv(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
struct tegra210_sfc *sfc = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
ucontrol->value.integer.value[0] = sfc->mono_conv_output;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_sfc_put_mono_conv(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
struct tegra210_sfc *sfc = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
sfc->mono_conv_output = ucontrol->value.integer.value[0];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_sfc_codec_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct tegra210_sfc *sfc = snd_soc_codec_get_drvdata(codec);
|
||||
@@ -624,11 +675,29 @@ static const char * const tegra210_sfc_format_text[] = {
|
||||
"32",
|
||||
};
|
||||
|
||||
static const char * const tegra210_sfc_stereo_conv_text[] = {
|
||||
"None", "CH0", "CH1", "AVG",
|
||||
};
|
||||
|
||||
static const char * const tegra210_sfc_mono_conv_text[] = {
|
||||
"None", "ZERO", "COPY",
|
||||
};
|
||||
|
||||
static const struct soc_enum tegra210_sfc_format_enum =
|
||||
SOC_ENUM_SINGLE(SND_SOC_NOPM, 0,
|
||||
ARRAY_SIZE(tegra210_sfc_format_text),
|
||||
tegra210_sfc_format_text);
|
||||
|
||||
static const struct soc_enum tegra210_sfc_stereo_conv_enum =
|
||||
SOC_ENUM_SINGLE(SND_SOC_NOPM, 0,
|
||||
ARRAY_SIZE(tegra210_sfc_stereo_conv_text),
|
||||
tegra210_sfc_stereo_conv_text);
|
||||
|
||||
static const struct soc_enum tegra210_sfc_mono_conv_enum =
|
||||
SOC_ENUM_SINGLE(SND_SOC_NOPM, 0,
|
||||
ARRAY_SIZE(tegra210_sfc_mono_conv_text),
|
||||
tegra210_sfc_mono_conv_text);
|
||||
|
||||
static const struct snd_kcontrol_new tegra210_sfc_controls[] = {
|
||||
SOC_SINGLE_EXT("input rate", 0, 0, 192000, 0,
|
||||
tegra210_sfc_get_srate, tegra210_sfc_put_srate),
|
||||
@@ -638,6 +707,10 @@ static const struct snd_kcontrol_new tegra210_sfc_controls[] = {
|
||||
tegra210_sfc_get_format, tegra210_sfc_put_format),
|
||||
SOC_SINGLE_EXT("init", 0, 0, 1, 0,
|
||||
tegra210_sfc_init_get, tegra210_sfc_init_put),
|
||||
SOC_ENUM_EXT("input stereo conv", tegra210_sfc_stereo_conv_enum,
|
||||
tegra210_sfc_get_stereo_conv, tegra210_sfc_put_stereo_conv),
|
||||
SOC_ENUM_EXT("output mono conv", tegra210_sfc_mono_conv_enum,
|
||||
tegra210_sfc_get_mono_conv, tegra210_sfc_put_mono_conv),
|
||||
};
|
||||
|
||||
static struct snd_soc_codec_driver tegra210_sfc_codec = {
|
||||
|
||||
Reference in New Issue
Block a user