summaryrefslogtreecommitdiff
path: root/sound/soc/tegra
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/tegra')
-rw-r--r--sound/soc/tegra/tegra_aic326x.c173
-rw-r--r--sound/soc/tegra/tegra_asoc_utils.c53
-rw-r--r--sound/soc/tegra/tegra_asoc_utils.h11
-rw-r--r--sound/soc/tegra/tegra_max98088.c193
-rw-r--r--sound/soc/tegra/tegra_max98095.c57
-rw-r--r--sound/soc/tegra/tegra_rt5640.c103
-rw-r--r--sound/soc/tegra/tegra_wm8753.c88
-rw-r--r--sound/soc/tegra/tegra_wm8903.c132
8 files changed, 570 insertions, 240 deletions
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 <asm/mach-types.h>
+#include <linux/clk.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
@@ -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 <swarren@nvidia.com>
- * Copyright (C) 2010 - NVIDIA, Inc.
- *
+ * Copyright (c) 2010-12, NVIDIA CORPORATION. All rights reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
@@ -342,28 +341,6 @@ int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data,
}
#endif
-#if !defined(CONFIG_ARCH_TEGRA_2x_SOC)
-#if TEGRA30_I2S_MASTER_PLAYBACK
- ret = clk_set_parent(data->clk_cdev1, data->clk_pll_a_out0);
- if (ret) {
- dev_err(data->dev, "Can't set clk cdev1/extern1 parent");
- goto err_put_out1;
- }
-#else
- rate = clk_get_rate(data->clk_m);
-
- if(rate == 26000000)
- clk_set_rate(data->clk_cdev1, 13000000);
-
- ret = clk_set_parent(data->clk_cdev1, data->clk_m);
- if (ret) {
- dev_err(data->dev, "Can't set clk cdev1/extern1 parent");
- goto err_put_out1;
- }
-#endif
-
-#endif
-
ret = clk_enable(data->clk_cdev1);
if (ret) {
dev_err(data->dev, "Can't enable clk cdev1/extern1");
@@ -402,6 +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 <swarren@nvidia.com>
- * Copyright (C) 2010 - NVIDIA, Inc.
+ * Copyright (c) 2010-12, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -24,7 +24,6 @@
#define __TEGRA_ASOC_UTILS_H_
-#define TEGRA30_I2S_MASTER_PLAYBACK 1
#define TEGRA_ALSA_MAX_DEVICES 6
#define TEGRA_DMA_MAX_CHANNELS 32
@@ -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 <asm/mach-types.h>
+#include <linux/clk.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
@@ -118,11 +119,12 @@ static int tegra_max98095_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_card *card = codec->card;
struct tegra_max98095 *machine = snd_soc_card_get_drvdata(card);
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
#ifndef CONFIG_ARCH_TEGRA_2x_SOC
struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(cpu_dai);
#endif
- unsigned int srate, mclk, sample_size;
- int err;
+ unsigned int srate, mclk, sample_size, i2s_daifmt;
+ int err, rate;
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
@@ -154,6 +156,31 @@ static int tegra_max98095_hw_params(struct snd_pcm_substream *substream,
break;
}
+ i2s_daifmt = SND_SOC_DAIFMT_NB_NF;
+ i2s_daifmt |= pdata->i2s_param[HIFI_CODEC].is_i2s_master; ?
+ SND_SOC_DAIFMT_CBS_CFS : SND_SOC_DAIFMT_CBM_CFM;
+
+ switch (pdata->i2s_param[HIFI_CODEC].i2s_mode) {
+ case TEGRA_DAIFMT_I2S :
+ i2s_daifmt |= SND_SOC_DAIFMT_I2S;
+ break;
+ case TEGRA_DAIFMT_DSP_A :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_A;
+ break;
+ case TEGRA_DAIFMT_DSP_B :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_B;
+ break;
+ case TEGRA_DAIFMT_LEFT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_LEFT_J;
+ break;
+ case TEGRA_DAIFMT_RIGHT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_RIGHT_J;
+ break;
+ default :
+ dev_err(card->dev, "Can't configure i2s format\n");
+ return -EINVAL;
+ }
+
err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
if (err < 0) {
if (!(machine->util_data.set_mclk % mclk))
@@ -166,26 +193,20 @@ static int tegra_max98095_hw_params(struct snd_pcm_substream *substream,
tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
- err = snd_soc_dai_set_fmt(codec_dai,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS);
+ rate = clk_get_rate(machine->util_data.clk_cdev1);
+ err = snd_soc_dai_set_fmt(codec_dai, i2s_daifmt);
if (err < 0) {
dev_err(card->dev, "codec_dai fmt not set\n");
return err;
}
- err = snd_soc_dai_set_fmt(cpu_dai,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS);
+ err = snd_soc_dai_set_fmt(cpu_dai, i2s_daifmt);
if (err < 0) {
dev_err(card->dev, "cpu_dai fmt not set\n");
return err;
}
- err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
- SND_SOC_CLOCK_IN);
+ err = snd_soc_dai_set_sysclk(codec_dai, 0, rate, SND_SOC_CLOCK_IN);
if (err < 0) {
dev_err(card->dev, "codec_dai clock not set\n");
return err;
@@ -667,6 +688,16 @@ static __devinit int tegra_max98095_driver_probe(struct platform_device *pdev)
goto err_unregister_card;
}
+#ifndef CONFIG_ARCH_TEGRA_2x_SOC
+ ret = tegra_asoc_utils_set_parent(&machine->util_data,
+ pdata->i2s_param[HIFI_CODEC].is_i2s_master);
+ if (ret) {
+ dev_err(&pdev->dev, "tegra_asoc_utils_set_parent failed (%d)\n",
+ ret);
+ goto err_switch_unregister;
+ }
+#endif
+
return 0;
err_unregister_card:
diff --git a/sound/soc/tegra/tegra_rt5640.c b/sound/soc/tegra/tegra_rt5640.c
index 765eb59fabae..a99711fb9234 100644
--- a/sound/soc/tegra/tegra_rt5640.c
+++ b/sound/soc/tegra/tegra_rt5640.c
@@ -10,6 +10,7 @@
* Author: Graeme Gregory
* graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
*
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
@@ -28,6 +29,7 @@
#include <asm/mach-types.h>
+#include <linux/clk.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
@@ -37,7 +39,7 @@
#include <linux/switch.h>
#endif
-#include <mach/tegra_rt5640_pdata.h>
+#include <mach/tegra_asoc_pdata.h>
#include <sound/core.h>
#include <sound/jack.h>
@@ -61,7 +63,7 @@
struct tegra_rt5640 {
struct tegra_asoc_utils_data util_data;
- struct tegra_rt5640_platform_data *pdata;
+ struct tegra_asoc_platform_data *pdata;
struct regulator *spk_reg;
struct regulator *dmic_reg;
struct regulator *cdc_en;
@@ -82,11 +84,38 @@ static int tegra_rt5640_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_card *card = codec->card;
struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
int srate, mclk, i2s_daifmt;
- int err;
+ int err, rate;
srate = params_rate(params);
mclk = 256 * srate;
+
+ i2s_daifmt = SND_SOC_DAIFMT_NB_NF;
+ i2s_daifmt |= pdata->i2s_param[HIFI_CODEC].is_i2s_master ?
+ SND_SOC_DAIFMT_CBS_CFS : SND_SOC_DAIFMT_CBM_CFM;
+
+ switch (pdata->i2s_param[HIFI_CODEC].i2s_mode) {
+ case TEGRA_DAIFMT_I2S :
+ i2s_daifmt |= SND_SOC_DAIFMT_I2S;
+ break;
+ case TEGRA_DAIFMT_DSP_A :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_A;
+ break;
+ case TEGRA_DAIFMT_DSP_B :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_B;
+ break;
+ case TEGRA_DAIFMT_LEFT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_LEFT_J;
+ break;
+ case TEGRA_DAIFMT_RIGHT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_RIGHT_J;
+ break;
+ default :
+ dev_err(card->dev, "Can't configure i2s format\n");
+ return -EINVAL;
+ }
+
err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
if (err < 0) {
if (!(machine->util_data.set_mclk % mclk)) {
@@ -99,10 +128,7 @@ static int tegra_rt5640_hw_params(struct snd_pcm_substream *substream,
tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
- i2s_daifmt = SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS;
-
- i2s_daifmt |= SND_SOC_DAIFMT_I2S;
+ rate = clk_get_rate(machine->util_data.clk_cdev1);
err = snd_soc_dai_set_fmt(codec_dai, i2s_daifmt);
if (err < 0) {
@@ -116,8 +142,7 @@ static int tegra_rt5640_hw_params(struct snd_pcm_substream *substream,
return err;
}
- err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
- SND_SOC_CLOCK_IN);
+ err = snd_soc_dai_set_sysclk(codec_dai, 0, rate, SND_SOC_CLOCK_IN);
if (err < 0) {
dev_err(card->dev, "codec_dai clock not set\n");
return err;
@@ -130,10 +155,10 @@ static int tegra_bt_sco_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct snd_soc_card *card = rtd->card;
struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
- int srate, mclk, min_mclk;
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
+ int srate, mclk, min_mclk, i2s_daifmt;
int err;
srate = params_rate(params);
@@ -169,10 +194,32 @@ static int tegra_bt_sco_hw_params(struct snd_pcm_substream *substream,
tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
- err = snd_soc_dai_set_fmt(cpu_dai,
- SND_SOC_DAIFMT_DSP_A |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS);
+ i2s_daifmt = SND_SOC_DAIFMT_NB_NF;
+ i2s_daifmt |= pdata->i2s_param[BT_SCO].is_i2s_master ?
+ SND_SOC_DAIFMT_CBS_CFS : SND_SOC_DAIFMT_CBM_CFM;
+
+ switch (pdata->i2s_param[BT_SCO].i2s_mode) {
+ case TEGRA_DAIFMT_I2S :
+ i2s_daifmt |= SND_SOC_DAIFMT_I2S;
+ break;
+ case TEGRA_DAIFMT_DSP_A :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_A;
+ break;
+ case TEGRA_DAIFMT_DSP_B :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_B;
+ break;
+ case TEGRA_DAIFMT_LEFT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_LEFT_J;
+ break;
+ case TEGRA_DAIFMT_RIGHT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_RIGHT_J;
+ break;
+ default :
+ dev_err(card->dev, "Can't configure i2s format\n");
+ return -EINVAL;
+ }
+
+ err = snd_soc_dai_set_fmt(rtd->cpu_dai, i2s_daifmt);
if (err < 0) {
dev_err(card->dev, "cpu_dai fmt not set\n");
return err;
@@ -279,7 +326,7 @@ static int tegra_rt5640_jack_notifier(struct notifier_block *self,
struct snd_soc_codec *codec = jack->codec;
struct snd_soc_card *card = codec->card;
struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
- struct tegra_rt5640_platform_data *pdata = machine->pdata;
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
enum headset_state state = BIT_NO_HEADSET;
unsigned char status_jack = 0;
@@ -357,7 +404,7 @@ static int tegra_rt5640_event_int_spk(struct snd_soc_dapm_widget *w,
struct snd_soc_dapm_context *dapm = w->dapm;
struct snd_soc_card *card = dapm->card;
struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
- struct tegra_rt5640_platform_data *pdata = machine->pdata;
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
if (machine->spk_reg) {
if (SND_SOC_DAPM_EVENT_ON(event))
@@ -381,7 +428,7 @@ static int tegra_rt5640_event_hp(struct snd_soc_dapm_widget *w,
struct snd_soc_dapm_context *dapm = w->dapm;
struct snd_soc_card *card = dapm->card;
struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
- struct tegra_rt5640_platform_data *pdata = machine->pdata;
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
if (!(machine->gpio_requested & GPIO_HP_MUTE))
return 0;
@@ -398,7 +445,7 @@ static int tegra_rt5640_event_int_mic(struct snd_soc_dapm_widget *w,
struct snd_soc_dapm_context *dapm = w->dapm;
struct snd_soc_card *card = dapm->card;
struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
- struct tegra_rt5640_platform_data *pdata = machine->pdata;
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
if (machine->dmic_reg) {
if (SND_SOC_DAPM_EVENT_ON(event))
@@ -422,7 +469,7 @@ static int tegra_rt5640_event_ext_mic(struct snd_soc_dapm_widget *w,
struct snd_soc_dapm_context *dapm = w->dapm;
struct snd_soc_card *card = dapm->card;
struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
- struct tegra_rt5640_platform_data *pdata = machine->pdata;
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
if (!(machine->gpio_requested & GPIO_EXT_MIC_EN))
return 0;
@@ -467,7 +514,7 @@ static int tegra_rt5640_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_dapm_context *dapm = &codec->dapm;
struct snd_soc_card *card = codec->card;
struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
- struct tegra_rt5640_platform_data *pdata = machine->pdata;
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
int ret;
if (gpio_is_valid(pdata->gpio_spkr_en)) {
@@ -650,7 +697,7 @@ static __devinit int tegra_rt5640_driver_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &snd_soc_tegra_rt5640;
struct tegra_rt5640 *machine;
- struct tegra_rt5640_platform_data *pdata;
+ struct tegra_asoc_platform_data *pdata;
int ret;
pdata = pdev->dev.platform_data;
@@ -716,6 +763,16 @@ static __devinit int tegra_rt5640_driver_probe(struct platform_device *pdev)
goto err_unregister_card;
}
+#ifndef CONFIG_ARCH_TEGRA_2x_SOC
+ ret = tegra_asoc_utils_set_parent(&machine->util_data,
+ pdata->i2s_param[HIFI_CODEC].is_i2s_master);
+ if (ret) {
+ dev_err(&pdev->dev, "tegra_asoc_utils_set_parent failed (%d)\n",
+ ret);
+ goto err_unregister_card;
+ }
+#endif
+
return 0;
err_unregister_card:
@@ -735,7 +792,7 @@ static int __devexit tegra_rt5640_driver_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
- struct tegra_rt5640_platform_data *pdata = machine->pdata;
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
if (machine->gpio_requested & GPIO_HP_DET)
snd_soc_jack_free_gpios(&tegra_rt5640_hp_jack,
diff --git a/sound/soc/tegra/tegra_wm8753.c b/sound/soc/tegra/tegra_wm8753.c
index f7c7a4c6b5a1..f1b9335ab473 100644
--- a/sound/soc/tegra/tegra_wm8753.c
+++ b/sound/soc/tegra/tegra_wm8753.c
@@ -12,6 +12,7 @@
* Author: Graeme Gregory
* graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
*
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
@@ -30,6 +31,7 @@
#include <asm/mach-types.h>
+#include <linux/clk.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
@@ -83,8 +85,10 @@ static int tegra_wm8753_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_card *card = codec->card;
struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card);
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
int srate, mclk, i2s_daifmt;
- int err;
+ int err, rate;
+
srate = params_rate(params);
switch (srate) {
case 8000:
@@ -119,14 +123,38 @@ static int tegra_wm8753_hw_params(struct snd_pcm_substream *substream,
tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
- i2s_daifmt = SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS;
+ rate = clk_get_rate(machine->util_data.clk_cdev1);
+
+ i2s_daifmt = SND_SOC_DAIFMT_NB_NF;
+ i2s_daifmt |= pdata->i2s_param[HIFI_CODEC].is_i2s_master ?
+ SND_SOC_DAIFMT_CBS_CFS : SND_SOC_DAIFMT_CBM_CFM;
/* Use DSP mode for mono on Tegra20 */
- if ((params_channels(params) != 2) && machine_is_whistler())
+ if ((params_channels(params) != 2) && machine_is_whistler()) {
i2s_daifmt |= SND_SOC_DAIFMT_DSP_A;
- else
- i2s_daifmt |= SND_SOC_DAIFMT_I2S;
+ } else {
+ switch (pdata->i2s_param[HIFI_CODEC].i2s_mode) {
+ case TEGRA_DAIFMT_I2S :
+ i2s_daifmt |= SND_SOC_DAIFMT_I2S;
+ break;
+ case TEGRA_DAIFMT_DSP_A :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_A;
+ break;
+ case TEGRA_DAIFMT_DSP_B :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_B;
+ break;
+ case TEGRA_DAIFMT_LEFT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_LEFT_J;
+ break;
+ case TEGRA_DAIFMT_RIGHT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_RIGHT_J;
+ break;
+ default :
+ dev_err(card->dev,
+ "Can't configure i2s format\n");
+ return -EINVAL;
+ }
+ }
err = snd_soc_dai_set_fmt(codec_dai, i2s_daifmt);
if (err < 0) {
@@ -140,8 +168,7 @@ static int tegra_wm8753_hw_params(struct snd_pcm_substream *substream,
return err;
}
- err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
- SND_SOC_CLOCK_IN);
+ err = snd_soc_dai_set_sysclk(codec_dai, 0, rate, SND_SOC_CLOCK_IN);
if (err < 0) {
dev_err(card->dev, "codec_dai clock not set\n");
return err;
@@ -173,7 +200,8 @@ static int tegra_bt_sco_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_card *card = codec->card;
struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card);
- int srate, mclk, min_mclk;
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
+ int srate, mclk, min_mclk, i2s_daifmt;
int err;
srate = params_rate(params);
@@ -209,10 +237,32 @@ static int tegra_bt_sco_hw_params(struct snd_pcm_substream *substream,
tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
- err = snd_soc_dai_set_fmt(cpu_dai,
- SND_SOC_DAIFMT_DSP_A |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS);
+ i2s_daifmt = SND_SOC_DAIFMT_NB_NF;
+ i2s_daifmt |= pdata->i2s_param[BT_SCO].is_i2s_master ?
+ SND_SOC_DAIFMT_CBS_CFS : SND_SOC_DAIFMT_CBM_CFM;
+
+ switch (pdata->i2s_param[BT_SCO].i2s_mode) {
+ case TEGRA_DAIFMT_I2S :
+ i2s_daifmt |= SND_SOC_DAIFMT_I2S;
+ break;
+ case TEGRA_DAIFMT_DSP_A :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_A;
+ break;
+ case TEGRA_DAIFMT_DSP_B :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_B;
+ break;
+ case TEGRA_DAIFMT_LEFT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_LEFT_J;
+ break;
+ case TEGRA_DAIFMT_RIGHT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_RIGHT_J;
+ break;
+ default :
+ dev_err(card->dev, "Can't configure i2s format\n");
+ return -EINVAL;
+ }
+
+ err = snd_soc_dai_set_fmt(cpu_dai, i2s_daifmt);
if (err < 0) {
dev_err(card->dev, "cpu_dai fmt not set\n");
return err;
@@ -873,8 +923,6 @@ static __devinit int tegra_wm8753_driver_probe(struct platform_device *pdev)
return -ENOMEM;
}
- machine->pdata = pdata;
-
ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev, card);
if (ret)
goto err_free_machine;
@@ -904,6 +952,16 @@ static __devinit int tegra_wm8753_driver_probe(struct platform_device *pdev)
}
#endif
+#ifndef CONFIG_ARCH_TEGRA_2x_SOC
+ ret = tegra_asoc_utils_set_parent(&machine->util_data,
+ pdata->i2s_param[HIFI_CODEC].is_i2s_master);
+ if (ret) {
+ dev_err(&pdev->dev, "tegra_asoc_utils_set_parent failed (%d)\n",
+ ret);
+ goto err_unregister_card;
+ }
+#endif
+
return 0;
err_unregister_card:
diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c
index 063aefe50507..dcd031209172 100644
--- a/sound/soc/tegra/tegra_wm8903.c
+++ b/sound/soc/tegra/tegra_wm8903.c
@@ -12,6 +12,8 @@
* Author: Graeme Gregory
* graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
*
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+ *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
@@ -40,7 +42,7 @@
#include <linux/switch.h>
#endif
-#include <mach/tegra_wm8903_pdata.h>
+#include <mach/tegra_asoc_pdata.h>
#include <sound/core.h>
#include <sound/jack.h>
@@ -67,7 +69,7 @@
struct tegra_wm8903 {
struct tegra_asoc_utils_data util_data;
- struct tegra_wm8903_platform_data *pdata;
+ struct tegra_asoc_platform_data *pdata;
struct regulator *spk_reg;
struct regulator *dmic_reg;
int gpio_requested;
@@ -86,9 +88,9 @@ static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_card *card = codec->card;
struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
int srate, mclk, i2s_daifmt;
int err;
- struct clk *clk_m;
int rate;
srate = params_rate(params);
@@ -103,31 +105,17 @@ static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream,
break;
}
+ if(pdata->i2s_param[HIFI_CODEC].is_i2s_master) {
+ /* FIXME: Codec only requires >= 3MHz if OSR==0 */
+ while (mclk < 6000000)
+ mclk *= 2;
-
- clk_m = clk_get_sys(NULL, "clk_m");
- if (IS_ERR(clk_m)) {
- dev_err(card->dev, "Can't retrieve clk clk_m\n");
- err = PTR_ERR(clk_m);
- return err;
+ i2s_daifmt = SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS;
+ } else {
+ i2s_daifmt = SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM;
}
- rate = clk_get_rate(clk_m);
- printk("extern1 rate=%d\n",rate);
-
-#if TEGRA30_I2S_MASTER_PLAYBACK
- /* FIXME: Codec only requires >= 3MHz if OSR==0 */
- while (mclk < 6000000)
- mclk *= 2;
-
- i2s_daifmt = SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS;
-#else
- mclk = rate;
-
- i2s_daifmt = SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBM_CFM;
-#endif
-
err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
if (err < 0) {
@@ -141,13 +129,36 @@ static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream,
tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
+ rate = clk_get_rate(machine->util_data.clk_cdev1);
+
/* Use DSP mode for mono on Tegra20 */
if ((params_channels(params) != 2) &&
- (machine_is_ventana() || machine_is_harmony() ||
- machine_is_kaen() || machine_is_aebl()))
+ (machine_is_ventana() || machine_is_harmony() ||
+ machine_is_kaen() || machine_is_aebl())) {
i2s_daifmt |= SND_SOC_DAIFMT_DSP_A;
- else
- i2s_daifmt |= SND_SOC_DAIFMT_I2S;
+ } else {
+ switch (pdata->i2s_param[HIFI_CODEC].i2s_mode) {
+ case TEGRA_DAIFMT_I2S :
+ i2s_daifmt |= SND_SOC_DAIFMT_I2S;
+ break;
+ case TEGRA_DAIFMT_DSP_A :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_A;
+ break;
+ case TEGRA_DAIFMT_DSP_B :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_B;
+ break;
+ case TEGRA_DAIFMT_LEFT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_LEFT_J;
+ break;
+ case TEGRA_DAIFMT_RIGHT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_RIGHT_J;
+ break;
+ default :
+ dev_err(card->dev,
+ "Can't configure i2s format\n");
+ return -EINVAL;
+ }
+ }
err = snd_soc_dai_set_fmt(codec_dai, i2s_daifmt);
if (err < 0) {
@@ -161,8 +172,7 @@ static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream,
return err;
}
- err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
- SND_SOC_CLOCK_IN);
+ err = snd_soc_dai_set_sysclk(codec_dai, 0, rate, SND_SOC_CLOCK_IN);
if (err < 0) {
dev_err(card->dev, "codec_dai clock not set\n");
return err;
@@ -190,10 +200,10 @@ static int tegra_bt_sco_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct snd_soc_card *card = rtd->card;
struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
- int srate, mclk, min_mclk;
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
+ int srate, mclk, min_mclk, i2s_daifmt;
int err;
srate = params_rate(params);
@@ -229,10 +239,32 @@ static int tegra_bt_sco_hw_params(struct snd_pcm_substream *substream,
tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
- err = snd_soc_dai_set_fmt(cpu_dai,
- SND_SOC_DAIFMT_DSP_A |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS);
+ i2s_daifmt = SND_SOC_DAIFMT_NB_NF;
+ i2s_daifmt |= pdata->i2s_param[BT_SCO].is_i2s_master ?
+ SND_SOC_DAIFMT_CBS_CFS : SND_SOC_DAIFMT_CBM_CFM;
+
+ switch (pdata->i2s_param[BT_SCO].i2s_mode) {
+ case TEGRA_DAIFMT_I2S :
+ i2s_daifmt |= SND_SOC_DAIFMT_I2S;
+ break;
+ case TEGRA_DAIFMT_DSP_A :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_A;
+ break;
+ case TEGRA_DAIFMT_DSP_B :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_B;
+ break;
+ case TEGRA_DAIFMT_LEFT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_LEFT_J;
+ break;
+ case TEGRA_DAIFMT_RIGHT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_RIGHT_J;
+ break;
+ default :
+ dev_err(card->dev, "Can't configure i2s format\n");
+ return -EINVAL;
+ }
+
+ err = snd_soc_dai_set_fmt(rtd->cpu_dai, i2s_daifmt);
if (err < 0) {
dev_err(card->dev, "cpu_dai fmt not set\n");
return err;
@@ -408,7 +440,7 @@ static int tegra_wm8903_event_int_spk(struct snd_soc_dapm_widget *w,
struct snd_soc_dapm_context *dapm = w->dapm;
struct snd_soc_card *card = dapm->card;
struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
- struct tegra_wm8903_platform_data *pdata = machine->pdata;
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
if (machine->spk_reg) {
if (SND_SOC_DAPM_EVENT_ON(event))
@@ -432,7 +464,7 @@ static int tegra_wm8903_event_hp(struct snd_soc_dapm_widget *w,
struct snd_soc_dapm_context *dapm = w->dapm;
struct snd_soc_card *card = dapm->card;
struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
- struct tegra_wm8903_platform_data *pdata = machine->pdata;
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
if (!(machine->gpio_requested & GPIO_HP_MUTE))
return 0;
@@ -449,7 +481,7 @@ static int tegra_wm8903_event_int_mic(struct snd_soc_dapm_widget *w,
struct snd_soc_dapm_context *dapm = w->dapm;
struct snd_soc_card *card = dapm->card;
struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
- struct tegra_wm8903_platform_data *pdata = machine->pdata;
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
if (machine->dmic_reg) {
if (SND_SOC_DAPM_EVENT_ON(event))
@@ -473,7 +505,7 @@ static int tegra_wm8903_event_ext_mic(struct snd_soc_dapm_widget *w,
struct snd_soc_dapm_context *dapm = w->dapm;
struct snd_soc_card *card = dapm->card;
struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
- struct tegra_wm8903_platform_data *pdata = machine->pdata;
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
if (!(machine->gpio_requested & GPIO_EXT_MIC_EN))
return 0;
@@ -578,7 +610,7 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_dapm_context *dapm = &codec->dapm;
struct snd_soc_card *card = codec->card;
struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
- struct tegra_wm8903_platform_data *pdata = machine->pdata;
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
int ret;
machine->bias_level = SND_SOC_BIAS_STANDBY;
@@ -792,7 +824,7 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &snd_soc_tegra_wm8903;
struct tegra_wm8903 *machine;
- struct tegra_wm8903_platform_data *pdata;
+ struct tegra_asoc_platform_data *pdata;
int ret;
pdata = pdev->dev.platform_data;
@@ -895,6 +927,16 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev)
goto err_unregister_card;
}
+#ifndef CONFIG_ARCH_TEGRA_2x_SOC
+ ret = tegra_asoc_utils_set_parent(&machine->util_data,
+ pdata->i2s_param[HIFI_CODEC].is_i2s_master);
+ if (ret) {
+ dev_err(&pdev->dev, "tegra_asoc_utils_set_parent failed (%d)\n",
+ ret);
+ goto err_unregister_card;
+ }
+#endif
+
return 0;
err_unregister_card:
@@ -914,7 +956,7 @@ static int __devexit tegra_wm8903_driver_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
- struct tegra_wm8903_platform_data *pdata = machine->pdata;
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
if (machine->gpio_requested & GPIO_HP_DET)
snd_soc_jack_free_gpios(&tegra_wm8903_hp_jack,