Skip to content

Commit 41b6c4b

Browse files
Fabio Estevamchrillomat
authored andcommitted
ASoC: sgtl5000: Fix the cache handling
Since commit e5d80e8 (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> (cherry picked from commit 29aa37c) Conflicts (resolved): sound/soc/codecs/sgtl5000.c
1 parent 584a896 commit 41b6c4b

File tree

1 file changed

+16
-61
lines changed

1 file changed

+16
-61
lines changed

sound/soc/codecs/sgtl5000.c

Lines changed: 16 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -36,25 +36,40 @@
3636

3737
/* default value of sgtl5000 registers */
3838
static const struct reg_default sgtl5000_reg_defaults[] = {
39+
{ SGTL5000_CHIP_DIG_POWER, 0x0000 },
3940
{ SGTL5000_CHIP_CLK_CTRL, 0x0008 },
4041
{ SGTL5000_CHIP_I2S_CTRL, 0x0010 },
41-
{ SGTL5000_CHIP_SSS_CTRL, 0x0008 },
42+
{ SGTL5000_CHIP_SSS_CTRL, 0x0010 },
43+
{ SGTL5000_CHIP_ADCDAC_CTRL, 0x020c },
4244
{ SGTL5000_CHIP_DAC_VOL, 0x3c3c },
4345
{ SGTL5000_CHIP_PAD_STRENGTH, 0x015f },
46+
{ SGTL5000_CHIP_ANA_ADC_CTRL, 0x0000 },
4447
{ SGTL5000_CHIP_ANA_HP_CTRL, 0x1818 },
4548
{ 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 },
4653
{ SGTL5000_CHIP_LINE_OUT_VOL, 0x0404 },
4754
{ SGTL5000_CHIP_ANA_POWER, 0x7060 },
4855
{ 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 },
4962
{ SGTL5000_DAP_BASS_ENHANCE, 0x0040 },
5063
{ SGTL5000_DAP_BASS_ENHANCE_CTRL, 0x051f },
64+
{ SGTL5000_DAP_AUDIO_EQ, 0x0000 },
5165
{ SGTL5000_DAP_SURROUND, 0x0040 },
5266
{ SGTL5000_DAP_EQ_BASS_BAND0, 0x002f },
5367
{ SGTL5000_DAP_EQ_BASS_BAND1, 0x002f },
5468
{ SGTL5000_DAP_EQ_BASS_BAND2, 0x002f },
5569
{ SGTL5000_DAP_EQ_BASS_BAND3, 0x002f },
5670
{ SGTL5000_DAP_EQ_BASS_BAND4, 0x002f },
5771
{ SGTL5000_DAP_MAIN_CHAN, 0x8000 },
72+
{ SGTL5000_DAP_MIX_CHAN, 0x0000 },
5873
{ SGTL5000_DAP_AVC_CTRL, 0x0510 },
5974
{ SGTL5000_DAP_AVC_THRESHOLD, 0x1473 },
6075
{ SGTL5000_DAP_AVC_ATTACK, 0x0028 },
@@ -1037,71 +1052,11 @@ static int sgtl5000_suspend(struct snd_soc_codec *codec)
10371052
return 0;
10381053
}
10391054

1040-
/*
1041-
* restore all sgtl5000 registers,
1042-
* since a big hole between dap and regular registers,
1043-
* we will restore them respectively.
1044-
*/
1045-
static int sgtl5000_restore_regs(struct snd_soc_codec *codec)
1046-
{
1047-
u16 *cache = codec->reg_cache;
1048-
u16 reg;
1049-
1050-
/* restore regular registers */
1051-
for (reg = 0; reg <= SGTL5000_CHIP_SHORT_CTRL; reg += 2) {
1052-
1053-
/* These regs should restore in particular order */
1054-
if (reg == SGTL5000_CHIP_ANA_POWER ||
1055-
reg == SGTL5000_CHIP_CLK_CTRL ||
1056-
reg == SGTL5000_CHIP_LINREG_CTRL ||
1057-
reg == SGTL5000_CHIP_LINE_OUT_CTRL ||
1058-
reg == SGTL5000_CHIP_REF_CTRL)
1059-
continue;
1060-
1061-
snd_soc_write(codec, reg, cache[reg]);
1062-
}
1063-
1064-
/* restore dap registers */
1065-
for (reg = SGTL5000_DAP_REG_OFFSET; reg < SGTL5000_MAX_REG_OFFSET; reg += 2)
1066-
snd_soc_write(codec, reg, cache[reg]);
1067-
1068-
/*
1069-
* restore these regs according to the power setting sequence in
1070-
* sgtl5000_set_power_regs() and clock setting sequence in
1071-
* sgtl5000_set_clock().
1072-
*
1073-
* The order of restore is:
1074-
* 1. SGTL5000_CHIP_CLK_CTRL MCLK_FREQ bits (1:0) should be restore after
1075-
* SGTL5000_CHIP_ANA_POWER PLL bits set
1076-
* 2. SGTL5000_CHIP_LINREG_CTRL should be set before
1077-
* SGTL5000_CHIP_ANA_POWER LINREG_D restored
1078-
* 3. SGTL5000_CHIP_REF_CTRL controls Analog Ground Voltage,
1079-
* prefer to resotre it after SGTL5000_CHIP_ANA_POWER restored
1080-
*/
1081-
snd_soc_write(codec, SGTL5000_CHIP_LINREG_CTRL,
1082-
cache[SGTL5000_CHIP_LINREG_CTRL]);
1083-
1084-
snd_soc_write(codec, SGTL5000_CHIP_ANA_POWER,
1085-
cache[SGTL5000_CHIP_ANA_POWER]);
1086-
1087-
snd_soc_write(codec, SGTL5000_CHIP_CLK_CTRL,
1088-
cache[SGTL5000_CHIP_CLK_CTRL]);
1089-
1090-
snd_soc_write(codec, SGTL5000_CHIP_REF_CTRL,
1091-
cache[SGTL5000_CHIP_REF_CTRL]);
1092-
1093-
snd_soc_write(codec, SGTL5000_CHIP_LINE_OUT_CTRL,
1094-
cache[SGTL5000_CHIP_LINE_OUT_CTRL]);
1095-
return 0;
1096-
}
1097-
10981055
static int sgtl5000_resume(struct snd_soc_codec *codec)
10991056
{
11001057
/* Bring the codec back up to standby to enable regulators */
11011058
sgtl5000_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
11021059

1103-
/* Restore registers by cached in memory */
1104-
sgtl5000_restore_regs(codec);
11051060
return 0;
11061061
}
11071062
#else

0 commit comments

Comments
 (0)