mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 17:25:35 +03:00
ASoC: 8 ch playback/capture support
Change adds support on adsp-alt: - allows pcm_open for upto 8 channel. - adds option to pass burst_size for HV - allows BE to be configured with FE's params to be sent via ivc to audioserver. Change-Id: Ib3ab3fb4d95bfc8335cd1d52eeb71cc4e5a538a5 Signed-off-by: Dipesh Gandhi <dipeshg@nvidia.com> Reviewed-on: http://git-master/r/1317770 GVS: Gerrit_Virtual_Submit Reviewed-by: Uday Gupta <udayg@nvidia.com> Reviewed-by: Viraj Karandikar <vkarandikar@nvidia.com> Reviewed-by: Nitin Pai <npai@nvidia.com>
This commit is contained in:
committed by
Sameer Pujar
parent
c85e969ca0
commit
76d48d8cd8
@@ -148,6 +148,9 @@ struct tegra210_adsp {
|
|||||||
struct tegra210_adsp_path {
|
struct tegra210_adsp_path {
|
||||||
uint32_t fe_reg;
|
uint32_t fe_reg;
|
||||||
uint32_t be_reg;
|
uint32_t be_reg;
|
||||||
|
uint32_t channels;
|
||||||
|
uint32_t format;
|
||||||
|
uint32_t rate;
|
||||||
} pcm_path[ADSP_FE_COUNT+1][2];
|
} pcm_path[ADSP_FE_COUNT+1][2];
|
||||||
#ifdef CONFIG_SND_SOC_TEGRA_VIRT_IVC_COMM
|
#ifdef CONFIG_SND_SOC_TEGRA_VIRT_IVC_COMM
|
||||||
struct nvaudio_ivc_ctxt *hivc_client;
|
struct nvaudio_ivc_ctxt *hivc_client;
|
||||||
@@ -2006,18 +2009,31 @@ static void tegra_adsp_set_admaif_id(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
static int tegra_adsp_get_connected_fe(struct tegra210_adsp *adsp,
|
||||||
|
uint32_t be_reg,
|
||||||
|
int stream)
|
||||||
|
{
|
||||||
|
unsigned int val;
|
||||||
|
|
||||||
|
for (val = 1; val < (ADSP_FE_COUNT); val++) {
|
||||||
|
if (adsp->pcm_path[val][stream].be_reg == be_reg)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
static int tegra_adsp_admaif_ivc_set_cif(struct tegra210_adsp *adsp,
|
static int tegra_adsp_admaif_ivc_set_cif(struct tegra210_adsp *adsp,
|
||||||
struct snd_pcm_hw_params *params,
|
struct snd_pcm_hw_params *params,
|
||||||
uint32_t admaif_id,
|
uint32_t admaif_id,
|
||||||
|
uint32_t be_reg,
|
||||||
|
nvfx_adma_init_params_t *adma_params,
|
||||||
int stream)
|
int stream)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret = 0;
|
||||||
uint32_t ivc_msg_admaif_id;
|
uint32_t ivc_msg_admaif_id;
|
||||||
struct tegra210_virt_audio_cif cif_setting;
|
struct tegra210_virt_audio_cif cif_setting;
|
||||||
struct tegra210_virt_audio_cif *cif_conf = NULL;
|
struct tegra210_virt_audio_cif *cif_conf = NULL;
|
||||||
struct nvaudio_ivc_msg msg;
|
struct nvaudio_ivc_msg msg;
|
||||||
unsigned int value;
|
unsigned int value, channels, format, rate;
|
||||||
|
|
||||||
adsp->hivc_client =
|
adsp->hivc_client =
|
||||||
nvaudio_ivc_alloc_ctxt(adsp->dev);
|
nvaudio_ivc_alloc_ctxt(adsp->dev);
|
||||||
@@ -2027,30 +2043,63 @@ static int tegra_adsp_admaif_ivc_set_cif(struct tegra210_adsp *adsp,
|
|||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
channels = params_channels(params);
|
||||||
|
format = params_format(params);
|
||||||
|
|
||||||
|
/* overwrite channel, rate, format if we already have FE info */
|
||||||
|
if (stream == SNDRV_PCM_STREAM_CAPTURE) {
|
||||||
|
ret = tegra_adsp_get_connected_fe(adsp, be_reg,
|
||||||
|
SNDRV_PCM_STREAM_PLAYBACK);
|
||||||
|
if (ret != ADSP_FE_COUNT) {
|
||||||
|
format = adsp->pcm_path
|
||||||
|
[ret][SNDRV_PCM_STREAM_PLAYBACK].format;
|
||||||
|
channels = adsp->pcm_path
|
||||||
|
[ret][SNDRV_PCM_STREAM_PLAYBACK].channels;
|
||||||
|
rate = adsp->pcm_path
|
||||||
|
[ret][SNDRV_PCM_STREAM_PLAYBACK].rate;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ret = tegra_adsp_get_connected_fe(adsp, be_reg,
|
||||||
|
SNDRV_PCM_STREAM_CAPTURE);
|
||||||
|
if (ret != ADSP_FE_COUNT) {
|
||||||
|
format = adsp->pcm_path
|
||||||
|
[ret][SNDRV_PCM_STREAM_CAPTURE].format;
|
||||||
|
channels = adsp->pcm_path
|
||||||
|
[ret][SNDRV_PCM_STREAM_CAPTURE].channels;
|
||||||
|
rate = adsp->pcm_path
|
||||||
|
[ret][SNDRV_PCM_STREAM_CAPTURE].rate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cif_conf = &cif_setting;
|
cif_conf = &cif_setting;
|
||||||
|
|
||||||
ivc_msg_admaif_id = admaif_id - 1;
|
ivc_msg_admaif_id = admaif_id - 1;
|
||||||
|
|
||||||
memset(cif_conf, 0, sizeof(struct tegra210_virt_audio_cif));
|
memset(cif_conf, 0, sizeof(struct tegra210_virt_audio_cif));
|
||||||
cif_conf->audio_channels = params_channels(params);
|
cif_conf->audio_channels = channels;
|
||||||
cif_conf->client_channels = params_channels(params);
|
cif_conf->client_channels = channels;
|
||||||
|
|
||||||
switch (params_format(params)) {
|
switch (format) {
|
||||||
case SNDRV_PCM_FORMAT_S8:
|
case SNDRV_PCM_FORMAT_S8:
|
||||||
cif_conf->client_bits = TEGRA210_AUDIOCIF_BITS_8;
|
cif_conf->client_bits = TEGRA210_AUDIOCIF_BITS_8;
|
||||||
cif_conf->audio_bits = TEGRA210_AUDIOCIF_BITS_8;
|
cif_conf->audio_bits = TEGRA210_AUDIOCIF_BITS_8;
|
||||||
|
adma_params->burst_size = channels/4;
|
||||||
break;
|
break;
|
||||||
case SNDRV_PCM_FORMAT_S16_LE:
|
case SNDRV_PCM_FORMAT_S16_LE:
|
||||||
cif_conf->client_bits = TEGRA210_AUDIOCIF_BITS_16;
|
cif_conf->client_bits = TEGRA210_AUDIOCIF_BITS_16;
|
||||||
cif_conf->audio_bits = TEGRA210_AUDIOCIF_BITS_16;
|
cif_conf->audio_bits = TEGRA210_AUDIOCIF_BITS_16;
|
||||||
|
adma_params->burst_size = (channels * 2)/4;
|
||||||
break;
|
break;
|
||||||
case SNDRV_PCM_FORMAT_S24_LE:
|
case SNDRV_PCM_FORMAT_S24_LE:
|
||||||
cif_conf->client_bits = TEGRA210_AUDIOCIF_BITS_24;
|
cif_conf->client_bits = TEGRA210_AUDIOCIF_BITS_24;
|
||||||
cif_conf->audio_bits = TEGRA210_AUDIOCIF_BITS_24;
|
cif_conf->audio_bits = TEGRA210_AUDIOCIF_BITS_24;
|
||||||
|
adma_params->burst_size = (channels * 3)/4;
|
||||||
break;
|
break;
|
||||||
case SNDRV_PCM_FORMAT_S32_LE:
|
case SNDRV_PCM_FORMAT_S32_LE:
|
||||||
cif_conf->client_bits = TEGRA210_AUDIOCIF_BITS_32;
|
cif_conf->client_bits = TEGRA210_AUDIOCIF_BITS_32;
|
||||||
cif_conf->audio_bits = TEGRA210_AUDIOCIF_BITS_32;
|
cif_conf->audio_bits = TEGRA210_AUDIOCIF_BITS_32;
|
||||||
|
adma_params->burst_size = channels;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dev_err(adsp->dev, "Wrong format!\n");
|
dev_err(adsp->dev, "Wrong format!\n");
|
||||||
@@ -2102,6 +2151,7 @@ static int tegra210_adsp_admaif_hv_hw_params(
|
|||||||
struct snd_pcm_hw_params *params,
|
struct snd_pcm_hw_params *params,
|
||||||
uint32_t admaif_id,
|
uint32_t admaif_id,
|
||||||
uint32_t be_reg,
|
uint32_t be_reg,
|
||||||
|
nvfx_adma_init_params_t *adma_params,
|
||||||
int stream)
|
int stream)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@@ -2109,6 +2159,8 @@ static int tegra210_adsp_admaif_hv_hw_params(
|
|||||||
ret = tegra_adsp_admaif_ivc_set_cif(adsp,
|
ret = tegra_adsp_admaif_ivc_set_cif(adsp,
|
||||||
params,
|
params,
|
||||||
admaif_id,
|
admaif_id,
|
||||||
|
be_reg,
|
||||||
|
adma_params,
|
||||||
stream);
|
stream);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
pr_err("error on ivc_send\n");
|
pr_err("error on ivc_send\n");
|
||||||
@@ -2121,6 +2173,32 @@ static int tegra210_adsp_admaif_hv_hw_params(
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
static int tegra210_adsp_fe_hw_params(struct snd_pcm_substream *substream,
|
||||||
|
struct snd_pcm_hw_params *params,
|
||||||
|
struct snd_soc_dai *dai)
|
||||||
|
{
|
||||||
|
|
||||||
|
struct tegra210_adsp *adsp = snd_soc_dai_get_drvdata(dai);
|
||||||
|
uint32_t fe_reg = dai->id;
|
||||||
|
|
||||||
|
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||||
|
adsp->pcm_path[fe_reg][SNDRV_PCM_STREAM_PLAYBACK].rate
|
||||||
|
= params_rate(params);
|
||||||
|
adsp->pcm_path[fe_reg][SNDRV_PCM_STREAM_PLAYBACK].channels
|
||||||
|
= params_channels(params);
|
||||||
|
adsp->pcm_path[fe_reg][SNDRV_PCM_STREAM_PLAYBACK].format
|
||||||
|
= params_format(params);
|
||||||
|
} else {
|
||||||
|
adsp->pcm_path[fe_reg][SNDRV_PCM_STREAM_CAPTURE].rate
|
||||||
|
= params_rate(params);
|
||||||
|
adsp->pcm_path[fe_reg][SNDRV_PCM_STREAM_CAPTURE].channels
|
||||||
|
= params_channels(params);
|
||||||
|
adsp->pcm_path[fe_reg][SNDRV_PCM_STREAM_CAPTURE].format
|
||||||
|
= params_format(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* ADSP-ADMAIF codec driver HW-params. Used for configuring ADMA */
|
/* ADSP-ADMAIF codec driver HW-params. Used for configuring ADMA */
|
||||||
static int tegra210_adsp_admaif_hw_params(struct snd_pcm_substream *substream,
|
static int tegra210_adsp_admaif_hw_params(struct snd_pcm_substream *substream,
|
||||||
@@ -2141,9 +2219,10 @@ static int tegra210_adsp_admaif_hw_params(struct snd_pcm_substream *substream,
|
|||||||
|
|
||||||
dev_vdbg(adsp->dev, "%s : stream %d admaif %d\n",
|
dev_vdbg(adsp->dev, "%s : stream %d admaif %d\n",
|
||||||
__func__, substream->stream, admaif_id);
|
__func__, substream->stream, admaif_id);
|
||||||
|
|
||||||
if (!adsp->adsp_started)
|
if (!adsp->adsp_started)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
memset(&adma_params, 0, sizeof(adma_params));
|
||||||
#ifdef CONFIG_SND_SOC_TEGRA_VIRT_IVC_COMM
|
#ifdef CONFIG_SND_SOC_TEGRA_VIRT_IVC_COMM
|
||||||
if (of_device_is_compatible(node, "nvidia,tegra210-adsp-audio-hv")) {
|
if (of_device_is_compatible(node, "nvidia,tegra210-adsp-audio-hv")) {
|
||||||
|
|
||||||
@@ -2152,6 +2231,7 @@ static int tegra210_adsp_admaif_hw_params(struct snd_pcm_substream *substream,
|
|||||||
params,
|
params,
|
||||||
admaif_id,
|
admaif_id,
|
||||||
be_reg,
|
be_reg,
|
||||||
|
&adma_params,
|
||||||
substream->stream);
|
substream->stream);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
pr_err("error on ivc_send\n");
|
pr_err("error on ivc_send\n");
|
||||||
@@ -2162,7 +2242,6 @@ static int tegra210_adsp_admaif_hw_params(struct snd_pcm_substream *substream,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
adma_params.mode = ADMA_MODE_CONTINUOUS;
|
adma_params.mode = ADMA_MODE_CONTINUOUS;
|
||||||
adma_params.ahub_channel = admaif_id;
|
adma_params.ahub_channel = admaif_id;
|
||||||
adma_params.periods = 2; /* We need ping-pong buffers for ADMA */
|
adma_params.periods = 2; /* We need ping-pong buffers for ADMA */
|
||||||
@@ -2548,6 +2627,9 @@ static int tegra210_adsp_widget_event(struct snd_soc_dapm_widget *w,
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
static struct snd_soc_dai_ops tegra210_adsp_fe_dai_ops = {
|
||||||
|
.hw_params = tegra210_adsp_fe_hw_params,
|
||||||
|
};
|
||||||
|
|
||||||
static struct snd_soc_dai_ops tegra210_adsp_admaif_dai_ops = {
|
static struct snd_soc_dai_ops tegra210_adsp_admaif_dai_ops = {
|
||||||
.hw_params = tegra210_adsp_admaif_hw_params,
|
.hw_params = tegra210_adsp_admaif_hw_params,
|
||||||
@@ -2563,7 +2645,7 @@ static struct snd_soc_dai_driver tegra210_adsp_dai[] = {
|
|||||||
.playback = {
|
.playback = {
|
||||||
.stream_name = "ADSP PCM1 Receive",
|
.stream_name = "ADSP PCM1 Receive",
|
||||||
.channels_min = 1,
|
.channels_min = 1,
|
||||||
.channels_max = 2,
|
.channels_max = 8,
|
||||||
.rates = SNDRV_PCM_RATE_8000_48000,
|
.rates = SNDRV_PCM_RATE_8000_48000,
|
||||||
.formats = SNDRV_PCM_FMTBIT_S8 |
|
.formats = SNDRV_PCM_FMTBIT_S8 |
|
||||||
SNDRV_PCM_FMTBIT_S16_LE |
|
SNDRV_PCM_FMTBIT_S16_LE |
|
||||||
@@ -2573,7 +2655,7 @@ static struct snd_soc_dai_driver tegra210_adsp_dai[] = {
|
|||||||
.capture = {
|
.capture = {
|
||||||
.stream_name = "ADSP PCM1 Transmit",
|
.stream_name = "ADSP PCM1 Transmit",
|
||||||
.channels_min = 1,
|
.channels_min = 1,
|
||||||
.channels_max = 2,
|
.channels_max = 8,
|
||||||
.rates = SNDRV_PCM_RATE_8000_48000,
|
.rates = SNDRV_PCM_RATE_8000_48000,
|
||||||
.formats = SNDRV_PCM_FMTBIT_S8 |
|
.formats = SNDRV_PCM_FMTBIT_S8 |
|
||||||
SNDRV_PCM_FMTBIT_S16_LE |
|
SNDRV_PCM_FMTBIT_S16_LE |
|
||||||
@@ -2586,7 +2668,7 @@ static struct snd_soc_dai_driver tegra210_adsp_dai[] = {
|
|||||||
.playback = {
|
.playback = {
|
||||||
.stream_name = "ADSP PCM2 Receive",
|
.stream_name = "ADSP PCM2 Receive",
|
||||||
.channels_min = 1,
|
.channels_min = 1,
|
||||||
.channels_max = 2,
|
.channels_max = 8,
|
||||||
.rates = SNDRV_PCM_RATE_8000_48000,
|
.rates = SNDRV_PCM_RATE_8000_48000,
|
||||||
.formats = SNDRV_PCM_FMTBIT_S8 |
|
.formats = SNDRV_PCM_FMTBIT_S8 |
|
||||||
SNDRV_PCM_FMTBIT_S16_LE |
|
SNDRV_PCM_FMTBIT_S16_LE |
|
||||||
@@ -2596,7 +2678,7 @@ static struct snd_soc_dai_driver tegra210_adsp_dai[] = {
|
|||||||
.capture = {
|
.capture = {
|
||||||
.stream_name = "ADSP PCM2 Transmit",
|
.stream_name = "ADSP PCM2 Transmit",
|
||||||
.channels_min = 1,
|
.channels_min = 1,
|
||||||
.channels_max = 2,
|
.channels_max = 8,
|
||||||
.rates = SNDRV_PCM_RATE_8000_48000,
|
.rates = SNDRV_PCM_RATE_8000_48000,
|
||||||
.formats = SNDRV_PCM_FMTBIT_S8 |
|
.formats = SNDRV_PCM_FMTBIT_S8 |
|
||||||
SNDRV_PCM_FMTBIT_S16_LE |
|
SNDRV_PCM_FMTBIT_S16_LE |
|
||||||
@@ -2652,7 +2734,7 @@ static struct snd_soc_dai_driver tegra210_adsp_dai[] = {
|
|||||||
.playback = { \
|
.playback = { \
|
||||||
.stream_name = "ADSP-FE" #idx " Receive",\
|
.stream_name = "ADSP-FE" #idx " Receive",\
|
||||||
.channels_min = 1, \
|
.channels_min = 1, \
|
||||||
.channels_max = 2, \
|
.channels_max = 8, \
|
||||||
.rates = SNDRV_PCM_RATE_8000_48000, \
|
.rates = SNDRV_PCM_RATE_8000_48000, \
|
||||||
.formats = SNDRV_PCM_FMTBIT_S8 | \
|
.formats = SNDRV_PCM_FMTBIT_S8 | \
|
||||||
SNDRV_PCM_FMTBIT_S16_LE | \
|
SNDRV_PCM_FMTBIT_S16_LE | \
|
||||||
@@ -2662,13 +2744,14 @@ static struct snd_soc_dai_driver tegra210_adsp_dai[] = {
|
|||||||
.capture = { \
|
.capture = { \
|
||||||
.stream_name = "ADSP-FE" #idx " Transmit",\
|
.stream_name = "ADSP-FE" #idx " Transmit",\
|
||||||
.channels_min = 1, \
|
.channels_min = 1, \
|
||||||
.channels_max = 2, \
|
.channels_max = 8, \
|
||||||
.rates = SNDRV_PCM_RATE_8000_48000, \
|
.rates = SNDRV_PCM_RATE_8000_48000, \
|
||||||
.formats = SNDRV_PCM_FMTBIT_S8 | \
|
.formats = SNDRV_PCM_FMTBIT_S8 | \
|
||||||
SNDRV_PCM_FMTBIT_S16_LE | \
|
SNDRV_PCM_FMTBIT_S16_LE | \
|
||||||
SNDRV_PCM_FMTBIT_S24_LE | \
|
SNDRV_PCM_FMTBIT_S24_LE | \
|
||||||
SNDRV_PCM_FMTBIT_S32_LE, \
|
SNDRV_PCM_FMTBIT_S32_LE, \
|
||||||
}, \
|
}, \
|
||||||
|
.ops = &tegra210_adsp_fe_dai_ops, \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ADSP_ADMAIF_CODEC_DAI(idx) \
|
#define ADSP_ADMAIF_CODEC_DAI(idx) \
|
||||||
@@ -2678,14 +2761,14 @@ static struct snd_soc_dai_driver tegra210_adsp_dai[] = {
|
|||||||
.playback = { \
|
.playback = { \
|
||||||
.stream_name = "ADSP-ADMAIF" #idx " Receive", \
|
.stream_name = "ADSP-ADMAIF" #idx " Receive", \
|
||||||
.channels_min = 1, \
|
.channels_min = 1, \
|
||||||
.channels_max = 2, \
|
.channels_max = 8, \
|
||||||
.rates = SNDRV_PCM_RATE_8000_48000, \
|
.rates = SNDRV_PCM_RATE_8000_48000, \
|
||||||
.formats = SNDRV_PCM_FMTBIT_S16_LE, \
|
.formats = SNDRV_PCM_FMTBIT_S16_LE, \
|
||||||
}, \
|
}, \
|
||||||
.capture = { \
|
.capture = { \
|
||||||
.stream_name = "ADSP-ADMAIF" #idx " Transmit",\
|
.stream_name = "ADSP-ADMAIF" #idx " Transmit",\
|
||||||
.channels_min = 1, \
|
.channels_min = 1, \
|
||||||
.channels_max = 2, \
|
.channels_max = 8, \
|
||||||
.rates = SNDRV_PCM_RATE_8000_48000, \
|
.rates = SNDRV_PCM_RATE_8000_48000, \
|
||||||
.formats = SNDRV_PCM_FMTBIT_S16_LE, \
|
.formats = SNDRV_PCM_FMTBIT_S16_LE, \
|
||||||
}, \
|
}, \
|
||||||
|
|||||||
Reference in New Issue
Block a user