diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-11-24 06:26:39 -0500 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-11-24 06:26:39 -0500 |
commit | a1c1f770e3653bfcd5dd664d8471f70d220e19f3 (patch) | |
tree | fdf3001d6608d8d8c715da7ea84c0d32fc33a9a7 /sound/soc/codecs/twl4030.c | |
parent | d50a87402e29e16a63152be810d9723ce4d87e37 (diff) | |
parent | 2ab46c9390e74368a38ddb5aa525124518df8b69 (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.c | 37 |
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 | ||
235 | static 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 | |||
235 | static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable) | 245 | static 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 | ||
2258 | static int twl4030_soc_remove(struct snd_soc_codec *codec) | 2273 | static 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 | ||
2292 | static int __devexit twl4030_codec_remove(struct platform_device *pdev) | 2310 | static 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 | ||