Commit 54dc6cabe684375b3cf549c7b0545613d694aba8
Committed by
Mark Brown
1 parent
98d97019c8
Exists in
master
and in
6 other branches
ASoC: sta32x: preserve coefficient RAM
The coefficient RAM must be saved in a shadow so it can be restored when the codec is powered on using regulator_bulk_enable(). Signed-off-by: Johannes Stezenbach <js@sig21.net> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Cc: stable@vger.kernel.org
Showing 2 changed files with 63 additions and 1 deletions Side-by-side Diff
sound/soc/codecs/sta32x.c
... | ... | @@ -76,6 +76,8 @@ |
76 | 76 | |
77 | 77 | unsigned int mclk; |
78 | 78 | unsigned int format; |
79 | + | |
80 | + u32 coef_shadow[STA32X_COEF_COUNT]; | |
79 | 81 | }; |
80 | 82 | |
81 | 83 | static const DECLARE_TLV_DB_SCALE(mvol_tlv, -12700, 50, 1); |
... | ... | @@ -227,6 +229,7 @@ |
227 | 229 | struct snd_ctl_elem_value *ucontrol) |
228 | 230 | { |
229 | 231 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
232 | + struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); | |
230 | 233 | int numcoef = kcontrol->private_value >> 16; |
231 | 234 | int index = kcontrol->private_value & 0xffff; |
232 | 235 | unsigned int cfud; |
... | ... | @@ -239,6 +242,11 @@ |
239 | 242 | snd_soc_write(codec, STA32X_CFUD, cfud); |
240 | 243 | |
241 | 244 | snd_soc_write(codec, STA32X_CFADDR2, index); |
245 | + for (i = 0; i < numcoef && (index + i < STA32X_COEF_COUNT); i++) | |
246 | + sta32x->coef_shadow[index + i] = | |
247 | + (ucontrol->value.bytes.data[3 * i] << 16) | |
248 | + | (ucontrol->value.bytes.data[3 * i + 1] << 8) | |
249 | + | (ucontrol->value.bytes.data[3 * i + 2]); | |
242 | 250 | for (i = 0; i < 3 * numcoef; i++) |
243 | 251 | snd_soc_write(codec, STA32X_B1CF1 + i, |
244 | 252 | ucontrol->value.bytes.data[i]); |
... | ... | @@ -252,6 +260,48 @@ |
252 | 260 | return 0; |
253 | 261 | } |
254 | 262 | |
263 | +int sta32x_sync_coef_shadow(struct snd_soc_codec *codec) | |
264 | +{ | |
265 | + struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); | |
266 | + unsigned int cfud; | |
267 | + int i; | |
268 | + | |
269 | + /* preserve reserved bits in STA32X_CFUD */ | |
270 | + cfud = snd_soc_read(codec, STA32X_CFUD) & 0xf0; | |
271 | + | |
272 | + for (i = 0; i < STA32X_COEF_COUNT; i++) { | |
273 | + snd_soc_write(codec, STA32X_CFADDR2, i); | |
274 | + snd_soc_write(codec, STA32X_B1CF1, | |
275 | + (sta32x->coef_shadow[i] >> 16) & 0xff); | |
276 | + snd_soc_write(codec, STA32X_B1CF2, | |
277 | + (sta32x->coef_shadow[i] >> 8) & 0xff); | |
278 | + snd_soc_write(codec, STA32X_B1CF3, | |
279 | + (sta32x->coef_shadow[i]) & 0xff); | |
280 | + /* chip documentation does not say if the bits are | |
281 | + * self-clearing, so do it explicitly */ | |
282 | + snd_soc_write(codec, STA32X_CFUD, cfud); | |
283 | + snd_soc_write(codec, STA32X_CFUD, cfud | 0x01); | |
284 | + } | |
285 | + return 0; | |
286 | +} | |
287 | + | |
288 | +int sta32x_cache_sync(struct snd_soc_codec *codec) | |
289 | +{ | |
290 | + unsigned int mute; | |
291 | + int rc; | |
292 | + | |
293 | + if (!codec->cache_sync) | |
294 | + return 0; | |
295 | + | |
296 | + /* mute during register sync */ | |
297 | + mute = snd_soc_read(codec, STA32X_MMUTE); | |
298 | + snd_soc_write(codec, STA32X_MMUTE, mute | STA32X_MMUTE_MMUTE); | |
299 | + sta32x_sync_coef_shadow(codec); | |
300 | + rc = snd_soc_cache_sync(codec); | |
301 | + snd_soc_write(codec, STA32X_MMUTE, mute); | |
302 | + return rc; | |
303 | +} | |
304 | + | |
255 | 305 | #define SINGLE_COEF(xname, index) \ |
256 | 306 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ |
257 | 307 | .info = sta32x_coefficient_info, \ |
... | ... | @@ -661,7 +711,7 @@ |
661 | 711 | return ret; |
662 | 712 | } |
663 | 713 | |
664 | - snd_soc_cache_sync(codec); | |
714 | + sta32x_cache_sync(codec); | |
665 | 715 | } |
666 | 716 | |
667 | 717 | /* Power up to mute */ |
... | ... | @@ -789,6 +839,17 @@ |
789 | 839 | snd_soc_update_bits(codec, STA32X_C3CFG, |
790 | 840 | STA32X_CxCFG_OM_MASK, |
791 | 841 | 2 << STA32X_CxCFG_OM_SHIFT); |
842 | + | |
843 | + /* initialize coefficient shadow RAM with reset values */ | |
844 | + for (i = 4; i <= 49; i += 5) | |
845 | + sta32x->coef_shadow[i] = 0x400000; | |
846 | + for (i = 50; i <= 54; i++) | |
847 | + sta32x->coef_shadow[i] = 0x7fffff; | |
848 | + sta32x->coef_shadow[55] = 0x5a9df7; | |
849 | + sta32x->coef_shadow[56] = 0x7fffff; | |
850 | + sta32x->coef_shadow[59] = 0x7fffff; | |
851 | + sta32x->coef_shadow[60] = 0x400000; | |
852 | + sta32x->coef_shadow[61] = 0x400000; | |
792 | 853 | |
793 | 854 | sta32x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
794 | 855 | /* Bias level configuration will have done an extra enable */ |