aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/twl6040.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/twl6040.c')
-rw-r--r--sound/soc/codecs/twl6040.c114
1 files changed, 22 insertions, 92 deletions
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
index 443032b3b329..81645c632447 100644
--- a/sound/soc/codecs/twl6040.c
+++ b/sound/soc/codecs/twl6040.c
@@ -118,8 +118,8 @@ static const u8 twl6040_reg[TWL6040_CACHEREGNUM] = {
118 0x4A, /* TWL6040_LPPLLDIV 0x09 */ 118 0x4A, /* TWL6040_LPPLLDIV 0x09 */
119 0x00, /* TWL6040_AMICBCTL 0x0A */ 119 0x00, /* TWL6040_AMICBCTL 0x0A */
120 0x00, /* TWL6040_DMICBCTL 0x0B */ 120 0x00, /* TWL6040_DMICBCTL 0x0B */
121 0x18, /* TWL6040_MICLCTL 0x0C - No input selected on Left Mic */ 121 0x00, /* TWL6040_MICLCTL 0x0C */
122 0x18, /* TWL6040_MICRCTL 0x0D - No input selected on Right Mic */ 122 0x00, /* TWL6040_MICRCTL 0x0D */
123 0x00, /* TWL6040_MICGAIN 0x0E */ 123 0x00, /* TWL6040_MICGAIN 0x0E */
124 0x1B, /* TWL6040_LINEGAIN 0x0F */ 124 0x1B, /* TWL6040_LINEGAIN 0x0F */
125 0x00, /* TWL6040_HSLCTL 0x10 */ 125 0x00, /* TWL6040_HSLCTL 0x10 */
@@ -155,41 +155,8 @@ static const u8 twl6040_reg[TWL6040_CACHEREGNUM] = {
155 0x00, /* TWL6040_STATUS (ro) 0x2E */ 155 0x00, /* TWL6040_STATUS (ro) 0x2E */
156}; 156};
157 157
158/* 158/* List of registers to be restored after power up */
159 * twl6040 vio/gnd registers: 159static const int twl6040_restore_list[] = {
160 * registers under vio/gnd supply can be accessed
161 * before the power-up sequence, after NRESPWRON goes high
162 */
163static const int twl6040_vio_reg[TWL6040_VIOREGNUM] = {
164 TWL6040_REG_ASICID,
165 TWL6040_REG_ASICREV,
166 TWL6040_REG_INTID,
167 TWL6040_REG_INTMR,
168 TWL6040_REG_NCPCTL,
169 TWL6040_REG_LDOCTL,
170 TWL6040_REG_AMICBCTL,
171 TWL6040_REG_DMICBCTL,
172 TWL6040_REG_HKCTL1,
173 TWL6040_REG_HKCTL2,
174 TWL6040_REG_GPOCTL,
175 TWL6040_REG_TRIM1,
176 TWL6040_REG_TRIM2,
177 TWL6040_REG_TRIM3,
178 TWL6040_REG_HSOTRIM,
179 TWL6040_REG_HFOTRIM,
180 TWL6040_REG_ACCCTL,
181 TWL6040_REG_STATUS,
182};
183
184/*
185 * twl6040 vdd/vss registers:
186 * registers under vdd/vss supplies can only be accessed
187 * after the power-up sequence
188 */
189static const int twl6040_vdd_reg[TWL6040_VDDREGNUM] = {
190 TWL6040_REG_HPPLLCTL,
191 TWL6040_REG_LPPLLCTL,
192 TWL6040_REG_LPPLLDIV,
193 TWL6040_REG_MICLCTL, 160 TWL6040_REG_MICLCTL,
194 TWL6040_REG_MICRCTL, 161 TWL6040_REG_MICRCTL,
195 TWL6040_REG_MICGAIN, 162 TWL6040_REG_MICGAIN,
@@ -202,12 +169,6 @@ static const int twl6040_vdd_reg[TWL6040_VDDREGNUM] = {
202 TWL6040_REG_HFLGAIN, 169 TWL6040_REG_HFLGAIN,
203 TWL6040_REG_HFRCTL, 170 TWL6040_REG_HFRCTL,
204 TWL6040_REG_HFRGAIN, 171 TWL6040_REG_HFRGAIN,
205 TWL6040_REG_VIBCTLL,
206 TWL6040_REG_VIBDATL,
207 TWL6040_REG_VIBCTLR,
208 TWL6040_REG_VIBDATR,
209 TWL6040_REG_ALB,
210 TWL6040_REG_DLB,
211}; 172};
212 173
213/* set of rates for each pll: low-power and high-performance */ 174/* set of rates for each pll: low-power and high-performance */
@@ -296,56 +257,27 @@ static int twl6040_write(struct snd_soc_codec *codec,
296 return twl6040_reg_write(twl6040, reg, value); 257 return twl6040_reg_write(twl6040, reg, value);
297} 258}
298 259
299static void twl6040_init_vio_regs(struct snd_soc_codec *codec) 260static void twl6040_init_chip(struct snd_soc_codec *codec)
300{ 261{
301 u8 *cache = codec->reg_cache; 262 struct twl6040 *twl6040 = codec->control_data;
302 int reg, i; 263 u8 val;
303 264
304 for (i = 0; i < TWL6040_VIOREGNUM; i++) { 265 val = twl6040_get_revid(twl6040);
305 reg = twl6040_vio_reg[i]; 266 twl6040_write_reg_cache(codec, TWL6040_REG_ASICREV, val);
306 /* 267
307 * skip read-only registers (ASICID, ASICREV, STATUS) 268 /* Change chip defaults */
308 * and registers shared among MFD children 269 /* No imput selected for microphone amplifiers */
309 */ 270 twl6040_write_reg_cache(codec, TWL6040_REG_MICLCTL, 0x18);
310 switch (reg) { 271 twl6040_write_reg_cache(codec, TWL6040_REG_MICRCTL, 0x18);
311 case TWL6040_REG_ASICID:
312 case TWL6040_REG_ASICREV:
313 case TWL6040_REG_INTID:
314 case TWL6040_REG_INTMR:
315 case TWL6040_REG_NCPCTL:
316 case TWL6040_REG_LDOCTL:
317 case TWL6040_REG_GPOCTL:
318 case TWL6040_REG_ACCCTL:
319 case TWL6040_REG_STATUS:
320 continue;
321 default:
322 break;
323 }
324 twl6040_write(codec, reg, cache[reg]);
325 }
326} 272}
327 273
328static void twl6040_init_vdd_regs(struct snd_soc_codec *codec) 274static void twl6040_restore_regs(struct snd_soc_codec *codec)
329{ 275{
330 u8 *cache = codec->reg_cache; 276 u8 *cache = codec->reg_cache;
331 int reg, i; 277 int reg, i;
332 278
333 for (i = 0; i < TWL6040_VDDREGNUM; i++) { 279 for (i = 0; i < ARRAY_SIZE(twl6040_restore_list); i++) {
334 reg = twl6040_vdd_reg[i]; 280 reg = twl6040_restore_list[i];
335 /* skip vibra and PLL registers */
336 switch (reg) {
337 case TWL6040_REG_VIBCTLL:
338 case TWL6040_REG_VIBDATL:
339 case TWL6040_REG_VIBCTLR:
340 case TWL6040_REG_VIBDATR:
341 case TWL6040_REG_HPPLLCTL:
342 case TWL6040_REG_LPPLLCTL:
343 case TWL6040_REG_LPPLLDIV:
344 continue;
345 default:
346 break;
347 }
348
349 twl6040_write(codec, reg, cache[reg]); 281 twl6040_write(codec, reg, cache[reg]);
350 } 282 }
351} 283}
@@ -1325,8 +1257,7 @@ static int twl6040_set_bias_level(struct snd_soc_codec *codec,
1325 1257
1326 priv->codec_powered = 1; 1258 priv->codec_powered = 1;
1327 1259
1328 /* initialize vdd/vss registers with reg_cache */ 1260 twl6040_restore_regs(codec);
1329 twl6040_init_vdd_regs(codec);
1330 1261
1331 /* Set external boost GPO */ 1262 /* Set external boost GPO */
1332 twl6040_write(codec, TWL6040_REG_GPOCTL, 0x02); 1263 twl6040_write(codec, TWL6040_REG_GPOCTL, 0x02);
@@ -1468,7 +1399,7 @@ static struct snd_soc_dai_driver twl6040_dai[] = {
1468 .playback = { 1399 .playback = {
1469 .stream_name = "Playback", 1400 .stream_name = "Playback",
1470 .channels_min = 1, 1401 .channels_min = 1,
1471 .channels_max = 2, 1402 .channels_max = 5,
1472 .rates = TWL6040_RATES, 1403 .rates = TWL6040_RATES,
1473 .formats = TWL6040_FORMATS, 1404 .formats = TWL6040_FORMATS,
1474 }, 1405 },
@@ -1518,8 +1449,8 @@ static struct snd_soc_dai_driver twl6040_dai[] = {
1518 .name = "twl6040-vib", 1449 .name = "twl6040-vib",
1519 .playback = { 1450 .playback = {
1520 .stream_name = "Vibra Playback", 1451 .stream_name = "Vibra Playback",
1521 .channels_min = 2, 1452 .channels_min = 1,
1522 .channels_max = 2, 1453 .channels_max = 1,
1523 .rates = SNDRV_PCM_RATE_CONTINUOUS, 1454 .rates = SNDRV_PCM_RATE_CONTINUOUS,
1524 .formats = TWL6040_FORMATS, 1455 .formats = TWL6040_FORMATS,
1525 }, 1456 },
@@ -1620,8 +1551,7 @@ static int twl6040_probe(struct snd_soc_codec *codec)
1620 goto plugirq_err; 1551 goto plugirq_err;
1621 } 1552 }
1622 1553
1623 /* init vio registers */ 1554 twl6040_init_chip(codec);
1624 twl6040_init_vio_regs(codec);
1625 1555
1626 /* power on device */ 1556 /* power on device */
1627 ret = twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1557 ret = twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY);