diff options
author | Sumit Bhattacharya <sumitb@nvidia.com> | 2014-02-03 12:52:18 +0530 |
---|---|---|
committer | Bharat Nihalani <bnihalani@nvidia.com> | 2014-03-12 01:25:58 -0700 |
commit | 6c45828760df11fbfa2d178f8359551b20b45268 (patch) | |
tree | 26ec2a87b56999a27dfe729411aa8ef9bc417079 /sound | |
parent | b7b2435cc8713ea088f7defbd9f7facdb62f3404 (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/Kconfig | 1 | ||||
-rw-r--r-- | sound/soc/tegra/tegra30_i2s.c | 27 | ||||
-rw-r--r-- | sound/soc/tegra/tegra_pcm.c | 28 | ||||
-rw-r--r-- | sound/soc/tegra/tegra_rt5640.c | 105 |
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 = |