aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/tlv320aic3x.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/tlv320aic3x.c')
-rw-r--r--sound/soc/codecs/tlv320aic3x.c71
1 files changed, 39 insertions, 32 deletions
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 77b8f9ae29b..3bedab26892 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -46,7 +46,6 @@
46#include <sound/pcm.h> 46#include <sound/pcm.h>
47#include <sound/pcm_params.h> 47#include <sound/pcm_params.h>
48#include <sound/soc.h> 48#include <sound/soc.h>
49#include <sound/soc-dapm.h>
50#include <sound/initval.h> 49#include <sound/initval.h>
51#include <sound/tlv.h> 50#include <sound/tlv.h>
52#include <sound/tlv320aic3x.h> 51#include <sound/tlv320aic3x.h>
@@ -61,6 +60,8 @@ static const char *aic3x_supply_names[AIC3X_NUM_SUPPLIES] = {
61 "DRVDD", /* ADC Analog and Output Driver Voltage */ 60 "DRVDD", /* ADC Analog and Output Driver Voltage */
62}; 61};
63 62
63static LIST_HEAD(reset_list);
64
64struct aic3x_priv; 65struct aic3x_priv;
65 66
66struct aic3x_disable_nb { 67struct aic3x_disable_nb {
@@ -77,6 +78,7 @@ struct aic3x_priv {
77 struct aic3x_setup_data *setup; 78 struct aic3x_setup_data *setup;
78 void *control_data; 79 void *control_data;
79 unsigned int sysclk; 80 unsigned int sysclk;
81 struct list_head list;
80 int master; 82 int master;
81 int gpio_reset; 83 int gpio_reset;
82 int power; 84 int power;
@@ -183,7 +185,7 @@ static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol,
183 185
184 if (snd_soc_test_bits(widget->codec, reg, val_mask, val)) { 186 if (snd_soc_test_bits(widget->codec, reg, val_mask, val)) {
185 /* find dapm widget path assoc with kcontrol */ 187 /* find dapm widget path assoc with kcontrol */
186 list_for_each_entry(path, &widget->codec->dapm_paths, list) { 188 list_for_each_entry(path, &widget->dapm->card->paths, list) {
187 if (path->kcontrol != kcontrol) 189 if (path->kcontrol != kcontrol)
188 continue; 190 continue;
189 191
@@ -199,7 +201,7 @@ static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol,
199 } 201 }
200 202
201 if (found) 203 if (found)
202 snd_soc_dapm_sync(widget->codec); 204 snd_soc_dapm_sync(widget->dapm);
203 } 205 }
204 206
205 ret = snd_soc_update_bits(widget->codec, reg, val_mask, val); 207 ret = snd_soc_update_bits(widget->codec, reg, val_mask, val);
@@ -788,17 +790,19 @@ static const struct snd_soc_dapm_route intercon_3007[] = {
788static int aic3x_add_widgets(struct snd_soc_codec *codec) 790static int aic3x_add_widgets(struct snd_soc_codec *codec)
789{ 791{
790 struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); 792 struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
793 struct snd_soc_dapm_context *dapm = &codec->dapm;
791 794
792 snd_soc_dapm_new_controls(codec, aic3x_dapm_widgets, 795 snd_soc_dapm_new_controls(dapm, aic3x_dapm_widgets,
793 ARRAY_SIZE(aic3x_dapm_widgets)); 796 ARRAY_SIZE(aic3x_dapm_widgets));
794 797
795 /* set up audio path interconnects */ 798 /* set up audio path interconnects */
796 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); 799 snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
797 800
798 if (aic3x->model == AIC3X_MODEL_3007) { 801 if (aic3x->model == AIC3X_MODEL_3007) {
799 snd_soc_dapm_new_controls(codec, aic3007_dapm_widgets, 802 snd_soc_dapm_new_controls(dapm, aic3007_dapm_widgets,
800 ARRAY_SIZE(aic3007_dapm_widgets)); 803 ARRAY_SIZE(aic3007_dapm_widgets));
801 snd_soc_dapm_add_routes(codec, intercon_3007, ARRAY_SIZE(intercon_3007)); 804 snd_soc_dapm_add_routes(dapm, intercon_3007,
805 ARRAY_SIZE(intercon_3007));
802 } 806 }
803 807
804 return 0; 808 return 0;
@@ -1075,7 +1079,7 @@ static int aic3x_regulator_event(struct notifier_block *nb,
1075 * 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
1076 * of the supplies was disabled 1080 * of the supplies was disabled
1077 */ 1081 */
1078 if (aic3x->gpio_reset >= 0) 1082 if (gpio_is_valid(aic3x->gpio_reset))
1079 gpio_set_value(aic3x->gpio_reset, 0); 1083 gpio_set_value(aic3x->gpio_reset, 0);
1080 aic3x->codec->cache_sync = 1; 1084 aic3x->codec->cache_sync = 1;
1081 } 1085 }
@@ -1102,7 +1106,7 @@ static int aic3x_set_power(struct snd_soc_codec *codec, int power)
1102 if (!codec->cache_sync) 1106 if (!codec->cache_sync)
1103 goto out; 1107 goto out;
1104 1108
1105 if (aic3x->gpio_reset >= 0) { 1109 if (gpio_is_valid(aic3x->gpio_reset)) {
1106 udelay(1); 1110 udelay(1);
1107 gpio_set_value(aic3x->gpio_reset, 1); 1111 gpio_set_value(aic3x->gpio_reset, 1);
1108 } 1112 }
@@ -1135,7 +1139,7 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec,
1135 case SND_SOC_BIAS_ON: 1139 case SND_SOC_BIAS_ON:
1136 break; 1140 break;
1137 case SND_SOC_BIAS_PREPARE: 1141 case SND_SOC_BIAS_PREPARE:
1138 if (codec->bias_level == SND_SOC_BIAS_STANDBY && 1142 if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY &&
1139 aic3x->master) { 1143 aic3x->master) {
1140 /* enable pll */ 1144 /* enable pll */
1141 reg = snd_soc_read(codec, AIC3X_PLL_PROGA_REG); 1145 reg = snd_soc_read(codec, AIC3X_PLL_PROGA_REG);
@@ -1146,7 +1150,7 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec,
1146 case SND_SOC_BIAS_STANDBY: 1150 case SND_SOC_BIAS_STANDBY:
1147 if (!aic3x->power) 1151 if (!aic3x->power)
1148 aic3x_set_power(codec, 1); 1152 aic3x_set_power(codec, 1);
1149 if (codec->bias_level == SND_SOC_BIAS_PREPARE && 1153 if (codec->dapm.bias_level == SND_SOC_BIAS_PREPARE &&
1150 aic3x->master) { 1154 aic3x->master) {
1151 /* disable pll */ 1155 /* disable pll */
1152 reg = snd_soc_read(codec, AIC3X_PLL_PROGA_REG); 1156 reg = snd_soc_read(codec, AIC3X_PLL_PROGA_REG);
@@ -1159,7 +1163,7 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec,
1159 aic3x_set_power(codec, 0); 1163 aic3x_set_power(codec, 0);
1160 break; 1164 break;
1161 } 1165 }
1162 codec->bias_level = level; 1166 codec->dapm.bias_level = level;
1163 1167
1164 return 0; 1168 return 0;
1165} 1169}
@@ -1344,14 +1348,28 @@ static int aic3x_init(struct snd_soc_codec *codec)
1344 return 0; 1348 return 0;
1345} 1349}
1346 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
1347static int aic3x_probe(struct snd_soc_codec *codec) 1364static int aic3x_probe(struct snd_soc_codec *codec)
1348{ 1365{
1349 struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); 1366 struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
1350 int ret, i; 1367 int ret, i;
1351 1368
1369 INIT_LIST_HEAD(&aic3x->list);
1352 codec->control_data = aic3x->control_data; 1370 codec->control_data = aic3x->control_data;
1353 aic3x->codec = codec; 1371 aic3x->codec = codec;
1354 codec->idle_bias_off = 1; 1372 codec->dapm.idle_bias_off = 1;
1355 1373
1356 ret = snd_soc_codec_set_cache_io(codec, 8, 8, aic3x->control_type); 1374 ret = snd_soc_codec_set_cache_io(codec, 8, 8, aic3x->control_type);
1357 if (ret != 0) { 1375 if (ret != 0) {
@@ -1359,7 +1377,8 @@ static int aic3x_probe(struct snd_soc_codec *codec)
1359 return ret; 1377 return ret;
1360 } 1378 }
1361 1379
1362 if (aic3x->gpio_reset >= 0) { 1380 if (gpio_is_valid(aic3x->gpio_reset) &&
1381 !aic3x_is_shared_reset(aic3x)) {
1363 ret = gpio_request(aic3x->gpio_reset, "tlv320aic3x reset"); 1382 ret = gpio_request(aic3x->gpio_reset, "tlv320aic3x reset");
1364 if (ret != 0) 1383 if (ret != 0)
1365 goto err_gpio; 1384 goto err_gpio;
@@ -1405,6 +1424,7 @@ static int aic3x_probe(struct snd_soc_codec *codec)
1405 snd_soc_add_controls(codec, &aic3x_classd_amp_gain_ctrl, 1); 1424 snd_soc_add_controls(codec, &aic3x_classd_amp_gain_ctrl, 1);
1406 1425
1407 aic3x_add_widgets(codec); 1426 aic3x_add_widgets(codec);
1427 list_add(&aic3x->list, &reset_list);
1408 1428
1409 return 0; 1429 return 0;
1410 1430
@@ -1414,10 +1434,10 @@ err_notif:
1414 &aic3x->disable_nb[i].nb); 1434 &aic3x->disable_nb[i].nb);
1415 regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); 1435 regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
1416err_get: 1436err_get:
1417 if (aic3x->gpio_reset >= 0) 1437 if (gpio_is_valid(aic3x->gpio_reset) &&
1438 !aic3x_is_shared_reset(aic3x))
1418 gpio_free(aic3x->gpio_reset); 1439 gpio_free(aic3x->gpio_reset);
1419err_gpio: 1440err_gpio:
1420 kfree(aic3x);
1421 return ret; 1441 return ret;
1422} 1442}
1423 1443
@@ -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 }
@@ -1523,21 +1545,6 @@ static struct i2c_driver aic3x_i2c_driver = {
1523 .remove = aic3x_i2c_remove, 1545 .remove = aic3x_i2c_remove,
1524 .id_table = aic3x_i2c_id, 1546 .id_table = aic3x_i2c_id,
1525}; 1547};
1526
1527static inline void aic3x_i2c_init(void)
1528{
1529 int ret;
1530
1531 ret = i2c_add_driver(&aic3x_i2c_driver);
1532 if (ret)
1533 printk(KERN_ERR "%s: error regsitering i2c driver, %d\n",
1534 __func__, ret);
1535}
1536
1537static inline void aic3x_i2c_exit(void)
1538{
1539 i2c_del_driver(&aic3x_i2c_driver);
1540}
1541#endif 1548#endif
1542 1549
1543static int __init aic3x_modinit(void) 1550static int __init aic3x_modinit(void)