Commit 54dc6cabe684375b3cf549c7b0545613d694aba8

Authored by Johannes Stezenbach
Committed by Mark Brown
1 parent 98d97019c8

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 */
sound/soc/codecs/sta32x.h
... ... @@ -19,6 +19,7 @@
19 19 /* STA326 register addresses */
20 20  
21 21 #define STA32X_REGISTER_COUNT 0x2d
  22 +#define STA32X_COEF_COUNT 62
22 23  
23 24 #define STA32X_CONFA 0x00
24 25 #define STA32X_CONFB 0x01