summaryrefslogtreecommitdiff
path: root/sound/soc/codecs/sgtl5000.c
diff options
context:
space:
mode:
authorFabio Estevam <fabio.estevam@freescale.com>2013-05-09 21:15:47 -0300
committerMarcel Ziswiler <marcel.ziswiler@toradex.com>2014-09-16 15:07:37 +0200
commit0c014d290863c2bda630886660809b996e5dae4e (patch)
treedc53941de6db1a59b839c7c42d74a9273f6e411c /sound/soc/codecs/sgtl5000.c
parent2df7c712311f5b6b0ed6ee281564f91713a6ebf2 (diff)
ASoC: sgtl5000: Fix driver probe after reset
After a 'reboot' command in Linux or after pressing the system's reset button the sgtl5000 driver fails to probe: sgtl5000 0-000a: Device with ID register ffff is not a sgtl5000 sgtl5000 0-000a: ASoC: failed to probe CODEC -19 imx-sgtl5000 sound.12: ASoC: failed to instantiate card -19 imx-sgtl5000 sound.12: snd_soc_register_card failed (-19) sgtl5000 codec does not have a reset line, nor a reset command in software, so after a system reset the codec does not contain the default register values from sgtl5000_reg_defaults[] anymore, as these are only valid after a power-on-reset cycle. Fix this issue by explicitly reading all the reset register values from sgtl5000_reg_defaults[] and writing them back into sgtl5000 to ensure a sane state. Signed-off-by: Fabio Estevam <fabio.estevam@freescale.com> Tested-by: Eric Nelson <eric.nelson@boundarydevices.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> (cherry picked from commit af8ee11209e749c75eabf32b2a4ca631f396acf8) Conflicts: sound/soc/codecs/sgtl5000.c
Diffstat (limited to 'sound/soc/codecs/sgtl5000.c')
-rw-r--r--sound/soc/codecs/sgtl5000.c64
1 files changed, 64 insertions, 0 deletions
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
index 86d46ef9947c..eeb4bb2060d4 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -35,6 +35,37 @@
#define SGTL5000_MAX_REG_OFFSET 0x013A
/* default value of sgtl5000 registers */
+struct reg_default {
+ unsigned int reg;
+ unsigned int def;
+};
+
+static const struct reg_default sgtl5000_reg_defaults[] = {
+ { SGTL5000_CHIP_CLK_CTRL, 0x0008 },
+ { SGTL5000_CHIP_I2S_CTRL, 0x0010 },
+ { SGTL5000_CHIP_SSS_CTRL, 0x0008 },
+ { SGTL5000_CHIP_DAC_VOL, 0x3c3c },
+ { SGTL5000_CHIP_PAD_STRENGTH, 0x015f },
+ { SGTL5000_CHIP_ANA_HP_CTRL, 0x1818 },
+ { SGTL5000_CHIP_ANA_CTRL, 0x0111 },
+ { SGTL5000_CHIP_LINE_OUT_VOL, 0x0404 },
+ { SGTL5000_CHIP_ANA_POWER, 0x7060 },
+ { SGTL5000_CHIP_PLL_CTRL, 0x5000 },
+ { SGTL5000_DAP_BASS_ENHANCE, 0x0040 },
+ { SGTL5000_DAP_BASS_ENHANCE_CTRL, 0x051f },
+ { SGTL5000_DAP_SURROUND, 0x0040 },
+ { SGTL5000_DAP_EQ_BASS_BAND0, 0x002f },
+ { SGTL5000_DAP_EQ_BASS_BAND1, 0x002f },
+ { SGTL5000_DAP_EQ_BASS_BAND2, 0x002f },
+ { SGTL5000_DAP_EQ_BASS_BAND3, 0x002f },
+ { SGTL5000_DAP_EQ_BASS_BAND4, 0x002f },
+ { SGTL5000_DAP_MAIN_CHAN, 0x8000 },
+ { SGTL5000_DAP_AVC_CTRL, 0x0510 },
+ { SGTL5000_DAP_AVC_THRESHOLD, 0x1473 },
+ { SGTL5000_DAP_AVC_ATTACK, 0x0028 },
+ { SGTL5000_DAP_AVC_DECAY, 0x0050 },
+};
+
static const u16 sgtl5000_regs[SGTL5000_MAX_REG_OFFSET] = {
[SGTL5000_CHIP_CLK_CTRL] = 0x0008,
[SGTL5000_CHIP_I2S_CTRL] = 0x0010,
@@ -1292,6 +1323,31 @@ err_regulator_free:
}
+/*
+ * Write all the default values from sgtl5000_reg_defaults[] array into the
+ * sgtl5000 registers, to make sure we always start with the sane registers
+ * values as stated in the datasheet.
+ *
+ * Since sgtl5000 does not have a reset line, nor a reset command in software,
+ * we follow this approach to guarantee we always start from the default values
+ * and avoid problems like, not being able to probe after an audio playback
+ * followed by a system reset or a 'reboot' command in Linux
+ */
+static int sgtl5000_fill_defaults(struct snd_soc_codec *codec)
+{
+ int i, ret, val, index;
+
+ for (i = 0; i < ARRAY_SIZE(sgtl5000_reg_defaults); i++) {
+ val = sgtl5000_reg_defaults[i].def;
+ index = sgtl5000_reg_defaults[i].reg;
+ ret = snd_soc_write(codec, index, val);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
static int sgtl5000_probe(struct snd_soc_codec *codec)
{
int ret;
@@ -1304,6 +1360,14 @@ static int sgtl5000_probe(struct snd_soc_codec *codec)
return ret;
}
+ /* Ensure sgtl5000 will start with sane register values */
+ ret = sgtl5000_fill_defaults(codec);
+ if (ret) {
+ dev_err(codec->dev, "Failed ensuring sgtl5000 will start with "
+ "sane register values: %d\n", ret);
+ return ret;
+ }
+
ret = sgtl5000_enable_regulators(codec);
if (ret)
return ret;