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
committerMark Brown <broonie@opensource.wolfsonmicro.com>2011-08-02 21:21:42 -0400
commit151798f872d6b386d82cd1707ad703e981fef8f2 (patch)
tree22bdd1a3b0270ce8b9353011b686b45875d51d03 /sound/soc/codecs/sgtl5000.c
parentf9925d4400927fcf3e25cd371442e47d40b37536 (diff)
ASoC: sgtl5000: fix cache handling
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> Cc: stable@kernel.org
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 76258f2a2ffb..7e4066e131e6 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 */
@@ -1023,12 +981,10 @@ static int sgtl5000_suspend(struct snd_soc_codec *codec, pm_message_t state)
1023static int sgtl5000_restore_regs(struct snd_soc_codec *codec) 981static int sgtl5000_restore_regs(struct snd_soc_codec *codec)
1024{ 982{
1025 u16 *cache = codec->reg_cache; 983 u16 *cache = codec->reg_cache;
1026 int i; 984 u16 reg;
1027 int regular_regs = SGTL5000_CHIP_SHORT_CTRL >> 1;
1028 985
1029 /* restore regular registers */ 986 /* restore regular registers */
1030 for (i = 0; i < regular_regs; i++) { 987 for (reg = 0; reg <= SGTL5000_CHIP_SHORT_CTRL; reg += 2) {
1031 int reg = i << 1;
1032 988
1033 /* this regs depends on the others */ 989 /* this regs depends on the others */
1034 if (reg == SGTL5000_CHIP_ANA_POWER || 990 if (reg == SGTL5000_CHIP_ANA_POWER ||
@@ -1038,35 +994,31 @@ static int sgtl5000_restore_regs(struct snd_soc_codec *codec)
1038 reg == SGTL5000_CHIP_CLK_CTRL) 994 reg == SGTL5000_CHIP_CLK_CTRL)
1039 continue; 995 continue;
1040 996
1041 snd_soc_write(codec, reg, cache[i]); 997 snd_soc_write(codec, reg, cache[reg]);
1042 } 998 }
1043 999
1044 /* restore dap registers */ 1000 /* restore dap registers */
1045 for (i = SGTL5000_DAP_REG_OFFSET >> 1; 1001 for (reg = SGTL5000_DAP_REG_OFFSET; reg < SGTL5000_MAX_REG_OFFSET; reg += 2)
1046 i < SGTL5000_MAX_REG_OFFSET >> 1; i++) { 1002 snd_soc_write(codec, reg, cache[reg]);
1047 int reg = i << 1;
1048
1049 snd_soc_write(codec, reg, cache[i]);
1050 }
1051 1003
1052 /* 1004 /*
1053 * restore power and other regs according 1005 * restore power and other regs according
1054 * to set_power() and set_clock() 1006 * to set_power() and set_clock()
1055 */ 1007 */
1056 snd_soc_write(codec, SGTL5000_CHIP_LINREG_CTRL, 1008 snd_soc_write(codec, SGTL5000_CHIP_LINREG_CTRL,
1057 cache[SGTL5000_CHIP_LINREG_CTRL >> 1]); 1009 cache[SGTL5000_CHIP_LINREG_CTRL]);
1058 1010
1059 snd_soc_write(codec, SGTL5000_CHIP_ANA_POWER, 1011 snd_soc_write(codec, SGTL5000_CHIP_ANA_POWER,
1060 cache[SGTL5000_CHIP_ANA_POWER >> 1]); 1012 cache[SGTL5000_CHIP_ANA_POWER]);
1061 1013
1062 snd_soc_write(codec, SGTL5000_CHIP_CLK_CTRL, 1014 snd_soc_write(codec, SGTL5000_CHIP_CLK_CTRL,
1063 cache[SGTL5000_CHIP_CLK_CTRL >> 1]); 1015 cache[SGTL5000_CHIP_CLK_CTRL]);
1064 1016
1065 snd_soc_write(codec, SGTL5000_CHIP_REF_CTRL, 1017 snd_soc_write(codec, SGTL5000_CHIP_REF_CTRL,
1066 cache[SGTL5000_CHIP_REF_CTRL >> 1]); 1018 cache[SGTL5000_CHIP_REF_CTRL]);
1067 1019
1068 snd_soc_write(codec, SGTL5000_CHIP_LINE_OUT_CTRL, 1020 snd_soc_write(codec, SGTL5000_CHIP_LINE_OUT_CTRL,
1069 cache[SGTL5000_CHIP_LINE_OUT_CTRL >> 1]); 1021 cache[SGTL5000_CHIP_LINE_OUT_CTRL]);
1070 return 0; 1022 return 0;
1071} 1023}
1072 1024
@@ -1454,16 +1406,6 @@ static __devinit int sgtl5000_i2c_probe(struct i2c_client *client,
1454 if (!sgtl5000) 1406 if (!sgtl5000)
1455 return -ENOMEM; 1407 return -ENOMEM;
1456 1408
1457 /*
1458 * copy DAP default values to default value array.
1459 * sgtl5000 register space has a big hole, merge it
1460 * at init phase makes life easy.
1461 * FIXME: should we drop 'const' of sgtl5000_regs?
1462 */
1463 memcpy((void *)(&sgtl5000_regs[0] + (SGTL5000_DAP_REG_OFFSET >> 1)),
1464 sgtl5000_dap_regs,
1465 SGTL5000_MAX_REG_OFFSET - SGTL5000_DAP_REG_OFFSET);
1466
1467 i2c_set_clientdata(client, sgtl5000); 1409 i2c_set_clientdata(client, sgtl5000);
1468 1410
1469 ret = snd_soc_register_codec(&client->dev, 1411 ret = snd_soc_register_codec(&client->dev,