aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/sgtl5000.c
diff options
context:
space:
mode:
authorFabio Estevam <fabio.estevam@freescale.com>2014-05-26 09:34:20 -0400
committerMark Brown <broonie@linaro.org>2014-05-27 07:22:15 -0400
commit29aa37cddfb9b721013ff28608200d73a9426368 (patch)
tree95fce255a4ae2edd577c9a63934c30fab7d8bdf3 /sound/soc/codecs/sgtl5000.c
parent63e54cd9caa3ce03635810608519e2b37d8bc706 (diff)
ASoC: sgtl5000: Fix the cache handling
Since commit e5d80e82e32e (ASoC: sgtl5000: Convert to use regmap directly) a kernel oops is observed after a suspend/resume sequence. The kernel oops happens inside sgtl5000_restore_regs() as codec->reg_cache is no longer a valid pointer. Add the remaining register entries into sgtl5000_reg_defaults[] and remove sgtl5000_restore_regs() completely, which allows suspend/resume to work fine and make the code simpler. Tested on a im53-qsb board. Reported-by: Shawn Guo <shawn.guo@freescale.com> Signed-off-by: Fabio Estevam <fabio.estevam@freescale.com> Tested-by: Shawn Guo <shawn.guo@freescale.com> Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'sound/soc/codecs/sgtl5000.c')
-rw-r--r--sound/soc/codecs/sgtl5000.c75
1 files changed, 15 insertions, 60 deletions
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
index 75f820c58833..f2de658d0923 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -36,18 +36,32 @@
36 36
37/* default value of sgtl5000 registers */ 37/* default value of sgtl5000 registers */
38static const struct reg_default sgtl5000_reg_defaults[] = { 38static const struct reg_default sgtl5000_reg_defaults[] = {
39 { SGTL5000_CHIP_DIG_POWER, 0x0000 },
39 { SGTL5000_CHIP_CLK_CTRL, 0x0008 }, 40 { SGTL5000_CHIP_CLK_CTRL, 0x0008 },
40 { SGTL5000_CHIP_I2S_CTRL, 0x0010 }, 41 { SGTL5000_CHIP_I2S_CTRL, 0x0010 },
41 { SGTL5000_CHIP_SSS_CTRL, 0x0010 }, 42 { SGTL5000_CHIP_SSS_CTRL, 0x0010 },
43 { SGTL5000_CHIP_ADCDAC_CTRL, 0x020c },
42 { SGTL5000_CHIP_DAC_VOL, 0x3c3c }, 44 { SGTL5000_CHIP_DAC_VOL, 0x3c3c },
43 { SGTL5000_CHIP_PAD_STRENGTH, 0x015f }, 45 { SGTL5000_CHIP_PAD_STRENGTH, 0x015f },
46 { SGTL5000_CHIP_ANA_ADC_CTRL, 0x0000 },
44 { SGTL5000_CHIP_ANA_HP_CTRL, 0x1818 }, 47 { SGTL5000_CHIP_ANA_HP_CTRL, 0x1818 },
45 { SGTL5000_CHIP_ANA_CTRL, 0x0111 }, 48 { SGTL5000_CHIP_ANA_CTRL, 0x0111 },
49 { SGTL5000_CHIP_LINREG_CTRL, 0x0000 },
50 { SGTL5000_CHIP_REF_CTRL, 0x0000 },
51 { SGTL5000_CHIP_MIC_CTRL, 0x0000 },
52 { SGTL5000_CHIP_LINE_OUT_CTRL, 0x0000 },
46 { SGTL5000_CHIP_LINE_OUT_VOL, 0x0404 }, 53 { SGTL5000_CHIP_LINE_OUT_VOL, 0x0404 },
47 { SGTL5000_CHIP_ANA_POWER, 0x7060 }, 54 { SGTL5000_CHIP_ANA_POWER, 0x7060 },
48 { SGTL5000_CHIP_PLL_CTRL, 0x5000 }, 55 { SGTL5000_CHIP_PLL_CTRL, 0x5000 },
56 { SGTL5000_CHIP_CLK_TOP_CTRL, 0x0000 },
57 { SGTL5000_CHIP_ANA_STATUS, 0x0000 },
58 { SGTL5000_CHIP_SHORT_CTRL, 0x0000 },
59 { SGTL5000_CHIP_ANA_TEST2, 0x0000 },
60 { SGTL5000_DAP_CTRL, 0x0000 },
61 { SGTL5000_DAP_PEQ, 0x0000 },
49 { SGTL5000_DAP_BASS_ENHANCE, 0x0040 }, 62 { SGTL5000_DAP_BASS_ENHANCE, 0x0040 },
50 { SGTL5000_DAP_BASS_ENHANCE_CTRL, 0x051f }, 63 { SGTL5000_DAP_BASS_ENHANCE_CTRL, 0x051f },
64 { SGTL5000_DAP_AUDIO_EQ, 0x0000 },
51 { SGTL5000_DAP_SURROUND, 0x0040 }, 65 { SGTL5000_DAP_SURROUND, 0x0040 },
52 { SGTL5000_DAP_EQ_BASS_BAND0, 0x002f }, 66 { SGTL5000_DAP_EQ_BASS_BAND0, 0x002f },
53 { SGTL5000_DAP_EQ_BASS_BAND1, 0x002f }, 67 { SGTL5000_DAP_EQ_BASS_BAND1, 0x002f },
@@ -55,6 +69,7 @@ static const struct reg_default sgtl5000_reg_defaults[] = {
55 { SGTL5000_DAP_EQ_BASS_BAND3, 0x002f }, 69 { SGTL5000_DAP_EQ_BASS_BAND3, 0x002f },
56 { SGTL5000_DAP_EQ_BASS_BAND4, 0x002f }, 70 { SGTL5000_DAP_EQ_BASS_BAND4, 0x002f },
57 { SGTL5000_DAP_MAIN_CHAN, 0x8000 }, 71 { SGTL5000_DAP_MAIN_CHAN, 0x8000 },
72 { SGTL5000_DAP_MIX_CHAN, 0x0000 },
58 { SGTL5000_DAP_AVC_CTRL, 0x0510 }, 73 { SGTL5000_DAP_AVC_CTRL, 0x0510 },
59 { SGTL5000_DAP_AVC_THRESHOLD, 0x1473 }, 74 { SGTL5000_DAP_AVC_THRESHOLD, 0x1473 },
60 { SGTL5000_DAP_AVC_ATTACK, 0x0028 }, 75 { SGTL5000_DAP_AVC_ATTACK, 0x0028 },
@@ -1068,71 +1083,11 @@ static int sgtl5000_suspend(struct snd_soc_codec *codec)
1068 return 0; 1083 return 0;
1069} 1084}
1070 1085
1071/*
1072 * restore all sgtl5000 registers,
1073 * since a big hole between dap and regular registers,
1074 * we will restore them respectively.
1075 */
1076static int sgtl5000_restore_regs(struct snd_soc_codec *codec)
1077{
1078 u16 *cache = codec->reg_cache;
1079 u16 reg;
1080
1081 /* restore regular registers */
1082 for (reg = 0; reg <= SGTL5000_CHIP_SHORT_CTRL; reg += 2) {
1083
1084 /* These regs should restore in particular order */
1085 if (reg == SGTL5000_CHIP_ANA_POWER ||
1086 reg == SGTL5000_CHIP_CLK_CTRL ||
1087 reg == SGTL5000_CHIP_LINREG_CTRL ||
1088 reg == SGTL5000_CHIP_LINE_OUT_CTRL ||
1089 reg == SGTL5000_CHIP_REF_CTRL)
1090 continue;
1091
1092 snd_soc_write(codec, reg, cache[reg]);
1093 }
1094
1095 /* restore dap registers */
1096 for (reg = SGTL5000_DAP_REG_OFFSET; reg < SGTL5000_MAX_REG_OFFSET; reg += 2)
1097 snd_soc_write(codec, reg, cache[reg]);
1098
1099 /*
1100 * restore these regs according to the power setting sequence in
1101 * sgtl5000_set_power_regs() and clock setting sequence in
1102 * sgtl5000_set_clock().
1103 *
1104 * The order of restore is:
1105 * 1. SGTL5000_CHIP_CLK_CTRL MCLK_FREQ bits (1:0) should be restore after
1106 * SGTL5000_CHIP_ANA_POWER PLL bits set
1107 * 2. SGTL5000_CHIP_LINREG_CTRL should be set before
1108 * SGTL5000_CHIP_ANA_POWER LINREG_D restored
1109 * 3. SGTL5000_CHIP_REF_CTRL controls Analog Ground Voltage,
1110 * prefer to resotre it after SGTL5000_CHIP_ANA_POWER restored
1111 */
1112 snd_soc_write(codec, SGTL5000_CHIP_LINREG_CTRL,
1113 cache[SGTL5000_CHIP_LINREG_CTRL]);
1114
1115 snd_soc_write(codec, SGTL5000_CHIP_ANA_POWER,
1116 cache[SGTL5000_CHIP_ANA_POWER]);
1117
1118 snd_soc_write(codec, SGTL5000_CHIP_CLK_CTRL,
1119 cache[SGTL5000_CHIP_CLK_CTRL]);
1120
1121 snd_soc_write(codec, SGTL5000_CHIP_REF_CTRL,
1122 cache[SGTL5000_CHIP_REF_CTRL]);
1123
1124 snd_soc_write(codec, SGTL5000_CHIP_LINE_OUT_CTRL,
1125 cache[SGTL5000_CHIP_LINE_OUT_CTRL]);
1126 return 0;
1127}
1128
1129static int sgtl5000_resume(struct snd_soc_codec *codec) 1086static int sgtl5000_resume(struct snd_soc_codec *codec)
1130{ 1087{
1131 /* Bring the codec back up to standby to enable regulators */ 1088 /* Bring the codec back up to standby to enable regulators */
1132 sgtl5000_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1089 sgtl5000_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1133 1090
1134 /* Restore registers by cached in memory */
1135 sgtl5000_restore_regs(codec);
1136 return 0; 1091 return 0;
1137} 1092}
1138#else 1093#else