aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/twl4030.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2010-11-24 06:26:39 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2010-11-24 06:26:39 -0500
commita1c1f770e3653bfcd5dd664d8471f70d220e19f3 (patch)
treefdf3001d6608d8d8c715da7ea84c0d32fc33a9a7 /sound/soc/codecs/twl4030.c
parentd50a87402e29e16a63152be810d9723ce4d87e37 (diff)
parent2ab46c9390e74368a38ddb5aa525124518df8b69 (diff)
Merge branch 'topic/asoc' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6 into for-2.6.38
Diffstat (limited to 'sound/soc/codecs/twl4030.c')
-rw-r--r--sound/soc/codecs/twl4030.c37
1 files changed, 26 insertions, 11 deletions
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index 0488d5514cd8..c173cf00f5cb 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -232,6 +232,16 @@ static int twl4030_write(struct snd_soc_codec *codec,
232 return 0; 232 return 0;
233} 233}
234 234
235static inline void twl4030_wait_ms(int time)
236{
237 if (time < 60) {
238 time *= 1000;
239 usleep_range(time, time + 500);
240 } else {
241 msleep(time);
242 }
243}
244
235static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable) 245static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable)
236{ 246{
237 struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); 247 struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
@@ -337,10 +347,14 @@ static void twl4030_init_chip(struct snd_soc_codec *codec)
337 twl4030_write(codec, TWL4030_REG_ANAMICL, 347 twl4030_write(codec, TWL4030_REG_ANAMICL,
338 reg | TWL4030_CNCL_OFFSET_START); 348 reg | TWL4030_CNCL_OFFSET_START);
339 349
340 /* wait for offset cancellation to complete */ 350 /*
351 * Wait for offset cancellation to complete.
352 * Since this takes a while, do not slam the i2c.
353 * Start polling the status after ~20ms.
354 */
355 msleep(20);
341 do { 356 do {
342 /* this takes a little while, so don't slam i2c */ 357 usleep_range(1000, 2000);
343 udelay(2000);
344 twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte, 358 twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte,
345 TWL4030_REG_ANAMICL); 359 TWL4030_REG_ANAMICL);
346 } while ((i++ < 100) && 360 } while ((i++ < 100) &&
@@ -724,9 +738,12 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp)
724 /* Base values for ramp delay calculation: 2^19 - 2^26 */ 738 /* Base values for ramp delay calculation: 2^19 - 2^26 */
725 unsigned int ramp_base[] = {524288, 1048576, 2097152, 4194304, 739 unsigned int ramp_base[] = {524288, 1048576, 2097152, 4194304,
726 8388608, 16777216, 33554432, 67108864}; 740 8388608, 16777216, 33554432, 67108864};
741 unsigned int delay;
727 742
728 hs_gain = twl4030_read_reg_cache(codec, TWL4030_REG_HS_GAIN_SET); 743 hs_gain = twl4030_read_reg_cache(codec, TWL4030_REG_HS_GAIN_SET);
729 hs_pop = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET); 744 hs_pop = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET);
745 delay = (ramp_base[(hs_pop & TWL4030_RAMP_DELAY) >> 2] /
746 twl4030->sysclk) + 1;
730 747
731 /* Enable external mute control, this dramatically reduces 748 /* Enable external mute control, this dramatically reduces
732 * the pop-noise */ 749 * the pop-noise */
@@ -750,16 +767,14 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp)
750 hs_pop |= TWL4030_RAMP_EN; 767 hs_pop |= TWL4030_RAMP_EN;
751 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); 768 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
752 /* Wait ramp delay time + 1, so the VMID can settle */ 769 /* Wait ramp delay time + 1, so the VMID can settle */
753 mdelay((ramp_base[(hs_pop & TWL4030_RAMP_DELAY) >> 2] / 770 twl4030_wait_ms(delay);
754 twl4030->sysclk) + 1);
755 } else { 771 } else {
756 /* Headset ramp-down _not_ according to 772 /* Headset ramp-down _not_ according to
757 * the TRM, but in a way that it is working */ 773 * the TRM, but in a way that it is working */
758 hs_pop &= ~TWL4030_RAMP_EN; 774 hs_pop &= ~TWL4030_RAMP_EN;
759 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); 775 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
760 /* Wait ramp delay time + 1, so the VMID can settle */ 776 /* Wait ramp delay time + 1, so the VMID can settle */
761 mdelay((ramp_base[(hs_pop & TWL4030_RAMP_DELAY) >> 2] / 777 twl4030_wait_ms(delay);
762 twl4030->sysclk) + 1);
763 /* Bypass the reg_cache to mute the headset */ 778 /* Bypass the reg_cache to mute the headset */
764 twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, 779 twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
765 hs_gain & (~0x0f), 780 hs_gain & (~0x0f),
@@ -834,7 +849,7 @@ static int digimic_event(struct snd_soc_dapm_widget *w,
834 struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(w->codec); 849 struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(w->codec);
835 850
836 if (twl4030->digimic_delay) 851 if (twl4030->digimic_delay)
837 mdelay(twl4030->digimic_delay); 852 twl4030_wait_ms(twl4030->digimic_delay);
838 return 0; 853 return 0;
839} 854}
840 855
@@ -2257,9 +2272,12 @@ static int twl4030_soc_probe(struct snd_soc_codec *codec)
2257 2272
2258static int twl4030_soc_remove(struct snd_soc_codec *codec) 2273static int twl4030_soc_remove(struct snd_soc_codec *codec)
2259{ 2274{
2275 struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
2276
2260 /* Reset registers to their chip default before leaving */ 2277 /* Reset registers to their chip default before leaving */
2261 twl4030_reset_registers(codec); 2278 twl4030_reset_registers(codec);
2262 twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); 2279 twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF);
2280 kfree(twl4030);
2263 return 0; 2281 return 0;
2264} 2282}
2265 2283
@@ -2291,10 +2309,7 @@ static int __devinit twl4030_codec_probe(struct platform_device *pdev)
2291 2309
2292static int __devexit twl4030_codec_remove(struct platform_device *pdev) 2310static int __devexit twl4030_codec_remove(struct platform_device *pdev)
2293{ 2311{
2294 struct twl4030_priv *twl4030 = dev_get_drvdata(&pdev->dev);
2295
2296 snd_soc_unregister_codec(&pdev->dev); 2312 snd_soc_unregister_codec(&pdev->dev);
2297 kfree(twl4030);
2298 return 0; 2313 return 0;
2299} 2314}
2300 2315