aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2010-12-28 15:37:59 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2010-12-28 18:19:36 -0500
commitf578a188e8b21be623b48bb0eb3a92174c2e5b82 (patch)
tree40526512bffd70b8eb515fdaa213ece5b91bf8f6
parent52ca353bc8597dcc1d6d7abc03eecc1b452d79c9 (diff)
ASoC: codecs: wm8904: Fix register cache incoherency
The multi-component patch(commit f0fba2ad1) moved the allocation of the register cache from the driver to the ASoC core. Most drivers where adjusted to this, but the wm8904 driver still uses its own register cache for its private functions, while functions from the ASoC core use the generic cache. Thus we end up with two from each other incoherent caches, which can lead to undefined behaviour. This patch fixes the issue by changing the wm8904 driver to use the generic register cache in its private functions. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Cc: Ian Lartey <ian@opensource.wolfsonmicro.com> Cc: Dimitris Papastamos <dp@opensource.wolfsonmicro.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Cc: stable@kernel.org (for 2.6.37 only)
-rw-r--r--sound/soc/codecs/wm8904.c37
1 files changed, 18 insertions, 19 deletions
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index 9001cc48ba13..1ec12eff0620 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -50,8 +50,6 @@ static const char *wm8904_supply_names[WM8904_NUM_SUPPLIES] = {
50/* codec private data */ 50/* codec private data */
51struct wm8904_priv { 51struct wm8904_priv {
52 52
53 u16 reg_cache[WM8904_MAX_REGISTER + 1];
54
55 enum wm8904_type devtype; 53 enum wm8904_type devtype;
56 void *control_data; 54 void *control_data;
57 55
@@ -2094,7 +2092,7 @@ static int wm8904_digital_mute(struct snd_soc_dai *codec_dai, int mute)
2094 2092
2095static void wm8904_sync_cache(struct snd_soc_codec *codec) 2093static void wm8904_sync_cache(struct snd_soc_codec *codec)
2096{ 2094{
2097 struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); 2095 u16 *reg_cache = codec->reg_cache;
2098 int i; 2096 int i;
2099 2097
2100 if (!codec->cache_sync) 2098 if (!codec->cache_sync)
@@ -2105,14 +2103,14 @@ static void wm8904_sync_cache(struct snd_soc_codec *codec)
2105 /* Sync back cached values if they're different from the 2103 /* Sync back cached values if they're different from the
2106 * hardware default. 2104 * hardware default.
2107 */ 2105 */
2108 for (i = 1; i < ARRAY_SIZE(wm8904->reg_cache); i++) { 2106 for (i = 1; i < codec->driver->reg_cache_size; i++) {
2109 if (!wm8904_access[i].writable) 2107 if (!wm8904_access[i].writable)
2110 continue; 2108 continue;
2111 2109
2112 if (wm8904->reg_cache[i] == wm8904_reg[i]) 2110 if (reg_cache[i] == wm8904_reg[i])
2113 continue; 2111 continue;
2114 2112
2115 snd_soc_write(codec, i, wm8904->reg_cache[i]); 2113 snd_soc_write(codec, i, reg_cache[i]);
2116 } 2114 }
2117 2115
2118 codec->cache_sync = 0; 2116 codec->cache_sync = 0;
@@ -2371,6 +2369,7 @@ static int wm8904_probe(struct snd_soc_codec *codec)
2371{ 2369{
2372 struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); 2370 struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
2373 struct wm8904_pdata *pdata = wm8904->pdata; 2371 struct wm8904_pdata *pdata = wm8904->pdata;
2372 u16 *reg_cache = codec->reg_cache;
2374 int ret, i; 2373 int ret, i;
2375 2374
2376 codec->cache_sync = 1; 2375 codec->cache_sync = 1;
@@ -2437,19 +2436,19 @@ static int wm8904_probe(struct snd_soc_codec *codec)
2437 } 2436 }
2438 2437
2439 /* Change some default settings - latch VU and enable ZC */ 2438 /* Change some default settings - latch VU and enable ZC */
2440 wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_LEFT] |= WM8904_ADC_VU; 2439 reg_cache[WM8904_ADC_DIGITAL_VOLUME_LEFT] |= WM8904_ADC_VU;
2441 wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_RIGHT] |= WM8904_ADC_VU; 2440 reg_cache[WM8904_ADC_DIGITAL_VOLUME_RIGHT] |= WM8904_ADC_VU;
2442 wm8904->reg_cache[WM8904_DAC_DIGITAL_VOLUME_LEFT] |= WM8904_DAC_VU; 2441 reg_cache[WM8904_DAC_DIGITAL_VOLUME_LEFT] |= WM8904_DAC_VU;
2443 wm8904->reg_cache[WM8904_DAC_DIGITAL_VOLUME_RIGHT] |= WM8904_DAC_VU; 2442 reg_cache[WM8904_DAC_DIGITAL_VOLUME_RIGHT] |= WM8904_DAC_VU;
2444 wm8904->reg_cache[WM8904_ANALOGUE_OUT1_LEFT] |= WM8904_HPOUT_VU | 2443 reg_cache[WM8904_ANALOGUE_OUT1_LEFT] |= WM8904_HPOUT_VU |
2445 WM8904_HPOUTLZC; 2444 WM8904_HPOUTLZC;
2446 wm8904->reg_cache[WM8904_ANALOGUE_OUT1_RIGHT] |= WM8904_HPOUT_VU | 2445 reg_cache[WM8904_ANALOGUE_OUT1_RIGHT] |= WM8904_HPOUT_VU |
2447 WM8904_HPOUTRZC; 2446 WM8904_HPOUTRZC;
2448 wm8904->reg_cache[WM8904_ANALOGUE_OUT2_LEFT] |= WM8904_LINEOUT_VU | 2447 reg_cache[WM8904_ANALOGUE_OUT2_LEFT] |= WM8904_LINEOUT_VU |
2449 WM8904_LINEOUTLZC; 2448 WM8904_LINEOUTLZC;
2450 wm8904->reg_cache[WM8904_ANALOGUE_OUT2_RIGHT] |= WM8904_LINEOUT_VU | 2449 reg_cache[WM8904_ANALOGUE_OUT2_RIGHT] |= WM8904_LINEOUT_VU |
2451 WM8904_LINEOUTRZC; 2450 WM8904_LINEOUTRZC;
2452 wm8904->reg_cache[WM8904_CLOCK_RATES_0] &= ~WM8904_SR_MODE; 2451 reg_cache[WM8904_CLOCK_RATES_0] &= ~WM8904_SR_MODE;
2453 2452
2454 /* Apply configuration from the platform data. */ 2453 /* Apply configuration from the platform data. */
2455 if (wm8904->pdata) { 2454 if (wm8904->pdata) {
@@ -2457,23 +2456,23 @@ static int wm8904_probe(struct snd_soc_codec *codec)
2457 if (!pdata->gpio_cfg[i]) 2456 if (!pdata->gpio_cfg[i])
2458 continue; 2457 continue;
2459 2458
2460 wm8904->reg_cache[WM8904_GPIO_CONTROL_1 + i] 2459 reg_cache[WM8904_GPIO_CONTROL_1 + i]
2461 = pdata->gpio_cfg[i] & 0xffff; 2460 = pdata->gpio_cfg[i] & 0xffff;
2462 } 2461 }
2463 2462
2464 /* Zero is the default value for these anyway */ 2463 /* Zero is the default value for these anyway */
2465 for (i = 0; i < WM8904_MIC_REGS; i++) 2464 for (i = 0; i < WM8904_MIC_REGS; i++)
2466 wm8904->reg_cache[WM8904_MIC_BIAS_CONTROL_0 + i] 2465 reg_cache[WM8904_MIC_BIAS_CONTROL_0 + i]
2467 = pdata->mic_cfg[i]; 2466 = pdata->mic_cfg[i];
2468 } 2467 }
2469 2468
2470 /* Set Class W by default - this will be managed by the Class 2469 /* Set Class W by default - this will be managed by the Class
2471 * G widget at runtime where bypass paths are available. 2470 * G widget at runtime where bypass paths are available.
2472 */ 2471 */
2473 wm8904->reg_cache[WM8904_CLASS_W_0] |= WM8904_CP_DYN_PWR; 2472 reg_cache[WM8904_CLASS_W_0] |= WM8904_CP_DYN_PWR;
2474 2473
2475 /* Use normal bias source */ 2474 /* Use normal bias source */
2476 wm8904->reg_cache[WM8904_BIAS_CONTROL_0] &= ~WM8904_POBCTRL; 2475 reg_cache[WM8904_BIAS_CONTROL_0] &= ~WM8904_POBCTRL;
2477 2476
2478 wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 2477 wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
2479 2478