aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/codecs/tlv320aic3x.c15
-rw-r--r--sound/soc/codecs/tlv320dac33.c57
-rw-r--r--sound/soc/codecs/tpa6130a2.c92
-rw-r--r--sound/soc/codecs/tpa6130a2.h1
-rw-r--r--sound/soc/codecs/twl4030.c5
-rw-r--r--sound/soc/codecs/twl6040.c842
-rw-r--r--sound/soc/codecs/twl6040.h8
-rw-r--r--sound/soc/omap/sdp4430.c43
8 files changed, 844 insertions, 219 deletions
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 899af41787c1..3bedab26892f 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -1545,21 +1545,6 @@ static struct i2c_driver aic3x_i2c_driver = {
1545 .remove = aic3x_i2c_remove, 1545 .remove = aic3x_i2c_remove,
1546 .id_table = aic3x_i2c_id, 1546 .id_table = aic3x_i2c_id,
1547}; 1547};
1548
1549static inline void aic3x_i2c_init(void)
1550{
1551 int ret;
1552
1553 ret = i2c_add_driver(&aic3x_i2c_driver);
1554 if (ret)
1555 printk(KERN_ERR "%s: error regsitering i2c driver, %d\n",
1556 __func__, ret);
1557}
1558
1559static inline void aic3x_i2c_exit(void)
1560{
1561 i2c_del_driver(&aic3x_i2c_driver);
1562}
1563#endif 1548#endif
1564 1549
1565static int __init aic3x_modinit(void) 1550static int __init aic3x_modinit(void)
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c
index ccb267f4e968..776ac80cc1a8 100644
--- a/sound/soc/codecs/tlv320dac33.c
+++ b/sound/soc/codecs/tlv320dac33.c
@@ -315,8 +315,6 @@ static void dac33_init_chip(struct snd_soc_codec *codec)
315 clock source = internal osc (?) */ 315 clock source = internal osc (?) */
316 dac33_write(codec, DAC33_ANA_VOL_SOFT_STEP_CTRL, DAC33_VOLCLKEN); 316 dac33_write(codec, DAC33_ANA_VOL_SOFT_STEP_CTRL, DAC33_VOLCLKEN);
317 317
318 dac33_write(codec, DAC33_PWR_CTRL, DAC33_PDNALLB);
319
320 /* Restore only selected registers (gains mostly) */ 318 /* Restore only selected registers (gains mostly) */
321 dac33_write(codec, DAC33_LDAC_DIG_VOL_CTRL, 319 dac33_write(codec, DAC33_LDAC_DIG_VOL_CTRL,
322 dac33_read_reg_cache(codec, DAC33_LDAC_DIG_VOL_CTRL)); 320 dac33_read_reg_cache(codec, DAC33_LDAC_DIG_VOL_CTRL));
@@ -356,6 +354,21 @@ static inline void dac33_soft_power(struct snd_soc_codec *codec, int power)
356 dac33_write(codec, DAC33_PWR_CTRL, reg); 354 dac33_write(codec, DAC33_PWR_CTRL, reg);
357} 355}
358 356
357static inline void dac33_disable_digital(struct snd_soc_codec *codec)
358{
359 u8 reg;
360
361 /* Stop the DAI clock */
362 reg = dac33_read_reg_cache(codec, DAC33_SER_AUDIOIF_CTRL_B);
363 reg &= ~DAC33_BCLKON;
364 dac33_write(codec, DAC33_SER_AUDIOIF_CTRL_B, reg);
365
366 /* Power down the Oscillator, and DACs */
367 reg = dac33_read_reg_cache(codec, DAC33_PWR_CTRL);
368 reg &= ~(DAC33_OSCPDNB | DAC33_DACRPDNB | DAC33_DACLPDNB);
369 dac33_write(codec, DAC33_PWR_CTRL, reg);
370}
371
359static int dac33_hard_power(struct snd_soc_codec *codec, int power) 372static int dac33_hard_power(struct snd_soc_codec *codec, int power)
360{ 373{
361 struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); 374 struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
@@ -404,7 +417,7 @@ exit:
404 return ret; 417 return ret;
405} 418}
406 419
407static int playback_event(struct snd_soc_dapm_widget *w, 420static int dac33_playback_event(struct snd_soc_dapm_widget *w,
408 struct snd_kcontrol *kcontrol, int event) 421 struct snd_kcontrol *kcontrol, int event)
409{ 422{
410 struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(w->codec); 423 struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(w->codec);
@@ -416,6 +429,9 @@ static int playback_event(struct snd_soc_dapm_widget *w,
416 dac33_prepare_chip(dac33->substream); 429 dac33_prepare_chip(dac33->substream);
417 } 430 }
418 break; 431 break;
432 case SND_SOC_DAPM_POST_PMD:
433 dac33_disable_digital(w->codec);
434 break;
419 } 435 }
420 return 0; 436 return 0;
421} 437}
@@ -592,8 +608,8 @@ static const struct snd_soc_dapm_widget dac33_dapm_widgets[] = {
592 SND_SOC_DAPM_INPUT("LINEL"), 608 SND_SOC_DAPM_INPUT("LINEL"),
593 SND_SOC_DAPM_INPUT("LINER"), 609 SND_SOC_DAPM_INPUT("LINER"),
594 610
595 SND_SOC_DAPM_DAC("DACL", "Left Playback", DAC33_LDAC_PWR_CTRL, 2, 0), 611 SND_SOC_DAPM_DAC("DACL", "Left Playback", SND_SOC_NOPM, 0, 0),
596 SND_SOC_DAPM_DAC("DACR", "Right Playback", DAC33_RDAC_PWR_CTRL, 2, 0), 612 SND_SOC_DAPM_DAC("DACR", "Right Playback", SND_SOC_NOPM, 0, 0),
597 613
598 /* Analog bypass */ 614 /* Analog bypass */
599 SND_SOC_DAPM_SWITCH("Analog Left Bypass", SND_SOC_NOPM, 0, 0, 615 SND_SOC_DAPM_SWITCH("Analog Left Bypass", SND_SOC_NOPM, 0, 0,
@@ -601,12 +617,18 @@ static const struct snd_soc_dapm_widget dac33_dapm_widgets[] = {
601 SND_SOC_DAPM_SWITCH("Analog Right Bypass", SND_SOC_NOPM, 0, 0, 617 SND_SOC_DAPM_SWITCH("Analog Right Bypass", SND_SOC_NOPM, 0, 0,
602 &dac33_dapm_abypassr_control), 618 &dac33_dapm_abypassr_control),
603 619
604 SND_SOC_DAPM_REG(snd_soc_dapm_mixer, "Output Left Amp Power", 620 SND_SOC_DAPM_REG(snd_soc_dapm_mixer, "Output Left Amplifier",
605 DAC33_OUT_AMP_PWR_CTRL, 6, 3, 3, 0), 621 DAC33_OUT_AMP_PWR_CTRL, 6, 3, 3, 0),
606 SND_SOC_DAPM_REG(snd_soc_dapm_mixer, "Output Right Amp Power", 622 SND_SOC_DAPM_REG(snd_soc_dapm_mixer, "Output Right Amplifier",
607 DAC33_OUT_AMP_PWR_CTRL, 4, 3, 3, 0), 623 DAC33_OUT_AMP_PWR_CTRL, 4, 3, 3, 0),
608 624
609 SND_SOC_DAPM_PRE("Prepare Playback", playback_event), 625 SND_SOC_DAPM_SUPPLY("Left DAC Power",
626 DAC33_LDAC_PWR_CTRL, 2, 0, NULL, 0),
627 SND_SOC_DAPM_SUPPLY("Right DAC Power",
628 DAC33_RDAC_PWR_CTRL, 2, 0, NULL, 0),
629
630 SND_SOC_DAPM_PRE("Pre Playback", dac33_playback_event),
631 SND_SOC_DAPM_POST("Post Playback", dac33_playback_event),
610}; 632};
611 633
612static const struct snd_soc_dapm_route audio_map[] = { 634static const struct snd_soc_dapm_route audio_map[] = {
@@ -614,15 +636,18 @@ static const struct snd_soc_dapm_route audio_map[] = {
614 {"Analog Left Bypass", "Switch", "LINEL"}, 636 {"Analog Left Bypass", "Switch", "LINEL"},
615 {"Analog Right Bypass", "Switch", "LINER"}, 637 {"Analog Right Bypass", "Switch", "LINER"},
616 638
617 {"Output Left Amp Power", NULL, "DACL"}, 639 {"Output Left Amplifier", NULL, "DACL"},
618 {"Output Right Amp Power", NULL, "DACR"}, 640 {"Output Right Amplifier", NULL, "DACR"},
641
642 {"Output Left Amplifier", NULL, "Analog Left Bypass"},
643 {"Output Right Amplifier", NULL, "Analog Right Bypass"},
619 644
620 {"Output Left Amp Power", NULL, "Analog Left Bypass"}, 645 {"Output Left Amplifier", NULL, "Left DAC Power"},
621 {"Output Right Amp Power", NULL, "Analog Right Bypass"}, 646 {"Output Right Amplifier", NULL, "Right DAC Power"},
622 647
623 /* output */ 648 /* output */
624 {"LEFT_LO", NULL, "Output Left Amp Power"}, 649 {"LEFT_LO", NULL, "Output Left Amplifier"},
625 {"RIGHT_LO", NULL, "Output Right Amp Power"}, 650 {"RIGHT_LO", NULL, "Output Right Amplifier"},
626}; 651};
627 652
628static int dac33_add_widgets(struct snd_soc_codec *codec) 653static int dac33_add_widgets(struct snd_soc_codec *codec)
@@ -640,11 +665,13 @@ static int dac33_add_widgets(struct snd_soc_codec *codec)
640static int dac33_set_bias_level(struct snd_soc_codec *codec, 665static int dac33_set_bias_level(struct snd_soc_codec *codec,
641 enum snd_soc_bias_level level) 666 enum snd_soc_bias_level level)
642{ 667{
668 struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
643 int ret; 669 int ret;
644 670
645 switch (level) { 671 switch (level) {
646 case SND_SOC_BIAS_ON: 672 case SND_SOC_BIAS_ON:
647 dac33_soft_power(codec, 1); 673 if (!dac33->substream)
674 dac33_soft_power(codec, 1);
648 break; 675 break;
649 case SND_SOC_BIAS_PREPARE: 676 case SND_SOC_BIAS_PREPARE:
650 break; 677 break;
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c
index 9d61a1d6fce0..0a99f313e218 100644
--- a/sound/soc/codecs/tpa6130a2.c
+++ b/sound/soc/codecs/tpa6130a2.c
@@ -41,7 +41,7 @@ struct tpa6130a2_data {
41 unsigned char regs[TPA6130A2_CACHEREGNUM]; 41 unsigned char regs[TPA6130A2_CACHEREGNUM];
42 struct regulator *supply; 42 struct regulator *supply;
43 int power_gpio; 43 int power_gpio;
44 unsigned char power_state; 44 u8 power_state:1;
45 enum tpa_model id; 45 enum tpa_model id;
46}; 46};
47 47
@@ -116,7 +116,7 @@ static int tpa6130a2_initialize(void)
116 return ret; 116 return ret;
117} 117}
118 118
119static int tpa6130a2_power(int power) 119static int tpa6130a2_power(u8 power)
120{ 120{
121 struct tpa6130a2_data *data; 121 struct tpa6130a2_data *data;
122 u8 val; 122 u8 val;
@@ -126,8 +126,10 @@ static int tpa6130a2_power(int power)
126 data = i2c_get_clientdata(tpa6130a2_client); 126 data = i2c_get_clientdata(tpa6130a2_client);
127 127
128 mutex_lock(&data->mutex); 128 mutex_lock(&data->mutex);
129 if (power && !data->power_state) { 129 if (power == data->power_state)
130 goto exit;
130 131
132 if (power) {
131 ret = regulator_enable(data->supply); 133 ret = regulator_enable(data->supply);
132 if (ret != 0) { 134 if (ret != 0) {
133 dev_err(&tpa6130a2_client->dev, 135 dev_err(&tpa6130a2_client->dev,
@@ -149,12 +151,7 @@ static int tpa6130a2_power(int power)
149 data->power_state = 0; 151 data->power_state = 0;
150 goto exit; 152 goto exit;
151 } 153 }
152 154 } else {
153 /* Clear SWS */
154 val = tpa6130a2_read(TPA6130A2_REG_CONTROL);
155 val &= ~TPA6130A2_SWS;
156 tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val);
157 } else if (!power && data->power_state) {
158 /* set SWS */ 155 /* set SWS */
159 val = tpa6130a2_read(TPA6130A2_REG_CONTROL); 156 val = tpa6130a2_read(TPA6130A2_REG_CONTROL);
160 val |= TPA6130A2_SWS; 157 val |= TPA6130A2_SWS;
@@ -299,6 +296,7 @@ static void tpa6130a2_channel_enable(u8 channel, int enable)
299 /* Enable amplifier */ 296 /* Enable amplifier */
300 val = tpa6130a2_read(TPA6130A2_REG_CONTROL); 297 val = tpa6130a2_read(TPA6130A2_REG_CONTROL);
301 val |= channel; 298 val |= channel;
299 val &= ~TPA6130A2_SWS;
302 tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val); 300 tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val);
303 301
304 /* Unmute channel */ 302 /* Unmute channel */
@@ -319,72 +317,24 @@ static void tpa6130a2_channel_enable(u8 channel, int enable)
319 } 317 }
320} 318}
321 319
322static int tpa6130a2_left_event(struct snd_soc_dapm_widget *w, 320int tpa6130a2_stereo_enable(struct snd_soc_codec *codec, int enable)
323 struct snd_kcontrol *kcontrol, int event)
324{
325 switch (event) {
326 case SND_SOC_DAPM_POST_PMU:
327 tpa6130a2_channel_enable(TPA6130A2_HP_EN_L, 1);
328 break;
329 case SND_SOC_DAPM_POST_PMD:
330 tpa6130a2_channel_enable(TPA6130A2_HP_EN_L, 0);
331 break;
332 }
333 return 0;
334}
335
336static int tpa6130a2_right_event(struct snd_soc_dapm_widget *w,
337 struct snd_kcontrol *kcontrol, int event)
338{
339 switch (event) {
340 case SND_SOC_DAPM_POST_PMU:
341 tpa6130a2_channel_enable(TPA6130A2_HP_EN_R, 1);
342 break;
343 case SND_SOC_DAPM_POST_PMD:
344 tpa6130a2_channel_enable(TPA6130A2_HP_EN_R, 0);
345 break;
346 }
347 return 0;
348}
349
350static int tpa6130a2_supply_event(struct snd_soc_dapm_widget *w,
351 struct snd_kcontrol *kcontrol, int event)
352{ 321{
353 int ret = 0; 322 int ret = 0;
354 323 if (enable) {
355 switch (event) {
356 case SND_SOC_DAPM_POST_PMU:
357 ret = tpa6130a2_power(1); 324 ret = tpa6130a2_power(1);
358 break; 325 if (ret < 0)
359 case SND_SOC_DAPM_POST_PMD: 326 return ret;
327 tpa6130a2_channel_enable(TPA6130A2_HP_EN_R | TPA6130A2_HP_EN_L,
328 1);
329 } else {
330 tpa6130a2_channel_enable(TPA6130A2_HP_EN_R | TPA6130A2_HP_EN_L,
331 0);
360 ret = tpa6130a2_power(0); 332 ret = tpa6130a2_power(0);
361 break;
362 } 333 }
334
363 return ret; 335 return ret;
364} 336}
365 337EXPORT_SYMBOL_GPL(tpa6130a2_stereo_enable);
366static const struct snd_soc_dapm_widget tpa6130a2_dapm_widgets[] = {
367 SND_SOC_DAPM_PGA_E("TPA6130A2 Left", SND_SOC_NOPM,
368 0, 0, NULL, 0, tpa6130a2_left_event,
369 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
370 SND_SOC_DAPM_PGA_E("TPA6130A2 Right", SND_SOC_NOPM,
371 0, 0, NULL, 0, tpa6130a2_right_event,
372 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
373 SND_SOC_DAPM_SUPPLY("TPA6130A2 Enable", SND_SOC_NOPM,
374 0, 0, tpa6130a2_supply_event,
375 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
376 /* Outputs */
377 SND_SOC_DAPM_OUTPUT("TPA6130A2 Headphone Left"),
378 SND_SOC_DAPM_OUTPUT("TPA6130A2 Headphone Right"),
379};
380
381static const struct snd_soc_dapm_route audio_map[] = {
382 {"TPA6130A2 Headphone Left", NULL, "TPA6130A2 Left"},
383 {"TPA6130A2 Headphone Right", NULL, "TPA6130A2 Right"},
384
385 {"TPA6130A2 Headphone Left", NULL, "TPA6130A2 Enable"},
386 {"TPA6130A2 Headphone Right", NULL, "TPA6130A2 Enable"},
387};
388 338
389int tpa6130a2_add_controls(struct snd_soc_codec *codec) 339int tpa6130a2_add_controls(struct snd_soc_codec *codec)
390{ 340{
@@ -396,18 +346,12 @@ int tpa6130a2_add_controls(struct snd_soc_codec *codec)
396 346
397 data = i2c_get_clientdata(tpa6130a2_client); 347 data = i2c_get_clientdata(tpa6130a2_client);
398 348
399 snd_soc_dapm_new_controls(dapm, tpa6130a2_dapm_widgets,
400 ARRAY_SIZE(tpa6130a2_dapm_widgets));
401
402 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
403
404 if (data->id == TPA6140A2) 349 if (data->id == TPA6140A2)
405 return snd_soc_add_controls(codec, tpa6140a2_controls, 350 return snd_soc_add_controls(codec, tpa6140a2_controls,
406 ARRAY_SIZE(tpa6140a2_controls)); 351 ARRAY_SIZE(tpa6140a2_controls));
407 else 352 else
408 return snd_soc_add_controls(codec, tpa6130a2_controls, 353 return snd_soc_add_controls(codec, tpa6130a2_controls,
409 ARRAY_SIZE(tpa6130a2_controls)); 354 ARRAY_SIZE(tpa6130a2_controls));
410
411} 355}
412EXPORT_SYMBOL_GPL(tpa6130a2_add_controls); 356EXPORT_SYMBOL_GPL(tpa6130a2_add_controls);
413 357
diff --git a/sound/soc/codecs/tpa6130a2.h b/sound/soc/codecs/tpa6130a2.h
index 57e867fd86d1..5df49c8756b2 100644
--- a/sound/soc/codecs/tpa6130a2.h
+++ b/sound/soc/codecs/tpa6130a2.h
@@ -57,5 +57,6 @@
57#define TPA6130A2_VERSION_MASK (0x0f) 57#define TPA6130A2_VERSION_MASK (0x0f)
58 58
59extern int tpa6130a2_add_controls(struct snd_soc_codec *codec); 59extern int tpa6130a2_add_controls(struct snd_soc_codec *codec);
60extern int tpa6130a2_stereo_enable(struct snd_soc_codec *codec, int enable);
60 61
61#endif /* __TPA6130A2_H__ */ 62#endif /* __TPA6130A2_H__ */
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index c173cf00f5cb..e4d464b937d6 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -1724,6 +1724,7 @@ static int twl4030_startup(struct snd_pcm_substream *substream,
1724 struct snd_soc_codec *codec = rtd->codec; 1724 struct snd_soc_codec *codec = rtd->codec;
1725 struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); 1725 struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
1726 1726
1727 snd_pcm_hw_constraint_msbits(substream->runtime, 0, 32, 24);
1727 if (twl4030->master_substream) { 1728 if (twl4030->master_substream) {
1728 twl4030->slave_substream = substream; 1729 twl4030->slave_substream = substream;
1729 /* The DAI has one configuration for playback and capture, so 1730 /* The DAI has one configuration for playback and capture, so
@@ -1848,7 +1849,7 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
1848 case SNDRV_PCM_FORMAT_S16_LE: 1849 case SNDRV_PCM_FORMAT_S16_LE:
1849 format |= TWL4030_DATA_WIDTH_16S_16W; 1850 format |= TWL4030_DATA_WIDTH_16S_16W;
1850 break; 1851 break;
1851 case SNDRV_PCM_FORMAT_S24_LE: 1852 case SNDRV_PCM_FORMAT_S32_LE:
1852 format |= TWL4030_DATA_WIDTH_32S_24W; 1853 format |= TWL4030_DATA_WIDTH_32S_24W;
1853 break; 1854 break;
1854 default: 1855 default:
@@ -2181,7 +2182,7 @@ static int twl4030_voice_set_tristate(struct snd_soc_dai *dai, int tristate)
2181} 2182}
2182 2183
2183#define TWL4030_RATES (SNDRV_PCM_RATE_8000_48000) 2184#define TWL4030_RATES (SNDRV_PCM_RATE_8000_48000)
2184#define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE) 2185#define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE)
2185 2186
2186static struct snd_soc_dai_ops twl4030_dai_hifi_ops = { 2187static struct snd_soc_dai_ops twl4030_dai_hifi_ops = {
2187 .startup = twl4030_startup, 2188 .startup = twl4030_startup,
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
index b92f2b737e4c..2f68f5949a63 100644
--- a/sound/soc/codecs/twl6040.c
+++ b/sound/soc/codecs/twl6040.c
@@ -39,8 +39,41 @@
39 39
40#include "twl6040.h" 40#include "twl6040.h"
41 41
42#define TWL6040_RATES (SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) 42#define TWL6040_RATES SNDRV_PCM_RATE_8000_96000
43#define TWL6040_FORMATS (SNDRV_PCM_FMTBIT_S32_LE) 43#define TWL6040_FORMATS (SNDRV_PCM_FMTBIT_S32_LE)
44
45#define TWL6040_OUTHS_0dB 0x00
46#define TWL6040_OUTHS_M30dB 0x0F
47#define TWL6040_OUTHF_0dB 0x03
48#define TWL6040_OUTHF_M52dB 0x1D
49
50#define TWL6040_RAMP_NONE 0
51#define TWL6040_RAMP_UP 1
52#define TWL6040_RAMP_DOWN 2
53
54#define TWL6040_HSL_VOL_MASK 0x0F
55#define TWL6040_HSL_VOL_SHIFT 0
56#define TWL6040_HSR_VOL_MASK 0xF0
57#define TWL6040_HSR_VOL_SHIFT 4
58#define TWL6040_HF_VOL_MASK 0x1F
59#define TWL6040_HF_VOL_SHIFT 0
60
61struct twl6040_output {
62 u16 active;
63 u16 left_vol;
64 u16 right_vol;
65 u16 left_step;
66 u16 right_step;
67 unsigned int step_delay;
68 u16 ramp;
69 u16 mute;
70 struct completion ramp_done;
71};
72
73struct twl6040_jack_data {
74 struct snd_soc_jack *jack;
75 int report;
76};
44 77
45/* codec private data */ 78/* codec private data */
46struct twl6040_data { 79struct twl6040_data {
@@ -52,6 +85,17 @@ struct twl6040_data {
52 unsigned int sysclk; 85 unsigned int sysclk;
53 struct snd_pcm_hw_constraint_list *sysclk_constraints; 86 struct snd_pcm_hw_constraint_list *sysclk_constraints;
54 struct completion ready; 87 struct completion ready;
88 struct twl6040_jack_data hs_jack;
89 struct snd_soc_codec *codec;
90 struct workqueue_struct *workqueue;
91 struct delayed_work delayed_work;
92 struct mutex mutex;
93 struct twl6040_output headset;
94 struct twl6040_output handsfree;
95 struct workqueue_struct *hf_workqueue;
96 struct workqueue_struct *hs_workqueue;
97 struct delayed_work hs_delayed_work;
98 struct delayed_work hf_delayed_work;
55}; 99};
56 100
57/* 101/*
@@ -200,7 +244,7 @@ static int twl6040_read_reg_volatile(struct snd_soc_codec *codec,
200 if (reg >= TWL6040_CACHEREGNUM) 244 if (reg >= TWL6040_CACHEREGNUM)
201 return -EIO; 245 return -EIO;
202 246
203 twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &value, reg); 247 twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &value, reg);
204 twl6040_write_reg_cache(codec, reg, value); 248 twl6040_write_reg_cache(codec, reg, value);
205 249
206 return value; 250 return value;
@@ -216,7 +260,7 @@ static int twl6040_write(struct snd_soc_codec *codec,
216 return -EIO; 260 return -EIO;
217 261
218 twl6040_write_reg_cache(codec, reg, value); 262 twl6040_write_reg_cache(codec, reg, value);
219 return twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value, reg); 263 return twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, value, reg);
220} 264}
221 265
222static void twl6040_init_vio_regs(struct snd_soc_codec *codec) 266static void twl6040_init_vio_regs(struct snd_soc_codec *codec)
@@ -253,6 +297,305 @@ static void twl6040_init_vdd_regs(struct snd_soc_codec *codec)
253 } 297 }
254} 298}
255 299
300/*
301 * Ramp HS PGA volume to minimise pops at stream startup and shutdown.
302 */
303static inline int twl6040_hs_ramp_step(struct snd_soc_codec *codec,
304 unsigned int left_step, unsigned int right_step)
305{
306
307 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
308 struct twl6040_output *headset = &priv->headset;
309 int left_complete = 0, right_complete = 0;
310 u8 reg, val;
311
312 /* left channel */
313 left_step = (left_step > 0xF) ? 0xF : left_step;
314 reg = twl6040_read_reg_cache(codec, TWL6040_REG_HSGAIN);
315 val = (~reg & TWL6040_HSL_VOL_MASK);
316
317 if (headset->ramp == TWL6040_RAMP_UP) {
318 /* ramp step up */
319 if (val < headset->left_vol) {
320 val += left_step;
321 reg &= ~TWL6040_HSL_VOL_MASK;
322 twl6040_write(codec, TWL6040_REG_HSGAIN,
323 (reg | (~val & TWL6040_HSL_VOL_MASK)));
324 } else {
325 left_complete = 1;
326 }
327 } else if (headset->ramp == TWL6040_RAMP_DOWN) {
328 /* ramp step down */
329 if (val > 0x0) {
330 val -= left_step;
331 reg &= ~TWL6040_HSL_VOL_MASK;
332 twl6040_write(codec, TWL6040_REG_HSGAIN, reg |
333 (~val & TWL6040_HSL_VOL_MASK));
334 } else {
335 left_complete = 1;
336 }
337 }
338
339 /* right channel */
340 right_step = (right_step > 0xF) ? 0xF : right_step;
341 reg = twl6040_read_reg_cache(codec, TWL6040_REG_HSGAIN);
342 val = (~reg & TWL6040_HSR_VOL_MASK) >> TWL6040_HSR_VOL_SHIFT;
343
344 if (headset->ramp == TWL6040_RAMP_UP) {
345 /* ramp step up */
346 if (val < headset->right_vol) {
347 val += right_step;
348 reg &= ~TWL6040_HSR_VOL_MASK;
349 twl6040_write(codec, TWL6040_REG_HSGAIN,
350 (reg | (~val << TWL6040_HSR_VOL_SHIFT)));
351 } else {
352 right_complete = 1;
353 }
354 } else if (headset->ramp == TWL6040_RAMP_DOWN) {
355 /* ramp step down */
356 if (val > 0x0) {
357 val -= right_step;
358 reg &= ~TWL6040_HSR_VOL_MASK;
359 twl6040_write(codec, TWL6040_REG_HSGAIN,
360 reg | (~val << TWL6040_HSR_VOL_SHIFT));
361 } else {
362 right_complete = 1;
363 }
364 }
365
366 return left_complete & right_complete;
367}
368
369/*
370 * Ramp HF PGA volume to minimise pops at stream startup and shutdown.
371 */
372static inline int twl6040_hf_ramp_step(struct snd_soc_codec *codec,
373 unsigned int left_step, unsigned int right_step)
374{
375 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
376 struct twl6040_output *handsfree = &priv->handsfree;
377 int left_complete = 0, right_complete = 0;
378 u16 reg, val;
379
380 /* left channel */
381 left_step = (left_step > 0x1D) ? 0x1D : left_step;
382 reg = twl6040_read_reg_cache(codec, TWL6040_REG_HFLGAIN);
383 reg = 0x1D - reg;
384 val = (reg & TWL6040_HF_VOL_MASK);
385 if (handsfree->ramp == TWL6040_RAMP_UP) {
386 /* ramp step up */
387 if (val < handsfree->left_vol) {
388 val += left_step;
389 reg &= ~TWL6040_HF_VOL_MASK;
390 twl6040_write(codec, TWL6040_REG_HFLGAIN,
391 reg | (0x1D - val));
392 } else {
393 left_complete = 1;
394 }
395 } else if (handsfree->ramp == TWL6040_RAMP_DOWN) {
396 /* ramp step down */
397 if (val > 0) {
398 val -= left_step;
399 reg &= ~TWL6040_HF_VOL_MASK;
400 twl6040_write(codec, TWL6040_REG_HFLGAIN,
401 reg | (0x1D - val));
402 } else {
403 left_complete = 1;
404 }
405 }
406
407 /* right channel */
408 right_step = (right_step > 0x1D) ? 0x1D : right_step;
409 reg = twl6040_read_reg_cache(codec, TWL6040_REG_HFRGAIN);
410 reg = 0x1D - reg;
411 val = (reg & TWL6040_HF_VOL_MASK);
412 if (handsfree->ramp == TWL6040_RAMP_UP) {
413 /* ramp step up */
414 if (val < handsfree->right_vol) {
415 val += right_step;
416 reg &= ~TWL6040_HF_VOL_MASK;
417 twl6040_write(codec, TWL6040_REG_HFRGAIN,
418 reg | (0x1D - val));
419 } else {
420 right_complete = 1;
421 }
422 } else if (handsfree->ramp == TWL6040_RAMP_DOWN) {
423 /* ramp step down */
424 if (val > 0) {
425 val -= right_step;
426 reg &= ~TWL6040_HF_VOL_MASK;
427 twl6040_write(codec, TWL6040_REG_HFRGAIN,
428 reg | (0x1D - val));
429 }
430 }
431
432 return left_complete & right_complete;
433}
434
435/*
436 * This work ramps both output PGAs at stream start/stop time to
437 * minimise pop associated with DAPM power switching.
438 */
439static void twl6040_pga_hs_work(struct work_struct *work)
440{
441 struct twl6040_data *priv =
442 container_of(work, struct twl6040_data, hs_delayed_work.work);
443 struct snd_soc_codec *codec = priv->codec;
444 struct twl6040_output *headset = &priv->headset;
445 unsigned int delay = headset->step_delay;
446 int i, headset_complete;
447
448 /* do we need to ramp at all ? */
449 if (headset->ramp == TWL6040_RAMP_NONE)
450 return;
451
452 /* HS PGA volumes have 4 bits of resolution to ramp */
453 for (i = 0; i <= 16; i++) {
454 headset_complete = 1;
455 if (headset->ramp != TWL6040_RAMP_NONE)
456 headset_complete = twl6040_hs_ramp_step(codec,
457 headset->left_step,
458 headset->right_step);
459
460 /* ramp finished ? */
461 if (headset_complete)
462 break;
463
464 /*
465 * TODO: tune: delay is longer over 0dB
466 * as increases are larger.
467 */
468 if (i >= 8)
469 schedule_timeout_interruptible(msecs_to_jiffies(delay +
470 (delay >> 1)));
471 else
472 schedule_timeout_interruptible(msecs_to_jiffies(delay));
473 }
474
475 if (headset->ramp == TWL6040_RAMP_DOWN) {
476 headset->active = 0;
477 complete(&headset->ramp_done);
478 } else {
479 headset->active = 1;
480 }
481 headset->ramp = TWL6040_RAMP_NONE;
482}
483
484static void twl6040_pga_hf_work(struct work_struct *work)
485{
486 struct twl6040_data *priv =
487 container_of(work, struct twl6040_data, hf_delayed_work.work);
488 struct snd_soc_codec *codec = priv->codec;
489 struct twl6040_output *handsfree = &priv->handsfree;
490 unsigned int delay = handsfree->step_delay;
491 int i, handsfree_complete;
492
493 /* do we need to ramp at all ? */
494 if (handsfree->ramp == TWL6040_RAMP_NONE)
495 return;
496
497 /* HF PGA volumes have 5 bits of resolution to ramp */
498 for (i = 0; i <= 32; i++) {
499 handsfree_complete = 1;
500 if (handsfree->ramp != TWL6040_RAMP_NONE)
501 handsfree_complete = twl6040_hf_ramp_step(codec,
502 handsfree->left_step,
503 handsfree->right_step);
504
505 /* ramp finished ? */
506 if (handsfree_complete)
507 break;
508
509 /*
510 * TODO: tune: delay is longer over 0dB
511 * as increases are larger.
512 */
513 if (i >= 16)
514 schedule_timeout_interruptible(msecs_to_jiffies(delay +
515 (delay >> 1)));
516 else
517 schedule_timeout_interruptible(msecs_to_jiffies(delay));
518 }
519
520
521 if (handsfree->ramp == TWL6040_RAMP_DOWN) {
522 handsfree->active = 0;
523 complete(&handsfree->ramp_done);
524 } else
525 handsfree->active = 1;
526 handsfree->ramp = TWL6040_RAMP_NONE;
527}
528
529static int pga_event(struct snd_soc_dapm_widget *w,
530 struct snd_kcontrol *kcontrol, int event)
531{
532 struct snd_soc_codec *codec = w->codec;
533 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
534 struct twl6040_output *out;
535 struct delayed_work *work;
536 struct workqueue_struct *queue;
537
538 switch (w->shift) {
539 case 2:
540 case 3:
541 out = &priv->headset;
542 work = &priv->hs_delayed_work;
543 queue = priv->hs_workqueue;
544 out->step_delay = 5; /* 5 ms between volume ramp steps */
545 break;
546 case 4:
547 out = &priv->handsfree;
548 work = &priv->hf_delayed_work;
549 queue = priv->hf_workqueue;
550 out->step_delay = 5; /* 5 ms between volume ramp steps */
551 if (SND_SOC_DAPM_EVENT_ON(event))
552 priv->non_lp++;
553 else
554 priv->non_lp--;
555 break;
556 default:
557 return -1;
558 }
559
560 switch (event) {
561 case SND_SOC_DAPM_POST_PMU:
562 if (out->active)
563 break;
564
565 /* don't use volume ramp for power-up */
566 out->left_step = out->left_vol;
567 out->right_step = out->right_vol;
568
569 if (!delayed_work_pending(work)) {
570 out->ramp = TWL6040_RAMP_UP;
571 queue_delayed_work(queue, work,
572 msecs_to_jiffies(1));
573 }
574 break;
575
576 case SND_SOC_DAPM_PRE_PMD:
577 if (!out->active)
578 break;
579
580 if (!delayed_work_pending(work)) {
581 /* use volume ramp for power-down */
582 out->left_step = 1;
583 out->right_step = 1;
584 out->ramp = TWL6040_RAMP_DOWN;
585 INIT_COMPLETION(out->ramp_done);
586
587 queue_delayed_work(queue, work,
588 msecs_to_jiffies(1));
589
590 wait_for_completion_timeout(&out->ramp_done,
591 msecs_to_jiffies(2000));
592 }
593 break;
594 }
595
596 return 0;
597}
598
256/* twl6040 codec manual power-up sequence */ 599/* twl6040 codec manual power-up sequence */
257static void twl6040_power_up(struct snd_soc_codec *codec) 600static void twl6040_power_up(struct snd_soc_codec *codec)
258{ 601{
@@ -381,6 +724,47 @@ static int twl6040_power_mode_event(struct snd_soc_dapm_widget *w,
381 return 0; 724 return 0;
382} 725}
383 726
727void twl6040_hs_jack_report(struct snd_soc_codec *codec,
728 struct snd_soc_jack *jack, int report)
729{
730 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
731 int status;
732
733 mutex_lock(&priv->mutex);
734
735 /* Sync status */
736 status = twl6040_read_reg_volatile(codec, TWL6040_REG_STATUS);
737 if (status & TWL6040_PLUGCOMP)
738 snd_soc_jack_report(jack, report, report);
739 else
740 snd_soc_jack_report(jack, 0, report);
741
742 mutex_unlock(&priv->mutex);
743}
744
745void twl6040_hs_jack_detect(struct snd_soc_codec *codec,
746 struct snd_soc_jack *jack, int report)
747{
748 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
749 struct twl6040_jack_data *hs_jack = &priv->hs_jack;
750
751 hs_jack->jack = jack;
752 hs_jack->report = report;
753
754 twl6040_hs_jack_report(codec, hs_jack->jack, hs_jack->report);
755}
756EXPORT_SYMBOL_GPL(twl6040_hs_jack_detect);
757
758static void twl6040_accessory_work(struct work_struct *work)
759{
760 struct twl6040_data *priv = container_of(work,
761 struct twl6040_data, delayed_work.work);
762 struct snd_soc_codec *codec = priv->codec;
763 struct twl6040_jack_data *hs_jack = &priv->hs_jack;
764
765 twl6040_hs_jack_report(codec, hs_jack->jack, hs_jack->report);
766}
767
384/* audio interrupt handler */ 768/* audio interrupt handler */
385static irqreturn_t twl6040_naudint_handler(int irq, void *data) 769static irqreturn_t twl6040_naudint_handler(int irq, void *data)
386{ 770{
@@ -388,33 +772,180 @@ static irqreturn_t twl6040_naudint_handler(int irq, void *data)
388 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 772 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
389 u8 intid; 773 u8 intid;
390 774
391 twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &intid, TWL6040_REG_INTID); 775 twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &intid, TWL6040_REG_INTID);
392 776
393 switch (intid) { 777 if (intid & TWL6040_THINT)
394 case TWL6040_THINT:
395 dev_alert(codec->dev, "die temp over-limit detection\n"); 778 dev_alert(codec->dev, "die temp over-limit detection\n");
779
780 if ((intid & TWL6040_PLUGINT) || (intid & TWL6040_UNPLUGINT))
781 queue_delayed_work(priv->workqueue, &priv->delayed_work,
782 msecs_to_jiffies(200));
783
784 if (intid & TWL6040_HOOKINT)
785 dev_info(codec->dev, "hook detection\n");
786
787 if (intid & TWL6040_HFINT)
788 dev_alert(codec->dev, "hf drivers over current detection\n");
789
790 if (intid & TWL6040_VIBINT)
791 dev_alert(codec->dev, "vib drivers over current detection\n");
792
793 if (intid & TWL6040_READYINT)
794 complete(&priv->ready);
795
796 return IRQ_HANDLED;
797}
798
799static int twl6040_put_volsw(struct snd_kcontrol *kcontrol,
800 struct snd_ctl_elem_value *ucontrol)
801{
802 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
803 struct twl6040_data *twl6040_priv = snd_soc_codec_get_drvdata(codec);
804 struct twl6040_output *out = NULL;
805 struct soc_mixer_control *mc =
806 (struct soc_mixer_control *)kcontrol->private_value;
807 int ret;
808 unsigned int reg = mc->reg;
809
810 /* For HS and HF we shadow the values and only actually write
811 * them out when active in order to ensure the amplifier comes on
812 * as quietly as possible. */
813 switch (reg) {
814 case TWL6040_REG_HSGAIN:
815 out = &twl6040_priv->headset;
396 break; 816 break;
397 case TWL6040_PLUGINT: 817 default:
398 case TWL6040_UNPLUGINT:
399 case TWL6040_HOOKINT:
400 break; 818 break;
401 case TWL6040_HFINT: 819 }
402 dev_alert(codec->dev, "hf drivers over current detection\n"); 820
821 if (out) {
822 out->left_vol = ucontrol->value.integer.value[0];
823 out->right_vol = ucontrol->value.integer.value[1];
824 if (!out->active)
825 return 1;
826 }
827
828 ret = snd_soc_put_volsw(kcontrol, ucontrol);
829 if (ret < 0)
830 return ret;
831
832 return 1;
833}
834
835static int twl6040_get_volsw(struct snd_kcontrol *kcontrol,
836 struct snd_ctl_elem_value *ucontrol)
837{
838 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
839 struct twl6040_data *twl6040_priv = snd_soc_codec_get_drvdata(codec);
840 struct twl6040_output *out = &twl6040_priv->headset;
841 struct soc_mixer_control *mc =
842 (struct soc_mixer_control *)kcontrol->private_value;
843 unsigned int reg = mc->reg;
844
845 switch (reg) {
846 case TWL6040_REG_HSGAIN:
847 out = &twl6040_priv->headset;
848 ucontrol->value.integer.value[0] = out->left_vol;
849 ucontrol->value.integer.value[1] = out->right_vol;
850 return 0;
851
852 default:
403 break; 853 break;
404 case TWL6040_VIBINT: 854 }
405 dev_alert(codec->dev, "vib drivers over current detection\n"); 855
856 return snd_soc_get_volsw(kcontrol, ucontrol);
857}
858
859static int twl6040_put_volsw_2r_vu(struct snd_kcontrol *kcontrol,
860 struct snd_ctl_elem_value *ucontrol)
861{
862 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
863 struct twl6040_data *twl6040_priv = snd_soc_codec_get_drvdata(codec);
864 struct twl6040_output *out = NULL;
865 struct soc_mixer_control *mc =
866 (struct soc_mixer_control *)kcontrol->private_value;
867 int ret;
868 unsigned int reg = mc->reg;
869
870 /* For HS and HF we shadow the values and only actually write
871 * them out when active in order to ensure the amplifier comes on
872 * as quietly as possible. */
873 switch (reg) {
874 case TWL6040_REG_HFLGAIN:
875 case TWL6040_REG_HFRGAIN:
876 out = &twl6040_priv->handsfree;
406 break; 877 break;
407 case TWL6040_READYINT: 878 default:
408 complete(&priv->ready);
409 break; 879 break;
880 }
881
882 if (out) {
883 out->left_vol = ucontrol->value.integer.value[0];
884 out->right_vol = ucontrol->value.integer.value[1];
885 if (!out->active)
886 return 1;
887 }
888
889 ret = snd_soc_put_volsw_2r(kcontrol, ucontrol);
890 if (ret < 0)
891 return ret;
892
893 return 1;
894}
895
896static int twl6040_get_volsw_2r(struct snd_kcontrol *kcontrol,
897 struct snd_ctl_elem_value *ucontrol)
898{
899 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
900 struct twl6040_data *twl6040_priv = snd_soc_codec_get_drvdata(codec);
901 struct twl6040_output *out = &twl6040_priv->handsfree;
902 struct soc_mixer_control *mc =
903 (struct soc_mixer_control *)kcontrol->private_value;
904 unsigned int reg = mc->reg;
905
906 /* If these are cached registers use the cache */
907 switch (reg) {
908 case TWL6040_REG_HFLGAIN:
909 case TWL6040_REG_HFRGAIN:
910 out = &twl6040_priv->handsfree;
911 ucontrol->value.integer.value[0] = out->left_vol;
912 ucontrol->value.integer.value[1] = out->right_vol;
913 return 0;
914
410 default: 915 default:
411 dev_err(codec->dev, "unknown audio interrupt %d\n", intid);
412 break; 916 break;
413 } 917 }
414 918
415 return IRQ_HANDLED; 919 return snd_soc_get_volsw_2r(kcontrol, ucontrol);
416} 920}
417 921
922/* double control with volume update */
923#define SOC_TWL6040_DOUBLE_TLV(xname, xreg, shift_left, shift_right, xmax,\
924 xinvert, tlv_array)\
925{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
926 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
927 SNDRV_CTL_ELEM_ACCESS_READWRITE,\
928 .tlv.p = (tlv_array), \
929 .info = snd_soc_info_volsw, .get = twl6040_get_volsw, \
930 .put = twl6040_put_volsw, \
931 .private_value = (unsigned long)&(struct soc_mixer_control) \
932 {.reg = xreg, .shift = shift_left, .rshift = shift_right,\
933 .max = xmax, .platform_max = xmax, .invert = xinvert} }
934
935/* double control with volume update */
936#define SOC_TWL6040_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax,\
937 xinvert, tlv_array)\
938{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
939 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
940 SNDRV_CTL_ELEM_ACCESS_READWRITE | \
941 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
942 .tlv.p = (tlv_array), \
943 .info = snd_soc_info_volsw_2r, \
944 .get = twl6040_get_volsw_2r, .put = twl6040_put_volsw_2r_vu, \
945 .private_value = (unsigned long)&(struct soc_mixer_control) \
946 {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
947 .rshift = xshift, .max = xmax, .invert = xinvert}, }
948
418/* 949/*
419 * MICATT volume control: 950 * MICATT volume control:
420 * from -6 to 0 dB in 6 dB steps 951 * from -6 to 0 dB in 6 dB steps
@@ -423,9 +954,15 @@ static DECLARE_TLV_DB_SCALE(mic_preamp_tlv, -600, 600, 0);
423 954
424/* 955/*
425 * MICGAIN volume control: 956 * MICGAIN volume control:
426 * from 6 to 30 dB in 6 dB steps 957 * from -6 to 30 dB in 6 dB steps
958 */
959static DECLARE_TLV_DB_SCALE(mic_amp_tlv, -600, 600, 0);
960
961/*
962 * AFMGAIN volume control:
963 * from 18 to 24 dB in 6 dB steps
427 */ 964 */
428static DECLARE_TLV_DB_SCALE(mic_amp_tlv, 600, 600, 0); 965static DECLARE_TLV_DB_SCALE(afm_amp_tlv, 1800, 600, 0);
429 966
430/* 967/*
431 * HSGAIN volume control: 968 * HSGAIN volume control:
@@ -454,8 +991,30 @@ static const char *twl6040_amicr_texts[] =
454 {"Headset Mic", "Sub Mic", "Aux/FM Right", "Off"}; 991 {"Headset Mic", "Sub Mic", "Aux/FM Right", "Off"};
455 992
456static const struct soc_enum twl6040_enum[] = { 993static const struct soc_enum twl6040_enum[] = {
457 SOC_ENUM_SINGLE(TWL6040_REG_MICLCTL, 3, 3, twl6040_amicl_texts), 994 SOC_ENUM_SINGLE(TWL6040_REG_MICLCTL, 3, 4, twl6040_amicl_texts),
458 SOC_ENUM_SINGLE(TWL6040_REG_MICRCTL, 3, 3, twl6040_amicr_texts), 995 SOC_ENUM_SINGLE(TWL6040_REG_MICRCTL, 3, 4, twl6040_amicr_texts),
996};
997
998static const char *twl6040_hs_texts[] = {
999 "Off", "HS DAC", "Line-In amp"
1000};
1001
1002static const struct soc_enum twl6040_hs_enum[] = {
1003 SOC_ENUM_SINGLE(TWL6040_REG_HSLCTL, 5, ARRAY_SIZE(twl6040_hs_texts),
1004 twl6040_hs_texts),
1005 SOC_ENUM_SINGLE(TWL6040_REG_HSRCTL, 5, ARRAY_SIZE(twl6040_hs_texts),
1006 twl6040_hs_texts),
1007};
1008
1009static const char *twl6040_hf_texts[] = {
1010 "Off", "HF DAC", "Line-In amp"
1011};
1012
1013static const struct soc_enum twl6040_hf_enum[] = {
1014 SOC_ENUM_SINGLE(TWL6040_REG_HFLCTL, 2, ARRAY_SIZE(twl6040_hf_texts),
1015 twl6040_hf_texts),
1016 SOC_ENUM_SINGLE(TWL6040_REG_HFRCTL, 2, ARRAY_SIZE(twl6040_hf_texts),
1017 twl6040_hf_texts),
459}; 1018};
460 1019
461static const struct snd_kcontrol_new amicl_control = 1020static const struct snd_kcontrol_new amicl_control =
@@ -465,18 +1024,18 @@ static const struct snd_kcontrol_new amicr_control =
465 SOC_DAPM_ENUM("Route", twl6040_enum[1]); 1024 SOC_DAPM_ENUM("Route", twl6040_enum[1]);
466 1025
467/* Headset DAC playback switches */ 1026/* Headset DAC playback switches */
468static const struct snd_kcontrol_new hsdacl_switch_controls = 1027static const struct snd_kcontrol_new hsl_mux_controls =
469 SOC_DAPM_SINGLE("Switch", TWL6040_REG_HSLCTL, 5, 1, 0); 1028 SOC_DAPM_ENUM("Route", twl6040_hs_enum[0]);
470 1029
471static const struct snd_kcontrol_new hsdacr_switch_controls = 1030static const struct snd_kcontrol_new hsr_mux_controls =
472 SOC_DAPM_SINGLE("Switch", TWL6040_REG_HSRCTL, 5, 1, 0); 1031 SOC_DAPM_ENUM("Route", twl6040_hs_enum[1]);
473 1032
474/* Handsfree DAC playback switches */ 1033/* Handsfree DAC playback switches */
475static const struct snd_kcontrol_new hfdacl_switch_controls = 1034static const struct snd_kcontrol_new hfl_mux_controls =
476 SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFLCTL, 2, 1, 0); 1035 SOC_DAPM_ENUM("Route", twl6040_hf_enum[0]);
477 1036
478static const struct snd_kcontrol_new hfdacr_switch_controls = 1037static const struct snd_kcontrol_new hfr_mux_controls =
479 SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFRCTL, 2, 1, 0); 1038 SOC_DAPM_ENUM("Route", twl6040_hf_enum[1]);
480 1039
481static const struct snd_kcontrol_new ep_driver_switch_controls = 1040static const struct snd_kcontrol_new ep_driver_switch_controls =
482 SOC_DAPM_SINGLE("Switch", TWL6040_REG_EARCTL, 0, 1, 0); 1041 SOC_DAPM_SINGLE("Switch", TWL6040_REG_EARCTL, 0, 1, 0);
@@ -488,10 +1047,14 @@ static const struct snd_kcontrol_new twl6040_snd_controls[] = {
488 SOC_DOUBLE_TLV("Capture Volume", 1047 SOC_DOUBLE_TLV("Capture Volume",
489 TWL6040_REG_MICGAIN, 0, 3, 4, 0, mic_amp_tlv), 1048 TWL6040_REG_MICGAIN, 0, 3, 4, 0, mic_amp_tlv),
490 1049
1050 /* AFM gains */
1051 SOC_DOUBLE_TLV("Aux FM Volume",
1052 TWL6040_REG_LINEGAIN, 0, 4, 0xF, 0, afm_amp_tlv),
1053
491 /* Playback gains */ 1054 /* Playback gains */
492 SOC_DOUBLE_TLV("Headset Playback Volume", 1055 SOC_TWL6040_DOUBLE_TLV("Headset Playback Volume",
493 TWL6040_REG_HSGAIN, 0, 4, 0xF, 1, hs_tlv), 1056 TWL6040_REG_HSGAIN, 0, 4, 0xF, 1, hs_tlv),
494 SOC_DOUBLE_R_TLV("Handsfree Playback Volume", 1057 SOC_TWL6040_DOUBLE_R_TLV("Handsfree Playback Volume",
495 TWL6040_REG_HFLGAIN, TWL6040_REG_HFRGAIN, 0, 0x1D, 1, hf_tlv), 1058 TWL6040_REG_HFLGAIN, TWL6040_REG_HFRGAIN, 0, 0x1D, 1, hf_tlv),
496 SOC_SINGLE_TLV("Earphone Playback Volume", 1059 SOC_SINGLE_TLV("Earphone Playback Volume",
497 TWL6040_REG_EARCTL, 1, 0xF, 1, ep_tlv), 1060 TWL6040_REG_EARCTL, 1, 0xF, 1, ep_tlv),
@@ -524,6 +1087,12 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {
524 SND_SOC_DAPM_PGA("MicAmpR", 1087 SND_SOC_DAPM_PGA("MicAmpR",
525 TWL6040_REG_MICRCTL, 0, 0, NULL, 0), 1088 TWL6040_REG_MICRCTL, 0, 0, NULL, 0),
526 1089
1090 /* Auxiliary FM PGAs */
1091 SND_SOC_DAPM_PGA("AFMAmpL",
1092 TWL6040_REG_MICLCTL, 1, 0, NULL, 0),
1093 SND_SOC_DAPM_PGA("AFMAmpR",
1094 TWL6040_REG_MICRCTL, 1, 0, NULL, 0),
1095
527 /* ADCs */ 1096 /* ADCs */
528 SND_SOC_DAPM_ADC("ADC Left", "Left Front Capture", 1097 SND_SOC_DAPM_ADC("ADC Left", "Left Front Capture",
529 TWL6040_REG_MICLCTL, 2, 0), 1098 TWL6040_REG_MICLCTL, 2, 0),
@@ -558,29 +1127,33 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {
558 twl6040_power_mode_event, 1127 twl6040_power_mode_event,
559 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 1128 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
560 1129
561 /* Analog playback switches */ 1130 SND_SOC_DAPM_MUX("HF Left Playback",
562 SND_SOC_DAPM_SWITCH("HSDAC Left Playback", 1131 SND_SOC_NOPM, 0, 0, &hfl_mux_controls),
563 SND_SOC_NOPM, 0, 0, &hsdacl_switch_controls), 1132 SND_SOC_DAPM_MUX("HF Right Playback",
564 SND_SOC_DAPM_SWITCH("HSDAC Right Playback", 1133 SND_SOC_NOPM, 0, 0, &hfr_mux_controls),
565 SND_SOC_NOPM, 0, 0, &hsdacr_switch_controls), 1134 /* Analog playback Muxes */
566 SND_SOC_DAPM_SWITCH("HFDAC Left Playback", 1135 SND_SOC_DAPM_MUX("HS Left Playback",
567 SND_SOC_NOPM, 0, 0, &hfdacl_switch_controls), 1136 SND_SOC_NOPM, 0, 0, &hsl_mux_controls),
568 SND_SOC_DAPM_SWITCH("HFDAC Right Playback", 1137 SND_SOC_DAPM_MUX("HS Right Playback",
569 SND_SOC_NOPM, 0, 0, &hfdacr_switch_controls), 1138 SND_SOC_NOPM, 0, 0, &hsr_mux_controls),
570 1139
571 /* Analog playback drivers */ 1140 /* Analog playback drivers */
572 SND_SOC_DAPM_PGA_E("Handsfree Left Driver", 1141 SND_SOC_DAPM_PGA_E("Handsfree Left Driver",
573 TWL6040_REG_HFLCTL, 4, 0, NULL, 0, 1142 TWL6040_REG_HFLCTL, 4, 0, NULL, 0,
574 twl6040_power_mode_event, 1143 pga_event,
575 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 1144 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
576 SND_SOC_DAPM_PGA_E("Handsfree Right Driver", 1145 SND_SOC_DAPM_PGA_E("Handsfree Right Driver",
577 TWL6040_REG_HFRCTL, 4, 0, NULL, 0, 1146 TWL6040_REG_HFRCTL, 4, 0, NULL, 0,
578 twl6040_power_mode_event, 1147 pga_event,
579 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 1148 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
580 SND_SOC_DAPM_PGA("Headset Left Driver", 1149 SND_SOC_DAPM_PGA_E("Headset Left Driver",
581 TWL6040_REG_HSLCTL, 2, 0, NULL, 0), 1150 TWL6040_REG_HSLCTL, 2, 0, NULL, 0,
582 SND_SOC_DAPM_PGA("Headset Right Driver", 1151 pga_event,
583 TWL6040_REG_HSRCTL, 2, 0, NULL, 0), 1152 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
1153 SND_SOC_DAPM_PGA_E("Headset Right Driver",
1154 TWL6040_REG_HSRCTL, 2, 0, NULL, 0,
1155 pga_event,
1156 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
584 SND_SOC_DAPM_SWITCH_E("Earphone Driver", 1157 SND_SOC_DAPM_SWITCH_E("Earphone Driver",
585 SND_SOC_NOPM, 0, 0, &ep_driver_switch_controls, 1158 SND_SOC_NOPM, 0, 0, &ep_driver_switch_controls,
586 twl6040_power_mode_event, 1159 twl6040_power_mode_event,
@@ -610,12 +1183,18 @@ static const struct snd_soc_dapm_route intercon[] = {
610 {"ADC Left", NULL, "MicAmpL"}, 1183 {"ADC Left", NULL, "MicAmpL"},
611 {"ADC Right", NULL, "MicAmpR"}, 1184 {"ADC Right", NULL, "MicAmpR"},
612 1185
613 /* Headset playback path */ 1186 /* AFM path */
614 {"HSDAC Left Playback", "Switch", "HSDAC Left"}, 1187 {"AFMAmpL", "NULL", "AFML"},
615 {"HSDAC Right Playback", "Switch", "HSDAC Right"}, 1188 {"AFMAmpR", "NULL", "AFMR"},
1189
1190 {"HS Left Playback", "HS DAC", "HSDAC Left"},
1191 {"HS Left Playback", "Line-In amp", "AFMAmpL"},
616 1192
617 {"Headset Left Driver", NULL, "HSDAC Left Playback"}, 1193 {"HS Right Playback", "HS DAC", "HSDAC Right"},
618 {"Headset Right Driver", NULL, "HSDAC Right Playback"}, 1194 {"HS Right Playback", "Line-In amp", "AFMAmpR"},
1195
1196 {"Headset Left Driver", "NULL", "HS Left Playback"},
1197 {"Headset Right Driver", "NULL", "HS Right Playback"},
619 1198
620 {"HSOL", NULL, "Headset Left Driver"}, 1199 {"HSOL", NULL, "Headset Left Driver"},
621 {"HSOR", NULL, "Headset Right Driver"}, 1200 {"HSOR", NULL, "Headset Right Driver"},
@@ -624,12 +1203,14 @@ static const struct snd_soc_dapm_route intercon[] = {
624 {"Earphone Driver", "Switch", "HSDAC Left"}, 1203 {"Earphone Driver", "Switch", "HSDAC Left"},
625 {"EP", NULL, "Earphone Driver"}, 1204 {"EP", NULL, "Earphone Driver"},
626 1205
627 /* Handsfree playback path */ 1206 {"HF Left Playback", "HF DAC", "HFDAC Left"},
628 {"HFDAC Left Playback", "Switch", "HFDAC Left"}, 1207 {"HF Left Playback", "Line-In amp", "AFMAmpL"},
629 {"HFDAC Right Playback", "Switch", "HFDAC Right"}, 1208
1209 {"HF Right Playback", "HF DAC", "HFDAC Right"},
1210 {"HF Right Playback", "Line-In amp", "AFMAmpR"},
630 1211
631 {"HFDAC Left PGA", NULL, "HFDAC Left Playback"}, 1212 {"HFDAC Left PGA", NULL, "HF Left Playback"},
632 {"HFDAC Right PGA", NULL, "HFDAC Right Playback"}, 1213 {"HFDAC Right PGA", NULL, "HF Right Playback"},
633 1214
634 {"Handsfree Left Driver", "Switch", "HFDAC Left PGA"}, 1215 {"Handsfree Left Driver", "Switch", "HFDAC Left PGA"},
635 {"Handsfree Right Driver", "Switch", "HFDAC Right PGA"}, 1216 {"Handsfree Right Driver", "Switch", "HFDAC Right PGA"},
@@ -658,10 +1239,10 @@ static int twl6040_power_up_completion(struct snd_soc_codec *codec,
658 u8 intid; 1239 u8 intid;
659 1240
660 time_left = wait_for_completion_timeout(&priv->ready, 1241 time_left = wait_for_completion_timeout(&priv->ready,
661 msecs_to_jiffies(48)); 1242 msecs_to_jiffies(144));
662 1243
663 if (!time_left) { 1244 if (!time_left) {
664 twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &intid, 1245 twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &intid,
665 TWL6040_REG_INTID); 1246 TWL6040_REG_INTID);
666 if (!(intid & TWL6040_READYINT)) { 1247 if (!(intid & TWL6040_READYINT)) {
667 dev_err(codec->dev, "timeout waiting for READYINT\n"); 1248 dev_err(codec->dev, "timeout waiting for READYINT\n");
@@ -712,6 +1293,15 @@ static int twl6040_set_bias_level(struct snd_soc_codec *codec,
712 1293
713 /* initialize vdd/vss registers with reg_cache */ 1294 /* initialize vdd/vss registers with reg_cache */
714 twl6040_init_vdd_regs(codec); 1295 twl6040_init_vdd_regs(codec);
1296
1297 /* Set external boost GPO */
1298 twl6040_write(codec, TWL6040_REG_GPOCTL, 0x02);
1299
1300 /* Set initial minimal gain values */
1301 twl6040_write(codec, TWL6040_REG_HSGAIN, 0xFF);
1302 twl6040_write(codec, TWL6040_REG_EARCTL, 0x1E);
1303 twl6040_write(codec, TWL6040_REG_HFLGAIN, 0x1D);
1304 twl6040_write(codec, TWL6040_REG_HFRGAIN, 0x1D);
715 break; 1305 break;
716 case SND_SOC_BIAS_OFF: 1306 case SND_SOC_BIAS_OFF:
717 if (!priv->codec_powered) 1307 if (!priv->codec_powered)
@@ -771,23 +1361,6 @@ static int twl6040_startup(struct snd_pcm_substream *substream,
771 struct snd_soc_codec *codec = rtd->codec; 1361 struct snd_soc_codec *codec = rtd->codec;
772 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 1362 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
773 1363
774 if (!priv->sysclk) {
775 dev_err(codec->dev,
776 "no mclk configured, call set_sysclk() on init\n");
777 return -EINVAL;
778 }
779
780 /*
781 * capture is not supported at 17.64 MHz,
782 * it's reserved for headset low-power playback scenario
783 */
784 if ((priv->sysclk == 17640000) && substream->stream) {
785 dev_err(codec->dev,
786 "capture mode is not supported at %dHz\n",
787 priv->sysclk);
788 return -EINVAL;
789 }
790
791 snd_pcm_hw_constraint_list(substream->runtime, 0, 1364 snd_pcm_hw_constraint_list(substream->runtime, 0,
792 SNDRV_PCM_HW_PARAM_RATE, 1365 SNDRV_PCM_HW_PARAM_RATE,
793 priv->sysclk_constraints); 1366 priv->sysclk_constraints);
@@ -813,10 +1386,17 @@ static int twl6040_hw_params(struct snd_pcm_substream *substream,
813 1386
814 rate = params_rate(params); 1387 rate = params_rate(params);
815 switch (rate) { 1388 switch (rate) {
1389 case 11250:
1390 case 22500:
1391 case 44100:
816 case 88200: 1392 case 88200:
817 lppllctl |= TWL6040_LPLLFIN; 1393 lppllctl |= TWL6040_LPLLFIN;
818 priv->sysclk = 17640000; 1394 priv->sysclk = 17640000;
819 break; 1395 break;
1396 case 8000:
1397 case 16000:
1398 case 32000:
1399 case 48000:
820 case 96000: 1400 case 96000:
821 lppllctl &= ~TWL6040_LPLLFIN; 1401 lppllctl &= ~TWL6040_LPLLFIN;
822 priv->sysclk = 19200000; 1402 priv->sysclk = 19200000;
@@ -831,31 +1411,37 @@ static int twl6040_hw_params(struct snd_pcm_substream *substream,
831 return 0; 1411 return 0;
832} 1412}
833 1413
834static int twl6040_trigger(struct snd_pcm_substream *substream, 1414static int twl6040_prepare(struct snd_pcm_substream *substream,
835 int cmd, struct snd_soc_dai *dai) 1415 struct snd_soc_dai *dai)
836{ 1416{
837 struct snd_soc_pcm_runtime *rtd = substream->private_data; 1417 struct snd_soc_pcm_runtime *rtd = substream->private_data;
838 struct snd_soc_codec *codec = rtd->codec; 1418 struct snd_soc_codec *codec = rtd->codec;
839 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 1419 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
840 1420
841 switch (cmd) { 1421 if (!priv->sysclk) {
842 case SNDRV_PCM_TRIGGER_START: 1422 dev_err(codec->dev,
843 case SNDRV_PCM_TRIGGER_RESUME: 1423 "no mclk configured, call set_sysclk() on init\n");
844 /* 1424 return -EINVAL;
845 * low-power playback mode is restricted 1425 }
846 * for headset path only 1426
847 */ 1427 /*
848 if ((priv->sysclk == 17640000) && priv->non_lp) { 1428 * capture is not supported at 17.64 MHz,
1429 * it's reserved for headset low-power playback scenario
1430 */
1431 if ((priv->sysclk == 17640000) &&
1432 substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
1433 dev_err(codec->dev,
1434 "capture mode is not supported at %dHz\n",
1435 priv->sysclk);
1436 return -EINVAL;
1437 }
1438
1439 if ((priv->sysclk == 17640000) && priv->non_lp) {
849 dev_err(codec->dev, 1440 dev_err(codec->dev,
850 "some enabled paths aren't supported at %dHz\n", 1441 "some enabled paths aren't supported at %dHz\n",
851 priv->sysclk); 1442 priv->sysclk);
852 return -EPERM; 1443 return -EPERM;
853 }
854 break;
855 default:
856 break;
857 } 1444 }
858
859 return 0; 1445 return 0;
860} 1446}
861 1447
@@ -969,7 +1555,7 @@ static int twl6040_set_dai_sysclk(struct snd_soc_dai *codec_dai,
969static struct snd_soc_dai_ops twl6040_dai_ops = { 1555static struct snd_soc_dai_ops twl6040_dai_ops = {
970 .startup = twl6040_startup, 1556 .startup = twl6040_startup,
971 .hw_params = twl6040_hw_params, 1557 .hw_params = twl6040_hw_params,
972 .trigger = twl6040_trigger, 1558 .prepare = twl6040_prepare,
973 .set_sysclk = twl6040_set_dai_sysclk, 1559 .set_sysclk = twl6040_set_dai_sysclk,
974}; 1560};
975 1561
@@ -1003,6 +1589,7 @@ static int twl6040_suspend(struct snd_soc_codec *codec, pm_message_t state)
1003static int twl6040_resume(struct snd_soc_codec *codec) 1589static int twl6040_resume(struct snd_soc_codec *codec)
1004{ 1590{
1005 twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1591 twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1592 twl6040_set_bias_level(codec, codec->dapm.suspend_bias_level);
1006 1593
1007 return 0; 1594 return 0;
1008} 1595}
@@ -1017,24 +1604,41 @@ static int twl6040_probe(struct snd_soc_codec *codec)
1017 struct twl6040_data *priv; 1604 struct twl6040_data *priv;
1018 int audpwron, naudint; 1605 int audpwron, naudint;
1019 int ret = 0; 1606 int ret = 0;
1607 u8 icrev, intmr = TWL6040_ALLINT_MSK;
1020 1608
1021 priv = kzalloc(sizeof(struct twl6040_data), GFP_KERNEL); 1609 priv = kzalloc(sizeof(struct twl6040_data), GFP_KERNEL);
1022 if (priv == NULL) 1610 if (priv == NULL)
1023 return -ENOMEM; 1611 return -ENOMEM;
1024 snd_soc_codec_set_drvdata(codec, priv); 1612 snd_soc_codec_set_drvdata(codec, priv);
1025 1613
1026 if (twl_codec) { 1614 priv->codec = codec;
1615
1616 twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &icrev, TWL6040_REG_ASICREV);
1617
1618 if (twl_codec && (icrev > 0))
1027 audpwron = twl_codec->audpwron_gpio; 1619 audpwron = twl_codec->audpwron_gpio;
1028 naudint = twl_codec->naudint_irq; 1620 else
1029 } else {
1030 audpwron = -EINVAL; 1621 audpwron = -EINVAL;
1622
1623 if (twl_codec)
1624 naudint = twl_codec->naudint_irq;
1625 else
1031 naudint = 0; 1626 naudint = 0;
1032 }
1033 1627
1034 priv->audpwron = audpwron; 1628 priv->audpwron = audpwron;
1035 priv->naudint = naudint; 1629 priv->naudint = naudint;
1630 priv->workqueue = create_singlethread_workqueue("twl6040-codec");
1631
1632 if (!priv->workqueue)
1633 goto work_err;
1634
1635 INIT_DELAYED_WORK(&priv->delayed_work, twl6040_accessory_work);
1636
1637 mutex_init(&priv->mutex);
1036 1638
1037 init_completion(&priv->ready); 1639 init_completion(&priv->ready);
1640 init_completion(&priv->headset.ramp_done);
1641 init_completion(&priv->handsfree.ramp_done);
1038 1642
1039 if (gpio_is_valid(audpwron)) { 1643 if (gpio_is_valid(audpwron)) {
1040 ret = gpio_request(audpwron, "audpwron"); 1644 ret = gpio_request(audpwron, "audpwron");
@@ -1046,7 +1650,14 @@ static int twl6040_probe(struct snd_soc_codec *codec)
1046 goto gpio2_err; 1650 goto gpio2_err;
1047 1651
1048 priv->codec_powered = 0; 1652 priv->codec_powered = 0;
1653
1654 /* enable only codec ready interrupt */
1655 intmr &= ~(TWL6040_READYMSK | TWL6040_PLUGMSK);
1656
1657 /* reset interrupt status to allow correct power up sequence */
1658 twl6040_read_reg_volatile(codec, TWL6040_REG_INTID);
1049 } 1659 }
1660 twl6040_write(codec, TWL6040_REG_INTMR, intmr);
1050 1661
1051 if (naudint) { 1662 if (naudint) {
1052 /* audio interrupt */ 1663 /* audio interrupt */
@@ -1056,25 +1667,29 @@ static int twl6040_probe(struct snd_soc_codec *codec)
1056 "twl6040_codec", codec); 1667 "twl6040_codec", codec);
1057 if (ret) 1668 if (ret)
1058 goto gpio2_err; 1669 goto gpio2_err;
1059 } else {
1060 if (gpio_is_valid(audpwron)) {
1061 /* enable only codec ready interrupt */
1062 twl6040_write_reg_cache(codec, TWL6040_REG_INTMR,
1063 ~TWL6040_READYMSK & TWL6040_ALLINT_MSK);
1064 } else {
1065 /* no interrupts at all */
1066 twl6040_write_reg_cache(codec, TWL6040_REG_INTMR,
1067 TWL6040_ALLINT_MSK);
1068 }
1069 } 1670 }
1070 1671
1071 /* init vio registers */ 1672 /* init vio registers */
1072 twl6040_init_vio_regs(codec); 1673 twl6040_init_vio_regs(codec);
1073 1674
1675 priv->hf_workqueue = create_singlethread_workqueue("twl6040-hf");
1676 if (priv->hf_workqueue == NULL) {
1677 ret = -ENOMEM;
1678 goto irq_err;
1679 }
1680 priv->hs_workqueue = create_singlethread_workqueue("twl6040-hs");
1681 if (priv->hs_workqueue == NULL) {
1682 ret = -ENOMEM;
1683 goto wq_err;
1684 }
1685
1686 INIT_DELAYED_WORK(&priv->hs_delayed_work, twl6040_pga_hs_work);
1687 INIT_DELAYED_WORK(&priv->hf_delayed_work, twl6040_pga_hf_work);
1688
1074 /* power on device */ 1689 /* power on device */
1075 ret = twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1690 ret = twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1076 if (ret) 1691 if (ret)
1077 goto irq_err; 1692 goto bias_err;
1078 1693
1079 snd_soc_add_controls(codec, twl6040_snd_controls, 1694 snd_soc_add_controls(codec, twl6040_snd_controls,
1080 ARRAY_SIZE(twl6040_snd_controls)); 1695 ARRAY_SIZE(twl6040_snd_controls));
@@ -1082,6 +1697,10 @@ static int twl6040_probe(struct snd_soc_codec *codec)
1082 1697
1083 return 0; 1698 return 0;
1084 1699
1700bias_err:
1701 destroy_workqueue(priv->hs_workqueue);
1702wq_err:
1703 destroy_workqueue(priv->hf_workqueue);
1085irq_err: 1704irq_err:
1086 if (naudint) 1705 if (naudint)
1087 free_irq(naudint, codec); 1706 free_irq(naudint, codec);
@@ -1089,6 +1708,8 @@ gpio2_err:
1089 if (gpio_is_valid(audpwron)) 1708 if (gpio_is_valid(audpwron))
1090 gpio_free(audpwron); 1709 gpio_free(audpwron);
1091gpio1_err: 1710gpio1_err:
1711 destroy_workqueue(priv->workqueue);
1712work_err:
1092 kfree(priv); 1713 kfree(priv);
1093 return ret; 1714 return ret;
1094} 1715}
@@ -1107,6 +1728,9 @@ static int twl6040_remove(struct snd_soc_codec *codec)
1107 if (naudint) 1728 if (naudint)
1108 free_irq(naudint, codec); 1729 free_irq(naudint, codec);
1109 1730
1731 destroy_workqueue(priv->workqueue);
1732 destroy_workqueue(priv->hf_workqueue);
1733 destroy_workqueue(priv->hs_workqueue);
1110 kfree(priv); 1734 kfree(priv);
1111 1735
1112 return 0; 1736 return 0;
diff --git a/sound/soc/codecs/twl6040.h b/sound/soc/codecs/twl6040.h
index f7c77fa58a3c..23aeed0963e6 100644
--- a/sound/soc/codecs/twl6040.h
+++ b/sound/soc/codecs/twl6040.h
@@ -79,6 +79,7 @@
79 79
80/* INTMR (0x04) fields */ 80/* INTMR (0x04) fields */
81 81
82#define TWL6040_PLUGMSK 0x02
82#define TWL6040_READYMSK 0x40 83#define TWL6040_READYMSK 0x40
83#define TWL6040_ALLINT_MSK 0x7B 84#define TWL6040_ALLINT_MSK 0x7B
84 85
@@ -135,4 +136,11 @@
135#define TWL6040_HPPLL_ID 1 136#define TWL6040_HPPLL_ID 1
136#define TWL6040_LPPLL_ID 2 137#define TWL6040_LPPLL_ID 2
137 138
139/* STATUS (0x2E) fields */
140
141#define TWL6040_PLUGCOMP 0x02
142
143void twl6040_hs_jack_detect(struct snd_soc_codec *codec,
144 struct snd_soc_jack *jack, int report);
145
138#endif /* End of __TWL6040_H__ */ 146#endif /* End of __TWL6040_H__ */
diff --git a/sound/soc/omap/sdp4430.c b/sound/soc/omap/sdp4430.c
index ebbd62fc447c..189e03900637 100644
--- a/sound/soc/omap/sdp4430.c
+++ b/sound/soc/omap/sdp4430.c
@@ -24,6 +24,7 @@
24#include <sound/core.h> 24#include <sound/core.h>
25#include <sound/pcm.h> 25#include <sound/pcm.h>
26#include <sound/soc.h> 26#include <sound/soc.h>
27#include <sound/jack.h>
27 28
28#include <asm/mach-types.h> 29#include <asm/mach-types.h>
29#include <plat/hardware.h> 30#include <plat/hardware.h>
@@ -65,6 +66,21 @@ static struct snd_soc_ops sdp4430_ops = {
65 .hw_params = sdp4430_hw_params, 66 .hw_params = sdp4430_hw_params,
66}; 67};
67 68
69/* Headset jack */
70static struct snd_soc_jack hs_jack;
71
72/*Headset jack detection DAPM pins */
73static struct snd_soc_jack_pin hs_jack_pins[] = {
74 {
75 .pin = "Headset Mic",
76 .mask = SND_JACK_MICROPHONE,
77 },
78 {
79 .pin = "Headset Stereophone",
80 .mask = SND_JACK_HEADPHONE,
81 },
82};
83
68static int sdp4430_get_power_mode(struct snd_kcontrol *kcontrol, 84static int sdp4430_get_power_mode(struct snd_kcontrol *kcontrol,
69 struct snd_ctl_elem_value *ucontrol) 85 struct snd_ctl_elem_value *ucontrol)
70{ 86{
@@ -101,6 +117,7 @@ static const struct snd_soc_dapm_widget sdp4430_twl6040_dapm_widgets[] = {
101 SND_SOC_DAPM_MIC("Headset Mic", NULL), 117 SND_SOC_DAPM_MIC("Headset Mic", NULL),
102 SND_SOC_DAPM_HP("Headset Stereophone", NULL), 118 SND_SOC_DAPM_HP("Headset Stereophone", NULL),
103 SND_SOC_DAPM_SPK("Earphone Spk", NULL), 119 SND_SOC_DAPM_SPK("Earphone Spk", NULL),
120 SND_SOC_DAPM_INPUT("Aux/FM Stereo In"),
104}; 121};
105 122
106static const struct snd_soc_dapm_route audio_map[] = { 123static const struct snd_soc_dapm_route audio_map[] = {
@@ -123,6 +140,10 @@ static const struct snd_soc_dapm_route audio_map[] = {
123 140
124 /* Earphone speaker */ 141 /* Earphone speaker */
125 {"Earphone Spk", NULL, "EP"}, 142 {"Earphone Spk", NULL, "EP"},
143
144 /* Aux/FM Stereo In: AFML, AFMR */
145 {"AFML", NULL, "Aux/FM Stereo In"},
146 {"AFMR", NULL, "Aux/FM Stereo In"},
126}; 147};
127 148
128static int sdp4430_twl6040_init(struct snd_soc_pcm_runtime *rtd) 149static int sdp4430_twl6040_init(struct snd_soc_pcm_runtime *rtd)
@@ -149,14 +170,28 @@ static int sdp4430_twl6040_init(struct snd_soc_pcm_runtime *rtd)
149 /* SDP4430 connected pins */ 170 /* SDP4430 connected pins */
150 snd_soc_dapm_enable_pin(dapm, "Ext Mic"); 171 snd_soc_dapm_enable_pin(dapm, "Ext Mic");
151 snd_soc_dapm_enable_pin(dapm, "Ext Spk"); 172 snd_soc_dapm_enable_pin(dapm, "Ext Spk");
173 snd_soc_dapm_enable_pin(dapm, "AFML");
174 snd_soc_dapm_enable_pin(dapm, "AFMR");
152 snd_soc_dapm_enable_pin(dapm, "Headset Mic"); 175 snd_soc_dapm_enable_pin(dapm, "Headset Mic");
153 snd_soc_dapm_enable_pin(dapm, "Headset Stereophone"); 176 snd_soc_dapm_enable_pin(dapm, "Headset Stereophone");
154 177
155 /* TWL6040 not connected pins */
156 snd_soc_dapm_nc_pin(dapm, "AFML");
157 snd_soc_dapm_nc_pin(dapm, "AFMR");
158
159 ret = snd_soc_dapm_sync(dapm); 178 ret = snd_soc_dapm_sync(dapm);
179 if (ret)
180 return ret;
181
182 /* Headset jack detection */
183 ret = snd_soc_jack_new(codec, "Headset Jack",
184 SND_JACK_HEADSET, &hs_jack);
185 if (ret)
186 return ret;
187
188 ret = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins),
189 hs_jack_pins);
190
191 if (machine_is_omap_4430sdp())
192 twl6040_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADSET);
193 else
194 snd_soc_jack_report(&hs_jack, SND_JACK_HEADSET, SND_JACK_HEADSET);
160 195
161 return ret; 196 return ret;
162} 197}