aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2010-11-23 06:45:05 -0500
committerTakashi Iwai <tiwai@suse.de>2010-11-23 06:45:05 -0500
commit2ab46c9390e74368a38ddb5aa525124518df8b69 (patch)
tree631e686fb11709add69f07b4fd1e5aaa10f232de /sound
parent9e18e1869f5ebac69f0d881fe97a198ebc0834db (diff)
parent5b3b0fa8fb0db9645b56361cdc9a9d0ddbc35e4d (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.c32
-rw-r--r--sound/soc/codecs/tpa6130a2.c6
-rw-r--r--sound/soc/codecs/twl4030.c37
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
64static LIST_HEAD(reset_list);
65
64struct aic3x_priv; 66struct aic3x_priv;
65 67
66struct aic3x_disable_nb { 68struct 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
1352static 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
1349static int aic3x_probe(struct snd_soc_codec *codec) 1365static 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);
1418err_get: 1437err_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);
1421err_gpio: 1441err_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
236static 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
236static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable) 246static 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
2259static int twl4030_soc_remove(struct snd_soc_codec *codec) 2274static 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
2293static int __devexit twl4030_codec_remove(struct platform_device *pdev) 2311static 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