aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Ujfalusi <peter.ujfalusi@ti.com>2013-11-29 09:03:47 -0500
committerMark Brown <broonie@linaro.org>2013-12-19 13:37:07 -0500
commit626bcacb89f93b2145f3a705a342067a77347a99 (patch)
tree366a5a962a2f60a8617462726ea334b3eff73166
parent79ae5130381cb7d3e74c162123392ba6067c218e (diff)
ASoC: twl6040: Remove self managed local reg_cache support
We can rely on mfd driver to manage the register caching via regmap. The driver still need to cache some registers associated with DL1/2 routes. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com> Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r--sound/soc/codecs/twl6040.c211
1 files changed, 49 insertions, 162 deletions
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
index b07839b2d912..0afe8bef6765 100644
--- a/sound/soc/codecs/twl6040.c
+++ b/sound/soc/codecs/twl6040.c
@@ -80,59 +80,6 @@ struct twl6040_data {
80 struct mutex mutex; 80 struct mutex mutex;
81}; 81};
82 82
83/*
84 * twl6040 register cache & default register settings
85 */
86static const u8 twl6040_reg[TWL6040_CACHEREGNUM] = {
87 0x00, /* not used 0x00 */
88 0x4B, /* REG_ASICID 0x01 (ro) */
89 0x00, /* REG_ASICREV 0x02 (ro) */
90 0x00, /* REG_INTID 0x03 */
91 0x00, /* REG_INTMR 0x04 */
92 0x00, /* REG_NCPCTRL 0x05 */
93 0x00, /* REG_LDOCTL 0x06 */
94 0x60, /* REG_HPPLLCTL 0x07 */
95 0x00, /* REG_LPPLLCTL 0x08 */
96 0x4A, /* REG_LPPLLDIV 0x09 */
97 0x00, /* REG_AMICBCTL 0x0A */
98 0x00, /* REG_DMICBCTL 0x0B */
99 0x00, /* REG_MICLCTL 0x0C */
100 0x00, /* REG_MICRCTL 0x0D */
101 0x00, /* REG_MICGAIN 0x0E */
102 0x1B, /* REG_LINEGAIN 0x0F */
103 0x00, /* REG_HSLCTL 0x10 */
104 0x00, /* REG_HSRCTL 0x11 */
105 0x00, /* REG_HSGAIN 0x12 */
106 0x00, /* REG_EARCTL 0x13 */
107 0x00, /* REG_HFLCTL 0x14 */
108 0x00, /* REG_HFLGAIN 0x15 */
109 0x00, /* REG_HFRCTL 0x16 */
110 0x00, /* REG_HFRGAIN 0x17 */
111 0x00, /* REG_VIBCTLL 0x18 */
112 0x00, /* REG_VIBDATL 0x19 */
113 0x00, /* REG_VIBCTLR 0x1A */
114 0x00, /* REG_VIBDATR 0x1B */
115 0x00, /* REG_HKCTL1 0x1C */
116 0x00, /* REG_HKCTL2 0x1D */
117 0x00, /* REG_GPOCTL 0x1E */
118 0x00, /* REG_ALB 0x1F */
119 0x00, /* REG_DLB 0x20 */
120 0x00, /* not used 0x21 */
121 0x00, /* not used 0x22 */
122 0x00, /* not used 0x23 */
123 0x00, /* not used 0x24 */
124 0x00, /* not used 0x25 */
125 0x00, /* not used 0x26 */
126 0x00, /* not used 0x27 */
127 0x00, /* REG_TRIM1 0x28 */
128 0x00, /* REG_TRIM2 0x29 */
129 0x00, /* REG_TRIM3 0x2A */
130 0x00, /* REG_HSOTRIM 0x2B */
131 0x00, /* REG_HFOTRIM 0x2C */
132 0x09, /* REG_ACCCTL 0x2D */
133 0x00, /* REG_STATUS 0x2E (ro) */
134};
135
136/* set of rates for each pll: low-power and high-performance */ 83/* set of rates for each pll: low-power and high-performance */
137static unsigned int lp_rates[] = { 84static unsigned int lp_rates[] = {
138 8000, 85 8000,
@@ -159,11 +106,14 @@ static struct snd_pcm_hw_constraint_list sysclk_constraints[] = {
159 { .count = ARRAY_SIZE(hp_rates), .list = hp_rates, }, 106 { .count = ARRAY_SIZE(hp_rates), .list = hp_rates, },
160}; 107};
161 108
162static inline int twl6040_read_dl12_cache(struct snd_soc_codec *codec, 109static unsigned int twl6040_read(struct snd_soc_codec *codec, unsigned int reg)
163 u8 reg, u8 *value)
164{ 110{
165 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 111 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
166 int ret = 0; 112 struct twl6040 *twl6040 = codec->control_data;
113 u8 value;
114
115 if (reg >= TWL6040_CACHEREGNUM)
116 return -EIO;
167 117
168 switch (reg) { 118 switch (reg) {
169 case TWL6040_REG_HSLCTL: 119 case TWL6040_REG_HSLCTL:
@@ -171,36 +121,18 @@ static inline int twl6040_read_dl12_cache(struct snd_soc_codec *codec,
171 case TWL6040_REG_EARCTL: 121 case TWL6040_REG_EARCTL:
172 case TWL6040_REG_HFLCTL: 122 case TWL6040_REG_HFLCTL:
173 case TWL6040_REG_HFRCTL: 123 case TWL6040_REG_HFRCTL:
174 *value = priv->dl12_cache[reg - TWL6040_REG_HSLCTL]; 124 value = priv->dl12_cache[reg - TWL6040_REG_HSLCTL];
175 break; 125 break;
176 default: 126 default:
177 ret = -EINVAL; 127 value = twl6040_reg_read(twl6040, reg);
178 break; 128 break;
179 } 129 }
180 130
181 return ret;
182}
183
184/*
185 * read twl6040 register cache
186 */
187static inline unsigned int twl6040_read_reg_cache(struct snd_soc_codec *codec,
188 unsigned int reg)
189{
190 u8 *cache = codec->reg_cache;
191 u8 value;
192
193 if (reg >= TWL6040_CACHEREGNUM)
194 return -EIO;
195
196 if (twl6040_read_dl12_cache(codec, reg, &value))
197 value = cache[reg];
198
199 return value; 131 return value;
200} 132}
201 133
202static inline void twl6040_update_dl12_cache(struct snd_soc_codec *codec, 134static bool twl6040_can_write_to_chip(struct snd_soc_codec *codec,
203 u8 reg, u8 value) 135 unsigned int reg)
204{ 136{
205 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 137 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
206 138
@@ -208,50 +140,18 @@ static inline void twl6040_update_dl12_cache(struct snd_soc_codec *codec,
208 case TWL6040_REG_HSLCTL: 140 case TWL6040_REG_HSLCTL:
209 case TWL6040_REG_HSRCTL: 141 case TWL6040_REG_HSRCTL:
210 case TWL6040_REG_EARCTL: 142 case TWL6040_REG_EARCTL:
143 /* DL1 path */
144 return priv->dl1_unmuted;
211 case TWL6040_REG_HFLCTL: 145 case TWL6040_REG_HFLCTL:
212 case TWL6040_REG_HFRCTL: 146 case TWL6040_REG_HFRCTL:
213 priv->dl12_cache[reg - TWL6040_REG_HSLCTL] = value; 147 return priv->dl2_unmuted;
214 break;
215 default: 148 default:
216 break; 149 return 1;
217 } 150 }
218} 151}
219 152
220/* 153static inline void twl6040_update_dl12_cache(struct snd_soc_codec *codec,
221 * write twl6040 register cache 154 u8 reg, u8 value)
222 */
223static inline void twl6040_write_reg_cache(struct snd_soc_codec *codec,
224 u8 reg, u8 value)
225{
226 u8 *cache = codec->reg_cache;
227
228 if (reg >= TWL6040_CACHEREGNUM)
229 return;
230 cache[reg] = value;
231
232 twl6040_update_dl12_cache(codec, reg, value);
233}
234
235/*
236 * read from twl6040 hardware register
237 */
238static int twl6040_read_reg_volatile(struct snd_soc_codec *codec,
239 unsigned int reg)
240{
241 struct twl6040 *twl6040 = codec->control_data;
242 u8 value;
243
244 if (reg >= TWL6040_CACHEREGNUM)
245 return -EIO;
246
247 value = twl6040_reg_read(twl6040, reg);
248 twl6040_write_reg_cache(codec, reg, value);
249
250 return value;
251}
252
253static bool twl6040_can_write_to_chip(struct snd_soc_codec *codec,
254 unsigned int reg)
255{ 155{
256 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 156 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
257 157
@@ -259,19 +159,15 @@ static bool twl6040_can_write_to_chip(struct snd_soc_codec *codec,
259 case TWL6040_REG_HSLCTL: 159 case TWL6040_REG_HSLCTL:
260 case TWL6040_REG_HSRCTL: 160 case TWL6040_REG_HSRCTL:
261 case TWL6040_REG_EARCTL: 161 case TWL6040_REG_EARCTL:
262 /* DL1 path */
263 return priv->dl1_unmuted;
264 case TWL6040_REG_HFLCTL: 162 case TWL6040_REG_HFLCTL:
265 case TWL6040_REG_HFRCTL: 163 case TWL6040_REG_HFRCTL:
266 return priv->dl2_unmuted; 164 priv->dl12_cache[reg - TWL6040_REG_HSLCTL] = value;
165 break;
267 default: 166 default:
268 return 1; 167 break;
269 } 168 }
270} 169}
271 170
272/*
273 * write to the twl6040 register space
274 */
275static int twl6040_write(struct snd_soc_codec *codec, 171static int twl6040_write(struct snd_soc_codec *codec,
276 unsigned int reg, unsigned int value) 172 unsigned int reg, unsigned int value)
277{ 173{
@@ -280,7 +176,7 @@ static int twl6040_write(struct snd_soc_codec *codec,
280 if (reg >= TWL6040_CACHEREGNUM) 176 if (reg >= TWL6040_CACHEREGNUM)
281 return -EIO; 177 return -EIO;
282 178
283 twl6040_write_reg_cache(codec, reg, value); 179 twl6040_update_dl12_cache(codec, reg, value);
284 if (twl6040_can_write_to_chip(codec, reg)) 180 if (twl6040_can_write_to_chip(codec, reg))
285 return twl6040_reg_write(twl6040, reg, value); 181 return twl6040_reg_write(twl6040, reg, value);
286 else 182 else
@@ -289,34 +185,27 @@ static int twl6040_write(struct snd_soc_codec *codec,
289 185
290static void twl6040_init_chip(struct snd_soc_codec *codec) 186static void twl6040_init_chip(struct snd_soc_codec *codec)
291{ 187{
292 struct twl6040 *twl6040 = codec->control_data; 188 twl6040_read(codec, TWL6040_REG_TRIM1);
293 u8 val; 189 twl6040_read(codec, TWL6040_REG_TRIM2);
294 190 twl6040_read(codec, TWL6040_REG_TRIM3);
295 /* Update reg_cache: ASICREV, and TRIM values */ 191 twl6040_read(codec, TWL6040_REG_HSOTRIM);
296 val = twl6040_get_revid(twl6040); 192 twl6040_read(codec, TWL6040_REG_HFOTRIM);
297 twl6040_write_reg_cache(codec, TWL6040_REG_ASICREV, val);
298
299 twl6040_read_reg_volatile(codec, TWL6040_REG_TRIM1);
300 twl6040_read_reg_volatile(codec, TWL6040_REG_TRIM2);
301 twl6040_read_reg_volatile(codec, TWL6040_REG_TRIM3);
302 twl6040_read_reg_volatile(codec, TWL6040_REG_HSOTRIM);
303 twl6040_read_reg_volatile(codec, TWL6040_REG_HFOTRIM);
304 193
305 /* Change chip defaults */ 194 /* Change chip defaults */
306 /* No imput selected for microphone amplifiers */ 195 /* No imput selected for microphone amplifiers */
307 twl6040_write_reg_cache(codec, TWL6040_REG_MICLCTL, 0x18); 196 twl6040_write(codec, TWL6040_REG_MICLCTL, 0x18);
308 twl6040_write_reg_cache(codec, TWL6040_REG_MICRCTL, 0x18); 197 twl6040_write(codec, TWL6040_REG_MICRCTL, 0x18);
309 198
310 /* 199 /*
311 * We need to lower the default gain values, so the ramp code 200 * We need to lower the default gain values, so the ramp code
312 * can work correctly for the first playback. 201 * can work correctly for the first playback.
313 * This reduces the pop noise heard at the first playback. 202 * This reduces the pop noise heard at the first playback.
314 */ 203 */
315 twl6040_write_reg_cache(codec, TWL6040_REG_HSGAIN, 0xff); 204 twl6040_write(codec, TWL6040_REG_HSGAIN, 0xff);
316 twl6040_write_reg_cache(codec, TWL6040_REG_EARCTL, 0x1e); 205 twl6040_write(codec, TWL6040_REG_EARCTL, 0x1e);
317 twl6040_write_reg_cache(codec, TWL6040_REG_HFLGAIN, 0x1d); 206 twl6040_write(codec, TWL6040_REG_HFLGAIN, 0x1d);
318 twl6040_write_reg_cache(codec, TWL6040_REG_HFRGAIN, 0x1d); 207 twl6040_write(codec, TWL6040_REG_HFRGAIN, 0x1d);
319 twl6040_write_reg_cache(codec, TWL6040_REG_LINEGAIN, 0); 208 twl6040_write(codec, TWL6040_REG_LINEGAIN, 0);
320} 209}
321 210
322/* set headset dac and driver power mode */ 211/* set headset dac and driver power mode */
@@ -325,8 +214,8 @@ static int headset_power_mode(struct snd_soc_codec *codec, int high_perf)
325 int hslctl, hsrctl; 214 int hslctl, hsrctl;
326 int mask = TWL6040_HSDRVMODE | TWL6040_HSDACMODE; 215 int mask = TWL6040_HSDRVMODE | TWL6040_HSDACMODE;
327 216
328 hslctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSLCTL); 217 hslctl = twl6040_read(codec, TWL6040_REG_HSLCTL);
329 hsrctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSRCTL); 218 hsrctl = twl6040_read(codec, TWL6040_REG_HSRCTL);
330 219
331 if (high_perf) { 220 if (high_perf) {
332 hslctl &= ~mask; 221 hslctl &= ~mask;
@@ -353,8 +242,8 @@ static int twl6040_hs_dac_event(struct snd_soc_dapm_widget *w,
353 * Both HS DAC need to be turned on (before the HS driver) and off at 242 * Both HS DAC need to be turned on (before the HS driver) and off at
354 * the same time. 243 * the same time.
355 */ 244 */
356 hslctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSLCTL); 245 hslctl = twl6040_read(codec, TWL6040_REG_HSLCTL);
357 hsrctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSRCTL); 246 hsrctl = twl6040_read(codec, TWL6040_REG_HSRCTL);
358 if (SND_SOC_DAPM_EVENT_ON(event)) { 247 if (SND_SOC_DAPM_EVENT_ON(event)) {
359 hslctl |= TWL6040_HSDACENA; 248 hslctl |= TWL6040_HSDACENA;
360 hsrctl |= TWL6040_HSDACENA; 249 hsrctl |= TWL6040_HSDACENA;
@@ -399,7 +288,7 @@ static void twl6040_hs_jack_report(struct snd_soc_codec *codec,
399 mutex_lock(&priv->mutex); 288 mutex_lock(&priv->mutex);
400 289
401 /* Sync status */ 290 /* Sync status */
402 status = twl6040_read_reg_volatile(codec, TWL6040_REG_STATUS); 291 status = twl6040_read(codec, TWL6040_REG_STATUS);
403 if (status & TWL6040_PLUGCOMP) 292 if (status & TWL6040_PLUGCOMP)
404 snd_soc_jack_report(jack, report, report); 293 snd_soc_jack_report(jack, report, report);
405 else 294 else
@@ -451,7 +340,7 @@ static int twl6040_soc_dapm_put_vibra_enum(struct snd_kcontrol *kcontrol,
451 unsigned int val; 340 unsigned int val;
452 341
453 /* Do not allow changes while Input/FF efect is running */ 342 /* Do not allow changes while Input/FF efect is running */
454 val = twl6040_read_reg_volatile(codec, e->reg); 343 val = twl6040_read(codec, e->reg);
455 if (val & TWL6040_VIBENA && !(val & TWL6040_VIBSEL)) 344 if (val & TWL6040_VIBENA && !(val & TWL6040_VIBSEL))
456 return -EBUSY; 345 return -EBUSY;
457 346
@@ -676,7 +565,7 @@ int twl6040_get_trim_value(struct snd_soc_codec *codec, enum twl6040_trim trim)
676 if (unlikely(trim >= TWL6040_TRIM_INVAL)) 565 if (unlikely(trim >= TWL6040_TRIM_INVAL))
677 return -EINVAL; 566 return -EINVAL;
678 567
679 return twl6040_read_reg_cache(codec, TWL6040_REG_TRIM1 + trim); 568 return twl6040_read(codec, TWL6040_REG_TRIM1 + trim);
680} 569}
681EXPORT_SYMBOL_GPL(twl6040_get_trim_value); 570EXPORT_SYMBOL_GPL(twl6040_get_trim_value);
682 571
@@ -1071,9 +960,9 @@ static void twl6040_mute_path(struct snd_soc_codec *codec, enum twl6040_dai_id i
1071 960
1072 switch (id) { 961 switch (id) {
1073 case TWL6040_DAI_DL1: 962 case TWL6040_DAI_DL1:
1074 hslctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSLCTL); 963 hslctl = twl6040_read(codec, TWL6040_REG_HSLCTL);
1075 hsrctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSRCTL); 964 hsrctl = twl6040_read(codec, TWL6040_REG_HSRCTL);
1076 earctl = twl6040_read_reg_cache(codec, TWL6040_REG_EARCTL); 965 earctl = twl6040_read(codec, TWL6040_REG_EARCTL);
1077 966
1078 if (mute) { 967 if (mute) {
1079 /* Power down drivers and DACs */ 968 /* Power down drivers and DACs */
@@ -1089,8 +978,8 @@ static void twl6040_mute_path(struct snd_soc_codec *codec, enum twl6040_dai_id i
1089 priv->dl1_unmuted = !mute; 978 priv->dl1_unmuted = !mute;
1090 break; 979 break;
1091 case TWL6040_DAI_DL2: 980 case TWL6040_DAI_DL2:
1092 hflctl = twl6040_read_reg_cache(codec, TWL6040_REG_HFLCTL); 981 hflctl = twl6040_read(codec, TWL6040_REG_HFLCTL);
1093 hfrctl = twl6040_read_reg_cache(codec, TWL6040_REG_HFRCTL); 982 hfrctl = twl6040_read(codec, TWL6040_REG_HFRCTL);
1094 983
1095 if (mute) { 984 if (mute) {
1096 /* Power down drivers and DACs */ 985 /* Power down drivers and DACs */
@@ -1227,6 +1116,7 @@ static int twl6040_resume(struct snd_soc_codec *codec)
1227static int twl6040_probe(struct snd_soc_codec *codec) 1116static int twl6040_probe(struct snd_soc_codec *codec)
1228{ 1117{
1229 struct twl6040_data *priv; 1118 struct twl6040_data *priv;
1119 struct twl6040 *twl6040 = dev_get_drvdata(codec->dev->parent);
1230 struct platform_device *pdev = container_of(codec->dev, 1120 struct platform_device *pdev = container_of(codec->dev,
1231 struct platform_device, dev); 1121 struct platform_device, dev);
1232 int ret = 0; 1122 int ret = 0;
@@ -1238,7 +1128,7 @@ static int twl6040_probe(struct snd_soc_codec *codec)
1238 snd_soc_codec_set_drvdata(codec, priv); 1128 snd_soc_codec_set_drvdata(codec, priv);
1239 1129
1240 priv->codec = codec; 1130 priv->codec = codec;
1241 codec->control_data = dev_get_drvdata(codec->dev->parent); 1131 codec->control_data = twl6040;
1242 1132
1243 priv->plug_irq = platform_get_irq(pdev, 0); 1133 priv->plug_irq = platform_get_irq(pdev, 0);
1244 if (priv->plug_irq < 0) { 1134 if (priv->plug_irq < 0) {
@@ -1258,10 +1148,10 @@ static int twl6040_probe(struct snd_soc_codec *codec)
1258 return ret; 1148 return ret;
1259 } 1149 }
1260 1150
1151 twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1261 twl6040_init_chip(codec); 1152 twl6040_init_chip(codec);
1262 1153
1263 /* power on device */ 1154 return 0;
1264 return twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1265} 1155}
1266 1156
1267static int twl6040_remove(struct snd_soc_codec *codec) 1157static int twl6040_remove(struct snd_soc_codec *codec)
@@ -1279,12 +1169,9 @@ static struct snd_soc_codec_driver soc_codec_dev_twl6040 = {
1279 .remove = twl6040_remove, 1169 .remove = twl6040_remove,
1280 .suspend = twl6040_suspend, 1170 .suspend = twl6040_suspend,
1281 .resume = twl6040_resume, 1171 .resume = twl6040_resume,
1282 .read = twl6040_read_reg_cache, 1172 .read = twl6040_read,
1283 .write = twl6040_write, 1173 .write = twl6040_write,
1284 .set_bias_level = twl6040_set_bias_level, 1174 .set_bias_level = twl6040_set_bias_level,
1285 .reg_cache_size = ARRAY_SIZE(twl6040_reg),
1286 .reg_word_size = sizeof(u8),
1287 .reg_cache_default = twl6040_reg,
1288 .ignore_pmdown_time = true, 1175 .ignore_pmdown_time = true,
1289 1176
1290 .controls = twl6040_snd_controls, 1177 .controls = twl6040_snd_controls,