diff options
author | Takashi Iwai <tiwai@suse.de> | 2010-11-23 06:45:05 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2010-11-23 06:45:05 -0500 |
commit | 2ab46c9390e74368a38ddb5aa525124518df8b69 (patch) | |
tree | 631e686fb11709add69f07b4fd1e5aaa10f232de /sound | |
parent | 9e18e1869f5ebac69f0d881fe97a198ebc0834db (diff) | |
parent | 5b3b0fa8fb0db9645b56361cdc9a9d0ddbc35e4d (diff) |
Merge branch 'for-2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/lrg/asoc-2.6 into topic/asoc
Conflicts:
sound/soc/codecs/tpa6130a2.c
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/codecs/tlv320aic3x.c | 32 | ||||
-rw-r--r-- | sound/soc/codecs/tpa6130a2.c | 6 | ||||
-rw-r--r-- | sound/soc/codecs/twl4030.c | 37 |
3 files changed, 56 insertions, 19 deletions
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index df726a5066e8..11a0a3d17055 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c | |||
@@ -61,6 +61,8 @@ static const char *aic3x_supply_names[AIC3X_NUM_SUPPLIES] = { | |||
61 | "DRVDD", /* ADC Analog and Output Driver Voltage */ | 61 | "DRVDD", /* ADC Analog and Output Driver Voltage */ |
62 | }; | 62 | }; |
63 | 63 | ||
64 | static LIST_HEAD(reset_list); | ||
65 | |||
64 | struct aic3x_priv; | 66 | struct aic3x_priv; |
65 | 67 | ||
66 | struct aic3x_disable_nb { | 68 | struct aic3x_disable_nb { |
@@ -77,6 +79,7 @@ struct aic3x_priv { | |||
77 | struct aic3x_setup_data *setup; | 79 | struct aic3x_setup_data *setup; |
78 | void *control_data; | 80 | void *control_data; |
79 | unsigned int sysclk; | 81 | unsigned int sysclk; |
82 | struct list_head list; | ||
80 | int master; | 83 | int master; |
81 | int gpio_reset; | 84 | int gpio_reset; |
82 | int power; | 85 | int power; |
@@ -1077,7 +1080,7 @@ static int aic3x_regulator_event(struct notifier_block *nb, | |||
1077 | * Put codec to reset and require cache sync as at least one | 1080 | * Put codec to reset and require cache sync as at least one |
1078 | * of the supplies was disabled | 1081 | * of the supplies was disabled |
1079 | */ | 1082 | */ |
1080 | if (aic3x->gpio_reset >= 0) | 1083 | if (gpio_is_valid(aic3x->gpio_reset)) |
1081 | gpio_set_value(aic3x->gpio_reset, 0); | 1084 | gpio_set_value(aic3x->gpio_reset, 0); |
1082 | aic3x->codec->cache_sync = 1; | 1085 | aic3x->codec->cache_sync = 1; |
1083 | } | 1086 | } |
@@ -1104,7 +1107,7 @@ static int aic3x_set_power(struct snd_soc_codec *codec, int power) | |||
1104 | if (!codec->cache_sync) | 1107 | if (!codec->cache_sync) |
1105 | goto out; | 1108 | goto out; |
1106 | 1109 | ||
1107 | if (aic3x->gpio_reset >= 0) { | 1110 | if (gpio_is_valid(aic3x->gpio_reset)) { |
1108 | udelay(1); | 1111 | udelay(1); |
1109 | gpio_set_value(aic3x->gpio_reset, 1); | 1112 | gpio_set_value(aic3x->gpio_reset, 1); |
1110 | } | 1113 | } |
@@ -1346,11 +1349,25 @@ static int aic3x_init(struct snd_soc_codec *codec) | |||
1346 | return 0; | 1349 | return 0; |
1347 | } | 1350 | } |
1348 | 1351 | ||
1352 | static bool aic3x_is_shared_reset(struct aic3x_priv *aic3x) | ||
1353 | { | ||
1354 | struct aic3x_priv *a; | ||
1355 | |||
1356 | list_for_each_entry(a, &reset_list, list) { | ||
1357 | if (gpio_is_valid(aic3x->gpio_reset) && | ||
1358 | aic3x->gpio_reset == a->gpio_reset) | ||
1359 | return true; | ||
1360 | } | ||
1361 | |||
1362 | return false; | ||
1363 | } | ||
1364 | |||
1349 | static int aic3x_probe(struct snd_soc_codec *codec) | 1365 | static int aic3x_probe(struct snd_soc_codec *codec) |
1350 | { | 1366 | { |
1351 | struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); | 1367 | struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); |
1352 | int ret, i; | 1368 | int ret, i; |
1353 | 1369 | ||
1370 | INIT_LIST_HEAD(&aic3x->list); | ||
1354 | codec->control_data = aic3x->control_data; | 1371 | codec->control_data = aic3x->control_data; |
1355 | aic3x->codec = codec; | 1372 | aic3x->codec = codec; |
1356 | codec->dapm.idle_bias_off = 1; | 1373 | codec->dapm.idle_bias_off = 1; |
@@ -1361,7 +1378,8 @@ static int aic3x_probe(struct snd_soc_codec *codec) | |||
1361 | return ret; | 1378 | return ret; |
1362 | } | 1379 | } |
1363 | 1380 | ||
1364 | if (aic3x->gpio_reset >= 0) { | 1381 | if (gpio_is_valid(aic3x->gpio_reset) && |
1382 | !aic3x_is_shared_reset(aic3x)) { | ||
1365 | ret = gpio_request(aic3x->gpio_reset, "tlv320aic3x reset"); | 1383 | ret = gpio_request(aic3x->gpio_reset, "tlv320aic3x reset"); |
1366 | if (ret != 0) | 1384 | if (ret != 0) |
1367 | goto err_gpio; | 1385 | goto err_gpio; |
@@ -1407,6 +1425,7 @@ static int aic3x_probe(struct snd_soc_codec *codec) | |||
1407 | snd_soc_add_controls(codec, &aic3x_classd_amp_gain_ctrl, 1); | 1425 | snd_soc_add_controls(codec, &aic3x_classd_amp_gain_ctrl, 1); |
1408 | 1426 | ||
1409 | aic3x_add_widgets(codec); | 1427 | aic3x_add_widgets(codec); |
1428 | list_add(&aic3x->list, &reset_list); | ||
1410 | 1429 | ||
1411 | return 0; | 1430 | return 0; |
1412 | 1431 | ||
@@ -1416,7 +1435,8 @@ err_notif: | |||
1416 | &aic3x->disable_nb[i].nb); | 1435 | &aic3x->disable_nb[i].nb); |
1417 | regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); | 1436 | regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); |
1418 | err_get: | 1437 | err_get: |
1419 | if (aic3x->gpio_reset >= 0) | 1438 | if (gpio_is_valid(aic3x->gpio_reset) && |
1439 | !aic3x_is_shared_reset(aic3x)) | ||
1420 | gpio_free(aic3x->gpio_reset); | 1440 | gpio_free(aic3x->gpio_reset); |
1421 | err_gpio: | 1441 | err_gpio: |
1422 | return ret; | 1442 | return ret; |
@@ -1428,7 +1448,9 @@ static int aic3x_remove(struct snd_soc_codec *codec) | |||
1428 | int i; | 1448 | int i; |
1429 | 1449 | ||
1430 | aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1450 | aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1431 | if (aic3x->gpio_reset >= 0) { | 1451 | list_del(&aic3x->list); |
1452 | if (gpio_is_valid(aic3x->gpio_reset) && | ||
1453 | !aic3x_is_shared_reset(aic3x)) { | ||
1432 | gpio_set_value(aic3x->gpio_reset, 0); | 1454 | gpio_set_value(aic3x->gpio_reset, 0); |
1433 | gpio_free(aic3x->gpio_reset); | 1455 | gpio_free(aic3x->gpio_reset); |
1434 | } | 1456 | } |
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index f9a92ea6b50a..d69d2f5f9570 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c | |||
@@ -126,9 +126,6 @@ static int tpa6130a2_power(int power) | |||
126 | 126 | ||
127 | mutex_lock(&data->mutex); | 127 | mutex_lock(&data->mutex); |
128 | if (power && !data->power_state) { | 128 | if (power && !data->power_state) { |
129 | /* Power on */ | ||
130 | if (data->power_gpio >= 0) | ||
131 | gpio_set_value(data->power_gpio, 1); | ||
132 | 129 | ||
133 | ret = regulator_enable(data->supply); | 130 | ret = regulator_enable(data->supply); |
134 | if (ret != 0) { | 131 | if (ret != 0) { |
@@ -136,6 +133,9 @@ static int tpa6130a2_power(int power) | |||
136 | "Failed to enable supply: %d\n", ret); | 133 | "Failed to enable supply: %d\n", ret); |
137 | goto exit; | 134 | goto exit; |
138 | } | 135 | } |
136 | /* Power on */ | ||
137 | if (data->power_gpio >= 0) | ||
138 | gpio_set_value(data->power_gpio, 1); | ||
139 | 139 | ||
140 | data->power_state = 1; | 140 | data->power_state = 1; |
141 | ret = tpa6130a2_initialize(); | 141 | ret = tpa6130a2_initialize(); |
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index f4602e8b67cc..50d3caf1191c 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c | |||
@@ -233,6 +233,16 @@ static int twl4030_write(struct snd_soc_codec *codec, | |||
233 | return 0; | 233 | return 0; |
234 | } | 234 | } |
235 | 235 | ||
236 | static inline void twl4030_wait_ms(int time) | ||
237 | { | ||
238 | if (time < 60) { | ||
239 | time *= 1000; | ||
240 | usleep_range(time, time + 500); | ||
241 | } else { | ||
242 | msleep(time); | ||
243 | } | ||
244 | } | ||
245 | |||
236 | static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable) | 246 | static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable) |
237 | { | 247 | { |
238 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | 248 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); |
@@ -338,10 +348,14 @@ static void twl4030_init_chip(struct snd_soc_codec *codec) | |||
338 | twl4030_write(codec, TWL4030_REG_ANAMICL, | 348 | twl4030_write(codec, TWL4030_REG_ANAMICL, |
339 | reg | TWL4030_CNCL_OFFSET_START); | 349 | reg | TWL4030_CNCL_OFFSET_START); |
340 | 350 | ||
341 | /* wait for offset cancellation to complete */ | 351 | /* |
352 | * Wait for offset cancellation to complete. | ||
353 | * Since this takes a while, do not slam the i2c. | ||
354 | * Start polling the status after ~20ms. | ||
355 | */ | ||
356 | msleep(20); | ||
342 | do { | 357 | do { |
343 | /* this takes a little while, so don't slam i2c */ | 358 | usleep_range(1000, 2000); |
344 | udelay(2000); | ||
345 | twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte, | 359 | twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte, |
346 | TWL4030_REG_ANAMICL); | 360 | TWL4030_REG_ANAMICL); |
347 | } while ((i++ < 100) && | 361 | } while ((i++ < 100) && |
@@ -725,9 +739,12 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp) | |||
725 | /* Base values for ramp delay calculation: 2^19 - 2^26 */ | 739 | /* Base values for ramp delay calculation: 2^19 - 2^26 */ |
726 | unsigned int ramp_base[] = {524288, 1048576, 2097152, 4194304, | 740 | unsigned int ramp_base[] = {524288, 1048576, 2097152, 4194304, |
727 | 8388608, 16777216, 33554432, 67108864}; | 741 | 8388608, 16777216, 33554432, 67108864}; |
742 | unsigned int delay; | ||
728 | 743 | ||
729 | hs_gain = twl4030_read_reg_cache(codec, TWL4030_REG_HS_GAIN_SET); | 744 | hs_gain = twl4030_read_reg_cache(codec, TWL4030_REG_HS_GAIN_SET); |
730 | hs_pop = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET); | 745 | hs_pop = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET); |
746 | delay = (ramp_base[(hs_pop & TWL4030_RAMP_DELAY) >> 2] / | ||
747 | twl4030->sysclk) + 1; | ||
731 | 748 | ||
732 | /* Enable external mute control, this dramatically reduces | 749 | /* Enable external mute control, this dramatically reduces |
733 | * the pop-noise */ | 750 | * the pop-noise */ |
@@ -751,16 +768,14 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp) | |||
751 | hs_pop |= TWL4030_RAMP_EN; | 768 | hs_pop |= TWL4030_RAMP_EN; |
752 | twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); | 769 | twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); |
753 | /* Wait ramp delay time + 1, so the VMID can settle */ | 770 | /* Wait ramp delay time + 1, so the VMID can settle */ |
754 | mdelay((ramp_base[(hs_pop & TWL4030_RAMP_DELAY) >> 2] / | 771 | twl4030_wait_ms(delay); |
755 | twl4030->sysclk) + 1); | ||
756 | } else { | 772 | } else { |
757 | /* Headset ramp-down _not_ according to | 773 | /* Headset ramp-down _not_ according to |
758 | * the TRM, but in a way that it is working */ | 774 | * the TRM, but in a way that it is working */ |
759 | hs_pop &= ~TWL4030_RAMP_EN; | 775 | hs_pop &= ~TWL4030_RAMP_EN; |
760 | twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); | 776 | twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); |
761 | /* Wait ramp delay time + 1, so the VMID can settle */ | 777 | /* Wait ramp delay time + 1, so the VMID can settle */ |
762 | mdelay((ramp_base[(hs_pop & TWL4030_RAMP_DELAY) >> 2] / | 778 | twl4030_wait_ms(delay); |
763 | twl4030->sysclk) + 1); | ||
764 | /* Bypass the reg_cache to mute the headset */ | 779 | /* Bypass the reg_cache to mute the headset */ |
765 | twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, | 780 | twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, |
766 | hs_gain & (~0x0f), | 781 | hs_gain & (~0x0f), |
@@ -835,7 +850,7 @@ static int digimic_event(struct snd_soc_dapm_widget *w, | |||
835 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(w->codec); | 850 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(w->codec); |
836 | 851 | ||
837 | if (twl4030->digimic_delay) | 852 | if (twl4030->digimic_delay) |
838 | mdelay(twl4030->digimic_delay); | 853 | twl4030_wait_ms(twl4030->digimic_delay); |
839 | return 0; | 854 | return 0; |
840 | } | 855 | } |
841 | 856 | ||
@@ -2258,9 +2273,12 @@ static int twl4030_soc_probe(struct snd_soc_codec *codec) | |||
2258 | 2273 | ||
2259 | static int twl4030_soc_remove(struct snd_soc_codec *codec) | 2274 | static int twl4030_soc_remove(struct snd_soc_codec *codec) |
2260 | { | 2275 | { |
2276 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | ||
2277 | |||
2261 | /* Reset registers to their chip default before leaving */ | 2278 | /* Reset registers to their chip default before leaving */ |
2262 | twl4030_reset_registers(codec); | 2279 | twl4030_reset_registers(codec); |
2263 | twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); | 2280 | twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); |
2281 | kfree(twl4030); | ||
2264 | return 0; | 2282 | return 0; |
2265 | } | 2283 | } |
2266 | 2284 | ||
@@ -2292,10 +2310,7 @@ static int __devinit twl4030_codec_probe(struct platform_device *pdev) | |||
2292 | 2310 | ||
2293 | static int __devexit twl4030_codec_remove(struct platform_device *pdev) | 2311 | static int __devexit twl4030_codec_remove(struct platform_device *pdev) |
2294 | { | 2312 | { |
2295 | struct twl4030_priv *twl4030 = dev_get_drvdata(&pdev->dev); | ||
2296 | |||
2297 | snd_soc_unregister_codec(&pdev->dev); | 2313 | snd_soc_unregister_codec(&pdev->dev); |
2298 | kfree(twl4030); | ||
2299 | return 0; | 2314 | return 0; |
2300 | } | 2315 | } |
2301 | 2316 | ||