diff options
author | Nikesh Oswal <noswal@nvidia.com> | 2011-11-09 15:59:12 +0530 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2012-03-23 15:49:20 -0700 |
commit | a4a739e6e175b303713b0f24d0819fcd9d84aab2 (patch) | |
tree | 87a66cf7598fb017f71cd14ec4e79433991645f3 | |
parent | edb715baf0c14aba00619c98882eb27ba4f62189 (diff) |
ASoC: tegra: max98088 machine: add bt voice call dai link
Bug: 862023
Change-Id: I74f6d8e14ca9c48cbbe272384c0821e880e59697
Signed-off-by: Nikesh Oswal <noswal@nvidia.com>
Reviewed-on: http://git-master/r/63259
Reviewed-by: Rohan Somvanshi <rsomvanshi@nvidia.com>
Rebase-Id: Re4124a65167562191b9058455a20f941887fad54
-rw-r--r-- | sound/soc/tegra/tegra_max98088.c | 110 |
1 files changed, 105 insertions, 5 deletions
diff --git a/sound/soc/tegra/tegra_max98088.c b/sound/soc/tegra/tegra_max98088.c index f389b7fd83bb..5787d3b1d833 100644 --- a/sound/soc/tegra/tegra_max98088.c +++ b/sound/soc/tegra/tegra_max98088.c @@ -87,6 +87,7 @@ struct tegra_max98088 { int gpio_requested; bool init_done; int is_call_mode; + int is_device_bt; #ifndef CONFIG_ARCH_TEGRA_2x_SOC struct codec_config codec_info[NUM_I2S_DEVICES]; #endif @@ -117,24 +118,30 @@ static int tegra_call_mode_put(struct snd_kcontrol *kcontrol, { struct tegra_max98088 *machine = snd_kcontrol_chip(kcontrol); int is_call_mode_new = ucontrol->value.integer.value[0]; + int codec_index; if (machine->is_call_mode == is_call_mode_new) return 0; + if (machine->is_device_bt) + codec_index = BT_SCO; + else + codec_index = HIFI_CODEC; + if (is_call_mode_new) { #ifndef CONFIG_ARCH_TEGRA_2x_SOC - if (machine->codec_info[HIFI_CODEC].rate == 0 || - machine->codec_info[HIFI_CODEC].channels == 0) + if (machine->codec_info[codec_index].rate == 0 || + machine->codec_info[codec_index].channels == 0) return -EINVAL; tegra30_make_voice_call_connections( - &machine->codec_info[HIFI_CODEC], + &machine->codec_info[codec_index], &machine->codec_info[BASEBAND]); #endif } else { #ifndef CONFIG_ARCH_TEGRA_2x_SOC tegra30_break_voice_call_connections( - &machine->codec_info[HIFI_CODEC], + &machine->codec_info[codec_index], &machine->codec_info[BASEBAND]); #endif } @@ -532,6 +539,8 @@ static int tegra_voice_call_hw_params(struct snd_pcm_substream *substream, machine->codec_info[BASEBAND].is_format_dsp = 1; #endif + machine->is_device_bt = 0; + return 0; } @@ -549,6 +558,80 @@ static int tegra_voice_call_shutdown(struct snd_pcm_substream *substream) return 0; } +static int tegra_bt_voice_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_card *card = rtd->card; + struct tegra_max98088 *machine = snd_soc_card_get_drvdata(card); + int err, srate, mclk, min_mclk; + + srate = params_rate(params); + switch (srate) { + case 11025: + case 22050: + case 44100: + case 88200: + mclk = 11289600; + break; + case 8000: + case 16000: + case 32000: + case 48000: + case 64000: + case 96000: + mclk = 12288000; + break; + default: + return -EINVAL; + } + min_mclk = 64 * srate; + + err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk); + if (err < 0) { + if (!(machine->util_data.set_mclk % min_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); + +#ifndef CONFIG_ARCH_TEGRA_2x_SOC + /* 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; + + return 0; +} + +static int tegra_bt_voice_call_shutdown(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct tegra_max98088 *machine = + snd_soc_card_get_drvdata(rtd->codec->card); + +#ifndef CONFIG_ARCH_TEGRA_2x_SOC + machine->codec_info[BT_SCO].rate = 0; + machine->codec_info[BT_SCO].channels = 0; +#endif + + return 0; +} + static struct snd_soc_ops tegra_max98088_ops = { .hw_params = tegra_max98088_hw_params, .hw_free = tegra_hw_free, @@ -569,6 +652,12 @@ static struct snd_soc_ops tegra_voice_call_ops = { .hw_free = tegra_hw_free, }; +static struct snd_soc_ops tegra_bt_voice_call_ops = { + .hw_params = tegra_bt_voice_call_hw_params, + .shutdown = tegra_bt_voice_call_shutdown, + .hw_free = tegra_hw_free, +}; + static struct snd_soc_ops tegra_bt_ops = { .hw_params = tegra_bt_hw_params, .hw_free = tegra_hw_free, @@ -823,7 +912,6 @@ static struct snd_soc_dai_link tegra_max98088_dai[NUM_DAI_LINKS] = { .stream_name = "BT SCO PCM", .codec_name = "spdif-dit.1", .platform_name = "tegra-pcm-audio", - .cpu_dai_name = "tegra30-i2s.3", .codec_dai_name = "dit-hifi", .init = tegra_max98088_init, .ops = &tegra_bt_ops, @@ -837,6 +925,15 @@ static struct snd_soc_dai_link tegra_max98088_dai[NUM_DAI_LINKS] = { .codec_dai_name = "HiFi", .ops = &tegra_voice_call_ops, }, + [DAI_LINK_BT_VOICE_CALL] = { + .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_voice_call_ops, + }, }; static struct snd_soc_card snd_soc_tegra_max98088 = { @@ -893,6 +990,9 @@ static __devinit int tegra_max98088_driver_probe(struct platform_device *pdev) tegra_max98088_dai[DAI_LINK_HIFI].cpu_dai_name = tegra_max98088_i2s_dai_name[machine->codec_info[HIFI_CODEC].i2s_id]; + + tegra_max98088_dai[DAI_LINK_BTSCO].cpu_dai_name = + tegra_max98088_i2s_dai_name[machine->codec_info[BT_SCO].i2s_id]; #endif ret = snd_soc_register_card(card); |