summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorMarcel Ziswiler <marcel.ziswiler@toradex.com>2012-09-10 14:53:27 +0200
committerMarcel Ziswiler <marcel.ziswiler@toradex.com>2012-09-10 15:04:19 +0200
commitd5bbf34613a877dbe3da847fa0432da8c6721e73 (patch)
tree902a90fd7eda61aad7abae9c35b0da2e7a786995 /sound
parentc6c1f7a2c194f1a2291a15c6691c0d6785f8976e (diff)
parent336961dd3cf9c39456dd9657e8f205718740c797 (diff)
Merge branch 'l4t/l4t-r16' into colibri
Merge with latest NVIDIA L4T R16. Only real conflict concerning inverted VBUS gpio support.
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/codecs/Makefile3
-rw-r--r--sound/soc/codecs/aic326x_tiload.c5
-rw-r--r--sound/soc/codecs/base_main_Rate48_pps_driver.h11
-rw-r--r--sound/soc/codecs/max98088.c29
-rw-r--r--sound/soc/codecs/max98088.h5
-rw-r--r--sound/soc/codecs/rt5639.c26
-rw-r--r--sound/soc/codecs/rt5640.c56
-rw-r--r--sound/soc/codecs/second_rate_pps_driver.h7
-rw-r--r--sound/soc/codecs/spdif_transciever.c2
-rw-r--r--sound/soc/codecs/tlv320aic326x.c24
-rw-r--r--sound/soc/codecs/tlv320aic326x.h11
-rw-r--r--sound/soc/codecs/tlv320aic326x_mini-dsp.c32
-rw-r--r--sound/soc/codecs/tlv320aic326x_minidsp_config.c11
-rw-r--r--sound/soc/codecs/wm8903.c2
-rw-r--r--sound/soc/sh/siu_pcm.c5
-rw-r--r--sound/soc/tegra/Makefile2
-rw-r--r--sound/soc/tegra/tegra20_das.c6
-rw-r--r--sound/soc/tegra/tegra20_das.h4
-rw-r--r--sound/soc/tegra/tegra30_ahub.c78
-rw-r--r--sound/soc/tegra/tegra30_ahub.h10
-rw-r--r--sound/soc/tegra/tegra30_dam.c47
-rw-r--r--sound/soc/tegra/tegra30_i2s.c175
-rw-r--r--sound/soc/tegra/tegra_aic326x.c4
-rw-r--r--sound/soc/tegra/tegra_asoc_utils.c138
-rw-r--r--sound/soc/tegra/tegra_asoc_utils.h4
-rw-r--r--sound/soc/tegra/tegra_max98088.c16
-rw-r--r--sound/soc/tegra/tegra_max98095.c17
-rw-r--r--sound/soc/tegra/tegra_p1852.c45
-rw-r--r--sound/soc/tegra/tegra_pcm.c26
-rw-r--r--sound/soc/tegra/tegra_pcm.h1
-rw-r--r--sound/soc/tegra/tegra_rt5640.c5
-rw-r--r--sound/soc/tegra/tegra_wm8753.c5
-rw-r--r--sound/soc/tegra/tegra_wm8903.c6
33 files changed, 590 insertions, 228 deletions
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 2eaef5b52e08..d80b7bbff2e8 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -35,8 +35,7 @@ snd-soc-stac9766-objs := stac9766.o
snd-soc-tlv320aic23-objs := tlv320aic23.o
snd-soc-tlv320aic26-objs := tlv320aic26.o
snd-soc-tlv320aic3x-objs := tlv320aic3x.o
-snd-soc-tlv320aic326x-objs := tlv320aic326x.o tlv320aic326x_minidsp_config.o
-snd-soc-tlv320aic326x-objs += tlv320aic326x_mini-dsp.o aic326x_tiload.o
+snd-soc-tlv320aic326x-objs := tlv320aic326x.o
snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o
snd-soc-tlv320dac33-objs := tlv320dac33.o
snd-soc-twl4030-objs := twl4030.o
diff --git a/sound/soc/codecs/aic326x_tiload.c b/sound/soc/codecs/aic326x_tiload.c
index 00aa4d4ce7d7..07615dc5ebd7 100644
--- a/sound/soc/codecs/aic326x_tiload.c
+++ b/sound/soc/codecs/aic326x_tiload.c
@@ -61,7 +61,8 @@ static void aic3262_dump_page(struct i2c_client *i2c, u8 page);
/* externs */
extern int aic3262_change_page(struct snd_soc_codec *codec, u8 new_page);
extern int aic3262_change_book(struct snd_soc_codec *codec, u8 new_book);
-extern int aic3262_write(struct snd_soc_codec *codec, u16 reg, u8 value);
+extern int aic3262_write(struct snd_soc_codec *codec, unsigned int reg,
+ unsigned int value);
int aic3262_driver_init(struct snd_soc_codec *codec);
/************** Dynamic aic3262 driver, TI LOAD support ***************/
@@ -236,7 +237,7 @@ static ssize_t tiload_write(struct file *file, const char __user * buf,
return i2c_master_send(i2c, wr_data, count);
}
-static int tiload_ioctl( struct file *filp,
+static long tiload_ioctl(struct file *filp,
unsigned int cmd, unsigned long arg)
{
int num = 0;
diff --git a/sound/soc/codecs/base_main_Rate48_pps_driver.h b/sound/soc/codecs/base_main_Rate48_pps_driver.h
index 4d6f227cc42e..dff91858940e 100644
--- a/sound/soc/codecs/base_main_Rate48_pps_driver.h
+++ b/sound/soc/codecs/base_main_Rate48_pps_driver.h
@@ -16,17 +16,6 @@ static control base_speaker_SRS_VOLUME_controls[] = {
static char * base_speaker_SRS_VOLUME_control_names[] = {
};
-/*//INSTRUCTIONS & COEFFICIENTS
-typedef struct {
- u8 reg_off;
- u8 reg_val;
-} reg_value;*/
-
-static char * base_speaker_SRS_REG_Section_names[] = {
- "miniDSP_A_reg_values",
- "miniDSP_D_reg_values",
-};
-
reg_value base_speaker_SRS_REG_init_Section_program[] = {
{ 0,0x0},
{ 0x7F,0x00},
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c
index e2ad10d2deaa..b2b31f912b74 100644
--- a/sound/soc/codecs/max98088.c
+++ b/sound/soc/codecs/max98088.c
@@ -57,6 +57,8 @@ struct max98088_priv {
unsigned int extmic_mode;
int irq;
struct snd_soc_jack *headset_jack;
+ unsigned int jk_sns;
+ int jack_report;
};
static const u8 max98088_reg[M98088_REG_CNT] = {
@@ -1968,19 +1970,28 @@ static void max98088_handle_pdata(struct snd_soc_codec *codec)
int max98088_report_jack(struct snd_soc_codec *codec)
{
struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
- unsigned int value;
- int jack_report = 0;
+ unsigned int jk_sns_curr;
+ int jack_report_curr = 0;
/* Read the Jack Status Register*/
- value = snd_soc_read(codec, M98088_REG_02_JACK_STAUS);
+ jk_sns_curr = (snd_soc_read(codec, M98088_REG_02_JACK_STAUS))
+ & (M98088_JKSNS_7 | M98088_JKSNS_6);
+
+ if (max98088->jk_sns == M98088_NONE && jk_sns_curr == M98088_HP)
+ jack_report_curr = SND_JACK_HEADPHONE;
+ else if (max98088->jk_sns == M98088_NONE && jk_sns_curr == M98088_HS)
+ jack_report_curr = SND_JACK_HEADSET;
+ else if ((max98088->jk_sns == M98088_HP || max98088->jk_sns == M98088_HS)
+ && jk_sns_curr == M98088_NONE)
+ jack_report_curr = 0;
+ else
+ jack_report_curr = max98088->jack_report;
- if ((value & M98088_JKSNS_7) == 0)
- jack_report |= SND_JACK_HEADPHONE;
- if (value & M98088_JKSNS_6)
- jack_report |= SND_JACK_MICROPHONE;
+ max98088->jack_report = jack_report_curr;
+ max98088->jk_sns = jk_sns_curr;
snd_soc_jack_report(max98088->headset_jack,
- jack_report, SND_JACK_HEADSET);
+ jack_report_curr, SND_JACK_HEADSET);
return 0;
}
@@ -2001,6 +2012,8 @@ int max98088_headset_detect(struct snd_soc_codec *codec,
{
struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
max98088->headset_jack = jack;
+ max98088->jk_sns = M98088_NONE;
+ max98088->jack_report = 0;
if (max98088->irq) {
if (type & SND_JACK_HEADSET) {
diff --git a/sound/soc/codecs/max98088.h b/sound/soc/codecs/max98088.h
index cf4b04d2d07a..81ccf4b4caee 100644
--- a/sound/soc/codecs/max98088.h
+++ b/sound/soc/codecs/max98088.h
@@ -222,6 +222,11 @@
#define M98088_BYTE1(w) ((w >> 8) & 0xff)
#define M98088_BYTE0(w) (w & 0xff)
+/* HeadPhone and HeadSet detection Bitmasks */
+#define M98088_HP 0
+#define M98088_HS M98088_JKSNS_6
+#define M98088_NONE (M98088_JKSNS_7 | M98088_JKSNS_6)
+
int max98088_headset_detect(struct snd_soc_codec *codec,
struct snd_soc_jack *jack, enum snd_jack_types type);
diff --git a/sound/soc/codecs/rt5639.c b/sound/soc/codecs/rt5639.c
index e8841e0d6e4d..13190e21404b 100644
--- a/sound/soc/codecs/rt5639.c
+++ b/sound/soc/codecs/rt5639.c
@@ -105,6 +105,18 @@ static int rt5639_reg_init(struct snd_soc_codec *codec)
}
#endif
+static int rt5639_index_sync(struct snd_soc_codec *codec)
+{
+ int i;
+
+ for (i = 0; i < RT5639_INIT_REG_LEN; i++)
+ if (RT5639_PRIV_INDEX == init_list[i].reg ||
+ RT5639_PRIV_DATA == init_list[i].reg)
+ snd_soc_write(codec, init_list[i].reg,
+ init_list[i].val);
+ return 0;
+}
+
static const u16 rt5639_reg[RT5639_VENDOR_ID2 + 1] = {
[RT5639_RESET] = 0x0008,
[RT5639_SPK_VOL] = 0xc8c8,
@@ -1198,8 +1210,6 @@ static int spk_event(struct snd_soc_dapm_widget *w,
static int hp_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
- struct snd_soc_codec *codec = w->codec;
-
switch (event) {
case SND_SOC_DAPM_POST_PMU:
printk("hp_event --SND_SOC_DAPM_POST_PMU\n");
@@ -2215,7 +2225,9 @@ static int rt5639_set_bias_level(struct snd_soc_codec *codec,
RT5639_PWR_FV1 | RT5639_PWR_FV2,
RT5639_PWR_FV1 | RT5639_PWR_FV2);
codec->cache_only = false;
+ codec->cache_sync = 1;
snd_soc_cache_sync(codec);
+ rt5639_index_sync(codec);
}
break;
@@ -2313,13 +2325,23 @@ static int rt5639_remove(struct snd_soc_codec *codec)
#ifdef CONFIG_PM
static int rt5639_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
+ rt5639_reset(codec);
rt5639_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
static int rt5639_resume(struct snd_soc_codec *codec)
{
+ int ret = 0 ;
+
+ codec->cache_sync = 1;
+ ret = snd_soc_cache_sync(codec);
+ if (ret) {
+ dev_err(codec->dev,"Failed to sync cache: %d\n", ret);
+ return ret;
+ }
rt5639_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
return 0;
}
#else
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index cd84ed0858ac..49256e2d151d 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -25,7 +25,7 @@
#include <sound/tlv.h>
#include "rt5640.h"
-#if (CONFIG_SND_SOC_RT5642_MODULE | CONFIG_SND_SOC_RT5642)
+#if defined(CONFIG_SND_SOC_RT5642_MODULE) || defined(CONFIG_SND_SOC_RT5642)
#include "rt5640-dsp.h"
#endif
@@ -106,6 +106,18 @@ static int rt5640_reg_init(struct snd_soc_codec *codec)
}
#endif
+static int rt5640_index_sync(struct snd_soc_codec *codec)
+{
+ int i;
+
+ for (i = 0; i < RT5640_INIT_REG_LEN; i++)
+ if (RT5640_PRIV_INDEX == init_list[i].reg ||
+ RT5640_PRIV_DATA == init_list[i].reg)
+ snd_soc_write(codec, init_list[i].reg,
+ init_list[i].val);
+ return 0;
+}
+
static const u16 rt5640_reg[RT5640_VENDOR_ID2 + 1] = {
[RT5640_RESET] = 0x000c,
[RT5640_SPK_VOL] = 0xc8c8,
@@ -1179,8 +1191,6 @@ static int spk_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
- static unsigned int spkl_out_enable;
- static unsigned int spkr_out_enable;
switch (event) {
case SND_SOC_DAPM_POST_PMU:
@@ -1206,9 +1216,6 @@ static int spk_event(struct snd_soc_dapm_widget *w,
static int hp_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
- struct snd_soc_codec *codec = w->codec;
- static unsigned int hp_out_enable;
-
switch (event) {
case SND_SOC_DAPM_POST_PMU:
pr_info("hp_event --SND_SOC_DAPM_POST_PMU\n");
@@ -1820,9 +1827,8 @@ static int get_sdp_info(struct snd_soc_codec *codec, int dai_id)
ret |= RT5640_U_IF3;
break;
-#if (CONFIG_SND_SOC_RT5643_MODULE | CONFIG_SND_SOC_RT5643 | \
- CONFIG_SND_SOC_RT5646_MODULE | CONFIG_SND_SOC_RT5646)
-
+#if defined(CONFIG_SND_SOC_RT5643_MODULE) || defined(CONFIG_SND_SOC_RT5643) || \
+ defined(CONFIG_SND_SOC_RT5646_MODULE) || defined(CONFIG_SND_SOC_RT5646)
case RT5640_AIF3:
if (val == RT5640_IF_312 || val == RT5640_IF_321)
ret |= RT5640_U_IF1;
@@ -1922,8 +1928,8 @@ static int rt5640_hw_params(struct snd_pcm_substream *substream,
RT5640_I2S_DL_MASK, val_len);
snd_soc_update_bits(codec, RT5640_ADDA_CLK1, mask_clk, val_clk);
}
-#if (CONFIG_SND_SOC_RT5643_MODULE | CONFIG_SND_SOC_RT5643 | \
- CONFIG_SND_SOC_RT5646_MODULE | CONFIG_SND_SOC_RT5646)
+#if defined(CONFIG_SND_SOC_RT5643_MODULE) || defined(CONFIG_SND_SOC_RT5643) || \
+ defined(CONFIG_SND_SOC_RT5646_MODULE) || defined(CONFIG_SND_SOC_RT5646)
if (dai_sel & RT5640_U_IF3) {
mask_clk = RT5640_I2S_BCLK_MS3_MASK | RT5640_I2S_PD3_MASK;
val_clk = bclk_ms << RT5640_I2S_BCLK_MS3_SFT |
@@ -2006,8 +2012,8 @@ static int rt5640_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
RT5640_I2S_MS_MASK | RT5640_I2S_BP_MASK |
RT5640_I2S_DF_MASK, reg_val);
}
-#if (CONFIG_SND_SOC_RT5643_MODULE | CONFIG_SND_SOC_RT5643 | \
- CONFIG_SND_SOC_RT5646_MODULE | CONFIG_SND_SOC_RT5646)
+#if defined(CONFIG_SND_SOC_RT5643_MODULE) || defined(CONFIG_SND_SOC_RT5643) || \
+ defined(CONFIG_SND_SOC_RT5646_MODULE) || defined(CONFIG_SND_SOC_RT5646)
if (dai_sel & RT5640_U_IF3) {
snd_soc_update_bits(codec, RT5640_I2S3_SDP,
RT5640_I2S_MS_MASK | RT5640_I2S_BP_MASK |
@@ -2135,10 +2141,8 @@ static int rt5640_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
break;
case RT5640_PLL1_S_BCLK1:
case RT5640_PLL1_S_BCLK2:
-
-#if (CONFIG_SND_SOC_RT5643_MODULE | CONFIG_SND_SOC_RT5643 | \
- CONFIG_SND_SOC_RT5646_MODULE | CONFIG_SND_SOC_RT5646)
-
+#if defined(CONFIG_SND_SOC_RT5643_MODULE) || defined(CONFIG_SND_SOC_RT5643) || \
+ defined(CONFIG_SND_SOC_RT5646_MODULE) || defined(CONFIG_SND_SOC_RT5646)
case RT5640_PLL1_S_BCLK3:
#endif
@@ -2277,7 +2281,9 @@ static int rt5640_set_bias_level(struct snd_soc_codec *codec,
RT5640_PWR_FV1 | RT5640_PWR_FV2,
RT5640_PWR_FV1 | RT5640_PWR_FV2);
codec->cache_only = false;
+ codec->cache_sync = 1;
snd_soc_cache_sync(codec);
+ rt5640_index_sync(codec);
}
break;
@@ -2358,8 +2364,7 @@ static int rt5640_probe(struct snd_soc_codec *codec)
rt5640_reg_init(codec);
#endif
-
-#if (CONFIG_SND_SOC_RT5642_MODULE | CONFIG_SND_SOC_RT5642)
+#if defined(CONFIG_SND_SOC_RT5642_MODULE) || defined(CONFIG_SND_SOC_RT5642)
rt5640_register_dsp(codec);
#endif
@@ -2390,6 +2395,7 @@ static int rt5640_remove(struct snd_soc_codec *codec)
#ifdef CONFIG_PM
static int rt5640_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
+ rt5640_reset(codec);
rt5640_set_bias_level(codec, SND_SOC_BIAS_OFF);
snd_soc_write(codec, RT5640_PWR_ANLG1, 0);
@@ -2398,6 +2404,14 @@ static int rt5640_suspend(struct snd_soc_codec *codec, pm_message_t state)
static int rt5640_resume(struct snd_soc_codec *codec)
{
+ int ret = 0 ;
+
+ codec->cache_sync = 1;
+ ret = snd_soc_cache_sync(codec);
+ if (ret) {
+ dev_err(codec->dev,"Failed to sync cache: %d\n", ret);
+ return ret;
+ }
rt5640_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
@@ -2458,8 +2472,8 @@ struct snd_soc_dai_driver rt5640_dai[] = {
},
.ops = &rt5640_aif_dai_ops,
},
-#if (CONFIG_SND_SOC_RT5643_MODULE | CONFIG_SND_SOC_RT5643 | \
- CONFIG_SND_SOC_RT5646_MODULE | CONFIG_SND_SOC_RT5646)
+#if defined(CONFIG_SND_SOC_RT5643_MODULE) || defined(CONFIG_SND_SOC_RT5643) || \
+ defined(CONFIG_SND_SOC_RT5646_MODULE) || defined(CONFIG_SND_SOC_RT5646)
{
.name = "rt5640-aif3",
.id = RT5640_AIF3,
diff --git a/sound/soc/codecs/second_rate_pps_driver.h b/sound/soc/codecs/second_rate_pps_driver.h
index c6c128a027dd..9956c08bcd80 100644
--- a/sound/soc/codecs/second_rate_pps_driver.h
+++ b/sound/soc/codecs/second_rate_pps_driver.h
@@ -14,13 +14,6 @@ static control main44_VOLUME_controls[] = {
static char *main44_VOLUME_control_names[] = {
};
-
-
-static char *main44_REG_Section_names[] = {
- "miniDSP_A_reg_values",
- "miniDSP_D_reg_values",
-};
-
reg_value main44_REG_Section_init_program[] = {
{ 0,0x0},
{ 0x7F,0x00},
diff --git a/sound/soc/codecs/spdif_transciever.c b/sound/soc/codecs/spdif_transciever.c
index 16ea0ed77355..6173b3a5b082 100644
--- a/sound/soc/codecs/spdif_transciever.c
+++ b/sound/soc/codecs/spdif_transciever.c
@@ -77,7 +77,7 @@ static struct snd_soc_dai_driver dit_stub_dai = {
static int spdif_dit_probe(struct platform_device *pdev)
{
- if(machine_is_kai())
+ if(machine_is_kai() || machine_is_tegra_enterprise())
return snd_soc_register_codec(&pdev->dev,
&soc_codec_spdif_dit1, &dit_stub_dai, 1);
else
diff --git a/sound/soc/codecs/tlv320aic326x.c b/sound/soc/codecs/tlv320aic326x.c
index 8bbd295a3328..5d6b92904d56 100644
--- a/sound/soc/codecs/tlv320aic326x.c
+++ b/sound/soc/codecs/tlv320aic326x.c
@@ -81,9 +81,6 @@ static u8 aic3262_reg_ctl;
* This function reprograms the clock dividers etc. this flag can be used to
* disable this when the clock dividers are programmed by pps config file
*/
-static int soc_static_freq_config = 1;
-static struct aic3262_priv *aic3262_priv_data;
-static struct i2c_client *i2c_pdev;
static struct snd_soc_codec *aic3262_codec;
/*
@@ -849,7 +846,6 @@ static const struct aic3262_rate_divs aic3262_divs[] = {
static void aic3262_multi_i2s_dump_regs(struct snd_soc_dai *dai)
{
struct snd_soc_codec *codec = dai->codec;
- struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
unsigned int counter;
DBG(KERN_INFO "#%s: Dai Active %d ASI%d REGS DUMP\n",
@@ -1965,7 +1961,7 @@ static int aic3262_multi_i2s_hw_params(struct snd_pcm_substream *substream,
* We can use this function to disable the DAC and ADC specific inputs from the
* individual ASI Ports of the Audio Codec.
*/
-static int aic3262_multi_i2s_shutdown(struct snd_pcm_substream *substream,
+static void aic3262_multi_i2s_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -2106,7 +2102,7 @@ static int aic3262_multi_i2s_shutdown(struct snd_pcm_substream *substream,
aic3262->active_count--;
}
err:
- return 0;
+ return;
}
@@ -2547,13 +2543,13 @@ static const struct snd_kcontrol_new hpl_output_mixer_controls[] = {
SOC_DAPM_SINGLE("MAL Switch", HP_AMP_CNTL_R1, 7, 1, 0),
SOC_DAPM_SINGLE("LDAC Switch", HP_AMP_CNTL_R1, 5, 1, 0),
SOC_DAPM_SINGLE_TLV("LOL-B1 Volume", HP_AMP_CNTL_R2, 0,
- 0x7f, 1, lo_hp_tlv),
+ 0x7f, 0, lo_hp_tlv),
};
/* Right HPR Mixer */
static const struct snd_kcontrol_new hpr_output_mixer_controls[] = {
SOC_DAPM_SINGLE_TLV("LOR-B1 Volume", HP_AMP_CNTL_R3, 0,
- 0x7f, 1, lo_hp_tlv),
+ 0x7f, 0, lo_hp_tlv),
SOC_DAPM_SINGLE("LDAC Switch", HP_AMP_CNTL_R1, 2, 1, 0),
SOC_DAPM_SINGLE("RDAC Switch", HP_AMP_CNTL_R1, 4, 1, 0),
SOC_DAPM_SINGLE("MAR Switch", HP_AMP_CNTL_R1, 6, 1, 0),
@@ -3565,7 +3561,7 @@ void aic3262_write_reg_cache(struct snd_soc_codec *codec,
*----------------------------------------------------------------------------
*/
-u8 aic3262_read(struct snd_soc_codec *codec, u16 reg)
+unsigned int aic3262_read(struct snd_soc_codec *codec, unsigned int reg)
{
struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
u8 value;
@@ -3573,7 +3569,7 @@ u8 aic3262_read(struct snd_soc_codec *codec, u16 reg)
u16 *cache = codec->reg_cache;
u16 cmd;
u8 buffer[2];
- int rc;
+ int rc = 0;
reg = reg % 128;
if (reg >= AIC3262_CACHEREGNUM) {
@@ -3619,7 +3615,8 @@ u8 aic3262_read(struct snd_soc_codec *codec, u16 reg)
*
*----------------------------------------------------------------------------
*/
-int aic3262_write(struct snd_soc_codec *codec, u16 reg, u8 value)
+int aic3262_write(struct snd_soc_codec *codec, unsigned int reg,
+ unsigned int value)
{
struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
u8 data[2];
@@ -3855,8 +3852,6 @@ int i2c_verify_book0(struct snd_soc_codec *codec)
static int aic3262_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
- struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
- u8 value;
switch (level) {
/* full On */
case SND_SOC_BIAS_ON:
@@ -4400,6 +4395,7 @@ static int aic3262_spi_write(struct spi_device *spi, const char *data, int len)
return len;
}
+#ifdef RUN_DELAYED_WORK
/*
* This function forces any delayed work to be queued and run.
*/
@@ -4418,6 +4414,8 @@ static int run_delayed_work(struct delayed_work *dwork)
}
return ret;
}
+#endif
+
static int __devinit aic3262_spi_probe(struct spi_device *spi)
{
int ret;
diff --git a/sound/soc/codecs/tlv320aic326x.h b/sound/soc/codecs/tlv320aic326x.h
index a31cc9eca5ca..bfcbefc5c079 100644
--- a/sound/soc/codecs/tlv320aic326x.h
+++ b/sound/soc/codecs/tlv320aic326x.h
@@ -36,7 +36,7 @@
/* Enable register caching on write */
#define EN_REG_CACHE 1
-#define MULTIBYTE_CONFIG_SUPPORT
+//#define MULTIBYTE_CONFIG_SUPPORT
/*Setting all codec reg/write locally*/
/* This definition is added as the snd_ direct call are
@@ -45,12 +45,12 @@ page, so fix that before commenting this line*/
#define LOCAL_REG_ACCESS 1
/* Macro to enable the inclusion of tiload kernel driver */
-#define AIC3262_TiLoad
+//#define AIC3262_TiLoad
/* Macro enables or disables support for miniDSP in the driver */
/* Enable the AIC3262_TiLoad macro first before enabling these macros */
-#define CONFIG_MINI_DSP
+//#define CONFIG_MINI_DSP
/*#undef CONFIG_MINI_DSP*/
/* Enable or disable controls to have Input routing*/
@@ -657,11 +657,12 @@ extern int aic326x_headset_detect(struct snd_soc_codec *codec,
extern int aic326x_headset_button_init(struct snd_soc_codec *codec,
struct snd_soc_jack *jack, int jack_type);
-extern u8 aic3262_read(struct snd_soc_codec *codec, u16 reg);
+extern unsigned int aic3262_read(struct snd_soc_codec *codec, unsigned int reg);
extern u16 aic3262_read_2byte(struct snd_soc_codec *codec, u16 reg);
extern int aic3262_reset_cache(struct snd_soc_codec *codec);
extern int aic3262_change_page(struct snd_soc_codec *codec, u8 new_page);
-extern int aic3262_write(struct snd_soc_codec *codec, u16 reg, u8 value);
+extern int aic3262_write(struct snd_soc_codec *codec, unsigned int reg,
+ unsigned int value);
extern void aic3262_write_reg_cache(struct snd_soc_codec *codec,
u16 reg, u8 value);
extern int aic3262_change_book(struct snd_soc_codec *codec, u8 new_book);
diff --git a/sound/soc/codecs/tlv320aic326x_mini-dsp.c b/sound/soc/codecs/tlv320aic326x_mini-dsp.c
index 6d55abb4dac8..0ef0fd09760c 100644
--- a/sound/soc/codecs/tlv320aic326x_mini-dsp.c
+++ b/sound/soc/codecs/tlv320aic326x_mini-dsp.c
@@ -601,25 +601,27 @@ struct process_flow{
int
set_minidsp_mode(struct snd_soc_codec *codec, int new_mode, int new_config)
{
-
- if (codec == NULL) {
- printk(KERN_INFO "%s codec is NULL\n",__func__);
- }
- struct aic3262_priv *aic326x = snd_soc_codec_get_drvdata(codec);
- struct snd_soc_dapm_context *dapm = &codec->dapm;
+ struct aic3262_priv *aic326x;
+ struct snd_soc_dapm_context *dapm;
struct process_flow * pflows = &miniDSP_programs[new_mode];
- u8 reg63, reg81, pll_pow, ndac_pow, mdac_pow, nadc_pow, madc_pow;
-
+ u8 pll_pow, ndac_pow, mdac_pow, nadc_pow;
u8 adc_status,dac_status;
- u8 reg, val;
- u8 shift;
- volatile u16 counter;
- int (*ptransfer)(struct snd_soc_codec *codec,
- reg_value *program_ptr,
- int size);
+ int (*ptransfer)(struct snd_soc_codec *codec, reg_value *program_ptr,
+ int size);
printk("%s:New Switch mode = %d New Config= %d\n", __func__, new_mode,new_config);
+
+ if (codec == NULL) {
+ printk(KERN_INFO "%s codec is NULL\n", __func__);
+ return 0;
+ }
+ aic326x = snd_soc_codec_get_drvdata(codec);
+ dapm = &codec->dapm;
+
+ printk(KERN_INFO "%s:New Switch mode = %d New Config= %d\n", __func__,
+ new_mode, new_config);
+
if (new_mode >= ARRAY_SIZE(miniDSP_programs))
return 0; // error condition
if (new_config > MAXCONFIG)
@@ -1231,7 +1233,7 @@ static int __new_control_put_minidsp_mux(struct snd_kcontrol *kcontrol,
int ret_val = -1, array_size;
control *array;
char **array_names;
- char *control_name, *control_name1, *control_name2;
+ char *control_name, *control_name1;
struct aic3262_priv *aic326x = snd_soc_codec_get_drvdata(codec);
i2c = codec->control_data;
diff --git a/sound/soc/codecs/tlv320aic326x_minidsp_config.c b/sound/soc/codecs/tlv320aic326x_minidsp_config.c
index e34ffbe2ca82..97a41c3ecf2b 100644
--- a/sound/soc/codecs/tlv320aic326x_minidsp_config.c
+++ b/sound/soc/codecs/tlv320aic326x_minidsp_config.c
@@ -347,17 +347,12 @@ int aic3262_add_multiconfig_controls(struct snd_soc_codec *codec)
*---------------------------------------------------------------------------
*/
void minidsp_multiconfig(struct snd_soc_codec *codec,
- reg_value *a_patch, int a_size,
- reg_value *d_patch, int d_size)
+ reg_value *a_patch, int a_size, reg_value *d_patch, int d_size)
{
- struct aic3262_priv *aic326x = snd_soc_codec_get_drvdata(codec);
- int val1,val2;
int adc_status,dac_status;
int (*ptransfer)(struct snd_soc_codec *codec,
- reg_value *program_ptr,
- int size);
-
-printk("======in the config_multiconfiguration function==== \n");
+ reg_value *program_ptr, int size);
+ printk(KERN_INFO "======in the config_multiconfiguration function====\n");
#ifndef MULTIBYTE_I2C
ptransfer = byte_i2c_array_transfer;
#else
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index df4d0ee6f975..2a2d16886989 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -1404,6 +1404,7 @@ static struct {
{ 1500, 0x9, 0x2, 2 },
};
+#ifdef SYS_BCLK_RATIO
/* CLK_SYS/BCLK ratios - multiplied by 10 due to .5s */
static struct {
int ratio;
@@ -1427,6 +1428,7 @@ static struct {
{ 440, 19 },
{ 480, 20 },
};
+#endif
/* Sample rates for DSP */
static struct {
diff --git a/sound/soc/sh/siu_pcm.c b/sound/soc/sh/siu_pcm.c
index de9abd032fd4..5cfcc655e95f 100644
--- a/sound/soc/sh/siu_pcm.c
+++ b/sound/soc/sh/siu_pcm.c
@@ -180,13 +180,8 @@ static int siu_pcm_rd_set(struct siu_port *port_info,
sg_dma_len(&sg) = size;
sg_dma_address(&sg) = buff;
-<<<<<<< HEAD
- desc = siu_stream->chan->device->device_prep_slave_sg(siu_stream->chan,
- &sg, 1, DMA_FROM_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-=======
desc = dmaengine_prep_slave_sg(siu_stream->chan,
&sg, 1, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
->>>>>>> 1605282... dmaengine/dma_slave: introduce inline wrappers
if (!desc) {
dev_err(dev, "Failed to allocate dma descriptor\n");
return -ENOMEM;
diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile
index 274421b483de..079a28ccbe99 100644
--- a/sound/soc/tegra/Makefile
+++ b/sound/soc/tegra/Makefile
@@ -1,5 +1,7 @@
GCOV_PROFILE := y
+subdir-ccflags-y := -Werror
+
# Tegra platform Support
snd-soc-tegra-pcm-objs := tegra_pcm.o
snd-soc-tegra-tdm-pcm-objs := tegra_tdm_pcm.o
diff --git a/sound/soc/tegra/tegra20_das.c b/sound/soc/tegra/tegra20_das.c
index 0774d360399a..29c4582cfa79 100644
--- a/sound/soc/tegra/tegra20_das.c
+++ b/sound/soc/tegra/tegra20_das.c
@@ -50,7 +50,7 @@ static inline u32 tegra20_das_read(u32 reg)
}
#ifdef CONFIG_PM
-int tegra20_das_resume()
+int tegra20_das_resume(void)
{
int i, reg;
@@ -67,7 +67,7 @@ int tegra20_das_resume()
}
#endif
-int tegra20_das_set_tristate(int dap_id, int is_tristate)
+void tegra20_das_set_tristate(int dap_id, int is_tristate)
{
enum tegra_pingroup pin;
enum tegra_tristate tristate;
@@ -86,7 +86,7 @@ int tegra20_das_set_tristate(int dap_id, int is_tristate)
pin = TEGRA_PINGROUP_DAP4;
break;
default:
- return -EINVAL;
+ return;
}
if (is_tristate)
diff --git a/sound/soc/tegra/tegra20_das.h b/sound/soc/tegra/tegra20_das.h
index 0d58c7d1bc3f..5cd2d07d43b8 100644
--- a/sound/soc/tegra/tegra20_das.h
+++ b/sound/soc/tegra/tegra20_das.h
@@ -98,7 +98,7 @@ struct tegra20_das {
#ifdef CONFIG_PM
/* Restores the das registers from cache */
-extern int tegra20_das_resume();
+extern int tegra20_das_resume(void);
#endif
/*
* Terminology:
@@ -143,6 +143,6 @@ extern int tegra20_das_connect_dap_to_dap(int dap_id, int other_dap_sel,
*/
extern int tegra20_das_connect_dac_to_dap(int dac_id, int dap_sel);
-extern int tegra20_das_set_tristate(int dap_id, int is_tristate);
+extern void tegra20_das_set_tristate(int dap_id, int is_tristate);
#endif
diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c
index ea772f40464b..6fac8fc0177b 100644
--- a/sound/soc/tegra/tegra30_ahub.c
+++ b/sound/soc/tegra/tegra30_ahub.c
@@ -3,6 +3,7 @@
*
* Author: Stephen Warren <swarren@nvidia.com>
* Copyright (C) 2011 - NVIDIA, Inc.
+ * 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
@@ -281,66 +282,61 @@ int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif,
return 0;
}
-int tegra30_ahub_rx_fifo_is_busy(enum tegra30_ahub_rxcif rxcif)
+int tegra30_ahub_rx_fifo_is_enabled(int i2s_id)
{
- int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0;
- int reg, val;
-
- reg = TEGRA30_AHUB_CHANNEL_STATUS +
- (channel * TEGRA30_AHUB_CHANNEL_STATUS_STRIDE);
-
- val = tegra30_apbif_read(reg);
- val &= TEGRA30_AHUB_CHANNEL_STATUS_RX_TRIG;
+ int val, mask;
+ val = tegra30_apbif_read(TEGRA30_AHUB_I2S_LIVE_STATUS);
+ mask = (TEGRA30_AHUB_I2S_LIVE_STATUS_I2S0_RX_FIFO_ENABLED << (i2s_id*2));
+ val &= mask;
return val;
}
-int tegra30_ahub_tx_fifo_is_busy(enum tegra30_ahub_txcif txcif)
+int tegra30_ahub_tx_fifo_is_enabled(int i2s_id)
{
- int channel = txcif - TEGRA30_AHUB_TXCIF_APBIF_TX0;
- int reg, val;
+ int val, mask;
- reg = TEGRA30_AHUB_CHANNEL_STATUS +
- (channel * TEGRA30_AHUB_CHANNEL_STATUS_STRIDE);
-
- val = tegra30_apbif_read(reg);
- val &= TEGRA30_AHUB_CHANNEL_STATUS_TX_TRIG;
+ val = tegra30_apbif_read(TEGRA30_AHUB_I2S_LIVE_STATUS);
+ mask = (TEGRA30_AHUB_I2S_LIVE_STATUS_I2S0_TX_FIFO_ENABLED << (i2s_id*2));
+ val &= mask;
return val;
}
-int tegra30_ahub_rx_fifo_clear(enum tegra30_ahub_rxcif rxcif)
+int tegra30_ahub_dam_ch0_is_enabled(int dam_id)
{
- int channel = rxcif - TEGRA30_AHUB_RXCIF_APBIF_RX0;
- int reg, val;
-
- reg = TEGRA30_AHUB_CHANNEL_CLEAR +
- (channel * TEGRA30_AHUB_CHANNEL_CLEAR_STRIDE);
-
- val = tegra30_apbif_read(reg);
- val |= TEGRA30_AHUB_CHANNEL_CLEAR_RX_SOFT_RESET;
- tegra30_apbif_write(reg, val);
+ int val, mask;
- tegra30_ahub_disable_clocks();
+ val = tegra30_apbif_read((TEGRA30_AHUB_DAM_LIVE_STATUS) +
+ (dam_id * TEGRA30_AHUB_DAM_LIVE_STATUS_STRIDE));
+ mask = TEGRA30_AHUB_DAM_LIVE_STATUS_RX0_ENABLED;
+ val &= mask;
- return 0;
+ return val;
}
-int tegra30_ahub_tx_fifo_clear(enum tegra30_ahub_txcif txcif)
+int tegra30_ahub_dam_ch1_is_enabled(int dam_id)
{
- int channel = txcif - TEGRA30_AHUB_TXCIF_APBIF_TX0;
- int reg, val;
+ int val, mask;
- reg = TEGRA30_AHUB_CHANNEL_CLEAR +
- (channel * TEGRA30_AHUB_CHANNEL_CLEAR_STRIDE);
+ val = tegra30_apbif_read((TEGRA30_AHUB_DAM_LIVE_STATUS) +
+ (dam_id * TEGRA30_AHUB_DAM_LIVE_STATUS_STRIDE));
+ mask = TEGRA30_AHUB_DAM_LIVE_STATUS_RX1_ENABLED;
+ val &= mask;
- val = tegra30_apbif_read(reg);
- val |= TEGRA30_AHUB_CHANNEL_CLEAR_TX_SOFT_RESET;
- tegra30_apbif_write(reg, val);
+ return val;
+}
- tegra30_ahub_disable_clocks();
+int tegra30_ahub_dam_tx_is_enabled(int dam_id)
+{
+ int val, mask;
- return 0;
+ val = tegra30_apbif_read((TEGRA30_AHUB_DAM_LIVE_STATUS) +
+ (dam_id * TEGRA30_AHUB_DAM_LIVE_STATUS_STRIDE));
+ mask = TEGRA30_AHUB_DAM_LIVE_STATUS_TX_ENABLED;
+ val &= mask;
+
+ return val;
}
int tegra30_ahub_set_rx_fifo_pack_mode(enum tegra30_ahub_rxcif rxcif,
@@ -418,6 +414,8 @@ int tegra30_ahub_disable_rx_fifo(enum tegra30_ahub_rxcif rxcif)
val &= ~TEGRA30_AHUB_CHANNEL_CTRL_RX_EN;
tegra30_apbif_write(reg, val);
+ tegra30_ahub_disable_clocks();
+
return 0;
}
@@ -503,6 +501,8 @@ int tegra30_ahub_disable_tx_fifo(enum tegra30_ahub_txcif txcif)
val &= ~TEGRA30_AHUB_CHANNEL_CTRL_TX_EN;
tegra30_apbif_write(reg, val);
+ tegra30_ahub_disable_clocks();
+
return 0;
}
diff --git a/sound/soc/tegra/tegra30_ahub.h b/sound/soc/tegra/tegra30_ahub.h
index 2c0f5aab4db1..b5fd2363f080 100644
--- a/sound/soc/tegra/tegra30_ahub.h
+++ b/sound/soc/tegra/tegra30_ahub.h
@@ -3,6 +3,7 @@
*
* Author: Stephen Warren <swarren@nvidia.com>
* Copyright (C) 2011 - NVIDIA, Inc.
+ * 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
@@ -500,10 +501,11 @@ extern int tegra30_ahub_set_rx_cif_source(enum tegra30_ahub_rxcif rxcif,
enum tegra30_ahub_txcif txcif);
extern int tegra30_ahub_unset_rx_cif_source(enum tegra30_ahub_rxcif rxcif);
-extern int tegra30_ahub_rx_fifo_is_busy(enum tegra30_ahub_rxcif rxcif);
-extern int tegra30_ahub_tx_fifo_is_busy(enum tegra30_ahub_txcif txcif);
-extern int tegra30_ahub_rx_fifo_clear(enum tegra30_ahub_rxcif rxcif);
-extern int tegra30_ahub_tx_fifo_clear(enum tegra30_ahub_txcif txcif);
+extern int tegra30_ahub_rx_fifo_is_enabled(int i2s_id);
+extern int tegra30_ahub_tx_fifo_is_enabled(int i2s_id);
+extern int tegra30_ahub_dam_ch0_is_enabled(int dam_id);
+extern int tegra30_ahub_dam_ch1_is_enabled(int dam_id);
+extern int tegra30_ahub_dam_tx_is_enabled(int dam_id);
#ifdef CONFIG_PM
extern int tegra30_ahub_apbif_resume(void);
diff --git a/sound/soc/tegra/tegra30_dam.c b/sound/soc/tegra/tegra30_dam.c
index d308179110c9..8460266d0d66 100644
--- a/sound/soc/tegra/tegra30_dam.c
+++ b/sound/soc/tegra/tegra30_dam.c
@@ -3,6 +3,7 @@
*
* Author: Nikesh Oswal <noswal@nvidia.com>
* Copyright (C) 2011 - NVIDIA, Inc.
+ * 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
@@ -27,6 +28,7 @@
#include <linux/platform_device.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
+#include <linux/delay.h>
#include <linux/io.h>
#include <sound/soc.h>
#include "tegra30_dam.h"
@@ -455,6 +457,8 @@ int tegra30_dam_set_acif(int ifc, int chid, unsigned int audio_channels,
void tegra30_dam_enable(int ifc, int on, int chid)
{
u32 old_val, val, enreg;
+ u32 old_val_dam, val_dam;
+ int dcnt = 10;
struct tegra30_dam_context *dam = dams_cont_info[ifc];
if (ifc >= TEGRA30_NR_DAM_IFC)
@@ -476,19 +480,46 @@ void tegra30_dam_enable(int ifc, int on, int chid)
val &= ~TEGRA30_DAM_CH0_CTRL_EN;
}
- if (val != old_val)
- tegra30_dam_writel(dam, val, enreg);
-
- old_val = val = tegra30_dam_readl(dam, TEGRA30_DAM_CTRL);
+ old_val_dam = val_dam = tegra30_dam_readl(dam, TEGRA30_DAM_CTRL);
if (dam->ch_enable_refcnt[dam_ch_in0] ||
dam->ch_enable_refcnt[dam_ch_in1])
- val |= TEGRA30_DAM_CTRL_DAM_EN;
+ val_dam |= TEGRA30_DAM_CTRL_DAM_EN;
else
- val &= ~TEGRA30_DAM_CTRL_DAM_EN;
+ val_dam &= ~TEGRA30_DAM_CTRL_DAM_EN;
+
+ if (val != old_val) {
+ tegra30_dam_writel(dam, val, enreg);
+
+ if (!on) {
+ if (chid == dam_ch_in0) {
+ while (tegra30_ahub_dam_ch0_is_enabled(ifc)
+ && dcnt--)
+ udelay(100);
+
+ dcnt = 10;
+ }
+ else {
+ while (tegra30_ahub_dam_ch1_is_enabled(ifc)
+ && dcnt--)
+ udelay(100);
+
+ dcnt = 10;
+ }
+ }
+ }
+
+ if (old_val_dam != val_dam) {
+ tegra30_dam_writel(dam, val_dam, TEGRA30_DAM_CTRL);
+
+ if (!on) {
+ while (tegra30_ahub_dam_tx_is_enabled(ifc) && dcnt--)
+ udelay(100);
- if (old_val != val)
- tegra30_dam_writel(dam, val, TEGRA30_DAM_CTRL);
+ dcnt = 10;
+ }
+
+ }
}
void tegra30_dam_ch0_set_datasync(struct tegra30_dam_context *dam, int datasync)
diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c
index c2750bfbef64..72e64470008a 100644
--- a/sound/soc/tegra/tegra30_i2s.c
+++ b/sound/soc/tegra/tegra30_i2s.c
@@ -7,6 +7,7 @@
* Based on code copyright/by:
*
* Copyright (c) 2009-2010, NVIDIA Corporation.
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
* Scott Peterson <speterson@nvidia.com>
*
* Copyright (C) 2010 Google, Inc.
@@ -346,6 +347,7 @@ static int tegra30_i2s_tdm_setup_clocks(struct device *dev,
dev_err(dev, "Can't set parent of I2S clock\n");
return ret;
}
+
ret = clk_set_rate(i2s->clk_i2s, *i2sclock);
if (ret) {
dev_err(dev, "Can't set I2S clock rate: %d\n", ret);
@@ -359,6 +361,13 @@ static int tegra30_i2s_tdm_setup_clocks(struct device *dev,
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 audio2x clock rate\n");
@@ -367,7 +376,7 @@ static int tegra30_i2s_tdm_setup_clocks(struct device *dev,
ret = clk_set_parent(i2s->clk_i2s, i2s->clk_audio_2x);
if (ret) {
- dev_err(dev, "Can't set parent of audio2x clock\n");
+ dev_err(dev, "Can't set parent of i2s clock\n");
return ret;
}
}
@@ -382,7 +391,8 @@ static int tegra30_i2s_tdm_hw_params(struct snd_pcm_substream *substream,
struct device *dev = substream->pcm->card->dev;
struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
u32 val;
- int i2s_client_ch, i2s_audio_ch, i2s_audio_bits, i2s_client_bits;
+ int i2s_client_ch, i2s_audio_ch;
+ int i2s_audio_bits = 0, i2s_client_bits = 0;
int i2sclock, srate;
int ret;
@@ -418,6 +428,10 @@ static int tegra30_i2s_tdm_hw_params(struct snd_pcm_substream *substream,
i2s_client_bits = TEGRA30_AUDIOCIF_BITS_32;
i2s->reg_ctrl |= TEGRA30_I2S_CTRL_BIT_SIZE_32;
break;
+ default:
+ dev_err(dev, "unknown slot_width %d\n",
+ i2s->dsp_config.slot_width);
+ return -EINVAL;
}
val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) |
@@ -625,9 +639,8 @@ static void tegra30_i2s_stop_playback(struct tegra30_i2s *i2s)
i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_TX;
tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl);
}
- while (tegra30_ahub_tx_fifo_is_busy(i2s->txcif) && dcnt--)
+ while (tegra30_ahub_tx_fifo_is_enabled(i2s->id) && dcnt--)
udelay(100);
- tegra30_ahub_tx_fifo_clear(i2s->txcif);
}
static void tegra30_i2s_start_capture(struct tegra30_i2s *i2s)
@@ -647,9 +660,8 @@ static void tegra30_i2s_stop_capture(struct tegra30_i2s *i2s)
i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_RX;
tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl);
}
- while (tegra30_ahub_rx_fifo_is_busy(i2s->rxcif) && dcnt--)
+ while (tegra30_ahub_rx_fifo_is_enabled(i2s->id) && dcnt--)
udelay(100);
- tegra30_ahub_rx_fifo_clear(i2s->rxcif);
}
static int tegra30_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
@@ -800,7 +812,47 @@ static int configure_baseband_i2s(struct tegra30_i2s *i2s, int is_i2smaster,
int is_formatdsp, int channels, int rate, int bitsize)
{
u32 val;
- int i2sclock, bitcnt;
+ int i2sclock, bitcnt, ret;
+
+ i2sclock = rate * channels * bitsize * 2;
+
+ /* additional 8 for baseband */
+ if (is_formatdsp)
+ i2sclock *= 8;
+
+ if (is_i2smaster) {
+ ret = clk_set_parent(i2s->clk_i2s, i2s->clk_pll_a_out0);
+ if (ret) {
+ pr_err("Can't set parent of I2S clock\n");
+ return ret;
+ }
+
+ ret = clk_set_rate(i2s->clk_i2s, i2sclock);
+ if (ret) {
+ pr_err("Can't set I2S clock rate: %d\n", ret);
+ return ret;
+ }
+ } else {
+ ret = clk_set_rate(i2s->clk_i2s_sync, i2sclock);
+ if (ret) {
+ pr_err("Can't set I2S sync clock rate\n");
+ return ret;
+ }
+
+ ret = clk_set_rate(i2s->clk_audio_2x, i2sclock);
+ if (ret) {
+ pr_err("Can't set I2S sync clock rate\n");
+ return ret;
+ }
+
+ ret = clk_set_parent(i2s->clk_i2s, i2s->clk_audio_2x);
+ if (ret) {
+ pr_err("Can't set parent of audio2x clock\n");
+ return ret;
+ }
+ }
+
+ tegra30_i2s_enable_clocks(i2s);
i2s->reg_ctrl &= ~(TEGRA30_I2S_CTRL_FRAME_FORMAT_MASK |
TEGRA30_I2S_CTRL_LRCK_MASK |
@@ -835,14 +887,6 @@ static int configure_baseband_i2s(struct tegra30_i2s *i2s, int is_i2smaster,
(1 << TEGRA30_I2S_OFFSET_TX_DATA_OFFSET_SHIFT);
tegra30_i2s_write(i2s, TEGRA30_I2S_OFFSET, val);
- i2sclock = rate * channels * bitsize * 2;
-
- /* additional 8 for baseband */
- if (is_formatdsp)
- i2sclock *= 8;
-
- clk_set_rate(i2s->clk_i2s, i2sclock);
-
if (is_formatdsp) {
bitcnt = (i2sclock/rate) - 1;
val = bitcnt << TEGRA30_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT;
@@ -905,8 +949,6 @@ int tegra30_make_voice_call_connections(struct codec_config *codec_info,
codec_i2s = &i2scont[codec_info->i2s_id];
bb_i2s = &i2scont[bb_info->i2s_id];
- tegra30_i2s_enable_clocks(codec_i2s);
- tegra30_i2s_enable_clocks(bb_i2s);
/* increment the codec i2s playback ref count */
codec_i2s->playback_ref_count++;
@@ -957,10 +999,7 @@ int tegra30_make_voice_call_connections(struct codec_config *codec_info,
tegra30_dam_enable(bb_i2s->dam_ifc, TEGRA30_DAM_ENABLE,
TEGRA30_DAM_CHIN0_SRC);
- /* if this is the only user of i2s tx then enable it*/
- if (codec_i2s->playback_ref_count == 1)
- codec_i2s->reg_ctrl |= TEGRA30_I2S_CTRL_XFER_EN_TX;
-
+ codec_i2s->reg_ctrl |= TEGRA30_I2S_CTRL_XFER_EN_TX;
codec_i2s->reg_ctrl |= TEGRA30_I2S_CTRL_XFER_EN_RX;
tegra30_i2s_write(codec_i2s, TEGRA30_I2S_CTRL,
codec_i2s->reg_ctrl);
@@ -977,61 +1016,89 @@ int tegra30_break_voice_call_connections(struct codec_config *codec_info,
{
struct tegra30_i2s *codec_i2s;
struct tegra30_i2s *bb_i2s;
+ int dcnt = 10;
codec_i2s = &i2scont[codec_info->i2s_id];
bb_i2s = &i2scont[bb_info->i2s_id];
- /* disconnect the ahub connections */
-
- /* if this is the only user of i2s tx then break ahub
- i2s rx connection */
- if (codec_i2s->playback_ref_count == 1)
- tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_I2S0_RX0
- + codec_info->i2s_id);
+ /*Disable Codec I2S RX (TX to ahub)*/
+ codec_i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_RX;
+ tegra30_i2s_write(codec_i2s, TEGRA30_I2S_CTRL, codec_i2s->reg_ctrl);
- tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_I2S0_RX0
- + bb_info->i2s_id);
- tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX0
- + (codec_i2s->dam_ifc*2));
- tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX0
- + (bb_i2s->dam_ifc*2));
+ while (tegra30_ahub_rx_fifo_is_enabled(codec_i2s->id) && dcnt--)
+ udelay(100);
- /* disable the i2s */
+ dcnt = 10;
- /* if this is the only user of i2s tx then disable it*/
- if (codec_i2s->playback_ref_count == 1)
- codec_i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_TX;
+ /*Disable baseband DAM*/
+ tegra30_dam_enable(bb_i2s->dam_ifc, TEGRA30_DAM_DISABLE,
+ TEGRA30_DAM_CHIN0_SRC);
+ tegra30_dam_free_channel(bb_i2s->dam_ifc, TEGRA30_DAM_CHIN0_SRC);
+ bb_i2s->dam_ch_refcount--;
+ if (!bb_i2s->dam_ch_refcount)
+ tegra30_dam_free_controller(bb_i2s->dam_ifc);
- codec_i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_RX;
- tegra30_i2s_write(codec_i2s, TEGRA30_I2S_CTRL, codec_i2s->reg_ctrl);
+ /*Disable baseband I2S TX (RX from ahub)*/
bb_i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_TX;
+ tegra30_i2s_write(bb_i2s, TEGRA30_I2S_CTRL, bb_i2s->reg_ctrl);
+
+ while (tegra30_ahub_tx_fifo_is_enabled(bb_i2s->id) && dcnt--)
+ udelay(100);
+
+ dcnt = 10;
+
+ /*Disable baseband I2S RX (TX to ahub)*/
bb_i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_RX;
tegra30_i2s_write(bb_i2s, TEGRA30_I2S_CTRL, bb_i2s->reg_ctrl);
- tegra30_i2s_disable_clocks(codec_i2s);
- tegra30_i2s_disable_clocks(bb_i2s);
- /* decrement the codec i2s playback ref count */
- codec_i2s->playback_ref_count--;
- bb_i2s->playback_ref_count--;
+ while (tegra30_ahub_rx_fifo_is_enabled(bb_i2s->id) && dcnt--)
+ udelay(100);
+
+ dcnt = 10;
- /* disable the codec dam */
+ /*Disable Codec DAM*/
tegra30_dam_enable(codec_i2s->dam_ifc,
TEGRA30_DAM_DISABLE, TEGRA30_DAM_CHIN0_SRC);
- tegra30_dam_disable_clock(codec_i2s->dam_ifc);
tegra30_dam_free_channel(codec_i2s->dam_ifc,
TEGRA30_DAM_CHIN0_SRC);
codec_i2s->dam_ch_refcount--;
if (!codec_i2s->dam_ch_refcount)
tegra30_dam_free_controller(codec_i2s->dam_ifc);
- /* disable the bb dam */
- tegra30_dam_enable(bb_i2s->dam_ifc, TEGRA30_DAM_DISABLE,
- TEGRA30_DAM_CHIN0_SRC);
+ /*Disable Codec I2S TX (RX from ahub)*/
+ if (codec_i2s->playback_ref_count == 1)
+ codec_i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_TX;
+
+ tegra30_i2s_write(codec_i2s, TEGRA30_I2S_CTRL, codec_i2s->reg_ctrl);
+
+ while (tegra30_ahub_tx_fifo_is_enabled(codec_i2s->id) && dcnt--)
+ udelay(100);
+
+ dcnt = 10;
+
+ /* Disconnect the ahub connections */
+ /* If this is the only user of i2s tx then break ahub
+ i2s rx connection */
+ if (codec_i2s->playback_ref_count == 1)
+ tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_I2S0_RX0
+ + codec_info->i2s_id);
+
+ tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_I2S0_RX0
+ + bb_info->i2s_id);
+ tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX0
+ + (codec_i2s->dam_ifc*2));
+ tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX0
+ + (bb_i2s->dam_ifc*2));
+
+ /* Decrement the codec and bb i2s playback ref count */
+ codec_i2s->playback_ref_count--;
+ bb_i2s->playback_ref_count--;
+
+ /* Disable the clocks */
+ tegra30_i2s_disable_clocks(codec_i2s);
+ tegra30_i2s_disable_clocks(bb_i2s);
+ tegra30_dam_disable_clock(codec_i2s->dam_ifc);
tegra30_dam_disable_clock(bb_i2s->dam_ifc);
- tegra30_dam_free_channel(bb_i2s->dam_ifc, TEGRA30_DAM_CHIN0_SRC);
- bb_i2s->dam_ch_refcount--;
- if (!bb_i2s->dam_ch_refcount)
- tegra30_dam_free_controller(bb_i2s->dam_ifc);
return 0;
}
diff --git a/sound/soc/tegra/tegra_aic326x.c b/sound/soc/tegra/tegra_aic326x.c
index a5c6fc0aecb7..4cacb6758eb8 100644
--- a/sound/soc/tegra/tegra_aic326x.c
+++ b/sound/soc/tegra/tegra_aic326x.c
@@ -1062,6 +1062,10 @@ static int tegra_aic326x_init(struct snd_soc_pcm_runtime *rtd)
if (ret < 0)
return ret;
+ ret = tegra_asoc_utils_register_ctls(&machine->util_data);
+ 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);
diff --git a/sound/soc/tegra/tegra_asoc_utils.c b/sound/soc/tegra/tegra_asoc_utils.c
index b134f0808afa..6ab5b2d46a1f 100644
--- a/sound/soc/tegra/tegra_asoc_utils.c
+++ b/sound/soc/tegra/tegra_asoc_utils.c
@@ -27,11 +27,14 @@
#include <mach/clk.h>
+#include <sound/soc.h>
+
+#include "tegra_pcm.h"
#include "tegra_asoc_utils.h"
int g_is_call_mode;
-bool tegra_is_voice_call_active()
+bool tegra_is_voice_call_active(void)
{
if (g_is_call_mode)
return true;
@@ -40,6 +43,115 @@ bool tegra_is_voice_call_active()
}
EXPORT_SYMBOL_GPL(tegra_is_voice_call_active);
+static int tegra_get_avp_device(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct tegra_asoc_utils_data *data = snd_kcontrol_chip(kcontrol);
+
+ ucontrol->value.integer.value[0] = data->avp_device_id;
+ return 0;
+}
+
+static int tegra_set_avp_device(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;
+ int id, old_id = data->avp_device_id;
+
+ id = ucontrol->value.integer.value[0];
+ if ((id >= card->num_rtd) || (id < 0))
+ id = -1;
+
+ if (old_id >= 0) {
+ rtd = &card->rtd[old_id];
+ substream =
+ rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+ if (substream && substream->runtime) {
+ prtd = substream->runtime->private_data;
+ if (prtd->running)
+ return -EBUSY;
+ if (prtd)
+ prtd->disable_intr = false;
+ }
+ }
+
+ if (id >= 0) {
+ rtd = &card->rtd[id];
+ substream =
+ rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+ if (substream && substream->runtime) {
+ prtd = substream->runtime->private_data;
+ if (prtd->running)
+ return -EBUSY;
+ if (prtd)
+ prtd->disable_intr = true;
+ }
+ }
+ data->avp_device_id = id;
+ return 1;
+}
+
+static int tegra_get_dma_ch_id(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;
+
+ ucontrol->value.integer.value[0] = -1;
+ if (data->avp_device_id < 0)
+ return 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 || !prtd->dma_chan)
+ return 0;
+
+ ucontrol->value.integer.value[0] =
+ tegra_dma_get_channel_id(prtd->dma_chan);
+ return 0;
+}
+
+static int tegra_get_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;
+
+ ucontrol->value.integer.value[0] = 0;
+ if (data->avp_device_id < 0)
+ return 0;
+
+ rtd = &card->rtd[data->avp_device_id];
+ substream = rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+ if (!substream || !substream->runtime)
+ return 0;
+
+ ucontrol->value.integer.value[0] = substream->runtime->dma_addr;
+ return 0;
+}
+
+struct snd_kcontrol_new tegra_avp_controls[] = {
+ SOC_SINGLE_EXT("AVP alsa device select", 0, 0, TEGRA_ALSA_MAX_DEVICES, \
+ 0, tegra_get_avp_device, tegra_set_avp_device),
+ 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),
+};
+
int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
int mclk)
{
@@ -152,6 +264,26 @@ int tegra_asoc_utils_clk_disable(struct tegra_asoc_utils_data *data)
}
EXPORT_SYMBOL_GPL(tegra_asoc_utils_clk_disable);
+int tegra_asoc_utils_register_ctls(struct tegra_asoc_utils_data *data)
+{
+ int i;
+ int ret = 0;
+
+ /* Add AVP related alsa controls */
+ data->avp_device_id = -1;
+ for (i = 0; i < ARRAY_SIZE(tegra_avp_controls); i++) {
+ ret = snd_ctl_add(data->card->snd_card,
+ snd_ctl_new1(&tegra_avp_controls[i], data));
+ if (ret < 0) {
+ dev_err(data->dev, "Can't add avp alsa controls");
+ return ret;
+ }
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(tegra_asoc_utils_register_ctls);
+
int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data,
struct device *dev, struct snd_soc_card *card)
{
@@ -276,6 +408,10 @@ void tegra_asoc_utils_fini(struct tegra_asoc_utils_data *data)
clk_put(data->clk_out1);
clk_put(data->clk_cdev1);
+ /* Just to make sure that clk_cdev1 should turn off in case if it is
+ * switched on by some codec whose hw switch is not registered.*/
+ if (tegra_is_clk_enabled(data->clk_cdev1))
+ clk_disable(data->clk_cdev1);
if (!IS_ERR(data->clk_pll_a_out0))
clk_put(data->clk_pll_a_out0);
diff --git a/sound/soc/tegra/tegra_asoc_utils.h b/sound/soc/tegra/tegra_asoc_utils.h
index 512df0d54eb1..0423f02b76cc 100644
--- a/sound/soc/tegra/tegra_asoc_utils.h
+++ b/sound/soc/tegra/tegra_asoc_utils.h
@@ -25,6 +25,8 @@
#define TEGRA30_I2S_MASTER_PLAYBACK 1
+#define TEGRA_ALSA_MAX_DEVICES 6
+#define TEGRA_DMA_MAX_CHANNELS 32
struct clk;
struct device;
@@ -41,6 +43,7 @@ struct tegra_asoc_utils_data {
int set_baseclock;
int set_mclk;
int lock_count;
+ int avp_device_id;
};
int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
@@ -52,6 +55,7 @@ int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data,
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);
+int tegra_asoc_utils_register_ctls(struct tegra_asoc_utils_data *data);
#endif
diff --git a/sound/soc/tegra/tegra_max98088.c b/sound/soc/tegra/tegra_max98088.c
index 63a067338dc4..82c2b930a39e 100644
--- a/sound/soc/tegra/tegra_max98088.c
+++ b/sound/soc/tegra/tegra_max98088.c
@@ -96,6 +96,7 @@ struct tegra_max98088 {
#endif
enum snd_soc_bias_level bias_level;
struct snd_soc_card *pcard;
+ volatile int clock_enabled;
};
static int tegra_call_mode_info(struct snd_kcontrol *kcontrol,
@@ -926,6 +927,7 @@ static int tegra_max98088_init(struct snd_soc_pcm_runtime *rtd)
machine->pcard = card;
machine->bias_level = SND_SOC_BIAS_STANDBY;
+ machine->clock_enabled = 1;
if (gpio_is_valid(pdata->gpio_spkr_en)) {
ret = gpio_request(pdata->gpio_spkr_en, "spkr_en");
@@ -1007,6 +1009,10 @@ static int tegra_max98088_init(struct snd_soc_pcm_runtime *rtd)
if (ret < 0)
return ret;
+ ret = tegra_asoc_utils_register_ctls(&machine->util_data);
+ if (ret < 0)
+ return ret;
+
snd_soc_dapm_nc_pin(dapm, "INA1");
snd_soc_dapm_nc_pin(dapm, "INA2");
snd_soc_dapm_nc_pin(dapm, "INB1");
@@ -1070,8 +1076,11 @@ static int tegra30_soc_set_bias_level(struct snd_soc_card *card,
struct tegra_max98088 *machine = snd_soc_card_get_drvdata(card);
if (machine->bias_level == SND_SOC_BIAS_OFF &&
- level != SND_SOC_BIAS_OFF)
+ level != SND_SOC_BIAS_OFF && (!machine->clock_enabled)) {
+ machine->clock_enabled = 1;
tegra_asoc_utils_clk_enable(&machine->util_data);
+ machine->bias_level = level;
+ }
return 0;
}
@@ -1082,8 +1091,10 @@ static int tegra30_soc_set_bias_level_post(struct snd_soc_card *card,
struct tegra_max98088 *machine = snd_soc_card_get_drvdata(card);
if (machine->bias_level != SND_SOC_BIAS_OFF &&
- level == SND_SOC_BIAS_OFF)
+ level == SND_SOC_BIAS_OFF && (machine->clock_enabled)) {
+ machine->clock_enabled = 0;
tegra_asoc_utils_clk_disable(&machine->util_data);
+ }
machine->bias_level = level;
@@ -1156,6 +1167,7 @@ static __devinit int tegra_max98088_driver_probe(struct platform_device *pdev)
tegra_max98088_i2s_dai_name[machine->codec_info[BT_SCO].i2s_id];
#endif
+ card->dapm.idle_bias_off = 1;
ret = snd_soc_register_card(card);
if (ret) {
dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
diff --git a/sound/soc/tegra/tegra_max98095.c b/sound/soc/tegra/tegra_max98095.c
index 95295ef4151e..d065b78164ac 100644
--- a/sound/soc/tegra/tegra_max98095.c
+++ b/sound/soc/tegra/tegra_max98095.c
@@ -542,6 +542,10 @@ static int tegra_max98095_init(struct snd_soc_pcm_runtime *rtd)
tegra_max98095_hp_jack_pins);
#endif
+ ret = tegra_asoc_utils_register_ctls(&machine->util_data);
+ if (ret < 0)
+ return ret;
+
/* max98095_headset_detect(codec, &tegra_max98095_hp_jack,
SND_JACK_HEADSET); */
@@ -577,6 +581,7 @@ static struct snd_soc_dai_link tegra_max98095_dai[] = {
};
static int tegra30_soc_set_bias_level(struct snd_soc_card *card,
+ struct snd_soc_dapm_context *dapm,
enum snd_soc_bias_level level)
{
struct tegra_max98095 *machine = snd_soc_card_get_drvdata(card);
@@ -591,6 +596,7 @@ static int tegra30_soc_set_bias_level(struct snd_soc_card *card,
}
static int tegra30_soc_set_bias_level_post(struct snd_soc_card *card,
+ struct snd_soc_dapm_context *dapm,
enum snd_soc_bias_level level)
{
struct tegra_max98095 *machine = snd_soc_card_get_drvdata(card);
@@ -654,13 +660,22 @@ static __devinit int tegra_max98095_driver_probe(struct platform_device *pdev)
goto err_switch_unregister;
}
+ 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);
err_switch_unregister:
#ifdef CONFIG_SWITCH
switch_dev_unregister(&wired_switch_dev);
-#endif
err_fini_utils:
+#endif
tegra_asoc_utils_fini(&machine->util_data);
err_free_machine:
kfree(machine);
diff --git a/sound/soc/tegra/tegra_p1852.c b/sound/soc/tegra/tegra_p1852.c
index 9506a1c842df..199bb8046636 100644
--- a/sound/soc/tegra/tegra_p1852.c
+++ b/sound/soc/tegra/tegra_p1852.c
@@ -49,7 +49,8 @@ struct tegra_p1852 {
};
static int tegra_p1852_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ 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;
@@ -61,7 +62,6 @@ static int tegra_p1852_hw_params(struct snd_pcm_substream *substream,
int i2s_daifmt = 0;
int err;
struct tegra_p1852_platform_data *pdata;
- int codec_id = codec_dai->id;
pdata = machine->pdata;
@@ -120,15 +120,39 @@ static int tegra_p1852_hw_params(struct snd_pcm_substream *substream,
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;
@@ -139,8 +163,12 @@ static int tegra_hw_free(struct snd_pcm_substream *substream)
return 0;
}
-static struct snd_soc_ops tegra_p1852_ops = {
- .hw_params = tegra_p1852_hw_params,
+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,
};
@@ -149,13 +177,13 @@ 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,
+ .ops = &tegra_p1852_ops_controller1,
},
{
.name = "I2S-TDM-2",
.stream_name = "TEGRA PCM",
.platform_name = "tegra-pcm-audio",
- .ops = &tegra_p1852_ops,
+ .ops = &tegra_p1852_ops_controller2,
}
};
@@ -199,6 +227,9 @@ static __devinit int tegra_p1852_driver_probe(struct platform_device *pdev)
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);
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c
index 5f2553b3dd66..090e8481dc37 100644
--- a/sound/soc/tegra/tegra_pcm.c
+++ b/sound/soc/tegra/tegra_pcm.c
@@ -58,8 +58,8 @@ static const struct snd_pcm_hardware tegra_pcm_hardware = {
.channels_min = 1,
.channels_max = 2,
.period_bytes_min = 128,
- .period_bytes_max = PAGE_SIZE,
- .periods_min = 2,
+ .period_bytes_max = PAGE_SIZE * 2,
+ .periods_min = 1,
.periods_max = 8,
.buffer_bytes_max = PAGE_SIZE * 8,
.fifo_size = 4,
@@ -281,15 +281,30 @@ int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct tegra_runtime_data *prtd = runtime->private_data;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct tegra_pcm_dma_params * dmap;
unsigned long flags;
int i;
+ dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+ if (!dmap)
+ return 0;
+
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
prtd->dma_pos = 0;
prtd->dma_pos_end = frames_to_bytes(runtime, runtime->periods * runtime->period_size);
prtd->period_index = 0;
prtd->dma_req_idx = 0;
+ if (prtd->disable_intr) {
+ prtd->dma_req_count = 1;
+ prtd->dma_req[0].complete = NULL;
+ } else if (!prtd->dma_req[0].complete) {
+ prtd->dma_req[0].complete = dma_complete_callback;
+ prtd->dma_req_count =
+ (MAX_DMA_REQ_COUNT <= runtime->periods) ?
+ MAX_DMA_REQ_COUNT : runtime->periods;
+ }
/* Fall-through */
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
@@ -307,8 +322,9 @@ int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
spin_unlock_irqrestore(&prtd->lock, flags);
tegra_dma_cancel(prtd->dma_chan);
for (i = 0; i < prtd->dma_req_count; i++) {
- if (prtd->dma_req[i].status ==
- -TEGRA_DMA_REQ_ERROR_ABORTED)
+ if (prtd->dma_req[i].complete &&
+ (prtd->dma_req[i].status ==
+ -TEGRA_DMA_REQ_ERROR_ABORTED))
prtd->dma_req[i].complete(&prtd->dma_req[i]);
}
break;
@@ -443,7 +459,7 @@ void tegra_pcm_free(struct snd_pcm *pcm)
static int tegra_pcm_probe(struct snd_soc_platform *platform)
{
- if(machine_is_kai())
+ if(machine_is_kai() || machine_is_tegra_enterprise())
platform->dapm.idle_bias_off = 1;
return 0;
diff --git a/sound/soc/tegra/tegra_pcm.h b/sound/soc/tegra/tegra_pcm.h
index 7fe22788004b..b63de32023e8 100644
--- a/sound/soc/tegra/tegra_pcm.h
+++ b/sound/soc/tegra/tegra_pcm.h
@@ -53,6 +53,7 @@ struct tegra_runtime_data {
struct tegra_dma_req dma_req[MAX_DMA_REQ_COUNT];
struct tegra_dma_channel *dma_chan;
int dma_req_count;
+ int disable_intr;
};
int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd);
diff --git a/sound/soc/tegra/tegra_rt5640.c b/sound/soc/tegra/tegra_rt5640.c
index 231b0ee61308..765eb59fabae 100644
--- a/sound/soc/tegra/tegra_rt5640.c
+++ b/sound/soc/tegra/tegra_rt5640.c
@@ -547,6 +547,11 @@ static int tegra_rt5640_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_add_routes(dapm, cardhu_audio_map,
ARRAY_SIZE(cardhu_audio_map));
+
+ ret = tegra_asoc_utils_register_ctls(&machine->util_data);
+ if (ret < 0)
+ return ret;
+
/* FIXME: Calculate automatically based on DAPM routes? */
snd_soc_dapm_nc_pin(dapm, "LOUTL");
snd_soc_dapm_nc_pin(dapm, "LOUTR");
diff --git a/sound/soc/tegra/tegra_wm8753.c b/sound/soc/tegra/tegra_wm8753.c
index 795356875ba4..f7c7a4c6b5a1 100644
--- a/sound/soc/tegra/tegra_wm8753.c
+++ b/sound/soc/tegra/tegra_wm8753.c
@@ -379,7 +379,6 @@ static int tegra_bt_call_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *codec_dai = rtd->codec_dai;
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_card *card = codec->card;
struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card);
@@ -783,6 +782,10 @@ static int tegra_wm8753_init(struct snd_soc_pcm_runtime *rtd)
if (ret < 0)
return ret;
+ ret = tegra_asoc_utils_register_ctls(&machine->util_data);
+ if (ret < 0)
+ return ret;
+
snd_soc_dapm_nc_pin(dapm, "ACIN");
snd_soc_dapm_nc_pin(dapm, "ACOP");
snd_soc_dapm_nc_pin(dapm, "OUT3");
diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c
index ce608b007bef..063aefe50507 100644
--- a/sound/soc/tegra/tegra_wm8903.c
+++ b/sound/soc/tegra/tegra_wm8903.c
@@ -660,6 +660,10 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd)
wm8903_mic_detect(codec, &tegra_wm8903_mic_jack, SND_JACK_MICROPHONE,
machine_is_cardhu() ? SND_JACK_MICROPHONE : 0);
+ ret = tegra_asoc_utils_register_ctls(&machine->util_data);
+ if (ret < 0)
+ return ret;
+
snd_soc_dapm_force_enable_pin(dapm, "Mic Bias");
/* FIXME: Calculate automatically based on DAPM routes? */
@@ -898,8 +902,8 @@ err_unregister_card:
err_unregister_switch:
#ifdef CONFIG_SWITCH
switch_dev_unregister(&tegra_wm8903_headset_switch);
-#endif
err_fini_utils:
+#endif
tegra_asoc_utils_fini(&machine->util_data);
err_free_machine:
kfree(machine);