aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
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 49b797ccc8d6..bfd036a2c83c 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -60,6 +60,8 @@ static const char *aic3x_supply_names[AIC3X_NUM_SUPPLIES] = {
60 "DRVDD", /* ADC Analog and Output Driver Voltage */ 60 "DRVDD", /* ADC Analog and Output Driver Voltage */
61}; 61};
62 62
63static LIST_HEAD(reset_list);
64
63struct aic3x_priv; 65struct aic3x_priv;
64 66
65struct aic3x_disable_nb { 67struct aic3x_disable_nb {
@@ -76,6 +78,7 @@ struct aic3x_priv {
76 struct aic3x_setup_data *setup; 78 struct aic3x_setup_data *setup;
77 void *control_data; 79 void *control_data;
78 unsigned int sysclk; 80 unsigned int sysclk;
81 struct list_head list;
79 int master; 82 int master;
80 int gpio_reset; 83 int gpio_reset;
81 int power; 84 int power;
@@ -1076,7 +1079,7 @@ static int aic3x_regulator_event(struct notifier_block *nb,
1076 * Put codec to reset and require cache sync as at least one 1079 * Put codec to reset and require cache sync as at least one
1077 * of the supplies was disabled 1080 * of the supplies was disabled
1078 */ 1081 */
1079 if (aic3x->gpio_reset >= 0) 1082 if (gpio_is_valid(aic3x->gpio_reset))
1080 gpio_set_value(aic3x->gpio_reset, 0); 1083 gpio_set_value(aic3x->gpio_reset, 0);
1081 aic3x->codec->cache_sync = 1; 1084 aic3x->codec->cache_sync = 1;
1082 } 1085 }
@@ -1103,7 +1106,7 @@ static int aic3x_set_power(struct snd_soc_codec *codec, int power)
1103 if (!codec->cache_sync) 1106 if (!codec->cache_sync)
1104 goto out; 1107 goto out;
1105 1108
1106 if (aic3x->gpio_reset >= 0) { 1109 if (gpio_is_valid(aic3x->gpio_reset)) {
1107 udelay(1); 1110 udelay(1);
1108 gpio_set_value(aic3x->gpio_reset, 1); 1111 gpio_set_value(aic3x->gpio_reset, 1);
1109 } 1112 }
@@ -1345,11 +1348,25 @@ static int aic3x_init(struct snd_soc_codec *codec)
1345 return 0; 1348 return 0;
1346} 1349}
1347 1350
1351static bool aic3x_is_shared_reset(struct aic3x_priv *aic3x)
1352{
1353 struct aic3x_priv *a;
1354
1355 list_for_each_entry(a, &reset_list, list) {
1356 if (gpio_is_valid(aic3x->gpio_reset) &&
1357 aic3x->gpio_reset == a->gpio_reset)
1358 return true;
1359 }
1360
1361 return false;
1362}
1363
1348static int aic3x_probe(struct snd_soc_codec *codec) 1364static int aic3x_probe(struct snd_soc_codec *codec)
1349{ 1365{
1350 struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); 1366 struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
1351 int ret, i; 1367 int ret, i;
1352 1368
1369 INIT_LIST_HEAD(&aic3x->list);
1353 codec->control_data = aic3x->control_data; 1370 codec->control_data = aic3x->control_data;
1354 aic3x->codec = codec; 1371 aic3x->codec = codec;
1355 codec->dapm.idle_bias_off = 1; 1372 codec->dapm.idle_bias_off = 1;
@@ -1360,7 +1377,8 @@ static int aic3x_probe(struct snd_soc_codec *codec)
1360 return ret; 1377 return ret;
1361 } 1378 }
1362 1379
1363 if (aic3x->gpio_reset >= 0) { 1380 if (gpio_is_valid(aic3x->gpio_reset) &&
1381 !aic3x_is_shared_reset(aic3x)) {
1364 ret = gpio_request(aic3x->gpio_reset, "tlv320aic3x reset"); 1382 ret = gpio_request(aic3x->gpio_reset, "tlv320aic3x reset");
1365 if (ret != 0) 1383 if (ret != 0)
1366 goto err_gpio; 1384 goto err_gpio;
@@ -1406,6 +1424,7 @@ static int aic3x_probe(struct snd_soc_codec *codec)
1406 snd_soc_add_controls(codec, &aic3x_classd_amp_gain_ctrl, 1); 1424 snd_soc_add_controls(codec, &aic3x_classd_amp_gain_ctrl, 1);
1407 1425
1408 aic3x_add_widgets(codec); 1426 aic3x_add_widgets(codec);
1427 list_add(&aic3x->list, &reset_list);
1409 1428
1410 return 0; 1429 return 0;
1411 1430
@@ -1415,7 +1434,8 @@ err_notif:
1415 &aic3x->disable_nb[i].nb); 1434 &aic3x->disable_nb[i].nb);
1416 regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); 1435 regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
1417err_get: 1436err_get:
1418 if (aic3x->gpio_reset >= 0) 1437 if (gpio_is_valid(aic3x->gpio_reset) &&
1438 !aic3x_is_shared_reset(aic3x))
1419 gpio_free(aic3x->gpio_reset); 1439 gpio_free(aic3x->gpio_reset);
1420err_gpio: 1440err_gpio:
1421 return ret; 1441 return ret;
@@ -1427,7 +1447,9 @@ static int aic3x_remove(struct snd_soc_codec *codec)
1427 int i; 1447 int i;
1428 1448
1429 aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF); 1449 aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF);
1430 if (aic3x->gpio_reset >= 0) { 1450 list_del(&aic3x->list);
1451 if (gpio_is_valid(aic3x->gpio_reset) &&
1452 !aic3x_is_shared_reset(aic3x)) {
1431 gpio_set_value(aic3x->gpio_reset, 0); 1453 gpio_set_value(aic3x->gpio_reset, 0);
1432 gpio_free(aic3x->gpio_reset); 1454 gpio_free(aic3x->gpio_reset);
1433 } 1455 }
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c
index 2d64502c0c5b..9d61a1d6fce0 100644
--- a/sound/soc/codecs/tpa6130a2.c
+++ b/sound/soc/codecs/tpa6130a2.c
@@ -127,9 +127,6 @@ static int tpa6130a2_power(int power)
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 /* Power on */
131 if (data->power_gpio >= 0)
132 gpio_set_value(data->power_gpio, 1);
133 130
134 ret = regulator_enable(data->supply); 131 ret = regulator_enable(data->supply);
135 if (ret != 0) { 132 if (ret != 0) {
@@ -137,6 +134,9 @@ static int tpa6130a2_power(int power)
137 "Failed to enable supply: %d\n", ret); 134 "Failed to enable supply: %d\n", ret);
138 goto exit; 135 goto exit;
139 } 136 }
137 /* Power on */
138 if (data->power_gpio >= 0)
139 gpio_set_value(data->power_gpio, 1);
140 140
141 data->power_state = 1; 141 data->power_state = 1;
142 ret = tpa6130a2_initialize(); 142 ret = tpa6130a2_initialize();
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