diff options
author | Mark Brown <broonie@linaro.org> | 2013-10-24 06:24:16 -0400 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2013-10-24 06:24:16 -0400 |
commit | 3caa28274e783875757a36dd4239c3269933255b (patch) | |
tree | 9b25957830da77eac2971237d1f3a1c43e0b7d07 /sound/soc/codecs/tlv320aic3x.c | |
parent | 24a6703abb582a98262f17049bd6fa6c7938b339 (diff) | |
parent | b3b70786ec18ef3088b55b76258bbd48d75aee08 (diff) |
Merge remote-tracking branch 'asoc/topic/tlv320aic3x' into asoc-next
Diffstat (limited to 'sound/soc/codecs/tlv320aic3x.c')
-rw-r--r-- | sound/soc/codecs/tlv320aic3x.c | 234 |
1 files changed, 113 insertions, 121 deletions
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 64ad84d8a306..546d16b7d38f 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/i2c.h> | 40 | #include <linux/i2c.h> |
41 | #include <linux/gpio.h> | 41 | #include <linux/gpio.h> |
42 | #include <linux/regulator/consumer.h> | 42 | #include <linux/regulator/consumer.h> |
43 | #include <linux/of.h> | ||
43 | #include <linux/of_gpio.h> | 44 | #include <linux/of_gpio.h> |
44 | #include <linux/slab.h> | 45 | #include <linux/slab.h> |
45 | #include <sound/core.h> | 46 | #include <sound/core.h> |
@@ -72,9 +73,9 @@ struct aic3x_disable_nb { | |||
72 | /* codec private data */ | 73 | /* codec private data */ |
73 | struct aic3x_priv { | 74 | struct aic3x_priv { |
74 | struct snd_soc_codec *codec; | 75 | struct snd_soc_codec *codec; |
76 | struct regmap *regmap; | ||
75 | struct regulator_bulk_data supplies[AIC3X_NUM_SUPPLIES]; | 77 | struct regulator_bulk_data supplies[AIC3X_NUM_SUPPLIES]; |
76 | struct aic3x_disable_nb disable_nb[AIC3X_NUM_SUPPLIES]; | 78 | struct aic3x_disable_nb disable_nb[AIC3X_NUM_SUPPLIES]; |
77 | enum snd_soc_control_type control_type; | ||
78 | struct aic3x_setup_data *setup; | 79 | struct aic3x_setup_data *setup; |
79 | unsigned int sysclk; | 80 | unsigned int sysclk; |
80 | struct list_head list; | 81 | struct list_head list; |
@@ -90,41 +91,45 @@ struct aic3x_priv { | |||
90 | enum aic3x_micbias_voltage micbias_vg; | 91 | enum aic3x_micbias_voltage micbias_vg; |
91 | }; | 92 | }; |
92 | 93 | ||
93 | /* | 94 | static const struct reg_default aic3x_reg[] = { |
94 | * AIC3X register cache | 95 | { 0, 0x00 }, { 1, 0x00 }, { 2, 0x00 }, { 3, 0x10 }, |
95 | * We can't read the AIC3X register space when we are | 96 | { 4, 0x04 }, { 5, 0x00 }, { 6, 0x00 }, { 7, 0x00 }, |
96 | * using 2 wire for device control, so we cache them instead. | 97 | { 8, 0x00 }, { 9, 0x00 }, { 10, 0x00 }, { 11, 0x01 }, |
97 | * There is no point in caching the reset register | 98 | { 12, 0x00 }, { 13, 0x00 }, { 14, 0x00 }, { 15, 0x80 }, |
98 | */ | 99 | { 16, 0x80 }, { 17, 0xff }, { 18, 0xff }, { 19, 0x78 }, |
99 | static const u8 aic3x_reg[AIC3X_CACHEREGNUM] = { | 100 | { 20, 0x78 }, { 21, 0x78 }, { 22, 0x78 }, { 23, 0x78 }, |
100 | 0x00, 0x00, 0x00, 0x10, /* 0 */ | 101 | { 24, 0x78 }, { 25, 0x00 }, { 26, 0x00 }, { 27, 0xfe }, |
101 | 0x04, 0x00, 0x00, 0x00, /* 4 */ | 102 | { 28, 0x00 }, { 29, 0x00 }, { 30, 0xfe }, { 31, 0x00 }, |
102 | 0x00, 0x00, 0x00, 0x01, /* 8 */ | 103 | { 32, 0x18 }, { 33, 0x18 }, { 34, 0x00 }, { 35, 0x00 }, |
103 | 0x00, 0x00, 0x00, 0x80, /* 12 */ | 104 | { 36, 0x00 }, { 37, 0x00 }, { 38, 0x00 }, { 39, 0x00 }, |
104 | 0x80, 0xff, 0xff, 0x78, /* 16 */ | 105 | { 40, 0x00 }, { 41, 0x00 }, { 42, 0x00 }, { 43, 0x80 }, |
105 | 0x78, 0x78, 0x78, 0x78, /* 20 */ | 106 | { 44, 0x80 }, { 45, 0x00 }, { 46, 0x00 }, { 47, 0x00 }, |
106 | 0x78, 0x00, 0x00, 0xfe, /* 24 */ | 107 | { 48, 0x00 }, { 49, 0x00 }, { 50, 0x00 }, { 51, 0x04 }, |
107 | 0x00, 0x00, 0xfe, 0x00, /* 28 */ | 108 | { 52, 0x00 }, { 53, 0x00 }, { 54, 0x00 }, { 55, 0x00 }, |
108 | 0x18, 0x18, 0x00, 0x00, /* 32 */ | 109 | { 56, 0x00 }, { 57, 0x00 }, { 58, 0x04 }, { 59, 0x00 }, |
109 | 0x00, 0x00, 0x00, 0x00, /* 36 */ | 110 | { 60, 0x00 }, { 61, 0x00 }, { 62, 0x00 }, { 63, 0x00 }, |
110 | 0x00, 0x00, 0x00, 0x80, /* 40 */ | 111 | { 64, 0x00 }, { 65, 0x04 }, { 66, 0x00 }, { 67, 0x00 }, |
111 | 0x80, 0x00, 0x00, 0x00, /* 44 */ | 112 | { 68, 0x00 }, { 69, 0x00 }, { 70, 0x00 }, { 71, 0x00 }, |
112 | 0x00, 0x00, 0x00, 0x04, /* 48 */ | 113 | { 72, 0x04 }, { 73, 0x00 }, { 74, 0x00 }, { 75, 0x00 }, |
113 | 0x00, 0x00, 0x00, 0x00, /* 52 */ | 114 | { 76, 0x00 }, { 77, 0x00 }, { 78, 0x00 }, { 79, 0x00 }, |
114 | 0x00, 0x00, 0x04, 0x00, /* 56 */ | 115 | { 80, 0x00 }, { 81, 0x00 }, { 82, 0x00 }, { 83, 0x00 }, |
115 | 0x00, 0x00, 0x00, 0x00, /* 60 */ | 116 | { 84, 0x00 }, { 85, 0x00 }, { 86, 0x00 }, { 87, 0x00 }, |
116 | 0x00, 0x04, 0x00, 0x00, /* 64 */ | 117 | { 88, 0x00 }, { 89, 0x00 }, { 90, 0x00 }, { 91, 0x00 }, |
117 | 0x00, 0x00, 0x00, 0x00, /* 68 */ | 118 | { 92, 0x00 }, { 93, 0x00 }, { 94, 0x00 }, { 95, 0x00 }, |
118 | 0x04, 0x00, 0x00, 0x00, /* 72 */ | 119 | { 96, 0x00 }, { 97, 0x00 }, { 98, 0x00 }, { 99, 0x00 }, |
119 | 0x00, 0x00, 0x00, 0x00, /* 76 */ | 120 | { 100, 0x00 }, { 101, 0x00 }, { 102, 0x02 }, { 103, 0x00 }, |
120 | 0x00, 0x00, 0x00, 0x00, /* 80 */ | 121 | { 104, 0x00 }, { 105, 0x00 }, { 106, 0x00 }, { 107, 0x00 }, |
121 | 0x00, 0x00, 0x00, 0x00, /* 84 */ | 122 | { 108, 0x00 }, { 109, 0x00 }, |
122 | 0x00, 0x00, 0x00, 0x00, /* 88 */ | 123 | }; |
123 | 0x00, 0x00, 0x00, 0x00, /* 92 */ | 124 | |
124 | 0x00, 0x00, 0x00, 0x00, /* 96 */ | 125 | static const struct regmap_config aic3x_regmap = { |
125 | 0x00, 0x00, 0x02, 0x00, /* 100 */ | 126 | .reg_bits = 8, |
126 | 0x00, 0x00, 0x00, 0x00, /* 104 */ | 127 | .val_bits = 8, |
127 | 0x00, 0x00, /* 108 */ | 128 | |
129 | .max_register = DAC_ICC_ADJ, | ||
130 | .reg_defaults = aic3x_reg, | ||
131 | .num_reg_defaults = ARRAY_SIZE(aic3x_reg), | ||
132 | .cache_type = REGCACHE_RBTREE, | ||
128 | }; | 133 | }; |
129 | 134 | ||
130 | #define SOC_DAPM_SINGLE_AIC3X(xname, reg, shift, mask, invert) \ | 135 | #define SOC_DAPM_SINGLE_AIC3X(xname, reg, shift, mask, invert) \ |
@@ -828,12 +833,6 @@ static int aic3x_add_widgets(struct snd_soc_codec *codec) | |||
828 | struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); | 833 | struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); |
829 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 834 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
830 | 835 | ||
831 | snd_soc_dapm_new_controls(dapm, aic3x_dapm_widgets, | ||
832 | ARRAY_SIZE(aic3x_dapm_widgets)); | ||
833 | |||
834 | /* set up audio path interconnects */ | ||
835 | snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon)); | ||
836 | |||
837 | if (aic3x->model == AIC3X_MODEL_3007) { | 836 | if (aic3x->model == AIC3X_MODEL_3007) { |
838 | snd_soc_dapm_new_controls(dapm, aic3007_dapm_widgets, | 837 | snd_soc_dapm_new_controls(dapm, aic3007_dapm_widgets, |
839 | ARRAY_SIZE(aic3007_dapm_widgets)); | 838 | ARRAY_SIZE(aic3007_dapm_widgets)); |
@@ -1082,29 +1081,6 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
1082 | return 0; | 1081 | return 0; |
1083 | } | 1082 | } |
1084 | 1083 | ||
1085 | static int aic3x_init_3007(struct snd_soc_codec *codec) | ||
1086 | { | ||
1087 | u8 tmp1, tmp2, *cache = codec->reg_cache; | ||
1088 | |||
1089 | /* | ||
1090 | * There is no need to cache writes to undocumented page 0xD but | ||
1091 | * respective page 0 register cache entries must be preserved | ||
1092 | */ | ||
1093 | tmp1 = cache[0xD]; | ||
1094 | tmp2 = cache[0x8]; | ||
1095 | /* Class-D speaker driver init; datasheet p. 46 */ | ||
1096 | snd_soc_write(codec, AIC3X_PAGE_SELECT, 0x0D); | ||
1097 | snd_soc_write(codec, 0xD, 0x0D); | ||
1098 | snd_soc_write(codec, 0x8, 0x5C); | ||
1099 | snd_soc_write(codec, 0x8, 0x5D); | ||
1100 | snd_soc_write(codec, 0x8, 0x5C); | ||
1101 | snd_soc_write(codec, AIC3X_PAGE_SELECT, 0x00); | ||
1102 | cache[0xD] = tmp1; | ||
1103 | cache[0x8] = tmp2; | ||
1104 | |||
1105 | return 0; | ||
1106 | } | ||
1107 | |||
1108 | static int aic3x_regulator_event(struct notifier_block *nb, | 1084 | static int aic3x_regulator_event(struct notifier_block *nb, |
1109 | unsigned long event, void *data) | 1085 | unsigned long event, void *data) |
1110 | { | 1086 | { |
@@ -1119,7 +1095,7 @@ static int aic3x_regulator_event(struct notifier_block *nb, | |||
1119 | */ | 1095 | */ |
1120 | if (gpio_is_valid(aic3x->gpio_reset)) | 1096 | if (gpio_is_valid(aic3x->gpio_reset)) |
1121 | gpio_set_value(aic3x->gpio_reset, 0); | 1097 | gpio_set_value(aic3x->gpio_reset, 0); |
1122 | aic3x->codec->cache_sync = 1; | 1098 | regcache_mark_dirty(aic3x->regmap); |
1123 | } | 1099 | } |
1124 | 1100 | ||
1125 | return 0; | 1101 | return 0; |
@@ -1128,8 +1104,7 @@ static int aic3x_regulator_event(struct notifier_block *nb, | |||
1128 | static int aic3x_set_power(struct snd_soc_codec *codec, int power) | 1104 | static int aic3x_set_power(struct snd_soc_codec *codec, int power) |
1129 | { | 1105 | { |
1130 | struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); | 1106 | struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); |
1131 | int i, ret; | 1107 | int ret; |
1132 | u8 *cache = codec->reg_cache; | ||
1133 | 1108 | ||
1134 | if (power) { | 1109 | if (power) { |
1135 | ret = regulator_bulk_enable(ARRAY_SIZE(aic3x->supplies), | 1110 | ret = regulator_bulk_enable(ARRAY_SIZE(aic3x->supplies), |
@@ -1137,12 +1112,6 @@ static int aic3x_set_power(struct snd_soc_codec *codec, int power) | |||
1137 | if (ret) | 1112 | if (ret) |
1138 | goto out; | 1113 | goto out; |
1139 | aic3x->power = 1; | 1114 | aic3x->power = 1; |
1140 | /* | ||
1141 | * Reset release and cache sync is necessary only if some | ||
1142 | * supply was off or if there were cached writes | ||
1143 | */ | ||
1144 | if (!codec->cache_sync) | ||
1145 | goto out; | ||
1146 | 1115 | ||
1147 | if (gpio_is_valid(aic3x->gpio_reset)) { | 1116 | if (gpio_is_valid(aic3x->gpio_reset)) { |
1148 | udelay(1); | 1117 | udelay(1); |
@@ -1150,12 +1119,8 @@ static int aic3x_set_power(struct snd_soc_codec *codec, int power) | |||
1150 | } | 1119 | } |
1151 | 1120 | ||
1152 | /* Sync reg_cache with the hardware */ | 1121 | /* Sync reg_cache with the hardware */ |
1153 | codec->cache_only = 0; | 1122 | regcache_cache_only(aic3x->regmap, false); |
1154 | for (i = AIC3X_SAMPLE_RATE_SEL_REG; i < ARRAY_SIZE(aic3x_reg); i++) | 1123 | regcache_sync(aic3x->regmap); |
1155 | snd_soc_write(codec, i, cache[i]); | ||
1156 | if (aic3x->model == AIC3X_MODEL_3007) | ||
1157 | aic3x_init_3007(codec); | ||
1158 | codec->cache_sync = 0; | ||
1159 | } else { | 1124 | } else { |
1160 | /* | 1125 | /* |
1161 | * Do soft reset to this codec instance in order to clear | 1126 | * Do soft reset to this codec instance in order to clear |
@@ -1163,10 +1128,10 @@ static int aic3x_set_power(struct snd_soc_codec *codec, int power) | |||
1163 | * remain on | 1128 | * remain on |
1164 | */ | 1129 | */ |
1165 | snd_soc_write(codec, AIC3X_RESET, SOFT_RESET); | 1130 | snd_soc_write(codec, AIC3X_RESET, SOFT_RESET); |
1166 | codec->cache_sync = 1; | 1131 | regcache_mark_dirty(aic3x->regmap); |
1167 | aic3x->power = 0; | 1132 | aic3x->power = 0; |
1168 | /* HW writes are needless when bias is off */ | 1133 | /* HW writes are needless when bias is off */ |
1169 | codec->cache_only = 1; | 1134 | regcache_cache_only(aic3x->regmap, true); |
1170 | ret = regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies), | 1135 | ret = regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies), |
1171 | aic3x->supplies); | 1136 | aic3x->supplies); |
1172 | } | 1137 | } |
@@ -1321,7 +1286,6 @@ static int aic3x_init(struct snd_soc_codec *codec) | |||
1321 | snd_soc_write(codec, LINE2R_2_MONOLOPM_VOL, DEFAULT_VOL); | 1286 | snd_soc_write(codec, LINE2R_2_MONOLOPM_VOL, DEFAULT_VOL); |
1322 | 1287 | ||
1323 | if (aic3x->model == AIC3X_MODEL_3007) { | 1288 | if (aic3x->model == AIC3X_MODEL_3007) { |
1324 | aic3x_init_3007(codec); | ||
1325 | snd_soc_write(codec, CLASSD_CTRL, 0); | 1289 | snd_soc_write(codec, CLASSD_CTRL, 0); |
1326 | } | 1290 | } |
1327 | 1291 | ||
@@ -1349,29 +1313,12 @@ static int aic3x_probe(struct snd_soc_codec *codec) | |||
1349 | INIT_LIST_HEAD(&aic3x->list); | 1313 | INIT_LIST_HEAD(&aic3x->list); |
1350 | aic3x->codec = codec; | 1314 | aic3x->codec = codec; |
1351 | 1315 | ||
1352 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, aic3x->control_type); | 1316 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); |
1353 | if (ret != 0) { | 1317 | if (ret != 0) { |
1354 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 1318 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
1355 | return ret; | 1319 | return ret; |
1356 | } | 1320 | } |
1357 | 1321 | ||
1358 | if (gpio_is_valid(aic3x->gpio_reset) && | ||
1359 | !aic3x_is_shared_reset(aic3x)) { | ||
1360 | ret = gpio_request(aic3x->gpio_reset, "tlv320aic3x reset"); | ||
1361 | if (ret != 0) | ||
1362 | goto err_gpio; | ||
1363 | gpio_direction_output(aic3x->gpio_reset, 0); | ||
1364 | } | ||
1365 | |||
1366 | for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) | ||
1367 | aic3x->supplies[i].supply = aic3x_supply_names[i]; | ||
1368 | |||
1369 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(aic3x->supplies), | ||
1370 | aic3x->supplies); | ||
1371 | if (ret != 0) { | ||
1372 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | ||
1373 | goto err_get; | ||
1374 | } | ||
1375 | for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) { | 1322 | for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) { |
1376 | aic3x->disable_nb[i].nb.notifier_call = aic3x_regulator_event; | 1323 | aic3x->disable_nb[i].nb.notifier_call = aic3x_regulator_event; |
1377 | aic3x->disable_nb[i].aic3x = aic3x; | 1324 | aic3x->disable_nb[i].aic3x = aic3x; |
@@ -1385,7 +1332,7 @@ static int aic3x_probe(struct snd_soc_codec *codec) | |||
1385 | } | 1332 | } |
1386 | } | 1333 | } |
1387 | 1334 | ||
1388 | codec->cache_only = 1; | 1335 | regcache_mark_dirty(aic3x->regmap); |
1389 | aic3x_init(codec); | 1336 | aic3x_init(codec); |
1390 | 1337 | ||
1391 | if (aic3x->setup) { | 1338 | if (aic3x->setup) { |
@@ -1396,8 +1343,6 @@ static int aic3x_probe(struct snd_soc_codec *codec) | |||
1396 | (aic3x->setup->gpio_func[1] & 0xf) << 4); | 1343 | (aic3x->setup->gpio_func[1] & 0xf) << 4); |
1397 | } | 1344 | } |
1398 | 1345 | ||
1399 | snd_soc_add_codec_controls(codec, aic3x_snd_controls, | ||
1400 | ARRAY_SIZE(aic3x_snd_controls)); | ||
1401 | if (aic3x->model == AIC3X_MODEL_3007) | 1346 | if (aic3x->model == AIC3X_MODEL_3007) |
1402 | snd_soc_add_codec_controls(codec, &aic3x_classd_amp_gain_ctrl, 1); | 1347 | snd_soc_add_codec_controls(codec, &aic3x_classd_amp_gain_ctrl, 1); |
1403 | 1348 | ||
@@ -1428,12 +1373,6 @@ err_notif: | |||
1428 | while (i--) | 1373 | while (i--) |
1429 | regulator_unregister_notifier(aic3x->supplies[i].consumer, | 1374 | regulator_unregister_notifier(aic3x->supplies[i].consumer, |
1430 | &aic3x->disable_nb[i].nb); | 1375 | &aic3x->disable_nb[i].nb); |
1431 | regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); | ||
1432 | err_get: | ||
1433 | if (gpio_is_valid(aic3x->gpio_reset) && | ||
1434 | !aic3x_is_shared_reset(aic3x)) | ||
1435 | gpio_free(aic3x->gpio_reset); | ||
1436 | err_gpio: | ||
1437 | return ret; | 1376 | return ret; |
1438 | } | 1377 | } |
1439 | 1378 | ||
@@ -1444,15 +1383,9 @@ static int aic3x_remove(struct snd_soc_codec *codec) | |||
1444 | 1383 | ||
1445 | aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1384 | aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1446 | list_del(&aic3x->list); | 1385 | list_del(&aic3x->list); |
1447 | if (gpio_is_valid(aic3x->gpio_reset) && | ||
1448 | !aic3x_is_shared_reset(aic3x)) { | ||
1449 | gpio_set_value(aic3x->gpio_reset, 0); | ||
1450 | gpio_free(aic3x->gpio_reset); | ||
1451 | } | ||
1452 | for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) | 1386 | for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) |
1453 | regulator_unregister_notifier(aic3x->supplies[i].consumer, | 1387 | regulator_unregister_notifier(aic3x->supplies[i].consumer, |
1454 | &aic3x->disable_nb[i].nb); | 1388 | &aic3x->disable_nb[i].nb); |
1455 | regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); | ||
1456 | 1389 | ||
1457 | return 0; | 1390 | return 0; |
1458 | } | 1391 | } |
@@ -1460,13 +1393,16 @@ static int aic3x_remove(struct snd_soc_codec *codec) | |||
1460 | static struct snd_soc_codec_driver soc_codec_dev_aic3x = { | 1393 | static struct snd_soc_codec_driver soc_codec_dev_aic3x = { |
1461 | .set_bias_level = aic3x_set_bias_level, | 1394 | .set_bias_level = aic3x_set_bias_level, |
1462 | .idle_bias_off = true, | 1395 | .idle_bias_off = true, |
1463 | .reg_cache_size = ARRAY_SIZE(aic3x_reg), | ||
1464 | .reg_word_size = sizeof(u8), | ||
1465 | .reg_cache_default = aic3x_reg, | ||
1466 | .probe = aic3x_probe, | 1396 | .probe = aic3x_probe, |
1467 | .remove = aic3x_remove, | 1397 | .remove = aic3x_remove, |
1468 | .suspend = aic3x_suspend, | 1398 | .suspend = aic3x_suspend, |
1469 | .resume = aic3x_resume, | 1399 | .resume = aic3x_resume, |
1400 | .controls = aic3x_snd_controls, | ||
1401 | .num_controls = ARRAY_SIZE(aic3x_snd_controls), | ||
1402 | .dapm_widgets = aic3x_dapm_widgets, | ||
1403 | .num_dapm_widgets = ARRAY_SIZE(aic3x_dapm_widgets), | ||
1404 | .dapm_routes = intercon, | ||
1405 | .num_dapm_routes = ARRAY_SIZE(intercon), | ||
1470 | }; | 1406 | }; |
1471 | 1407 | ||
1472 | /* | 1408 | /* |
@@ -1483,6 +1419,16 @@ static const struct i2c_device_id aic3x_i2c_id[] = { | |||
1483 | }; | 1419 | }; |
1484 | MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id); | 1420 | MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id); |
1485 | 1421 | ||
1422 | static const struct reg_default aic3007_class_d[] = { | ||
1423 | /* Class-D speaker driver init; datasheet p. 46 */ | ||
1424 | { AIC3X_PAGE_SELECT, 0x0D }, | ||
1425 | { 0xD, 0x0D }, | ||
1426 | { 0x8, 0x5C }, | ||
1427 | { 0x8, 0x5D }, | ||
1428 | { 0x8, 0x5C }, | ||
1429 | { AIC3X_PAGE_SELECT, 0x00 }, | ||
1430 | }; | ||
1431 | |||
1486 | /* | 1432 | /* |
1487 | * If the i2c layer weren't so broken, we could pass this kind of data | 1433 | * If the i2c layer weren't so broken, we could pass this kind of data |
1488 | * around | 1434 | * around |
@@ -1494,7 +1440,7 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, | |||
1494 | struct aic3x_priv *aic3x; | 1440 | struct aic3x_priv *aic3x; |
1495 | struct aic3x_setup_data *ai3x_setup; | 1441 | struct aic3x_setup_data *ai3x_setup; |
1496 | struct device_node *np = i2c->dev.of_node; | 1442 | struct device_node *np = i2c->dev.of_node; |
1497 | int ret; | 1443 | int ret, i; |
1498 | u32 value; | 1444 | u32 value; |
1499 | 1445 | ||
1500 | aic3x = devm_kzalloc(&i2c->dev, sizeof(struct aic3x_priv), GFP_KERNEL); | 1446 | aic3x = devm_kzalloc(&i2c->dev, sizeof(struct aic3x_priv), GFP_KERNEL); |
@@ -1503,7 +1449,13 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, | |||
1503 | return -ENOMEM; | 1449 | return -ENOMEM; |
1504 | } | 1450 | } |
1505 | 1451 | ||
1506 | aic3x->control_type = SND_SOC_I2C; | 1452 | aic3x->regmap = devm_regmap_init_i2c(i2c, &aic3x_regmap); |
1453 | if (IS_ERR(aic3x->regmap)) { | ||
1454 | ret = PTR_ERR(aic3x->regmap); | ||
1455 | return ret; | ||
1456 | } | ||
1457 | |||
1458 | regcache_cache_only(aic3x->regmap, true); | ||
1507 | 1459 | ||
1508 | i2c_set_clientdata(i2c, aic3x); | 1460 | i2c_set_clientdata(i2c, aic3x); |
1509 | if (pdata) { | 1461 | if (pdata) { |
@@ -1555,14 +1507,54 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, | |||
1555 | 1507 | ||
1556 | aic3x->model = id->driver_data; | 1508 | aic3x->model = id->driver_data; |
1557 | 1509 | ||
1510 | if (gpio_is_valid(aic3x->gpio_reset) && | ||
1511 | !aic3x_is_shared_reset(aic3x)) { | ||
1512 | ret = gpio_request(aic3x->gpio_reset, "tlv320aic3x reset"); | ||
1513 | if (ret != 0) | ||
1514 | goto err; | ||
1515 | gpio_direction_output(aic3x->gpio_reset, 0); | ||
1516 | } | ||
1517 | |||
1518 | for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) | ||
1519 | aic3x->supplies[i].supply = aic3x_supply_names[i]; | ||
1520 | |||
1521 | ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(aic3x->supplies), | ||
1522 | aic3x->supplies); | ||
1523 | if (ret != 0) { | ||
1524 | dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); | ||
1525 | goto err_gpio; | ||
1526 | } | ||
1527 | |||
1528 | if (aic3x->model == AIC3X_MODEL_3007) { | ||
1529 | ret = regmap_register_patch(aic3x->regmap, aic3007_class_d, | ||
1530 | ARRAY_SIZE(aic3007_class_d)); | ||
1531 | if (ret != 0) | ||
1532 | dev_err(&i2c->dev, "Failed to init class D: %d\n", | ||
1533 | ret); | ||
1534 | } | ||
1535 | |||
1558 | ret = snd_soc_register_codec(&i2c->dev, | 1536 | ret = snd_soc_register_codec(&i2c->dev, |
1559 | &soc_codec_dev_aic3x, &aic3x_dai, 1); | 1537 | &soc_codec_dev_aic3x, &aic3x_dai, 1); |
1560 | return ret; | 1538 | return ret; |
1539 | |||
1540 | err_gpio: | ||
1541 | if (gpio_is_valid(aic3x->gpio_reset) && | ||
1542 | !aic3x_is_shared_reset(aic3x)) | ||
1543 | gpio_free(aic3x->gpio_reset); | ||
1544 | err: | ||
1545 | return ret; | ||
1561 | } | 1546 | } |
1562 | 1547 | ||
1563 | static int aic3x_i2c_remove(struct i2c_client *client) | 1548 | static int aic3x_i2c_remove(struct i2c_client *client) |
1564 | { | 1549 | { |
1550 | struct aic3x_priv *aic3x = i2c_get_clientdata(client); | ||
1551 | |||
1565 | snd_soc_unregister_codec(&client->dev); | 1552 | snd_soc_unregister_codec(&client->dev); |
1553 | if (gpio_is_valid(aic3x->gpio_reset) && | ||
1554 | !aic3x_is_shared_reset(aic3x)) { | ||
1555 | gpio_set_value(aic3x->gpio_reset, 0); | ||
1556 | gpio_free(aic3x->gpio_reset); | ||
1557 | } | ||
1566 | return 0; | 1558 | return 0; |
1567 | } | 1559 | } |
1568 | 1560 | ||