From 94dc32841c85c112ca24dfbbe76dea7f3ed371c3 Mon Sep 17 00:00:00 2001 From: Nitin Pai Date: Fri, 6 Jul 2012 16:31:11 +0530 Subject: asoc: tegra: p852: Added machine driver for P852 Renamed P1852 machine driver to VCM so that can be used for P1852/P852 and E1853 as well. Bug 1008391 Signed-off-by: Nitin Pai Reviewed-on: http://git-master/r/113886 (cherry picked from commit 5eb23e30bab716b28146b85438989e58761c7136) Change-Id: I8d1363a6419c6381b8d23ebd38d625fb482084dc Reviewed-on: http://git-master/r/116056 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Scott Peterson --- sound/soc/tegra/Makefile | 5 +- sound/soc/tegra/tegra_p1852.c | 303 ---------------------------------------- sound/soc/tegra/tegra_vcm.c | 312 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 315 insertions(+), 305 deletions(-) delete mode 100644 sound/soc/tegra/tegra_p1852.c create mode 100644 sound/soc/tegra/tegra_vcm.c (limited to 'sound/soc/tegra') diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile index 7af02a69b8ae..83f30054a085 100644 --- a/sound/soc/tegra/Makefile +++ b/sound/soc/tegra/Makefile @@ -33,7 +33,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_TRIMSLICE) += snd-soc-tegra-trimslice.o @@ -42,4 +42,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/tegra_p1852.c b/sound/soc/tegra/tegra_p1852.c deleted file mode 100644 index 199bb8046636..000000000000 --- a/sound/soc/tegra/tegra_p1852.c +++ /dev/null @@ -1,303 +0,0 @@ -/* - * tegra_p1852.c - Tegra machine ASoC driver for P1852 Boards. - * - * Author: Nitin Pai - * Copyright (C) 2010-2012 - NVIDIA, Inc. - * - * Based on code copyright/by: - * Copyright (c) 2009-2010, NVIDIA Corporation. - * Stephen Warren - * - * 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. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include - -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include "tegra_pcm.h" -#include "tegra_asoc_utils.h" - -#define DRV_NAME "tegra-snd-p1852" - -struct tegra_p1852 { - struct tegra_asoc_utils_data util_data; - struct tegra_p1852_platform_data *pdata; -}; - -static int tegra_p1852_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - int codec_id) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - 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); - int srate, mclk; - int i2s_daifmt = 0; - int err; - struct tegra_p1852_platform_data *pdata; - - pdata = machine->pdata; - - srate = params_rate(params); - switch (srate) { - case 64000: - case 88200: - case 96000: - mclk = 128 * srate; - break; - default: - mclk = 256 * srate; - 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); - - if (pdata->codec_info[codec_id].master) - i2s_daifmt |= SND_SOC_DAIFMT_CBM_CFM; - else - i2s_daifmt |= SND_SOC_DAIFMT_CBS_CFS; - - switch (pdata->codec_info[codec_id].i2s_format) { - case format_tdm: - i2s_daifmt |= SND_SOC_DAIFMT_DSP_A; - break; - case format_i2s: - i2s_daifmt |= SND_SOC_DAIFMT_I2S; - break; - case format_rjm: - i2s_daifmt |= SND_SOC_DAIFMT_RIGHT_J; - break; - case format_ljm: - i2s_daifmt |= SND_SOC_DAIFMT_LEFT_J; - break; - default: - break; - } - - err = snd_soc_dai_set_fmt(codec_dai, i2s_daifmt); - if (err < 0) - dev_info(card->dev, "codec_dai fmt not set\n"); - - 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); - if (err < 0) - dev_info(card->dev, "codec_dai clock not set\n"); - - if (pdata->codec_info[codec_id].i2s_format == - format_tdm) { - err = snd_soc_dai_set_tdm_slot(cpu_dai, - pdata->codec_info[codec_id].rx_mask, - pdata->codec_info[codec_id].tx_mask, - pdata->codec_info[codec_id].num_slots, - pdata->codec_info[codec_id].slot_width); - if (err < 0) - dev_err(card->dev, "cpu_dai tdm mode setting not done\n"); - } - - return 0; -} - -static int tegra_p1852_hw_params_controller1( - struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - return tegra_p1852_hw_params(substream, params, 0); -} - -static int tegra_p1852_hw_params_controller2( - struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - return tegra_p1852_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); - - 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, - .hw_free = tegra_hw_free, -}; -static struct snd_soc_ops tegra_p1852_ops_controller2 = { - .hw_params = tegra_p1852_hw_params_controller2, - .hw_free = tegra_hw_free, -}; - -static struct snd_soc_dai_link tegra_p1852_dai_link[] = { - { - .name = "I2S-TDM-1", - .stream_name = "TEGRA PCM", - .platform_name = "tegra-pcm-audio", - .ops = &tegra_p1852_ops_controller1, - }, - { - .name = "I2S-TDM-2", - .stream_name = "TEGRA PCM", - .platform_name = "tegra-pcm-audio", - .ops = &tegra_p1852_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 __devinit int tegra_p1852_driver_probe(struct platform_device *pdev) -{ - struct snd_soc_card *card = &snd_soc_tegra_p1852; - struct tegra_p1852 *machine; - struct tegra_p1852_platform_data *pdata; - int ret; - int i; - - pdata = pdev->dev.platform_data; - if (!pdata) { - dev_err(&pdev->dev, "No platform data supplied\n"); - return -EINVAL; - } - - machine = kzalloc(sizeof(struct tegra_p1852), GFP_KERNEL); - if (!machine) { - dev_err(&pdev->dev, "Can't allocate tegra_p1852 struct\n"); - return -ENOMEM; - } - - machine->pdata = pdata; - - /* 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 = - pdata->codec_info[i].codec_name; - tegra_p1852_dai_link[i].cpu_dai_name = - pdata->codec_info[i].cpu_dai_name; - tegra_p1852_dai_link[i].codec_dai_name = - pdata->codec_info[i].codec_dai_name; - tegra_p1852_dai_link[i].name = - pdata->codec_info[i].name; - if (pdata->codec_info[i].pcm_driver) - tegra_p1852_dai_link[i].platform_name = - pdata->codec_info[i].pcm_driver; - } - - ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev, card); - if (ret) - goto err_free_machine; - - card->dev = &pdev->dev; - platform_set_drvdata(pdev, card); - snd_soc_card_set_drvdata(card, machine); - - ret = snd_soc_register_card(card); - if (ret) { - dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", - ret); - } - - if (!card->instantiated) { - ret = -ENODEV; - dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", - ret); - goto err_unregister_card; - } - - return 0; - -err_unregister_card: - snd_soc_unregister_card(card); - tegra_asoc_utils_fini(&machine->util_data); -err_free_machine: - kfree(machine); - return ret; -} - -static int __devexit tegra_p1852_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); - - snd_soc_unregister_card(card); - tegra_asoc_utils_fini(&machine->util_data); - kfree(machine); - - return 0; -} - -static struct platform_driver tegra_p1852_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), -}; - -static int __init tegra_p1852_modinit(void) -{ - return platform_driver_register(&tegra_p1852_driver); -} -module_init(tegra_p1852_modinit); - -static void __exit tegra_p1852_modexit(void) -{ - platform_driver_unregister(&tegra_p1852_driver); -} -module_exit(tegra_p1852_modexit); - -MODULE_AUTHOR("Nitin Pai "); -MODULE_DESCRIPTION("Tegra+P1852 machine ASoC driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:" DRV_NAME); diff --git a/sound/soc/tegra/tegra_vcm.c b/sound/soc/tegra/tegra_vcm.c new file mode 100644 index 000000000000..afb444e3f19f --- /dev/null +++ b/sound/soc/tegra/tegra_vcm.c @@ -0,0 +1,312 @@ +/* + * tegra_vcm.c - Tegra machine ASoC driver for P852/P1852/P1853 Boards. + * + * Author: Nitin Pai + * Copyright (C) 2010-2012 - NVIDIA, Corporation. All rights reserved. + * + * Based on code copyright/by: + * Copyright (c) 2009-2010, NVIDIA Corporation. + * Stephen Warren + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#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_vcm { + struct tegra_asoc_utils_data util_data; + struct tegra_p1852_platform_data *pdata; +}; + +static int tegra_vcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + int codec_id) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + 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_vcm *machine = snd_soc_card_get_drvdata(card); + int srate, mclk; + int i2s_daifmt = 0; + int err; + struct tegra_p1852_platform_data *pdata; + + pdata = machine->pdata; + + srate = params_rate(params); + switch (srate) { + case 64000: + case 88200: + case 96000: + mclk = 128 * srate; + break; + default: + mclk = 256 * srate; + 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); + + if (pdata->codec_info[codec_id].master) + i2s_daifmt |= SND_SOC_DAIFMT_CBM_CFM; + else + i2s_daifmt |= SND_SOC_DAIFMT_CBS_CFS; + + switch (pdata->codec_info[codec_id].i2s_format) { + case format_tdm: + i2s_daifmt |= SND_SOC_DAIFMT_DSP_A; + break; + case format_i2s: + i2s_daifmt |= SND_SOC_DAIFMT_I2S; + break; + case format_rjm: + i2s_daifmt |= SND_SOC_DAIFMT_RIGHT_J; + break; + case format_ljm: + i2s_daifmt |= SND_SOC_DAIFMT_LEFT_J; + break; + default: + break; + } + + err = snd_soc_dai_set_fmt(codec_dai, i2s_daifmt); + if (err < 0) + dev_info(card->dev, "codec_dai fmt not set\n"); + + 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); + if (err < 0) + dev_info(card->dev, "codec_dai clock not set\n"); + + if (pdata->codec_info[codec_id].i2s_format == + format_tdm) { + err = snd_soc_dai_set_tdm_slot(cpu_dai, + pdata->codec_info[codec_id].rx_mask, + pdata->codec_info[codec_id].tx_mask, + pdata->codec_info[codec_id].num_slots, + pdata->codec_info[codec_id].slot_width); + if (err < 0) + dev_err(card->dev, "cpu_dai tdm mode setting not done\n"); + } + + return 0; +} + +static int tegra_vcm_hw_params_controller1( + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + return tegra_vcm_hw_params(substream, params, 0); +} + +static int tegra_vcm_hw_params_controller2( + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + 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_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_vcm_ops_controller1 = { + .hw_params = tegra_vcm_hw_params_controller1, + .hw_free = tegra_hw_free, +}; +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_vcm_dai_link[] = { + { + .name = "I2S-TDM-1", + .stream_name = "TEGRA PCM", + .platform_name = "tegra-pcm-audio", + .ops = &tegra_vcm_ops_controller1, + }, + { + .name = "I2S-TDM-2", + .stream_name = "TEGRA PCM", + .platform_name = "tegra-pcm-audio", + .ops = &tegra_vcm_ops_controller2, + } +}; + +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_vcm_driver_probe(struct platform_device *pdev) +{ + struct snd_soc_card *card = &snd_soc_tegra_vcm; + struct tegra_vcm *machine; + struct tegra_p1852_platform_data *pdata; + int ret; + int i; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "No platform data supplied\n"); + return -EINVAL; + } + + machine = kzalloc(sizeof(struct tegra_vcm), GFP_KERNEL); + if (!machine) { + dev_err(&pdev->dev, "Can't allocate tegra_vcm struct\n"); + return -ENOMEM; + } + + machine->pdata = pdata; + + /* The codec driver and codec dai have to come from the system + * level board configuration file + * */ + 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_vcm_dai_link[i].cpu_dai_name = + pdata->codec_info[i].cpu_dai_name; + tegra_vcm_dai_link[i].codec_dai_name = + pdata->codec_info[i].codec_dai_name; + tegra_vcm_dai_link[i].name = + pdata->codec_info[i].name; + if (pdata->codec_info[i].pcm_driver) + tegra_vcm_dai_link[i].platform_name = + pdata->codec_info[i].pcm_driver; + } + + ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev, card); + if (ret) + goto err_free_machine; + + card->dev = &pdev->dev; + platform_set_drvdata(pdev, card); + snd_soc_card_set_drvdata(card, machine); + + ret = snd_soc_register_card(card); + if (ret) { + dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", + ret); + } + + if (!card->instantiated) { + ret = -ENODEV; + dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", + ret); + goto err_unregister_card; + } + + return 0; + +err_unregister_card: + snd_soc_unregister_card(card); + tegra_asoc_utils_fini(&machine->util_data); +err_free_machine: + kfree(machine); + return ret; +} + +static int __devexit tegra_vcm_driver_remove(struct platform_device *pdev) +{ + struct snd_soc_card *card = platform_get_drvdata(pdev); + struct tegra_vcm *machine = snd_soc_card_get_drvdata(card); + + snd_soc_unregister_card(card); + tegra_asoc_utils_fini(&machine->util_data); + kfree(machine); + + return 0; +} + +static struct platform_driver tegra_vcm_driver = { + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + .pm = &snd_soc_pm_ops, + }, + .probe = tegra_vcm_driver_probe, + .remove = __devexit_p(tegra_vcm_driver_remove), +}; + +static int __init tegra_vcm_modinit(void) +{ + return platform_driver_register(&tegra_vcm_driver); +} +module_init(tegra_vcm_modinit); + +static void __exit tegra_vcm_modexit(void) +{ + platform_driver_unregister(&tegra_vcm_driver); +} +module_exit(tegra_vcm_modexit); + +MODULE_AUTHOR("Nitin Pai "); +MODULE_DESCRIPTION("Tegra+VCM machine ASoC driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:" DRV_NAME); -- cgit v1.2.3 From 4b70cc537cadc787b748c7c246d703a240b08985 Mon Sep 17 00:00:00 2001 From: Ankit Gupta Date: Wed, 11 Jul 2012 20:50:01 +0530 Subject: asoc: tegra: integration of slave mode support. Add master/slave configurability support interface for all codecs. Currently, complete slave mode functionality is added only for MAX98088 and WM8903 codec only. By default, board parameters will set i2s master mode for all codecs. asoc: tegra: utils: add support for i2s master/slave mode. Support for i2s in master or slave mode is made generic by obtaining information from platform data. Signed-off-by: Ankit Gupta Change-Id: Ided0fcefb6cdb124b78aab423bfd8c7dccd4bf6e Reviewed-on: http://git-master/r/111553 (cherry picked from commit bb1ad7222f9c75424a45976d16de418bc927dc04) asoc: tegra: wm8903 machine: add support for i2s in slave mode. Add support for i2s as slave for playback and capture use cases. Signed-off-by: Ankit Gupta Change-Id: I1f6b73a0a1b690ecd311b0ff4107aadbb1f037d8 Reviewed-on: http://git-master/r/111472 (cherry picked from commit 0434f8ba74adefe60597d95d30a455b9b2ece9b8) asoc: tegra: wm8753 machine: add support for i2s in slave mode. Add support for i2s as slave for playback and capture use cases. Signed-off-by: Ankit Gupta Change-Id: Ib0596955cd0c6ac5ec57b0f3c6ecc9e4ed41268c Reviewed-on: http://git-master/r/113208 (cherry picked from commit 0fc6b5e3a98d9f8866f73d7914b0c590334ce862) asoc: tegra: aic326x machine: add support for i2s in slave mode. Support for i2s in slave mode is added for playabck and capture use cases. Signed-off-by: Ankit Gupta Change-Id: I41f6459765f075703ad7f5f8dc9d4628dd853820 Reviewed-on: http://git-master/r/112874 (cherry picked from commit 9a89ede36a1dca6f53250444e819443fb6f28d09) asoc: tegra: rt5640 machine: add support for i2s in slave mode. Add support for i2s as slave for playback and capture use cases. Signed-off-by: Ankit Gupta Change-Id: I850ec62149b8a8d244445b70658b632dbce06558 Reviewed-on: http://git-master/r/112878 (cherry picked from commit 1d51561c8edf47d8557a825450a48ee8743a185b) asoc: tegra: max98088 machine: add support for codec i2s as slave. Add support for codec i2s as slave during voice Call. (Bug 998682) Signed-off-by: Ankit Gupta Change-Id: I8fc54d367e9acd5417d270869cb5a9398b3b527f Reviewed-on: http://git-master/r/110559 (cherry picked from commit 78a490867e131b1cc892094ddd844c2b892cafb6) asoc: tegra: max98095 machine: add support for i2s in slave mode. Add support for i2s as slave for playback and capture use cases. Signed-off-by: Ankit Gupta Change-Id: I80944d403be94c55ad2ce31aea921d80ea7c088a Reviewed-on: http://git-master/r/112875 Reviewed-on: http://git-master/r/118080 Reviewed-by: Scott Peterson Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Sumit Bhattacharya --- sound/soc/tegra/tegra_aic326x.c | 173 +++++++++++++++++++++++---------- sound/soc/tegra/tegra_asoc_utils.c | 53 +++++----- sound/soc/tegra/tegra_asoc_utils.h | 11 ++- sound/soc/tegra/tegra_max98088.c | 193 ++++++++++++++++++++++++------------- sound/soc/tegra/tegra_max98095.c | 57 ++++++++--- sound/soc/tegra/tegra_rt5640.c | 103 +++++++++++++++----- sound/soc/tegra/tegra_wm8753.c | 88 ++++++++++++++--- sound/soc/tegra/tegra_wm8903.c | 132 ++++++++++++++++--------- 8 files changed, 570 insertions(+), 240 deletions(-) (limited to 'sound/soc/tegra') diff --git a/sound/soc/tegra/tegra_aic326x.c b/sound/soc/tegra/tegra_aic326x.c index 4cacb6758eb8..a809d4c74145 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 +#include #include #include #include @@ -274,8 +276,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 +297,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,20 +334,21 @@ 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; @@ -390,7 +415,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 +449,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 +672,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 +681,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,25 +723,15 @@ 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; @@ -691,14 +760,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 +815,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; @@ -1183,11 +1236,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]; @@ -1214,6 +1279,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..2c18a71b8b52 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 - * 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. @@ -340,28 +339,6 @@ int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data, ret = PTR_ERR(data->clk_out1); goto err_put_cdev1; } -#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); @@ -402,6 +379,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..ce379e3e513d 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 - * 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 @@ -47,11 +46,13 @@ struct tegra_asoc_utils_data { }; 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..f77c327b4b00 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 +#include #include #include #include @@ -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_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 +#include #include #include #include @@ -37,7 +39,7 @@ #include #endif -#include +#include #include #include @@ -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_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 +#include #include #include #include @@ -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 #endif -#include +#include #include #include @@ -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, -- cgit v1.2.3 From cfb86bf491e3cf6baad2f164fae4880185f0e22c Mon Sep 17 00:00:00 2001 From: Nitin Pai Date: Mon, 2 Jul 2012 14:02:31 +0530 Subject: asoc: tegra: i2s: Fixes for audio_clock_2x rate audio_clock_2x parent needs to be set first before changing the rate, else it will not work. Bug 1019017 Signed-off-by: Nitin Pai Reviewed-on: http://git-master/r/116682 (cherry picked from commit fdc4da6d96e7be4aa2accf098de48543e745cf11) Change-Id: I93aeb1afed8732e8a1b1cff4ab03b9a9f654804f Reviewed-on: http://git-master/r/118250 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Bob Johnston Reviewed-by: Varun Wadekar --- sound/soc/tegra/tegra30_i2s.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'sound/soc/tegra') 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"); -- cgit v1.2.3 From c5dea888253285e23107585805b7728ebe46e17e Mon Sep 17 00:00:00 2001 From: Rhyland Klein Date: Thu, 2 Aug 2012 15:27:53 -0400 Subject: asoc: tegra: fix compilation error in max98095 change 4b70cc537cadc787b748c7c246d703a240b08985 introduced a compilation error. Signed-off-by: Rhyland Klein Change-Id: I59e54537d9bb4b30e807478e5b7634db0813a739 Reviewed-on: http://git-master/r/120443 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Ankit Gupta (Engrg-SW) Reviewed-by: Scott Peterson --- sound/soc/tegra/tegra_max98095.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc/tegra') diff --git a/sound/soc/tegra/tegra_max98095.c b/sound/soc/tegra/tegra_max98095.c index f77c327b4b00..1d03980f276f 100644 --- a/sound/soc/tegra/tegra_max98095.c +++ b/sound/soc/tegra/tegra_max98095.c @@ -157,7 +157,7 @@ static int tegra_max98095_hw_params(struct snd_pcm_substream *substream, } i2s_daifmt = SND_SOC_DAIFMT_NB_NF; - i2s_daifmt |= pdata->i2s_param[HIFI_CODEC].is_i2s_master; ? + 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) { -- cgit v1.2.3 From 554ff140ba7b0c4d7ba5b548689776cf284d0c8a Mon Sep 17 00:00:00 2001 From: Manoj Gangwal Date: Fri, 24 Aug 2012 12:38:38 +0530 Subject: asoc: aic326x machine: Add supp. for new TI driver Add support for latest TI codec aic326x driver. Bug 1034241 Change-Id: I387693ed2de466d1704c6f7ff0a1b15c7cbff32f Signed-off-by: Manoj Gangwal Reviewed-on: http://git-master/r/125180 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Lokesh Pathak --- sound/soc/tegra/tegra_aic326x.c | 48 ++++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 17 deletions(-) (limited to 'sound/soc/tegra') diff --git a/sound/soc/tegra/tegra_aic326x.c b/sound/soc/tegra/tegra_aic326x.c index a809d4c74145..1b5598dc278c 100644 --- a/sound/soc/tegra/tegra_aic326x.c +++ b/sound/soc/tegra/tegra_aic326x.c @@ -44,6 +44,7 @@ #include #include #include +#include #include "../codecs/tlv320aic326x.h" @@ -354,6 +355,9 @@ static int tegra_aic326x_hw_params(struct snd_pcm_substream *substream, 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); @@ -737,7 +741,15 @@ static int tegra_aic326x_voice_call_hw_params( 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; @@ -889,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: @@ -975,10 +987,11 @@ 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"}, +/* {"CM1L" ,NULL, "Mic Jack"}, */ +/* {"IN1L", NULL, "Mic Bias Ext"}, */ +/* {"IN1L", NULL, "CM1L"}, */ }; static const struct snd_kcontrol_new tegra_aic326x_controls[] = { @@ -1105,7 +1118,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 */ @@ -1119,9 +1133,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; } @@ -1130,14 +1144,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, }, @@ -1171,10 +1185,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] = { @@ -1261,10 +1275,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); -- cgit v1.2.3 From 3745839f5f25ac8de101827813bf305476033d35 Mon Sep 17 00:00:00 2001 From: Manoj Gangwal Date: Wed, 22 Aug 2012 22:18:44 +0530 Subject: asoc: aic326x machine: Add support for D-Mic Bug 1034241 Change-Id: I205a74a8f27237470a3cd1266bb925971654459c Signed-off-by: Manoj Gangwal Reviewed-on: http://git-master/r/125280 Reviewed-by: Simone Willett Tested-by: Simone Willett --- sound/soc/tegra/tegra_aic326x.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'sound/soc/tegra') diff --git a/sound/soc/tegra/tegra_aic326x.c b/sound/soc/tegra/tegra_aic326x.c index 1b5598dc278c..de4a1457a7ae 100644 --- a/sound/soc/tegra/tegra_aic326x.c +++ b/sound/soc/tegra/tegra_aic326x.c @@ -973,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[] = { @@ -989,6 +990,10 @@ static const struct snd_soc_dapm_route aic326x_audio_map[] = { {"IN2R", NULL, "Mic Bias Int"}, {"IN1L", NULL, "Mic Bias Ext"}, {"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"}, */ -- cgit v1.2.3 From 49553e9c6dd0ef9dac304adc69c676b0b000d31f Mon Sep 17 00:00:00 2001 From: Sumit Bhattacharya Date: Mon, 27 Aug 2012 16:07:39 +0800 Subject: ASoC: Tegra: Add ALSA ctl to set DMA address Add support for setting of DMA address through alsa control for AVP rendering. This is required to directly do DMA from IRAM to I2S. Bug 1024403 Change-Id: I6b79ae6e9a562160a19d238b817e1a8b407ac208 Signed-off-by: Sumit Bhattacharya Reviewed-on: http://git-master/r/127436 (cherry picked from commit f270f46bef98a56f44432e608041adb617c22559) Signed-off-by: Chandrakanth Gorantla Change-Id: I195aae9043f967273283579f44d5367fe73d542f Reviewed-on: http://git-master/r/129159 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Scott Peterson --- sound/soc/tegra/tegra_asoc_utils.c | 41 +++++++++++++++++++++++++++++++++++--- sound/soc/tegra/tegra_asoc_utils.h | 1 + sound/soc/tegra/tegra_pcm.c | 6 +++++- sound/soc/tegra/tegra_pcm.h | 1 + 4 files changed, 45 insertions(+), 4 deletions(-) (limited to 'sound/soc/tegra') diff --git a/sound/soc/tegra/tegra_asoc_utils.c b/sound/soc/tegra/tegra_asoc_utils.c index 2c18a71b8b52..80d22d203fb6 100644 --- a/sound/soc/tegra/tegra_asoc_utils.c +++ b/sound/soc/tegra/tegra_asoc_utils.c @@ -86,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; @@ -121,6 +124,30 @@ 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; + + 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) { @@ -128,6 +155,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) @@ -138,7 +166,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; } @@ -148,7 +183,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, diff --git a/sound/soc/tegra/tegra_asoc_utils.h b/sound/soc/tegra/tegra_asoc_utils.h index ce379e3e513d..cd137967fcb0 100644 --- a/sound/soc/tegra/tegra_asoc_utils.h +++ b/sound/soc/tegra/tegra_asoc_utils.h @@ -43,6 +43,7 @@ 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, diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c index f471fafff2ac..a7c9c0a110f9 100644 --- a/sound/soc/tegra/tegra_pcm.c +++ b/sound/soc/tegra/tegra_pcm.c @@ -70,7 +70,11 @@ static void tegra_pcm_queue_dma(struct tegra_runtime_data *prtd) if (++prtd->dma_req_idx >= prtd->dma_req_count) prtd->dma_req_idx -= prtd->dma_req_count; - 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; + prtd->dma_pos += dma_req->size; if (prtd->dma_pos >= prtd->dma_pos_end) prtd->dma_pos = 0; 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); -- cgit v1.2.3 From b02a1cb7dbb6b0815ddd8e104ad8819e847947a0 Mon Sep 17 00:00:00 2001 From: Shashank Sharma Date: Fri, 28 Sep 2012 16:29:24 +0530 Subject: asoc: tegra: WAR: Check AVP id before setting DMA WAR to check souncard data's avp_id before trying to set DMA address. An invalid avp_id can cause invlaid rtd, causing panic in control ioctl calls. Bug 1046249 Bug 1044761 Bug 1049940 Bug 1050152 Change-Id: Ib536220fdb92f8256c777d6fa14b66e47bc6b7be Signed-off-by: Shashank Sharma Reviewed-on: http://git-master/r/134426 (cherry picked from commit 007fd7b1ae101c5be2a3d35ad11e7190862c04ca) Reviewed-on: http://git-master/r/142493 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Tested-by: Matthew Pedro Reviewed-by: Winnie Hsu --- sound/soc/tegra/tegra_asoc_utils.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'sound/soc/tegra') diff --git a/sound/soc/tegra/tegra_asoc_utils.c b/sound/soc/tegra/tegra_asoc_utils.c index 80d22d203fb6..99ba90d9fc7b 100644 --- a/sound/soc/tegra/tegra_asoc_utils.c +++ b/sound/soc/tegra/tegra_asoc_utils.c @@ -133,6 +133,9 @@ static int tegra_set_dma_addr(struct snd_kcontrol *kcontrol, 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]; -- cgit v1.2.3