aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/sgtl5000.c
diff options
context:
space:
mode:
authorWolfram Sang <w.sang@pengutronix.de>2011-08-02 13:42:19 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2011-08-15 21:31:36 -0400
commit4c1f50da71cc26a4074ec4b1cb748869a6279f39 (patch)
tree6c42694ac62f7f5f66d0486aec62f56f46fbcd21 /sound/soc/codecs/sgtl5000.c
parent407529f61453bf0e683aa4584bfe2a5b864f1525 (diff)
ASoC: sgtl5000: fix cache handling
commit 151798f872d6b386d82cd1707ad703e981fef8f2 upstream. Cache handling in this driver is broken. The chip has 16-bit registers, yet the register numbers also increase by 2 per register, i.e. there are only even-numbered registers. The cache in this driver, though, simply increments register numbers, so it does need some mapping as seen in sgtl5000_restore_regs(), note the '>> 1': snd_soc_write(codec, SGTL5000_CHIP_LINREG_CTRL, cache[SGTL5000_CHIP_LINREG_CTRL >> 1]); That, of course, won't work with snd_soc_update_bits(). (Thus, we won't even notice the missing register 0x1c in the default regs which shifted all follwing registers to wrong values.) Noticed on the MX28EVK where enabling the regulators simply locked up the chip. Refactor the routines and use a properly sized default_regs array which matches the register layout of the underlying chip, i.e. create a truly flat cache. This also saves some code which should make up for the bigger array a little. When soc-core will somewhen have another cache type which handles a step size, this conversion will also ease the transition. Signed-off-by: Wolfram Sang <w.sang@pengutronix.de> Tested-by: Dong Aisheng <b29396@freescale.com> Tested-by: Shawn Guo <shawn.guo@linaro.org> Acked-by: Liam Girdwood <lrg@ti.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'sound/soc/codecs/sgtl5000.c')
-rw-r--r--sound/soc/codecs/sgtl5000.c128
1 files changed, 35 insertions, 93 deletions
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
index ff29380c9ed..c49317c255d 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -33,73 +33,31 @@
33#define SGTL5000_DAP_REG_OFFSET 0x0100 33#define SGTL5000_DAP_REG_OFFSET 0x0100
34#define SGTL5000_MAX_REG_OFFSET 0x013A 34#define SGTL5000_MAX_REG_OFFSET 0x013A
35 35
36/* default value of sgtl5000 registers except DAP */ 36/* default value of sgtl5000 registers */
37static const u16 sgtl5000_regs[SGTL5000_MAX_REG_OFFSET >> 1] = { 37static const u16 sgtl5000_regs[SGTL5000_MAX_REG_OFFSET] = {
38 0xa011, /* 0x0000, CHIP_ID. 11 stand for revison 17 */ 38 [SGTL5000_CHIP_CLK_CTRL] = 0x0008,
39 0x0000, /* 0x0002, CHIP_DIG_POWER. */ 39 [SGTL5000_CHIP_I2S_CTRL] = 0x0010,
40 0x0008, /* 0x0004, CHIP_CKL_CTRL */ 40 [SGTL5000_CHIP_SSS_CTRL] = 0x0008,
41 0x0010, /* 0x0006, CHIP_I2S_CTRL */ 41 [SGTL5000_CHIP_DAC_VOL] = 0x3c3c,
42 0x0000, /* 0x0008, reserved */ 42 [SGTL5000_CHIP_PAD_STRENGTH] = 0x015f,
43 0x0008, /* 0x000A, CHIP_SSS_CTRL */ 43 [SGTL5000_CHIP_ANA_HP_CTRL] = 0x1818,
44 0x0000, /* 0x000C, reserved */ 44 [SGTL5000_CHIP_ANA_CTRL] = 0x0111,
45 0x020c, /* 0x000E, CHIP_ADCDAC_CTRL */ 45 [SGTL5000_CHIP_LINE_OUT_VOL] = 0x0404,
46 0x3c3c, /* 0x0010, CHIP_DAC_VOL */ 46 [SGTL5000_CHIP_ANA_POWER] = 0x7060,
47 0x0000, /* 0x0012, reserved */ 47 [SGTL5000_CHIP_PLL_CTRL] = 0x5000,
48 0x015f, /* 0x0014, CHIP_PAD_STRENGTH */ 48 [SGTL5000_DAP_BASS_ENHANCE] = 0x0040,
49 0x0000, /* 0x0016, reserved */ 49 [SGTL5000_DAP_BASS_ENHANCE_CTRL] = 0x051f,
50 0x0000, /* 0x0018, reserved */ 50 [SGTL5000_DAP_SURROUND] = 0x0040,
51 0x0000, /* 0x001A, reserved */ 51 [SGTL5000_DAP_EQ_BASS_BAND0] = 0x002f,
52 0x0000, /* 0x001E, reserved */ 52 [SGTL5000_DAP_EQ_BASS_BAND1] = 0x002f,
53 0x0000, /* 0x0020, CHIP_ANA_ADC_CTRL */ 53 [SGTL5000_DAP_EQ_BASS_BAND2] = 0x002f,
54 0x1818, /* 0x0022, CHIP_ANA_HP_CTRL */ 54 [SGTL5000_DAP_EQ_BASS_BAND3] = 0x002f,
55 0x0111, /* 0x0024, CHIP_ANN_CTRL */ 55 [SGTL5000_DAP_EQ_BASS_BAND4] = 0x002f,
56 0x0000, /* 0x0026, CHIP_LINREG_CTRL */ 56 [SGTL5000_DAP_MAIN_CHAN] = 0x8000,
57 0x0000, /* 0x0028, CHIP_REF_CTRL */ 57 [SGTL5000_DAP_AVC_CTRL] = 0x0510,
58 0x0000, /* 0x002A, CHIP_MIC_CTRL */ 58 [SGTL5000_DAP_AVC_THRESHOLD] = 0x1473,
59 0x0000, /* 0x002C, CHIP_LINE_OUT_CTRL */ 59 [SGTL5000_DAP_AVC_ATTACK] = 0x0028,
60 0x0404, /* 0x002E, CHIP_LINE_OUT_VOL */ 60 [SGTL5000_DAP_AVC_DECAY] = 0x0050,
61 0x7060, /* 0x0030, CHIP_ANA_POWER */
62 0x5000, /* 0x0032, CHIP_PLL_CTRL */
63 0x0000, /* 0x0034, CHIP_CLK_TOP_CTRL */
64 0x0000, /* 0x0036, CHIP_ANA_STATUS */
65 0x0000, /* 0x0038, reserved */
66 0x0000, /* 0x003A, CHIP_ANA_TEST2 */
67 0x0000, /* 0x003C, CHIP_SHORT_CTRL */
68 0x0000, /* reserved */
69};
70
71/* default value of dap registers */
72static const u16 sgtl5000_dap_regs[] = {
73 0x0000, /* 0x0100, DAP_CONTROL */
74 0x0000, /* 0x0102, DAP_PEQ */
75 0x0040, /* 0x0104, DAP_BASS_ENHANCE */
76 0x051f, /* 0x0106, DAP_BASS_ENHANCE_CTRL */
77 0x0000, /* 0x0108, DAP_AUDIO_EQ */
78 0x0040, /* 0x010A, DAP_SGTL_SURROUND */
79 0x0000, /* 0x010C, DAP_FILTER_COEF_ACCESS */
80 0x0000, /* 0x010E, DAP_COEF_WR_B0_MSB */
81 0x0000, /* 0x0110, DAP_COEF_WR_B0_LSB */
82 0x0000, /* 0x0112, reserved */
83 0x0000, /* 0x0114, reserved */
84 0x002f, /* 0x0116, DAP_AUDIO_EQ_BASS_BAND0 */
85 0x002f, /* 0x0118, DAP_AUDIO_EQ_BAND0 */
86 0x002f, /* 0x011A, DAP_AUDIO_EQ_BAND2 */
87 0x002f, /* 0x011C, DAP_AUDIO_EQ_BAND3 */
88 0x002f, /* 0x011E, DAP_AUDIO_EQ_TREBLE_BAND4 */
89 0x8000, /* 0x0120, DAP_MAIN_CHAN */
90 0x0000, /* 0x0122, DAP_MIX_CHAN */
91 0x0510, /* 0x0124, DAP_AVC_CTRL */
92 0x1473, /* 0x0126, DAP_AVC_THRESHOLD */
93 0x0028, /* 0x0128, DAP_AVC_ATTACK */
94 0x0050, /* 0x012A, DAP_AVC_DECAY */
95 0x0000, /* 0x012C, DAP_COEF_WR_B1_MSB */
96 0x0000, /* 0x012E, DAP_COEF_WR_B1_LSB */
97 0x0000, /* 0x0130, DAP_COEF_WR_B2_MSB */
98 0x0000, /* 0x0132, DAP_COEF_WR_B2_LSB */
99 0x0000, /* 0x0134, DAP_COEF_WR_A1_MSB */
100 0x0000, /* 0x0136, DAP_COEF_WR_A1_LSB */
101 0x0000, /* 0x0138, DAP_COEF_WR_A2_MSB */
102 0x0000, /* 0x013A, DAP_COEF_WR_A2_LSB */
103}; 61};
104 62
105/* regulator supplies for sgtl5000, VDDD is an optional external supply */ 63/* regulator supplies for sgtl5000, VDDD is an optional external supply */
@@ -1022,12 +980,10 @@ static int sgtl5000_suspend(struct snd_soc_codec *codec, pm_message_t state)
1022static int sgtl5000_restore_regs(struct snd_soc_codec *codec) 980static int sgtl5000_restore_regs(struct snd_soc_codec *codec)
1023{ 981{
1024 u16 *cache = codec->reg_cache; 982 u16 *cache = codec->reg_cache;
1025 int i; 983 u16 reg;
1026 int regular_regs = SGTL5000_CHIP_SHORT_CTRL >> 1;
1027 984
1028 /* restore regular registers */ 985 /* restore regular registers */
1029 for (i = 0; i < regular_regs; i++) { 986 for (reg = 0; reg <= SGTL5000_CHIP_SHORT_CTRL; reg += 2) {
1030 int reg = i << 1;
1031 987
1032 /* this regs depends on the others */ 988 /* this regs depends on the others */
1033 if (reg == SGTL5000_CHIP_ANA_POWER || 989 if (reg == SGTL5000_CHIP_ANA_POWER ||
@@ -1037,35 +993,31 @@ static int sgtl5000_restore_regs(struct snd_soc_codec *codec)
1037 reg == SGTL5000_CHIP_CLK_CTRL) 993 reg == SGTL5000_CHIP_CLK_CTRL)
1038 continue; 994 continue;
1039 995
1040 snd_soc_write(codec, reg, cache[i]); 996 snd_soc_write(codec, reg, cache[reg]);
1041 } 997 }
1042 998
1043 /* restore dap registers */ 999 /* restore dap registers */
1044 for (i = SGTL5000_DAP_REG_OFFSET >> 1; 1000 for (reg = SGTL5000_DAP_REG_OFFSET; reg < SGTL5000_MAX_REG_OFFSET; reg += 2)
1045 i < SGTL5000_MAX_REG_OFFSET >> 1; i++) { 1001 snd_soc_write(codec, reg, cache[reg]);
1046 int reg = i << 1;
1047
1048 snd_soc_write(codec, reg, cache[i]);
1049 }
1050 1002
1051 /* 1003 /*
1052 * restore power and other regs according 1004 * restore power and other regs according
1053 * to set_power() and set_clock() 1005 * to set_power() and set_clock()
1054 */ 1006 */
1055 snd_soc_write(codec, SGTL5000_CHIP_LINREG_CTRL, 1007 snd_soc_write(codec, SGTL5000_CHIP_LINREG_CTRL,
1056 cache[SGTL5000_CHIP_LINREG_CTRL >> 1]); 1008 cache[SGTL5000_CHIP_LINREG_CTRL]);
1057 1009
1058 snd_soc_write(codec, SGTL5000_CHIP_ANA_POWER, 1010 snd_soc_write(codec, SGTL5000_CHIP_ANA_POWER,
1059 cache[SGTL5000_CHIP_ANA_POWER >> 1]); 1011 cache[SGTL5000_CHIP_ANA_POWER]);
1060 1012
1061 snd_soc_write(codec, SGTL5000_CHIP_CLK_CTRL, 1013 snd_soc_write(codec, SGTL5000_CHIP_CLK_CTRL,
1062 cache[SGTL5000_CHIP_CLK_CTRL >> 1]); 1014 cache[SGTL5000_CHIP_CLK_CTRL]);
1063 1015
1064 snd_soc_write(codec, SGTL5000_CHIP_REF_CTRL, 1016 snd_soc_write(codec, SGTL5000_CHIP_REF_CTRL,
1065 cache[SGTL5000_CHIP_REF_CTRL >> 1]); 1017 cache[SGTL5000_CHIP_REF_CTRL]);
1066 1018
1067 snd_soc_write(codec, SGTL5000_CHIP_LINE_OUT_CTRL, 1019 snd_soc_write(codec, SGTL5000_CHIP_LINE_OUT_CTRL,
1068 cache[SGTL5000_CHIP_LINE_OUT_CTRL >> 1]); 1020 cache[SGTL5000_CHIP_LINE_OUT_CTRL]);
1069 return 0; 1021 return 0;
1070} 1022}
1071 1023
@@ -1460,16 +1412,6 @@ static __devinit int sgtl5000_i2c_probe(struct i2c_client *client,
1460 if (!sgtl5000) 1412 if (!sgtl5000)
1461 return -ENOMEM; 1413 return -ENOMEM;
1462 1414
1463 /*
1464 * copy DAP default values to default value array.
1465 * sgtl5000 register space has a big hole, merge it
1466 * at init phase makes life easy.
1467 * FIXME: should we drop 'const' of sgtl5000_regs?
1468 */
1469 memcpy((void *)(&sgtl5000_regs[0] + (SGTL5000_DAP_REG_OFFSET >> 1)),
1470 sgtl5000_dap_regs,
1471 SGTL5000_MAX_REG_OFFSET - SGTL5000_DAP_REG_OFFSET);
1472
1473 i2c_set_clientdata(client, sgtl5000); 1415 i2c_set_clientdata(client, sgtl5000);
1474 1416
1475 ret = snd_soc_register_codec(&client->dev, 1417 ret = snd_soc_register_codec(&client->dev,