aboutsummaryrefslogtreecommitdiffstats
path: root/extras/recipes-kernel/linux/linux-omap/linus/0021-ASoC-codecs-wm8904-Fix-register-cache-incoherency.patch
diff options
context:
space:
mode:
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.patch131
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
+