summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorNikesh Oswal <noswal@nvidia.com>2012-01-30 11:46:34 +0530
committerRohan Somvanshi <rsomvanshi@nvidia.com>2012-02-03 05:42:01 -0800
commit5a0a5bf298d0ab9782cbba670319a7be59ca57a8 (patch)
tree617a0981f4df8f72d2d672f9cae4df57df5a956c /sound
parent418eb73306ce3f5965d442456f07985530a1efd7 (diff)
asoc: tegra: whistler: add support for bt voice call
add support for bt voice call and also make bt as master and i2s as slave for bt-soc playback and record because for bt voice call modem is slave and bt is master Bug: 919350 Reviewed-on: http://git-master/r/77990 Change-Id: I5bbb6cc4b08c5ab1d700ce4d21bbdf9be606e551 Signed-off-by: Nikesh Oswal <noswal@nvidia.com> Signed-off-by: Varun Wadekar <vwadekar@nvidia.com> Reviewed-on: http://git-master/r/78703 Reviewed-by: Automatic_Commit_Validation_User
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/tegra/tegra_wm8753.c127
1 files changed, 110 insertions, 17 deletions
diff --git a/sound/soc/tegra/tegra_wm8753.c b/sound/soc/tegra/tegra_wm8753.c
index 1388a8d664bb..858ef908b5e1 100644
--- a/sound/soc/tegra/tegra_wm8753.c
+++ b/sound/soc/tegra/tegra_wm8753.c
@@ -69,6 +69,7 @@ struct tegra_wm8753 {
struct regulator *audio_reg;
int gpio_requested;
int is_call_mode;
+ int is_call_mode_bt;
};
static int tegra_wm8753_hw_params(struct snd_pcm_substream *substream,
@@ -209,7 +210,7 @@ static int tegra_bt_sco_hw_params(struct snd_pcm_substream *substream,
err = snd_soc_dai_set_fmt(cpu_dai,
SND_SOC_DAIFMT_DSP_A |
SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS);
+ SND_SOC_DAIFMT_CBM_CFM);
if (err < 0) {
dev_err(card->dev, "cpu_dai fmt not set\n");
return err;
@@ -367,9 +368,62 @@ static int tegra_wm8753_voice_hw_params(struct snd_pcm_substream *substream,
snd_soc_dai_set_clkdiv(codec_dai, WM8753_VXCLKDIV, vxclkdiv);
snd_soc_dai_set_clkdiv(codec_dai, WM8753_PCMDIV, pcmdiv);
+ machine->is_call_mode_bt = 0;
+
return 0;
}
+static int tegra_bt_call_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 *codec_dai = rtd->codec_dai;
+ 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;
+ int err;
+
+ srate = params_rate(params);
+ switch (srate) {
+ case 8000:
+ case 16000:
+ case 24000:
+ case 32000:
+ case 48000:
+ case 64000:
+ case 96000:
+ mclk = 12288000;
+ break;
+ case 11025:
+ case 22050:
+ case 44100:
+ case 88200:
+ mclk = 11289600;
+ break;
+ default:
+ mclk = 12000000;
+ break;
+ }
+
+ err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
+ if (err < 0) {
+ if (!(machine->util_data.set_mclk % mclk))
+ mclk = machine->util_data.set_mclk;
+ else {
+ dev_err(card->dev, "Can't configure clocks\n");
+ return err;
+ }
+ }
+
+ tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
+
+ machine->is_call_mode_bt = 1;
+
+ return 0;
+}
+
+
static int tegra_hw_free(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -380,12 +434,24 @@ static int tegra_hw_free(struct snd_pcm_substream *substream)
return 0;
}
+static int tegra_bt_call_hw_free(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(rtd->card);
+
+ tegra_asoc_utils_lock_clk_rate(&machine->util_data, 0);
+ machine->is_call_mode_bt = 0;
+
+ return 0;
+}
+
static int tegra_wm8753_voice_hw_free(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(rtd->card);
tegra_asoc_utils_lock_clk_rate(&machine->util_data, 0);
+ machine->is_call_mode_bt = 0;
return 0;
}
@@ -415,31 +481,44 @@ static int tegra_call_mode_put(struct snd_kcontrol *kcontrol,
{
struct tegra_wm8753 *machine = snd_kcontrol_chip(kcontrol);
int is_call_mode_new = ucontrol->value.integer.value[0];
+ int codec_dap_id, codec_dap_sel, bb_dap_id, bb_dap_sel;
if (machine->is_call_mode == is_call_mode_new)
return 0;
+ bb_dap_id = TEGRA20_DAS_DAP_ID_3;
+ bb_dap_sel = TEGRA20_DAS_DAP_SEL_DAP3;
+
+ if (machine->is_call_mode_bt) {
+ codec_dap_id = TEGRA20_DAS_DAP_ID_4;
+ codec_dap_sel = TEGRA20_DAS_DAP_SEL_DAP4;
+ }
+ else {
+ codec_dap_id = TEGRA20_DAS_DAP_ID_2;
+ codec_dap_sel = TEGRA20_DAS_DAP_SEL_DAP2;
+ }
+
if (is_call_mode_new) {
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- tegra20_das_set_tristate(TEGRA20_DAS_DAP_ID_2, 1);
- tegra20_das_set_tristate(TEGRA20_DAS_DAP_ID_3, 1);
- tegra20_das_connect_dap_to_dap(TEGRA20_DAS_DAP_ID_2,
- TEGRA20_DAS_DAP_SEL_DAP3, 1, 0, 0);
- tegra20_das_connect_dap_to_dap(TEGRA20_DAS_DAP_ID_3,
- TEGRA20_DAS_DAP_SEL_DAP2, 0, 0, 0);
- tegra20_das_set_tristate(TEGRA20_DAS_DAP_ID_2, 0);
- tegra20_das_set_tristate(TEGRA20_DAS_DAP_ID_3, 0);
+ tegra20_das_set_tristate(codec_dap_id, 1);
+ tegra20_das_set_tristate(bb_dap_id, 1);
+ tegra20_das_connect_dap_to_dap(codec_dap_id,
+ bb_dap_sel, 1, 0, 0);
+ tegra20_das_connect_dap_to_dap(bb_dap_id,
+ codec_dap_sel, 0, 0, 0);
+ tegra20_das_set_tristate(codec_dap_id, 0);
+ tegra20_das_set_tristate(bb_dap_id, 0);
#endif
} else {
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- tegra20_das_set_tristate(TEGRA20_DAS_DAP_ID_2, 1);
- tegra20_das_set_tristate(TEGRA20_DAS_DAP_ID_3, 1);
- tegra20_das_connect_dap_to_dap(TEGRA20_DAS_DAP_ID_3,
- TEGRA20_DAS_DAP_SEL_DAP3, 0, 0, 0);
- tegra20_das_connect_dap_to_dap(TEGRA20_DAS_DAP_ID_2,
- TEGRA20_DAS_DAP_SEL_DAP2, 0, 0, 0);
- tegra20_das_set_tristate(TEGRA20_DAS_DAP_ID_2, 0);
- tegra20_das_set_tristate(TEGRA20_DAS_DAP_ID_3, 0);
+ tegra20_das_set_tristate(codec_dap_id, 1);
+ tegra20_das_set_tristate(bb_dap_id, 1);
+ tegra20_das_connect_dap_to_dap(bb_dap_id,
+ bb_dap_sel, 0, 0, 0);
+ tegra20_das_connect_dap_to_dap(codec_dap_id,
+ codec_dap_sel, 0, 0, 0);
+ tegra20_das_set_tristate(codec_dap_id, 0);
+ tegra20_das_set_tristate(bb_dap_id, 0);
#endif
}
@@ -468,6 +547,11 @@ static struct snd_soc_ops tegra_wm8753_voice_ops = {
.hw_free = tegra_wm8753_voice_hw_free,
};
+static struct snd_soc_ops tegra_bt_call_ops = {
+ .hw_params = tegra_bt_call_hw_params,
+ .hw_free = tegra_bt_call_hw_free,
+};
+
static struct snd_soc_ops tegra_bt_sco_ops = {
.hw_params = tegra_bt_sco_hw_params,
.hw_free = tegra_hw_free,
@@ -746,6 +830,15 @@ static struct snd_soc_dai_link tegra_wm8753_dai[] = {
.codec_dai_name = "wm8753-voice",
.ops = &tegra_wm8753_voice_ops,
},
+ {
+ .name = "BT VOICE CALL",
+ .stream_name = "BT VOICE CALL PCM",
+ .codec_name = "spdif-dit.2",
+ .platform_name = "tegra-pcm-audio",
+ .cpu_dai_name = "dit-hifi",
+ .codec_dai_name = "dit-hifi",
+ .ops = &tegra_bt_call_ops,
+ },
};
static struct snd_soc_card snd_soc_tegra_wm8753 = {