diff options
Diffstat (limited to 'extras/recipes-kernel/linux/linux-omap/linus/0021-ASoC-codecs-wm8904-Fix-register-cache-incoherency.patch')
-rw-r--r-- | extras/recipes-kernel/linux/linux-omap/linus/0021-ASoC-codecs-wm8904-Fix-register-cache-incoherency.patch | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/extras/recipes-kernel/linux/linux-omap/linus/0021-ASoC-codecs-wm8904-Fix-register-cache-incoherency.patch b/extras/recipes-kernel/linux/linux-omap/linus/0021-ASoC-codecs-wm8904-Fix-register-cache-incoherency.patch new file mode 100644 index 00000000..51363a40 --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap/linus/0021-ASoC-codecs-wm8904-Fix-register-cache-incoherency.patch @@ -0,0 +1,131 @@ +From 2f369c65cdd41f8eda535cd4065edd63346a016b Mon Sep 17 00:00:00 2001 +From: Lars-Peter Clausen <lars@metafoo.de> +Date: Tue, 28 Dec 2010 21:37:59 +0100 +Subject: [PATCH 21/65] 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) +--- + sound/soc/codecs/wm8904.c | 37 ++++++++++++++++++------------------- + 1 files changed, 18 insertions(+), 19 deletions(-) + +diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c +index 9001cc4..1ec12ef 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] = { + /* codec private data */ + struct wm8904_priv { + +- u16 reg_cache[WM8904_MAX_REGISTER + 1]; +- + enum wm8904_type devtype; + void *control_data; + +@@ -2094,7 +2092,7 @@ static int wm8904_digital_mute(struct snd_soc_dai *codec_dai, int mute) + + static void wm8904_sync_cache(struct snd_soc_codec *codec) + { +- struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); ++ u16 *reg_cache = codec->reg_cache; + int i; + + if (!codec->cache_sync) +@@ -2105,14 +2103,14 @@ static void wm8904_sync_cache(struct snd_soc_codec *codec) + /* Sync back cached values if they're different from the + * hardware default. + */ +- for (i = 1; i < ARRAY_SIZE(wm8904->reg_cache); i++) { ++ for (i = 1; i < codec->driver->reg_cache_size; i++) { + if (!wm8904_access[i].writable) + continue; + +- if (wm8904->reg_cache[i] == wm8904_reg[i]) ++ if (reg_cache[i] == wm8904_reg[i]) + continue; + +- snd_soc_write(codec, i, wm8904->reg_cache[i]); ++ snd_soc_write(codec, i, reg_cache[i]); + } + + codec->cache_sync = 0; +@@ -2371,6 +2369,7 @@ static int wm8904_probe(struct snd_soc_codec *codec) + { + struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); + struct wm8904_pdata *pdata = wm8904->pdata; ++ u16 *reg_cache = codec->reg_cache; + int ret, i; + + codec->cache_sync = 1; +@@ -2437,19 +2436,19 @@ static int wm8904_probe(struct snd_soc_codec *codec) + } + + /* Change some default settings - latch VU and enable ZC */ +- wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_LEFT] |= WM8904_ADC_VU; +- wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_RIGHT] |= WM8904_ADC_VU; +- wm8904->reg_cache[WM8904_DAC_DIGITAL_VOLUME_LEFT] |= WM8904_DAC_VU; +- wm8904->reg_cache[WM8904_DAC_DIGITAL_VOLUME_RIGHT] |= WM8904_DAC_VU; +- wm8904->reg_cache[WM8904_ANALOGUE_OUT1_LEFT] |= WM8904_HPOUT_VU | ++ reg_cache[WM8904_ADC_DIGITAL_VOLUME_LEFT] |= WM8904_ADC_VU; ++ reg_cache[WM8904_ADC_DIGITAL_VOLUME_RIGHT] |= WM8904_ADC_VU; ++ reg_cache[WM8904_DAC_DIGITAL_VOLUME_LEFT] |= WM8904_DAC_VU; ++ reg_cache[WM8904_DAC_DIGITAL_VOLUME_RIGHT] |= WM8904_DAC_VU; ++ reg_cache[WM8904_ANALOGUE_OUT1_LEFT] |= WM8904_HPOUT_VU | + WM8904_HPOUTLZC; +- wm8904->reg_cache[WM8904_ANALOGUE_OUT1_RIGHT] |= WM8904_HPOUT_VU | ++ reg_cache[WM8904_ANALOGUE_OUT1_RIGHT] |= WM8904_HPOUT_VU | + WM8904_HPOUTRZC; +- wm8904->reg_cache[WM8904_ANALOGUE_OUT2_LEFT] |= WM8904_LINEOUT_VU | ++ reg_cache[WM8904_ANALOGUE_OUT2_LEFT] |= WM8904_LINEOUT_VU | + WM8904_LINEOUTLZC; +- wm8904->reg_cache[WM8904_ANALOGUE_OUT2_RIGHT] |= WM8904_LINEOUT_VU | ++ reg_cache[WM8904_ANALOGUE_OUT2_RIGHT] |= WM8904_LINEOUT_VU | + WM8904_LINEOUTRZC; +- wm8904->reg_cache[WM8904_CLOCK_RATES_0] &= ~WM8904_SR_MODE; ++ reg_cache[WM8904_CLOCK_RATES_0] &= ~WM8904_SR_MODE; + + /* Apply configuration from the platform data. */ + if (wm8904->pdata) { +@@ -2457,23 +2456,23 @@ static int wm8904_probe(struct snd_soc_codec *codec) + if (!pdata->gpio_cfg[i]) + continue; + +- wm8904->reg_cache[WM8904_GPIO_CONTROL_1 + i] ++ reg_cache[WM8904_GPIO_CONTROL_1 + i] + = pdata->gpio_cfg[i] & 0xffff; + } + + /* Zero is the default value for these anyway */ + for (i = 0; i < WM8904_MIC_REGS; i++) +- wm8904->reg_cache[WM8904_MIC_BIAS_CONTROL_0 + i] ++ reg_cache[WM8904_MIC_BIAS_CONTROL_0 + i] + = pdata->mic_cfg[i]; + } + + /* Set Class W by default - this will be managed by the Class + * G widget at runtime where bypass paths are available. + */ +- wm8904->reg_cache[WM8904_CLASS_W_0] |= WM8904_CP_DYN_PWR; ++ reg_cache[WM8904_CLASS_W_0] |= WM8904_CP_DYN_PWR; + + /* Use normal bias source */ +- wm8904->reg_cache[WM8904_BIAS_CONTROL_0] &= ~WM8904_POBCTRL; ++ reg_cache[WM8904_BIAS_CONTROL_0] &= ~WM8904_POBCTRL; + + wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY); + +-- +1.6.6.1 + |