aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/tlv320aic3x.c
diff options
context:
space:
mode:
authorMark Brown <broonie@linaro.org>2013-09-23 19:07:13 -0400
committerMark Brown <broonie@linaro.org>2013-09-24 14:32:59 -0400
commit2a6fedec195b9bd20e60f9825ba7cc6315e54652 (patch)
tree21b3df062227789571b37ad5fd7a09cb72afebfc /sound/soc/codecs/tlv320aic3x.c
parent2677b4bb7316c07dd53535e01bd9b2ec699d0314 (diff)
ASoC: tlv320aic3x: Convert to direct regmap API usage
This is slightly more complex than a standard regmap conversion due to the moderately detailed cache control and the open coding of a register patch for the class D speaker on the TLV320AIC3007. Although the device supports paging this is not currently implemented as the additional pages are only used during the application of the patch for the TLV320AIC3007. Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'sound/soc/codecs/tlv320aic3x.c')
-rw-r--r--sound/soc/codecs/tlv320aic3x.c151
1 files changed, 73 insertions, 78 deletions
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 83e7d855c49a..892c108ca67a 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -72,9 +72,9 @@ struct aic3x_disable_nb {
72/* codec private data */ 72/* codec private data */
73struct aic3x_priv { 73struct aic3x_priv {
74 struct snd_soc_codec *codec; 74 struct snd_soc_codec *codec;
75 struct regmap *regmap;
75 struct regulator_bulk_data supplies[AIC3X_NUM_SUPPLIES]; 76 struct regulator_bulk_data supplies[AIC3X_NUM_SUPPLIES];
76 struct aic3x_disable_nb disable_nb[AIC3X_NUM_SUPPLIES]; 77 struct aic3x_disable_nb disable_nb[AIC3X_NUM_SUPPLIES];
77 enum snd_soc_control_type control_type;
78 struct aic3x_setup_data *setup; 78 struct aic3x_setup_data *setup;
79 unsigned int sysclk; 79 unsigned int sysclk;
80 struct list_head list; 80 struct list_head list;
@@ -90,35 +90,45 @@ struct aic3x_priv {
90 enum aic3x_micbias_voltage micbias_vg; 90 enum aic3x_micbias_voltage micbias_vg;
91}; 91};
92 92
93static const u8 aic3x_reg[AIC3X_CACHEREGNUM] = { 93static const struct reg_default aic3x_reg[] = {
94 0x00, 0x00, 0x00, 0x10, /* 0 */ 94 { 0, 0x00 }, { 1, 0x00 }, { 2, 0x00 }, { 3, 0x10 },
95 0x04, 0x00, 0x00, 0x00, /* 4 */ 95 { 4, 0x04 }, { 5, 0x00 }, { 6, 0x00 }, { 7, 0x00 },
96 0x00, 0x00, 0x00, 0x01, /* 8 */ 96 { 8, 0x00 }, { 9, 0x00 }, { 10, 0x00 }, { 11, 0x01 },
97 0x00, 0x00, 0x00, 0x80, /* 12 */ 97 { 12, 0x00 }, { 13, 0x00 }, { 14, 0x00 }, { 15, 0x80 },
98 0x80, 0xff, 0xff, 0x78, /* 16 */ 98 { 16, 0x80 }, { 17, 0xff }, { 18, 0xff }, { 19, 0x78 },
99 0x78, 0x78, 0x78, 0x78, /* 20 */ 99 { 20, 0x78 }, { 21, 0x78 }, { 22, 0x78 }, { 23, 0x78 },
100 0x78, 0x00, 0x00, 0xfe, /* 24 */ 100 { 24, 0x78 }, { 25, 0x00 }, { 26, 0x00 }, { 27, 0xfe },
101 0x00, 0x00, 0xfe, 0x00, /* 28 */ 101 { 28, 0x00 }, { 29, 0x00 }, { 30, 0xfe }, { 31, 0x00 },
102 0x18, 0x18, 0x00, 0x00, /* 32 */ 102 { 32, 0x18 }, { 33, 0x18 }, { 34, 0x00 }, { 35, 0x00 },
103 0x00, 0x00, 0x00, 0x00, /* 36 */ 103 { 36, 0x00 }, { 37, 0x00 }, { 38, 0x00 }, { 39, 0x00 },
104 0x00, 0x00, 0x00, 0x80, /* 40 */ 104 { 40, 0x00 }, { 41, 0x00 }, { 42, 0x00 }, { 43, 0x80 },
105 0x80, 0x00, 0x00, 0x00, /* 44 */ 105 { 44, 0x80 }, { 45, 0x00 }, { 46, 0x00 }, { 47, 0x00 },
106 0x00, 0x00, 0x00, 0x04, /* 48 */ 106 { 48, 0x00 }, { 49, 0x00 }, { 50, 0x00 }, { 51, 0x04 },
107 0x00, 0x00, 0x00, 0x00, /* 52 */ 107 { 52, 0x00 }, { 53, 0x00 }, { 54, 0x00 }, { 55, 0x00 },
108 0x00, 0x00, 0x04, 0x00, /* 56 */ 108 { 56, 0x00 }, { 57, 0x00 }, { 58, 0x04 }, { 59, 0x00 },
109 0x00, 0x00, 0x00, 0x00, /* 60 */ 109 { 60, 0x00 }, { 61, 0x00 }, { 62, 0x00 }, { 63, 0x00 },
110 0x00, 0x04, 0x00, 0x00, /* 64 */ 110 { 64, 0x00 }, { 65, 0x04 }, { 66, 0x00 }, { 67, 0x00 },
111 0x00, 0x00, 0x00, 0x00, /* 68 */ 111 { 68, 0x00 }, { 69, 0x00 }, { 70, 0x00 }, { 71, 0x00 },
112 0x04, 0x00, 0x00, 0x00, /* 72 */ 112 { 72, 0x04 }, { 73, 0x00 }, { 74, 0x00 }, { 75, 0x00 },
113 0x00, 0x00, 0x00, 0x00, /* 76 */ 113 { 76, 0x00 }, { 77, 0x00 }, { 78, 0x00 }, { 79, 0x00 },
114 0x00, 0x00, 0x00, 0x00, /* 80 */ 114 { 80, 0x00 }, { 81, 0x00 }, { 82, 0x00 }, { 83, 0x00 },
115 0x00, 0x00, 0x00, 0x00, /* 84 */ 115 { 84, 0x00 }, { 85, 0x00 }, { 86, 0x00 }, { 87, 0x00 },
116 0x00, 0x00, 0x00, 0x00, /* 88 */ 116 { 88, 0x00 }, { 89, 0x00 }, { 90, 0x00 }, { 91, 0x00 },
117 0x00, 0x00, 0x00, 0x00, /* 92 */ 117 { 92, 0x00 }, { 93, 0x00 }, { 94, 0x00 }, { 95, 0x00 },
118 0x00, 0x00, 0x00, 0x00, /* 96 */ 118 { 96, 0x00 }, { 97, 0x00 }, { 98, 0x00 }, { 99, 0x00 },
119 0x00, 0x00, 0x02, 0x00, /* 100 */ 119 { 100, 0x00 }, { 101, 0x00 }, { 102, 0x02 }, { 103, 0x00 },
120 0x00, 0x00, 0x00, 0x00, /* 104 */ 120 { 104, 0x00 }, { 105, 0x00 }, { 106, 0x00 }, { 107, 0x00 },
121 0x00, 0x00, /* 108 */ 121 { 108, 0x00 }, { 109, 0x00 },
122};
123
124static const struct regmap_config aic3x_regmap = {
125 .reg_bits = 8,
126 .val_bits = 8,
127
128 .max_register = DAC_ICC_ADJ,
129 .reg_defaults = aic3x_reg,
130 .num_reg_defaults = ARRAY_SIZE(aic3x_reg),
131 .cache_type = REGCACHE_RBTREE,
122}; 132};
123 133
124#define SOC_DAPM_SINGLE_AIC3X(xname, reg, shift, mask, invert) \ 134#define SOC_DAPM_SINGLE_AIC3X(xname, reg, shift, mask, invert) \
@@ -1066,30 +1076,6 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai,
1066 return 0; 1076 return 0;
1067} 1077}
1068 1078
1069static int aic3x_init_3007(struct snd_soc_codec *codec)
1070{
1071 unsigned int tmp1, tmp2;
1072
1073 /*
1074 * There is no need to cache writes to undocumented page 0xD but
1075 * respective page 0 register cache entries must be preserved
1076 */
1077 tmp1 = snd_soc_read(codec, 0xD);
1078 tmp2 = snd_soc_read(codec, 0x8);
1079 /* Class-D speaker driver init; datasheet p. 46 */
1080 snd_soc_write(codec, AIC3X_PAGE_SELECT, 0x0D);
1081 snd_soc_write(codec, 0xD, 0x0D);
1082 snd_soc_write(codec, 0x8, 0x5C);
1083 snd_soc_write(codec, 0x8, 0x5D);
1084 snd_soc_write(codec, 0x8, 0x5C);
1085 snd_soc_write(codec, AIC3X_PAGE_SELECT, 0x00);
1086
1087 snd_soc_write(codec, 0xD, tmp1);
1088 snd_soc_write(codec, 0x8, tmp2);
1089
1090 return 0;
1091}
1092
1093static int aic3x_regulator_event(struct notifier_block *nb, 1079static int aic3x_regulator_event(struct notifier_block *nb,
1094 unsigned long event, void *data) 1080 unsigned long event, void *data)
1095{ 1081{
@@ -1104,7 +1090,7 @@ static int aic3x_regulator_event(struct notifier_block *nb,
1104 */ 1090 */
1105 if (gpio_is_valid(aic3x->gpio_reset)) 1091 if (gpio_is_valid(aic3x->gpio_reset))
1106 gpio_set_value(aic3x->gpio_reset, 0); 1092 gpio_set_value(aic3x->gpio_reset, 0);
1107 aic3x->codec->cache_sync = 1; 1093 regcache_mark_dirty(aic3x->regmap);
1108 } 1094 }
1109 1095
1110 return 0; 1096 return 0;
@@ -1113,8 +1099,7 @@ static int aic3x_regulator_event(struct notifier_block *nb,
1113static int aic3x_set_power(struct snd_soc_codec *codec, int power) 1099static int aic3x_set_power(struct snd_soc_codec *codec, int power)
1114{ 1100{
1115 struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); 1101 struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
1116 int i, ret; 1102 int ret;
1117 u8 *cache = codec->reg_cache;
1118 1103
1119 if (power) { 1104 if (power) {
1120 ret = regulator_bulk_enable(ARRAY_SIZE(aic3x->supplies), 1105 ret = regulator_bulk_enable(ARRAY_SIZE(aic3x->supplies),
@@ -1122,12 +1107,6 @@ static int aic3x_set_power(struct snd_soc_codec *codec, int power)
1122 if (ret) 1107 if (ret)
1123 goto out; 1108 goto out;
1124 aic3x->power = 1; 1109 aic3x->power = 1;
1125 /*
1126 * Reset release and cache sync is necessary only if some
1127 * supply was off or if there were cached writes
1128 */
1129 if (!codec->cache_sync)
1130 goto out;
1131 1110
1132 if (gpio_is_valid(aic3x->gpio_reset)) { 1111 if (gpio_is_valid(aic3x->gpio_reset)) {
1133 udelay(1); 1112 udelay(1);
@@ -1135,12 +1114,8 @@ static int aic3x_set_power(struct snd_soc_codec *codec, int power)
1135 } 1114 }
1136 1115
1137 /* Sync reg_cache with the hardware */ 1116 /* Sync reg_cache with the hardware */
1138 codec->cache_only = 0; 1117 regcache_cache_only(aic3x->regmap, false);
1139 for (i = AIC3X_SAMPLE_RATE_SEL_REG; i < ARRAY_SIZE(aic3x_reg); i++) 1118 regcache_sync(aic3x->regmap);
1140 snd_soc_write(codec, i, cache[i]);
1141 if (aic3x->model == AIC3X_MODEL_3007)
1142 aic3x_init_3007(codec);
1143 codec->cache_sync = 0;
1144 } else { 1119 } else {
1145 /* 1120 /*
1146 * Do soft reset to this codec instance in order to clear 1121 * Do soft reset to this codec instance in order to clear
@@ -1148,10 +1123,10 @@ static int aic3x_set_power(struct snd_soc_codec *codec, int power)
1148 * remain on 1123 * remain on
1149 */ 1124 */
1150 snd_soc_write(codec, AIC3X_RESET, SOFT_RESET); 1125 snd_soc_write(codec, AIC3X_RESET, SOFT_RESET);
1151 codec->cache_sync = 1; 1126 regcache_mark_dirty(aic3x->regmap);
1152 aic3x->power = 0; 1127 aic3x->power = 0;
1153 /* HW writes are needless when bias is off */ 1128 /* HW writes are needless when bias is off */
1154 codec->cache_only = 1; 1129 regcache_cache_only(aic3x->regmap, true);
1155 ret = regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies), 1130 ret = regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies),
1156 aic3x->supplies); 1131 aic3x->supplies);
1157 } 1132 }
@@ -1306,7 +1281,6 @@ static int aic3x_init(struct snd_soc_codec *codec)
1306 snd_soc_write(codec, LINE2R_2_MONOLOPM_VOL, DEFAULT_VOL); 1281 snd_soc_write(codec, LINE2R_2_MONOLOPM_VOL, DEFAULT_VOL);
1307 1282
1308 if (aic3x->model == AIC3X_MODEL_3007) { 1283 if (aic3x->model == AIC3X_MODEL_3007) {
1309 aic3x_init_3007(codec);
1310 snd_soc_write(codec, CLASSD_CTRL, 0); 1284 snd_soc_write(codec, CLASSD_CTRL, 0);
1311 } 1285 }
1312 1286
@@ -1334,7 +1308,7 @@ static int aic3x_probe(struct snd_soc_codec *codec)
1334 INIT_LIST_HEAD(&aic3x->list); 1308 INIT_LIST_HEAD(&aic3x->list);
1335 aic3x->codec = codec; 1309 aic3x->codec = codec;
1336 1310
1337 ret = snd_soc_codec_set_cache_io(codec, 8, 8, aic3x->control_type); 1311 ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
1338 if (ret != 0) { 1312 if (ret != 0) {
1339 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); 1313 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
1340 return ret; 1314 return ret;
@@ -1353,7 +1327,7 @@ static int aic3x_probe(struct snd_soc_codec *codec)
1353 } 1327 }
1354 } 1328 }
1355 1329
1356 codec->cache_only = 1; 1330 regcache_mark_dirty(aic3x->regmap);
1357 aic3x_init(codec); 1331 aic3x_init(codec);
1358 1332
1359 if (aic3x->setup) { 1333 if (aic3x->setup) {
@@ -1414,9 +1388,6 @@ static int aic3x_remove(struct snd_soc_codec *codec)
1414static struct snd_soc_codec_driver soc_codec_dev_aic3x = { 1388static struct snd_soc_codec_driver soc_codec_dev_aic3x = {
1415 .set_bias_level = aic3x_set_bias_level, 1389 .set_bias_level = aic3x_set_bias_level,
1416 .idle_bias_off = true, 1390 .idle_bias_off = true,
1417 .reg_cache_size = ARRAY_SIZE(aic3x_reg),
1418 .reg_word_size = sizeof(u8),
1419 .reg_cache_default = aic3x_reg,
1420 .probe = aic3x_probe, 1391 .probe = aic3x_probe,
1421 .remove = aic3x_remove, 1392 .remove = aic3x_remove,
1422 .suspend = aic3x_suspend, 1393 .suspend = aic3x_suspend,
@@ -1443,6 +1414,16 @@ static const struct i2c_device_id aic3x_i2c_id[] = {
1443}; 1414};
1444MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id); 1415MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id);
1445 1416
1417static const struct reg_default aic3007_class_d[] = {
1418 /* Class-D speaker driver init; datasheet p. 46 */
1419 { AIC3X_PAGE_SELECT, 0x0D },
1420 { 0xD, 0x0D },
1421 { 0x8, 0x5C },
1422 { 0x8, 0x5D },
1423 { 0x8, 0x5C },
1424 { AIC3X_PAGE_SELECT, 0x00 },
1425};
1426
1446/* 1427/*
1447 * If the i2c layer weren't so broken, we could pass this kind of data 1428 * If the i2c layer weren't so broken, we could pass this kind of data
1448 * around 1429 * around
@@ -1463,7 +1444,13 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
1463 return -ENOMEM; 1444 return -ENOMEM;
1464 } 1445 }
1465 1446
1466 aic3x->control_type = SND_SOC_I2C; 1447 aic3x->regmap = devm_regmap_init_i2c(i2c, &aic3x_regmap);
1448 if (IS_ERR(aic3x->regmap)) {
1449 ret = PTR_ERR(aic3x->regmap);
1450 return ret;
1451 }
1452
1453 regcache_cache_only(aic3x->regmap, true);
1467 1454
1468 i2c_set_clientdata(i2c, aic3x); 1455 i2c_set_clientdata(i2c, aic3x);
1469 if (pdata) { 1456 if (pdata) {
@@ -1533,6 +1520,14 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
1533 goto err_gpio; 1520 goto err_gpio;
1534 } 1521 }
1535 1522
1523 if (aic3x->model == AIC3X_MODEL_3007) {
1524 ret = regmap_register_patch(aic3x->regmap, aic3007_class_d,
1525 ARRAY_SIZE(aic3007_class_d));
1526 if (ret != 0)
1527 dev_err(&i2c->dev, "Failed to init class D: %d\n",
1528 ret);
1529 }
1530
1536 ret = snd_soc_register_codec(&i2c->dev, 1531 ret = snd_soc_register_codec(&i2c->dev,
1537 &soc_codec_dev_aic3x, &aic3x_dai, 1); 1532 &soc_codec_dev_aic3x, &aic3x_dai, 1);
1538 return ret; 1533 return ret;