diff options
author | Marcel Ziswiler <marcel.ziswiler@toradex.com> | 2012-09-10 14:53:27 +0200 |
---|---|---|
committer | Marcel Ziswiler <marcel.ziswiler@toradex.com> | 2012-09-10 15:04:19 +0200 |
commit | d5bbf34613a877dbe3da847fa0432da8c6721e73 (patch) | |
tree | 902a90fd7eda61aad7abae9c35b0da2e7a786995 /sound | |
parent | c6c1f7a2c194f1a2291a15c6691c0d6785f8976e (diff) | |
parent | 336961dd3cf9c39456dd9657e8f205718740c797 (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')
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); |