summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorSumit Bhattacharya <sumitb@nvidia.com>2014-02-03 12:52:18 +0530
committerBharat Nihalani <bnihalani@nvidia.com>2014-03-12 01:25:58 -0700
commit6c45828760df11fbfa2d178f8359551b20b45268 (patch)
tree26ec2a87b56999a27dfe729411aa8ef9bc417079 /sound
parentb7b2435cc8713ea088f7defbd9f7facdb62f3404 (diff)
ASoC: Tegra: Add offload support for RT5640
Integrate offload platform driver interface with RT5640 codec which will add offload rendering support for dalmore. Add support for no_pcm mode in tegra pcm platform driver. Also add device specific stream name to I2s DAI so that it can be used as DPCM node. Bug 1399922 Change-Id: Icc01d7499d8e1585a76b93d6bc3337e7102194f6 Signed-off-by: Sumit Bhattacharya <sumitb@nvidia.com> Reviewed-on: http://git-master/r/362762 Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com> Tested-by: Bharat Nihalani <bnihalani@nvidia.com>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/tegra/Kconfig1
-rw-r--r--sound/soc/tegra/tegra30_i2s.c27
-rw-r--r--sound/soc/tegra/tegra_pcm.c28
-rw-r--r--sound/soc/tegra/tegra_rt5640.c105
4 files changed, 148 insertions, 13 deletions
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig
index 47504058c332..ac54daac9460 100644
--- a/sound/soc/tegra/Kconfig
+++ b/sound/soc/tegra/Kconfig
@@ -293,6 +293,7 @@ config SND_SOC_TEGRA_RT5640
select SND_SOC_RT5640
select SND_SOC_SPDIF
select SND_SOC_TEGRA30_DAM if !ARCH_TEGRA_2x_SOC
+ select SND_SOC_TEGRA30_AVP if !ARCH_TEGRA_2x_SOC
help
Say Y or M here if you want to add support for SoC audio on Tegra
boards using the ALC5640 codec. Currently, the supported boards
diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c
index d6705bb0abd3..413de6a31daa 100644
--- a/sound/soc/tegra/tegra30_i2s.c
+++ b/sound/soc/tegra/tegra30_i2s.c
@@ -2201,6 +2201,31 @@ static int tegra30_i2s_platform_probe(struct platform_device *pdev)
i2s->capture_i2s_cif = TEGRA30_AHUB_TXCIF_I2S0_TX0 + pdev->id;
}
+ switch (i2s->id) {
+ case 0:
+ i2s->dai.playback.stream_name = DRV_NAME ".0 Playback";
+ i2s->dai.capture.stream_name = DRV_NAME ".0 Capture";
+ break;
+ case 1:
+ i2s->dai.playback.stream_name = DRV_NAME ".1 Playback";
+ i2s->dai.capture.stream_name = DRV_NAME ".1 Capture";
+ break;
+ case 2:
+ i2s->dai.playback.stream_name = DRV_NAME ".2 Playback";
+ i2s->dai.capture.stream_name = DRV_NAME ".3 Capture";
+ break;
+ case 3:
+ i2s->dai.playback.stream_name = DRV_NAME ".3 Playback";
+ i2s->dai.capture.stream_name = DRV_NAME ".3 Capture";
+ break;
+ case 4:
+ i2s->dai.playback.stream_name = DRV_NAME ".4 Playback";
+ i2s->dai.capture.stream_name = DRV_NAME ".4 Capture";
+ break;
+ default:
+ break;
+ }
+
i2scont[i2s->id] = i2s;
i2s->clk_i2s = clk_get(&pdev->dev, "i2s");
@@ -2270,7 +2295,7 @@ static int tegra30_i2s_platform_probe(struct platform_device *pdev)
}
ret = snd_soc_register_component(&pdev->dev, &tegra30_i2s_component,
- &tegra30_i2s_dai_template, 1);
+ &i2s->dai, 1);
if (ret) {
dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c
index cf10d62f305a..d5c76b28dd98 100644
--- a/sound/soc/tegra/tegra_pcm.c
+++ b/sound/soc/tegra/tegra_pcm.c
@@ -2,7 +2,7 @@
* tegra_pcm.c - Tegra PCM driver
*
* Author: Stephen Warren <swarren@nvidia.com>
- * Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2010-2014, NVIDIA CORPORATION. All rights reserved.
*
* Based on code copyright/by:
*
@@ -70,6 +70,9 @@ static int tegra_pcm_open(struct snd_pcm_substream *substream)
struct tegra_runtime_data *prtd;
int ret;
+ if (rtd->dai_link->no_pcm)
+ return 0;
+
prtd = kzalloc(sizeof(struct tegra_runtime_data), GFP_KERNEL);
if (prtd == NULL)
return -ENOMEM;
@@ -100,6 +103,11 @@ static int tegra_pcm_open(struct snd_pcm_substream *substream)
static int tegra_pcm_close(struct snd_pcm_substream *substream)
{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+
+ if (rtd->dai_link->no_pcm)
+ return 0;
+
snd_dmaengine_pcm_close_release_chan(substream);
return 0;
}
@@ -109,11 +117,15 @@ int tegra_pcm_hw_params(struct snd_pcm_substream *substream,
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct device *dev = rtd->platform->dev;
- struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream);
+ struct dma_chan *chan;
struct tegra_pcm_dma_params *dmap;
struct dma_slave_config slave_config;
int ret;
+ if (rtd->dai_link->no_pcm)
+ return 0;
+
+ chan = snd_dmaengine_pcm_get_chan(substream);
dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
if (!dmap)
return 0;
@@ -148,6 +160,11 @@ int tegra_pcm_hw_params(struct snd_pcm_substream *substream,
int tegra_pcm_hw_free(struct snd_pcm_substream *substream)
{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+
+ if (rtd->dai_link->no_pcm)
+ return 0;
+
snd_pcm_set_runtime_buffer(substream, NULL);
return 0;
}
@@ -158,6 +175,9 @@ int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
struct tegra_pcm_dma_params * dmap;
struct tegra_runtime_data *prtd;
+ if (rtd->dai_link->no_pcm)
+ return 0;
+
dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
@@ -198,8 +218,12 @@ int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
static int tegra_pcm_mmap(struct snd_pcm_substream *substream,
struct vm_area_struct *vma)
{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_pcm_runtime *runtime = substream->runtime;
+ if (rtd->dai_link->no_pcm)
+ return 0;
+
return dma_mmap_writecombine(substream->pcm->card->dev, vma,
runtime->dma_area,
runtime->dma_addr,
diff --git a/sound/soc/tegra/tegra_rt5640.c b/sound/soc/tegra/tegra_rt5640.c
index ca2274fe37bd..057f9cedd3f4 100644
--- a/sound/soc/tegra/tegra_rt5640.c
+++ b/sound/soc/tegra/tegra_rt5640.c
@@ -2,7 +2,7 @@
* tegra_rt5640.c - Tegra machine ASoC driver for boards using ALC5640 codec.
*
* Author: Johnny Qiu <joqiu@nvidia.com>
- * Copyright (c) 2011-2013, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2011-2014, NVIDIA CORPORATION. All rights reserved.
*
* Based on code copyright/by:
*
@@ -60,10 +60,13 @@
#define DRV_NAME "tegra-snd-rt5640"
-#define DAI_LINK_HIFI 0
-#define DAI_LINK_SPDIF 1
-#define DAI_LINK_BTSCO 2
-#define NUM_DAI_LINKS 3
+#define DAI_LINK_HIFI 0
+#define DAI_LINK_SPDIF 1
+#define DAI_LINK_BTSCO 2
+#define DAI_LINK_PCM_OFFLOAD_FE 3
+#define DAI_LINK_COMPR_OFFLOAD_FE 4
+#define DAI_LINK_I2S_OFFLOAD_BE 5
+#define NUM_DAI_LINKS 6
const char *tegra_rt5640_i2s_dai_name[TEGRA30_NR_I2S_IFC] = {
"tegra30-i2s.0",
@@ -79,11 +82,6 @@ const char *tegra_rt5640_i2s_dai_name[TEGRA30_NR_I2S_IFC] = {
#define GPIO_EXT_MIC_EN BIT(3)
#define GPIO_HP_DET BIT(4)
-#define DAI_LINK_HIFI 0
-#define DAI_LINK_SPDIF 1
-#define DAI_LINK_BTSCO 2
-#define NUM_DAI_LINKS 3
-
struct tegra30_i2s *i2s_tfa = NULL;
struct snd_soc_codec *codec_rt;
@@ -342,6 +340,28 @@ static int tegra_hw_free(struct snd_pcm_substream *substream)
return 0;
}
+int tegra_offload_hw_params_be_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ if (!params_rate(params)) {
+ struct snd_interval *snd_rate = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_RATE);
+
+ snd_rate->min = snd_rate->max = 48000;
+ }
+
+ if (!params_channels(params)) {
+ struct snd_interval *snd_channels = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_CHANNELS);
+
+ snd_channels->min = snd_channels->max = 2;
+ }
+ snd_mask_set(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT),
+ ffs(SNDRV_PCM_FORMAT_S16_LE));
+
+ return 1;
+}
+
static struct snd_soc_ops tegra_rt5640_ops = {
.hw_params = tegra_rt5640_hw_params,
.hw_free = tegra_hw_free,
@@ -582,6 +602,12 @@ static const struct snd_soc_dapm_route tegra_rt5640_audio_map[] = {
{"DMIC L2", NULL, "Int Mic"},
{"DMIC R1", NULL, "Int Mic"},
{"DMIC R2", NULL, "Int Mic"},
+
+ /* AHUB BE connections */
+ {"tegra30-i2s.1 Playback", NULL, "I2S1_OUT"},
+
+ {"I2S1_OUT", NULL, "offload-pcm-playback"},
+ {"I2S1_OUT", NULL, "offload-compr-playback"},
};
static const struct snd_soc_dapm_route tegra_rt5640_no_micbias_audio_map[] = {
@@ -597,6 +623,12 @@ static const struct snd_soc_dapm_route tegra_rt5640_no_micbias_audio_map[] = {
{"DMIC L2", NULL, "Int Mic"},
{"DMIC R1", NULL, "Int Mic"},
{"DMIC R2", NULL, "Int Mic"},
+
+ /* AHUB BE connections */
+ {"tegra30-i2s.1 Playback", NULL, "I2S1_OUT"},
+
+ {"I2S1_OUT", NULL, "offload-pcm-playback"},
+ {"I2S1_OUT", NULL, "offload-compr-playback"},
};
static const struct snd_kcontrol_new tegra_rt5640_controls[] = {
@@ -725,6 +757,44 @@ static struct snd_soc_dai_link tegra_rt5640_dai[NUM_DAI_LINKS] = {
.codec_dai_name = "dit-hifi",
.ops = &tegra_rt5640_bt_sco_ops,
},
+ [DAI_LINK_PCM_OFFLOAD_FE] = {
+ .name = "offload-pcm",
+ .stream_name = "offload-pcm",
+
+ .platform_name = "tegra-offload",
+ .cpu_dai_name = "tegra-offload-pcm",
+
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+
+ .dynamic = 1,
+ },
+ [DAI_LINK_COMPR_OFFLOAD_FE] = {
+ .name = "offload-compr",
+ .stream_name = "offload-compr",
+
+ .platform_name = "tegra-offload",
+ .cpu_dai_name = "tegra-offload-compr",
+
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+
+ .dynamic = 1,
+ },
+ [DAI_LINK_I2S_OFFLOAD_BE] = {
+ .name = "offload-audio",
+ .stream_name = "offload-audio-pcm",
+ .codec_name = "rt5640.4-001c",
+ .platform_name = "tegra30-i2s.1",
+ .cpu_dai_name = "tegra30-i2s.1",
+ .codec_dai_name = "rt5640-aif1",
+ .ops = &tegra_rt5640_ops,
+
+ .no_pcm = 1,
+
+ .be_id = 0,
+ .be_hw_params_fixup = tegra_offload_hw_params_be_fixup,
+ },
};
static int tegra_rt5640_resume_pre(struct snd_soc_card *card)
@@ -864,6 +934,19 @@ static int tegra_rt5640_driver_probe(struct platform_device *pdev)
if (pdata->codec_dai_name)
card->dai_link->codec_dai_name = pdata->codec_dai_name;
+ if (pdata->codec_name) {
+ card->dai_link[DAI_LINK_HIFI].codec_name = pdata->codec_name;
+ card->dai_link[DAI_LINK_I2S_OFFLOAD_BE].codec_name =
+ pdata->codec_name;
+ }
+
+ if (pdata->codec_dai_name) {
+ card->dai_link[DAI_LINK_HIFI].codec_dai_name =
+ pdata->codec_dai_name;
+ card->dai_link[DAI_LINK_I2S_OFFLOAD_BE].codec_dai_name =
+ pdata->codec_dai_name;
+ }
+
machine = kzalloc(sizeof(struct tegra_rt5640), GFP_KERNEL);
if (!machine) {
dev_err(&pdev->dev, "Can't allocate tegra_rt5640 struct\n");
@@ -963,6 +1046,8 @@ static int tegra_rt5640_driver_probe(struct platform_device *pdev)
tegra_rt5640_i2s_dai_name[codec_id];
tegra_rt5640_dai[DAI_LINK_HIFI].platform_name =
tegra_rt5640_i2s_dai_name[codec_id];
+ tegra_rt5640_dai[DAI_LINK_I2S_OFFLOAD_BE].cpu_dai_name =
+ tegra_rt5640_i2s_dai_name[codec_id];
codec_id = pdata->i2s_param[BT_SCO].audio_port_id;
tegra_rt5640_dai[DAI_LINK_BTSCO].cpu_dai_name =