From d304c6ef6e9888addde075acb5bdd87e3fb48c1a Mon Sep 17 00:00:00 2001
From: Jarkko Nikula <jarkko.nikula@nokia.com>
Date: Tue, 23 Dec 2008 10:09:35 +0200
Subject: ASoC: OMAP: Select OMAP pin multiplexing when using Nokia N810 ASoC
 drivers

N810 bootloader muxes I2S pins for OMAP2420 EAC block while N810 ASoC
drivers are using McBSP block so the kernel have to change configuration
runtime.

Author has not seen problems using kernel pin multiplexing on N810 but very
many times unworking audio after forgotten to enable it and spending
15 minutes each time to figure it out again...

This change makes it easier for other users as well. If problems arise, then
they are better to find and fix in OMAP pin multiplexing framework.

Signed-off-by: Jarkko Nikula <jarkko.nikula@nokia.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
 sound/soc/omap/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index a7b1d77b2105..4f7f04014585 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -10,6 +10,7 @@ config SND_OMAP_SOC_N810
 	tristate "SoC Audio support for Nokia N810"
 	depends on SND_OMAP_SOC && MACH_NOKIA_N810
 	select SND_OMAP_SOC_MCBSP
+	select OMAP_MUX
 	select SND_SOC_TLV320AIC3X
 	help
 	  Say Y if you want to add support for SoC audio on Nokia N810.
-- 
cgit v1.2.3-58-ga151


From 7f185340da2594d65520b26f41e706a3ad0a368c Mon Sep 17 00:00:00 2001
From: Grazvydas Ignotas <notasas@gmail.com>
Date: Tue, 23 Dec 2008 12:04:48 +0200
Subject: ASoC: Mark non-connected TWL4030 pins for pandora

Pandora has all TWL4030 output pins floating, it uses
external DAC for playback. Mark those outputs as not
connected using DAPM calls.

Signed-off-by: Grazvydas Ignotas <notasas@gmail.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
 sound/soc/omap/omap3pandora.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/sound/soc/omap/omap3pandora.c b/sound/soc/omap/omap3pandora.c
index bd91594496b1..fcc2f5d9a878 100644
--- a/sound/soc/omap/omap3pandora.c
+++ b/sound/soc/omap/omap3pandora.c
@@ -180,6 +180,19 @@ static int omap3pandora_in_init(struct snd_soc_codec *codec)
 {
 	int ret;
 
+	/* All TWL4030 output pins are floating */
+	snd_soc_dapm_nc_pin(codec, "OUTL"),
+	snd_soc_dapm_nc_pin(codec, "OUTR"),
+	snd_soc_dapm_nc_pin(codec, "EARPIECE"),
+	snd_soc_dapm_nc_pin(codec, "PREDRIVEL"),
+	snd_soc_dapm_nc_pin(codec, "PREDRIVER"),
+	snd_soc_dapm_nc_pin(codec, "HSOL"),
+	snd_soc_dapm_nc_pin(codec, "HSOR"),
+	snd_soc_dapm_nc_pin(codec, "CARKITL"),
+	snd_soc_dapm_nc_pin(codec, "CARKITR"),
+	snd_soc_dapm_nc_pin(codec, "HFL"),
+	snd_soc_dapm_nc_pin(codec, "HFR"),
+
 	ret = snd_soc_dapm_new_controls(codec, omap3pandora_in_dapm_widgets,
 				ARRAY_SIZE(omap3pandora_in_dapm_widgets));
 	if (ret < 0)
-- 
cgit v1.2.3-58-ga151


From 05d5e991a7290807e7d62a7d272bb4f37c27c6ae Mon Sep 17 00:00:00 2001
From: David Brownell <dbrownell@users.sourceforge.net>
Date: Sun, 4 Jan 2009 02:50:10 -0800
Subject: ASoC: Clocking fixes for davinci-evm.c

Let's have audio playback not sound like chipmunks, 'k? :)

ASP1 on the DM355 EVM uses a 27 MHz external audio clock, not
the slower clock used with ASP0 on the DM6446 EVM.

Also, that slower ASP0 clock on the DM6446 is 12.288 MHz,
not 22.5792 MHz ... 48 KHz sample rate (x256), not a double
speed 44.1 KHz sample rate (which could be done, but isn't
what the board init code now sets up).

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
 sound/soc/davinci/davinci-evm.c | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c
index 01b948bb55a1..54851f318568 100644
--- a/sound/soc/davinci/davinci-evm.c
+++ b/sound/soc/davinci/davinci-evm.c
@@ -26,7 +26,6 @@
 #include "davinci-pcm.h"
 #include "davinci-i2s.h"
 
-#define EVM_CODEC_CLOCK 22579200
 
 #define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \
 		SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF)
@@ -37,6 +36,21 @@ static int evm_hw_params(struct snd_pcm_substream *substream,
 	struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
 	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
 	int ret = 0;
+	unsigned sysclk;
+
+	/* ASP1 on DM355 EVM is clocked by an external oscillator */
+	if (machine_is_davinci_dm355_evm())
+		sysclk = 27000000;
+
+	/* ASP0 in DM6446 EVM is clocked by U55, as configured by
+	 * board-dm644x-evm.c using GPIOs from U18.  There are six
+	 * options; here we "know" we use a 48 KHz sample rate.
+	 */
+	else if (machine_is_davinci_evm())
+		sysclk = 12288000;
+
+	else
+		return -EINVAL;
 
 	/* set codec DAI configuration */
 	ret = snd_soc_dai_set_fmt(codec_dai, AUDIO_FORMAT);
@@ -49,8 +63,7 @@ static int evm_hw_params(struct snd_pcm_substream *substream,
 		return ret;
 
 	/* set the codec system clock */
-	ret = snd_soc_dai_set_sysclk(codec_dai, 0, EVM_CODEC_CLOCK,
-					    SND_SOC_CLOCK_OUT);
+	ret = snd_soc_dai_set_sysclk(codec_dai, 0, sysclk, SND_SOC_CLOCK_OUT);
 	if (ret < 0)
 		return ret;
 
-- 
cgit v1.2.3-58-ga151


From 796123368871e4a838dc0dfd5dbc3cd8981ef429 Mon Sep 17 00:00:00 2001
From: Dmitry Baryshkov <dbaryshkov@gmail.com>
Date: Mon, 5 Jan 2009 12:58:06 +0300
Subject: pxa2xx-ac97: switch AC unit to correct state before probing

If AC97 unit is in partially enabled state, early request_irq can trigger
IRQ storm or even full hang up. Workaround this by forcibly switching ACLINK off
at the start of the probe.

Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
 sound/arm/pxa2xx-ac97-lib.c | 25 ++++++++++++++++---------
 1 file changed, 16 insertions(+), 9 deletions(-)

diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c
index ef6539eea579..35afd0c33be5 100644
--- a/sound/arm/pxa2xx-ac97-lib.c
+++ b/sound/arm/pxa2xx-ac97-lib.c
@@ -321,10 +321,6 @@ int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev)
 {
 	int ret;
 
-	ret = request_irq(IRQ_AC97, pxa2xx_ac97_irq, 0, "AC97", NULL);
-	if (ret < 0)
-		goto err;
-
 	if (cpu_is_pxa25x() || cpu_is_pxa27x()) {
 		pxa_gpio_mode(GPIO31_SYNC_AC97_MD);
 		pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD);
@@ -339,7 +335,7 @@ int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev)
 		if (IS_ERR(ac97conf_clk)) {
 			ret = PTR_ERR(ac97conf_clk);
 			ac97conf_clk = NULL;
-			goto err_irq;
+			goto err_conf;
 		}
 	}
 
@@ -347,19 +343,30 @@ int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev)
 	if (IS_ERR(ac97_clk)) {
 		ret = PTR_ERR(ac97_clk);
 		ac97_clk = NULL;
-		goto err_irq;
+		goto err_clk;
 	}
 
-	return clk_enable(ac97_clk);
+	ret = clk_enable(ac97_clk);
+	if (ret)
+		goto err_clk2;
+
+	ret = request_irq(IRQ_AC97, pxa2xx_ac97_irq, IRQF_DISABLED, "AC97", NULL);
+	if (ret < 0)
+		goto err_irq;
+
+	return 0;
 
 err_irq:
 	GCR |= GCR_ACLINK_OFF;
+err_clk2:
+	clk_put(ac97_clk);
+	ac97_clk = NULL;
+err_clk:
 	if (ac97conf_clk) {
 		clk_put(ac97conf_clk);
 		ac97conf_clk = NULL;
 	}
-	free_irq(IRQ_AC97, NULL);
-err:
+err_conf:
 	return ret;
 }
 EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_probe);
-- 
cgit v1.2.3-58-ga151


From 2e72f8e3716bc3bbf4c9b5b987fb5ab3223f60bf Mon Sep 17 00:00:00 2001
From: Peter Ujfalusi <peter.ujfalusi@nokia.com>
Date: Mon, 5 Jan 2009 09:54:57 +0200
Subject: ASoC: New enum type: value_enum

This patch introduces a new enum type.
In this enum type each enumerated items referred with a value.

This new enum type can handle enums encoded in bitfield, or any other
weird ways. twl4030 codec has several mux selection register, where the
input/output mux is coded in a bitfield. With the normal enum type this type
of mux can not be handled in a clean way.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@nokia.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
 include/sound/soc-dapm.h |  15 ++++
 include/sound/soc.h      |  30 ++++++++
 sound/soc/soc-core.c     | 107 +++++++++++++++++++++++++
 sound/soc/soc-dapm.c     | 197 ++++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 346 insertions(+), 3 deletions(-)

diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index 7ee2f70ca42e..4af1083e3287 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -85,6 +85,10 @@
 #define SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols) \
 {	.id = snd_soc_dapm_mux, .name = wname, .reg = wreg, .shift = wshift, \
 	.invert = winvert, .kcontrols = wcontrols, .num_kcontrols = 1}
+#define SND_SOC_DAPM_VALUE_MUX(wname, wreg, wshift, winvert, wcontrols) \
+{	.id = snd_soc_dapm_value_mux, .name = wname, .reg = wreg, \
+	.shift = wshift, .invert = winvert, .kcontrols = wcontrols, \
+	.num_kcontrols = 1}
 
 /* path domain with event - event handler must return 0 for success */
 #define SND_SOC_DAPM_PGA_E(wname, wreg, wshift, winvert, wcontrols, \
@@ -172,6 +176,12 @@
  	.get = snd_soc_dapm_get_enum_double, \
  	.put = snd_soc_dapm_put_enum_double, \
   	.private_value = (unsigned long)&xenum }
+#define SOC_DAPM_VALUE_ENUM(xname, xenum) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+	.info = snd_soc_info_value_enum_double, \
+	.get = snd_soc_dapm_get_value_enum_double, \
+	.put = snd_soc_dapm_put_value_enum_double, \
+	.private_value = (unsigned long)&xenum }
 
 /* dapm stream operations */
 #define SND_SOC_DAPM_STREAM_NOP			0x0
@@ -214,6 +224,10 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol);
 int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol);
+int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol);
+int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol);
 int snd_soc_dapm_new_control(struct snd_soc_codec *codec,
 	const struct snd_soc_dapm_widget *widget);
 int snd_soc_dapm_new_controls(struct snd_soc_codec *codec,
@@ -247,6 +261,7 @@ enum snd_soc_dapm_type {
 	snd_soc_dapm_input = 0,		/* input pin */
 	snd_soc_dapm_output,		/* output pin */
 	snd_soc_dapm_mux,			/* selects 1 analog signal from many inputs */
+	snd_soc_dapm_value_mux,			/* selects 1 analog signal from many inputs */
 	snd_soc_dapm_mixer,			/* mixes several analog signals together */
 	snd_soc_dapm_pga,			/* programmable gain/attenuation (volume) */
 	snd_soc_dapm_adc,			/* analog to digital converter */
diff --git a/include/sound/soc.h b/include/sound/soc.h
index f86e455d3828..9b930d342116 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -94,11 +94,22 @@
 	SOC_ENUM_DOUBLE(xreg, xshift, xshift, xmax, xtexts)
 #define SOC_ENUM_SINGLE_EXT(xmax, xtexts) \
 {	.max = xmax, .texts = xtexts }
+#define SOC_VALUE_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xmax, xtexts, xvalues) \
+{	.reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \
+	.mask = xmask, .max = xmax, .texts = xtexts, .values = xvalues}
+#define SOC_VALUE_ENUM_SINGLE(xreg, xshift, xmask, xmax, xtexts, xvalues) \
+	SOC_VALUE_ENUM_DOUBLE(xreg, xshift, xshift, xmask, xmax, xtexts, xvalues)
 #define SOC_ENUM(xname, xenum) \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,\
 	.info = snd_soc_info_enum_double, \
 	.get = snd_soc_get_enum_double, .put = snd_soc_put_enum_double, \
 	.private_value = (unsigned long)&xenum }
+#define SOC_VALUE_ENUM(xname, xenum) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,\
+	.info = snd_soc_info_value_enum_double, \
+	.get = snd_soc_get_value_enum_double, \
+	.put = snd_soc_put_value_enum_double, \
+	.private_value = (unsigned long)&xenum }
 #define SOC_SINGLE_EXT(xname, xreg, xshift, xmax, xinvert,\
 	 xhandler_get, xhandler_put) \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
@@ -200,6 +211,12 @@ int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol);
 int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol);
+int snd_soc_info_value_enum_double(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_info *uinfo);
+int snd_soc_get_value_enum_double(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol);
+int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol);
 int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_info *uinfo);
 int snd_soc_info_volsw_ext(struct snd_kcontrol *kcontrol,
@@ -406,6 +423,19 @@ struct soc_enum {
 	void *dapm;
 };
 
+/* semi enumerated kcontrol */
+struct soc_value_enum {
+	unsigned short reg;
+	unsigned short reg2;
+	unsigned char shift_l;
+	unsigned char shift_r;
+	unsigned int max;
+	unsigned int mask;
+	const char **texts;
+	const unsigned int *values;
+	void *dapm;
+};
+
 #include <sound/soc-dai.h>
 
 #endif
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index f73c1341437c..6cbe7e82f238 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -1584,6 +1584,113 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
 }
 EXPORT_SYMBOL_GPL(snd_soc_put_enum_double);
 
+/**
+ * snd_soc_info_value_enum_double - semi enumerated double mixer info callback
+ * @kcontrol: mixer control
+ * @uinfo: control element information
+ *
+ * Callback to provide information about a double semi enumerated
+ * mixer control.
+ *
+ * Semi enumerated mixer: the enumerated items are referred as values. Can be
+ * used for handling bitfield coded enumeration for example.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_info_value_enum_double(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_info *uinfo)
+{
+	struct soc_value_enum *e = (struct soc_value_enum *)
+			kcontrol->private_value;
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = e->shift_l == e->shift_r ? 1 : 2;
+	uinfo->value.enumerated.items = e->max;
+
+	if (uinfo->value.enumerated.item > e->max - 1)
+		uinfo->value.enumerated.item = e->max - 1;
+	strcpy(uinfo->value.enumerated.name,
+		e->texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_info_value_enum_double);
+
+/**
+ * snd_soc_get_value_enum_double - semi enumerated double mixer get callback
+ * @kcontrol: mixer control
+ * @ucontrol: control element information
+ *
+ * Callback to get the value of a double semi enumerated mixer.
+ *
+ * Semi enumerated mixer: the enumerated items are referred as values. Can be
+ * used for handling bitfield coded enumeration for example.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_get_value_enum_double(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct soc_value_enum *e = (struct soc_value_enum *)
+			kcontrol->private_value;
+	unsigned short reg_val, val, mux;
+
+	reg_val = snd_soc_read(codec, e->reg);
+	val = (reg_val >> e->shift_l) & e->mask;
+	for (mux = 0; mux < e->max; mux++) {
+		if (val == e->values[mux])
+			break;
+	}
+	ucontrol->value.enumerated.item[0] = mux;
+	if (e->shift_l != e->shift_r) {
+		val = (reg_val >> e->shift_r) & e->mask;
+		for (mux = 0; mux < e->max; mux++) {
+			if (val == e->values[mux])
+				break;
+		}
+		ucontrol->value.enumerated.item[1] = mux;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_get_value_enum_double);
+
+/**
+ * snd_soc_put_value_enum_double - semi enumerated double mixer put callback
+ * @kcontrol: mixer control
+ * @ucontrol: control element information
+ *
+ * Callback to set the value of a double semi enumerated mixer.
+ *
+ * Semi enumerated mixer: the enumerated items are referred as values. Can be
+ * used for handling bitfield coded enumeration for example.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct soc_value_enum *e = (struct soc_value_enum *)
+			kcontrol->private_value;
+	unsigned short val;
+	unsigned short mask;
+
+	if (ucontrol->value.enumerated.item[0] > e->max - 1)
+		return -EINVAL;
+	val = e->values[ucontrol->value.enumerated.item[0]] << e->shift_l;
+	mask = e->mask << e->shift_l;
+	if (e->shift_l != e->shift_r) {
+		if (ucontrol->value.enumerated.item[1] > e->max - 1)
+			return -EINVAL;
+		val |= e->values[ucontrol->value.enumerated.item[1]] << e->shift_r;
+		mask |= e->mask << e->shift_r;
+	}
+
+	return snd_soc_update_bits(codec, e->reg, mask, val);
+}
+EXPORT_SYMBOL_GPL(snd_soc_put_value_enum_double);
+
 /**
  * snd_soc_info_enum_ext - external enumerated single mixer info callback
  * @kcontrol: mixer control
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 6c79ca6df0bf..ad0d801677c1 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -53,13 +53,15 @@
 /* dapm power sequences - make this per codec in the future */
 static int dapm_up_seq[] = {
 	snd_soc_dapm_pre, snd_soc_dapm_micbias, snd_soc_dapm_mic,
-	snd_soc_dapm_mux, snd_soc_dapm_dac, snd_soc_dapm_mixer, snd_soc_dapm_pga,
-	snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, snd_soc_dapm_post
+	snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_dac,
+	snd_soc_dapm_mixer, snd_soc_dapm_pga, snd_soc_dapm_adc, snd_soc_dapm_hp,
+	snd_soc_dapm_spk, snd_soc_dapm_post
 };
 static int dapm_down_seq[] = {
 	snd_soc_dapm_pre, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk,
 	snd_soc_dapm_pga, snd_soc_dapm_mixer, snd_soc_dapm_dac, snd_soc_dapm_mic,
-	snd_soc_dapm_micbias, snd_soc_dapm_mux, snd_soc_dapm_post
+	snd_soc_dapm_micbias, snd_soc_dapm_mux, snd_soc_dapm_value_mux,
+	snd_soc_dapm_post
 };
 
 static int dapm_status = 1;
@@ -134,6 +136,25 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
 		}
 	}
 	break;
+	case snd_soc_dapm_value_mux: {
+		struct soc_value_enum *e = (struct soc_value_enum *)
+			w->kcontrols[i].private_value;
+		int val, item;
+
+		val = snd_soc_read(w->codec, e->reg);
+		val = (val >> e->shift_l) & e->mask;
+		for (item = 0; item < e->max; item++) {
+			if (val == e->values[item])
+				break;
+		}
+
+		p->connect = 0;
+		for (i = 0; i < e->max; i++) {
+			if (!(strcmp(p->name, e->texts[i])) && item == i)
+				p->connect = 1;
+		}
+	}
+	break;
 	/* does not effect routing - always connected */
 	case snd_soc_dapm_pga:
 	case snd_soc_dapm_output:
@@ -179,6 +200,30 @@ static int dapm_connect_mux(struct snd_soc_codec *codec,
 	return -ENODEV;
 }
 
+/* connect value_mux widget to it's interconnecting audio paths */
+static int dapm_connect_value_mux(struct snd_soc_codec *codec,
+	struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest,
+	struct snd_soc_dapm_path *path, const char *control_name,
+	const struct snd_kcontrol_new *kcontrol)
+{
+	struct soc_value_enum *e = (struct soc_value_enum *)
+			kcontrol->private_value;
+	int i;
+
+	for (i = 0; i < e->max; i++) {
+		if (!(strcmp(control_name, e->texts[i]))) {
+			list_add(&path->list, &codec->dapm_paths);
+			list_add(&path->list_sink, &dest->sources);
+			list_add(&path->list_source, &src->sinks);
+			path->name = (char *)e->texts[i];
+			dapm_set_path_status(dest, path, 0);
+			return 0;
+		}
+	}
+
+	return -ENODEV;
+}
+
 /* connect mixer widget to it's interconnecting audio paths */
 static int dapm_connect_mixer(struct snd_soc_codec *codec,
 	struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest,
@@ -653,6 +698,7 @@ static void dbg_dump_dapm(struct snd_soc_codec* codec, const char *action)
 		case snd_soc_dapm_vmid:
 			continue;
 		case snd_soc_dapm_mux:
+		case snd_soc_dapm_value_mux:
 		case snd_soc_dapm_output:
 		case snd_soc_dapm_input:
 		case snd_soc_dapm_switch:
@@ -728,6 +774,45 @@ static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
 	return 0;
 }
 
+/* test and update the power status of a value_mux widget */
+static int dapm_value_mux_update_power(struct snd_soc_dapm_widget *widget,
+				 struct snd_kcontrol *kcontrol, int mask,
+				 int mux, int val, struct soc_value_enum *e)
+{
+	struct snd_soc_dapm_path *path;
+	int found = 0;
+
+	if (widget->id != snd_soc_dapm_value_mux)
+		return -ENODEV;
+
+	if (!snd_soc_test_bits(widget->codec, e->reg, mask, val))
+		return 0;
+
+	/* find dapm widget path assoc with kcontrol */
+	list_for_each_entry(path, &widget->codec->dapm_paths, list) {
+		if (path->kcontrol != kcontrol)
+			continue;
+
+		if (!path->name || !e->texts[mux])
+			continue;
+
+		found = 1;
+		/* we now need to match the string in the enum to the path */
+		if (!(strcmp(path->name, e->texts[mux])))
+			path->connect = 1; /* new connection */
+		else
+			path->connect = 0; /* old connection must be
+					      powered down */
+	}
+
+	if (found) {
+		dapm_power_widgets(widget->codec, SND_SOC_DAPM_STREAM_NOP);
+		dump_dapm(widget->codec, "mux power update");
+	}
+
+	return 0;
+}
+
 /* test and update the power status of a mixer or switch widget */
 static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
 				   struct snd_kcontrol *kcontrol, int reg,
@@ -965,6 +1050,12 @@ static int snd_soc_dapm_add_route(struct snd_soc_codec *codec,
 		if (ret != 0)
 			goto err;
 		break;
+	case snd_soc_dapm_value_mux:
+		ret = dapm_connect_value_mux(codec, wsource, wsink, path,
+			control, &wsink->kcontrols[0]);
+		if (ret != 0)
+			goto err;
+		break;
 	case snd_soc_dapm_switch:
 	case snd_soc_dapm_mixer:
 		ret = dapm_connect_mixer(codec, wsource, wsink, path, control);
@@ -1047,6 +1138,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec)
 			dapm_new_mixer(codec, w);
 			break;
 		case snd_soc_dapm_mux:
+		case snd_soc_dapm_value_mux:
 			dapm_new_mux(codec, w);
 			break;
 		case snd_soc_dapm_adc:
@@ -1273,6 +1365,105 @@ out:
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double);
 
+/**
+ * snd_soc_dapm_get_value_enum_double - dapm semi enumerated double mixer get
+ *					callback
+ * @kcontrol: mixer control
+ * @ucontrol: control element information
+ *
+ * Callback to get the value of a dapm semi enumerated double mixer control.
+ *
+ * Semi enumerated mixer: the enumerated items are referred as values. Can be
+ * used for handling bitfield coded enumeration for example.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
+	struct soc_value_enum *e = (struct soc_value_enum *)
+			kcontrol->private_value;
+	unsigned short reg_val, val, mux;
+
+	reg_val = snd_soc_read(widget->codec, e->reg);
+	val = (reg_val >> e->shift_l) & e->mask;
+	for (mux = 0; mux < e->max; mux++) {
+		if (val == e->values[mux])
+			break;
+	}
+	ucontrol->value.enumerated.item[0] = mux;
+	if (e->shift_l != e->shift_r) {
+		val = (reg_val >> e->shift_r) & e->mask;
+		for (mux = 0; mux < e->max; mux++) {
+			if (val == e->values[mux])
+				break;
+		}
+		ucontrol->value.enumerated.item[1] = mux;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_get_value_enum_double);
+
+/**
+ * snd_soc_dapm_put_value_enum_double - dapm semi enumerated double mixer set
+ *					callback
+ * @kcontrol: mixer control
+ * @ucontrol: control element information
+ *
+ * Callback to set the value of a dapm semi enumerated double mixer control.
+ *
+ * Semi enumerated mixer: the enumerated items are referred as values. Can be
+ * used for handling bitfield coded enumeration for example.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
+	struct soc_value_enum *e = (struct soc_value_enum *)
+			kcontrol->private_value;
+	unsigned short val, mux;
+	unsigned short mask;
+	int ret = 0;
+
+	if (ucontrol->value.enumerated.item[0] > e->max - 1)
+		return -EINVAL;
+	mux = ucontrol->value.enumerated.item[0];
+	val = e->values[ucontrol->value.enumerated.item[0]] << e->shift_l;
+	mask = e->mask << e->shift_l;
+	if (e->shift_l != e->shift_r) {
+		if (ucontrol->value.enumerated.item[1] > e->max - 1)
+			return -EINVAL;
+		val |= e->values[ucontrol->value.enumerated.item[1]] << e->shift_r;
+		mask |= e->mask << e->shift_r;
+	}
+
+	mutex_lock(&widget->codec->mutex);
+	widget->value = val;
+	dapm_value_mux_update_power(widget, kcontrol, mask, mux, val, e);
+	if (widget->event) {
+		if (widget->event_flags & SND_SOC_DAPM_PRE_REG) {
+			ret = widget->event(widget,
+				kcontrol, SND_SOC_DAPM_PRE_REG);
+			if (ret < 0)
+				goto out;
+		}
+		ret = snd_soc_update_bits(widget->codec, e->reg, mask, val);
+		if (widget->event_flags & SND_SOC_DAPM_POST_REG)
+			ret = widget->event(widget,
+				kcontrol, SND_SOC_DAPM_POST_REG);
+	} else
+		ret = snd_soc_update_bits(widget->codec, e->reg, mask, val);
+
+out:
+	mutex_unlock(&widget->codec->mutex);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double);
+
 /**
  * snd_soc_dapm_new_control - create new dapm control
  * @codec: audio codec
-- 
cgit v1.2.3-58-ga151


From 2f42357722f7ddc1ec0236fa55ad49ea8a7ce4b0 Mon Sep 17 00:00:00 2001
From: Peter Ujfalusi <peter.ujfalusi@nokia.com>
Date: Mon, 5 Jan 2009 09:54:58 +0200
Subject: ASoC: TWL4030: Convert the bitfield enums to VALUE_ENUM type

Convert the bitfield coded enums to the new VALUE_ENUM type.
Remove the enum check, since the VALUE_ENUM type can handle
the bitfield coding and also handles the 'holes' in the bitfield.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@nokia.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
 sound/soc/codecs/twl4030.c | 118 +++++++++++++++++++++------------------------
 1 file changed, 55 insertions(+), 63 deletions(-)

diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index 31e44e346dc8..fd0f338374a7 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -192,39 +192,51 @@ static void twl4030_init_chip(struct snd_soc_codec *codec)
 
 /* Earpiece */
 static const char *twl4030_earpiece_texts[] =
-		{"Off", "DACL1", "DACL2", "Invalid", "DACR1"};
+		{"Off", "DACL1", "DACL2", "DACR1"};
 
-static const struct soc_enum twl4030_earpiece_enum =
-	SOC_ENUM_SINGLE(TWL4030_REG_EAR_CTL, 1,
+static const unsigned int twl4030_earpiece_values[] =
+		{0x0, 0x1, 0x2, 0x4};
+
+static const struct soc_value_enum twl4030_earpiece_enum =
+	SOC_VALUE_ENUM_SINGLE(TWL4030_REG_EAR_CTL, 1, 0x7,
 			ARRAY_SIZE(twl4030_earpiece_texts),
-			twl4030_earpiece_texts);
+			twl4030_earpiece_texts,
+			twl4030_earpiece_values);
 
 static const struct snd_kcontrol_new twl4030_dapm_earpiece_control =
-SOC_DAPM_ENUM("Route", twl4030_earpiece_enum);
+SOC_DAPM_VALUE_ENUM("Route", twl4030_earpiece_enum);
 
 /* PreDrive Left */
 static const char *twl4030_predrivel_texts[] =
-		{"Off", "DACL1", "DACL2", "Invalid", "DACR2"};
+		{"Off", "DACL1", "DACL2", "DACR2"};
+
+static const unsigned int twl4030_predrivel_values[] =
+		{0x0, 0x1, 0x2, 0x4};
 
-static const struct soc_enum twl4030_predrivel_enum =
-	SOC_ENUM_SINGLE(TWL4030_REG_PREDL_CTL, 1,
+static const struct soc_value_enum twl4030_predrivel_enum =
+	SOC_VALUE_ENUM_SINGLE(TWL4030_REG_PREDL_CTL, 1, 0x7,
 			ARRAY_SIZE(twl4030_predrivel_texts),
-			twl4030_predrivel_texts);
+			twl4030_predrivel_texts,
+			twl4030_predrivel_values);
 
 static const struct snd_kcontrol_new twl4030_dapm_predrivel_control =
-SOC_DAPM_ENUM("Route", twl4030_predrivel_enum);
+SOC_DAPM_VALUE_ENUM("Route", twl4030_predrivel_enum);
 
 /* PreDrive Right */
 static const char *twl4030_predriver_texts[] =
-		{"Off", "DACR1", "DACR2", "Invalid", "DACL2"};
+		{"Off", "DACR1", "DACR2", "DACL2"};
 
-static const struct soc_enum twl4030_predriver_enum =
-	SOC_ENUM_SINGLE(TWL4030_REG_PREDR_CTL, 1,
+static const unsigned int twl4030_predriver_values[] =
+		{0x0, 0x1, 0x2, 0x4};
+
+static const struct soc_value_enum twl4030_predriver_enum =
+	SOC_VALUE_ENUM_SINGLE(TWL4030_REG_PREDR_CTL, 1, 0x7,
 			ARRAY_SIZE(twl4030_predriver_texts),
-			twl4030_predriver_texts);
+			twl4030_predriver_texts,
+			twl4030_predriver_values);
 
 static const struct snd_kcontrol_new twl4030_dapm_predriver_control =
-SOC_DAPM_ENUM("Route", twl4030_predriver_enum);
+SOC_DAPM_VALUE_ENUM("Route", twl4030_predriver_enum);
 
 /* Headset Left */
 static const char *twl4030_hsol_texts[] =
@@ -300,28 +312,35 @@ SOC_DAPM_ENUM("Route", twl4030_handsfreer_enum);
 
 /* Left analog microphone selection */
 static const char *twl4030_analoglmic_texts[] =
-		{"Off", "Main mic", "Headset mic", "Invalid", "AUXL",
-		 "Invalid", "Invalid", "Invalid", "Carkit mic"};
+		{"Off", "Main mic", "Headset mic", "AUXL", "Carkit mic"};
+
+static const unsigned int twl4030_analoglmic_values[] =
+		{0x0, 0x1, 0x2, 0x4, 0x8};
 
-static const struct soc_enum twl4030_analoglmic_enum =
-	SOC_ENUM_SINGLE(TWL4030_REG_ANAMICL, 0,
+static const struct soc_value_enum twl4030_analoglmic_enum =
+	SOC_VALUE_ENUM_SINGLE(TWL4030_REG_ANAMICL, 0, 0xf,
 			ARRAY_SIZE(twl4030_analoglmic_texts),
-			twl4030_analoglmic_texts);
+			twl4030_analoglmic_texts,
+			twl4030_analoglmic_values);
 
 static const struct snd_kcontrol_new twl4030_dapm_analoglmic_control =
-SOC_DAPM_ENUM("Route", twl4030_analoglmic_enum);
+SOC_DAPM_VALUE_ENUM("Route", twl4030_analoglmic_enum);
 
 /* Right analog microphone selection */
 static const char *twl4030_analogrmic_texts[] =
-		{"Off", "Sub mic", "Invalid", "Invalid", "AUXR"};
+		{"Off", "Sub mic", "AUXR"};
 
-static const struct soc_enum twl4030_analogrmic_enum =
-	SOC_ENUM_SINGLE(TWL4030_REG_ANAMICR, 0,
+static const unsigned int twl4030_analogrmic_values[] =
+		{0x0, 0x1, 0x4};
+
+static const struct soc_value_enum twl4030_analogrmic_enum =
+	SOC_VALUE_ENUM_SINGLE(TWL4030_REG_ANAMICR, 0, 0x5,
 			ARRAY_SIZE(twl4030_analogrmic_texts),
-			twl4030_analogrmic_texts);
+			twl4030_analogrmic_texts,
+			twl4030_analogrmic_values);
 
 static const struct snd_kcontrol_new twl4030_dapm_analogrmic_control =
-SOC_DAPM_ENUM("Route", twl4030_analogrmic_enum);
+SOC_DAPM_VALUE_ENUM("Route", twl4030_analogrmic_enum);
 
 /* TX1 L/R Analog/Digital microphone selection */
 static const char *twl4030_micpathtx1_texts[] =
@@ -347,28 +366,6 @@ static const struct soc_enum twl4030_micpathtx2_enum =
 static const struct snd_kcontrol_new twl4030_dapm_micpathtx2_control =
 SOC_DAPM_ENUM("Route", twl4030_micpathtx2_enum);
 
-/*
- * This function filters out the non valid mux settings, named as "Invalid"
- * in the enum texts.
- * Just refuse to set an invalid mux mode.
- */
-static int twl4030_enum_event(struct snd_soc_dapm_widget *w,
-	struct snd_kcontrol *kcontrol, int event)
-{
-	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
-	int ret = 0;
-	int val;
-
-	val = w->value >> e->shift_l;
-	if (!strcmp("Invalid", e->texts[val])) {
-		printk(KERN_WARNING "Invalid MUX setting on 0x%02x (%d)\n",
-			e->reg, val);
-		ret = -1;
-	}
-
-	return ret;
-}
-
 static int micpath_event(struct snd_soc_dapm_widget *w,
 	struct snd_kcontrol *kcontrol, int event)
 {
@@ -737,16 +734,13 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
 
 	/* Output MUX controls */
 	/* Earpiece */
-	SND_SOC_DAPM_MUX_E("Earpiece Mux", SND_SOC_NOPM, 0, 0,
-		&twl4030_dapm_earpiece_control, twl4030_enum_event,
-		SND_SOC_DAPM_PRE_REG),
+	SND_SOC_DAPM_VALUE_MUX("Earpiece Mux", SND_SOC_NOPM, 0, 0,
+		&twl4030_dapm_earpiece_control),
 	/* PreDrivL/R */
-	SND_SOC_DAPM_MUX_E("PredriveL Mux", SND_SOC_NOPM, 0, 0,
-		&twl4030_dapm_predrivel_control, twl4030_enum_event,
-		SND_SOC_DAPM_PRE_REG),
-	SND_SOC_DAPM_MUX_E("PredriveR Mux", SND_SOC_NOPM, 0, 0,
-		&twl4030_dapm_predriver_control, twl4030_enum_event,
-		SND_SOC_DAPM_PRE_REG),
+	SND_SOC_DAPM_VALUE_MUX("PredriveL Mux", SND_SOC_NOPM, 0, 0,
+		&twl4030_dapm_predrivel_control),
+	SND_SOC_DAPM_VALUE_MUX("PredriveR Mux", SND_SOC_NOPM, 0, 0,
+		&twl4030_dapm_predriver_control),
 	/* HeadsetL/R */
 	SND_SOC_DAPM_MUX("HeadsetL Mux", SND_SOC_NOPM, 0, 0,
 		&twl4030_dapm_hsol_control),
@@ -789,12 +783,10 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
 		SND_SOC_DAPM_POST_REG),
 
 	/* Analog input muxes with power switch for the physical ADCL/R */
-	SND_SOC_DAPM_MUX_E("Analog Left Capture Route",
-		TWL4030_REG_AVADC_CTL, 3, 0, &twl4030_dapm_analoglmic_control,
-		twl4030_enum_event, SND_SOC_DAPM_PRE_REG),
-	SND_SOC_DAPM_MUX_E("Analog Right Capture Route",
-		TWL4030_REG_AVADC_CTL, 1, 0, &twl4030_dapm_analogrmic_control,
-		twl4030_enum_event, SND_SOC_DAPM_PRE_REG),
+	SND_SOC_DAPM_VALUE_MUX("Analog Left Capture Route",
+		TWL4030_REG_AVADC_CTL, 3, 0, &twl4030_dapm_analoglmic_control),
+	SND_SOC_DAPM_VALUE_MUX("Analog Right Capture Route",
+		TWL4030_REG_AVADC_CTL, 1, 0, &twl4030_dapm_analogrmic_control),
 
 	SND_SOC_DAPM_PGA("Analog Left Amplifier",
 		TWL4030_REG_ANAMICL, 4, 0, NULL, 0),
-- 
cgit v1.2.3-58-ga151


From 8c0bad7fa5be47aa8a3d03ff6ee1917fa68b72e3 Mon Sep 17 00:00:00 2001
From: Mark Brown <broonie@opensource.wolfsonmicro.com>
Date: Tue, 6 Jan 2009 09:52:18 +0000
Subject: ASoC: Use snd_soc_dapm_nc_pin() in at91sam9g20ek

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
 sound/soc/atmel/sam9g20_wm8731.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c
index 1fb59a9d3719..6ea04be911d0 100644
--- a/sound/soc/atmel/sam9g20_wm8731.c
+++ b/sound/soc/atmel/sam9g20_wm8731.c
@@ -221,8 +221,8 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_codec *codec)
 	snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
 
 	/* not connected */
-	snd_soc_dapm_disable_pin(codec, "RLINEIN");
-	snd_soc_dapm_disable_pin(codec, "LLINEIN");
+	snd_soc_dapm_nc_pin(codec, "RLINEIN");
+	snd_soc_dapm_nc_pin(codec, "LLINEIN");
 
 	/* always connected */
 	snd_soc_dapm_enable_pin(codec, "Int Mic");
-- 
cgit v1.2.3-58-ga151


From 227b4dc6432d271eecd0ff0aefe6f0897ec47397 Mon Sep 17 00:00:00 2001
From: Mark Brown <broonie@opensource.wolfsonmicro.com>
Date: Sat, 3 Jan 2009 11:24:41 +0100
Subject: ASoC: Fix SND_SOC_ALL_CODECS handling of dual SPI and I2C control
 buses

For codecs that have both SPI and I2C support we need to ensure that we
don't try to make the codec driver built in when I2C is modular since
that won't link.  Do this by creating a helper variable which uses
conditional defaults to pick up the correct value for all combinations.

We don't need to do anything special for I2C-only codecs since a
conditional select passes on the full value for a tristate.

Reported-by: Ingo Molnar <mingo@elte.hu>
Tested-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
 sound/soc/codecs/Kconfig | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index c41289b5f586..d0e0d691ae51 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -1,3 +1,13 @@
+# Helper to resolve issues with configs that have SPI enabled but I2C
+# modular, meaning we can't build the codec driver in with I2C support.
+# We use an ordered list of conditional defaults to pick the appropriate
+# setting - SPI can't be modular so that case doesn't need to be covered.
+config SND_SOC_I2C_AND_SPI
+	tristate
+	default m if I2C=m
+	default y if I2C=y
+	default y if SPI_MASTER=y
+
 config SND_SOC_ALL_CODECS
 	tristate "Build all ASoC CODEC drivers"
 	select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS
@@ -14,12 +24,12 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_UDA134X
 	select SND_SOC_UDA1380 if I2C
 	select SND_SOC_WM8350 if MFD_WM8350
-	select SND_SOC_WM8510 if (I2C || SPI_MASTER)
+	select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI
 	select SND_SOC_WM8580 if I2C
-	select SND_SOC_WM8728 if (I2C || SPI_MASTER)
-	select SND_SOC_WM8731 if (I2C || SPI_MASTER)
-	select SND_SOC_WM8750 if (I2C || SPI_MASTER)
-	select SND_SOC_WM8753 if (I2C || SPI_MASTER)
+	select SND_SOC_WM8728 if SND_SOC_I2C_AND_SPI
+	select SND_SOC_WM8731 if SND_SOC_I2C_AND_SPI
+	select SND_SOC_WM8750 if SND_SOC_I2C_AND_SPI
+	select SND_SOC_WM8753 if SND_SOC_I2C_AND_SPI
 	select SND_SOC_WM8900 if I2C
 	select SND_SOC_WM8903 if I2C
 	select SND_SOC_WM8971 if I2C
-- 
cgit v1.2.3-58-ga151