mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 17:25:35 +03:00
ASoC: tegra-alt: remove channel hard coding for I2S and ADMAIF
Currently CIF channels are overridden based on mono/stereo settings. This can be problematic for multi-channel use cases or the cases where user is intentionally overriding channels through mixer control. In such cases hard coding based on CIF mono/stereo settings can result in wrong behavior. Following are the changes in current patch, * Decouple CIF mono/stereo and CIF channel settings. It means that, user can override audio channels and CIF settings independently. Also these controls are provided for both playback and capture paths. * For ADMAIF, channel overrides are provided for both audio and client channels in both playback and capture paths. * For I2S, separate channel overrides for client channels is not needed in playback and capture paths. Hence a common client channel override control is provided. However for audio channels it is similar to the controls provided for ADMAIF. * Similar to channels, for I2S, audio bit format control is updated and provided separate controls in playback and capture paths. * "None" option is removed for mono/stereo to match HW register spec. Earlier channel was hard coded based on this. * For I2S, audio channels are used for CIF configuration and for the slot control client channels are used (earlier audio channels were getting used for slot control) * For upstream, we are standardizing mixer control names. For now, only relevant controls are updated. Going forward we need to take similar approach for all controls/modules. This needs to be reflected in test scripts and documentation as well. Bug 200503387 Change-Id: I04df9a3bda41e028edc46e86ecd1d80966bc83e1 Signed-off-by: Sameer Pujar <spujar@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/2244477 Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
@@ -158,6 +158,11 @@ enum {
|
|||||||
DATA_32BIT
|
DATA_32BIT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
ADMAIF_RX_PATH,
|
||||||
|
ADMAIF_TX_PATH,
|
||||||
|
ADMAIF_PATHS,
|
||||||
|
};
|
||||||
|
|
||||||
struct tegra_admaif_soc_data {
|
struct tegra_admaif_soc_data {
|
||||||
unsigned int num_ch;
|
unsigned int num_ch;
|
||||||
@@ -177,9 +182,10 @@ struct tegra_admaif {
|
|||||||
struct tegra_alt_pcm_dma_params *capture_dma_data;
|
struct tegra_alt_pcm_dma_params *capture_dma_data;
|
||||||
struct tegra_alt_pcm_dma_params *playback_dma_data;
|
struct tegra_alt_pcm_dma_params *playback_dma_data;
|
||||||
const struct tegra_admaif_soc_data *soc_data;
|
const struct tegra_admaif_soc_data *soc_data;
|
||||||
int *override_channels;
|
unsigned int *audio_ch_override[ADMAIF_PATHS];
|
||||||
int *tx_mono_to_stereo;
|
unsigned int *client_ch_override[ADMAIF_PATHS];
|
||||||
int *rx_stereo_to_mono;
|
unsigned int *mono_to_stereo[ADMAIF_PATHS];
|
||||||
|
unsigned int *stereo_to_mono[ADMAIF_PATHS];
|
||||||
int reg_dump_flag;
|
int reg_dump_flag;
|
||||||
void __iomem *base_addr;
|
void __iomem *base_addr;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -206,10 +206,11 @@ struct tegra210_i2s {
|
|||||||
struct notifier_block slgc_notifier;
|
struct notifier_block slgc_notifier;
|
||||||
int num_supplies;
|
int num_supplies;
|
||||||
int bclk_ratio;
|
int bclk_ratio;
|
||||||
int format_in;
|
int audio_fmt_override[I2S_PATHS];
|
||||||
int codec_bit_format;
|
int codec_bit_format;
|
||||||
int sample_rate_via_control;
|
int sample_rate_via_control;
|
||||||
int channels_via_control;
|
int audio_ch_override[I2S_PATHS];
|
||||||
|
int client_ch_override; /* common for both TX and RX */
|
||||||
int stereo_to_mono[I2S_PATHS];
|
int stereo_to_mono[I2S_PATHS];
|
||||||
int mono_to_stereo[I2S_PATHS];
|
int mono_to_stereo[I2S_PATHS];
|
||||||
unsigned int fsync_width;
|
unsigned int fsync_width;
|
||||||
|
|||||||
@@ -318,7 +318,7 @@ static int tegra_admaif_hw_params(struct snd_pcm_substream *substream,
|
|||||||
struct device *dev = dai->dev;
|
struct device *dev = dai->dev;
|
||||||
struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai);
|
struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai);
|
||||||
struct tegra210_xbar_cif_conf cif_conf;
|
struct tegra210_xbar_cif_conf cif_conf;
|
||||||
unsigned int reg;
|
unsigned int reg, path;
|
||||||
int valid_bit, channels;
|
int valid_bit, channels;
|
||||||
|
|
||||||
memset(&cif_conf, 0, sizeof(struct tegra210_xbar_cif_conf));
|
memset(&cif_conf, 0, sizeof(struct tegra210_xbar_cif_conf));
|
||||||
@@ -354,40 +354,26 @@ static int tegra_admaif_hw_params(struct snd_pcm_substream *substream,
|
|||||||
cif_conf.audio_channels = channels;
|
cif_conf.audio_channels = channels;
|
||||||
|
|
||||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||||
|
path = ADMAIF_TX_PATH;
|
||||||
reg = CH_TX_REG(TEGRA_ADMAIF_CHAN_ACIF_TX_CTRL, dai->id);
|
reg = CH_TX_REG(TEGRA_ADMAIF_CHAN_ACIF_TX_CTRL, dai->id);
|
||||||
|
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
|
path = ADMAIF_RX_PATH;
|
||||||
reg = CH_RX_REG(TEGRA_ADMAIF_CHAN_ACIF_RX_CTRL, dai->id);
|
reg = CH_RX_REG(TEGRA_ADMAIF_CHAN_ACIF_RX_CTRL, dai->id);
|
||||||
|
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (admaif->audio_ch_override[path][dai->id])
|
||||||
|
cif_conf.audio_channels =
|
||||||
|
admaif->audio_ch_override[path][dai->id];
|
||||||
|
|
||||||
|
if (admaif->client_ch_override[path][dai->id])
|
||||||
|
cif_conf.client_channels =
|
||||||
|
admaif->client_ch_override[path][dai->id];
|
||||||
|
|
||||||
|
cif_conf.mono_conv = admaif->mono_to_stereo[path][dai->id];
|
||||||
|
cif_conf.stereo_conv = admaif->stereo_to_mono[path][dai->id];
|
||||||
|
|
||||||
tegra_admaif_set_pack_mode(admaif->regmap, reg, valid_bit);
|
tegra_admaif_set_pack_mode(admaif->regmap, reg, valid_bit);
|
||||||
|
|
||||||
tegra210_xbar_set_cif(admaif->regmap, reg, &cif_conf);
|
tegra210_xbar_set_cif(admaif->regmap, reg, &cif_conf);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -504,29 +490,26 @@ static int tegra_admaif_get_format(struct snd_kcontrol *kcontrol,
|
|||||||
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
|
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
|
||||||
struct soc_mixer_control *mc =
|
struct soc_mixer_control *mc =
|
||||||
(struct soc_mixer_control *)kcontrol->private_value;
|
(struct soc_mixer_control *)kcontrol->private_value;
|
||||||
|
struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
|
||||||
struct tegra_admaif *admaif = snd_soc_codec_get_drvdata(codec);
|
struct tegra_admaif *admaif = snd_soc_codec_get_drvdata(codec);
|
||||||
int i;
|
long *uctl_val = &ucontrol->value.integer.value[0];
|
||||||
char buf[50];
|
|
||||||
|
|
||||||
if (strstr(kcontrol->id.name, "Channels"))
|
if (strstr(kcontrol->id.name, "Playback Audio Channels"))
|
||||||
ucontrol->value.integer.value[0] =
|
*uctl_val = admaif->audio_ch_override[ADMAIF_TX_PATH][mc->reg];
|
||||||
admaif->override_channels[mc->reg];
|
else if (strstr(kcontrol->id.name, "Capture Audio Channels"))
|
||||||
else {
|
*uctl_val = admaif->audio_ch_override[ADMAIF_RX_PATH][mc->reg];
|
||||||
for (i = 0 ; i < admaif->soc_data->num_ch; i++) {
|
else if (strstr(kcontrol->id.name, "Playback Client Channels"))
|
||||||
snprintf(buf, 50, "ADMAIF%d Capture stereo to mono", i+1);
|
*uctl_val = admaif->client_ch_override[ADMAIF_TX_PATH][mc->reg];
|
||||||
if (strstr(kcontrol->id.name, buf)) {
|
else if (strstr(kcontrol->id.name, "Capture Client Channels"))
|
||||||
ucontrol->value.integer.value[0] =
|
*uctl_val = admaif->client_ch_override[ADMAIF_RX_PATH][mc->reg];
|
||||||
admaif->rx_stereo_to_mono[i];
|
else if (strstr(kcontrol->id.name, "Playback mono to stereo"))
|
||||||
break;
|
*uctl_val = admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg];
|
||||||
}
|
else if (strstr(kcontrol->id.name, "Playback stereo to mono"))
|
||||||
snprintf(buf, 50, "ADMAIF%d Playback mono to stereo", i+1);
|
*uctl_val = admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg];
|
||||||
if (strstr(kcontrol->id.name, buf)) {
|
else if (strstr(kcontrol->id.name, "Capture mono to stereo"))
|
||||||
ucontrol->value.integer.value[0] =
|
*uctl_val = admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg];
|
||||||
admaif->tx_mono_to_stereo[i];
|
else if (strstr(kcontrol->id.name, "Capture stereo to mono"))
|
||||||
break;
|
*uctl_val = admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg];
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -536,31 +519,27 @@ static int tegra_admaif_put_format(struct snd_kcontrol *kcontrol,
|
|||||||
{
|
{
|
||||||
struct soc_mixer_control *mc =
|
struct soc_mixer_control *mc =
|
||||||
(struct soc_mixer_control *)kcontrol->private_value;
|
(struct soc_mixer_control *)kcontrol->private_value;
|
||||||
|
struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
|
||||||
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
|
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
|
||||||
struct tegra_admaif *admaif = snd_soc_codec_get_drvdata(codec);
|
struct tegra_admaif *admaif = snd_soc_codec_get_drvdata(codec);
|
||||||
int value = ucontrol->value.integer.value[0];
|
int value = ucontrol->value.integer.value[0];
|
||||||
int i;
|
|
||||||
char buf[50];
|
|
||||||
|
|
||||||
if (strstr(kcontrol->id.name, "Channels")) {
|
if (strstr(kcontrol->id.name, "Playback Audio Channels"))
|
||||||
if (value >= 0 && value <= 16)
|
admaif->audio_ch_override[ADMAIF_TX_PATH][mc->reg] = value;
|
||||||
admaif->override_channels[mc->reg] = value;
|
else if (strstr(kcontrol->id.name, "Capture Audio Channels"))
|
||||||
else
|
admaif->audio_ch_override[ADMAIF_RX_PATH][mc->reg] = value;
|
||||||
return -EINVAL;
|
else if (strstr(kcontrol->id.name, "Playback Client Channels"))
|
||||||
} else {
|
admaif->client_ch_override[ADMAIF_TX_PATH][mc->reg] = value;
|
||||||
for (i = 0 ; i < admaif->soc_data->num_ch; i++) {
|
else if (strstr(kcontrol->id.name, "Capture Client Channels"))
|
||||||
snprintf(buf, 50, "ADMAIF%d Capture stereo to mono", i+1);
|
admaif->client_ch_override[ADMAIF_RX_PATH][mc->reg] = value;
|
||||||
if (strstr(kcontrol->id.name, buf)) {
|
else if (strstr(kcontrol->id.name, "Playback mono to stereo"))
|
||||||
admaif->rx_stereo_to_mono[i] = value;
|
admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg] = value;
|
||||||
break;
|
else if (strstr(kcontrol->id.name, "Playback stereo to mono"))
|
||||||
}
|
admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg] = value;
|
||||||
snprintf(buf, 50, "ADMAIF%d Playback mono to stereo", i+1);
|
else if (strstr(kcontrol->id.name, "Capture mono to stereo"))
|
||||||
if (strstr(kcontrol->id.name, buf)) {
|
admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg] = value;
|
||||||
admaif->tx_mono_to_stereo[i] = value;
|
else if (strstr(kcontrol->id.name, "Capture stereo to mono"))
|
||||||
break;
|
admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg] = value;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -886,11 +865,11 @@ static const struct snd_soc_dapm_route tegra_admaif_routes[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const char * const tegra_admaif_stereo_conv_text[] = {
|
static const char * const tegra_admaif_stereo_conv_text[] = {
|
||||||
"None", "CH0", "CH1", "AVG",
|
"CH0", "CH1", "AVG",
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char * const tegra_admaif_mono_conv_text[] = {
|
static const char * const tegra_admaif_mono_conv_text[] = {
|
||||||
"None", "ZERO", "COPY",
|
"ZERO", "COPY",
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct soc_enum tegra_admaif_mono_conv_enum =
|
static const struct soc_enum tegra_admaif_mono_conv_enum =
|
||||||
@@ -903,19 +882,48 @@ static const struct soc_enum tegra_admaif_stereo_conv_enum =
|
|||||||
ARRAY_SIZE(tegra_admaif_stereo_conv_text),
|
ARRAY_SIZE(tegra_admaif_stereo_conv_text),
|
||||||
tegra_admaif_stereo_conv_text);
|
tegra_admaif_stereo_conv_text);
|
||||||
|
|
||||||
#define TEGRA_ADMAIF_CHANNEL_CTRL(reg) \
|
#define TEGRA_ADMAIF_CHANNEL_CTRL(reg) \
|
||||||
SOC_SINGLE_EXT("ADMAIF" #reg " Channels", reg - 1, 0, 16, 0, \
|
SOC_SINGLE_EXT("ADMAIF" #reg " Playback Audio Channels", reg - 1, \
|
||||||
tegra_admaif_get_format, tegra_admaif_put_format)
|
0, 16, 0, tegra_admaif_get_format, \
|
||||||
|
tegra_admaif_put_format), \
|
||||||
|
SOC_SINGLE_EXT("ADMAIF" #reg " Capture Audio Channels", reg - 1, \
|
||||||
|
0, 16, 0, tegra_admaif_get_format, \
|
||||||
|
tegra_admaif_put_format), \
|
||||||
|
SOC_SINGLE_EXT("ADMAIF" #reg " Playback Client Channels", reg - 1, \
|
||||||
|
0, 16, 0, tegra_admaif_get_format, \
|
||||||
|
tegra_admaif_put_format), \
|
||||||
|
SOC_SINGLE_EXT("ADMAIF" #reg " Capture Client Channels", reg - 1, \
|
||||||
|
0, 16, 0, tegra_admaif_get_format, \
|
||||||
|
tegra_admaif_put_format)
|
||||||
|
|
||||||
#define TEGRA_ADMAIF_TX_CIF_CTRL(reg) \
|
/*
|
||||||
SOC_ENUM_EXT("ADMAIF" #reg " Playback mono to stereo conv", \
|
* below macro is added to avoid looping over all ADMAIFx controls related
|
||||||
tegra_admaif_mono_conv_enum, tegra_admaif_get_format, \
|
* to mono/stereo conversions in get()/put() callbacks.
|
||||||
tegra_admaif_put_format)
|
*/
|
||||||
|
#define NV_SOC_ENUM_EXT(xname, xreg, xhandler_get, xhandler_put, xenum_text) \
|
||||||
|
{ \
|
||||||
|
.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
|
||||||
|
.info = snd_soc_info_enum_double, \
|
||||||
|
.name = xname, \
|
||||||
|
.get = xhandler_get, \
|
||||||
|
.put = xhandler_put, \
|
||||||
|
.private_value = (unsigned long)&(struct soc_enum) \
|
||||||
|
SOC_ENUM_SINGLE(xreg, 0, ARRAY_SIZE(xenum_text), xenum_text) \
|
||||||
|
}
|
||||||
|
|
||||||
#define TEGRA_ADMAIF_RX_CIF_CTRL(reg) \
|
#define TEGRA_ADMAIF_CIF_CTRL(reg) \
|
||||||
SOC_ENUM_EXT("ADMAIF" #reg " Capture stereo to mono conv", \
|
NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback mono to stereo conv", reg - 1,\
|
||||||
tegra_admaif_stereo_conv_enum, tegra_admaif_get_format, \
|
tegra_admaif_get_format, tegra_admaif_put_format, \
|
||||||
tegra_admaif_put_format)
|
tegra_admaif_mono_conv_text), \
|
||||||
|
NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback stereo to mono conv", reg - 1,\
|
||||||
|
tegra_admaif_get_format, tegra_admaif_put_format, \
|
||||||
|
tegra_admaif_stereo_conv_text), \
|
||||||
|
NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture mono to stereo conv", reg - 1, \
|
||||||
|
tegra_admaif_get_format, tegra_admaif_put_format, \
|
||||||
|
tegra_admaif_mono_conv_text), \
|
||||||
|
NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture stereo to mono conv", reg - 1, \
|
||||||
|
tegra_admaif_get_format, tegra_admaif_put_format, \
|
||||||
|
tegra_admaif_stereo_conv_text)
|
||||||
|
|
||||||
static struct snd_kcontrol_new tegra210_admaif_controls[] = {
|
static struct snd_kcontrol_new tegra210_admaif_controls[] = {
|
||||||
TEGRA_ADMAIF_CHANNEL_CTRL(1),
|
TEGRA_ADMAIF_CHANNEL_CTRL(1),
|
||||||
@@ -928,26 +936,16 @@ static struct snd_kcontrol_new tegra210_admaif_controls[] = {
|
|||||||
TEGRA_ADMAIF_CHANNEL_CTRL(8),
|
TEGRA_ADMAIF_CHANNEL_CTRL(8),
|
||||||
TEGRA_ADMAIF_CHANNEL_CTRL(9),
|
TEGRA_ADMAIF_CHANNEL_CTRL(9),
|
||||||
TEGRA_ADMAIF_CHANNEL_CTRL(10),
|
TEGRA_ADMAIF_CHANNEL_CTRL(10),
|
||||||
TEGRA_ADMAIF_RX_CIF_CTRL(1),
|
TEGRA_ADMAIF_CIF_CTRL(1),
|
||||||
TEGRA_ADMAIF_RX_CIF_CTRL(2),
|
TEGRA_ADMAIF_CIF_CTRL(2),
|
||||||
TEGRA_ADMAIF_RX_CIF_CTRL(3),
|
TEGRA_ADMAIF_CIF_CTRL(3),
|
||||||
TEGRA_ADMAIF_RX_CIF_CTRL(4),
|
TEGRA_ADMAIF_CIF_CTRL(4),
|
||||||
TEGRA_ADMAIF_RX_CIF_CTRL(5),
|
TEGRA_ADMAIF_CIF_CTRL(5),
|
||||||
TEGRA_ADMAIF_RX_CIF_CTRL(6),
|
TEGRA_ADMAIF_CIF_CTRL(6),
|
||||||
TEGRA_ADMAIF_RX_CIF_CTRL(7),
|
TEGRA_ADMAIF_CIF_CTRL(7),
|
||||||
TEGRA_ADMAIF_RX_CIF_CTRL(8),
|
TEGRA_ADMAIF_CIF_CTRL(8),
|
||||||
TEGRA_ADMAIF_RX_CIF_CTRL(9),
|
TEGRA_ADMAIF_CIF_CTRL(9),
|
||||||
TEGRA_ADMAIF_RX_CIF_CTRL(10),
|
TEGRA_ADMAIF_CIF_CTRL(10),
|
||||||
TEGRA_ADMAIF_TX_CIF_CTRL(1),
|
|
||||||
TEGRA_ADMAIF_TX_CIF_CTRL(2),
|
|
||||||
TEGRA_ADMAIF_TX_CIF_CTRL(3),
|
|
||||||
TEGRA_ADMAIF_TX_CIF_CTRL(4),
|
|
||||||
TEGRA_ADMAIF_TX_CIF_CTRL(5),
|
|
||||||
TEGRA_ADMAIF_TX_CIF_CTRL(6),
|
|
||||||
TEGRA_ADMAIF_TX_CIF_CTRL(7),
|
|
||||||
TEGRA_ADMAIF_TX_CIF_CTRL(8),
|
|
||||||
TEGRA_ADMAIF_TX_CIF_CTRL(9),
|
|
||||||
TEGRA_ADMAIF_TX_CIF_CTRL(10),
|
|
||||||
SOC_SINGLE_EXT("APE Reg Dump", SND_SOC_NOPM, 0, 1, 0,
|
SOC_SINGLE_EXT("APE Reg Dump", SND_SOC_NOPM, 0, 1, 0,
|
||||||
tegra210_ape_dump_reg_get, tegra210_ape_dump_reg_put),
|
tegra210_ape_dump_reg_get, tegra210_ape_dump_reg_put),
|
||||||
};
|
};
|
||||||
@@ -973,46 +971,26 @@ static struct snd_kcontrol_new tegra186_admaif_controls[] = {
|
|||||||
TEGRA_ADMAIF_CHANNEL_CTRL(18),
|
TEGRA_ADMAIF_CHANNEL_CTRL(18),
|
||||||
TEGRA_ADMAIF_CHANNEL_CTRL(19),
|
TEGRA_ADMAIF_CHANNEL_CTRL(19),
|
||||||
TEGRA_ADMAIF_CHANNEL_CTRL(20),
|
TEGRA_ADMAIF_CHANNEL_CTRL(20),
|
||||||
TEGRA_ADMAIF_RX_CIF_CTRL(1),
|
TEGRA_ADMAIF_CIF_CTRL(1),
|
||||||
TEGRA_ADMAIF_RX_CIF_CTRL(2),
|
TEGRA_ADMAIF_CIF_CTRL(2),
|
||||||
TEGRA_ADMAIF_RX_CIF_CTRL(3),
|
TEGRA_ADMAIF_CIF_CTRL(3),
|
||||||
TEGRA_ADMAIF_RX_CIF_CTRL(4),
|
TEGRA_ADMAIF_CIF_CTRL(4),
|
||||||
TEGRA_ADMAIF_RX_CIF_CTRL(5),
|
TEGRA_ADMAIF_CIF_CTRL(5),
|
||||||
TEGRA_ADMAIF_RX_CIF_CTRL(6),
|
TEGRA_ADMAIF_CIF_CTRL(6),
|
||||||
TEGRA_ADMAIF_RX_CIF_CTRL(7),
|
TEGRA_ADMAIF_CIF_CTRL(7),
|
||||||
TEGRA_ADMAIF_RX_CIF_CTRL(8),
|
TEGRA_ADMAIF_CIF_CTRL(8),
|
||||||
TEGRA_ADMAIF_RX_CIF_CTRL(9),
|
TEGRA_ADMAIF_CIF_CTRL(9),
|
||||||
TEGRA_ADMAIF_RX_CIF_CTRL(10),
|
TEGRA_ADMAIF_CIF_CTRL(10),
|
||||||
TEGRA_ADMAIF_RX_CIF_CTRL(11),
|
TEGRA_ADMAIF_CIF_CTRL(11),
|
||||||
TEGRA_ADMAIF_RX_CIF_CTRL(12),
|
TEGRA_ADMAIF_CIF_CTRL(12),
|
||||||
TEGRA_ADMAIF_RX_CIF_CTRL(13),
|
TEGRA_ADMAIF_CIF_CTRL(13),
|
||||||
TEGRA_ADMAIF_RX_CIF_CTRL(14),
|
TEGRA_ADMAIF_CIF_CTRL(14),
|
||||||
TEGRA_ADMAIF_RX_CIF_CTRL(15),
|
TEGRA_ADMAIF_CIF_CTRL(15),
|
||||||
TEGRA_ADMAIF_RX_CIF_CTRL(16),
|
TEGRA_ADMAIF_CIF_CTRL(16),
|
||||||
TEGRA_ADMAIF_RX_CIF_CTRL(17),
|
TEGRA_ADMAIF_CIF_CTRL(17),
|
||||||
TEGRA_ADMAIF_RX_CIF_CTRL(18),
|
TEGRA_ADMAIF_CIF_CTRL(18),
|
||||||
TEGRA_ADMAIF_RX_CIF_CTRL(19),
|
TEGRA_ADMAIF_CIF_CTRL(19),
|
||||||
TEGRA_ADMAIF_RX_CIF_CTRL(20),
|
TEGRA_ADMAIF_CIF_CTRL(20),
|
||||||
TEGRA_ADMAIF_TX_CIF_CTRL(1),
|
|
||||||
TEGRA_ADMAIF_TX_CIF_CTRL(2),
|
|
||||||
TEGRA_ADMAIF_TX_CIF_CTRL(3),
|
|
||||||
TEGRA_ADMAIF_TX_CIF_CTRL(4),
|
|
||||||
TEGRA_ADMAIF_TX_CIF_CTRL(5),
|
|
||||||
TEGRA_ADMAIF_TX_CIF_CTRL(6),
|
|
||||||
TEGRA_ADMAIF_TX_CIF_CTRL(7),
|
|
||||||
TEGRA_ADMAIF_TX_CIF_CTRL(8),
|
|
||||||
TEGRA_ADMAIF_TX_CIF_CTRL(9),
|
|
||||||
TEGRA_ADMAIF_TX_CIF_CTRL(10),
|
|
||||||
TEGRA_ADMAIF_TX_CIF_CTRL(11),
|
|
||||||
TEGRA_ADMAIF_TX_CIF_CTRL(12),
|
|
||||||
TEGRA_ADMAIF_TX_CIF_CTRL(13),
|
|
||||||
TEGRA_ADMAIF_TX_CIF_CTRL(14),
|
|
||||||
TEGRA_ADMAIF_TX_CIF_CTRL(15),
|
|
||||||
TEGRA_ADMAIF_TX_CIF_CTRL(16),
|
|
||||||
TEGRA_ADMAIF_TX_CIF_CTRL(17),
|
|
||||||
TEGRA_ADMAIF_TX_CIF_CTRL(18),
|
|
||||||
TEGRA_ADMAIF_TX_CIF_CTRL(19),
|
|
||||||
TEGRA_ADMAIF_TX_CIF_CTRL(20),
|
|
||||||
SOC_SINGLE_EXT("APE Reg Dump", SND_SOC_NOPM, 0, 1, 0,
|
SOC_SINGLE_EXT("APE Reg Dump", SND_SOC_NOPM, 0, 1, 0,
|
||||||
tegra210_ape_dump_reg_get, tegra210_ape_dump_reg_put),
|
tegra210_ape_dump_reg_get, tegra210_ape_dump_reg_put),
|
||||||
};
|
};
|
||||||
@@ -1107,23 +1085,31 @@ static int tegra_admaif_probe(struct platform_device *pdev)
|
|||||||
if (!admaif->playback_dma_data)
|
if (!admaif->playback_dma_data)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
admaif->override_channels = devm_kzalloc(&pdev->dev,
|
for (i = 0; i < ADMAIF_PATHS; i++) {
|
||||||
sizeof(int) * admaif->soc_data->num_ch,
|
admaif->audio_ch_override[i] =
|
||||||
GFP_KERNEL);
|
devm_kcalloc(&pdev->dev, admaif->soc_data->num_ch,
|
||||||
if (!admaif->override_channels)
|
sizeof(unsigned int), GFP_KERNEL);
|
||||||
return -ENOMEM;
|
if (!admaif->audio_ch_override[i])
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
admaif->tx_mono_to_stereo = devm_kzalloc(&pdev->dev,
|
admaif->client_ch_override[i] =
|
||||||
sizeof(int) * admaif->soc_data->num_ch,
|
devm_kcalloc(&pdev->dev, admaif->soc_data->num_ch,
|
||||||
GFP_KERNEL);
|
sizeof(unsigned int), GFP_KERNEL);
|
||||||
if (!admaif->tx_mono_to_stereo)
|
if (!admaif->client_ch_override[i])
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
admaif->rx_stereo_to_mono = devm_kzalloc(&pdev->dev,
|
admaif->mono_to_stereo[i] =
|
||||||
sizeof(int) * admaif->soc_data->num_ch,
|
devm_kcalloc(&pdev->dev, admaif->soc_data->num_ch,
|
||||||
GFP_KERNEL);
|
sizeof(unsigned int), GFP_KERNEL);
|
||||||
if (!admaif->rx_stereo_to_mono)
|
if (!admaif->mono_to_stereo[i])
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
admaif->stereo_to_mono[i] =
|
||||||
|
devm_kcalloc(&pdev->dev, admaif->soc_data->num_ch,
|
||||||
|
sizeof(unsigned int), GFP_KERNEL);
|
||||||
|
if (!admaif->stereo_to_mono[i])
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
regs = devm_ioremap_resource(&pdev->dev, res);
|
regs = devm_ioremap_resource(&pdev->dev, res);
|
||||||
|
|||||||
@@ -370,32 +370,35 @@ static int tegra210_i2s_get_format(struct snd_kcontrol *kcontrol,
|
|||||||
{
|
{
|
||||||
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
|
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
|
||||||
struct tegra210_i2s *i2s = snd_soc_codec_get_drvdata(codec);
|
struct tegra210_i2s *i2s = snd_soc_codec_get_drvdata(codec);
|
||||||
|
long *uctl_val = &ucontrol->value.integer.value[0];
|
||||||
|
|
||||||
/* get the format control flag */
|
/* get the format control flag */
|
||||||
if (strstr(kcontrol->id.name, "input"))
|
if (strstr(kcontrol->id.name, "Playback Audio Bit Format"))
|
||||||
ucontrol->value.integer.value[0] = i2s->format_in;
|
*uctl_val = i2s->audio_fmt_override[I2S_RX_PATH];
|
||||||
|
else if (strstr(kcontrol->id.name, "Capture Audio Bit Format"))
|
||||||
|
*uctl_val = i2s->audio_fmt_override[I2S_TX_PATH];
|
||||||
else if (strstr(kcontrol->id.name, "codec"))
|
else if (strstr(kcontrol->id.name, "codec"))
|
||||||
ucontrol->value.integer.value[0] = i2s->codec_bit_format;
|
*uctl_val = i2s->codec_bit_format;
|
||||||
else if (strstr(kcontrol->id.name, "Sample Rate"))
|
else if (strstr(kcontrol->id.name, "Sample Rate"))
|
||||||
ucontrol->value.integer.value[0] = i2s->sample_rate_via_control;
|
*uctl_val = i2s->sample_rate_via_control;
|
||||||
else if (strstr(kcontrol->id.name, "Channels"))
|
else if (strstr(kcontrol->id.name, "Playback Audio Channels"))
|
||||||
ucontrol->value.integer.value[0] = i2s->channels_via_control;
|
*uctl_val = i2s->audio_ch_override[I2S_RX_PATH];
|
||||||
|
else if (strstr(kcontrol->id.name, "Capture Audio Channels"))
|
||||||
|
*uctl_val = i2s->audio_ch_override[I2S_TX_PATH];
|
||||||
|
else if (strstr(kcontrol->id.name, "Client Channels"))
|
||||||
|
*uctl_val = i2s->client_ch_override;
|
||||||
else if (strstr(kcontrol->id.name, "Capture stereo to mono"))
|
else if (strstr(kcontrol->id.name, "Capture stereo to mono"))
|
||||||
ucontrol->value.integer.value[0] =
|
*uctl_val = i2s->stereo_to_mono[I2S_TX_PATH];
|
||||||
i2s->stereo_to_mono[I2S_TX_PATH];
|
|
||||||
else if (strstr(kcontrol->id.name, "Capture mono to stereo"))
|
else if (strstr(kcontrol->id.name, "Capture mono to stereo"))
|
||||||
ucontrol->value.integer.value[0] =
|
*uctl_val = i2s->mono_to_stereo[I2S_TX_PATH];
|
||||||
i2s->mono_to_stereo[I2S_TX_PATH];
|
|
||||||
else if (strstr(kcontrol->id.name, "Playback stereo to mono"))
|
else if (strstr(kcontrol->id.name, "Playback stereo to mono"))
|
||||||
ucontrol->value.integer.value[0] =
|
*uctl_val = i2s->stereo_to_mono[I2S_RX_PATH];
|
||||||
i2s->stereo_to_mono[I2S_RX_PATH];
|
|
||||||
else if (strstr(kcontrol->id.name, "Playback mono to stereo"))
|
else if (strstr(kcontrol->id.name, "Playback mono to stereo"))
|
||||||
ucontrol->value.integer.value[0] =
|
*uctl_val = i2s->mono_to_stereo[I2S_RX_PATH];
|
||||||
i2s->mono_to_stereo[I2S_RX_PATH];
|
|
||||||
else if (strstr(kcontrol->id.name, "Playback FIFO threshold"))
|
else if (strstr(kcontrol->id.name, "Playback FIFO threshold"))
|
||||||
ucontrol->value.integer.value[0] = i2s->rx_fifo_th;
|
*uctl_val = i2s->rx_fifo_th;
|
||||||
else if (strstr(kcontrol->id.name, "BCLK Ratio"))
|
else if (strstr(kcontrol->id.name, "BCLK Ratio"))
|
||||||
ucontrol->value.integer.value[0] = i2s->bclk_ratio;
|
*uctl_val = i2s->bclk_ratio;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -408,14 +411,20 @@ static int tegra210_i2s_put_format(struct snd_kcontrol *kcontrol,
|
|||||||
int value = ucontrol->value.integer.value[0];
|
int value = ucontrol->value.integer.value[0];
|
||||||
|
|
||||||
/* set the format control flag */
|
/* set the format control flag */
|
||||||
if (strstr(kcontrol->id.name, "input"))
|
if (strstr(kcontrol->id.name, "Playback Audio Bit Format"))
|
||||||
i2s->format_in = value;
|
i2s->audio_fmt_override[I2S_RX_PATH] = value;
|
||||||
|
else if (strstr(kcontrol->id.name, "Capture Audio Bit Format"))
|
||||||
|
i2s->audio_fmt_override[I2S_TX_PATH] = value;
|
||||||
else if (strstr(kcontrol->id.name, "codec"))
|
else if (strstr(kcontrol->id.name, "codec"))
|
||||||
i2s->codec_bit_format = value;
|
i2s->codec_bit_format = value;
|
||||||
else if (strstr(kcontrol->id.name, "Sample Rate"))
|
else if (strstr(kcontrol->id.name, "Sample Rate"))
|
||||||
i2s->sample_rate_via_control = value;
|
i2s->sample_rate_via_control = value;
|
||||||
else if (strstr(kcontrol->id.name, "Channels"))
|
else if (strstr(kcontrol->id.name, "Playback Audio Channels"))
|
||||||
i2s->channels_via_control = value;
|
i2s->audio_ch_override[I2S_RX_PATH] = value;
|
||||||
|
else if (strstr(kcontrol->id.name, "Capture Audio Channels"))
|
||||||
|
i2s->audio_ch_override[I2S_TX_PATH] = value;
|
||||||
|
else if (strstr(kcontrol->id.name, "Client Channels"))
|
||||||
|
i2s->client_ch_override = value;
|
||||||
else if (strstr(kcontrol->id.name, "Capture stereo to mono"))
|
else if (strstr(kcontrol->id.name, "Capture stereo to mono"))
|
||||||
i2s->stereo_to_mono[I2S_TX_PATH] = value;
|
i2s->stereo_to_mono[I2S_TX_PATH] = value;
|
||||||
else if (strstr(kcontrol->id.name, "Capture mono to stereo"))
|
else if (strstr(kcontrol->id.name, "Capture mono to stereo"))
|
||||||
@@ -512,7 +521,7 @@ static int tegra210_i2s_hw_params(struct snd_pcm_substream *substream,
|
|||||||
struct device *dev = dai->dev;
|
struct device *dev = dai->dev;
|
||||||
struct tegra210_i2s *i2s = snd_soc_dai_get_drvdata(dai);
|
struct tegra210_i2s *i2s = snd_soc_dai_get_drvdata(dai);
|
||||||
unsigned int mask, val, reg, frame_format, rx_mask, tx_mask;
|
unsigned int mask, val, reg, frame_format, rx_mask, tx_mask;
|
||||||
int ret, sample_size, channels, srate, i2sclock, bitcnt, max_th;
|
int ret, sample_size, channels, srate, i2sclock, bitcnt, max_th, path;
|
||||||
struct tegra210_xbar_cif_conf cif_conf;
|
struct tegra210_xbar_cif_conf cif_conf;
|
||||||
|
|
||||||
memset(&cif_conf, 0, sizeof(struct tegra210_xbar_cif_conf));
|
memset(&cif_conf, 0, sizeof(struct tegra210_xbar_cif_conf));
|
||||||
@@ -523,6 +532,9 @@ static int tegra210_i2s_hw_params(struct snd_pcm_substream *substream,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cif_conf.audio_channels = channels;
|
||||||
|
cif_conf.client_channels = channels;
|
||||||
|
|
||||||
mask = TEGRA210_I2S_CTRL_BIT_SIZE_MASK;
|
mask = TEGRA210_I2S_CTRL_BIT_SIZE_MASK;
|
||||||
switch (params_format(params)) {
|
switch (params_format(params)) {
|
||||||
case SNDRV_PCM_FORMAT_S8:
|
case SNDRV_PCM_FORMAT_S8:
|
||||||
@@ -567,27 +579,37 @@ static int tegra210_i2s_hw_params(struct snd_pcm_substream *substream,
|
|||||||
if (i2s->sample_rate_via_control)
|
if (i2s->sample_rate_via_control)
|
||||||
srate = i2s->sample_rate_via_control;
|
srate = i2s->sample_rate_via_control;
|
||||||
|
|
||||||
if (i2s->channels_via_control) {
|
/*
|
||||||
channels = i2s->channels_via_control;
|
* For playback I2S RX-CIF and for capture TX-CIF is used.
|
||||||
rx_mask = tx_mask = (1 << channels) - 1;
|
* With reference to AHUB, for I2S, SNDRV_PCM_STREAM_CAPTURE stream is
|
||||||
|
* actually for playback.
|
||||||
|
*/
|
||||||
|
path = (substream->stream == SNDRV_PCM_STREAM_CAPTURE) ?
|
||||||
|
I2S_RX_PATH : I2S_TX_PATH;
|
||||||
|
|
||||||
|
if (i2s->audio_ch_override[path]) {
|
||||||
|
cif_conf.audio_channels = i2s->audio_ch_override[path];
|
||||||
|
rx_mask = tx_mask = (1 << cif_conf.audio_channels) - 1;
|
||||||
} else {
|
} else {
|
||||||
rx_mask = i2s->rx_mask;
|
rx_mask = i2s->rx_mask;
|
||||||
tx_mask = i2s->tx_mask;
|
tx_mask = i2s->tx_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (i2s->client_ch_override)
|
||||||
|
cif_conf.client_channels = i2s->client_ch_override;
|
||||||
|
|
||||||
|
if (i2s->audio_fmt_override[path])
|
||||||
|
cif_conf.audio_bits =
|
||||||
|
tegra210_i2s_fmt_values[i2s->audio_fmt_override[path]];
|
||||||
|
|
||||||
regmap_read(i2s->regmap, TEGRA210_I2S_CTRL, &val);
|
regmap_read(i2s->regmap, TEGRA210_I2S_CTRL, &val);
|
||||||
|
|
||||||
frame_format = val & TEGRA210_I2S_CTRL_FRAME_FORMAT_MASK;
|
frame_format = val & TEGRA210_I2S_CTRL_FRAME_FORMAT_MASK;
|
||||||
|
|
||||||
if (frame_format == TEGRA210_I2S_CTRL_FRAME_FORMAT_FSYNC_MODE) {
|
if (frame_format == TEGRA210_I2S_CTRL_FRAME_FORMAT_FSYNC_MODE)
|
||||||
tegra210_i2s_set_slot_ctrl(i2s->regmap, channels, tx_mask,
|
tegra210_i2s_set_slot_ctrl(i2s->regmap,
|
||||||
rx_mask);
|
cif_conf.client_channels,
|
||||||
cif_conf.audio_channels = channels;
|
tx_mask, rx_mask);
|
||||||
cif_conf.client_channels = channels;
|
|
||||||
} else {
|
|
||||||
cif_conf.audio_channels = channels;
|
|
||||||
cif_conf.client_channels = (channels == 1) ? 2 : channels;
|
|
||||||
}
|
|
||||||
|
|
||||||
i2sclock = srate * sample_size * cif_conf.client_channels;
|
i2sclock = srate * sample_size * cif_conf.client_channels;
|
||||||
|
|
||||||
@@ -620,44 +642,24 @@ static int tegra210_i2s_hw_params(struct snd_pcm_substream *substream,
|
|||||||
|
|
||||||
/* As a COCEC DAI, CAPTURE is transmit */
|
/* As a COCEC DAI, CAPTURE is transmit */
|
||||||
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
|
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
|
||||||
|
unsigned int audio_ch = cif_conf.audio_channels;
|
||||||
|
|
||||||
reg = TEGRA210_I2S_AXBAR_RX_CIF_CTRL;
|
reg = TEGRA210_I2S_AXBAR_RX_CIF_CTRL;
|
||||||
if (i2s->mono_to_stereo[I2S_RX_PATH] > 0) {
|
|
||||||
cif_conf.audio_channels = 1;
|
|
||||||
cif_conf.client_channels = 2;
|
|
||||||
cif_conf.mono_conv =
|
|
||||||
i2s->mono_to_stereo[I2S_RX_PATH] - 1;
|
|
||||||
} else if (i2s->stereo_to_mono[I2S_RX_PATH] > 0) {
|
|
||||||
cif_conf.audio_channels = 2;
|
|
||||||
cif_conf.client_channels = 1;
|
|
||||||
cif_conf.stereo_conv =
|
|
||||||
i2s->stereo_to_mono[I2S_RX_PATH] - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* RX FIFO threshold interms of frames */
|
/* RX FIFO threshold interms of frames */
|
||||||
max_th = (TEGRA210_I2S_RX_FIFO_DEPTH / channels) - 1;
|
max_th = (TEGRA210_I2S_RX_FIFO_DEPTH / audio_ch) - 1;
|
||||||
if (i2s->rx_fifo_th > max_th) { /* error handling */
|
if (max_th < 0)
|
||||||
cif_conf.threshold = max_th;
|
return -EINVAL;
|
||||||
i2s->rx_fifo_th = max_th;
|
|
||||||
} else
|
|
||||||
cif_conf.threshold = i2s->rx_fifo_th;
|
|
||||||
} else {
|
|
||||||
if (i2s->mono_to_stereo[I2S_TX_PATH] > 0) {
|
|
||||||
cif_conf.audio_channels = 2;
|
|
||||||
cif_conf.client_channels = 1;
|
|
||||||
cif_conf.mono_conv =
|
|
||||||
i2s->mono_to_stereo[I2S_TX_PATH] - 1;
|
|
||||||
} else if (i2s->stereo_to_mono[I2S_TX_PATH] > 0) {
|
|
||||||
cif_conf.audio_channels = 1;
|
|
||||||
cif_conf.client_channels = 2;
|
|
||||||
cif_conf.stereo_conv =
|
|
||||||
i2s->stereo_to_mono[I2S_TX_PATH] - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i2s->format_in)
|
if (i2s->rx_fifo_th > max_th) /* error handling */
|
||||||
cif_conf.audio_bits =
|
i2s->rx_fifo_th = max_th;
|
||||||
tegra210_i2s_fmt_values[i2s->format_in];
|
|
||||||
|
cif_conf.threshold = i2s->rx_fifo_th;
|
||||||
|
} else
|
||||||
reg = TEGRA210_I2S_AXBAR_TX_CIF_CTRL;
|
reg = TEGRA210_I2S_AXBAR_TX_CIF_CTRL;
|
||||||
}
|
|
||||||
|
cif_conf.stereo_conv = i2s->stereo_to_mono[path];
|
||||||
|
cif_conf.mono_conv = i2s->mono_to_stereo[path];
|
||||||
|
|
||||||
tegra210_xbar_set_cif(i2s->regmap, reg, &cif_conf);
|
tegra210_xbar_set_cif(i2s->regmap, reg, &cif_conf);
|
||||||
|
|
||||||
@@ -829,11 +831,11 @@ static int tegra210_i2s_fsync_width_put(struct snd_kcontrol *kcontrol,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const char * const tegra210_i2s_stereo_conv_text[] = {
|
static const char * const tegra210_i2s_stereo_conv_text[] = {
|
||||||
"None", "CH0", "CH1", "AVG",
|
"CH0", "CH1", "AVG",
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char * const tegra210_i2s_mono_conv_text[] = {
|
static const char * const tegra210_i2s_mono_conv_text[] = {
|
||||||
"None", "ZERO", "COPY",
|
"ZERO", "COPY",
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct soc_enum tegra210_i2s_mono_conv_enum =
|
static const struct soc_enum tegra210_i2s_mono_conv_enum =
|
||||||
@@ -856,15 +858,21 @@ static const struct soc_enum tegra210_i2s_stereo_conv_enum =
|
|||||||
static const struct snd_kcontrol_new tegra210_i2s_controls[] = {
|
static const struct snd_kcontrol_new tegra210_i2s_controls[] = {
|
||||||
SOC_SINGLE_EXT("Loopback", SND_SOC_NOPM, 0, 1, 0,
|
SOC_SINGLE_EXT("Loopback", SND_SOC_NOPM, 0, 1, 0,
|
||||||
tegra210_i2s_loopback_get, tegra210_i2s_loopback_put),
|
tegra210_i2s_loopback_get, tegra210_i2s_loopback_put),
|
||||||
SOC_ENUM_EXT("input bit format", tegra210_i2s_format_enum,
|
SOC_ENUM_EXT("Playback Audio Bit Format", tegra210_i2s_format_enum,
|
||||||
tegra210_i2s_get_format, tegra210_i2s_put_format),
|
tegra210_i2s_get_format, tegra210_i2s_put_format),
|
||||||
|
SOC_ENUM_EXT("Capture Audio Bit Format", tegra210_i2s_format_enum,
|
||||||
|
tegra210_i2s_get_format, tegra210_i2s_put_format),
|
||||||
SOC_ENUM_EXT("codec bit format", tegra210_i2s_format_enum,
|
SOC_ENUM_EXT("codec bit format", tegra210_i2s_format_enum,
|
||||||
tegra210_i2s_get_format, tegra210_i2s_put_format),
|
tegra210_i2s_get_format, tegra210_i2s_put_format),
|
||||||
SOC_SINGLE_EXT("fsync width", SND_SOC_NOPM, 0, 255, 0,
|
SOC_SINGLE_EXT("fsync width", SND_SOC_NOPM, 0, 255, 0,
|
||||||
tegra210_i2s_fsync_width_get, tegra210_i2s_fsync_width_put),
|
tegra210_i2s_fsync_width_get, tegra210_i2s_fsync_width_put),
|
||||||
SOC_SINGLE_EXT("Sample Rate", 0, 0, 192000, 0,
|
SOC_SINGLE_EXT("Sample Rate", 0, 0, 192000, 0,
|
||||||
tegra210_i2s_get_format, tegra210_i2s_put_format),
|
tegra210_i2s_get_format, tegra210_i2s_put_format),
|
||||||
SOC_SINGLE_EXT("Channels", 0, 0, 16, 0,
|
SOC_SINGLE_EXT("Playback Audio Channels", 0, 0, 16, 0,
|
||||||
|
tegra210_i2s_get_format, tegra210_i2s_put_format),
|
||||||
|
SOC_SINGLE_EXT("Capture Audio Channels", 0, 0, 16, 0,
|
||||||
|
tegra210_i2s_get_format, tegra210_i2s_put_format),
|
||||||
|
SOC_SINGLE_EXT("Client Channels", 0, 0, 16, 0,
|
||||||
tegra210_i2s_get_format, tegra210_i2s_put_format),
|
tegra210_i2s_get_format, tegra210_i2s_put_format),
|
||||||
SOC_SINGLE_EXT("BCLK Ratio", SND_SOC_NOPM, 0, INT_MAX, 0,
|
SOC_SINGLE_EXT("BCLK Ratio", SND_SOC_NOPM, 0, INT_MAX, 0,
|
||||||
tegra210_i2s_get_bclk_ratio,
|
tegra210_i2s_get_bclk_ratio,
|
||||||
|
|||||||
Reference in New Issue
Block a user