1 From 54dc6cabe684375b3cf549c7b0545613d694aba8 Mon Sep 17 00:00:00 2001
2 From: Johannes Stezenbach <js@sig21.net>
3 Date: Mon, 14 Nov 2011 17:23:16 +0100
4 Subject: ASoC: sta32x: preserve coefficient RAM
6 From: Johannes Stezenbach <js@sig21.net>
8 commit 54dc6cabe684375b3cf549c7b0545613d694aba8 upstream.
10 The coefficient RAM must be saved in a shadow so it can
11 be restored when the codec is powered on using
12 regulator_bulk_enable().
14 Signed-off-by: Johannes Stezenbach <js@sig21.net>
15 Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
16 Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
19 sound/soc/codecs/sta32x.c | 63 +++++++++++++++++++++++++++++++++++++++++++++-
20 sound/soc/codecs/sta32x.h | 1
21 2 files changed, 63 insertions(+), 1 deletion(-)
23 --- a/sound/soc/codecs/sta32x.c
24 +++ b/sound/soc/codecs/sta32x.c
25 @@ -76,6 +76,8 @@ struct sta32x_priv {
30 + u32 coef_shadow[STA32X_COEF_COUNT];
33 static const DECLARE_TLV_DB_SCALE(mvol_tlv, -12700, 50, 1);
34 @@ -227,6 +229,7 @@ static int sta32x_coefficient_put(struct
35 struct snd_ctl_elem_value *ucontrol)
37 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
38 + struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
39 int numcoef = kcontrol->private_value >> 16;
40 int index = kcontrol->private_value & 0xffff;
42 @@ -239,6 +242,11 @@ static int sta32x_coefficient_put(struct
43 snd_soc_write(codec, STA32X_CFUD, cfud);
45 snd_soc_write(codec, STA32X_CFADDR2, index);
46 + for (i = 0; i < numcoef && (index + i < STA32X_COEF_COUNT); i++)
47 + sta32x->coef_shadow[index + i] =
48 + (ucontrol->value.bytes.data[3 * i] << 16)
49 + | (ucontrol->value.bytes.data[3 * i + 1] << 8)
50 + | (ucontrol->value.bytes.data[3 * i + 2]);
51 for (i = 0; i < 3 * numcoef; i++)
52 snd_soc_write(codec, STA32X_B1CF1 + i,
53 ucontrol->value.bytes.data[i]);
54 @@ -252,6 +260,48 @@ static int sta32x_coefficient_put(struct
58 +int sta32x_sync_coef_shadow(struct snd_soc_codec *codec)
60 + struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
64 + /* preserve reserved bits in STA32X_CFUD */
65 + cfud = snd_soc_read(codec, STA32X_CFUD) & 0xf0;
67 + for (i = 0; i < STA32X_COEF_COUNT; i++) {
68 + snd_soc_write(codec, STA32X_CFADDR2, i);
69 + snd_soc_write(codec, STA32X_B1CF1,
70 + (sta32x->coef_shadow[i] >> 16) & 0xff);
71 + snd_soc_write(codec, STA32X_B1CF2,
72 + (sta32x->coef_shadow[i] >> 8) & 0xff);
73 + snd_soc_write(codec, STA32X_B1CF3,
74 + (sta32x->coef_shadow[i]) & 0xff);
75 + /* chip documentation does not say if the bits are
76 + * self-clearing, so do it explicitly */
77 + snd_soc_write(codec, STA32X_CFUD, cfud);
78 + snd_soc_write(codec, STA32X_CFUD, cfud | 0x01);
83 +int sta32x_cache_sync(struct snd_soc_codec *codec)
88 + if (!codec->cache_sync)
91 + /* mute during register sync */
92 + mute = snd_soc_read(codec, STA32X_MMUTE);
93 + snd_soc_write(codec, STA32X_MMUTE, mute | STA32X_MMUTE_MMUTE);
94 + sta32x_sync_coef_shadow(codec);
95 + rc = snd_soc_cache_sync(codec);
96 + snd_soc_write(codec, STA32X_MMUTE, mute);
100 #define SINGLE_COEF(xname, index) \
101 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
102 .info = sta32x_coefficient_info, \
103 @@ -657,7 +707,7 @@ static int sta32x_set_bias_level(struct
107 - snd_soc_cache_sync(codec);
108 + sta32x_cache_sync(codec);
111 /* Power up to mute */
112 @@ -792,6 +842,17 @@ static int sta32x_probe(struct snd_soc_c
113 STA32X_CxCFG_OM_MASK,
114 2 << STA32X_CxCFG_OM_SHIFT);
116 + /* initialize coefficient shadow RAM with reset values */
117 + for (i = 4; i <= 49; i += 5)
118 + sta32x->coef_shadow[i] = 0x400000;
119 + for (i = 50; i <= 54; i++)
120 + sta32x->coef_shadow[i] = 0x7fffff;
121 + sta32x->coef_shadow[55] = 0x5a9df7;
122 + sta32x->coef_shadow[56] = 0x7fffff;
123 + sta32x->coef_shadow[59] = 0x7fffff;
124 + sta32x->coef_shadow[60] = 0x400000;
125 + sta32x->coef_shadow[61] = 0x400000;
127 sta32x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
128 /* Bias level configuration will have done an extra enable */
129 regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies);
130 --- a/sound/soc/codecs/sta32x.h
131 +++ b/sound/soc/codecs/sta32x.h
133 /* STA326 register addresses */
135 #define STA32X_REGISTER_COUNT 0x2d
136 +#define STA32X_COEF_COUNT 62
138 #define STA32X_CONFA 0x00
139 #define STA32X_CONFB 0x01