Files
linux-nv-oot/sound/soc/tegra-virt-alt/tegra_asoc_util_virt_alt.c
Jon Hunter 1bdabd6286 ASoC: tegra-virt-alt: Fix build for Linux v6.13
Building the tegra-virt-alt driver with Linux v6.13 fails because some
of the header files are not found ...

 sound/soc/tegra-virt-alt/tegra210_virt_alt_admaif.c:17:10: fatal error:
  tegra_pcm_alt.h: No such file or directory
   17 | #include "tegra_pcm_alt.h"
      |          ^~~~~~~~~~~~~~~~~

The 'tegra_pcm_alt.h' header is located in a 'include' sub-directory and
although the cflags add this path for find headers, the header is not
found because the '#include' of the file uses double-quotes and not
"<>". This could be fixed by simply updating the file with
'#include <tegra_pcm_alt.h>'. However, reviewing the code it simplifies
the Makefile to remove the 'include' sub-directory and directly include
the header files. Similarly, we can remove the search path of the
'nvaudio_ivc' headers and directly include these.

Bug 4991705

Change-Id: I1993d1f619698f33fc9edab05ad9235334fd3b5b
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3260938
Reviewed-by: Sameer Pujar <spujar@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2025-07-24 10:19:11 +00:00

1452 lines
39 KiB
C

// SPDX-License-Identifier: GPL-2.0-only
//
// SPDX-FileCopyrightText: Copyright (c) 2021-2024 NVIDIA CORPORATION. All rights reserved.
#include <linux/module.h>
#include <linux/platform_device.h>
#include "nvaudio_ivc/tegra_virt_alt_ivc.h"
#include "tegra_asoc_util_virt_alt.h"
#if TEGRA_ARAD
const int tegra186_arad_mux_value[] = {
-1, /* None */
0, 1, 2, 3, 4, 5, /* I2S1~6 */
12, 13, 14, 15, /* DMIC1~4 */
24, 25, /* DSPK1~2 */
};
const char * const tegra186_arad_mux_text[] = {
"None",
"I2S1",
"I2S2",
"I2S3",
"I2S4",
"I2S5",
"I2S6",
"DMIC1",
"DMIC2",
"DMIC3",
"DMIC4",
"DSPK1",
"DSPK2",
};
#endif
const char * const tegra186_asrc_ratio_source_text[] = {
"ARAD",
"SW",
};
const char * const tegra210_mvc_curve_type_text[] = {
"Poly",
"Linear",
};
int tegra_virt_t210mixer_get_gain(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
int32_t reg = mc->reg;
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
int err;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_AMIXER_GET_RX_GAIN;
msg.params.amixer_info.id = 0;
msg.params.amixer_info.rx_idx = reg;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
if (err < 0)
pr_err("%s: error on ivc_send_receive\n", __func__);
ucontrol->value.integer.value[0] =
msg.params.amixer_info.gain;
return 0;
}
EXPORT_SYMBOL(tegra_virt_t210mixer_get_gain);
int tegra_virt_t210mixer_set_gain(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
int32_t reg = mc->reg;
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
int err;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_AMIXER_SET_RX_GAIN;
msg.params.amixer_info.id = 0;
msg.params.amixer_info.rx_idx = reg;
msg.params.amixer_info.gain =
ucontrol->value.integer.value[0];
msg.params.amixer_info.is_instant_gain = 0;
msg.ack_required = true;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
if (err < 0) {
pr_err("%s: error on ivc_send_receive\n", __func__);
return err;
}
return 0;
}
EXPORT_SYMBOL(tegra_virt_t210mixer_set_gain);
int tegra_virt_t210mixer_set_gain_instant(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
int32_t reg = mc->reg;
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
int err;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_AMIXER_SET_RX_GAIN;
msg.params.amixer_info.id = 0;
msg.params.amixer_info.rx_idx = reg;
msg.params.amixer_info.gain =
ucontrol->value.integer.value[0];
msg.params.amixer_info.is_instant_gain = 1;
msg.ack_required = true;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
if (err < 0) {
pr_err("%s: error on ivc_send_receive\n", __func__);
return err;
}
return 0;
}
EXPORT_SYMBOL(tegra_virt_t210mixer_set_gain_instant);
int tegra_virt_t210mixer_get_duration(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
int32_t reg = mc->reg;
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
int err;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_AMIXER_GET_RX_DURATION;
msg.params.amixer_info.id = 0;
msg.params.amixer_info.rx_idx = reg;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
if (err < 0)
pr_err("%s: error on ivc_send_receive\n", __func__);
ucontrol->value.integer.value[0] =
msg.params.amixer_info.duration_n3;
return 0;
}
EXPORT_SYMBOL(tegra_virt_t210mixer_get_duration);
int tegra_virt_t210mixer_set_duration(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
int32_t reg = mc->reg;
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
int err;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_AMIXER_SET_RX_DURATION;
msg.params.amixer_info.id = 0;
msg.params.amixer_info.rx_idx = reg;
msg.params.amixer_info.duration_n3 =
ucontrol->value.integer.value[0];
msg.params.amixer_info.is_instant_gain = 0;
msg.ack_required = true;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
if (err < 0) {
pr_err("%s: error on ivc_send_receive\n", __func__);
return err;
}
return 0;
}
EXPORT_SYMBOL(tegra_virt_t210mixer_set_duration);
int tegra_virt_t210mixer_get_adder_config(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
int32_t reg = mc->reg;
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
int err;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_AMIXER_GET_TX_ADDER_CONFIG;
msg.params.amixer_info.id = 0;
msg.params.amixer_info.adder_idx = ((reg) >>
MIXER_CONFIG_SHIFT_VALUE) & 0xFFFF;
msg.params.amixer_info.adder_rx_idx = (reg) & 0xFFFF;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
if (err < 0)
pr_err("%s: error on ivc_send_receive\n", __func__);
ucontrol->value.integer.value[0] =
msg.params.amixer_info.adder_rx_idx_enable;
if (err < 0)
return err;
return 0;
}
EXPORT_SYMBOL(tegra_virt_t210mixer_get_adder_config);
int tegra_virt_t210mixer_set_adder_config(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_dapm_context *dapm =
snd_soc_dapm_kcontrol_dapm(kcontrol);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
int32_t reg = mc->reg;
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
int err, connect;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_AMIXER_SET_TX_ADDER_CONFIG;
msg.params.amixer_info.id = 0;
msg.params.amixer_info.adder_idx = ((reg) >>
MIXER_CONFIG_SHIFT_VALUE) & 0xFFFF;
msg.params.amixer_info.adder_rx_idx = (reg) & 0xFFFF;
msg.params.amixer_info.adder_rx_idx_enable =
ucontrol->value.integer.value[0];
msg.ack_required = true;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
if (err < 0) {
pr_err("%s: error on ivc_send_receive\n", __func__);
return err;
}
connect = !!ucontrol->value.integer.value[0];
snd_soc_dapm_mixer_update_power(dapm, kcontrol, connect, NULL);
return 0;
}
EXPORT_SYMBOL(tegra_virt_t210mixer_set_adder_config);
int tegra_virt_t210sfc_get_in_freq(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
unsigned int reg = mc->reg;
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
int err;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_SFC_GET_IN_FREQ;
msg.params.sfc_info.id = reg;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
ucontrol->value.integer.value[0] = msg.params.sfc_info.in_freq;
if (err < 0) {
pr_err("%s: error on ivc_send_receive\n", __func__);
return err;
}
return 0;
}
EXPORT_SYMBOL(tegra_virt_t210sfc_get_in_freq);
int tegra_virt_t210sfc_set_in_freq(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
unsigned int reg = mc->reg;
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
int err;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_SFC_SET_IN_FREQ;
msg.params.sfc_info.id = reg;
msg.params.sfc_info.in_freq =
ucontrol->value.integer.value[0];
msg.ack_required = true;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
if (err < 0) {
pr_err("%s: error on ivc_send_receive\n", __func__);
return err;
}
return 0;
}
EXPORT_SYMBOL(tegra_virt_t210sfc_set_in_freq);
int tegra_virt_t210sfc_get_out_freq(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
unsigned int reg = mc->reg;
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
int err;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_SFC_GET_OUT_FREQ;
msg.params.sfc_info.id = reg;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
ucontrol->value.integer.value[0] = msg.params.sfc_info.out_freq;
if (err < 0) {
pr_err("%s: error on ivc_send_receive\n", __func__);
return err;
}
return 0;
}
EXPORT_SYMBOL(tegra_virt_t210sfc_get_out_freq);
int tegra_virt_t210sfc_set_out_freq(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
int32_t reg = mc->reg;
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
int err;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_SFC_SET_OUT_FREQ;
msg.params.sfc_info.id = reg;
msg.params.sfc_info.out_freq =
ucontrol->value.integer.value[0];
msg.ack_required = true;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
if (err < 0) {
pr_err("%s: error on ivc_send_receive\n", __func__);
return err;
}
return 0;
}
EXPORT_SYMBOL(tegra_virt_t210sfc_set_out_freq);
int tegra_virt_t210mvc_get_curve_type(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
unsigned int reg = mc->reg;
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
int err;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_MVC_GET_CURVETYPE;
msg.params.mvc_info.id = reg;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
if (err < 0) {
pr_err("%s: error on ivc_send_receive\n", __func__);
return err;
}
ucontrol->value.integer.value[0] = msg.params.mvc_info.curve_type;
return 0;
}
EXPORT_SYMBOL(tegra_virt_t210mvc_get_curve_type);
int tegra_virt_t210mvc_set_curve_type(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
long int reg = (long int)kcontrol->tlv.p;
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
int err;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_MVC_SET_CURVETYPE;
msg.params.mvc_info.id = reg;
msg.params.mvc_info.curve_type =
ucontrol->value.integer.value[0];
msg.ack_required = true;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
if (err < 0) {
pr_err("%s: error on ivc_send_receive\n", __func__);
return err;
}
return 0;
}
EXPORT_SYMBOL(tegra_virt_t210mvc_set_curve_type);
int tegra_virt_t210mvc_get_tar_vol(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
unsigned int reg = mc->reg;
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
int err;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_MVC_GET_TAR_VOL;
msg.params.mvc_info.id = reg;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
if (err < 0) {
pr_err("%s: error on ivc_send_receive\n", __func__);
return err;
}
ucontrol->value.integer.value[0] = msg.params.mvc_info.tar_vol;
return 0;
}
EXPORT_SYMBOL(tegra_virt_t210mvc_get_tar_vol);
int tegra_virt_t210mvc_set_tar_vol(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
unsigned int reg = mc->reg;
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
int err;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_MVC_SET_TAR_VOL;
msg.params.mvc_info.id = reg;
msg.params.mvc_info.tar_vol =
ucontrol->value.integer.value[0];
msg.ack_required = true;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
if (err < 0) {
pr_err("%s: error on ivc_send_receive\n", __func__);
return err;
}
return 0;
}
EXPORT_SYMBOL(tegra_virt_t210mvc_set_tar_vol);
int tegra_virt_t210mvc_get_mute(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
int32_t reg = mc->reg;
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
int err;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_MVC_GET_MUTE;
msg.params.mvc_info.id = reg;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
if (err < 0) {
pr_err("%s: error on ivc_send_receive\n", __func__);
return err;
}
ucontrol->value.integer.value[0] = msg.params.mvc_info.mute;
return 0;
}
EXPORT_SYMBOL(tegra_virt_t210mvc_get_mute);
int tegra_virt_t210mvc_set_mute(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
unsigned int reg = mc->reg;
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
int err;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_MVC_SET_MUTE;
msg.params.mvc_info.id = reg;
msg.params.mvc_info.mute =
ucontrol->value.integer.value[0];
msg.ack_required = true;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
if (err < 0) {
pr_err("%s: error on ivc_send_receive\n", __func__);
return err;
}
return 0;
}
EXPORT_SYMBOL(tegra_virt_t210mvc_set_mute);
int tegra186_virt_asrc_get_ratio(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
struct soc_mreg_control *mc =
(struct soc_mreg_control *)kcontrol->private_value;
int32_t reg = mc->regbase;
int err;
uint64_t val;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_ASRC_GET_RATIO;
msg.params.asrc_info.id = 0;
msg.params.asrc_info.stream_num = reg;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
if (err < 0) {
pr_err("%s: error on ivc_send_receive\n", __func__);
return err;
}
val = (uint64_t) msg.params.asrc_info.int_ratio << 32;
val &= 0xffffffff00000000ULL;
val |= msg.params.asrc_info.frac_ratio;
ucontrol->value.integer64.value[0] = val;
return 0;
}
EXPORT_SYMBOL(tegra186_virt_asrc_get_ratio);
int tegra186_virt_asrc_set_ratio(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
struct soc_mreg_control *mc =
(struct soc_mreg_control *)kcontrol->private_value;
int32_t reg = mc->regbase;
int err;
uint64_t val;
struct nvaudio_ivc_msg msg;
val = ucontrol->value.integer64.value[0];
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_ASRC_SET_RATIO;
msg.params.asrc_info.id = 0;
msg.params.asrc_info.stream_num = reg;
msg.params.asrc_info.int_ratio =
(val >> 32) & 0xffffffffULL;
msg.params.asrc_info.frac_ratio =
(val & 0xffffffffULL);
msg.ack_required = true;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
if (err < 0) {
pr_err("%s: error on ivc_send_receive\n", __func__);
return err;
}
return 0;
}
EXPORT_SYMBOL(tegra186_virt_asrc_set_ratio);
int tegra186_virt_ratio_param_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
struct soc_mreg_control *mc =
(struct soc_mreg_control *)kcontrol->private_value;
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER64;
uinfo->count = 1;
uinfo->value.integer.min = mc->min;
uinfo->value.integer.max = mc->max;
return 0;
}
EXPORT_SYMBOL(tegra186_virt_ratio_param_info);
int tegra186_virt_asrc_get_ratio_source(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
uint64_t reg = (uint64_t)kcontrol->tlv.p;
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
int err;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_ASRC_GET_RATIO_SOURCE;
msg.params.asrc_info.stream_num = reg;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
if (err < 0) {
pr_err("%s: error on ivc_send_receive\n", __func__);
return err;
}
ucontrol->value.integer.value[0] = msg.params.asrc_info.ratio_source;
return 0;
}
EXPORT_SYMBOL(tegra186_virt_asrc_get_ratio_source);
int tegra186_virt_asrc_set_ratio_source(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
uint64_t reg = (uint64_t)kcontrol->tlv.p;
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
int err;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_ASRC_SET_RATIO_SOURCE;
msg.params.asrc_info.id = 0;
msg.params.asrc_info.stream_num = reg;
msg.params.asrc_info.ratio_source =
ucontrol->value.integer.value[0];
msg.ack_required = true;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
if (err < 0) {
pr_err("%s: error on ivc_send_receive\n", __func__);
return err;
}
return 0;
}
EXPORT_SYMBOL(tegra186_virt_asrc_set_ratio_source);
int tegra186_virt_asrc_get_hwcomp_disable(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
int32_t reg = mc->reg;
int err;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_ASRC_GET_HWCOMP_DISABLE;
msg.params.asrc_info.id = 0;
msg.params.asrc_info.stream_num = reg;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
if (err < 0) {
pr_err("%s: error on ivc_send_receive\n", __func__);
return err;
}
ucontrol->value.integer.value[0] = msg.params.asrc_info.hwcomp_disable;
return 0;
}
EXPORT_SYMBOL(tegra186_virt_asrc_get_hwcomp_disable);
int tegra186_virt_asrc_set_hwcomp_disable(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
int32_t reg = mc->reg;
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
int err;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_ASRC_SET_HWCOMP_DISABLE;
msg.params.asrc_info.id = 0;
msg.params.asrc_info.stream_num = reg;
msg.params.asrc_info.hwcomp_disable =
ucontrol->value.integer.value[0];
msg.ack_required = true;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
if (err < 0) {
pr_err("%s: error on ivc_send_receive\n", __func__);
return err;
}
return 0;
}
EXPORT_SYMBOL(tegra186_virt_asrc_set_hwcomp_disable);
int tegra186_virt_asrc_get_input_threshold(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
int32_t reg = mc->reg;
int err;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_ASRC_GET_INPUT_THRESHOLD;
msg.params.asrc_info.id = 0;
msg.params.asrc_info.stream_num = reg;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
ucontrol->value.integer.value[0] = msg.params.sfc_info.out_freq;
if (err < 0) {
pr_err("%s: error on ivc_send_receive\n", __func__);
return err;
}
ucontrol->value.integer.value[0] = msg.params.asrc_info.input_threshold;
return 0;
}
EXPORT_SYMBOL(tegra186_virt_asrc_get_input_threshold);
int tegra186_virt_asrc_set_input_threshold(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
int32_t reg = mc->reg;
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
int err;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_ASRC_SET_INPUT_THRESHOLD;
msg.params.asrc_info.id = 0;
msg.params.asrc_info.stream_num = reg;
msg.params.asrc_info.input_threshold =
ucontrol->value.integer.value[0];
msg.ack_required = true;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
if (err < 0) {
pr_err("%s: error on ivc_send_receive\n", __func__);
return err;
}
return 0;
}
EXPORT_SYMBOL(tegra186_virt_asrc_set_input_threshold);
int tegra186_virt_asrc_get_output_threshold(
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
int32_t reg = mc->reg;
int err;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_ASRC_GET_OUTPUT_THRESHOLD;
msg.params.asrc_info.id = 0;
msg.params.asrc_info.stream_num = reg;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
if (err < 0) {
pr_err("%s: error on ivc_send_receive\n", __func__);
return err;
}
ucontrol->value.integer.value[0] =
msg.params.asrc_info.output_threshold;
return 0;
}
EXPORT_SYMBOL(tegra186_virt_asrc_get_output_threshold);
int tegra186_virt_asrc_set_output_threshold(
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
int32_t reg = mc->reg;
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
int err;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_ASRC_SET_OUTPUT_THRESHOLD;
msg.params.asrc_info.id = 0;
msg.params.asrc_info.stream_num = reg;
msg.params.asrc_info.output_threshold =
ucontrol->value.integer.value[0];
msg.ack_required = true;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
if (err < 0) {
pr_err("%s: error on ivc_send_receive\n", __func__);
return err;
}
return 0;
}
EXPORT_SYMBOL(tegra186_virt_asrc_set_output_threshold);
#if TEGRA_ARAD
int tegra186_virt_arad_get_lane_source(
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
uint64_t reg = (uint64_t)kcontrol->tlv.p;
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
int err, i;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_ARAD_GET_LANE_SRC;
msg.params.arad_info.id = 0;
msg.params.arad_info.lane_id = reg % NUM_ARAD_LANES;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
if (err < 0) {
pr_err("%s: error on ivc_send_receive\n", __func__);
return err;
}
/* numerator reg 0 to 5, denominator reg 6 to 11 */
if (reg/NUM_ARAD_LANES) {
for (i = 0; i < NUM_ARAD_SOURCES; i++) {
if (e->values[i] ==
msg.params.arad_info.den_source)
break;
}
ucontrol->value.integer.value[0] = i;
} else {
for (i = 0; i < NUM_ARAD_SOURCES; i++) {
if (e->values[i] ==
msg.params.arad_info.num_source)
break;
}
ucontrol->value.integer.value[0] = i;
}
return 0;
}
EXPORT_SYMBOL(tegra186_virt_arad_get_lane_source);
int tegra186_virt_arad_set_lane_source(
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
uint64_t reg = (uint64_t)kcontrol->tlv.p;
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
int err;
struct nvaudio_ivc_msg msg;
int source;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_ARAD_SET_LANE_SRC;
msg.params.arad_info.id = 0;
msg.params.arad_info.lane_id = reg % NUM_ARAD_LANES;
/* numerator reg 0 to 5, denominator reg 6 to 11 */
source = e->values[ucontrol->value.integer.value[0]];
if (reg/NUM_ARAD_LANES) {
msg.params.arad_info.num_source = -1;
msg.params.arad_info.den_source = source;
} else {
msg.params.arad_info.num_source = source;
msg.params.arad_info.den_source = -1;
}
msg.ack_required = true;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
if (err < 0) {
pr_err("%s: error on ivc_send_receive\n", __func__);
return err;
}
return 0;
}
EXPORT_SYMBOL(tegra186_virt_arad_set_lane_source);
int tegra186_virt_arad_get_lane_prescalar(
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
unsigned int reg = mc->reg;
int err;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_ARAD_GET_PRESCALAR;
msg.params.arad_info.id = 0;
msg.params.arad_info.lane_id = reg % NUM_ARAD_LANES;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
if (err < 0) {
pr_err("%s: error on ivc_send_receive\n", __func__);
return err;
}
/* numerator reg 0 to 5, denominator reg 6 to 11 */
if (reg/NUM_ARAD_LANES)
ucontrol->value.integer.value[0] =
msg.params.arad_info.den_prescalar;
else
ucontrol->value.integer.value[0] =
msg.params.arad_info.num_prescalar;
return 0;
}
EXPORT_SYMBOL(tegra186_virt_arad_get_lane_prescalar);
int tegra186_virt_arad_set_lane_prescalar(
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
unsigned int reg = mc->reg;
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
int err;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_ARAD_SET_PRESCALAR;
msg.params.arad_info.id = 0;
msg.params.arad_info.lane_id = reg % NUM_ARAD_LANES;
/* numerator reg 0 to 5, denominator reg 6 to 11 */
if (reg/NUM_ARAD_LANES) {
msg.params.arad_info.num_prescalar = -1;
msg.params.arad_info.den_prescalar =
ucontrol->value.integer.value[0];
} else {
msg.params.arad_info.num_prescalar =
ucontrol->value.integer.value[0];
msg.params.arad_info.den_prescalar = -1;
}
msg.ack_required = true;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
if (err < 0) {
pr_err("%s: error on ivc_send_receive\n", __func__);
return err;
}
return 0;
}
EXPORT_SYMBOL(tegra186_virt_arad_set_lane_prescalar);
int tegra186_virt_arad_get_lane_enable(
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
unsigned int reg = mc->reg;
int err;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_ARAD_GET_LANE_ENABLE;
msg.params.arad_info.id = 0;
msg.params.arad_info.lane_id = reg;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
if (err < 0) {
pr_err("%s: error on ivc_send_receive\n", __func__);
return err;
}
ucontrol->value.integer.value[0] =
msg.params.arad_info.lane_enable;
return 0;
}
EXPORT_SYMBOL(tegra186_virt_arad_get_lane_enable);
int tegra186_virt_arad_set_lane_enable(
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
unsigned int reg = mc->reg;
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
int err;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_ARAD_SET_LANE_ENABLE;
msg.params.arad_info.id = 0;
msg.params.arad_info.lane_id = reg;
msg.params.arad_info.lane_enable =
ucontrol->value.integer.value[0];
msg.ack_required = true;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
if (err < 0) {
pr_err("%s: error on ivc_send_receive\n", __func__);
return err;
}
return 0;
}
EXPORT_SYMBOL(tegra186_virt_arad_set_lane_enable);
int tegra186_virt_arad_get_lane_ratio(
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
unsigned int reg = mc->reg;
int err;
uint64_t val;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_ARAD_GET_LANE_RATIO;
msg.params.arad_info.id = 0;
msg.params.arad_info.lane_id = reg;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
if (err < 0) {
pr_err("%s: error on ivc_send_receive\n", __func__);
return err;
}
val = (uint64_t)msg.params.arad_info.int_ratio << 32;
val &= 0xffffffff00000000ULL;
val |= (uint64_t)msg.params.arad_info.frac_ratio;
ucontrol->value.integer64.value[0] = val;
return 0;
}
EXPORT_SYMBOL(tegra186_virt_arad_get_lane_ratio);
#endif
int tegra_virt_i2s_get_loopback_enable(
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
unsigned int reg = mc->reg;
int err;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_I2S_GET_LOOPBACK_ENABLE;
msg.params.i2s_info.i2s_id = reg;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
if (err < 0) {
pr_err("%s: error on ivc_send_receive\n", __func__);
return err;
}
ucontrol->value.integer.value[0] =
msg.params.i2s_info.i2s_loopback_enable;
return 0;
}
EXPORT_SYMBOL(tegra_virt_i2s_get_loopback_enable);
int tegra_virt_i2s_set_loopback_enable(
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
unsigned int reg = mc->reg;
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
int err;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_I2S_SET_LOOPBACK_ENABLE;
msg.params.i2s_info.i2s_id = reg;
msg.params.i2s_info.i2s_loopback_enable =
ucontrol->value.integer.value[0];
msg.ack_required = true;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
if (err < 0) {
pr_err("%s: error on ivc_send_receive\n", __func__);
return err;
}
return 0;
}
EXPORT_SYMBOL(tegra_virt_i2s_set_loopback_enable);
#if TEGRA_REGDUMP
int tegra_virt_t210ahub_get_regdump(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
return 0;
}
EXPORT_SYMBOL(tegra_virt_t210ahub_get_regdump);
int tegra_virt_t210ahub_set_regdump(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
int32_t reg = mc->reg;
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
int err;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_AHUB_BLOCK_REGDUMP;
msg.params.ahub_block_info.block_id = (reg) & 0xFFFF;
msg.params.ahub_block_info.stream_id = ((reg) >>
STREAM_ID_SHIFT_VALUE) & 0xFF;
msg.params.ahub_block_info.dump_cmd = ((reg) >>
REGDUMP_CMD_SHIFT_VALUE) & 0xFF;
msg.ack_required = true;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
if (err < 0) {
pr_err("%s: error on ivc_send_receive\n", __func__);
return err;
}
return 0;
}
EXPORT_SYMBOL(tegra_virt_t210ahub_set_regdump);
int tegra_virt_t210adma_get_regdump(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
return 0;
}
EXPORT_SYMBOL(tegra_virt_t210adma_get_regdump);
int tegra_virt_t210adma_set_regdump(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
unsigned int reg = mc->reg;
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
int err;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_ADMA_BLOCK_REGDUMP;
msg.params.adma_info.channel_num = (uint32_t)reg;
msg.ack_required = true;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
if (err < 0) {
pr_err("%s: error on ivc_send_receive\n", __func__);
return err;
}
return 0;
}
EXPORT_SYMBOL(tegra_virt_t210adma_set_regdump);
#endif
//Set mixer fade
int tegra_virt_t210mixer_set_fade(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
int err, id;
uint32_t rx_id, rx_gain, rx_dur;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_AMIXER_SET_FADE;
msg.params.fade_info.id = 0;
for (id = 0; id < TEGRA210_MIXER_AXBAR_RX_MAX; id++) {
rx_id = ucontrol->value.integer.value[3 * id];
rx_gain = ucontrol->value.integer.value[(3 * id) + 1];
rx_dur = ucontrol->value.integer.value[(3 * id) + 2];
// Checking for end of input data
if (rx_id == 0 && rx_gain == 0 && rx_dur == 0)
break;
// Checking for valid rx id
if (rx_id <= 0 || rx_id > TEGRA210_MIXER_AXBAR_RX_MAX) {
pr_err("Mixer id is out of range\n");
return -EINVAL;
}
// Making rx id zero-indexed for audio server
rx_id = rx_id - 1;
msg.params.fade_info.rx_idx |= (1 << rx_id);
msg.params.fade_info.gain_level[rx_id] = rx_gain;
msg.params.fade_info.duration_n3[rx_id] = rx_dur;
}
msg.ack_required = true;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
if (err < 0) {
pr_err("%s: error on ivc_send_receive\n", __func__);
return err;
}
return 0;
}
EXPORT_SYMBOL(tegra_virt_t210mixer_set_fade);
// Dummy get fade
int tegra_virt_t210mixer_get_fade(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
return 0;
}
EXPORT_SYMBOL(tegra_virt_t210mixer_get_fade);
//Get fade status
int tegra_virt_t210mixer_get_fade_status(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct nvaudio_ivc_ctxt *hivc_client =
nvaudio_ivc_alloc_ctxt(card->dev);
int err, id;
struct nvaudio_ivc_msg msg;
memset(&msg, 0, sizeof(struct nvaudio_ivc_msg));
msg.cmd = NVAUDIO_AMIXER_GET_FADE_STATUS;
msg.params.fade_status.id = 0;
err = nvaudio_ivc_send_receive(hivc_client,
&msg,
sizeof(struct nvaudio_ivc_msg));
if (err < 0)
pr_err("%s: error on ivc_send_receive\n", __func__);
for (id = 0; id < TEGRA210_MIXER_AXBAR_RX_MAX; id++) {
ucontrol->value.integer.value[id] =
msg.params.fade_status.status[id];
}
return 0;
}
EXPORT_SYMBOL(tegra_virt_t210mixer_get_fade_status);
//Fade param info
int tegra_virt_t210mixer_param_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
struct soc_bytes *params = (void *)kcontrol->private_value;
if (params->mask == SNDRV_CTL_ELEM_TYPE_INTEGER) {
params->num_regs = 30;
uinfo->value.integer.min = 0;
uinfo->value.integer.max = 0xffffffff;
}
if (strstr(kcontrol->id.name, "Status"))
params->num_regs = 10;
uinfo->type = params->mask;
uinfo->count = params->num_regs;
return 0;
}
MODULE_AUTHOR("Dipesh Gandhi <dipeshg@nvidia.com>");
MODULE_DESCRIPTION("Tegra Virt ASoC utility code");
MODULE_LICENSE("GPL");