]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/3.1.5/asoc-sta32x-preserve-coefficient-ram.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 3.1.5 / asoc-sta32x-preserve-coefficient-ram.patch
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
5
6 From: Johannes Stezenbach <js@sig21.net>
7
8 commit 54dc6cabe684375b3cf549c7b0545613d694aba8 upstream.
9
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().
13
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>
17
18 ---
19 sound/soc/codecs/sta32x.c | 63 +++++++++++++++++++++++++++++++++++++++++++++-
20 sound/soc/codecs/sta32x.h | 1
21 2 files changed, 63 insertions(+), 1 deletion(-)
22
23 --- a/sound/soc/codecs/sta32x.c
24 +++ b/sound/soc/codecs/sta32x.c
25 @@ -76,6 +76,8 @@ struct sta32x_priv {
26
27 unsigned int mclk;
28 unsigned int format;
29 +
30 + u32 coef_shadow[STA32X_COEF_COUNT];
31 };
32
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)
36 {
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;
41 unsigned int cfud;
42 @@ -239,6 +242,11 @@ static int sta32x_coefficient_put(struct
43 snd_soc_write(codec, STA32X_CFUD, cfud);
44
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
55 return 0;
56 }
57
58 +int sta32x_sync_coef_shadow(struct snd_soc_codec *codec)
59 +{
60 + struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
61 + unsigned int cfud;
62 + int i;
63 +
64 + /* preserve reserved bits in STA32X_CFUD */
65 + cfud = snd_soc_read(codec, STA32X_CFUD) & 0xf0;
66 +
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);
79 + }
80 + return 0;
81 +}
82 +
83 +int sta32x_cache_sync(struct snd_soc_codec *codec)
84 +{
85 + unsigned int mute;
86 + int rc;
87 +
88 + if (!codec->cache_sync)
89 + return 0;
90 +
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);
97 + return rc;
98 +}
99 +
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
104 return ret;
105 }
106
107 - snd_soc_cache_sync(codec);
108 + sta32x_cache_sync(codec);
109 }
110
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);
115
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;
126 +
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
132 @@ -19,6 +19,7 @@
133 /* STA326 register addresses */
134
135 #define STA32X_REGISTER_COUNT 0x2d
136 +#define STA32X_COEF_COUNT 62
137
138 #define STA32X_CONFA 0x00
139 #define STA32X_CONFB 0x01