/*
* tegra210_virt_alt_admaif.c - Tegra ADMAIF component driver
*
* Copyright (c) 2014-2021 NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include
#include
#include
#include
#include
#include "tegra210_virt_alt_admaif.h"
#include "tegra_virt_alt_ivc.h"
#include "tegra_pcm_alt.h"
#include "tegra_asoc_xbar_virt_alt.h"
#include "tegra_asoc_util_virt_alt.h"
#define NUM_META_CONTROLS 3
static const unsigned int tegra210_rates[] = {
8000, 11025, 12000, 16000, 22050,
24000, 32000, 44100, 48000, 64000,
88200, 96000, 176400, 192000
};
static const struct snd_pcm_hw_constraint_list tegra210_rate_constraints = {
.count = ARRAY_SIZE(tegra210_rates),
.list = tegra210_rates,
};
static struct tegra210_admaif *admaif;
static int tegra210_admaif_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
struct device *dev = dai->dev;
struct tegra210_virt_admaif_client_data *data =
&admaif->client_data;
struct tegra210_virt_audio_cif cif_conf;
struct nvaudio_ivc_msg msg;
unsigned int value;
int err;
memset(&cif_conf, 0, sizeof(struct tegra210_virt_audio_cif));
cif_conf.audio_channels = params_channels(params);
cif_conf.client_channels = params_channels(params);
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S8:
cif_conf.client_bits = TEGRA210_AUDIOCIF_BITS_8;
cif_conf.audio_bits = TEGRA210_AUDIOCIF_BITS_8;
break;
case SNDRV_PCM_FORMAT_S16_LE:
cif_conf.client_bits = TEGRA210_AUDIOCIF_BITS_16;
cif_conf.audio_bits = TEGRA210_AUDIOCIF_BITS_16;
break;
case SNDRV_PCM_FORMAT_S24_LE:
cif_conf.client_bits = TEGRA210_AUDIOCIF_BITS_24;
cif_conf.audio_bits = TEGRA210_AUDIOCIF_BITS_24;
break;
case SNDRV_PCM_FORMAT_S32_LE:
cif_conf.client_bits = TEGRA210_AUDIOCIF_BITS_32;
cif_conf.audio_bits = TEGRA210_AUDIOCIF_BITS_32;
break;
default:
dev_err(dev, "Wrong format!\n");
return -EINVAL;
}
cif_conf.direction = substream->stream;
value = (cif_conf.threshold <<
TEGRA210_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) |
((cif_conf.audio_channels - 1) <<
TEGRA210_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
((cif_conf.client_channels - 1) <<
TEGRA210_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) |
(cif_conf.audio_bits <<
TEGRA210_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT) |
(cif_conf.client_bits <<
TEGRA210_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT) |
(cif_conf.expand <<
TEGRA210_AUDIOCIF_CTRL_EXPAND_SHIFT) |
(cif_conf.stereo_conv <<
TEGRA210_AUDIOCIF_CTRL_STEREO_CONV_SHIFT) |
(cif_conf.replicate <<
TEGRA210_AUDIOCIF_CTRL_REPLICATE_SHIFT) |
(cif_conf.truncate <<
TEGRA210_AUDIOCIF_CTRL_TRUNCATE_SHIFT) |
(cif_conf.mono_conv <<
TEGRA210_AUDIOCIF_CTRL_MONO_CONV_SHIFT);
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.params.dmaif_info.id = dai->id;
msg.params.dmaif_info.value = value;
if (!cif_conf.direction)
msg.cmd = NVAUDIO_DMAIF_SET_TXCIF;
else
msg.cmd = NVAUDIO_DMAIF_SET_RXCIF;
err = nvaudio_ivc_send(data->hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
if (err < 0)
pr_err("%s: error on ivc_send\n", __func__);
return 0;
}
static void tegra210_admaif_start_playback(struct snd_soc_dai *dai)
{
struct tegra210_virt_admaif_client_data *data =
&admaif->client_data;
int err;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_START_PLAYBACK;
msg.params.dmaif_info.id = dai->id;
msg.ack_required = true;
err = nvaudio_ivc_send_receive(data->hivc_client,
&msg, sizeof(struct nvaudio_ivc_msg));
if (err < 0)
pr_err("%s: error on ivc_send\n", __func__);
}
static void tegra210_admaif_stop_playback(struct snd_soc_dai *dai)
{
struct tegra210_virt_admaif_client_data *data =
&admaif->client_data;
int err;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_STOP_PLAYBACK;
msg.params.dmaif_info.id = dai->id;
msg.ack_required = true;
err = nvaudio_ivc_send_receive(data->hivc_client,
&msg, sizeof(struct nvaudio_ivc_msg));
if (err < 0)
pr_err("%s: error on ivc_send\n", __func__);
}
static void tegra210_admaif_start_capture(struct snd_soc_dai *dai)
{
struct tegra210_virt_admaif_client_data *data =
&admaif->client_data;
int err;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_START_CAPTURE;
msg.params.dmaif_info.id = dai->id;
msg.ack_required = true;
err = nvaudio_ivc_send_receive(data->hivc_client,
&msg, sizeof(struct nvaudio_ivc_msg));
if (err < 0)
pr_err("%s: error on ivc_send\n", __func__);
}
static void tegra210_admaif_stop_capture(struct snd_soc_dai *dai)
{
struct tegra210_virt_admaif_client_data *data =
&admaif->client_data;
int err;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_STOP_CAPTURE;
msg.params.dmaif_info.id = dai->id;
msg.ack_required = true;
err = nvaudio_ivc_send_receive(data->hivc_client,
&msg, sizeof(struct nvaudio_ivc_msg));
if (err < 0)
pr_err("%s: error on ivc_send\n", __func__);
}
static int tegra210_admaif_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *dai)
{
pr_info("Pcm trigger for admaif%d %s: cmd_id %d\n", dai->id+1,
(substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
"playback":"capture", cmd);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
case SNDRV_PCM_TRIGGER_RESUME:
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
tegra210_admaif_start_playback(dai);
else
tegra210_admaif_start_capture(dai);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
case SNDRV_PCM_TRIGGER_SUSPEND:
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
tegra210_admaif_stop_playback(dai);
else
tegra210_admaif_stop_capture(dai);
break;
default:
return -EINVAL;
}
return 0;
}
static int tegra210_admaif_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai)
{
return snd_pcm_hw_constraint_list(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_RATE, &tegra210_rate_constraints);
}
static struct snd_soc_dai_ops tegra210_admaif_dai_ops = {
.hw_params = tegra210_admaif_hw_params,
.trigger = tegra210_admaif_trigger,
.startup = tegra210_admaif_startup,
};
static int tegra210_admaif_dai_probe(struct snd_soc_dai *dai)
{
dai->capture_dma_data = &admaif->capture_dma_data[dai->id];
dai->playback_dma_data = &admaif->playback_dma_data[dai->id];
return 0;
}
static int tegra_bytes_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
struct soc_bytes *params = (void *)kcontrol->private_value;
uinfo->type = params->mask;
uinfo->count = params->num_regs;
return 0;
}
#define ADMAIF_DAI(id) \
{ \
.name = "ADMAIF" #id, \
.probe = tegra210_admaif_dai_probe, \
.playback = { \
.stream_name = "Playback " #id, \
.channels_min = 1, \
.channels_max = 16, \
.rates = SNDRV_PCM_RATE_8000_192000, \
.formats = SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_S16_LE | \
SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE, \
}, \
.capture = { \
.stream_name = "Capture " #id, \
.channels_min = 1, \
.channels_max = 16, \
.rates = SNDRV_PCM_RATE_8000_192000, \
.formats = SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_S16_LE | \
SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE, \
}, \
.ops = &tegra210_admaif_dai_ops, \
}
static struct snd_soc_dai_driver tegra210_admaif_dais[] = {
ADMAIF_DAI(1),
ADMAIF_DAI(2),
ADMAIF_DAI(3),
ADMAIF_DAI(4),
ADMAIF_DAI(5),
ADMAIF_DAI(6),
ADMAIF_DAI(7),
ADMAIF_DAI(8),
ADMAIF_DAI(9),
ADMAIF_DAI(10),
ADMAIF_DAI(11),
ADMAIF_DAI(12),
ADMAIF_DAI(13),
ADMAIF_DAI(14),
ADMAIF_DAI(15),
ADMAIF_DAI(16),
ADMAIF_DAI(17),
ADMAIF_DAI(18),
ADMAIF_DAI(19),
ADMAIF_DAI(20),
};
static const struct soc_enum tegra_virt_t186_asrc_source =
SOC_ENUM_SINGLE_EXT(NUM_ASRC_MODE, tegra186_asrc_ratio_source_text);
static const struct soc_enum tegra_virt_t186_arad_source =
SOC_VALUE_ENUM_SINGLE(0, 0, 0, NUM_ARAD_SOURCES,
tegra186_arad_mux_text,
tegra186_arad_mux_value);
static const struct soc_enum tegra_virt_t210_mvc_curvetype =
SOC_ENUM_SINGLE_EXT(NUM_MVC_CURVETYPE, tegra210_mvc_curve_type_text);
static const struct snd_kcontrol_new tegra_virt_t210ref_controls[] = {
MIXER_GAIN_CTRL_DECL("RX1 Gain", 0x00),
MIXER_GAIN_CTRL_DECL("RX2 Gain", 0x01),
MIXER_GAIN_CTRL_DECL("RX3 Gain", 0x02),
MIXER_GAIN_CTRL_DECL("RX4 Gain", 0x03),
MIXER_GAIN_CTRL_DECL("RX5 Gain", 0x04),
MIXER_GAIN_CTRL_DECL("RX6 Gain", 0x05),
MIXER_GAIN_CTRL_DECL("RX7 Gain", 0x06),
MIXER_GAIN_CTRL_DECL("RX8 Gain", 0x07),
MIXER_GAIN_CTRL_DECL("RX9 Gain", 0x08),
MIXER_GAIN_CTRL_DECL("RX10 Gain", 0x09),
MIXER_GAIN_INSTANT_CTRL_DECL("RX1 Gain Instant", 0x00),
MIXER_GAIN_INSTANT_CTRL_DECL("RX2 Gain Instant", 0x01),
MIXER_GAIN_INSTANT_CTRL_DECL("RX3 Gain Instant", 0x02),
MIXER_GAIN_INSTANT_CTRL_DECL("RX4 Gain Instant", 0x03),
MIXER_GAIN_INSTANT_CTRL_DECL("RX5 Gain Instant", 0x04),
MIXER_GAIN_INSTANT_CTRL_DECL("RX6 Gain Instant", 0x05),
MIXER_GAIN_INSTANT_CTRL_DECL("RX7 Gain Instant", 0x06),
MIXER_GAIN_INSTANT_CTRL_DECL("RX8 Gain Instant", 0x07),
MIXER_GAIN_INSTANT_CTRL_DECL("RX9 Gain Instant", 0x08),
MIXER_GAIN_INSTANT_CTRL_DECL("RX10 Gain Instant", 0x09),
MIXER_DURATION_CTRL_DECL("RX1 Duration", 0x00),
MIXER_DURATION_CTRL_DECL("RX2 Duration", 0x01),
MIXER_DURATION_CTRL_DECL("RX3 Duration", 0x02),
MIXER_DURATION_CTRL_DECL("RX4 Duration", 0x03),
MIXER_DURATION_CTRL_DECL("RX5 Duration", 0x04),
MIXER_DURATION_CTRL_DECL("RX6 Duration", 0x05),
MIXER_DURATION_CTRL_DECL("RX7 Duration", 0x06),
MIXER_DURATION_CTRL_DECL("RX8 Duration", 0x07),
MIXER_DURATION_CTRL_DECL("RX9 Duration", 0x08),
MIXER_DURATION_CTRL_DECL("RX10 Duration", 0x09),
MIXER_ENABLE_CTRL_DECL("Mixer Enable", 0x00),
MIXER_SET_FADE("Mixer fade", 0x00),
MIXER_GET_FADE_STATUS("Mixer fade status", 0x00),
SFC_IN_FREQ_CTRL_DECL("SFC1 input rate", 0x00),
SFC_IN_FREQ_CTRL_DECL("SFC2 input rate", 0x01),
SFC_IN_FREQ_CTRL_DECL("SFC3 input rate", 0x02),
SFC_IN_FREQ_CTRL_DECL("SFC4 input rate", 0x03),
SFC_OUT_FREQ_CTRL_DECL("SFC1 output rate", 0x00),
SFC_OUT_FREQ_CTRL_DECL("SFC2 output rate", 0x01),
SFC_OUT_FREQ_CTRL_DECL("SFC3 output rate", 0x02),
SFC_OUT_FREQ_CTRL_DECL("SFC4 output rate", 0x03),
MVC_CURVE_TYPE_CTRL_DECL("MVC1 Curve Type", 0x00,
&tegra_virt_t210_mvc_curvetype),
MVC_CURVE_TYPE_CTRL_DECL("MVC2 Curve Type", 0x01,
&tegra_virt_t210_mvc_curvetype),
MVC_TAR_VOL_CTRL_DECL("MVC1 Vol", 0x00),
MVC_TAR_VOL_CTRL_DECL("MVC2 Vol", 0x01),
MVC_MUTE_CTRL_DECL("MVC1 Mute", 0x00),
MVC_MUTE_CTRL_DECL("MVC2 Mute", 0x01),
AMX_ENABLE_CTRL_DECL("AMX1-1 Enable", 0x01, 0x01),
AMX_ENABLE_CTRL_DECL("AMX1-2 Enable", 0x01, 0x02),
AMX_ENABLE_CTRL_DECL("AMX1-3 Enable", 0x01, 0x03),
AMX_ENABLE_CTRL_DECL("AMX1-4 Enable", 0x01, 0x04),
AMX_ENABLE_CTRL_DECL("AMX2-1 Enable", 0x02, 0x01),
AMX_ENABLE_CTRL_DECL("AMX2-2 Enable", 0x02, 0x02),
AMX_ENABLE_CTRL_DECL("AMX2-3 Enable", 0x02, 0x03),
AMX_ENABLE_CTRL_DECL("AMX2-4 Enable", 0x02, 0x04),
I2S_LOOPBACK_ENABLE_CTRL_DECL("I2S1 Loopback", 0x01),
I2S_LOOPBACK_ENABLE_CTRL_DECL("I2S2 Loopback", 0x02),
I2S_LOOPBACK_ENABLE_CTRL_DECL("I2S3 Loopback", 0x03),
I2S_LOOPBACK_ENABLE_CTRL_DECL("I2S4 Loopback", 0x04),
I2S_LOOPBACK_ENABLE_CTRL_DECL("I2S5 Loopback", 0x05),
REGDUMP_CTRL_DECL("ADMAIF1 regdump", ADMAIF1, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ADMAIF2 regdump", ADMAIF2, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ADMAIF3 regdump", ADMAIF3, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ADMAIF4 regdump", ADMAIF4, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ADMAIF5 regdump", ADMAIF5, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ADMAIF6 regdump", ADMAIF6, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ADMAIF7 regdump", ADMAIF7, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ADMAIF8 regdump", ADMAIF8, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ADMAIF9 regdump", ADMAIF9, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ADMAIF10 regdump", ADMAIF10, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("AMX1 regdump", AMX1, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("AMX2 regdump", AMX2, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ADX1 regdump", ADX1, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ADX2 regdump", ADX2, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("MIXER1-1 RX regdump", MIXER1, 0, NVAUDIO_REGDUMP_RX),
REGDUMP_CTRL_DECL("MIXER1-2 RX regdump", MIXER1, 1, NVAUDIO_REGDUMP_RX),
REGDUMP_CTRL_DECL("MIXER1-3 RX regdump", MIXER1, 2, NVAUDIO_REGDUMP_RX),
REGDUMP_CTRL_DECL("MIXER1-4 RX regdump", MIXER1, 3, NVAUDIO_REGDUMP_RX),
REGDUMP_CTRL_DECL("MIXER1-5 RX regdump", MIXER1, 4, NVAUDIO_REGDUMP_RX),
REGDUMP_CTRL_DECL("MIXER1-6 RX regdump", MIXER1, 5, NVAUDIO_REGDUMP_RX),
REGDUMP_CTRL_DECL("MIXER1-7 RX regdump", MIXER1, 6, NVAUDIO_REGDUMP_RX),
REGDUMP_CTRL_DECL("MIXER1-8 RX regdump", MIXER1, 7, NVAUDIO_REGDUMP_RX),
REGDUMP_CTRL_DECL("MIXER1-9 RX regdump", MIXER1, 8, NVAUDIO_REGDUMP_RX),
REGDUMP_CTRL_DECL("MIXER1-10 RX regdump", MIXER1, 9, NVAUDIO_REGDUMP_RX),
REGDUMP_CTRL_DECL("MIXER1-1 TX regdump", MIXER1, 0, NVAUDIO_REGDUMP_TX),
REGDUMP_CTRL_DECL("MIXER1-2 TX regdump", MIXER1, 1, NVAUDIO_REGDUMP_TX),
REGDUMP_CTRL_DECL("MIXER1-3 TX regdump", MIXER1, 2, NVAUDIO_REGDUMP_TX),
REGDUMP_CTRL_DECL("MIXER1-4 TX regdump", MIXER1, 3, NVAUDIO_REGDUMP_TX),
REGDUMP_CTRL_DECL("MIXER1-5 TX regdump", MIXER1, 4, NVAUDIO_REGDUMP_TX),
REGDUMP_CTRL_DECL("I2S1 regdump", I2S1, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("I2S2 regdump", I2S2, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("I2S3 regdump", I2S3, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("I2S4 regdump", I2S4, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("I2S5 regdump", I2S5, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("SFC1 regdump", SFC1, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("SFC2 regdump", SFC2, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("SFC3 regdump", SFC3, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("SFC4 regdump", SFC4, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("MVC1 regdump", MVC1, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("MVC2 regdump", MVC2, 0, NVAUDIO_REGDUMP_RX_TX),
ADMA_REGDUMP_CTRL_DECL("ADMA1 regdump", 1),
ADMA_REGDUMP_CTRL_DECL("ADMA2 regdump", 2),
ADMA_REGDUMP_CTRL_DECL("ADMA3 regdump", 3),
ADMA_REGDUMP_CTRL_DECL("ADMA4 regdump", 4),
ADMA_REGDUMP_CTRL_DECL("ADMA5 regdump", 5),
ADMA_REGDUMP_CTRL_DECL("ADMA6 regdump", 6),
ADMA_REGDUMP_CTRL_DECL("ADMA7 regdump", 7),
ADMA_REGDUMP_CTRL_DECL("ADMA8 regdump", 8),
ADMA_REGDUMP_CTRL_DECL("ADMA9 regdump", 9),
ADMA_REGDUMP_CTRL_DECL("ADMA10 regdump", 10),
ADMA_REGDUMP_CTRL_DECL("ADMA11 regdump", 11),
ADMA_REGDUMP_CTRL_DECL("ADMA12 regdump", 12),
ADMA_REGDUMP_CTRL_DECL("ADMA13 regdump", 13),
ADMA_REGDUMP_CTRL_DECL("ADMA14 regdump", 14),
ADMA_REGDUMP_CTRL_DECL("ADMA15 regdump", 15),
ADMA_REGDUMP_CTRL_DECL("ADMA16 regdump", 16),
ADMA_REGDUMP_CTRL_DECL("ADMA17 regdump", 17),
ADMA_REGDUMP_CTRL_DECL("ADMA18 regdump", 18),
ADMA_REGDUMP_CTRL_DECL("ADMA19 regdump", 19),
ADMA_REGDUMP_CTRL_DECL("ADMA20 regdump", 20),
};
static const struct snd_kcontrol_new tegra_virt_t186ref_controls[] = {
MIXER_GAIN_CTRL_DECL("RX1 Gain", 0x00),
MIXER_GAIN_CTRL_DECL("RX2 Gain", 0x01),
MIXER_GAIN_CTRL_DECL("RX3 Gain", 0x02),
MIXER_GAIN_CTRL_DECL("RX4 Gain", 0x03),
MIXER_GAIN_CTRL_DECL("RX5 Gain", 0x04),
MIXER_GAIN_CTRL_DECL("RX6 Gain", 0x05),
MIXER_GAIN_CTRL_DECL("RX7 Gain", 0x06),
MIXER_GAIN_CTRL_DECL("RX8 Gain", 0x07),
MIXER_GAIN_CTRL_DECL("RX9 Gain", 0x08),
MIXER_GAIN_CTRL_DECL("RX10 Gain", 0x09),
MIXER_GAIN_INSTANT_CTRL_DECL("RX1 Gain Instant", 0x00),
MIXER_GAIN_INSTANT_CTRL_DECL("RX2 Gain Instant", 0x01),
MIXER_GAIN_INSTANT_CTRL_DECL("RX3 Gain Instant", 0x02),
MIXER_GAIN_INSTANT_CTRL_DECL("RX4 Gain Instant", 0x03),
MIXER_GAIN_INSTANT_CTRL_DECL("RX5 Gain Instant", 0x04),
MIXER_GAIN_INSTANT_CTRL_DECL("RX6 Gain Instant", 0x05),
MIXER_GAIN_INSTANT_CTRL_DECL("RX7 Gain Instant", 0x06),
MIXER_GAIN_INSTANT_CTRL_DECL("RX8 Gain Instant", 0x07),
MIXER_GAIN_INSTANT_CTRL_DECL("RX9 Gain Instant", 0x08),
MIXER_GAIN_INSTANT_CTRL_DECL("RX10 Gain Instant", 0x09),
MIXER_DURATION_CTRL_DECL("RX1 Duration", 0x00),
MIXER_DURATION_CTRL_DECL("RX2 Duration", 0x01),
MIXER_DURATION_CTRL_DECL("RX3 Duration", 0x02),
MIXER_DURATION_CTRL_DECL("RX4 Duration", 0x03),
MIXER_DURATION_CTRL_DECL("RX5 Duration", 0x04),
MIXER_DURATION_CTRL_DECL("RX6 Duration", 0x05),
MIXER_DURATION_CTRL_DECL("RX7 Duration", 0x06),
MIXER_DURATION_CTRL_DECL("RX8 Duration", 0x07),
MIXER_DURATION_CTRL_DECL("RX9 Duration", 0x08),
MIXER_DURATION_CTRL_DECL("RX10 Duration", 0x09),
MIXER_ENABLE_CTRL_DECL("Mixer Enable", 0x00),
MIXER_SET_FADE("Mixer fade", 0x00),
MIXER_GET_FADE_STATUS("Mixer fade status", 0x00),
SFC_IN_FREQ_CTRL_DECL("SFC1 input rate", 0x00),
SFC_IN_FREQ_CTRL_DECL("SFC2 input rate", 0x01),
SFC_IN_FREQ_CTRL_DECL("SFC3 input rate", 0x02),
SFC_IN_FREQ_CTRL_DECL("SFC4 input rate", 0x03),
SFC_OUT_FREQ_CTRL_DECL("SFC1 output rate", 0x00),
SFC_OUT_FREQ_CTRL_DECL("SFC2 output rate", 0x01),
SFC_OUT_FREQ_CTRL_DECL("SFC3 output rate", 0x02),
SFC_OUT_FREQ_CTRL_DECL("SFC4 output rate", 0x03),
MVC_CURVE_TYPE_CTRL_DECL("MVC1 Curve Type", 0x00,
&tegra_virt_t210_mvc_curvetype),
MVC_CURVE_TYPE_CTRL_DECL("MVC2 Curve Type", 0x01,
&tegra_virt_t210_mvc_curvetype),
MVC_TAR_VOL_CTRL_DECL("MVC1 Vol", 0x00),
MVC_TAR_VOL_CTRL_DECL("MVC2 Vol", 0x01),
MVC_MUTE_CTRL_DECL("MVC1 Mute", 0x00),
MVC_MUTE_CTRL_DECL("MVC2 Mute", 0x01),
ASRC_RATIO_CTRL_DECL("ASRC1 Ratio1", 0x01),
ASRC_RATIO_CTRL_DECL("ASRC1 Ratio2", 0x02),
ASRC_RATIO_CTRL_DECL("ASRC1 Ratio3", 0x03),
ASRC_RATIO_CTRL_DECL("ASRC1 Ratio4", 0x04),
ASRC_RATIO_CTRL_DECL("ASRC1 Ratio5", 0x05),
ASRC_RATIO_CTRL_DECL("ASRC1 Ratio6", 0x06),
ASRC_STREAM_RATIO_CTRL_DECL("ASRC1 Ratio1 SRC", 0x01,
&tegra_virt_t186_asrc_source),
ASRC_STREAM_RATIO_CTRL_DECL("ASRC1 Ratio2 SRC", 0x02,
&tegra_virt_t186_asrc_source),
ASRC_STREAM_RATIO_CTRL_DECL("ASRC1 Ratio3 SRC", 0x03,
&tegra_virt_t186_asrc_source),
ASRC_STREAM_RATIO_CTRL_DECL("ASRC1 Ratio4 SRC", 0x04,
&tegra_virt_t186_asrc_source),
ASRC_STREAM_RATIO_CTRL_DECL("ASRC1 Ratio5 SRC", 0x05,
&tegra_virt_t186_asrc_source),
ASRC_STREAM_RATIO_CTRL_DECL("ASRC1 Ratio6 SRC", 0x06,
&tegra_virt_t186_asrc_source),
ASRC_STREAM_ENABLE_CTRL_DECL("ASRC1 Stream1 Enable", 0x01),
ASRC_STREAM_ENABLE_CTRL_DECL("ASRC1 Stream2 Enable", 0x02),
ASRC_STREAM_ENABLE_CTRL_DECL("ASRC1 Stream3 Enable", 0x03),
ASRC_STREAM_ENABLE_CTRL_DECL("ASRC1 Stream4 Enable", 0x04),
ASRC_STREAM_ENABLE_CTRL_DECL("ASRC1 Stream5 Enable", 0x05),
ASRC_STREAM_ENABLE_CTRL_DECL("ASRC1 Stream6 Enable", 0x06),
ASRC_STREAM_HWCOMP_CTRL_DECL("ASRC1 Stream1 Hwcomp Disable", 0x01),
ASRC_STREAM_HWCOMP_CTRL_DECL("ASRC1 Stream2 Hwcomp Disable", 0x02),
ASRC_STREAM_HWCOMP_CTRL_DECL("ASRC1 Stream3 Hwcomp Disable", 0x03),
ASRC_STREAM_HWCOMP_CTRL_DECL("ASRC1 Stream4 Hwcomp Disable", 0x04),
ASRC_STREAM_HWCOMP_CTRL_DECL("ASRC1 Stream5 Hwcomp Disable", 0x05),
ASRC_STREAM_HWCOMP_CTRL_DECL("ASRC1 Stream6 Hwcomp Disable", 0x06),
ASRC_STREAM_INPUT_THRESHOLD_CTRL_DECL("ASRC1 Stream1 Input Thresh", 0x01),
ASRC_STREAM_INPUT_THRESHOLD_CTRL_DECL("ASRC1 Stream2 Input Thresh", 0x02),
ASRC_STREAM_INPUT_THRESHOLD_CTRL_DECL("ASRC1 Stream3 Input Thresh", 0x03),
ASRC_STREAM_INPUT_THRESHOLD_CTRL_DECL("ASRC1 Stream4 Input Thresh", 0x04),
ASRC_STREAM_INPUT_THRESHOLD_CTRL_DECL("ASRC1 Stream5 Input Thresh", 0x05),
ASRC_STREAM_INPUT_THRESHOLD_CTRL_DECL("ASRC1 Stream6 Input Thresh", 0x06),
ASRC_STREAM_OUTPUT_THRESHOLD_CTRL_DECL("ASRC1 Stream1 Output Thresh", 0x01),
ASRC_STREAM_OUTPUT_THRESHOLD_CTRL_DECL("ASRC1 Stream2 Output Thresh", 0x02),
ASRC_STREAM_OUTPUT_THRESHOLD_CTRL_DECL("ASRC1 Stream3 Output Thresh", 0x03),
ASRC_STREAM_OUTPUT_THRESHOLD_CTRL_DECL("ASRC1 Stream4 Output Thresh", 0x04),
ASRC_STREAM_OUTPUT_THRESHOLD_CTRL_DECL("ASRC1 Stream5 Output Thresh", 0x05),
ASRC_STREAM_OUTPUT_THRESHOLD_CTRL_DECL("ASRC1 Stream6 Output Thresh", 0x06),
ARAD_LANE_SOURCE_CTRL_DECL("Numerator1 Mux", numerator1_enum,
&tegra_virt_t186_arad_source),
ARAD_LANE_SOURCE_CTRL_DECL("Numerator2 Mux", numerator2_enum,
&tegra_virt_t186_arad_source),
ARAD_LANE_SOURCE_CTRL_DECL("Numerator3 Mux", numerator3_enum,
&tegra_virt_t186_arad_source),
ARAD_LANE_SOURCE_CTRL_DECL("Numerator4 Mux", numerator4_enum,
&tegra_virt_t186_arad_source),
ARAD_LANE_SOURCE_CTRL_DECL("Numerator5 Mux", numerator5_enum,
&tegra_virt_t186_arad_source),
ARAD_LANE_SOURCE_CTRL_DECL("Numerator6 Mux", numerator6_enum,
&tegra_virt_t186_arad_source),
ARAD_LANE_SOURCE_CTRL_DECL("Denominator1 Mux", denominator1_enum,
&tegra_virt_t186_arad_source),
ARAD_LANE_SOURCE_CTRL_DECL("Denominator2 Mux", denominator2_enum,
&tegra_virt_t186_arad_source),
ARAD_LANE_SOURCE_CTRL_DECL("Denominator3 Mux", denominator3_enum,
&tegra_virt_t186_arad_source),
ARAD_LANE_SOURCE_CTRL_DECL("Denominator4 Mux", denominator4_enum,
&tegra_virt_t186_arad_source),
ARAD_LANE_SOURCE_CTRL_DECL("Denominator5 Mux", denominator5_enum,
&tegra_virt_t186_arad_source),
ARAD_LANE_SOURCE_CTRL_DECL("Denominator6 Mux", denominator6_enum,
&tegra_virt_t186_arad_source),
ARAD_LANE_PRESCALAR_CTRL_DECL("Numerator1 Prescalar", numerator1_enum),
ARAD_LANE_PRESCALAR_CTRL_DECL("Numerator2 Prescalar", numerator2_enum),
ARAD_LANE_PRESCALAR_CTRL_DECL("Numerator3 Prescalar", numerator3_enum),
ARAD_LANE_PRESCALAR_CTRL_DECL("Numerator4 Prescalar", numerator4_enum),
ARAD_LANE_PRESCALAR_CTRL_DECL("Numerator5 Prescalar", numerator5_enum),
ARAD_LANE_PRESCALAR_CTRL_DECL("Numerator6 Prescalar", numerator6_enum),
ARAD_LANE_PRESCALAR_CTRL_DECL("Denominator1 Prescalar", denominator1_enum),
ARAD_LANE_PRESCALAR_CTRL_DECL("Denominator2 Prescalar", denominator2_enum),
ARAD_LANE_PRESCALAR_CTRL_DECL("Denominator3 Prescalar", denominator3_enum),
ARAD_LANE_PRESCALAR_CTRL_DECL("Denominator4 Prescalar", denominator4_enum),
ARAD_LANE_PRESCALAR_CTRL_DECL("Denominator5 Prescalar", denominator5_enum),
ARAD_LANE_PRESCALAR_CTRL_DECL("Denominator6 Prescalar", denominator6_enum),
ARAD_LANE_ENABLE_CTRL_DECL("Lane1 enable", 0x00),
ARAD_LANE_ENABLE_CTRL_DECL("Lane2 enable", 0x01),
ARAD_LANE_ENABLE_CTRL_DECL("Lane3 enable", 0x02),
ARAD_LANE_ENABLE_CTRL_DECL("Lane4 enable", 0x03),
ARAD_LANE_ENABLE_CTRL_DECL("Lane5 enable", 0x04),
ARAD_LANE_ENABLE_CTRL_DECL("Lane6 enable", 0x05),
ARAD_LANE_RATIO_CTRL_DECL("Lane1 Ratio", 0x00),
ARAD_LANE_RATIO_CTRL_DECL("Lane2 Ratio", 0x01),
ARAD_LANE_RATIO_CTRL_DECL("Lane3 Ratio", 0x02),
ARAD_LANE_RATIO_CTRL_DECL("Lane4 Ratio", 0x03),
ARAD_LANE_RATIO_CTRL_DECL("Lane5 Ratio", 0x04),
ARAD_LANE_RATIO_CTRL_DECL("Lane6 Ratio", 0x05),
AMX_ENABLE_CTRL_DECL("AMX1-1 Enable", 0x01, 0x01),
AMX_ENABLE_CTRL_DECL("AMX1-2 Enable", 0x01, 0x02),
AMX_ENABLE_CTRL_DECL("AMX1-3 Enable", 0x01, 0x03),
AMX_ENABLE_CTRL_DECL("AMX1-4 Enable", 0x01, 0x04),
AMX_ENABLE_CTRL_DECL("AMX2-1 Enable", 0x02, 0x01),
AMX_ENABLE_CTRL_DECL("AMX2-2 Enable", 0x02, 0x02),
AMX_ENABLE_CTRL_DECL("AMX2-3 Enable", 0x02, 0x03),
AMX_ENABLE_CTRL_DECL("AMX2-4 Enable", 0x02, 0x04),
AMX_ENABLE_CTRL_DECL("AMX3-1 Enable", 0x03, 0x01),
AMX_ENABLE_CTRL_DECL("AMX3-2 Enable", 0x03, 0x02),
AMX_ENABLE_CTRL_DECL("AMX3-3 Enable", 0x03, 0x03),
AMX_ENABLE_CTRL_DECL("AMX3-4 Enable", 0x03, 0x04),
AMX_ENABLE_CTRL_DECL("AMX4-1 Enable", 0x04, 0x01),
AMX_ENABLE_CTRL_DECL("AMX4-2 Enable", 0x04, 0x02),
AMX_ENABLE_CTRL_DECL("AMX4-3 Enable", 0x04, 0x03),
AMX_ENABLE_CTRL_DECL("AMX4-4 Enable", 0x04, 0x04),
I2S_SET_RATE("I2S1 rate", 0x01),
I2S_SET_RATE("I2S2 rate", 0x02),
I2S_SET_RATE("I2S3 rate", 0x03),
I2S_SET_RATE("I2S4 rate", 0x04),
I2S_SET_RATE("I2S5 rate", 0x05),
I2S_SET_RATE("I2S6 rate", 0x06),
I2S_LOOPBACK_ENABLE_CTRL_DECL("I2S1 Loopback", 0x01),
I2S_LOOPBACK_ENABLE_CTRL_DECL("I2S2 Loopback", 0x02),
I2S_LOOPBACK_ENABLE_CTRL_DECL("I2S3 Loopback", 0x03),
I2S_LOOPBACK_ENABLE_CTRL_DECL("I2S4 Loopback", 0x04),
I2S_LOOPBACK_ENABLE_CTRL_DECL("I2S5 Loopback", 0x05),
I2S_LOOPBACK_ENABLE_CTRL_DECL("I2S6 Loopback", 0x06),
REGDUMP_CTRL_DECL("ADMAIF1 regdump", ADMAIF1, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ADMAIF2 regdump", ADMAIF2, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ADMAIF3 regdump", ADMAIF3, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ADMAIF4 regdump", ADMAIF4, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ADMAIF5 regdump", ADMAIF5, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ADMAIF6 regdump", ADMAIF6, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ADMAIF7 regdump", ADMAIF7, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ADMAIF8 regdump", ADMAIF8, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ADMAIF9 regdump", ADMAIF9, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ADMAIF10 regdump", ADMAIF10, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ADMAIF11 regdump", ADMAIF11, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ADMAIF12 regdump", ADMAIF12, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ADMAIF13 regdump", ADMAIF13, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ADMAIF14 regdump", ADMAIF14, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ADMAIF15 regdump", ADMAIF15, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ADMAIF16 regdump", ADMAIF16, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ADMAIF17 regdump", ADMAIF17, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ADMAIF18 regdump", ADMAIF18, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ADMAIF19 regdump", ADMAIF19, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ADMAIF20 regdump", ADMAIF20, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("AMX1 regdump", AMX1, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("AMX2 regdump", AMX2, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("AMX3 regdump", AMX3, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("AMX4 regdump", AMX4, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ADX1 regdump", ADX1, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ADX2 regdump", ADX2, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ADX3 regdump", ADX3, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ADX4 regdump", ADX4, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("MIXER1-1 RX regdump", MIXER1, 0, NVAUDIO_REGDUMP_RX),
REGDUMP_CTRL_DECL("MIXER1-2 RX regdump", MIXER1, 1, NVAUDIO_REGDUMP_RX),
REGDUMP_CTRL_DECL("MIXER1-3 RX regdump", MIXER1, 2, NVAUDIO_REGDUMP_RX),
REGDUMP_CTRL_DECL("MIXER1-4 RX regdump", MIXER1, 3, NVAUDIO_REGDUMP_RX),
REGDUMP_CTRL_DECL("MIXER1-5 RX regdump", MIXER1, 4, NVAUDIO_REGDUMP_RX),
REGDUMP_CTRL_DECL("MIXER1-6 RX regdump", MIXER1, 5, NVAUDIO_REGDUMP_RX),
REGDUMP_CTRL_DECL("MIXER1-7 RX regdump", MIXER1, 6, NVAUDIO_REGDUMP_RX),
REGDUMP_CTRL_DECL("MIXER1-8 RX regdump", MIXER1, 7, NVAUDIO_REGDUMP_RX),
REGDUMP_CTRL_DECL("MIXER1-9 RX regdump", MIXER1, 8, NVAUDIO_REGDUMP_RX),
REGDUMP_CTRL_DECL("MIXER1-10 RX regdump", MIXER1, 9, NVAUDIO_REGDUMP_RX),
REGDUMP_CTRL_DECL("MIXER1-1 TX regdump", MIXER1, 0, NVAUDIO_REGDUMP_TX),
REGDUMP_CTRL_DECL("MIXER1-2 TX regdump", MIXER1, 1, NVAUDIO_REGDUMP_TX),
REGDUMP_CTRL_DECL("MIXER1-3 TX regdump", MIXER1, 2, NVAUDIO_REGDUMP_TX),
REGDUMP_CTRL_DECL("MIXER1-4 TX regdump", MIXER1, 3, NVAUDIO_REGDUMP_TX),
REGDUMP_CTRL_DECL("MIXER1-5 TX regdump", MIXER1, 4, NVAUDIO_REGDUMP_TX),
REGDUMP_CTRL_DECL("I2S1 regdump", I2S1, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("I2S2 regdump", I2S2, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("I2S3 regdump", I2S3, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("I2S4 regdump", I2S4, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("I2S5 regdump", I2S5, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("I2S6 regdump", I2S6, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ASRC1-1 regdump", ASRC1, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ASRC1-2 regdump", ASRC1, 1, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ASRC1-3 regdump", ASRC1, 2, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ASRC1-4 regdump", ASRC1, 3, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ASRC1-5 regdump", ASRC1, 4, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ASRC1-6 regdump", ASRC1, 5, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("SFC1 regdump", SFC1, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("SFC2 regdump", SFC2, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("SFC3 regdump", SFC3, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("SFC4 regdump", SFC4, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("MVC1 regdump", MVC1, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("MVC2 regdump", MVC2, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ARAD1 Lane1 regdump", ARAD1, 0, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ARAD1 Lane2 regdump", ARAD1, 1, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ARAD1 Lane3 regdump", ARAD1, 2, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ARAD1 Lane4 regdump", ARAD1, 3, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ARAD1 Lane5 regdump", ARAD1, 4, NVAUDIO_REGDUMP_RX_TX),
REGDUMP_CTRL_DECL("ARAD1 Lane6 regdump", ARAD1, 5, NVAUDIO_REGDUMP_RX_TX),
ADMA_REGDUMP_CTRL_DECL("ADMA1 regdump", 1),
ADMA_REGDUMP_CTRL_DECL("ADMA2 regdump", 2),
ADMA_REGDUMP_CTRL_DECL("ADMA3 regdump", 3),
ADMA_REGDUMP_CTRL_DECL("ADMA4 regdump", 4),
ADMA_REGDUMP_CTRL_DECL("ADMA5 regdump", 5),
ADMA_REGDUMP_CTRL_DECL("ADMA6 regdump", 6),
ADMA_REGDUMP_CTRL_DECL("ADMA7 regdump", 7),
ADMA_REGDUMP_CTRL_DECL("ADMA8 regdump", 8),
ADMA_REGDUMP_CTRL_DECL("ADMA9 regdump", 9),
ADMA_REGDUMP_CTRL_DECL("ADMA10 regdump", 10),
ADMA_REGDUMP_CTRL_DECL("ADMA11 regdump", 11),
ADMA_REGDUMP_CTRL_DECL("ADMA12 regdump", 12),
ADMA_REGDUMP_CTRL_DECL("ADMA13 regdump", 13),
ADMA_REGDUMP_CTRL_DECL("ADMA14 regdump", 14),
ADMA_REGDUMP_CTRL_DECL("ADMA15 regdump", 15),
ADMA_REGDUMP_CTRL_DECL("ADMA16 regdump", 16),
ADMA_REGDUMP_CTRL_DECL("ADMA17 regdump", 17),
ADMA_REGDUMP_CTRL_DECL("ADMA18 regdump", 18),
ADMA_REGDUMP_CTRL_DECL("ADMA19 regdump", 19),
ADMA_REGDUMP_CTRL_DECL("ADMA20 regdump", 20),
ADMA_REGDUMP_CTRL_DECL("ADMA21 regdump", 21),
ADMA_REGDUMP_CTRL_DECL("ADMA22 regdump", 22),
ADMA_REGDUMP_CTRL_DECL("ADMA23 regdump", 23),
ADMA_REGDUMP_CTRL_DECL("ADMA24 regdump", 24),
ADMA_REGDUMP_CTRL_DECL("ADMA25 regdump", 25),
ADMA_REGDUMP_CTRL_DECL("ADMA26 regdump", 26),
ADMA_REGDUMP_CTRL_DECL("ADMA27 regdump", 27),
ADMA_REGDUMP_CTRL_DECL("ADMA28 regdump", 28),
ADMA_REGDUMP_CTRL_DECL("ADMA29 regdump", 29),
ADMA_REGDUMP_CTRL_DECL("ADMA30 regdump", 30),
ADMA_REGDUMP_CTRL_DECL("ADMA31 regdump", 31),
ADMA_REGDUMP_CTRL_DECL("ADMA32 regdump", 32),
/* Metadata controls should be always the last ones */
SOC_SINGLE_BOOL_EXT("SAD Init", 0,
tegra_metadata_get_init, tegra_metadata_set_init),
SOC_SINGLE_BOOL_EXT("SAD Enable", 0,
tegra_metadata_get_enable, tegra_metadata_set_enable),
METADATA_CTRL_DECL("SAD Metadata"),
};
static struct snd_soc_component_driver tegra210_admaif_dai_driver = {
.name = "tegra210-virt-pcm",
.controls = tegra_virt_t186ref_controls,
.num_controls = ARRAY_SIZE(tegra_virt_t186ref_controls),
};
int tegra210_virt_admaif_register_component(struct platform_device *pdev,
struct tegra_virt_admaif_soc_data *data)
{
int i = 0;
int ret;
int admaif_ch_num = 0;
unsigned int admaif_ch_list[MAX_ADMAIF_IDS] = {0};
struct tegra_virt_admaif_soc_data *soc_data = data;
int adma_count = 0;
bool meta_enabled = false;
unsigned int buffer_size;
admaif = devm_kzalloc(&pdev->dev, sizeof(*admaif), GFP_KERNEL);
if (admaif == NULL) {
ret = -ENOMEM;
goto err;
}
admaif->client_data.hivc_client =
nvaudio_ivc_alloc_ctxt(&pdev->dev);
if (!admaif->client_data.hivc_client) {
dev_err(&pdev->dev, "Failed to allocate IVC context\n");
ret = -ENODEV;
goto err;
}
admaif->capture_dma_data = devm_kzalloc(&pdev->dev,
sizeof(struct tegra_alt_pcm_dma_params) *
soc_data->num_ch,
GFP_KERNEL);
if (admaif->capture_dma_data == NULL) {
ret = -ENOMEM;
goto err;
}
admaif->playback_dma_data = devm_kzalloc(&pdev->dev,
sizeof(struct tegra_alt_pcm_dma_params) *
soc_data->num_ch,
GFP_KERNEL);
if (admaif->playback_dma_data == NULL) {
ret = -ENOMEM;
goto err;
}
if (of_property_read_u32(pdev->dev.of_node,
"admaif_ch_num", &admaif_ch_num)) {
dev_err(&pdev->dev, "number of admaif channels is not set\n");
return -EINVAL;
}
if (of_property_read_u32_array(pdev->dev.of_node,
"admaif_ch_list",
admaif_ch_list,
admaif_ch_num)) {
dev_err(&pdev->dev, "admaif_ch_list is not populated\n");
return -EINVAL;
}
for (i = 0; i < soc_data->num_ch; i++) {
if ((i + 1) != admaif_ch_list[adma_count])
continue;
if (of_device_is_compatible(pdev->dev.of_node,
"nvidia,tegra186-virt-pcm")) {
admaif->playback_dma_data[i].addr = TEGRA186_ADMAIF_BASE +
TEGRA186_ADMAIF_XBAR_TX_FIFO_WRITE +
(i * TEGRA186_ADMAIF_CHANNEL_REG_STRIDE);
admaif->capture_dma_data[i].addr = TEGRA186_ADMAIF_BASE +
TEGRA186_ADMAIF_XBAR_RX_FIFO_READ +
(i * TEGRA186_ADMAIF_CHANNEL_REG_STRIDE);
} else if (of_device_is_compatible(pdev->dev.of_node,
"nvidia,tegra210-virt-pcm")) {
admaif->playback_dma_data[i].addr = TEGRA210_ADMAIF_BASE +
TEGRA210_ADMAIF_XBAR_TX_FIFO_WRITE +
(i * TEGRA210_ADMAIF_CHANNEL_REG_STRIDE);
admaif->capture_dma_data[i].addr = TEGRA210_ADMAIF_BASE +
TEGRA210_ADMAIF_XBAR_RX_FIFO_READ +
(i * TEGRA210_ADMAIF_CHANNEL_REG_STRIDE);
} else {
dev_err(&pdev->dev,
"Uncompatible device driver\n");
ret = -ENODEV;
goto err;
}
buffer_size = 0;
if (of_property_read_u32_index(pdev->dev.of_node,
"dma-buffer-size",
(i * 2) + 1,
&buffer_size) < 0)
dev_dbg(&pdev->dev,
"Missing property nvidia,dma-buffer-size\n");
admaif->playback_dma_data[i].buffer_size = buffer_size;
admaif->playback_dma_data[i].width = 32;
admaif->playback_dma_data[i].req_sel = i + 1;
if (of_property_read_string_index(pdev->dev.of_node,
"dma-names",
(adma_count * 2) + 1,
&admaif->playback_dma_data[i].chan_name) < 0) {
dev_err(&pdev->dev,
"Missing property nvidia,dma-names\n");
ret = -ENODEV;
goto err;
}
buffer_size = 0;
if (of_property_read_u32_index(pdev->dev.of_node,
"dma-buffer-size",
(i * 2),
&buffer_size) < 0)
dev_dbg(&pdev->dev,
"Missing property nvidia,dma-buffer-size\n");
admaif->capture_dma_data[i].buffer_size = buffer_size;
admaif->capture_dma_data[i].width = 32;
admaif->capture_dma_data[i].req_sel = i + 1;
if (of_property_read_string_index(pdev->dev.of_node,
"dma-names",
(adma_count * 2),
&admaif->capture_dma_data[i].chan_name) < 0) {
dev_err(&pdev->dev,
"Missing property nvidia,dma-names\n");
ret = -ENODEV;
goto err;
}
adma_count++;
}
/* Remove exposing metadata controls if not enabled in device node */
meta_enabled = of_property_read_bool(pdev->dev.of_node,
"sad_enabled");
if (!meta_enabled) {
tegra210_admaif_dai_driver.num_controls =
ARRAY_SIZE(tegra_virt_t186ref_controls) - NUM_META_CONTROLS;
}
ret = snd_soc_register_component(&pdev->dev,
&tegra210_admaif_dai_driver,
tegra210_admaif_dais,
soc_data->num_ch);
if (ret) {
dev_err(&pdev->dev, "Could not register DAIs %d: %d\n",
i, ret);
goto err;
}
ret = tegra_alt_pcm_platform_register(&pdev->dev);
if (ret) {
dev_err(&pdev->dev, "Could not register PCM: %d\n", ret);
goto err_unregister_dais;
}
return 0;
err_unregister_dais:
snd_soc_unregister_component(&pdev->dev);
err:
return ret;
}
EXPORT_SYMBOL_GPL(tegra210_virt_admaif_register_component);
void tegra210_virt_admaif_unregister_component(struct platform_device *pdev)
{
tegra_alt_pcm_platform_unregister(&pdev->dev);
snd_soc_unregister_component(&pdev->dev);
}
EXPORT_SYMBOL_GPL(tegra210_virt_admaif_unregister_component);
MODULE_LICENSE("GPL");