summaryrefslogtreecommitdiff
path: root/sound/soc/tegra
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/tegra')
-rw-r--r--sound/soc/tegra/Makefile5
-rw-r--r--sound/soc/tegra/tegra30_i2s.c7
-rw-r--r--sound/soc/tegra/tegra_aic326x.c226
-rw-r--r--sound/soc/tegra/tegra_asoc_utils.c97
-rw-r--r--sound/soc/tegra/tegra_asoc_utils.h12
-rw-r--r--sound/soc/tegra/tegra_max98088.c193
-rw-r--r--sound/soc/tegra/tegra_max98095.c57
-rw-r--r--sound/soc/tegra/tegra_pcm.c5
-rw-r--r--sound/soc/tegra/tegra_pcm.h1
-rw-r--r--sound/soc/tegra/tegra_rt5640.c103
-rw-r--r--sound/soc/tegra/tegra_vcm.c (renamed from sound/soc/tegra/tegra_p1852.c)97
-rw-r--r--sound/soc/tegra/tegra_wm8753.c88
-rw-r--r--sound/soc/tegra/tegra_wm8903.c132
13 files changed, 716 insertions, 307 deletions
diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile
index d3d549a907a4..594c963cb8ea 100644
--- a/sound/soc/tegra/Makefile
+++ b/sound/soc/tegra/Makefile
@@ -37,7 +37,7 @@ snd-soc-tegra-max98088-objs := tegra_max98088.o
snd-soc-tegra-aic326x-objs := tegra_aic326x.o
snd-soc-tegra-rt5640-objs := tegra_rt5640.o
snd-soc-tegra-max98095-objs := tegra_max98095.o
-snd-soc-tegra-p1852-objs := tegra_p1852.o
+snd-soc-tegra-vcm-objs := tegra_vcm.o
obj-$(CONFIG_SND_SOC_TEGRA_WM8903) += snd-soc-tegra-wm8903.o
obj-$(CONFIG_SND_SOC_TEGRA_COLIBRI_T20) += snd-soc-tegra-colibri_t20.o
@@ -48,4 +48,5 @@ obj-$(CONFIG_SND_SOC_TEGRA_MAX98088) += snd-soc-tegra-max98088.o
obj-$(CONFIG_SND_SOC_TEGRA_TLV320AIC326X) += snd-soc-tegra-aic326x.o
obj-$(CONFIG_SND_SOC_TEGRA_RT5640) += snd-soc-tegra-rt5640.o
obj-$(CONFIG_SND_SOC_TEGRA_MAX98095) += snd-soc-tegra-max98095.o
-obj-$(CONFIG_SND_SOC_TEGRA_P1852) += snd-soc-tegra-p1852.o
+obj-$(CONFIG_SND_SOC_TEGRA_P1852) += snd-soc-tegra-vcm.o
+obj-$(CONFIG_SND_SOC_TEGRA_P852) += snd-soc-tegra-vcm.o
diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c
index 72e64470008a..03ddff5e8b95 100644
--- a/sound/soc/tegra/tegra30_i2s.c
+++ b/sound/soc/tegra/tegra30_i2s.c
@@ -557,6 +557,13 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream,
return ret;
}
+ ret = clk_set_parent(clk_get_parent(i2s->clk_audio_2x),
+ i2s->clk_i2s_sync);
+ if (ret) {
+ dev_err(dev, "Can't set parent of audio2x clock\n");
+ return ret;
+ }
+
ret = clk_set_rate(i2s->clk_audio_2x, i2sclock);
if (ret) {
dev_err(dev, "Can't set I2S sync clock rate\n");
diff --git a/sound/soc/tegra/tegra_aic326x.c b/sound/soc/tegra/tegra_aic326x.c
index 4cacb6758eb8..de4a1457a7ae 100644
--- a/sound/soc/tegra/tegra_aic326x.c
+++ b/sound/soc/tegra/tegra_aic326x.c
@@ -8,6 +8,7 @@
*
* (c) 2010, 2011 Nvidia Graphics Pvt. Ltd.
*
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
@@ -26,6 +27,7 @@
#include <asm/mach-types.h>
+#include <linux/clk.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
@@ -42,6 +44,7 @@
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
+#include <linux/mfd/tlv320aic3262-registers.h>
#include "../codecs/tlv320aic326x.h"
@@ -274,8 +277,9 @@ static int tegra_aic326x_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_card *card = codec->card;
struct tegra_aic326x *machine = snd_soc_card_get_drvdata(card);
- int srate, mclk, sample_size, daifmt;
- int err;
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
+ int srate, mclk, sample_size, i2s_daifmt;
+ int err, rate;
#ifndef CONFIG_ARCH_TEGRA_2x_SOC
struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(cpu_dai);
#endif
@@ -294,9 +298,30 @@ static int tegra_aic326x_hw_params(struct snd_pcm_substream *substream,
if (mclk < 0)
return mclk;
- daifmt = SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS;
+ i2s_daifmt = SND_SOC_DAIFMT_NB_NF;
+ i2s_daifmt |= pdata->i2s_param[HIFI_CODEC].is_i2s_master ?
+ SND_SOC_DAIFMT_CBS_CFS : SND_SOC_DAIFMT_CBM_CFM;
+
+ switch (pdata->i2s_param[HIFI_CODEC].i2s_mode) {
+ case TEGRA_DAIFMT_I2S :
+ i2s_daifmt |= SND_SOC_DAIFMT_I2S;
+ break;
+ case TEGRA_DAIFMT_DSP_A :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_A;
+ break;
+ case TEGRA_DAIFMT_DSP_B :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_B;
+ break;
+ case TEGRA_DAIFMT_LEFT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_LEFT_J;
+ break;
+ case TEGRA_DAIFMT_RIGHT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_RIGHT_J;
+ break;
+ default :
+ dev_err(card->dev, "Can't configure i2s format\n");
+ return -EINVAL;
+ }
err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
if (err < 0) {
@@ -310,25 +335,29 @@ static int tegra_aic326x_hw_params(struct snd_pcm_substream *substream,
tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
- err = snd_soc_dai_set_fmt(codec_dai, daifmt);
+ rate = clk_get_rate(machine->util_data.clk_cdev1);
+
+ err = snd_soc_dai_set_fmt(codec_dai, i2s_daifmt);
if (err < 0) {
dev_err(card->dev, "codec_dai fmt not set\n");
return err;
}
- err = snd_soc_dai_set_fmt(cpu_dai, daifmt);
+ err = snd_soc_dai_set_fmt(cpu_dai, i2s_daifmt);
if (err < 0) {
dev_err(card->dev, "cpu_dai fmt not set\n");
return err;
}
- err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
- SND_SOC_CLOCK_IN);
+ err = snd_soc_dai_set_sysclk(codec_dai, 0, rate, SND_SOC_CLOCK_IN);
if (err < 0) {
dev_err(card->dev, "codec_dai clock not set\n");
return err;
}
+ err = snd_soc_dai_set_pll(codec_dai, 0, AIC3262_PLL_CLKIN_MCLK1 , rate,
+ params_rate(params));
+
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
err = tegra20_das_connect_dac_to_dap(TEGRA20_DAS_DAP_SEL_DAC1,
TEGRA20_DAS_DAP_ID_1);
@@ -390,7 +419,8 @@ static int tegra_aic326x_bt_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_card *card = rtd->card;
struct tegra_aic326x *machine = snd_soc_card_get_drvdata(card);
- int err, srate, mclk, min_mclk, sample_size;
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
+ int err, srate, mclk, min_mclk, sample_size, i2s_daifmt;
#ifndef CONFIG_ARCH_TEGRA_2x_SOC
struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(rtd->cpu_dai);
#endif
@@ -423,10 +453,32 @@ static int tegra_aic326x_bt_hw_params(struct snd_pcm_substream *substream,
tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
- err = snd_soc_dai_set_fmt(rtd->cpu_dai,
- SND_SOC_DAIFMT_DSP_A |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS);
+ i2s_daifmt = SND_SOC_DAIFMT_NB_NF;
+ i2s_daifmt |= pdata->i2s_param[BT_SCO].is_i2s_master ?
+ SND_SOC_DAIFMT_CBS_CFS : SND_SOC_DAIFMT_CBM_CFM;
+
+ switch (pdata->i2s_param[BT_SCO].i2s_mode) {
+ case TEGRA_DAIFMT_I2S :
+ i2s_daifmt |= SND_SOC_DAIFMT_I2S;
+ break;
+ case TEGRA_DAIFMT_DSP_A :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_A;
+ break;
+ case TEGRA_DAIFMT_DSP_B :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_B;
+ break;
+ case TEGRA_DAIFMT_LEFT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_LEFT_J;
+ break;
+ case TEGRA_DAIFMT_RIGHT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_RIGHT_J;
+ break;
+ default :
+ dev_err(card->dev, "Can't configure i2s format\n");
+ return -EINVAL;
+ }
+
+ err = snd_soc_dai_set_fmt(rtd->cpu_dai, i2s_daifmt);
if (err < 0) {
dev_err(rtd->codec->card->dev, "cpu_dai fmt not set\n");
@@ -624,7 +676,8 @@ static int tegra_aic326x_voice_call_hw_params(
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_card *card = codec->card;
struct tegra_aic326x *machine = snd_soc_card_get_drvdata(card);
- int srate, mclk;
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
+ int srate, mclk, rate, i2s_daifmt;
int err, pcmdiv, vxclkdiv;;
srate = params_rate(params);
@@ -632,6 +685,36 @@ static int tegra_aic326x_voice_call_hw_params(
if (mclk < 0)
return mclk;
+ i2s_daifmt = SND_SOC_DAIFMT_NB_NF;
+ i2s_daifmt |= pdata->i2s_param[HIFI_CODEC].is_i2s_master ?
+ SND_SOC_DAIFMT_CBS_CFS : SND_SOC_DAIFMT_CBM_CFM;
+
+ if (machine_is_tegra_enterprise()) {
+ switch (pdata->i2s_param[HIFI_CODEC].i2s_mode) {
+ case TEGRA_DAIFMT_I2S :
+ i2s_daifmt |= SND_SOC_DAIFMT_I2S;
+ break;
+ case TEGRA_DAIFMT_DSP_A :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_A;
+ break;
+ case TEGRA_DAIFMT_DSP_B :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_B;
+ break;
+ case TEGRA_DAIFMT_LEFT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_LEFT_J;
+ break;
+ case TEGRA_DAIFMT_RIGHT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_RIGHT_J;
+ break;
+ default :
+ dev_err(card->dev,
+ "Can't configure i2s format\n");
+ return -EINVAL;
+ }
+ } else {
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_B;
+ }
+
err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
if (err < 0) {
if (!(machine->util_data.set_mclk % mclk))
@@ -644,31 +727,29 @@ static int tegra_aic326x_voice_call_hw_params(
tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
- if(machine_is_tegra_enterprise()) {
- err = snd_soc_dai_set_fmt(codec_dai,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS);
- } else {
- err = snd_soc_dai_set_fmt(codec_dai,
- SND_SOC_DAIFMT_DSP_B |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS);
- }
+ rate = clk_get_rate(machine->util_data.clk_cdev1);
+ err = snd_soc_dai_set_fmt(codec_dai, i2s_daifmt);
if (err < 0) {
dev_err(card->dev, "codec_dai fmt not set\n");
return err;
}
- err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
- SND_SOC_CLOCK_IN);
+ err = snd_soc_dai_set_sysclk(codec_dai, 0, rate, SND_SOC_CLOCK_IN);
if (err < 0) {
dev_err(card->dev, "codec_dai clock not set\n");
return err;
}
- if(!machine_is_tegra_enterprise()) {
+ err = snd_soc_dai_set_pll(codec_dai, 0, AIC3262_PLL_CLKIN_MCLK1 , rate,
+ params_rate(params));
+
+ if (err < 0) {
+ dev_err(card->dev, "codec_dai PLL clock not set\n");
+ return err;
+ }
+
+ if (!machine_is_tegra_enterprise()) {
if (params_rate(params) == 8000) {
/* Change these Settings for 8KHz*/
pcmdiv = 1;
@@ -691,14 +772,6 @@ static int tegra_aic326x_voice_call_hw_params(
/* codec configuration */
machine->codec_info[HIFI_CODEC].rate = params_rate(params);
machine->codec_info[HIFI_CODEC].channels = params_channels(params);
- machine->codec_info[HIFI_CODEC].bitsize = 16;
- machine->codec_info[HIFI_CODEC].is_i2smaster = 1;
- machine->codec_info[HIFI_CODEC].is_format_dsp = 0;
-
- /* baseband configuration */
- machine->codec_info[BASEBAND].bitsize = 16;
- machine->codec_info[BASEBAND].is_i2smaster = 1;
- machine->codec_info[BASEBAND].is_format_dsp = 1;
#endif
machine->is_device_bt = 0;
@@ -754,14 +827,6 @@ static int tegra_aic326x_bt_voice_call_hw_params(
/* codec configuration */
machine->codec_info[BT_SCO].rate = params_rate(params);
machine->codec_info[BT_SCO].channels = params_channels(params);
- machine->codec_info[BT_SCO].bitsize = 16;
- machine->codec_info[BT_SCO].is_i2smaster = 1;
- machine->codec_info[BT_SCO].is_format_dsp = 1;
-
- /* baseband configuration */
- machine->codec_info[BASEBAND].bitsize = 16;
- machine->codec_info[BASEBAND].is_i2smaster = 1;
- machine->codec_info[BASEBAND].is_format_dsp = 1;
#endif
machine->is_device_bt = 1;
@@ -836,7 +901,7 @@ enum headset_state {
static int aic326x_headset_switch_notify(struct notifier_block *self,
unsigned long action, void *dev)
{
- int state = 0;
+ int state = BIT_NO_HEADSET;
switch (action) {
case SND_JACK_HEADPHONE:
@@ -908,6 +973,7 @@ static const struct snd_soc_dapm_widget tegra_aic326x_dapm_widgets[] = {
SND_SOC_DAPM_INPUT("Ext Mic"),
SND_SOC_DAPM_LINE("Linein", NULL),
SND_SOC_DAPM_MIC("Int Mic", NULL),
+ SND_SOC_DAPM_MIC("DMIC", NULL),
};
static const struct snd_soc_dapm_route aic326x_audio_map[] = {
@@ -922,10 +988,15 @@ static const struct snd_soc_dapm_route aic326x_audio_map[] = {
{"IN2L", NULL, "Mic Bias Int"},
{"Mic Bias Int" ,NULL, "Int Mic"},
{"IN2R", NULL, "Mic Bias Int"},
- {"Mic Bias Ext" ,NULL, "Mic Jack"},
- {"CM1L" ,NULL, "Mic Jack"},
{"IN1L", NULL, "Mic Bias Ext"},
- {"IN1L", NULL, "CM1L"},
+ {"Mic Bias Ext" ,NULL, "Mic Jack"},
+ /* Connect LDMIC and RDMIC to DMIC widget*/
+ {"Left DMIC", NULL, "Mic Bias Int"},
+ {"Right DMIC", NULL, "Mic Bias Int"},
+ {"Mic Bias Int", NULL, "Int Mic"},
+/* {"CM1L" ,NULL, "Mic Jack"}, */
+/* {"IN1L", NULL, "Mic Bias Ext"}, */
+/* {"IN1L", NULL, "CM1L"}, */
};
static const struct snd_kcontrol_new tegra_aic326x_controls[] = {
@@ -1052,7 +1123,8 @@ static int tegra_aic326x_init(struct snd_soc_pcm_runtime *rtd)
tegra_aic326x_hp_jack_pins);
#endif
- aic326x_headset_detect(codec, &tegra_aic326x_hp_jack,
+ /* update jack status during boot */
+ aic3262_hs_jack_detect(codec, &tegra_aic326x_hp_jack,
SND_JACK_HEADSET);
/* Add call mode switch control */
@@ -1066,9 +1138,9 @@ static int tegra_aic326x_init(struct snd_soc_pcm_runtime *rtd)
if (ret < 0)
return ret;
- snd_soc_dapm_force_enable_pin(dapm, "MICBIAS_EXT ON");
- snd_soc_dapm_force_enable_pin(dapm,"MICBIAS_INT ON");
- snd_soc_dapm_sync(dapm);
+/* snd_soc_dapm_force_enable_pin(dapm, "Mic Bias Ext");
+ snd_soc_dapm_force_enable_pin(dapm,"Mic Bias Int");
+ snd_soc_dapm_sync(dapm); */
return 0;
}
@@ -1077,14 +1149,14 @@ static struct snd_soc_dai_link tegra_aic326x_dai[] = {
[DAI_LINK_HIFI] = {
.name = "AIC3262",
.stream_name = "AIC3262 PCM HIFI",
- .codec_name = "aic3262-codec.4-0018",
+ .codec_name = "tlv320aic3262-codec",
.platform_name = "tegra-pcm-audio",
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
.cpu_dai_name = "tegra20-i2s.0",
#else
.cpu_dai_name = "tegra30-i2s.0",
#endif
- .codec_dai_name = "aic3262-asi1",
+ .codec_dai_name = "aic326x-asi1",
.init = tegra_aic326x_init,
.ops = &tegra_aic326x_hifi_ops,
},
@@ -1118,10 +1190,10 @@ static struct snd_soc_dai_link tegra_aic326x_dai[] = {
[DAI_LINK_VOICE_CALL] = {
.name = "VOICE CALL",
.stream_name = "VOICE CALL PCM",
- .codec_name = "aic3262-codec.4-0018",
+ .codec_name = "tlv320aic3262-codec",
.platform_name = "tegra-pcm-audio",
.cpu_dai_name = "dit-hifi",
- .codec_dai_name = "aic3262-asi2",
+ .codec_dai_name = "aic326x-asi2",
.ops = &tegra_aic326x_voice_call_ops,
},
[DAI_LINK_BT_VOICE_CALL] = {
@@ -1183,11 +1255,23 @@ static __devinit int tegra_aic326x_driver_probe(struct platform_device *pdev)
#endif
#ifndef CONFIG_ARCH_TEGRA_2x_SOC
- for (i = 0; i < NUM_I2S_DEVICES ; i++)
- machine->codec_info[i].i2s_id = pdata->audio_port_id[i];
-
- machine->codec_info[BASEBAND].rate = pdata->baseband_param.rate;
- machine->codec_info[BASEBAND].channels = pdata->baseband_param.channels;
+ for (i = 0; i < NUM_I2S_DEVICES ; i++) {
+ machine->codec_info[i].i2s_id =
+ pdata->i2s_param[i].audio_port_id;
+ machine->codec_info[i].bitsize =
+ pdata->i2s_param[i].sample_size;
+ machine->codec_info[i].is_i2smaster =
+ pdata->i2s_param[i].is_i2s_master;
+ machine->codec_info[i].rate =
+ pdata->i2s_param[i].rate;
+ machine->codec_info[i].channels =
+ pdata->i2s_param[i].channels;
+ if ((pdata->i2s_param[i].i2s_mode == TEGRA_DAIFMT_DSP_A) ||
+ (pdata->i2s_param[i].i2s_mode == TEGRA_DAIFMT_DSP_B))
+ machine->codec_info[i].is_format_dsp = 1;
+ else
+ machine->codec_info[i].is_format_dsp = 0;
+ }
tegra_aic326x_dai[DAI_LINK_HIFI].cpu_dai_name =
tegra_i2s_dai_name[machine->codec_info[HIFI_CODEC].i2s_id];
@@ -1196,10 +1280,10 @@ static __devinit int tegra_aic326x_driver_probe(struct platform_device *pdev)
tegra_i2s_dai_name[machine->codec_info[BT_SCO].i2s_id];
#endif
- if(machine_is_tegra_enterprise()) {
- tegra_aic326x_dai[DAI_LINK_HIFI].codec_name = "aic3262-codec.0-0018";
- tegra_aic326x_dai[DAI_LINK_VOICE_CALL].codec_name = "aic3262-codec.0-0018";
- tegra_aic326x_dai[DAI_LINK_VOICE_CALL].codec_dai_name = "aic3262-asi1";
+ if (machine_is_tegra_enterprise()) {
+ tegra_aic326x_dai[DAI_LINK_HIFI].codec_name = "tlv320aic3262-codec";
+ tegra_aic326x_dai[DAI_LINK_VOICE_CALL].codec_name = "tlv320aic3262-codec";
+ tegra_aic326x_dai[DAI_LINK_VOICE_CALL].codec_dai_name = "aic326x-asi1";
}
ret = snd_soc_register_card(card);
@@ -1214,6 +1298,16 @@ static __devinit int tegra_aic326x_driver_probe(struct platform_device *pdev)
goto err_unregister_card;
}
+#ifndef CONFIG_ARCH_TEGRA_2x_SOC
+ ret = tegra_asoc_utils_set_parent(&machine->util_data,
+ pdata->i2s_param[HIFI_CODEC].is_i2s_master);
+ if (ret) {
+ dev_err(&pdev->dev, "tegra_asoc_utils_set_parent failed (%d)\n",
+ ret);
+ goto err_unregister_card;
+ }
+#endif
+
return 0;
err_unregister_card:
diff --git a/sound/soc/tegra/tegra_asoc_utils.c b/sound/soc/tegra/tegra_asoc_utils.c
index 6ab5b2d46a1f..99ba90d9fc7b 100644
--- a/sound/soc/tegra/tegra_asoc_utils.c
+++ b/sound/soc/tegra/tegra_asoc_utils.c
@@ -2,8 +2,7 @@
* tegra_asoc_utils.c - Harmony machine ASoC driver
*
* Author: Stephen Warren <swarren@nvidia.com>
- * Copyright (C) 2010 - NVIDIA, Inc.
- *
+ * Copyright (c) 2010-12, NVIDIA CORPORATION. All rights reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
@@ -87,8 +86,11 @@ static int tegra_set_avp_device(struct snd_kcontrol *kcontrol,
prtd = substream->runtime->private_data;
if (prtd->running)
return -EBUSY;
- if (prtd)
+ if (prtd) {
prtd->disable_intr = true;
+ if (data->avp_dma_addr || prtd->avp_dma_addr)
+ prtd->avp_dma_addr = data->avp_dma_addr;
+ }
}
}
data->avp_device_id = id;
@@ -122,6 +124,33 @@ static int tegra_get_dma_ch_id(struct snd_kcontrol *kcontrol,
return 0;
}
+static int tegra_set_dma_addr(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct tegra_asoc_utils_data *data = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = data->card;
+ struct snd_soc_pcm_runtime *rtd;
+ struct snd_pcm_substream *substream;
+ struct tegra_runtime_data *prtd;
+
+ if (data->avp_device_id < 0)
+ return 0;
+
+ data->avp_dma_addr = ucontrol->value.integer.value[0];
+
+ rtd = &card->rtd[data->avp_device_id];
+ substream = rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+ if (!substream || !substream->runtime)
+ return 0;
+
+ prtd = substream->runtime->private_data;
+ if (!prtd)
+ return 0;
+
+ prtd->avp_dma_addr = data->avp_dma_addr;
+ return 1;
+}
+
static int tegra_get_dma_addr(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -129,6 +158,7 @@ static int tegra_get_dma_addr(struct snd_kcontrol *kcontrol,
struct snd_soc_card *card = data->card;
struct snd_soc_pcm_runtime *rtd;
struct snd_pcm_substream *substream;
+ struct tegra_runtime_data *prtd;
ucontrol->value.integer.value[0] = 0;
if (data->avp_device_id < 0)
@@ -139,7 +169,14 @@ static int tegra_get_dma_addr(struct snd_kcontrol *kcontrol,
if (!substream || !substream->runtime)
return 0;
- ucontrol->value.integer.value[0] = substream->runtime->dma_addr;
+ prtd = substream->runtime->private_data;
+ if (!prtd || !prtd->dma_chan)
+ return 0;
+
+ ucontrol->value.integer.value[0] = prtd->avp_dma_addr ?
+ prtd->avp_dma_addr :
+ substream->runtime->dma_addr;
+
return 0;
}
@@ -149,7 +186,7 @@ struct snd_kcontrol_new tegra_avp_controls[] = {
SOC_SINGLE_EXT("AVP DMA channel id", 0, 0, TEGRA_DMA_MAX_CHANNELS, \
0, tegra_get_dma_ch_id, NULL),
SOC_SINGLE_EXT("AVP DMA address", 0, 0, 0xFFFFFFFF, \
- 0, tegra_get_dma_addr, NULL),
+ 0, tegra_get_dma_addr, tegra_set_dma_addr),
};
int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
@@ -342,28 +379,6 @@ int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data,
}
#endif
-#if !defined(CONFIG_ARCH_TEGRA_2x_SOC)
-#if TEGRA30_I2S_MASTER_PLAYBACK
- ret = clk_set_parent(data->clk_cdev1, data->clk_pll_a_out0);
- if (ret) {
- dev_err(data->dev, "Can't set clk cdev1/extern1 parent");
- goto err_put_out1;
- }
-#else
- rate = clk_get_rate(data->clk_m);
-
- if(rate == 26000000)
- clk_set_rate(data->clk_cdev1, 13000000);
-
- ret = clk_set_parent(data->clk_cdev1, data->clk_m);
- if (ret) {
- dev_err(data->dev, "Can't set clk cdev1/extern1 parent");
- goto err_put_out1;
- }
-#endif
-
-#endif
-
ret = clk_enable(data->clk_cdev1);
if (ret) {
dev_err(data->dev, "Can't enable clk cdev1/extern1");
@@ -402,6 +417,34 @@ err:
}
EXPORT_SYMBOL_GPL(tegra_asoc_utils_init);
+#if !defined(CONFIG_ARCH_TEGRA_2x_SOC)
+int tegra_asoc_utils_set_parent (struct tegra_asoc_utils_data *data,
+ int is_i2s_master)
+{
+ int ret = -ENODEV;
+
+ if (is_i2s_master) {
+ ret = clk_set_parent(data->clk_cdev1, data->clk_pll_a_out0);
+ if (ret) {
+ dev_err(data->dev, "Can't set clk cdev1/extern1 parent");
+ return ret;
+ }
+ } else {
+ if(clk_get_rate(data->clk_m) == 26000000)
+ clk_set_rate(data->clk_cdev1, 13000000);
+
+ ret = clk_set_parent(data->clk_cdev1, data->clk_m);
+ if (ret) {
+ dev_err(data->dev, "Can't set clk cdev1/extern1 parent");
+ return ret;
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tegra_asoc_utils_set_parent);
+#endif
+
void tegra_asoc_utils_fini(struct tegra_asoc_utils_data *data)
{
if (!IS_ERR(data->clk_out1))
diff --git a/sound/soc/tegra/tegra_asoc_utils.h b/sound/soc/tegra/tegra_asoc_utils.h
index 0423f02b76cc..cd137967fcb0 100644
--- a/sound/soc/tegra/tegra_asoc_utils.h
+++ b/sound/soc/tegra/tegra_asoc_utils.h
@@ -2,7 +2,7 @@
* tegra_asoc_utils.h - Definitions for Tegra DAS driver
*
* Author: Stephen Warren <swarren@nvidia.com>
- * Copyright (C) 2010 - NVIDIA, Inc.
+ * Copyright (c) 2010-12, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -24,7 +24,6 @@
#define __TEGRA_ASOC_UTILS_H_
-#define TEGRA30_I2S_MASTER_PLAYBACK 1
#define TEGRA_ALSA_MAX_DEVICES 6
#define TEGRA_DMA_MAX_CHANNELS 32
@@ -44,14 +43,17 @@ struct tegra_asoc_utils_data {
int set_mclk;
int lock_count;
int avp_device_id;
+ unsigned int avp_dma_addr;
};
int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
- int mclk);
+ int mclk);
void tegra_asoc_utils_lock_clk_rate(struct tegra_asoc_utils_data *data,
- int lock);
+ int lock);
int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data,
- struct device *dev, struct snd_soc_card *card);
+ struct device *dev, struct snd_soc_card *card);
+int tegra_asoc_utils_set_parent(struct tegra_asoc_utils_data *data,
+ int is_i2s_master);
void tegra_asoc_utils_fini(struct tegra_asoc_utils_data *data);
int tegra_asoc_utils_clk_enable(struct tegra_asoc_utils_data *data);
int tegra_asoc_utils_clk_disable(struct tegra_asoc_utils_data *data);
diff --git a/sound/soc/tegra/tegra_max98088.c b/sound/soc/tegra/tegra_max98088.c
index 82c2b930a39e..88098fcd99d9 100644
--- a/sound/soc/tegra/tegra_max98088.c
+++ b/sound/soc/tegra/tegra_max98088.c
@@ -12,6 +12,7 @@
* Author: Graeme Gregory
* graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
*
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
@@ -213,14 +214,16 @@ static int tegra_max98088_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_card *card = codec->card;
struct tegra_max98088 *machine = snd_soc_card_get_drvdata(card);
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
#ifndef CONFIG_ARCH_TEGRA_2x_SOC
struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(cpu_dai);
#endif
- int srate, mclk, sample_size, i2s_daifmt;
+ int srate, mclk, sample_size, i2s_daifmt, i2s_master;
int err;
- struct clk *clk;
int rate;
+ i2s_master = pdata->i2s_param[HIFI_CODEC].is_i2s_master;
+
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
sample_size = 16;
@@ -251,32 +254,31 @@ static int tegra_max98088_hw_params(struct snd_pcm_substream *substream,
break;
}
+ i2s_daifmt = SND_SOC_DAIFMT_NB_NF;
+ i2s_daifmt |= i2s_master ? SND_SOC_DAIFMT_CBS_CFS :
+ SND_SOC_DAIFMT_CBM_CFM;
-#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
- clk = clk_get_sys(NULL, "cdev1");
-#else
- clk = clk_get_sys("extern1", NULL);
-#endif
- if (IS_ERR(clk)) {
- dev_err(card->dev, "Can't retrieve clk cdev1\n");
- err = PTR_ERR(clk);
- return err;
+ switch (pdata->i2s_param[HIFI_CODEC].i2s_mode) {
+ case TEGRA_DAIFMT_I2S :
+ i2s_daifmt |= SND_SOC_DAIFMT_I2S;
+ break;
+ case TEGRA_DAIFMT_DSP_A :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_A;
+ break;
+ case TEGRA_DAIFMT_DSP_B :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_B;
+ break;
+ case TEGRA_DAIFMT_LEFT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_LEFT_J;
+ break;
+ case TEGRA_DAIFMT_RIGHT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_RIGHT_J;
+ break;
+ default :
+ dev_err(card->dev, "Can't configure i2s format\n");
+ return -EINVAL;
}
- rate = clk_get_rate(clk);
- printk("extern1 rate=%d\n",rate);
-
-#if TEGRA30_I2S_MASTER_PLAYBACK
- i2s_daifmt = SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS;
-#else
- i2s_daifmt = SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBM_CFM;
- mclk = rate;
-#endif
-
err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
if (err < 0) {
if (!(machine->util_data.set_mclk % mclk))
@@ -289,7 +291,9 @@ static int tegra_max98088_hw_params(struct snd_pcm_substream *substream,
tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
- err = snd_soc_dai_set_fmt(codec_dai,i2s_daifmt);
+ rate = clk_get_rate(machine->util_data.clk_cdev1);
+
+ err = snd_soc_dai_set_fmt(codec_dai, i2s_daifmt);
if (err < 0) {
dev_err(card->dev, "codec_dai fmt not set\n");
return err;
@@ -301,8 +305,17 @@ static int tegra_max98088_hw_params(struct snd_pcm_substream *substream,
return err;
}
- err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
- SND_SOC_CLOCK_IN);
+ err = snd_soc_dai_set_sysclk(codec_dai, 0, rate, SND_SOC_CLOCK_IN);
+
+ /* ULP specific use case for 44.1kHz stream. */
+ if ((!i2s_master) && (srate == 44100) &&
+ machine_is_tegra_enterprise()) {
+ clk_set_rate(machine->util_data.clk_cdev1, (256 * srate));
+ rate = clk_get_rate(machine->util_data.clk_cdev1);
+ err = snd_soc_dai_set_sysclk(codec_dai, 0, rate,
+ SND_SOC_CLOCK_IN);
+ }
+
if (err < 0) {
dev_err(card->dev, "codec_dai clock not set\n");
return err;
@@ -371,7 +384,9 @@ static int tegra_bt_hw_params(struct snd_pcm_substream *substream,
#endif
struct snd_soc_card *card = rtd->card;
struct tegra_max98088 *machine = snd_soc_card_get_drvdata(card);
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
int err, srate, mclk, min_mclk, sample_size;
+ int i2s_daifmt;
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
@@ -414,10 +429,32 @@ static int tegra_bt_hw_params(struct snd_pcm_substream *substream,
tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
- err = snd_soc_dai_set_fmt(rtd->cpu_dai,
- SND_SOC_DAIFMT_DSP_A |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS);
+ i2s_daifmt = SND_SOC_DAIFMT_NB_NF;
+ i2s_daifmt |= pdata->i2s_param[BT_SCO].is_i2s_master ?
+ SND_SOC_DAIFMT_CBS_CFS : SND_SOC_DAIFMT_CBM_CFM;
+
+ switch (pdata->i2s_param[BT_SCO].i2s_mode) {
+ case TEGRA_DAIFMT_I2S :
+ i2s_daifmt |= SND_SOC_DAIFMT_I2S;
+ break;
+ case TEGRA_DAIFMT_DSP_A :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_A;
+ break;
+ case TEGRA_DAIFMT_DSP_B :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_B;
+ break;
+ case TEGRA_DAIFMT_LEFT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_LEFT_J;
+ break;
+ case TEGRA_DAIFMT_RIGHT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_RIGHT_J;
+ break;
+ default :
+ dev_err(card->dev, "Can't configure i2s format\n");
+ return -EINVAL;
+ }
+
+ err = snd_soc_dai_set_fmt(rtd->cpu_dai, i2s_daifmt);
if (err < 0) {
dev_err(rtd->codec->card->dev, "cpu_dai fmt not set\n");
return err;
@@ -598,8 +635,9 @@ static int tegra_voice_call_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_card *card = codec->card;
struct tegra_max98088 *machine = snd_soc_card_get_drvdata(card);
- int srate, mclk;
- int err;
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
+ int srate, mclk, i2s_daifmt;
+ int err, rate;
srate = params_rate(params);
switch (srate) {
@@ -623,6 +661,31 @@ static int tegra_voice_call_hw_params(struct snd_pcm_substream *substream,
break;
}
+ i2s_daifmt = SND_SOC_DAIFMT_NB_NF;
+ i2s_daifmt |= pdata->i2s_param[HIFI_CODEC].is_i2s_master ?
+ SND_SOC_DAIFMT_CBS_CFS : SND_SOC_DAIFMT_CBM_CFM;
+
+ switch (pdata->i2s_param[HIFI_CODEC].i2s_mode) {
+ case TEGRA_DAIFMT_I2S :
+ i2s_daifmt |= SND_SOC_DAIFMT_I2S;
+ break;
+ case TEGRA_DAIFMT_DSP_A :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_A;
+ break;
+ case TEGRA_DAIFMT_DSP_B :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_B;
+ break;
+ case TEGRA_DAIFMT_LEFT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_LEFT_J;
+ break;
+ case TEGRA_DAIFMT_RIGHT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_RIGHT_J;
+ break;
+ default :
+ dev_err(card->dev, "Can't configure i2s format\n");
+ return -EINVAL;
+ }
+
err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
if (err < 0) {
if (!(machine->util_data.set_mclk % mclk))
@@ -635,17 +698,15 @@ static int tegra_voice_call_hw_params(struct snd_pcm_substream *substream,
tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
- err = snd_soc_dai_set_fmt(codec_dai,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS);
+ rate = clk_get_rate(machine->util_data.clk_cdev1);
+
+ err = snd_soc_dai_set_fmt(codec_dai, i2s_daifmt);
if (err < 0) {
dev_err(card->dev, "codec_dai fmt not set\n");
return err;
}
- err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
- SND_SOC_CLOCK_IN);
+ err = snd_soc_dai_set_sysclk(codec_dai, 0, rate, SND_SOC_CLOCK_IN);
if (err < 0) {
dev_err(card->dev, "codec_dai clock not set\n");
return err;
@@ -655,14 +716,6 @@ static int tegra_voice_call_hw_params(struct snd_pcm_substream *substream,
/* codec configuration */
machine->codec_info[HIFI_CODEC].rate = params_rate(params);
machine->codec_info[HIFI_CODEC].channels = params_channels(params);
- machine->codec_info[HIFI_CODEC].bitsize = 16;
- machine->codec_info[HIFI_CODEC].is_i2smaster = 1;
- machine->codec_info[HIFI_CODEC].is_format_dsp = 0;
-
- /* baseband configuration */
- machine->codec_info[BASEBAND].bitsize = 16;
- machine->codec_info[BASEBAND].is_i2smaster = 1;
- machine->codec_info[BASEBAND].is_format_dsp = 1;
#endif
machine->is_device_bt = 0;
@@ -729,14 +782,6 @@ static int tegra_bt_voice_call_hw_params(struct snd_pcm_substream *substream,
/* codec configuration */
machine->codec_info[BT_SCO].rate = params_rate(params);
machine->codec_info[BT_SCO].channels = params_channels(params);
- machine->codec_info[BT_SCO].bitsize = 16;
- machine->codec_info[BT_SCO].is_i2smaster = 1;
- machine->codec_info[BT_SCO].is_format_dsp = 1;
-
- /* baseband configuration */
- machine->codec_info[BASEBAND].bitsize = 16;
- machine->codec_info[BASEBAND].is_i2smaster = 1;
- machine->codec_info[BASEBAND].is_format_dsp = 1;
#endif
machine->is_device_bt = 1;
@@ -1148,16 +1193,22 @@ static __devinit int tegra_max98088_driver_probe(struct platform_device *pdev)
#endif
#ifndef CONFIG_ARCH_TEGRA_2x_SOC
- for (i = 0; i < NUM_I2S_DEVICES ; i++)
- machine->codec_info[i].i2s_id = pdata->audio_port_id[i];
-
- machine->codec_info[BASEBAND].rate = pdata->baseband_param.rate;
- machine->codec_info[BASEBAND].channels = pdata->baseband_param.channels;
- machine->codec_info[BASEBAND].is_format_dsp = 0;
-
- if ((pdata->baseband_param.bit_format == TEGRA_DAIFMT_DSP_A) ||
- (pdata->baseband_param.bit_format == TEGRA_DAIFMT_DSP_B)) {
- machine->codec_info[BASEBAND].is_format_dsp = 1;
+ for (i = 0; i < NUM_I2S_DEVICES ; i++) {
+ machine->codec_info[i].i2s_id =
+ pdata->i2s_param[i].audio_port_id;
+ machine->codec_info[i].bitsize =
+ pdata->i2s_param[i].sample_size;
+ machine->codec_info[i].is_i2smaster =
+ pdata->i2s_param[i].is_i2s_master;
+ machine->codec_info[i].rate =
+ pdata->i2s_param[i].rate;
+ machine->codec_info[i].channels =
+ pdata->i2s_param[i].channels;
+ if ((pdata->i2s_param[i].i2s_mode == TEGRA_DAIFMT_DSP_A) ||
+ (pdata->i2s_param[i].i2s_mode == TEGRA_DAIFMT_DSP_B))
+ machine->codec_info[i].is_format_dsp = 1;
+ else
+ machine->codec_info[i].is_format_dsp = 0;
}
tegra_max98088_dai[DAI_LINK_HIFI].cpu_dai_name =
@@ -1180,6 +1231,16 @@ static __devinit int tegra_max98088_driver_probe(struct platform_device *pdev)
goto err_unregister_card;
}
+#ifndef CONFIG_ARCH_TEGRA_2x_SOC
+ ret = tegra_asoc_utils_set_parent(&machine->util_data,
+ pdata->i2s_param[HIFI_CODEC].is_i2s_master);
+ if (ret) {
+ dev_err(&pdev->dev, "tegra_asoc_utils_set_parent failed (%d)\n",
+ ret);
+ goto err_unregister_card;
+ }
+#endif
+
return 0;
err_unregister_card:
diff --git a/sound/soc/tegra/tegra_max98095.c b/sound/soc/tegra/tegra_max98095.c
index d065b78164ac..1d03980f276f 100644
--- a/sound/soc/tegra/tegra_max98095.c
+++ b/sound/soc/tegra/tegra_max98095.c
@@ -8,7 +8,7 @@
*
* Based on code copyright/by:
*
- * (c) 2010, 2011, 2012 Nvidia Graphics Pvt. Ltd.
+ * Copyright (c) 2010-12, NVIDIA CORPORATION. All rights reserved.
*
* Copyright 2007 Wolfson Microelectronics PLC.
* Author: Graeme Gregory
@@ -32,6 +32,7 @@
#include <asm/mach-types.h>
+#include <linux/clk.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
@@ -118,11 +119,12 @@ static int tegra_max98095_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_card *card = codec->card;
struct tegra_max98095 *machine = snd_soc_card_get_drvdata(card);
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
#ifndef CONFIG_ARCH_TEGRA_2x_SOC
struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(cpu_dai);
#endif
- unsigned int srate, mclk, sample_size;
- int err;
+ unsigned int srate, mclk, sample_size, i2s_daifmt;
+ int err, rate;
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
@@ -154,6 +156,31 @@ static int tegra_max98095_hw_params(struct snd_pcm_substream *substream,
break;
}
+ i2s_daifmt = SND_SOC_DAIFMT_NB_NF;
+ i2s_daifmt |= pdata->i2s_param[HIFI_CODEC].is_i2s_master ?
+ SND_SOC_DAIFMT_CBS_CFS : SND_SOC_DAIFMT_CBM_CFM;
+
+ switch (pdata->i2s_param[HIFI_CODEC].i2s_mode) {
+ case TEGRA_DAIFMT_I2S :
+ i2s_daifmt |= SND_SOC_DAIFMT_I2S;
+ break;
+ case TEGRA_DAIFMT_DSP_A :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_A;
+ break;
+ case TEGRA_DAIFMT_DSP_B :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_B;
+ break;
+ case TEGRA_DAIFMT_LEFT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_LEFT_J;
+ break;
+ case TEGRA_DAIFMT_RIGHT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_RIGHT_J;
+ break;
+ default :
+ dev_err(card->dev, "Can't configure i2s format\n");
+ return -EINVAL;
+ }
+
err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
if (err < 0) {
if (!(machine->util_data.set_mclk % mclk))
@@ -166,26 +193,20 @@ static int tegra_max98095_hw_params(struct snd_pcm_substream *substream,
tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
- err = snd_soc_dai_set_fmt(codec_dai,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS);
+ rate = clk_get_rate(machine->util_data.clk_cdev1);
+ err = snd_soc_dai_set_fmt(codec_dai, i2s_daifmt);
if (err < 0) {
dev_err(card->dev, "codec_dai fmt not set\n");
return err;
}
- err = snd_soc_dai_set_fmt(cpu_dai,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS);
+ err = snd_soc_dai_set_fmt(cpu_dai, i2s_daifmt);
if (err < 0) {
dev_err(card->dev, "cpu_dai fmt not set\n");
return err;
}
- err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
- SND_SOC_CLOCK_IN);
+ err = snd_soc_dai_set_sysclk(codec_dai, 0, rate, SND_SOC_CLOCK_IN);
if (err < 0) {
dev_err(card->dev, "codec_dai clock not set\n");
return err;
@@ -667,6 +688,16 @@ static __devinit int tegra_max98095_driver_probe(struct platform_device *pdev)
goto err_unregister_card;
}
+#ifndef CONFIG_ARCH_TEGRA_2x_SOC
+ ret = tegra_asoc_utils_set_parent(&machine->util_data,
+ pdata->i2s_param[HIFI_CODEC].is_i2s_master);
+ if (ret) {
+ dev_err(&pdev->dev, "tegra_asoc_utils_set_parent failed (%d)\n",
+ ret);
+ goto err_switch_unregister;
+ }
+#endif
+
return 0;
err_unregister_card:
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c
index 090e8481dc37..8bd0af7df610 100644
--- a/sound/soc/tegra/tegra_pcm.c
+++ b/sound/soc/tegra/tegra_pcm.c
@@ -74,7 +74,10 @@ static void tegra_pcm_queue_dma(struct tegra_runtime_data *prtd)
dma_req = &prtd->dma_req[prtd->dma_req_idx];
- addr = buf->addr + prtd->dma_pos;
+ if (prtd->avp_dma_addr)
+ addr = prtd->avp_dma_addr + prtd->dma_pos;
+ else
+ addr = buf->addr + prtd->dma_pos;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
dma_req->source_addr = addr;
diff --git a/sound/soc/tegra/tegra_pcm.h b/sound/soc/tegra/tegra_pcm.h
index b63de32023e8..5a9531b9fbf7 100644
--- a/sound/soc/tegra/tegra_pcm.h
+++ b/sound/soc/tegra/tegra_pcm.h
@@ -54,6 +54,7 @@ struct tegra_runtime_data {
struct tegra_dma_channel *dma_chan;
int dma_req_count;
int disable_intr;
+ unsigned int avp_dma_addr;
};
int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd);
diff --git a/sound/soc/tegra/tegra_rt5640.c b/sound/soc/tegra/tegra_rt5640.c
index 765eb59fabae..a99711fb9234 100644
--- a/sound/soc/tegra/tegra_rt5640.c
+++ b/sound/soc/tegra/tegra_rt5640.c
@@ -10,6 +10,7 @@
* Author: Graeme Gregory
* graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
*
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
@@ -28,6 +29,7 @@
#include <asm/mach-types.h>
+#include <linux/clk.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
@@ -37,7 +39,7 @@
#include <linux/switch.h>
#endif
-#include <mach/tegra_rt5640_pdata.h>
+#include <mach/tegra_asoc_pdata.h>
#include <sound/core.h>
#include <sound/jack.h>
@@ -61,7 +63,7 @@
struct tegra_rt5640 {
struct tegra_asoc_utils_data util_data;
- struct tegra_rt5640_platform_data *pdata;
+ struct tegra_asoc_platform_data *pdata;
struct regulator *spk_reg;
struct regulator *dmic_reg;
struct regulator *cdc_en;
@@ -82,11 +84,38 @@ static int tegra_rt5640_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_card *card = codec->card;
struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
int srate, mclk, i2s_daifmt;
- int err;
+ int err, rate;
srate = params_rate(params);
mclk = 256 * srate;
+
+ i2s_daifmt = SND_SOC_DAIFMT_NB_NF;
+ i2s_daifmt |= pdata->i2s_param[HIFI_CODEC].is_i2s_master ?
+ SND_SOC_DAIFMT_CBS_CFS : SND_SOC_DAIFMT_CBM_CFM;
+
+ switch (pdata->i2s_param[HIFI_CODEC].i2s_mode) {
+ case TEGRA_DAIFMT_I2S :
+ i2s_daifmt |= SND_SOC_DAIFMT_I2S;
+ break;
+ case TEGRA_DAIFMT_DSP_A :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_A;
+ break;
+ case TEGRA_DAIFMT_DSP_B :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_B;
+ break;
+ case TEGRA_DAIFMT_LEFT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_LEFT_J;
+ break;
+ case TEGRA_DAIFMT_RIGHT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_RIGHT_J;
+ break;
+ default :
+ dev_err(card->dev, "Can't configure i2s format\n");
+ return -EINVAL;
+ }
+
err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
if (err < 0) {
if (!(machine->util_data.set_mclk % mclk)) {
@@ -99,10 +128,7 @@ static int tegra_rt5640_hw_params(struct snd_pcm_substream *substream,
tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
- i2s_daifmt = SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS;
-
- i2s_daifmt |= SND_SOC_DAIFMT_I2S;
+ rate = clk_get_rate(machine->util_data.clk_cdev1);
err = snd_soc_dai_set_fmt(codec_dai, i2s_daifmt);
if (err < 0) {
@@ -116,8 +142,7 @@ static int tegra_rt5640_hw_params(struct snd_pcm_substream *substream,
return err;
}
- err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
- SND_SOC_CLOCK_IN);
+ err = snd_soc_dai_set_sysclk(codec_dai, 0, rate, SND_SOC_CLOCK_IN);
if (err < 0) {
dev_err(card->dev, "codec_dai clock not set\n");
return err;
@@ -130,10 +155,10 @@ static int tegra_bt_sco_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct snd_soc_card *card = rtd->card;
struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
- int srate, mclk, min_mclk;
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
+ int srate, mclk, min_mclk, i2s_daifmt;
int err;
srate = params_rate(params);
@@ -169,10 +194,32 @@ static int tegra_bt_sco_hw_params(struct snd_pcm_substream *substream,
tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
- err = snd_soc_dai_set_fmt(cpu_dai,
- SND_SOC_DAIFMT_DSP_A |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS);
+ i2s_daifmt = SND_SOC_DAIFMT_NB_NF;
+ i2s_daifmt |= pdata->i2s_param[BT_SCO].is_i2s_master ?
+ SND_SOC_DAIFMT_CBS_CFS : SND_SOC_DAIFMT_CBM_CFM;
+
+ switch (pdata->i2s_param[BT_SCO].i2s_mode) {
+ case TEGRA_DAIFMT_I2S :
+ i2s_daifmt |= SND_SOC_DAIFMT_I2S;
+ break;
+ case TEGRA_DAIFMT_DSP_A :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_A;
+ break;
+ case TEGRA_DAIFMT_DSP_B :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_B;
+ break;
+ case TEGRA_DAIFMT_LEFT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_LEFT_J;
+ break;
+ case TEGRA_DAIFMT_RIGHT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_RIGHT_J;
+ break;
+ default :
+ dev_err(card->dev, "Can't configure i2s format\n");
+ return -EINVAL;
+ }
+
+ err = snd_soc_dai_set_fmt(rtd->cpu_dai, i2s_daifmt);
if (err < 0) {
dev_err(card->dev, "cpu_dai fmt not set\n");
return err;
@@ -279,7 +326,7 @@ static int tegra_rt5640_jack_notifier(struct notifier_block *self,
struct snd_soc_codec *codec = jack->codec;
struct snd_soc_card *card = codec->card;
struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
- struct tegra_rt5640_platform_data *pdata = machine->pdata;
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
enum headset_state state = BIT_NO_HEADSET;
unsigned char status_jack = 0;
@@ -357,7 +404,7 @@ static int tegra_rt5640_event_int_spk(struct snd_soc_dapm_widget *w,
struct snd_soc_dapm_context *dapm = w->dapm;
struct snd_soc_card *card = dapm->card;
struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
- struct tegra_rt5640_platform_data *pdata = machine->pdata;
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
if (machine->spk_reg) {
if (SND_SOC_DAPM_EVENT_ON(event))
@@ -381,7 +428,7 @@ static int tegra_rt5640_event_hp(struct snd_soc_dapm_widget *w,
struct snd_soc_dapm_context *dapm = w->dapm;
struct snd_soc_card *card = dapm->card;
struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
- struct tegra_rt5640_platform_data *pdata = machine->pdata;
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
if (!(machine->gpio_requested & GPIO_HP_MUTE))
return 0;
@@ -398,7 +445,7 @@ static int tegra_rt5640_event_int_mic(struct snd_soc_dapm_widget *w,
struct snd_soc_dapm_context *dapm = w->dapm;
struct snd_soc_card *card = dapm->card;
struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
- struct tegra_rt5640_platform_data *pdata = machine->pdata;
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
if (machine->dmic_reg) {
if (SND_SOC_DAPM_EVENT_ON(event))
@@ -422,7 +469,7 @@ static int tegra_rt5640_event_ext_mic(struct snd_soc_dapm_widget *w,
struct snd_soc_dapm_context *dapm = w->dapm;
struct snd_soc_card *card = dapm->card;
struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
- struct tegra_rt5640_platform_data *pdata = machine->pdata;
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
if (!(machine->gpio_requested & GPIO_EXT_MIC_EN))
return 0;
@@ -467,7 +514,7 @@ static int tegra_rt5640_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_dapm_context *dapm = &codec->dapm;
struct snd_soc_card *card = codec->card;
struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
- struct tegra_rt5640_platform_data *pdata = machine->pdata;
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
int ret;
if (gpio_is_valid(pdata->gpio_spkr_en)) {
@@ -650,7 +697,7 @@ static __devinit int tegra_rt5640_driver_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &snd_soc_tegra_rt5640;
struct tegra_rt5640 *machine;
- struct tegra_rt5640_platform_data *pdata;
+ struct tegra_asoc_platform_data *pdata;
int ret;
pdata = pdev->dev.platform_data;
@@ -716,6 +763,16 @@ static __devinit int tegra_rt5640_driver_probe(struct platform_device *pdev)
goto err_unregister_card;
}
+#ifndef CONFIG_ARCH_TEGRA_2x_SOC
+ ret = tegra_asoc_utils_set_parent(&machine->util_data,
+ pdata->i2s_param[HIFI_CODEC].is_i2s_master);
+ if (ret) {
+ dev_err(&pdev->dev, "tegra_asoc_utils_set_parent failed (%d)\n",
+ ret);
+ goto err_unregister_card;
+ }
+#endif
+
return 0;
err_unregister_card:
@@ -735,7 +792,7 @@ static int __devexit tegra_rt5640_driver_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
- struct tegra_rt5640_platform_data *pdata = machine->pdata;
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
if (machine->gpio_requested & GPIO_HP_DET)
snd_soc_jack_free_gpios(&tegra_rt5640_hp_jack,
diff --git a/sound/soc/tegra/tegra_p1852.c b/sound/soc/tegra/tegra_vcm.c
index 199bb8046636..afb444e3f19f 100644
--- a/sound/soc/tegra/tegra_p1852.c
+++ b/sound/soc/tegra/tegra_vcm.c
@@ -1,8 +1,8 @@
/*
- * tegra_p1852.c - Tegra machine ASoC driver for P1852 Boards.
+ * tegra_vcm.c - Tegra machine ASoC driver for P852/P1852/P1853 Boards.
*
* Author: Nitin Pai <npai@nvidia.com>
- * Copyright (C) 2010-2012 - NVIDIA, Inc.
+ * Copyright (C) 2010-2012 - NVIDIA, Corporation. All rights reserved.
*
* Based on code copyright/by:
* Copyright (c) 2009-2010, NVIDIA Corporation.
@@ -41,14 +41,23 @@
#include "tegra_pcm.h"
#include "tegra_asoc_utils.h"
+#ifdef CONFIG_MACH_P1852
#define DRV_NAME "tegra-snd-p1852"
+#endif
+#ifdef CONFIG_MACH_E1853
+#define DRV_NAME "tegra-snd-e1853"
+#endif
+#ifdef CONFIG_MACH_P852
+#define DRV_NAME "tegra-snd-p852"
+#endif
-struct tegra_p1852 {
+
+struct tegra_vcm {
struct tegra_asoc_utils_data util_data;
struct tegra_p1852_platform_data *pdata;
};
-static int tegra_p1852_hw_params(struct snd_pcm_substream *substream,
+static int tegra_vcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
int codec_id)
{
@@ -57,7 +66,7 @@ static int tegra_p1852_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_card *card = codec->card;
- struct tegra_p1852 *machine = snd_soc_card_get_drvdata(card);
+ struct tegra_vcm *machine = snd_soc_card_get_drvdata(card);
int srate, mclk;
int i2s_daifmt = 0;
int err;
@@ -139,64 +148,64 @@ static int tegra_p1852_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static int tegra_p1852_hw_params_controller1(
+static int tegra_vcm_hw_params_controller1(
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
- return tegra_p1852_hw_params(substream, params, 0);
+ return tegra_vcm_hw_params(substream, params, 0);
}
-static int tegra_p1852_hw_params_controller2(
+static int tegra_vcm_hw_params_controller2(
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
- return tegra_p1852_hw_params(substream, params, 1);
+ return tegra_vcm_hw_params(substream, params, 1);
}
static int tegra_hw_free(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct tegra_p1852 *machine = snd_soc_card_get_drvdata(rtd->card);
+ struct tegra_vcm *machine = snd_soc_card_get_drvdata(rtd->card);
tegra_asoc_utils_lock_clk_rate(&machine->util_data, 0);
return 0;
}
-static struct snd_soc_ops tegra_p1852_ops_controller1 = {
- .hw_params = tegra_p1852_hw_params_controller1,
+static struct snd_soc_ops tegra_vcm_ops_controller1 = {
+ .hw_params = tegra_vcm_hw_params_controller1,
.hw_free = tegra_hw_free,
};
-static struct snd_soc_ops tegra_p1852_ops_controller2 = {
- .hw_params = tegra_p1852_hw_params_controller2,
+static struct snd_soc_ops tegra_vcm_ops_controller2 = {
+ .hw_params = tegra_vcm_hw_params_controller2,
.hw_free = tegra_hw_free,
};
-static struct snd_soc_dai_link tegra_p1852_dai_link[] = {
+static struct snd_soc_dai_link tegra_vcm_dai_link[] = {
{
.name = "I2S-TDM-1",
.stream_name = "TEGRA PCM",
.platform_name = "tegra-pcm-audio",
- .ops = &tegra_p1852_ops_controller1,
+ .ops = &tegra_vcm_ops_controller1,
},
{
.name = "I2S-TDM-2",
.stream_name = "TEGRA PCM",
.platform_name = "tegra-pcm-audio",
- .ops = &tegra_p1852_ops_controller2,
+ .ops = &tegra_vcm_ops_controller2,
}
};
-static struct snd_soc_card snd_soc_tegra_p1852 = {
- .name = "tegra-p1852",
- .dai_link = tegra_p1852_dai_link,
- .num_links = ARRAY_SIZE(tegra_p1852_dai_link),
+static struct snd_soc_card snd_soc_tegra_vcm = {
+ .name = "tegra-vcm",
+ .dai_link = tegra_vcm_dai_link,
+ .num_links = ARRAY_SIZE(tegra_vcm_dai_link),
};
-static __devinit int tegra_p1852_driver_probe(struct platform_device *pdev)
+static __devinit int tegra_vcm_driver_probe(struct platform_device *pdev)
{
- struct snd_soc_card *card = &snd_soc_tegra_p1852;
- struct tegra_p1852 *machine;
+ struct snd_soc_card *card = &snd_soc_tegra_vcm;
+ struct tegra_vcm *machine;
struct tegra_p1852_platform_data *pdata;
int ret;
int i;
@@ -207,9 +216,9 @@ static __devinit int tegra_p1852_driver_probe(struct platform_device *pdev)
return -EINVAL;
}
- machine = kzalloc(sizeof(struct tegra_p1852), GFP_KERNEL);
+ machine = kzalloc(sizeof(struct tegra_vcm), GFP_KERNEL);
if (!machine) {
- dev_err(&pdev->dev, "Can't allocate tegra_p1852 struct\n");
+ dev_err(&pdev->dev, "Can't allocate tegra_vcm struct\n");
return -ENOMEM;
}
@@ -218,17 +227,17 @@ static __devinit int tegra_p1852_driver_probe(struct platform_device *pdev)
/* The codec driver and codec dai have to come from the system
* level board configuration file
* */
- for (i = 0; i < ARRAY_SIZE(tegra_p1852_dai_link); i++) {
- tegra_p1852_dai_link[i].codec_name =
+ for (i = 0; i < ARRAY_SIZE(tegra_vcm_dai_link); i++) {
+ tegra_vcm_dai_link[i].codec_name =
pdata->codec_info[i].codec_name;
- tegra_p1852_dai_link[i].cpu_dai_name =
+ tegra_vcm_dai_link[i].cpu_dai_name =
pdata->codec_info[i].cpu_dai_name;
- tegra_p1852_dai_link[i].codec_dai_name =
+ tegra_vcm_dai_link[i].codec_dai_name =
pdata->codec_info[i].codec_dai_name;
- tegra_p1852_dai_link[i].name =
+ tegra_vcm_dai_link[i].name =
pdata->codec_info[i].name;
if (pdata->codec_info[i].pcm_driver)
- tegra_p1852_dai_link[i].platform_name =
+ tegra_vcm_dai_link[i].platform_name =
pdata->codec_info[i].pcm_driver;
}
@@ -263,10 +272,10 @@ err_free_machine:
return ret;
}
-static int __devexit tegra_p1852_driver_remove(struct platform_device *pdev)
+static int __devexit tegra_vcm_driver_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
- struct tegra_p1852 *machine = snd_soc_card_get_drvdata(card);
+ struct tegra_vcm *machine = snd_soc_card_get_drvdata(card);
snd_soc_unregister_card(card);
tegra_asoc_utils_fini(&machine->util_data);
@@ -275,29 +284,29 @@ static int __devexit tegra_p1852_driver_remove(struct platform_device *pdev)
return 0;
}
-static struct platform_driver tegra_p1852_driver = {
+static struct platform_driver tegra_vcm_driver = {
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
.pm = &snd_soc_pm_ops,
},
- .probe = tegra_p1852_driver_probe,
- .remove = __devexit_p(tegra_p1852_driver_remove),
+ .probe = tegra_vcm_driver_probe,
+ .remove = __devexit_p(tegra_vcm_driver_remove),
};
-static int __init tegra_p1852_modinit(void)
+static int __init tegra_vcm_modinit(void)
{
- return platform_driver_register(&tegra_p1852_driver);
+ return platform_driver_register(&tegra_vcm_driver);
}
-module_init(tegra_p1852_modinit);
+module_init(tegra_vcm_modinit);
-static void __exit tegra_p1852_modexit(void)
+static void __exit tegra_vcm_modexit(void)
{
- platform_driver_unregister(&tegra_p1852_driver);
+ platform_driver_unregister(&tegra_vcm_driver);
}
-module_exit(tegra_p1852_modexit);
+module_exit(tegra_vcm_modexit);
MODULE_AUTHOR("Nitin Pai <npai@nvidia.com>");
-MODULE_DESCRIPTION("Tegra+P1852 machine ASoC driver");
+MODULE_DESCRIPTION("Tegra+VCM machine ASoC driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/tegra/tegra_wm8753.c b/sound/soc/tegra/tegra_wm8753.c
index f7c7a4c6b5a1..f1b9335ab473 100644
--- a/sound/soc/tegra/tegra_wm8753.c
+++ b/sound/soc/tegra/tegra_wm8753.c
@@ -12,6 +12,7 @@
* Author: Graeme Gregory
* graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
*
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
@@ -30,6 +31,7 @@
#include <asm/mach-types.h>
+#include <linux/clk.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
@@ -83,8 +85,10 @@ static int tegra_wm8753_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_card *card = codec->card;
struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card);
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
int srate, mclk, i2s_daifmt;
- int err;
+ int err, rate;
+
srate = params_rate(params);
switch (srate) {
case 8000:
@@ -119,14 +123,38 @@ static int tegra_wm8753_hw_params(struct snd_pcm_substream *substream,
tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
- i2s_daifmt = SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS;
+ rate = clk_get_rate(machine->util_data.clk_cdev1);
+
+ i2s_daifmt = SND_SOC_DAIFMT_NB_NF;
+ i2s_daifmt |= pdata->i2s_param[HIFI_CODEC].is_i2s_master ?
+ SND_SOC_DAIFMT_CBS_CFS : SND_SOC_DAIFMT_CBM_CFM;
/* Use DSP mode for mono on Tegra20 */
- if ((params_channels(params) != 2) && machine_is_whistler())
+ if ((params_channels(params) != 2) && machine_is_whistler()) {
i2s_daifmt |= SND_SOC_DAIFMT_DSP_A;
- else
- i2s_daifmt |= SND_SOC_DAIFMT_I2S;
+ } else {
+ switch (pdata->i2s_param[HIFI_CODEC].i2s_mode) {
+ case TEGRA_DAIFMT_I2S :
+ i2s_daifmt |= SND_SOC_DAIFMT_I2S;
+ break;
+ case TEGRA_DAIFMT_DSP_A :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_A;
+ break;
+ case TEGRA_DAIFMT_DSP_B :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_B;
+ break;
+ case TEGRA_DAIFMT_LEFT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_LEFT_J;
+ break;
+ case TEGRA_DAIFMT_RIGHT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_RIGHT_J;
+ break;
+ default :
+ dev_err(card->dev,
+ "Can't configure i2s format\n");
+ return -EINVAL;
+ }
+ }
err = snd_soc_dai_set_fmt(codec_dai, i2s_daifmt);
if (err < 0) {
@@ -140,8 +168,7 @@ static int tegra_wm8753_hw_params(struct snd_pcm_substream *substream,
return err;
}
- err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
- SND_SOC_CLOCK_IN);
+ err = snd_soc_dai_set_sysclk(codec_dai, 0, rate, SND_SOC_CLOCK_IN);
if (err < 0) {
dev_err(card->dev, "codec_dai clock not set\n");
return err;
@@ -173,7 +200,8 @@ static int tegra_bt_sco_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_card *card = codec->card;
struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card);
- int srate, mclk, min_mclk;
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
+ int srate, mclk, min_mclk, i2s_daifmt;
int err;
srate = params_rate(params);
@@ -209,10 +237,32 @@ static int tegra_bt_sco_hw_params(struct snd_pcm_substream *substream,
tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
- err = snd_soc_dai_set_fmt(cpu_dai,
- SND_SOC_DAIFMT_DSP_A |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS);
+ i2s_daifmt = SND_SOC_DAIFMT_NB_NF;
+ i2s_daifmt |= pdata->i2s_param[BT_SCO].is_i2s_master ?
+ SND_SOC_DAIFMT_CBS_CFS : SND_SOC_DAIFMT_CBM_CFM;
+
+ switch (pdata->i2s_param[BT_SCO].i2s_mode) {
+ case TEGRA_DAIFMT_I2S :
+ i2s_daifmt |= SND_SOC_DAIFMT_I2S;
+ break;
+ case TEGRA_DAIFMT_DSP_A :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_A;
+ break;
+ case TEGRA_DAIFMT_DSP_B :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_B;
+ break;
+ case TEGRA_DAIFMT_LEFT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_LEFT_J;
+ break;
+ case TEGRA_DAIFMT_RIGHT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_RIGHT_J;
+ break;
+ default :
+ dev_err(card->dev, "Can't configure i2s format\n");
+ return -EINVAL;
+ }
+
+ err = snd_soc_dai_set_fmt(cpu_dai, i2s_daifmt);
if (err < 0) {
dev_err(card->dev, "cpu_dai fmt not set\n");
return err;
@@ -873,8 +923,6 @@ static __devinit int tegra_wm8753_driver_probe(struct platform_device *pdev)
return -ENOMEM;
}
- machine->pdata = pdata;
-
ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev, card);
if (ret)
goto err_free_machine;
@@ -904,6 +952,16 @@ static __devinit int tegra_wm8753_driver_probe(struct platform_device *pdev)
}
#endif
+#ifndef CONFIG_ARCH_TEGRA_2x_SOC
+ ret = tegra_asoc_utils_set_parent(&machine->util_data,
+ pdata->i2s_param[HIFI_CODEC].is_i2s_master);
+ if (ret) {
+ dev_err(&pdev->dev, "tegra_asoc_utils_set_parent failed (%d)\n",
+ ret);
+ goto err_unregister_card;
+ }
+#endif
+
return 0;
err_unregister_card:
diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c
index 063aefe50507..dcd031209172 100644
--- a/sound/soc/tegra/tegra_wm8903.c
+++ b/sound/soc/tegra/tegra_wm8903.c
@@ -12,6 +12,8 @@
* Author: Graeme Gregory
* graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
*
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+ *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
@@ -40,7 +42,7 @@
#include <linux/switch.h>
#endif
-#include <mach/tegra_wm8903_pdata.h>
+#include <mach/tegra_asoc_pdata.h>
#include <sound/core.h>
#include <sound/jack.h>
@@ -67,7 +69,7 @@
struct tegra_wm8903 {
struct tegra_asoc_utils_data util_data;
- struct tegra_wm8903_platform_data *pdata;
+ struct tegra_asoc_platform_data *pdata;
struct regulator *spk_reg;
struct regulator *dmic_reg;
int gpio_requested;
@@ -86,9 +88,9 @@ static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_card *card = codec->card;
struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
int srate, mclk, i2s_daifmt;
int err;
- struct clk *clk_m;
int rate;
srate = params_rate(params);
@@ -103,31 +105,17 @@ static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream,
break;
}
+ if(pdata->i2s_param[HIFI_CODEC].is_i2s_master) {
+ /* FIXME: Codec only requires >= 3MHz if OSR==0 */
+ while (mclk < 6000000)
+ mclk *= 2;
-
- clk_m = clk_get_sys(NULL, "clk_m");
- if (IS_ERR(clk_m)) {
- dev_err(card->dev, "Can't retrieve clk clk_m\n");
- err = PTR_ERR(clk_m);
- return err;
+ i2s_daifmt = SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS;
+ } else {
+ i2s_daifmt = SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM;
}
- rate = clk_get_rate(clk_m);
- printk("extern1 rate=%d\n",rate);
-
-#if TEGRA30_I2S_MASTER_PLAYBACK
- /* FIXME: Codec only requires >= 3MHz if OSR==0 */
- while (mclk < 6000000)
- mclk *= 2;
-
- i2s_daifmt = SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS;
-#else
- mclk = rate;
-
- i2s_daifmt = SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBM_CFM;
-#endif
-
err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
if (err < 0) {
@@ -141,13 +129,36 @@ static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream,
tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
+ rate = clk_get_rate(machine->util_data.clk_cdev1);
+
/* Use DSP mode for mono on Tegra20 */
if ((params_channels(params) != 2) &&
- (machine_is_ventana() || machine_is_harmony() ||
- machine_is_kaen() || machine_is_aebl()))
+ (machine_is_ventana() || machine_is_harmony() ||
+ machine_is_kaen() || machine_is_aebl())) {
i2s_daifmt |= SND_SOC_DAIFMT_DSP_A;
- else
- i2s_daifmt |= SND_SOC_DAIFMT_I2S;
+ } else {
+ switch (pdata->i2s_param[HIFI_CODEC].i2s_mode) {
+ case TEGRA_DAIFMT_I2S :
+ i2s_daifmt |= SND_SOC_DAIFMT_I2S;
+ break;
+ case TEGRA_DAIFMT_DSP_A :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_A;
+ break;
+ case TEGRA_DAIFMT_DSP_B :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_B;
+ break;
+ case TEGRA_DAIFMT_LEFT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_LEFT_J;
+ break;
+ case TEGRA_DAIFMT_RIGHT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_RIGHT_J;
+ break;
+ default :
+ dev_err(card->dev,
+ "Can't configure i2s format\n");
+ return -EINVAL;
+ }
+ }
err = snd_soc_dai_set_fmt(codec_dai, i2s_daifmt);
if (err < 0) {
@@ -161,8 +172,7 @@ static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream,
return err;
}
- err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
- SND_SOC_CLOCK_IN);
+ err = snd_soc_dai_set_sysclk(codec_dai, 0, rate, SND_SOC_CLOCK_IN);
if (err < 0) {
dev_err(card->dev, "codec_dai clock not set\n");
return err;
@@ -190,10 +200,10 @@ static int tegra_bt_sco_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct snd_soc_card *card = rtd->card;
struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
- int srate, mclk, min_mclk;
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
+ int srate, mclk, min_mclk, i2s_daifmt;
int err;
srate = params_rate(params);
@@ -229,10 +239,32 @@ static int tegra_bt_sco_hw_params(struct snd_pcm_substream *substream,
tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
- err = snd_soc_dai_set_fmt(cpu_dai,
- SND_SOC_DAIFMT_DSP_A |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS);
+ i2s_daifmt = SND_SOC_DAIFMT_NB_NF;
+ i2s_daifmt |= pdata->i2s_param[BT_SCO].is_i2s_master ?
+ SND_SOC_DAIFMT_CBS_CFS : SND_SOC_DAIFMT_CBM_CFM;
+
+ switch (pdata->i2s_param[BT_SCO].i2s_mode) {
+ case TEGRA_DAIFMT_I2S :
+ i2s_daifmt |= SND_SOC_DAIFMT_I2S;
+ break;
+ case TEGRA_DAIFMT_DSP_A :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_A;
+ break;
+ case TEGRA_DAIFMT_DSP_B :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_B;
+ break;
+ case TEGRA_DAIFMT_LEFT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_LEFT_J;
+ break;
+ case TEGRA_DAIFMT_RIGHT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_RIGHT_J;
+ break;
+ default :
+ dev_err(card->dev, "Can't configure i2s format\n");
+ return -EINVAL;
+ }
+
+ err = snd_soc_dai_set_fmt(rtd->cpu_dai, i2s_daifmt);
if (err < 0) {
dev_err(card->dev, "cpu_dai fmt not set\n");
return err;
@@ -408,7 +440,7 @@ static int tegra_wm8903_event_int_spk(struct snd_soc_dapm_widget *w,
struct snd_soc_dapm_context *dapm = w->dapm;
struct snd_soc_card *card = dapm->card;
struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
- struct tegra_wm8903_platform_data *pdata = machine->pdata;
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
if (machine->spk_reg) {
if (SND_SOC_DAPM_EVENT_ON(event))
@@ -432,7 +464,7 @@ static int tegra_wm8903_event_hp(struct snd_soc_dapm_widget *w,
struct snd_soc_dapm_context *dapm = w->dapm;
struct snd_soc_card *card = dapm->card;
struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
- struct tegra_wm8903_platform_data *pdata = machine->pdata;
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
if (!(machine->gpio_requested & GPIO_HP_MUTE))
return 0;
@@ -449,7 +481,7 @@ static int tegra_wm8903_event_int_mic(struct snd_soc_dapm_widget *w,
struct snd_soc_dapm_context *dapm = w->dapm;
struct snd_soc_card *card = dapm->card;
struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
- struct tegra_wm8903_platform_data *pdata = machine->pdata;
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
if (machine->dmic_reg) {
if (SND_SOC_DAPM_EVENT_ON(event))
@@ -473,7 +505,7 @@ static int tegra_wm8903_event_ext_mic(struct snd_soc_dapm_widget *w,
struct snd_soc_dapm_context *dapm = w->dapm;
struct snd_soc_card *card = dapm->card;
struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
- struct tegra_wm8903_platform_data *pdata = machine->pdata;
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
if (!(machine->gpio_requested & GPIO_EXT_MIC_EN))
return 0;
@@ -578,7 +610,7 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_dapm_context *dapm = &codec->dapm;
struct snd_soc_card *card = codec->card;
struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
- struct tegra_wm8903_platform_data *pdata = machine->pdata;
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
int ret;
machine->bias_level = SND_SOC_BIAS_STANDBY;
@@ -792,7 +824,7 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &snd_soc_tegra_wm8903;
struct tegra_wm8903 *machine;
- struct tegra_wm8903_platform_data *pdata;
+ struct tegra_asoc_platform_data *pdata;
int ret;
pdata = pdev->dev.platform_data;
@@ -895,6 +927,16 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev)
goto err_unregister_card;
}
+#ifndef CONFIG_ARCH_TEGRA_2x_SOC
+ ret = tegra_asoc_utils_set_parent(&machine->util_data,
+ pdata->i2s_param[HIFI_CODEC].is_i2s_master);
+ if (ret) {
+ dev_err(&pdev->dev, "tegra_asoc_utils_set_parent failed (%d)\n",
+ ret);
+ goto err_unregister_card;
+ }
+#endif
+
return 0;
err_unregister_card:
@@ -914,7 +956,7 @@ static int __devexit tegra_wm8903_driver_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
- struct tegra_wm8903_platform_data *pdata = machine->pdata;
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
if (machine->gpio_requested & GPIO_HP_DET)
snd_soc_jack_free_gpios(&tegra_wm8903_hp_jack,