From c21098ea5608c98b5ada1b7ec82522c7c53869eb Mon Sep 17 00:00:00 2001
From: Andrew Victor <linux@maxim.org.za>
Date: Tue, 8 Apr 2008 21:33:07 +0100
Subject: [ARM] 4912/2: [AT91] Endrelia audio driver must use GPIO interface

The SoC audio driver for the Endrelia ETI_B1 board should not access
the PIO controller directly, but must rather use the AT91 GPIO
interface.

(This is updated version of patch with removed trailing whitespace)

Signed-off-by: Andrew Victor <linux@maxim.org.za>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 sound/soc/at91/eti_b1_wm8731.c | 30 +++++++-----------------------
 1 file changed, 7 insertions(+), 23 deletions(-)

(limited to 'sound')

diff --git a/sound/soc/at91/eti_b1_wm8731.c b/sound/soc/at91/eti_b1_wm8731.c
index ad3ad9d662f..1347dcf3f80 100644
--- a/sound/soc/at91/eti_b1_wm8731.c
+++ b/sound/soc/at91/eti_b1_wm8731.c
@@ -33,8 +33,7 @@
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
 
-#include <asm/arch/hardware.h>
-#include <asm/arch/at91_pio.h>
+#include <asm/hardware.h>
 #include <asm/arch/gpio.h>
 
 #include "../codecs/wm8731.h"
@@ -47,13 +46,6 @@
 #define	DBG(x...)
 #endif
 
-#define AT91_PIO_TF1	(1 << (AT91_PIN_PB6 - PIN_BASE) % 32)
-#define AT91_PIO_TK1	(1 << (AT91_PIN_PB7 - PIN_BASE) % 32)
-#define AT91_PIO_TD1	(1 << (AT91_PIN_PB8 - PIN_BASE) % 32)
-#define AT91_PIO_RD1	(1 << (AT91_PIN_PB9 - PIN_BASE) % 32)
-#define AT91_PIO_RK1	(1 << (AT91_PIN_PB10 - PIN_BASE) % 32)
-#define AT91_PIO_RF1	(1 << (AT91_PIN_PB11 - PIN_BASE) % 32)
-
 static struct clk *pck1_clk;
 static struct clk *pllb_clk;
 
@@ -276,7 +268,6 @@ static struct platform_device *eti_b1_snd_device;
 static int __init eti_b1_init(void)
 {
 	int ret;
-	u32 ssc_pio_lines;
 	struct at91_ssc_periph *ssc = eti_b1_dai.cpu_dai->private_data;
 
 	if (!request_mem_region(AT91RM9200_BASE_SSC1, SZ_16K, "soc-audio")) {
@@ -310,19 +301,12 @@ static int __init eti_b1_init(void)
 		goto fail_io_unmap;
 	}
 
- 	ssc_pio_lines = AT91_PIO_TF1 | AT91_PIO_TK1 | AT91_PIO_TD1
-			| AT91_PIO_RD1 /* | AT91_PIO_RK1 */ | AT91_PIO_RF1;
-
-	/* Reset all PIO registers and assign lines to peripheral A */
- 	at91_sys_write(AT91_PIOB + PIO_PDR,  ssc_pio_lines);
- 	at91_sys_write(AT91_PIOB + PIO_ODR,  ssc_pio_lines);
- 	at91_sys_write(AT91_PIOB + PIO_IFDR, ssc_pio_lines);
- 	at91_sys_write(AT91_PIOB + PIO_CODR, ssc_pio_lines);
- 	at91_sys_write(AT91_PIOB + PIO_IDR,  ssc_pio_lines);
- 	at91_sys_write(AT91_PIOB + PIO_MDDR, ssc_pio_lines);
- 	at91_sys_write(AT91_PIOB + PIO_PUDR, ssc_pio_lines);
- 	at91_sys_write(AT91_PIOB + PIO_ASR,  ssc_pio_lines);
- 	at91_sys_write(AT91_PIOB + PIO_OWDR, ssc_pio_lines);
+	at91_set_A_periph(AT91_PIN_PB6, 0);	/* TF1 */
+	at91_set_A_periph(AT91_PIN_PB7, 0);	/* TK1 */
+	at91_set_A_periph(AT91_PIN_PB8, 0);	/* TD1 */
+	at91_set_A_periph(AT91_PIN_PB9, 0);	/* RD1 */
+/*	at91_set_A_periph(AT91_PIN_PB10, 0);*/	/* RK1 */
+	at91_set_A_periph(AT91_PIN_PB11, 0);	/* RF1 */
 
 	/*
 	 * Set PCK1 parent to PLLB and its rate to 12 Mhz.
-- 
cgit v1.2.3-70-g09d2


From 93873fbfd86c08ac3e4f1b37e667cf858a8b2fab Mon Sep 17 00:00:00 2001
From: Mark Brown <broonie@sirena.org.uk>
Date: Tue, 4 Mar 2008 11:14:25 +0100
Subject: [ARM] 4833/3: Convert non-SoC PXA2xx AC97 driver to clock API

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Acked-by: Takashi Iwai <tiwai@suse.de>
Acked-by: eric miao <eric.miao@marvell.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 sound/arm/pxa2xx-ac97.c | 48 ++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 40 insertions(+), 8 deletions(-)

(limited to 'sound')

diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c
index 5d86e680975..fd7bc865e67 100644
--- a/sound/arm/pxa2xx-ac97.c
+++ b/sound/arm/pxa2xx-ac97.c
@@ -16,6 +16,7 @@
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/wait.h>
+#include <linux/clk.h>
 #include <linux/delay.h>
 
 #include <sound/core.h>
@@ -35,6 +36,10 @@
 static DEFINE_MUTEX(car_mutex);
 static DECLARE_WAIT_QUEUE_HEAD(gsr_wq);
 static volatile long gsr_bits;
+static struct clk *ac97_clk;
+#ifdef CONFIG_PXA27x
+static struct clk *ac97conf_clk;
+#endif
 
 /*
  * Beware PXA27x bugs:
@@ -112,9 +117,9 @@ static void pxa2xx_ac97_reset(struct snd_ac97 *ac97)
 	gsr_bits = 0;
 #ifdef CONFIG_PXA27x
 	/* PXA27x Developers Manual section 13.5.2.2.1 */
-	pxa_set_cken(CKEN_AC97CONF, 1);
+	clk_enable(ac97conf_clk);
 	udelay(5);
-	pxa_set_cken(CKEN_AC97CONF, 0);
+	clk_disable(ac97conf_clk);
 	GCR = GCR_COLD_RST;
 	udelay(50);
 #else
@@ -259,7 +264,7 @@ static int pxa2xx_ac97_do_suspend(struct snd_card *card, pm_message_t state)
 	if (platform_ops && platform_ops->suspend)
 		platform_ops->suspend(platform_ops->priv);
 	GCR |= GCR_ACLINK_OFF;
-	pxa_set_cken(CKEN_AC97, 0);
+	clk_disable(ac97_clk);
 
 	return 0;
 }
@@ -268,7 +273,7 @@ static int pxa2xx_ac97_do_resume(struct snd_card *card)
 {
 	pxa2xx_audio_ops_t *platform_ops = card->dev->platform_data;
 
-	pxa_set_cken(CKEN_AC97, 1);
+	clk_enable(ac97_clk);
 	if (platform_ops && platform_ops->resume)
 		platform_ops->resume(platform_ops->priv);
 	snd_ac97_resume(pxa2xx_ac97_ac97);
@@ -335,8 +340,21 @@ static int __devinit pxa2xx_ac97_probe(struct platform_device *dev)
 #ifdef CONFIG_PXA27x
 	/* Use GPIO 113 as AC97 Reset on Bulverde */
 	pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
+	ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK");
+	if (IS_ERR(ac97conf_clk)) {
+		ret = PTR_ERR(ac97conf_clk);
+		ac97conf_clk = NULL;
+		goto err;
+	}
 #endif
-	pxa_set_cken(CKEN_AC97, 1);
+
+	ac97_clk = clk_get(&dev->dev, "AC97CLK");
+	if (IS_ERR(ac97_clk)) {
+		ret = PTR_ERR(ac97_clk);
+		ac97_clk = NULL;
+		goto err;
+	}
+	clk_enable(ac97_clk);
 
 	ret = snd_ac97_bus(card, 0, &pxa2xx_ac97_ops, NULL, &ac97_bus);
 	if (ret)
@@ -361,11 +379,19 @@ static int __devinit pxa2xx_ac97_probe(struct platform_device *dev)
  err:
 	if (card)
 		snd_card_free(card);
-	if (CKEN & (1 << CKEN_AC97)) {
+	if (ac97_clk) {
 		GCR |= GCR_ACLINK_OFF;
 		free_irq(IRQ_AC97, NULL);
-		pxa_set_cken(CKEN_AC97, 0);
+		clk_disable(ac97_clk);
+		clk_put(ac97_clk);
+		ac97_clk = NULL;
+	}
+#ifdef CONFIG_PXA27x
+	if (ac97conf_clk) {
+		clk_put(ac97conf_clk);
+		ac97conf_clk = NULL;
 	}
+#endif
 	return ret;
 }
 
@@ -378,7 +404,13 @@ static int __devexit pxa2xx_ac97_remove(struct platform_device *dev)
 		platform_set_drvdata(dev, NULL);
 		GCR |= GCR_ACLINK_OFF;
 		free_irq(IRQ_AC97, NULL);
-		pxa_set_cken(CKEN_AC97, 0);
+		clk_disable(ac97_clk);
+		clk_put(ac97_clk);
+		ac97_clk = NULL;
+#ifdef CONFIG_PXA27x
+		clk_put(ac97conf_clk);
+		ac97conf_clk = NULL;
+#endif
 	}
 
 	return 0;
-- 
cgit v1.2.3-70-g09d2


From 942de47bfee24143ecbf75b981b32143bd414529 Mon Sep 17 00:00:00 2001
From: Mark Brown <broonie@sirena.org.uk>
Date: Tue, 4 Mar 2008 11:14:24 +0100
Subject: [ARM] 4834/3: Convert ASoC pxa2xx-ac97 driver to use the clock API

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Acked-by: Takashi Iwai <tiwai@suse.de>
Acked-by: eric miao <eric.miao@marvell.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 sound/soc/pxa/pxa2xx-ac97.c | 49 +++++++++++++++++++++++++++++++++++----------
 1 file changed, 38 insertions(+), 11 deletions(-)

(limited to 'sound')

diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
index 815c1533625..711b916e58a 100644
--- a/sound/soc/pxa/pxa2xx-ac97.c
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -15,6 +15,7 @@
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/wait.h>
+#include <linux/clk.h>
 #include <linux/delay.h>
 
 #include <sound/core.h>
@@ -35,6 +36,10 @@
 static DEFINE_MUTEX(car_mutex);
 static DECLARE_WAIT_QUEUE_HEAD(gsr_wq);
 static volatile long gsr_bits;
+static struct clk *ac97_clk;
+#ifdef CONFIG_PXA27x
+static struct clk *ac97conf_clk;
+#endif
 
 /*
  * Beware PXA27x bugs:
@@ -159,9 +164,9 @@ static void pxa2xx_ac97_cold_reset(struct snd_ac97 *ac97)
 	gsr_bits = 0;
 #ifdef CONFIG_PXA27x
 	/* PXA27x Developers Manual section 13.5.2.2.1 */
-	pxa_set_cken(CKEN_AC97CONF, 1);
+	clk_enable(ac97conf_clk);
 	udelay(5);
-	pxa_set_cken(CKEN_AC97CONF, 0);
+	clk_disable(ac97conf_clk);
 	GCR = GCR_COLD_RST;
 	udelay(50);
 #else
@@ -255,7 +260,7 @@ static int pxa2xx_ac97_suspend(struct platform_device *pdev,
 	struct snd_soc_cpu_dai *dai)
 {
 	GCR |= GCR_ACLINK_OFF;
-	pxa_set_cken(CKEN_AC97, 0);
+	clk_disable(ac97_clk);
 	return 0;
 }
 
@@ -270,7 +275,7 @@ static int pxa2xx_ac97_resume(struct platform_device *pdev,
 	/* Use GPIO 113 as AC97 Reset on Bulverde */
 	pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
 #endif
-	pxa_set_cken(CKEN_AC97, 1);
+	clk_enable(ac97_clk);
 	return 0;
 }
 
@@ -294,16 +299,32 @@ static int pxa2xx_ac97_probe(struct platform_device *pdev)
 #ifdef CONFIG_PXA27x
 	/* Use GPIO 113 as AC97 Reset on Bulverde */
 	pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
+
+	ac97conf_clk = clk_get(&pdev->dev, "AC97CONFCLK");
+	if (IS_ERR(ac97conf_clk)) {
+		ret = PTR_ERR(ac97conf_clk);
+		ac97conf_clk = NULL;
+		goto err_irq;
+	}
 #endif
-	pxa_set_cken(CKEN_AC97, 1);
+	ac97_clk = clk_get(&pdev->dev, "AC97CLK");
+	if (IS_ERR(ac97_clk)) {
+		ret = PTR_ERR(ac97_clk);
+		ac97_clk = NULL;
+		goto err_irq;
+	}
 	return 0;
 
- err:
-	if (CKEN & (1 << CKEN_AC97)) {
-		GCR |= GCR_ACLINK_OFF;
-		free_irq(IRQ_AC97, NULL);
-		pxa_set_cken(CKEN_AC97, 0);
+ err_irq:
+	GCR |= GCR_ACLINK_OFF;
+#ifdef CONFIG_PXA27x
+	if (ac97conf_clk) {
+		clk_put(ac97conf_clk);
+		ac97conf_clk = NULL;
 	}
+#endif
+	free_irq(IRQ_AC97, NULL);
+ err:
 	return ret;
 }
 
@@ -311,7 +332,13 @@ static void pxa2xx_ac97_remove(struct platform_device *pdev)
 {
 	GCR |= GCR_ACLINK_OFF;
 	free_irq(IRQ_AC97, NULL);
-	pxa_set_cken(CKEN_AC97, 0);
+#ifdef CONFIG_PXA27x
+	clk_put(ac97conf_clk);
+	ac97conf_clk = NULL;
+#endif
+	clk_disable(ac97_clk);
+	clk_put(ac97_clk);
+	ac97_clk = NULL;
 }
 
 static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream,
-- 
cgit v1.2.3-70-g09d2


From a683b14df8f4320d0ef6cac93a6d9806173bf339 Mon Sep 17 00:00:00 2001
From: eric miao <eric.miao@marvell.com>
Date: Mon, 3 Mar 2008 09:44:25 +0800
Subject: [ARM] pxa: separate GPIOs and their mode definitions to pxa2xx-gpio.h

two reasons:
1. GPIO namings and their mode definitions are conceptually not part
   of the PXA register definitions

2. this is actually a temporary move in the transition of PXA2xx to
   use MFP-alike APIs (as what PXA3xx is now doing), so that legacy
   code will still work and new code can be added in step by step

Signed-off-by: eric miao <eric.miao@marvell.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 arch/arm/mach-pxa/clock.c              |   1 +
 arch/arm/mach-pxa/cm-x270-pci.c        |   1 +
 arch/arm/mach-pxa/cm-x270.c            |   1 +
 arch/arm/mach-pxa/colibri.c            |   1 +
 arch/arm/mach-pxa/corgi.c              |   1 +
 arch/arm/mach-pxa/corgi_pm.c           |   1 +
 arch/arm/mach-pxa/corgi_ssp.c          |   1 +
 arch/arm/mach-pxa/em-x270.c            |   1 +
 arch/arm/mach-pxa/gpio.c               |   1 +
 arch/arm/mach-pxa/idp.c                |   1 +
 arch/arm/mach-pxa/irq.c                |   1 +
 arch/arm/mach-pxa/leds-trizeps4.c      |   1 +
 arch/arm/mach-pxa/lpd270.c             |   1 +
 arch/arm/mach-pxa/lubbock.c            |   1 +
 arch/arm/mach-pxa/mainstone.c          |   1 +
 arch/arm/mach-pxa/pcm027.c             |   1 +
 arch/arm/mach-pxa/pcm990-baseboard.c   |   1 +
 arch/arm/mach-pxa/poodle.c             |   1 +
 arch/arm/mach-pxa/sharpsl_pm.c         |   1 +
 arch/arm/mach-pxa/spitz.c              |   1 +
 arch/arm/mach-pxa/spitz_pm.c           |   1 +
 arch/arm/mach-pxa/tosa.c               |   1 +
 arch/arm/mach-pxa/trizeps4.c           |   1 +
 drivers/i2c/busses/i2c-pxa.c           |   1 +
 drivers/input/keyboard/corgikbd.c      |   1 +
 drivers/input/keyboard/spitzkbd.c      |   1 +
 drivers/input/touchscreen/corgi_ts.c   |   1 +
 drivers/net/irda/pxaficp_ir.c          |   1 +
 drivers/pcmcia/pxa2xx_cm_x270.c        |   1 +
 drivers/video/pxafb.c                  |   1 +
 include/asm-arm/arch-pxa/pxa-regs.h    | 301 --------------------------------
 include/asm-arm/arch-pxa/pxa2xx-gpio.h | 304 +++++++++++++++++++++++++++++++++
 sound/arm/pxa2xx-ac97.c                |   1 +
 sound/soc/pxa/pxa2xx-ac97.c            |   1 +
 sound/soc/pxa/pxa2xx-i2s.c             |   1 +
 35 files changed, 337 insertions(+), 301 deletions(-)
 create mode 100644 include/asm-arm/arch-pxa/pxa2xx-gpio.h

(limited to 'sound')

diff --git a/arch/arm/mach-pxa/clock.c b/arch/arm/mach-pxa/clock.c
index df5ae2710ab..e97dc59813c 100644
--- a/arch/arm/mach-pxa/clock.c
+++ b/arch/arm/mach-pxa/clock.c
@@ -13,6 +13,7 @@
 #include <linux/delay.h>
 
 #include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
 #include <asm/hardware.h>
 
 #include "devices.h"
diff --git a/arch/arm/mach-pxa/cm-x270-pci.c b/arch/arm/mach-pxa/cm-x270-pci.c
index fcda7d5cb69..ac7f05f9f3e 100644
--- a/arch/arm/mach-pxa/cm-x270-pci.c
+++ b/arch/arm/mach-pxa/cm-x270-pci.c
@@ -23,6 +23,7 @@
 #include <asm/mach/pci.h>
 #include <asm/arch/cm-x270.h>
 #include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
 #include <asm/mach-types.h>
 
 #include <asm/hardware/it8152.h>
diff --git a/arch/arm/mach-pxa/cm-x270.c b/arch/arm/mach-pxa/cm-x270.c
index ecdbc96a4de..6d4416a4f37 100644
--- a/arch/arm/mach-pxa/cm-x270.c
+++ b/arch/arm/mach-pxa/cm-x270.c
@@ -30,6 +30,7 @@
 
 #include <asm/arch/pxa-regs.h>
 #include <asm/arch/pxa2xx-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
 #include <asm/arch/pxafb.h>
 #include <asm/arch/ohci.h>
 #include <asm/arch/mmc.h>
diff --git a/arch/arm/mach-pxa/colibri.c b/arch/arm/mach-pxa/colibri.c
index 6db54e31c39..43bf5a183e9 100644
--- a/arch/arm/mach-pxa/colibri.c
+++ b/arch/arm/mach-pxa/colibri.c
@@ -29,6 +29,7 @@
 #include <asm/mach/irq.h>
 #include <asm/mach/flash.h>
 #include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
 #include <asm/arch/colibri.h>
 
 #include "generic.h"
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index 9292576b83b..259ca821e46 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -36,6 +36,7 @@
 #include <asm/mach/irq.h>
 
 #include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
 #include <asm/arch/irda.h>
 #include <asm/arch/mmc.h>
 #include <asm/arch/udc.h>
diff --git a/arch/arm/mach-pxa/corgi_pm.c b/arch/arm/mach-pxa/corgi_pm.c
index 392c3871736..0a85f706e88 100644
--- a/arch/arm/mach-pxa/corgi_pm.c
+++ b/arch/arm/mach-pxa/corgi_pm.c
@@ -26,6 +26,7 @@
 #include <asm/arch/sharpsl.h>
 #include <asm/arch/corgi.h>
 #include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
 #include "sharpsl.h"
 
 #define SHARPSL_CHARGE_ON_VOLT         0x99  /* 2.9V */
diff --git a/arch/arm/mach-pxa/corgi_ssp.c b/arch/arm/mach-pxa/corgi_ssp.c
index 31706224a04..eccc45d21f7 100644
--- a/arch/arm/mach-pxa/corgi_ssp.c
+++ b/arch/arm/mach-pxa/corgi_ssp.c
@@ -21,6 +21,7 @@
 
 #include <asm/arch/ssp.h>
 #include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
 #include <asm/arch/regs-ssp.h>
 #include "sharpsl.h"
 
diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c
index 3bb31314429..edc4f07a230 100644
--- a/arch/arm/mach-pxa/em-x270.c
+++ b/arch/arm/mach-pxa/em-x270.c
@@ -23,6 +23,7 @@
 #include <asm/mach/arch.h>
 
 #include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
 #include <asm/arch/pxafb.h>
 #include <asm/arch/ohci.h>
 #include <asm/arch/mmc.h>
diff --git a/arch/arm/mach-pxa/gpio.c b/arch/arm/mach-pxa/gpio.c
index f96cae04f6f..1a7057991da 100644
--- a/arch/arm/mach-pxa/gpio.c
+++ b/arch/arm/mach-pxa/gpio.c
@@ -21,6 +21,7 @@
 #include <asm/hardware.h>
 #include <asm/io.h>
 #include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
 
 #include "generic.h"
 
diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c
index 0a9434432c5..2637633f916 100644
--- a/arch/arm/mach-pxa/idp.c
+++ b/arch/arm/mach-pxa/idp.c
@@ -32,6 +32,7 @@
 #include <asm/mach/map.h>
 
 #include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
 #include <asm/arch/idp.h>
 #include <asm/arch/pxafb.h>
 #include <asm/arch/bitfield.h>
diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
index fbff557bb22..a9a0c3fab15 100644
--- a/arch/arm/mach-pxa/irq.c
+++ b/arch/arm/mach-pxa/irq.c
@@ -21,6 +21,7 @@
 #include <asm/irq.h>
 #include <asm/mach/irq.h>
 #include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
 
 #include "generic.h"
 
diff --git a/arch/arm/mach-pxa/leds-trizeps4.c b/arch/arm/mach-pxa/leds-trizeps4.c
index 2271d20ffed..21880daabaf 100644
--- a/arch/arm/mach-pxa/leds-trizeps4.c
+++ b/arch/arm/mach-pxa/leds-trizeps4.c
@@ -18,6 +18,7 @@
 #include <asm/leds.h>
 
 #include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
 #include <asm/arch/trizeps4.h>
 
 #include "leds.h"
diff --git a/arch/arm/mach-pxa/lpd270.c b/arch/arm/mach-pxa/lpd270.c
index afa62ffe3ad..a20e4b1649d 100644
--- a/arch/arm/mach-pxa/lpd270.c
+++ b/arch/arm/mach-pxa/lpd270.c
@@ -39,6 +39,7 @@
 
 #include <asm/arch/pxa-regs.h>
 #include <asm/arch/pxa2xx-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
 #include <asm/arch/lpd270.h>
 #include <asm/arch/audio.h>
 #include <asm/arch/pxafb.h>
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index e7ae4bb3e36..81567ec983a 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -42,6 +42,7 @@
 
 #include <asm/arch/pxa-regs.h>
 #include <asm/arch/pxa2xx-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
 #include <asm/arch/lubbock.h>
 #include <asm/arch/udc.h>
 #include <asm/arch/irda.h>
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index 72a436fb9a2..75be0c74a64 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -40,6 +40,7 @@
 
 #include <asm/arch/pxa-regs.h>
 #include <asm/arch/pxa2xx-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
 #include <asm/arch/mainstone.h>
 #include <asm/arch/audio.h>
 #include <asm/arch/pxafb.h>
diff --git a/arch/arm/mach-pxa/pcm027.c b/arch/arm/mach-pxa/pcm027.c
index c14696b9979..3b945eb0aee 100644
--- a/arch/arm/mach-pxa/pcm027.c
+++ b/arch/arm/mach-pxa/pcm027.c
@@ -29,6 +29,7 @@
 #include <asm/mach/arch.h>
 #include <asm/arch/hardware.h>
 #include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
 #include <asm/arch/pxa2xx-regs.h>
 #include <asm/arch/pxa2xx_spi.h>
 #include <asm/arch/pcm027.h>
diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c
index 3dda16a2004..20b2974e396 100644
--- a/arch/arm/mach-pxa/pcm990-baseboard.c
+++ b/arch/arm/mach-pxa/pcm990-baseboard.c
@@ -25,6 +25,7 @@
 #include <linux/ide.h>
 #include <asm/mach/map.h>
 #include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
 #include <asm/arch/mmc.h>
 #include <asm/arch/ohci.h>
 #include <asm/arch/pcm990_baseboard.h>
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index 209eabf0ed3..ca5ac196b47 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -32,6 +32,7 @@
 #include <asm/mach/irq.h>
 
 #include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
 #include <asm/arch/mmc.h>
 #include <asm/arch/udc.h>
 #include <asm/arch/irda.h>
diff --git a/arch/arm/mach-pxa/sharpsl_pm.c b/arch/arm/mach-pxa/sharpsl_pm.c
index f9d1b61e118..34cd585075b 100644
--- a/arch/arm/mach-pxa/sharpsl_pm.c
+++ b/arch/arm/mach-pxa/sharpsl_pm.c
@@ -26,6 +26,7 @@
 #include <asm/mach-types.h>
 #include <asm/arch/pm.h>
 #include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
 #include <asm/arch/sharpsl.h>
 #include "sharpsl.h"
 
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index 9e7773fca01..62a02c3927c 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -37,6 +37,7 @@
 
 #include <asm/arch/pxa-regs.h>
 #include <asm/arch/pxa2xx-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
 #include <asm/arch/irda.h>
 #include <asm/arch/mmc.h>
 #include <asm/arch/ohci.h>
diff --git a/arch/arm/mach-pxa/spitz_pm.c b/arch/arm/mach-pxa/spitz_pm.c
index 745a4dc7acd..7a7f5f947cc 100644
--- a/arch/arm/mach-pxa/spitz_pm.c
+++ b/arch/arm/mach-pxa/spitz_pm.c
@@ -26,6 +26,7 @@
 #include <asm/arch/sharpsl.h>
 #include <asm/arch/spitz.h>
 #include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
 #include "sharpsl.h"
 
 #define SHARPSL_CHARGE_ON_VOLT         0x99  /* 2.9V */
diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
index f99112d50b4..d427d87b4fe 100644
--- a/arch/arm/mach-pxa/tosa.c
+++ b/arch/arm/mach-pxa/tosa.c
@@ -32,6 +32,7 @@
 #include <asm/system.h>
 #include <asm/arch/pxa-regs.h>
 #include <asm/arch/pxa2xx-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
 #include <asm/arch/irda.h>
 #include <asm/arch/mmc.h>
 #include <asm/arch/udc.h>
diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c
index f207fcd30cd..931885d86b9 100644
--- a/arch/arm/mach-pxa/trizeps4.c
+++ b/arch/arm/mach-pxa/trizeps4.c
@@ -41,6 +41,7 @@
 #include <asm/mach/flash.h>
 
 #include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
 #include <asm/arch/trizeps4.h>
 #include <asm/arch/audio.h>
 #include <asm/arch/pxafb.h>
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index 2d2087ad708..6fd2d6a84ef 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -39,6 +39,7 @@
 #include <asm/io.h>
 #include <asm/arch/i2c.h>
 #include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
 
 struct pxa_i2c {
 	spinlock_t		lock;
diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c
index 790fed368aa..5d6cc7f1dc9 100644
--- a/drivers/input/keyboard/corgikbd.c
+++ b/drivers/input/keyboard/corgikbd.c
@@ -23,6 +23,7 @@
 #include <asm/arch/corgi.h>
 #include <asm/arch/hardware.h>
 #include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
 #include <asm/hardware/scoop.h>
 
 #define KB_ROWS				8
diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c
index 1d59a2dc3c1..0be74bfc58f 100644
--- a/drivers/input/keyboard/spitzkbd.c
+++ b/drivers/input/keyboard/spitzkbd.c
@@ -23,6 +23,7 @@
 #include <asm/arch/spitz.h>
 #include <asm/arch/hardware.h>
 #include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
 
 #define KB_ROWS			7
 #define KB_COLS			11
diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c
index 99d92f5c93d..a22576779ac 100644
--- a/drivers/input/touchscreen/corgi_ts.c
+++ b/drivers/input/touchscreen/corgi_ts.c
@@ -22,6 +22,7 @@
 #include <asm/arch/sharpsl.h>
 #include <asm/arch/hardware.h>
 #include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
 
 
 #define PWR_MODE_ACTIVE		0
diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c
index 8c09344f58d..8239c520f1e 100644
--- a/drivers/net/irda/pxaficp_ir.c
+++ b/drivers/net/irda/pxaficp_ir.c
@@ -36,6 +36,7 @@
 #include <asm/hardware.h>
 #include <asm/arch/irda.h>
 #include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
 
 #ifdef CONFIG_MACH_MAINSTONE
 #include <asm/arch/mainstone.h>
diff --git a/drivers/pcmcia/pxa2xx_cm_x270.c b/drivers/pcmcia/pxa2xx_cm_x270.c
index fbf2f3a6984..e7ab060ff11 100644
--- a/drivers/pcmcia/pxa2xx_cm_x270.c
+++ b/drivers/pcmcia/pxa2xx_cm_x270.c
@@ -20,6 +20,7 @@
 #include <asm/hardware.h>
 
 #include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
 #include <asm/arch/cm-x270.h>
 
 #include "soc_common.h"
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index 97facb121c7..757651954e6 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -45,6 +45,7 @@
 #include <asm/irq.h>
 #include <asm/div64.h>
 #include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
 #include <asm/arch/bitfield.h>
 #include <asm/arch/pxafb.h>
 
diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h
index e659be4df3a..e78adf8268e 100644
--- a/include/asm-arm/arch-pxa/pxa-regs.h
+++ b/include/asm-arm/arch-pxa/pxa-regs.h
@@ -1236,307 +1236,6 @@
 
 #endif
 
-
-/* GPIO alternate function assignments */
-
-#define GPIO1_RST		1	/* reset */
-#define GPIO6_MMCCLK		6	/* MMC Clock */
-#define GPIO7_48MHz		7	/* 48 MHz clock output */
-#define GPIO8_MMCCS0		8	/* MMC Chip Select 0 */
-#define GPIO9_MMCCS1		9	/* MMC Chip Select 1 */
-#define GPIO10_RTCCLK		10	/* real time clock (1 Hz) */
-#define GPIO11_3_6MHz		11	/* 3.6 MHz oscillator out */
-#define GPIO12_32KHz		12	/* 32 kHz out */
-#define GPIO12_CIF_DD_7		12	/* Camera data pin 7 */
-#define GPIO13_MBGNT		13	/* memory controller grant */
-#define GPIO14_MBREQ		14	/* alternate bus master request */
-#define GPIO15_nCS_1		15	/* chip select 1 */
-#define GPIO16_PWM0		16	/* PWM0 output */
-#define GPIO17_PWM1		17	/* PWM1 output */
-#define GPIO17_CIF_DD_6		17	/* Camera data pin 6 */
-#define GPIO18_RDY		18	/* Ext. Bus Ready */
-#define GPIO19_DREQ1		19	/* External DMA Request */
-#define GPIO20_DREQ0		20	/* External DMA Request */
-#define GPIO23_SCLK		23	/* SSP clock */
-#define GPIO24_SFRM		24	/* SSP Frame */
-#define GPIO25_STXD		25	/* SSP transmit */
-#define GPIO26_SRXD		26	/* SSP receive */
-#define GPIO27_SEXTCLK		27	/* SSP ext_clk */
-#define GPIO28_BITCLK		28	/* AC97/I2S bit_clk */
-#define GPIO29_SDATA_IN		29	/* AC97 Sdata_in0 / I2S Sdata_in */
-#define GPIO30_SDATA_OUT	30	/* AC97/I2S Sdata_out */
-#define GPIO31_SYNC		31	/* AC97/I2S sync */
-#define GPIO32_SDATA_IN1	32	/* AC97 Sdata_in1 */
-#define GPIO32_SYSCLK		32	/* I2S System Clock */
-#define GPIO32_MMCCLK		32	/* MMC Clock (PXA270) */
-#define GPIO33_nCS_5		33	/* chip select 5 */
-#define GPIO34_FFRXD		34	/* FFUART receive */
-#define GPIO34_MMCCS0		34	/* MMC Chip Select 0 */
-#define GPIO35_FFCTS		35	/* FFUART Clear to send */
-#define GPIO36_FFDCD		36	/* FFUART Data carrier detect */
-#define GPIO37_FFDSR		37	/* FFUART data set ready */
-#define GPIO38_FFRI		38	/* FFUART Ring Indicator */
-#define GPIO39_MMCCS1		39	/* MMC Chip Select 1 */
-#define GPIO39_FFTXD		39	/* FFUART transmit data */
-#define GPIO40_FFDTR		40	/* FFUART data terminal Ready */
-#define GPIO41_FFRTS		41	/* FFUART request to send */
-#define GPIO42_BTRXD		42	/* BTUART receive data */
-#define GPIO42_HWRXD		42	/* HWUART receive data */
-#define GPIO43_BTTXD		43	/* BTUART transmit data */
-#define GPIO43_HWTXD		43	/* HWUART transmit data */
-#define GPIO44_BTCTS		44	/* BTUART clear to send */
-#define GPIO44_HWCTS		44	/* HWUART clear to send */
-#define GPIO45_BTRTS		45	/* BTUART request to send */
-#define GPIO45_HWRTS		45	/* HWUART request to send */
-#define GPIO45_AC97_SYSCLK	45	/* AC97 System Clock */
-#define GPIO46_ICPRXD		46	/* ICP receive data */
-#define GPIO46_STRXD		46	/* STD_UART receive data */
-#define GPIO47_ICPTXD		47	/* ICP transmit data */
-#define GPIO47_STTXD		47	/* STD_UART transmit data */
-#define GPIO48_nPOE		48	/* Output Enable for Card Space */
-#define GPIO49_nPWE		49	/* Write Enable for Card Space */
-#define GPIO50_nPIOR		50	/* I/O Read for Card Space */
-#define GPIO50_CIF_DD_3		50	/* Camera data pin 3 */
-#define GPIO51_nPIOW		51	/* I/O Write for Card Space */
-#define GPIO51_CIF_DD_2		51	/* Camera data pin 2 */
-#define GPIO52_nPCE_1		52	/* Card Enable for Card Space */
-#define GPIO52_CIF_DD_4		52	/* Camera data pin 4 */
-#define GPIO53_nPCE_2		53	/* Card Enable for Card Space */
-#define GPIO53_MMCCLK		53	/* MMC Clock */
-#define GPIO53_CIF_MCLK		53	/* Camera Master Clock */
-#define GPIO54_MMCCLK		54	/* MMC Clock */
-#define GPIO54_pSKTSEL		54	/* Socket Select for Card Space */
-#define GPIO54_nPCE_2		54	/* Card Enable for Card Space (PXA27x) */
-#define GPIO54_CIF_PCLK		54	/* Camera Pixel Clock */
-#define GPIO55_nPREG		55	/* Card Address bit 26 */
-#define GPIO55_CIF_DD_1		55	/* Camera data pin 1 */
-#define GPIO56_nPWAIT		56	/* Wait signal for Card Space */
-#define GPIO57_nIOIS16		57	/* Bus Width select for I/O Card Space */
-#define GPIO58_LDD_0		58	/* LCD data pin 0 */
-#define GPIO59_LDD_1		59	/* LCD data pin 1 */
-#define GPIO60_LDD_2		60	/* LCD data pin 2 */
-#define GPIO61_LDD_3		61	/* LCD data pin 3 */
-#define GPIO62_LDD_4		62	/* LCD data pin 4 */
-#define GPIO63_LDD_5		63	/* LCD data pin 5 */
-#define GPIO64_LDD_6		64	/* LCD data pin 6 */
-#define GPIO65_LDD_7		65	/* LCD data pin 7 */
-#define GPIO66_LDD_8		66	/* LCD data pin 8 */
-#define GPIO66_MBREQ		66	/* alternate bus master req */
-#define GPIO67_LDD_9		67	/* LCD data pin 9 */
-#define GPIO67_MMCCS0		67	/* MMC Chip Select 0 */
-#define GPIO68_LDD_10		68	/* LCD data pin 10 */
-#define GPIO68_MMCCS1		68	/* MMC Chip Select 1 */
-#define GPIO69_LDD_11		69	/* LCD data pin 11 */
-#define GPIO69_MMCCLK		69	/* MMC_CLK */
-#define GPIO70_LDD_12		70	/* LCD data pin 12 */
-#define GPIO70_RTCCLK		70	/* Real Time clock (1 Hz) */
-#define GPIO71_LDD_13		71	/* LCD data pin 13 */
-#define GPIO71_3_6MHz		71	/* 3.6 MHz Oscillator clock */
-#define GPIO72_LDD_14		72	/* LCD data pin 14 */
-#define GPIO72_32kHz		72	/* 32 kHz clock */
-#define GPIO73_LDD_15		73	/* LCD data pin 15 */
-#define GPIO73_MBGNT		73	/* Memory controller grant */
-#define GPIO74_LCD_FCLK		74	/* LCD Frame clock */
-#define GPIO75_LCD_LCLK		75	/* LCD line clock */
-#define GPIO76_LCD_PCLK		76	/* LCD Pixel clock */
-#define GPIO77_LCD_ACBIAS	77	/* LCD AC Bias */
-#define GPIO78_nCS_2		78	/* chip select 2 */
-#define GPIO79_nCS_3		79	/* chip select 3 */
-#define GPIO80_nCS_4		80	/* chip select 4 */
-#define GPIO81_NSCLK		81	/* NSSP clock */
-#define GPIO81_CIF_DD_0		81	/* Camera data pin 0 */
-#define GPIO82_NSFRM		82	/* NSSP Frame */
-#define GPIO82_CIF_DD_5		82	/* Camera data pin 5 */
-#define GPIO83_NSTXD		83	/* NSSP transmit */
-#define GPIO84_NSRXD		84	/* NSSP receive */
-#define GPIO84_CIF_FV		84	/* Camera frame start signal */
-#define GPIO85_nPCE_1		85	/* Card Enable for Card Space (PXA27x) */
-#define GPIO85_CIF_LV		85	/* Camera line start signal */
-#define GPIO92_MMCDAT0		92	/* MMC DAT0 (PXA27x) */
-#define GPIO102_nPCE_1		102	/* PCMCIA (PXA27x) */
-#define GPIO109_MMCDAT1		109	/* MMC DAT1 (PXA27x) */
-#define GPIO110_MMCDAT2		110	/* MMC DAT2 (PXA27x) */
-#define GPIO110_MMCCS0		110	/* MMC Chip Select 0 (PXA27x) */
-#define GPIO111_MMCDAT3		111	/* MMC DAT3 (PXA27x) */
-#define GPIO111_MMCCS1		111	/* MMC Chip Select 1 (PXA27x) */
-#define GPIO112_MMCCMD		112	/* MMC CMD (PXA27x) */
-#define GPIO113_I2S_SYSCLK	113	/* I2S System Clock (PXA27x) */
-#define GPIO113_AC97_RESET_N	113	/* AC97 NRESET on (PXA27x) */
-
-/* GPIO alternate function mode & direction */
-
-#define GPIO_IN			0x000
-#define GPIO_OUT		0x080
-#define GPIO_ALT_FN_1_IN	0x100
-#define GPIO_ALT_FN_1_OUT	0x180
-#define GPIO_ALT_FN_2_IN	0x200
-#define GPIO_ALT_FN_2_OUT	0x280
-#define GPIO_ALT_FN_3_IN	0x300
-#define GPIO_ALT_FN_3_OUT	0x380
-#define GPIO_MD_MASK_NR		0x07f
-#define GPIO_MD_MASK_DIR	0x080
-#define GPIO_MD_MASK_FN		0x300
-#define GPIO_DFLT_LOW		0x400
-#define GPIO_DFLT_HIGH		0x800
-
-#define GPIO1_RTS_MD		( 1 | GPIO_ALT_FN_1_IN)
-#define GPIO6_MMCCLK_MD		( 6 | GPIO_ALT_FN_1_OUT)
-#define GPIO7_48MHz_MD		( 7 | GPIO_ALT_FN_1_OUT)
-#define GPIO8_MMCCS0_MD		( 8 | GPIO_ALT_FN_1_OUT)
-#define GPIO9_MMCCS1_MD		( 9 | GPIO_ALT_FN_1_OUT)
-#define GPIO10_RTCCLK_MD	(10 | GPIO_ALT_FN_1_OUT)
-#define GPIO11_3_6MHz_MD	(11 | GPIO_ALT_FN_1_OUT)
-#define GPIO12_32KHz_MD		(12 | GPIO_ALT_FN_1_OUT)
-#define GPIO12_CIF_DD_7_MD	(12 | GPIO_ALT_FN_2_IN)
-#define GPIO13_MBGNT_MD		(13 | GPIO_ALT_FN_2_OUT)
-#define GPIO14_MBREQ_MD		(14 | GPIO_ALT_FN_1_IN)
-#define GPIO15_nCS_1_MD		(15 | GPIO_ALT_FN_2_OUT)
-#define GPIO16_PWM0_MD		(16 | GPIO_ALT_FN_2_OUT)
-#define GPIO17_PWM1_MD		(17 | GPIO_ALT_FN_2_OUT)
-#define GPIO17_CIF_DD_6_MD	(17 | GPIO_ALT_FN_2_IN)
-#define GPIO18_RDY_MD		(18 | GPIO_ALT_FN_1_IN)
-#define GPIO19_DREQ1_MD		(19 | GPIO_ALT_FN_1_IN)
-#define GPIO20_DREQ0_MD		(20 | GPIO_ALT_FN_1_IN)
-#define GPIO23_SCLK_MD		(23 | GPIO_ALT_FN_2_OUT)
-#define GPIO24_SFRM_MD		(24 | GPIO_ALT_FN_2_OUT)
-#define GPIO25_STXD_MD		(25 | GPIO_ALT_FN_2_OUT)
-#define GPIO26_SRXD_MD		(26 | GPIO_ALT_FN_1_IN)
-#define GPIO27_SEXTCLK_MD	(27 | GPIO_ALT_FN_1_IN)
-#define GPIO28_BITCLK_AC97_MD	(28 | GPIO_ALT_FN_1_IN)
-#define GPIO28_BITCLK_IN_I2S_MD	(28 | GPIO_ALT_FN_2_IN)
-#define GPIO28_BITCLK_OUT_I2S_MD	(28 | GPIO_ALT_FN_1_OUT)
-#define GPIO29_SDATA_IN_AC97_MD	(29 | GPIO_ALT_FN_1_IN)
-#define GPIO29_SDATA_IN_I2S_MD	(29 | GPIO_ALT_FN_2_IN)
-#define GPIO30_SDATA_OUT_AC97_MD	(30 | GPIO_ALT_FN_2_OUT)
-#define GPIO30_SDATA_OUT_I2S_MD	(30 | GPIO_ALT_FN_1_OUT)
-#define GPIO31_SYNC_I2S_MD	(31 | GPIO_ALT_FN_1_OUT)
-#define GPIO31_SYNC_AC97_MD	(31 | GPIO_ALT_FN_2_OUT)
-#define GPIO32_SDATA_IN1_AC97_MD	(32 | GPIO_ALT_FN_1_IN)
-#define GPIO32_SYSCLK_I2S_MD	(32 | GPIO_ALT_FN_1_OUT)
-#define GPIO32_MMCCLK_MD	(32 | GPIO_ALT_FN_2_OUT)
-#define GPIO33_nCS_5_MD		(33 | GPIO_ALT_FN_2_OUT)
-#define GPIO34_FFRXD_MD		(34 | GPIO_ALT_FN_1_IN)
-#define GPIO34_MMCCS0_MD	(34 | GPIO_ALT_FN_2_OUT)
-#define GPIO35_FFCTS_MD		(35 | GPIO_ALT_FN_1_IN)
-#define GPIO35_KP_MKOUT6_MD	(35 | GPIO_ALT_FN_2_OUT)
-#define GPIO36_FFDCD_MD		(36 | GPIO_ALT_FN_1_IN)
-#define GPIO37_FFDSR_MD		(37 | GPIO_ALT_FN_1_IN)
-#define GPIO38_FFRI_MD		(38 | GPIO_ALT_FN_1_IN)
-#define GPIO39_MMCCS1_MD	(39 | GPIO_ALT_FN_1_OUT)
-#define GPIO39_FFTXD_MD		(39 | GPIO_ALT_FN_2_OUT)
-#define GPIO40_FFDTR_MD		(40 | GPIO_ALT_FN_2_OUT)
-#define GPIO41_FFRTS_MD		(41 | GPIO_ALT_FN_2_OUT)
-#define GPIO41_KP_MKOUT7_MD	(41 | GPIO_ALT_FN_1_OUT)
-#define GPIO42_BTRXD_MD		(42 | GPIO_ALT_FN_1_IN)
-#define GPIO42_HWRXD_MD		(42 | GPIO_ALT_FN_3_IN)
-#define GPIO43_BTTXD_MD		(43 | GPIO_ALT_FN_2_OUT)
-#define GPIO43_HWTXD_MD		(43 | GPIO_ALT_FN_3_OUT)
-#define GPIO44_BTCTS_MD		(44 | GPIO_ALT_FN_1_IN)
-#define GPIO44_HWCTS_MD		(44 | GPIO_ALT_FN_3_IN)
-#define GPIO45_BTRTS_MD		(45 | GPIO_ALT_FN_2_OUT)
-#define GPIO45_HWRTS_MD		(45 | GPIO_ALT_FN_3_OUT)
-#define GPIO45_SYSCLK_AC97_MD	(45 | GPIO_ALT_FN_1_OUT)
-#define GPIO46_ICPRXD_MD	(46 | GPIO_ALT_FN_1_IN)
-#define GPIO46_STRXD_MD		(46 | GPIO_ALT_FN_2_IN)
-#define GPIO47_ICPTXD_MD	(47 | GPIO_ALT_FN_2_OUT)
-#define GPIO47_STTXD_MD		(47 | GPIO_ALT_FN_1_OUT)
-#define GPIO48_nPOE_MD		(48 | GPIO_ALT_FN_2_OUT)
-#define GPIO48_HWTXD_MD		(48 | GPIO_ALT_FN_1_OUT)
-#define GPIO48_nPOE_MD		(48 | GPIO_ALT_FN_2_OUT)
-#define GPIO49_HWRXD_MD		(49 | GPIO_ALT_FN_1_IN)
-#define GPIO49_nPWE_MD		(49 | GPIO_ALT_FN_2_OUT)
-#define GPIO50_nPIOR_MD		(50 | GPIO_ALT_FN_2_OUT)
-#define GPIO50_HWCTS_MD		(50 | GPIO_ALT_FN_1_IN)
-#define GPIO50_CIF_DD_3_MD	(50 | GPIO_ALT_FN_1_IN)
-#define GPIO51_nPIOW_MD		(51 | GPIO_ALT_FN_2_OUT)
-#define GPIO51_HWRTS_MD		(51 | GPIO_ALT_FN_1_OUT)
-#define GPIO51_CIF_DD_2_MD	(51 | GPIO_ALT_FN_1_IN)
-#define GPIO52_nPCE_1_MD	(52 | GPIO_ALT_FN_2_OUT)
-#define GPIO52_CIF_DD_4_MD	(52 | GPIO_ALT_FN_1_IN)
-#define GPIO53_nPCE_2_MD	(53 | GPIO_ALT_FN_2_OUT)
-#define GPIO53_MMCCLK_MD	(53 | GPIO_ALT_FN_1_OUT)
-#define GPIO53_CIF_MCLK_MD	(53 | GPIO_ALT_FN_2_OUT)
-#define GPIO54_MMCCLK_MD	(54 | GPIO_ALT_FN_1_OUT)
-#define GPIO54_nPCE_2_MD	(54 | GPIO_ALT_FN_2_OUT)
-#define GPIO54_pSKTSEL_MD	(54 | GPIO_ALT_FN_2_OUT)
-#define GPIO54_CIF_PCLK_MD	(54 | GPIO_ALT_FN_3_IN)
-#define GPIO55_nPREG_MD		(55 | GPIO_ALT_FN_2_OUT)
-#define GPIO55_CIF_DD_1_MD	(55 | GPIO_ALT_FN_1_IN)
-#define GPIO56_nPWAIT_MD	(56 | GPIO_ALT_FN_1_IN)
-#define GPIO57_nIOIS16_MD	(57 | GPIO_ALT_FN_1_IN)
-#define GPIO58_LDD_0_MD		(58 | GPIO_ALT_FN_2_OUT)
-#define GPIO59_LDD_1_MD		(59 | GPIO_ALT_FN_2_OUT)
-#define GPIO60_LDD_2_MD		(60 | GPIO_ALT_FN_2_OUT)
-#define GPIO61_LDD_3_MD		(61 | GPIO_ALT_FN_2_OUT)
-#define GPIO62_LDD_4_MD		(62 | GPIO_ALT_FN_2_OUT)
-#define GPIO63_LDD_5_MD		(63 | GPIO_ALT_FN_2_OUT)
-#define GPIO64_LDD_6_MD		(64 | GPIO_ALT_FN_2_OUT)
-#define GPIO65_LDD_7_MD		(65 | GPIO_ALT_FN_2_OUT)
-#define GPIO66_LDD_8_MD		(66 | GPIO_ALT_FN_2_OUT)
-#define GPIO66_MBREQ_MD		(66 | GPIO_ALT_FN_1_IN)
-#define GPIO67_LDD_9_MD		(67 | GPIO_ALT_FN_2_OUT)
-#define GPIO67_MMCCS0_MD	(67 | GPIO_ALT_FN_1_OUT)
-#define GPIO68_LDD_10_MD	(68 | GPIO_ALT_FN_2_OUT)
-#define GPIO68_MMCCS1_MD	(68 | GPIO_ALT_FN_1_OUT)
-#define GPIO69_LDD_11_MD	(69 | GPIO_ALT_FN_2_OUT)
-#define GPIO69_MMCCLK_MD	(69 | GPIO_ALT_FN_1_OUT)
-#define GPIO70_LDD_12_MD	(70 | GPIO_ALT_FN_2_OUT)
-#define GPIO70_RTCCLK_MD	(70 | GPIO_ALT_FN_1_OUT)
-#define GPIO71_LDD_13_MD	(71 | GPIO_ALT_FN_2_OUT)
-#define GPIO71_3_6MHz_MD	(71 | GPIO_ALT_FN_1_OUT)
-#define GPIO72_LDD_14_MD	(72 | GPIO_ALT_FN_2_OUT)
-#define GPIO72_32kHz_MD		(72 | GPIO_ALT_FN_1_OUT)
-#define GPIO73_LDD_15_MD	(73 | GPIO_ALT_FN_2_OUT)
-#define GPIO73_MBGNT_MD		(73 | GPIO_ALT_FN_1_OUT)
-#define GPIO74_LCD_FCLK_MD	(74 | GPIO_ALT_FN_2_OUT)
-#define GPIO75_LCD_LCLK_MD	(75 | GPIO_ALT_FN_2_OUT)
-#define GPIO76_LCD_PCLK_MD	(76 | GPIO_ALT_FN_2_OUT)
-#define GPIO77_LCD_ACBIAS_MD	(77 | GPIO_ALT_FN_2_OUT)
-#define GPIO78_nCS_2_MD		(78 | GPIO_ALT_FN_2_OUT)
-#define GPIO78_nPCE_2_MD	(78 | GPIO_ALT_FN_1_OUT)
-#define GPIO79_nCS_3_MD		(79 | GPIO_ALT_FN_2_OUT)
-#define GPIO79_pSKTSEL_MD	(79 | GPIO_ALT_FN_1_OUT)
-#define GPIO80_nCS_4_MD		(80 | GPIO_ALT_FN_2_OUT)
-#define GPIO81_NSSP_CLK_OUT	(81 | GPIO_ALT_FN_1_OUT)
-#define GPIO81_NSSP_CLK_IN	(81 | GPIO_ALT_FN_1_IN)
-#define GPIO81_CIF_DD_0_MD	(81 | GPIO_ALT_FN_2_IN)
-#define GPIO82_NSSP_FRM_OUT	(82 | GPIO_ALT_FN_1_OUT)
-#define GPIO82_NSSP_FRM_IN	(82 | GPIO_ALT_FN_1_IN)
-#define GPIO82_CIF_DD_5_MD	(82 | GPIO_ALT_FN_3_IN)
-#define GPIO83_NSSP_TX		(83 | GPIO_ALT_FN_1_OUT)
-#define GPIO83_NSSP_RX		(83 | GPIO_ALT_FN_2_IN)
-#define GPIO84_NSSP_TX		(84 | GPIO_ALT_FN_1_OUT)
-#define GPIO84_NSSP_RX		(84 | GPIO_ALT_FN_2_IN)
-#define GPIO84_CIF_FV_MD	(84 | GPIO_ALT_FN_3_IN)
-#define GPIO85_nPCE_1_MD	(85 | GPIO_ALT_FN_1_OUT)
-#define GPIO85_CIF_LV_MD	(85 | GPIO_ALT_FN_3_IN)
-#define GPIO86_nPCE_1_MD	(86 | GPIO_ALT_FN_1_OUT)
-#define GPIO92_MMCDAT0_MD	(92 | GPIO_ALT_FN_1_OUT)
-#define GPIO95_KP_MKIN6_MD	(95 | GPIO_ALT_FN_3_IN)
-#define GPIO96_KP_DKIN3_MD	(96 | GPIO_ALT_FN_1_IN)
-#define GPIO97_KP_MKIN3_MD	(97 | GPIO_ALT_FN_3_IN)
-#define GPIO100_KP_MKIN0_MD	(100 | GPIO_ALT_FN_1_IN)
-#define GPIO101_KP_MKIN1_MD	(101 | GPIO_ALT_FN_1_IN)
-#define GPIO102_nPCE_1_MD	(102 | GPIO_ALT_FN_1_OUT)
-#define GPIO102_KP_MKIN2_MD	(102 | GPIO_ALT_FN_1_IN)
-#define GPIO103_KP_MKOUT0_MD	(103 | GPIO_ALT_FN_2_OUT)
-#define GPIO104_pSKTSEL_MD	(104 | GPIO_ALT_FN_1_OUT)
-#define GPIO104_KP_MKOUT1_MD	(104 | GPIO_ALT_FN_2_OUT)
-#define GPIO105_KP_MKOUT2_MD	(105 | GPIO_ALT_FN_2_OUT)
-#define GPIO106_KP_MKOUT3_MD	(106 | GPIO_ALT_FN_2_OUT)
-#define GPIO107_KP_MKOUT4_MD	(107 | GPIO_ALT_FN_2_OUT)
-#define GPIO108_KP_MKOUT5_MD	(108 | GPIO_ALT_FN_2_OUT)
-#define GPIO109_MMCDAT1_MD	(109 | GPIO_ALT_FN_1_OUT)
-#define GPIO110_MMCDAT2_MD	(110 | GPIO_ALT_FN_1_OUT)
-#define GPIO110_MMCCS0_MD	(110 | GPIO_ALT_FN_1_OUT)
-#define GPIO111_MMCDAT3_MD	(111 | GPIO_ALT_FN_1_OUT)
-#define GPIO110_MMCCS1_MD	(111 | GPIO_ALT_FN_1_OUT)
-#define GPIO112_MMCCMD_MD	(112 | GPIO_ALT_FN_1_OUT)
-#define GPIO113_I2S_SYSCLK_MD	(113 | GPIO_ALT_FN_1_OUT)
-#define GPIO113_AC97_RESET_N_MD	(113 | GPIO_ALT_FN_2_OUT)
-#define GPIO117_I2CSCL_MD	(117 | GPIO_ALT_FN_1_IN)
-#define GPIO118_I2CSDA_MD	(118 | GPIO_ALT_FN_1_IN)
-
 /*
  * Power Manager
  */
diff --git a/include/asm-arm/arch-pxa/pxa2xx-gpio.h b/include/asm-arm/arch-pxa/pxa2xx-gpio.h
new file mode 100644
index 00000000000..fb418944753
--- /dev/null
+++ b/include/asm-arm/arch-pxa/pxa2xx-gpio.h
@@ -0,0 +1,304 @@
+#ifndef __ASM_ARCH_PXA2XX_GPIO_H
+#define __ASM_ARCH_PXA2XX_GPIO_H
+
+/* GPIO alternate function assignments */
+
+#define GPIO1_RST		1	/* reset */
+#define GPIO6_MMCCLK		6	/* MMC Clock */
+#define GPIO7_48MHz		7	/* 48 MHz clock output */
+#define GPIO8_MMCCS0		8	/* MMC Chip Select 0 */
+#define GPIO9_MMCCS1		9	/* MMC Chip Select 1 */
+#define GPIO10_RTCCLK		10	/* real time clock (1 Hz) */
+#define GPIO11_3_6MHz		11	/* 3.6 MHz oscillator out */
+#define GPIO12_32KHz		12	/* 32 kHz out */
+#define GPIO12_CIF_DD_7		12	/* Camera data pin 7 */
+#define GPIO13_MBGNT		13	/* memory controller grant */
+#define GPIO14_MBREQ		14	/* alternate bus master request */
+#define GPIO15_nCS_1		15	/* chip select 1 */
+#define GPIO16_PWM0		16	/* PWM0 output */
+#define GPIO17_PWM1		17	/* PWM1 output */
+#define GPIO17_CIF_DD_6		17	/* Camera data pin 6 */
+#define GPIO18_RDY		18	/* Ext. Bus Ready */
+#define GPIO19_DREQ1		19	/* External DMA Request */
+#define GPIO20_DREQ0		20	/* External DMA Request */
+#define GPIO23_SCLK		23	/* SSP clock */
+#define GPIO24_SFRM		24	/* SSP Frame */
+#define GPIO25_STXD		25	/* SSP transmit */
+#define GPIO26_SRXD		26	/* SSP receive */
+#define GPIO27_SEXTCLK		27	/* SSP ext_clk */
+#define GPIO28_BITCLK		28	/* AC97/I2S bit_clk */
+#define GPIO29_SDATA_IN		29	/* AC97 Sdata_in0 / I2S Sdata_in */
+#define GPIO30_SDATA_OUT	30	/* AC97/I2S Sdata_out */
+#define GPIO31_SYNC		31	/* AC97/I2S sync */
+#define GPIO32_SDATA_IN1	32	/* AC97 Sdata_in1 */
+#define GPIO32_SYSCLK		32	/* I2S System Clock */
+#define GPIO32_MMCCLK		32	/* MMC Clock (PXA270) */
+#define GPIO33_nCS_5		33	/* chip select 5 */
+#define GPIO34_FFRXD		34	/* FFUART receive */
+#define GPIO34_MMCCS0		34	/* MMC Chip Select 0 */
+#define GPIO35_FFCTS		35	/* FFUART Clear to send */
+#define GPIO36_FFDCD		36	/* FFUART Data carrier detect */
+#define GPIO37_FFDSR		37	/* FFUART data set ready */
+#define GPIO38_FFRI		38	/* FFUART Ring Indicator */
+#define GPIO39_MMCCS1		39	/* MMC Chip Select 1 */
+#define GPIO39_FFTXD		39	/* FFUART transmit data */
+#define GPIO40_FFDTR		40	/* FFUART data terminal Ready */
+#define GPIO41_FFRTS		41	/* FFUART request to send */
+#define GPIO42_BTRXD		42	/* BTUART receive data */
+#define GPIO42_HWRXD		42	/* HWUART receive data */
+#define GPIO43_BTTXD		43	/* BTUART transmit data */
+#define GPIO43_HWTXD		43	/* HWUART transmit data */
+#define GPIO44_BTCTS		44	/* BTUART clear to send */
+#define GPIO44_HWCTS		44	/* HWUART clear to send */
+#define GPIO45_BTRTS		45	/* BTUART request to send */
+#define GPIO45_HWRTS		45	/* HWUART request to send */
+#define GPIO45_AC97_SYSCLK	45	/* AC97 System Clock */
+#define GPIO46_ICPRXD		46	/* ICP receive data */
+#define GPIO46_STRXD		46	/* STD_UART receive data */
+#define GPIO47_ICPTXD		47	/* ICP transmit data */
+#define GPIO47_STTXD		47	/* STD_UART transmit data */
+#define GPIO48_nPOE		48	/* Output Enable for Card Space */
+#define GPIO49_nPWE		49	/* Write Enable for Card Space */
+#define GPIO50_nPIOR		50	/* I/O Read for Card Space */
+#define GPIO50_CIF_DD_3		50	/* Camera data pin 3 */
+#define GPIO51_nPIOW		51	/* I/O Write for Card Space */
+#define GPIO51_CIF_DD_2		51	/* Camera data pin 2 */
+#define GPIO52_nPCE_1		52	/* Card Enable for Card Space */
+#define GPIO52_CIF_DD_4		52	/* Camera data pin 4 */
+#define GPIO53_nPCE_2		53	/* Card Enable for Card Space */
+#define GPIO53_MMCCLK		53	/* MMC Clock */
+#define GPIO53_CIF_MCLK		53	/* Camera Master Clock */
+#define GPIO54_MMCCLK		54	/* MMC Clock */
+#define GPIO54_pSKTSEL		54	/* Socket Select for Card Space */
+#define GPIO54_nPCE_2		54	/* Card Enable for Card Space (PXA27x) */
+#define GPIO54_CIF_PCLK		54	/* Camera Pixel Clock */
+#define GPIO55_nPREG		55	/* Card Address bit 26 */
+#define GPIO55_CIF_DD_1		55	/* Camera data pin 1 */
+#define GPIO56_nPWAIT		56	/* Wait signal for Card Space */
+#define GPIO57_nIOIS16		57	/* Bus Width select for I/O Card Space */
+#define GPIO58_LDD_0		58	/* LCD data pin 0 */
+#define GPIO59_LDD_1		59	/* LCD data pin 1 */
+#define GPIO60_LDD_2		60	/* LCD data pin 2 */
+#define GPIO61_LDD_3		61	/* LCD data pin 3 */
+#define GPIO62_LDD_4		62	/* LCD data pin 4 */
+#define GPIO63_LDD_5		63	/* LCD data pin 5 */
+#define GPIO64_LDD_6		64	/* LCD data pin 6 */
+#define GPIO65_LDD_7		65	/* LCD data pin 7 */
+#define GPIO66_LDD_8		66	/* LCD data pin 8 */
+#define GPIO66_MBREQ		66	/* alternate bus master req */
+#define GPIO67_LDD_9		67	/* LCD data pin 9 */
+#define GPIO67_MMCCS0		67	/* MMC Chip Select 0 */
+#define GPIO68_LDD_10		68	/* LCD data pin 10 */
+#define GPIO68_MMCCS1		68	/* MMC Chip Select 1 */
+#define GPIO69_LDD_11		69	/* LCD data pin 11 */
+#define GPIO69_MMCCLK		69	/* MMC_CLK */
+#define GPIO70_LDD_12		70	/* LCD data pin 12 */
+#define GPIO70_RTCCLK		70	/* Real Time clock (1 Hz) */
+#define GPIO71_LDD_13		71	/* LCD data pin 13 */
+#define GPIO71_3_6MHz		71	/* 3.6 MHz Oscillator clock */
+#define GPIO72_LDD_14		72	/* LCD data pin 14 */
+#define GPIO72_32kHz		72	/* 32 kHz clock */
+#define GPIO73_LDD_15		73	/* LCD data pin 15 */
+#define GPIO73_MBGNT		73	/* Memory controller grant */
+#define GPIO74_LCD_FCLK		74	/* LCD Frame clock */
+#define GPIO75_LCD_LCLK		75	/* LCD line clock */
+#define GPIO76_LCD_PCLK		76	/* LCD Pixel clock */
+#define GPIO77_LCD_ACBIAS	77	/* LCD AC Bias */
+#define GPIO78_nCS_2		78	/* chip select 2 */
+#define GPIO79_nCS_3		79	/* chip select 3 */
+#define GPIO80_nCS_4		80	/* chip select 4 */
+#define GPIO81_NSCLK		81	/* NSSP clock */
+#define GPIO81_CIF_DD_0		81	/* Camera data pin 0 */
+#define GPIO82_NSFRM		82	/* NSSP Frame */
+#define GPIO82_CIF_DD_5		82	/* Camera data pin 5 */
+#define GPIO83_NSTXD		83	/* NSSP transmit */
+#define GPIO84_NSRXD		84	/* NSSP receive */
+#define GPIO84_CIF_FV		84	/* Camera frame start signal */
+#define GPIO85_nPCE_1		85	/* Card Enable for Card Space (PXA27x) */
+#define GPIO85_CIF_LV		85	/* Camera line start signal */
+#define GPIO92_MMCDAT0		92	/* MMC DAT0 (PXA27x) */
+#define GPIO102_nPCE_1		102	/* PCMCIA (PXA27x) */
+#define GPIO109_MMCDAT1		109	/* MMC DAT1 (PXA27x) */
+#define GPIO110_MMCDAT2		110	/* MMC DAT2 (PXA27x) */
+#define GPIO110_MMCCS0		110	/* MMC Chip Select 0 (PXA27x) */
+#define GPIO111_MMCDAT3		111	/* MMC DAT3 (PXA27x) */
+#define GPIO111_MMCCS1		111	/* MMC Chip Select 1 (PXA27x) */
+#define GPIO112_MMCCMD		112	/* MMC CMD (PXA27x) */
+#define GPIO113_I2S_SYSCLK	113	/* I2S System Clock (PXA27x) */
+#define GPIO113_AC97_RESET_N	113	/* AC97 NRESET on (PXA27x) */
+
+/* GPIO alternate function mode & direction */
+
+#define GPIO_IN			0x000
+#define GPIO_OUT		0x080
+#define GPIO_ALT_FN_1_IN	0x100
+#define GPIO_ALT_FN_1_OUT	0x180
+#define GPIO_ALT_FN_2_IN	0x200
+#define GPIO_ALT_FN_2_OUT	0x280
+#define GPIO_ALT_FN_3_IN	0x300
+#define GPIO_ALT_FN_3_OUT	0x380
+#define GPIO_MD_MASK_NR		0x07f
+#define GPIO_MD_MASK_DIR	0x080
+#define GPIO_MD_MASK_FN		0x300
+#define GPIO_DFLT_LOW		0x400
+#define GPIO_DFLT_HIGH		0x800
+
+#define GPIO1_RTS_MD		( 1 | GPIO_ALT_FN_1_IN)
+#define GPIO6_MMCCLK_MD		( 6 | GPIO_ALT_FN_1_OUT)
+#define GPIO7_48MHz_MD		( 7 | GPIO_ALT_FN_1_OUT)
+#define GPIO8_MMCCS0_MD		( 8 | GPIO_ALT_FN_1_OUT)
+#define GPIO9_MMCCS1_MD		( 9 | GPIO_ALT_FN_1_OUT)
+#define GPIO10_RTCCLK_MD	(10 | GPIO_ALT_FN_1_OUT)
+#define GPIO11_3_6MHz_MD	(11 | GPIO_ALT_FN_1_OUT)
+#define GPIO12_32KHz_MD		(12 | GPIO_ALT_FN_1_OUT)
+#define GPIO12_CIF_DD_7_MD	(12 | GPIO_ALT_FN_2_IN)
+#define GPIO13_MBGNT_MD		(13 | GPIO_ALT_FN_2_OUT)
+#define GPIO14_MBREQ_MD		(14 | GPIO_ALT_FN_1_IN)
+#define GPIO15_nCS_1_MD		(15 | GPIO_ALT_FN_2_OUT)
+#define GPIO16_PWM0_MD		(16 | GPIO_ALT_FN_2_OUT)
+#define GPIO17_PWM1_MD		(17 | GPIO_ALT_FN_2_OUT)
+#define GPIO17_CIF_DD_6_MD	(17 | GPIO_ALT_FN_2_IN)
+#define GPIO18_RDY_MD		(18 | GPIO_ALT_FN_1_IN)
+#define GPIO19_DREQ1_MD		(19 | GPIO_ALT_FN_1_IN)
+#define GPIO20_DREQ0_MD		(20 | GPIO_ALT_FN_1_IN)
+#define GPIO23_SCLK_MD		(23 | GPIO_ALT_FN_2_OUT)
+#define GPIO24_SFRM_MD		(24 | GPIO_ALT_FN_2_OUT)
+#define GPIO25_STXD_MD		(25 | GPIO_ALT_FN_2_OUT)
+#define GPIO26_SRXD_MD		(26 | GPIO_ALT_FN_1_IN)
+#define GPIO27_SEXTCLK_MD	(27 | GPIO_ALT_FN_1_IN)
+#define GPIO28_BITCLK_AC97_MD	(28 | GPIO_ALT_FN_1_IN)
+#define GPIO28_BITCLK_IN_I2S_MD	(28 | GPIO_ALT_FN_2_IN)
+#define GPIO28_BITCLK_OUT_I2S_MD	(28 | GPIO_ALT_FN_1_OUT)
+#define GPIO29_SDATA_IN_AC97_MD	(29 | GPIO_ALT_FN_1_IN)
+#define GPIO29_SDATA_IN_I2S_MD	(29 | GPIO_ALT_FN_2_IN)
+#define GPIO30_SDATA_OUT_AC97_MD	(30 | GPIO_ALT_FN_2_OUT)
+#define GPIO30_SDATA_OUT_I2S_MD	(30 | GPIO_ALT_FN_1_OUT)
+#define GPIO31_SYNC_I2S_MD	(31 | GPIO_ALT_FN_1_OUT)
+#define GPIO31_SYNC_AC97_MD	(31 | GPIO_ALT_FN_2_OUT)
+#define GPIO32_SDATA_IN1_AC97_MD	(32 | GPIO_ALT_FN_1_IN)
+#define GPIO32_SYSCLK_I2S_MD	(32 | GPIO_ALT_FN_1_OUT)
+#define GPIO32_MMCCLK_MD	(32 | GPIO_ALT_FN_2_OUT)
+#define GPIO33_nCS_5_MD		(33 | GPIO_ALT_FN_2_OUT)
+#define GPIO34_FFRXD_MD		(34 | GPIO_ALT_FN_1_IN)
+#define GPIO34_MMCCS0_MD	(34 | GPIO_ALT_FN_2_OUT)
+#define GPIO35_FFCTS_MD		(35 | GPIO_ALT_FN_1_IN)
+#define GPIO35_KP_MKOUT6_MD	(35 | GPIO_ALT_FN_2_OUT)
+#define GPIO36_FFDCD_MD		(36 | GPIO_ALT_FN_1_IN)
+#define GPIO37_FFDSR_MD		(37 | GPIO_ALT_FN_1_IN)
+#define GPIO38_FFRI_MD		(38 | GPIO_ALT_FN_1_IN)
+#define GPIO39_MMCCS1_MD	(39 | GPIO_ALT_FN_1_OUT)
+#define GPIO39_FFTXD_MD		(39 | GPIO_ALT_FN_2_OUT)
+#define GPIO40_FFDTR_MD		(40 | GPIO_ALT_FN_2_OUT)
+#define GPIO41_FFRTS_MD		(41 | GPIO_ALT_FN_2_OUT)
+#define GPIO41_KP_MKOUT7_MD	(41 | GPIO_ALT_FN_1_OUT)
+#define GPIO42_BTRXD_MD		(42 | GPIO_ALT_FN_1_IN)
+#define GPIO42_HWRXD_MD		(42 | GPIO_ALT_FN_3_IN)
+#define GPIO43_BTTXD_MD		(43 | GPIO_ALT_FN_2_OUT)
+#define GPIO43_HWTXD_MD		(43 | GPIO_ALT_FN_3_OUT)
+#define GPIO44_BTCTS_MD		(44 | GPIO_ALT_FN_1_IN)
+#define GPIO44_HWCTS_MD		(44 | GPIO_ALT_FN_3_IN)
+#define GPIO45_BTRTS_MD		(45 | GPIO_ALT_FN_2_OUT)
+#define GPIO45_HWRTS_MD		(45 | GPIO_ALT_FN_3_OUT)
+#define GPIO45_SYSCLK_AC97_MD	(45 | GPIO_ALT_FN_1_OUT)
+#define GPIO46_ICPRXD_MD	(46 | GPIO_ALT_FN_1_IN)
+#define GPIO46_STRXD_MD		(46 | GPIO_ALT_FN_2_IN)
+#define GPIO47_ICPTXD_MD	(47 | GPIO_ALT_FN_2_OUT)
+#define GPIO47_STTXD_MD		(47 | GPIO_ALT_FN_1_OUT)
+#define GPIO48_nPOE_MD		(48 | GPIO_ALT_FN_2_OUT)
+#define GPIO48_HWTXD_MD		(48 | GPIO_ALT_FN_1_OUT)
+#define GPIO48_nPOE_MD		(48 | GPIO_ALT_FN_2_OUT)
+#define GPIO49_HWRXD_MD		(49 | GPIO_ALT_FN_1_IN)
+#define GPIO49_nPWE_MD		(49 | GPIO_ALT_FN_2_OUT)
+#define GPIO50_nPIOR_MD		(50 | GPIO_ALT_FN_2_OUT)
+#define GPIO50_HWCTS_MD		(50 | GPIO_ALT_FN_1_IN)
+#define GPIO50_CIF_DD_3_MD	(50 | GPIO_ALT_FN_1_IN)
+#define GPIO51_nPIOW_MD		(51 | GPIO_ALT_FN_2_OUT)
+#define GPIO51_HWRTS_MD		(51 | GPIO_ALT_FN_1_OUT)
+#define GPIO51_CIF_DD_2_MD	(51 | GPIO_ALT_FN_1_IN)
+#define GPIO52_nPCE_1_MD	(52 | GPIO_ALT_FN_2_OUT)
+#define GPIO52_CIF_DD_4_MD	(52 | GPIO_ALT_FN_1_IN)
+#define GPIO53_nPCE_2_MD	(53 | GPIO_ALT_FN_2_OUT)
+#define GPIO53_MMCCLK_MD	(53 | GPIO_ALT_FN_1_OUT)
+#define GPIO53_CIF_MCLK_MD	(53 | GPIO_ALT_FN_2_OUT)
+#define GPIO54_MMCCLK_MD	(54 | GPIO_ALT_FN_1_OUT)
+#define GPIO54_nPCE_2_MD	(54 | GPIO_ALT_FN_2_OUT)
+#define GPIO54_pSKTSEL_MD	(54 | GPIO_ALT_FN_2_OUT)
+#define GPIO54_CIF_PCLK_MD	(54 | GPIO_ALT_FN_3_IN)
+#define GPIO55_nPREG_MD		(55 | GPIO_ALT_FN_2_OUT)
+#define GPIO55_CIF_DD_1_MD	(55 | GPIO_ALT_FN_1_IN)
+#define GPIO56_nPWAIT_MD	(56 | GPIO_ALT_FN_1_IN)
+#define GPIO57_nIOIS16_MD	(57 | GPIO_ALT_FN_1_IN)
+#define GPIO58_LDD_0_MD		(58 | GPIO_ALT_FN_2_OUT)
+#define GPIO59_LDD_1_MD		(59 | GPIO_ALT_FN_2_OUT)
+#define GPIO60_LDD_2_MD		(60 | GPIO_ALT_FN_2_OUT)
+#define GPIO61_LDD_3_MD		(61 | GPIO_ALT_FN_2_OUT)
+#define GPIO62_LDD_4_MD		(62 | GPIO_ALT_FN_2_OUT)
+#define GPIO63_LDD_5_MD		(63 | GPIO_ALT_FN_2_OUT)
+#define GPIO64_LDD_6_MD		(64 | GPIO_ALT_FN_2_OUT)
+#define GPIO65_LDD_7_MD		(65 | GPIO_ALT_FN_2_OUT)
+#define GPIO66_LDD_8_MD		(66 | GPIO_ALT_FN_2_OUT)
+#define GPIO66_MBREQ_MD		(66 | GPIO_ALT_FN_1_IN)
+#define GPIO67_LDD_9_MD		(67 | GPIO_ALT_FN_2_OUT)
+#define GPIO67_MMCCS0_MD	(67 | GPIO_ALT_FN_1_OUT)
+#define GPIO68_LDD_10_MD	(68 | GPIO_ALT_FN_2_OUT)
+#define GPIO68_MMCCS1_MD	(68 | GPIO_ALT_FN_1_OUT)
+#define GPIO69_LDD_11_MD	(69 | GPIO_ALT_FN_2_OUT)
+#define GPIO69_MMCCLK_MD	(69 | GPIO_ALT_FN_1_OUT)
+#define GPIO70_LDD_12_MD	(70 | GPIO_ALT_FN_2_OUT)
+#define GPIO70_RTCCLK_MD	(70 | GPIO_ALT_FN_1_OUT)
+#define GPIO71_LDD_13_MD	(71 | GPIO_ALT_FN_2_OUT)
+#define GPIO71_3_6MHz_MD	(71 | GPIO_ALT_FN_1_OUT)
+#define GPIO72_LDD_14_MD	(72 | GPIO_ALT_FN_2_OUT)
+#define GPIO72_32kHz_MD		(72 | GPIO_ALT_FN_1_OUT)
+#define GPIO73_LDD_15_MD	(73 | GPIO_ALT_FN_2_OUT)
+#define GPIO73_MBGNT_MD		(73 | GPIO_ALT_FN_1_OUT)
+#define GPIO74_LCD_FCLK_MD	(74 | GPIO_ALT_FN_2_OUT)
+#define GPIO75_LCD_LCLK_MD	(75 | GPIO_ALT_FN_2_OUT)
+#define GPIO76_LCD_PCLK_MD	(76 | GPIO_ALT_FN_2_OUT)
+#define GPIO77_LCD_ACBIAS_MD	(77 | GPIO_ALT_FN_2_OUT)
+#define GPIO78_nCS_2_MD		(78 | GPIO_ALT_FN_2_OUT)
+#define GPIO78_nPCE_2_MD	(78 | GPIO_ALT_FN_1_OUT)
+#define GPIO79_nCS_3_MD		(79 | GPIO_ALT_FN_2_OUT)
+#define GPIO79_pSKTSEL_MD	(79 | GPIO_ALT_FN_1_OUT)
+#define GPIO80_nCS_4_MD		(80 | GPIO_ALT_FN_2_OUT)
+#define GPIO81_NSSP_CLK_OUT	(81 | GPIO_ALT_FN_1_OUT)
+#define GPIO81_NSSP_CLK_IN	(81 | GPIO_ALT_FN_1_IN)
+#define GPIO81_CIF_DD_0_MD	(81 | GPIO_ALT_FN_2_IN)
+#define GPIO82_NSSP_FRM_OUT	(82 | GPIO_ALT_FN_1_OUT)
+#define GPIO82_NSSP_FRM_IN	(82 | GPIO_ALT_FN_1_IN)
+#define GPIO82_CIF_DD_5_MD	(82 | GPIO_ALT_FN_3_IN)
+#define GPIO83_NSSP_TX		(83 | GPIO_ALT_FN_1_OUT)
+#define GPIO83_NSSP_RX		(83 | GPIO_ALT_FN_2_IN)
+#define GPIO84_NSSP_TX		(84 | GPIO_ALT_FN_1_OUT)
+#define GPIO84_NSSP_RX		(84 | GPIO_ALT_FN_2_IN)
+#define GPIO84_CIF_FV_MD	(84 | GPIO_ALT_FN_3_IN)
+#define GPIO85_nPCE_1_MD	(85 | GPIO_ALT_FN_1_OUT)
+#define GPIO85_CIF_LV_MD	(85 | GPIO_ALT_FN_3_IN)
+#define GPIO86_nPCE_1_MD	(86 | GPIO_ALT_FN_1_OUT)
+#define GPIO92_MMCDAT0_MD	(92 | GPIO_ALT_FN_1_OUT)
+#define GPIO95_KP_MKIN6_MD	(95 | GPIO_ALT_FN_3_IN)
+#define GPIO96_KP_DKIN3_MD	(96 | GPIO_ALT_FN_1_IN)
+#define GPIO97_KP_MKIN3_MD	(97 | GPIO_ALT_FN_3_IN)
+#define GPIO100_KP_MKIN0_MD	(100 | GPIO_ALT_FN_1_IN)
+#define GPIO101_KP_MKIN1_MD	(101 | GPIO_ALT_FN_1_IN)
+#define GPIO102_nPCE_1_MD	(102 | GPIO_ALT_FN_1_OUT)
+#define GPIO102_KP_MKIN2_MD	(102 | GPIO_ALT_FN_1_IN)
+#define GPIO103_KP_MKOUT0_MD	(103 | GPIO_ALT_FN_2_OUT)
+#define GPIO104_pSKTSEL_MD	(104 | GPIO_ALT_FN_1_OUT)
+#define GPIO104_KP_MKOUT1_MD	(104 | GPIO_ALT_FN_2_OUT)
+#define GPIO105_KP_MKOUT2_MD	(105 | GPIO_ALT_FN_2_OUT)
+#define GPIO106_KP_MKOUT3_MD	(106 | GPIO_ALT_FN_2_OUT)
+#define GPIO107_KP_MKOUT4_MD	(107 | GPIO_ALT_FN_2_OUT)
+#define GPIO108_KP_MKOUT5_MD	(108 | GPIO_ALT_FN_2_OUT)
+#define GPIO109_MMCDAT1_MD	(109 | GPIO_ALT_FN_1_OUT)
+#define GPIO110_MMCDAT2_MD	(110 | GPIO_ALT_FN_1_OUT)
+#define GPIO110_MMCCS0_MD	(110 | GPIO_ALT_FN_1_OUT)
+#define GPIO111_MMCDAT3_MD	(111 | GPIO_ALT_FN_1_OUT)
+#define GPIO110_MMCCS1_MD	(111 | GPIO_ALT_FN_1_OUT)
+#define GPIO112_MMCCMD_MD	(112 | GPIO_ALT_FN_1_OUT)
+#define GPIO113_I2S_SYSCLK_MD	(113 | GPIO_ALT_FN_1_OUT)
+#define GPIO113_AC97_RESET_N_MD	(113 | GPIO_ALT_FN_2_OUT)
+#define GPIO117_I2CSCL_MD	(117 | GPIO_ALT_FN_1_IN)
+#define GPIO118_I2CSDA_MD	(118 | GPIO_ALT_FN_1_IN)
+
+#endif /* __ASM_ARCH_PXA2XX_GPIO_H */
diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c
index fd7bc865e67..8704e2825b1 100644
--- a/sound/arm/pxa2xx-ac97.c
+++ b/sound/arm/pxa2xx-ac97.c
@@ -28,6 +28,7 @@
 #include <linux/mutex.h>
 #include <asm/hardware.h>
 #include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
 #include <asm/arch/audio.h>
 
 #include "pxa2xx-pcm.h"
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
index 711b916e58a..fe9c297ae6f 100644
--- a/sound/soc/pxa/pxa2xx-ac97.c
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -28,6 +28,7 @@
 #include <linux/mutex.h>
 #include <asm/hardware.h>
 #include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
 #include <asm/arch/audio.h>
 
 #include "pxa2xx-pcm.h"
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
index 692b9000248..42507103097 100644
--- a/sound/soc/pxa/pxa2xx-i2s.c
+++ b/sound/soc/pxa/pxa2xx-i2s.c
@@ -25,6 +25,7 @@
 
 #include <asm/hardware.h>
 #include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
 #include <asm/arch/audio.h>
 
 #include "pxa2xx-pcm.h"
-- 
cgit v1.2.3-70-g09d2


From b907ef688ddb6d73fc1c83b6fbcd62f5c2c2a14f Mon Sep 17 00:00:00 2001
From: Mark Brown <broonie@sirena.org.uk>
Date: Tue, 15 Apr 2008 16:12:44 +0100
Subject: [ARM] 4977/2: soc - pxa2xx-ac97 - Add missing clk_enable()

Add missing clk_enable()

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Acked-by: eric miao <eric.y.miao@gmail.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 sound/soc/pxa/pxa2xx-ac97.c | 1 +
 1 file changed, 1 insertion(+)

(limited to 'sound')

diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
index fe9c297ae6f..e1737999880 100644
--- a/sound/soc/pxa/pxa2xx-ac97.c
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -314,6 +314,7 @@ static int pxa2xx_ac97_probe(struct platform_device *pdev)
 		ac97_clk = NULL;
 		goto err_irq;
 	}
+	clk_enable(ac97_clk);
 	return 0;
 
  err_irq:
-- 
cgit v1.2.3-70-g09d2


From 3f76d9841e9cf6dd969ff3aec96476dced9c53f8 Mon Sep 17 00:00:00 2001
From: Tobias Klauser <tklauser@distanz.ch>
Date: Mon, 21 Apr 2008 22:25:51 +0000
Subject: ALSA: Storage class should be before const qualifier

The C99 specification states in section 6.11.5:

The placement of a storage-class specifier other than at the
beginning of the declaration specifiers in a declaration is an
obsolescent feature.

Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
Signed-off-by: Jesper Juhl <jesper.juhl@gmail.com>
---
 sound/pci/sis7019.c | 6 +++---
 sound/ppc/snd_ps3.c | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c
index dcd7cd01046..742f1180c39 100644
--- a/sound/pci/sis7019.c
+++ b/sound/pci/sis7019.c
@@ -920,7 +920,7 @@ static unsigned short sis_ac97_rw(struct sis7019 *sis, int codec, u32 cmd)
 	u16 status;
 	u16 rdy;
 	int count;
-	const static u16 codec_ready[3] = {
+	static const u16 codec_ready[3] = {
 		SIS_AC97_STATUS_CODEC_READY,
 		SIS_AC97_STATUS_CODEC2_READY,
 		SIS_AC97_STATUS_CODEC3_READY,
@@ -984,7 +984,7 @@ timeout:
 static void sis_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
 				unsigned short val)
 {
-	const static u32 cmd[3] = {
+	static const u32 cmd[3] = {
 		SIS_AC97_CMD_CODEC_WRITE,
 		SIS_AC97_CMD_CODEC2_WRITE,
 		SIS_AC97_CMD_CODEC3_WRITE,
@@ -995,7 +995,7 @@ static void sis_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
 
 static unsigned short sis_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
 {
-	const static u32 cmd[3] = {
+	static const u32 cmd[3] = {
 		SIS_AC97_CMD_CODEC_READ,
 		SIS_AC97_CMD_CODEC2_READ,
 		SIS_AC97_CMD_CODEC3_READ,
diff --git a/sound/ppc/snd_ps3.c b/sound/ppc/snd_ps3.c
index d8d0b4b2395..20d0e328288 100644
--- a/sound/ppc/snd_ps3.c
+++ b/sound/ppc/snd_ps3.c
@@ -137,7 +137,7 @@ static inline void update_mask_reg(unsigned int reg, u32 mask, u32 or_val)
 /*
  * ALSA defs
  */
-const static struct snd_pcm_hardware snd_ps3_pcm_hw = {
+static const struct snd_pcm_hardware snd_ps3_pcm_hw = {
 	.info = (SNDRV_PCM_INFO_MMAP |
 		 SNDRV_PCM_INFO_NONINTERLEAVED |
 		 SNDRV_PCM_INFO_MMAP_VALID),
-- 
cgit v1.2.3-70-g09d2


From 102646085ab530a0e155d2bde424589b83ef5a89 Mon Sep 17 00:00:00 2001
From: Mike Montour <mail@mmontour.net>
Date: Fri, 1 Feb 2008 13:12:12 +0100
Subject: [ALSA] soc - Mono voice playback volume for WM8753

Voice playback volume is in register bits 0:2, not 4:6.

From: Mike Montour <mail@mmontour.net>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: Werner Almesberger <werner@openmoko.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/soc/codecs/wm8753.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'sound')

diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index ddd9c71b3fd..02882758415 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -279,7 +279,7 @@ SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8753_LOUT2V, WM8753_ROUT2V, 7, 1, 0
 
 SOC_SINGLE("Mono Bypass Playback Volume", WM8753_MOUTM1, 4, 7, 1),
 SOC_SINGLE("Mono Sidetone Playback Volume", WM8753_MOUTM2, 4, 7, 1),
-SOC_SINGLE("Mono Voice Playback Volume", WM8753_MOUTM2, 4, 7, 1),
+SOC_SINGLE("Mono Voice Playback Volume", WM8753_MOUTM2, 0, 7, 1),
 SOC_SINGLE("Mono Playback ZC Switch", WM8753_MOUTV, 7, 1, 0),
 
 SOC_ENUM("Bass Boost", wm8753_enum[0]),
-- 
cgit v1.2.3-70-g09d2


From dc952e693e3653d0fa50ee1986a47d88de3465b7 Mon Sep 17 00:00:00 2001
From: Kristoffer Ericson <kristoffer.ericson@gmail.com>
Date: Fri, 1 Feb 2008 13:16:10 +0100
Subject: [ALSA] Add SUPERH depends to sound/soc/sh/Kconfig

Currently you will see an empty "SoC Audio support for SuperH" menu
when building for other archs (example pxa).
This patch adds "depends on SUPERH" to remove that empty menu.

Signed-off-by: Kristoffer Ericson <kristoffer.ericson@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/soc/sh/Kconfig | 1 +
 1 file changed, 1 insertion(+)

(limited to 'sound')

diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig
index f03220d23e7..4c1e013381c 100644
--- a/sound/soc/sh/Kconfig
+++ b/sound/soc/sh/Kconfig
@@ -1,4 +1,5 @@
 menu "SoC Audio support for SuperH"
+	depends on SUPERH
 
 config SND_SOC_PCM_SH7760
 	tristate "SoC Audio support for Renesas SH7760"
-- 
cgit v1.2.3-70-g09d2


From bf277785d6921b8a9f8339ad5ad632aef6cae73c Mon Sep 17 00:00:00 2001
From: Tobin Davis <tdavis@dsl-only.net>
Date: Sun, 3 Feb 2008 20:31:47 +0100
Subject: [ALSA] HDA - Add support for the OQO Model 2

This patch adds support for the OQO Model 2 Ultra Mobile PC.

Signed-off-by: Tobin Davis <tdavis@dsl-only.net>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_sigmatel.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index caf48edaa92..4c3c4e6ce3d 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -39,6 +39,7 @@
 
 enum {
 	STAC_REF,
+	STAC_9200_OQO,
 	STAC_9200_DELL_D21,
 	STAC_9200_DELL_D22,
 	STAC_9200_DELL_D23,
@@ -1052,9 +1053,15 @@ static unsigned int dell9200_m27_pin_configs[8] = {
 	0x90170310, 0x04a11020, 0x90170310, 0x40f003fc,
 };
 
+static unsigned int oqo9200_pin_configs[8] = {
+	0x40c000f0, 0x404000f1, 0x0221121f, 0x02211210,
+	0x90170111, 0x90a70120, 0x400000f2, 0x400000f3,
+};
+
 
 static unsigned int *stac9200_brd_tbl[STAC_9200_MODELS] = {
 	[STAC_REF] = ref9200_pin_configs,
+	[STAC_9200_OQO] = oqo9200_pin_configs,
 	[STAC_9200_DELL_D21] = dell9200_d21_pin_configs,
 	[STAC_9200_DELL_D22] = dell9200_d22_pin_configs,
 	[STAC_9200_DELL_D23] = dell9200_d23_pin_configs,
@@ -1069,6 +1076,7 @@ static unsigned int *stac9200_brd_tbl[STAC_9200_MODELS] = {
 
 static const char *stac9200_models[STAC_9200_MODELS] = {
 	[STAC_REF] = "ref",
+	[STAC_9200_OQO] = "oqo",
 	[STAC_9200_DELL_D21] = "dell-d21",
 	[STAC_9200_DELL_D22] = "dell-d22",
 	[STAC_9200_DELL_D23] = "dell-d23",
@@ -1153,6 +1161,8 @@ static struct snd_pci_quirk stac9200_cfg_tbl[] = {
 		      STAC_9200_GATEWAY),
 	SND_PCI_QUIRK(0x107b, 0x0318, "Gateway ML3019, MT3707",
 		      STAC_9200_GATEWAY),
+	/* OQO Mobile */
+	SND_PCI_QUIRK(0x1106, 0x3288, "OQO Model 2", STAC_9200_OQO),
 	{} /* terminator */
 };
 
@@ -3147,7 +3157,8 @@ static int patch_stac9200(struct hda_codec *codec)
 	spec->num_adcs = 1;
 	spec->num_pwrs = 0;
 
-	if (spec->board_config == STAC_9200_GATEWAY)
+	if (spec->board_config == STAC_9200_GATEWAY ||
+	    spec->board_config == STAC_9200_OQO)
 		spec->init = stac9200_eapd_init;
 	else
 		spec->init = stac9200_core_init;
-- 
cgit v1.2.3-70-g09d2


From 09f99701393c7b66bde01df6c292fe5d9f843033 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 4 Feb 2008 12:31:13 +0100
Subject: [ALSA] hda-codec - Allow multiple SPDIF devices

The current code doesn't allow multiple SPDIF devices, and causes
errors when multiple SPDIF devices are found (e.g. SPDIF out and HDMI).
This patch allows multiple SPDIF devices by incrementing the index
automatically.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/hda_codec.c | 35 +++++++++++++++++++++++++++++++++--
 1 file changed, 33 insertions(+), 2 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 37c413923db..ab3bb7997cd 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -1037,16 +1037,24 @@ void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
 }
 
 /* find a mixer control element with the given name */
-struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
-					    const char *name)
+static struct snd_kcontrol *
+_snd_hda_find_mixer_ctl(struct hda_codec *codec,
+			const char *name, int idx)
 {
 	struct snd_ctl_elem_id id;
 	memset(&id, 0, sizeof(id));
 	id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+	id.index = idx;
 	strcpy(id.name, name);
 	return snd_ctl_find_id(codec->bus->card, &id);
 }
 
+struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
+					    const char *name)
+{
+	return _snd_hda_find_mixer_ctl(codec, name, 0);
+}
+
 /* create a virtual master control and add slaves */
 int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
 			unsigned int *tlv, const char **slaves)
@@ -1481,6 +1489,8 @@ static struct snd_kcontrol_new dig_mixes[] = {
 	{ } /* end */
 };
 
+#define SPDIF_MAX_IDX	4	/* 4 instances should be enough to probe */
+
 /**
  * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls
  * @codec: the HDA codec
@@ -1496,9 +1506,20 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
 	int err;
 	struct snd_kcontrol *kctl;
 	struct snd_kcontrol_new *dig_mix;
+	int idx;
 
+	for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
+		if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Playback Switch",
+					     idx))
+			break;
+	}
+	if (idx >= SPDIF_MAX_IDX) {
+		printk(KERN_ERR "hda_codec: too many IEC958 outputs\n");
+		return -EBUSY;
+	}
 	for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
 		kctl = snd_ctl_new1(dig_mix, codec);
+		kctl->id.index = idx;
 		kctl->private_value = nid;
 		err = snd_ctl_add(codec->bus->card, kctl);
 		if (err < 0)
@@ -1595,7 +1616,17 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
 	int err;
 	struct snd_kcontrol *kctl;
 	struct snd_kcontrol_new *dig_mix;
+	int idx;
 
+	for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
+		if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Capture Switch",
+					     idx))
+			break;
+	}
+	if (idx >= SPDIF_MAX_IDX) {
+		printk(KERN_ERR "hda_codec: too many IEC958 inputs\n");
+		return -EBUSY;
+	}
 	for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) {
 		kctl = snd_ctl_new1(dig_mix, codec);
 		kctl->private_value = nid;
-- 
cgit v1.2.3-70-g09d2


From 12a733e56c0f1c78bd34bf36e9765463fd51c88e Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 4 Feb 2008 12:32:20 +0100
Subject: [ALSA] hda-codec - Add SI HDMI codec support

Added the support of SI HDMI codec, found in ASUS machines.
ALSA bug#3654
        https://bugtrack.alsa-project.org/alsa-bug/view.php?id=3654

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_atihdmi.c | 5 +++++
 1 file changed, 5 insertions(+)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_atihdmi.c b/sound/pci/hda/patch_atihdmi.c
index 9a8bb4ce3f8..27d2e007404 100644
--- a/sound/pci/hda/patch_atihdmi.c
+++ b/sound/pci/hda/patch_atihdmi.c
@@ -58,6 +58,10 @@ static int atihdmi_build_controls(struct hda_codec *codec)
 static int atihdmi_init(struct hda_codec *codec)
 {
 	snd_hda_sequence_write(codec, atihdmi_basic_init);
+	/* SI codec requires to unmute the pin */
+	if (get_wcaps(codec, 0x03) & AC_WCAP_OUT_AMP)
+		snd_hda_codec_write(codec, 0x03, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+				    AMP_OUT_UNMUTE);
 	return 0;
 }
 
@@ -158,5 +162,6 @@ struct hda_codec_preset snd_hda_preset_atihdmi[] = {
 	{ .id = 0x10027919, .name = "ATI RS600 HDMI", .patch = patch_atihdmi },
 	{ .id = 0x1002791a, .name = "ATI RS690/780 HDMI", .patch = patch_atihdmi },
 	{ .id = 0x1002aa01, .name = "ATI R6xx HDMI", .patch = patch_atihdmi },
+	{ .id = 0x10951392, .name = "SI HDMI", .patch = patch_atihdmi },
 	{} /* terminator */
 };
-- 
cgit v1.2.3-70-g09d2


From f12462c5224bf992f5ed4d37af4d42622f7d5934 Mon Sep 17 00:00:00 2001
From: Mirco Tischler <mt-ml@gmx.de>
Date: Mon, 4 Feb 2008 12:33:59 +0100
Subject: [ALSA] hda-codec - Add support of Zepto laptops

Adds support for zepto laptops with alc268 intel_hda codec.

Signed-off-by: Mirco Tischler <mt-ml@gmx.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 Documentation/sound/alsa/ALSA-Configuration.txt |  1 +
 sound/pci/hda/patch_realtek.c                   | 19 +++++++++++++++++++
 2 files changed, 20 insertions(+)

(limited to 'sound')

diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index e985cf5e041..9a56b9b273c 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -826,6 +826,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
 	  toshiba	Toshiba A205
 	  acer		Acer laptops
 	  dell		Dell OEM laptops (Vostro 1200)
+	  zepto		Zepto laptops
 	  test		for testing/debugging purpose, almost all controls can
 			adjusted.  Appearing only when compiled with
 			$CONFIG_SND_DEBUG=y
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 33282f9c01c..45e661e42c0 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -107,6 +107,7 @@ enum {
 	ALC268_TOSHIBA,
 	ALC268_ACER,
 	ALC268_DELL,
+	ALC268_ZEPTO,
 #ifdef CONFIG_SND_DEBUG
 	ALC268_TEST,
 #endif
@@ -10105,6 +10106,7 @@ static const char *alc268_models[ALC268_MODEL_LAST] = {
 	[ALC268_TOSHIBA]	= "toshiba",
 	[ALC268_ACER]		= "acer",
 	[ALC268_DELL]		= "dell",
+	[ALC268_ZEPTO]		= "zepto",
 #ifdef CONFIG_SND_DEBUG
 	[ALC268_TEST]		= "test",
 #endif
@@ -10122,6 +10124,7 @@ static struct snd_pci_quirk alc268_cfg_tbl[] = {
 	SND_PCI_QUIRK(0x1179, 0xff10, "TOSHIBA A205", ALC268_TOSHIBA),
 	SND_PCI_QUIRK(0x1179, 0xff50, "TOSHIBA A305", ALC268_TOSHIBA),
 	SND_PCI_QUIRK(0x152d, 0x0763, "Diverse (CPR2000)", ALC268_ACER),
+	SND_PCI_QUIRK(0x1170, 0x0040, "ZEPTO", ALC268_ZEPTO),
 	{}
 };
 
@@ -10182,6 +10185,22 @@ static struct alc_config_preset alc268_presets[] = {
 		.init_hook = alc268_dell_init_hook,
 		.input_mux = &alc268_capture_source,
 	},
+	[ALC268_ZEPTO] = {
+		.mixers = { alc268_base_mixer, alc268_capture_alt_mixer },
+		.init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
+				alc268_toshiba_verbs },
+		.num_dacs = ARRAY_SIZE(alc268_dac_nids),
+		.dac_nids = alc268_dac_nids,
+		.num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
+		.adc_nids = alc268_adc_nids_alt,
+		.hp_nid = 0x03,
+		.dig_out_nid = ALC268_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc268_modes),
+		.channel_mode = alc268_modes,
+		.input_mux = &alc268_capture_source,
+		.unsol_event = alc268_toshiba_unsol_event,
+		.init_hook = alc268_toshiba_automute
+	},
 #ifdef CONFIG_SND_DEBUG
 	[ALC268_TEST] = {
 		.mixers = { alc268_test_mixer, alc268_capture_mixer },
-- 
cgit v1.2.3-70-g09d2


From f339eb0f30e6598c1d3f91b01a3e634364fab7a2 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 4 Feb 2008 12:34:59 +0100
Subject: [ALSA] ice1724 - Enable AK4114 support for Audiophile192

Fixed and enabled the support of AK4114 chip on Audiophile192.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/ice1712/revo.c | 26 ++++++++------------------
 1 file changed, 8 insertions(+), 18 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/ice1712/revo.c b/sound/pci/ice1712/revo.c
index 301bf929acd..1d3b1ebf9c9 100644
--- a/sound/pci/ice1712/revo.c
+++ b/sound/pci/ice1712/revo.c
@@ -353,28 +353,20 @@ static struct snd_ak4xxx_private akm_ap192_priv __devinitdata = {
 	.cif = 0,
 	.data_mask = VT1724_REVO_CDOUT,
 	.clk_mask = VT1724_REVO_CCLK,
-	.cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS3,
-	.cs_addr = VT1724_REVO_CS3,
-	.cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS3,
+	.cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS1,
+	.cs_addr = VT1724_REVO_CS1,
+	.cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS1,
 	.add_flags = VT1724_REVO_CCLK, /* high at init */
 	.mask_flags = 0,
 };
 
-#if 0
-/* FIXME: ak4114 makes the sound much lower due to some confliction,
- *        so let's disable it right now...
- */
-#define BUILD_AK4114_AP192
-#endif
-
-#ifdef BUILD_AK4114_AP192
 /* AK4114 support on Audiophile 192 */
 /* CDTO (pin 32) -- GPIO2 pin 52
  * CDTI (pin 33) -- GPIO3 pin 53 (shared with AK4358)
  * CCLK (pin 34) -- GPIO1 pin 51 (shared with AK4358)
  * CSN  (pin 35) -- GPIO7 pin 59
  */
-#define AK4114_ADDR	0x00
+#define AK4114_ADDR	0x02
 
 static void write_data(struct snd_ice1712 *ice, unsigned int gpio,
 		       unsigned int data, int idx)
@@ -428,7 +420,7 @@ static unsigned int ap192_4wire_start(struct snd_ice1712 *ice)
 	tmp = snd_ice1712_gpio_read(ice);
 	tmp |= VT1724_REVO_CCLK; /* high at init */
 	tmp |= VT1724_REVO_CS0;
-	tmp &= ~VT1724_REVO_CS3;
+	tmp &= ~VT1724_REVO_CS1;
 	snd_ice1712_gpio_write(ice, tmp);
 	udelay(1);
 	return tmp;
@@ -436,7 +428,7 @@ static unsigned int ap192_4wire_start(struct snd_ice1712 *ice)
 
 static void ap192_4wire_finish(struct snd_ice1712 *ice, unsigned int tmp)
 {
-	tmp |= VT1724_REVO_CS3;
+	tmp |= VT1724_REVO_CS1;
 	tmp |= VT1724_REVO_CS0;
 	snd_ice1712_gpio_write(ice, tmp);
 	udelay(1);
@@ -485,13 +477,13 @@ static int __devinit ap192_ak4114_init(struct snd_ice1712 *ice)
 	struct ak4114 *ak;
 	int err;
 
-	return snd_ak4114_create(ice->card,
+	err = snd_ak4114_create(ice->card,
 				 ap192_ak4114_read,
 				 ap192_ak4114_write,
 				 ak4114_init_vals, ak4114_init_txcsb,
 				 ice, &ak);
+	return 0; /* error ignored; it's no fatal error */
 }
-#endif /* BUILD_AK4114_AP192 */
 
 static int __devinit revo_init(struct snd_ice1712 *ice)
 {
@@ -588,11 +580,9 @@ static int __devinit revo_add_controls(struct snd_ice1712 *ice)
 		err = snd_ice1712_akm4xxx_build_controls(ice);
 		if (err < 0)
 			return err;
-#ifdef BUILD_AK4114_AP192
 		err = ap192_ak4114_init(ice);
 		if (err < 0)
 			return err;
-#endif
 		break;
 	}
 	return 0;
-- 
cgit v1.2.3-70-g09d2


From a76969228a5b341f9c968abbc6eb7655ac3734e4 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 4 Feb 2008 12:36:32 +0100
Subject: [ALSA] ice1724 - Add ADC setup in set_rate callback for Audiophile192

Added the missing GPIO setup for the AK5385A ADC codec on Audiophile192.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/ice1712/revo.c | 25 +++++++++++++++++--------
 1 file changed, 17 insertions(+), 8 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/ice1712/revo.c b/sound/pci/ice1712/revo.c
index 1d3b1ebf9c9..7c930cc05f1 100644
--- a/sound/pci/ice1712/revo.c
+++ b/sound/pci/ice1712/revo.c
@@ -322,17 +322,23 @@ static struct snd_pt2258 ptc_revo51_volume;
 static void ap192_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate)
 {
 	struct snd_ice1712 *ice = ak->private_data[0];
+	int dfs;
 
 	revo_set_rate_val(ak, rate);
 
-#if 1 /* FIXME: do we need this procedure? */
-	/* reset DFS pin of AK5385A for ADC, too */
-	/* DFS0 (pin 18) -- GPIO10 pin 77 */
-	snd_ice1712_save_gpio_status(ice);
-	snd_ice1712_gpio_write_bits(ice, 1 << 10,
-				    rate > 48000 ? (1 << 10) : 0);
-	snd_ice1712_restore_gpio_status(ice);
-#endif
+	/* reset CKS */
+	snd_ice1712_gpio_write_bits(ice, 1 << 8, rate > 96000 ? 1 : 0);
+	/* reset DFS pins of AK5385A for ADC, too */
+	if (rate > 96000)
+		dfs = 2;
+	else if (rate > 48000)
+		dfs = 1;
+	else
+		dfs = 0;
+	snd_ice1712_gpio_write_bits(ice, 3 << 9, dfs << 9);
+	/* reset ADC */
+	snd_ice1712_gpio_write_bits(ice, 1 << 11, 0);
+	snd_ice1712_gpio_write_bits(ice, 1 << 11, 1);
 }
 
 static const struct snd_akm4xxx_dac_channel ap192_dac[] = {
@@ -549,6 +555,9 @@ static int __devinit revo_init(struct snd_ice1712 *ice)
 		if (err < 0)
 			return err;
 		
+		/* unmute all codecs */
+		snd_ice1712_gpio_write_bits(ice, VT1724_REVO_MUTE,
+					    VT1724_REVO_MUTE);
 		break;
 	}
 
-- 
cgit v1.2.3-70-g09d2


From 6c4cc3a8ed15aacc06a5fd369639fef633cee2bc Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 4 Feb 2008 12:44:11 +0100
Subject: [ALSA] Add more fallbacks to OSS PHONEOUT mixer map

Added more fallbacks to OSS PHONEOUT mixer mapping.  This corresponds
to the speaker output in general, so now "Mono" and "Speaker" are
assigned.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/core/oss/mixer_oss.c | 2 ++
 1 file changed, 2 insertions(+)

(limited to 'sound')

diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index 75daed298a1..581aa2c60e6 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -1257,6 +1257,8 @@ static void snd_mixer_oss_build(struct snd_mixer_oss *mixer)
 		{ SOUND_MIXER_DIGITAL3,	"Digital",		2 },
 		{ SOUND_MIXER_PHONEIN,	"Phone",		0 },
 		{ SOUND_MIXER_PHONEOUT,	"Master Mono",		0 },
+		{ SOUND_MIXER_PHONEOUT,	"Speaker",		0 }, /*fallback*/
+		{ SOUND_MIXER_PHONEOUT,	"Mono",			0 }, /*fallback*/
 		{ SOUND_MIXER_PHONEOUT,	"Phone",		0 }, /* fallback */
 		{ SOUND_MIXER_VIDEO,	"Video",		0 },
 		{ SOUND_MIXER_RADIO,	"Radio",		0 },
-- 
cgit v1.2.3-70-g09d2


From 7ba72ba1fe891a94b1e9d506236507e4dc50e872 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Wed, 6 Feb 2008 14:03:20 +0100
Subject: [ALSA] hda-intel - Fix PCM device number assignment

In the current scheme, PCM device numbers are assigned incrementally
in the order of codecs.  This causes problems when the codec number
is irregular, e.g. codec #0 for HDMI and codec #1 for analog.  Then
the HDMI becomes the first PCM, which is picked up as the default
output device.  Unfortuantely this doesn't work well with normal
setups.

This patch introduced the fixed device numbers for the PCM types,
namely, analog, SPDIF, HDMI and modem.  The PCM devices are assigned
according to the corresponding PCM type.  After this patch, HDMI will
be always assigned to PCM #3, SPDIF to PCM #1, and the first analog
to PCM #0, etc.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/hda_codec.h      | 12 +++++-
 sound/pci/hda/hda_intel.c      | 89 ++++++++++++++++++++++--------------------
 sound/pci/hda/patch_analog.c   |  1 +
 sound/pci/hda/patch_atihdmi.c  |  1 +
 sound/pci/hda/patch_cmedia.c   |  1 +
 sound/pci/hda/patch_conexant.c |  1 +
 sound/pci/hda/patch_realtek.c  |  1 +
 sound/pci/hda/patch_si3054.c   |  2 +-
 sound/pci/hda/patch_sigmatel.c |  1 +
 sound/pci/hda/patch_via.c      |  1 +
 10 files changed, 66 insertions(+), 44 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index f14871151be..301b5227bfb 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -590,11 +590,21 @@ struct hda_pcm_stream {
 	struct hda_pcm_ops ops;
 };
 
+/* PCM types */
+enum {
+	HDA_PCM_TYPE_AUDIO,
+	HDA_PCM_TYPE_SPDIF,
+	HDA_PCM_TYPE_HDMI,
+	HDA_PCM_TYPE_MODEM,
+	HDA_PCM_NTYPES
+};
+
 /* for PCM creation */
 struct hda_pcm {
 	char *name;
 	struct hda_pcm_stream stream[2];
-	unsigned int is_modem;	/* modem codec? */
+	unsigned int pcm_type;	/* HDA_PCM_TYPE_XXX */
+	int device;	/* assigned device number */
 };
 
 /* codec information */
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 4be36c84b36..18475de074b 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -211,9 +211,7 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
 /* max buffer size - no h/w limit, you can increase as you like */
 #define AZX_MAX_BUF_SIZE	(1024*1024*1024)
 /* max number of PCM devics per card */
-#define AZX_MAX_AUDIO_PCMS	6
-#define AZX_MAX_MODEM_PCMS	2
-#define AZX_MAX_PCMS		(AZX_MAX_AUDIO_PCMS + AZX_MAX_MODEM_PCMS)
+#define AZX_MAX_PCMS		8
 
 /* RIRB int mask: overrun[2], response[0] */
 #define RIRB_INT_RESPONSE	0x01
@@ -350,7 +348,6 @@ struct azx {
 	struct azx_dev *azx_dev;
 
 	/* PCM */
-	unsigned int pcm_devs;
 	struct snd_pcm *pcm[AZX_MAX_PCMS];
 
 	/* HD codec */
@@ -1386,7 +1383,7 @@ static void azx_pcm_free(struct snd_pcm *pcm)
 }
 
 static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec,
-				      struct hda_pcm *cpcm, int pcm_dev)
+				      struct hda_pcm *cpcm)
 {
 	int err;
 	struct snd_pcm *pcm;
@@ -1400,7 +1397,7 @@ static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec,
 
 	snd_assert(cpcm->name, return -EINVAL);
 
-	err = snd_pcm_new(chip->card, cpcm->name, pcm_dev,
+	err = snd_pcm_new(chip->card, cpcm->name, cpcm->device,
 			  cpcm->stream[0].substreams,
 			  cpcm->stream[1].substreams,
 			  &pcm);
@@ -1423,59 +1420,67 @@ static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec,
 	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
 					      snd_dma_pci_data(chip->pci),
 					      1024 * 64, 1024 * 1024);
-	chip->pcm[pcm_dev] = pcm;
-	if (chip->pcm_devs < pcm_dev + 1)
-		chip->pcm_devs = pcm_dev + 1;
-
+	chip->pcm[cpcm->device] = pcm;
 	return 0;
 }
 
 static int __devinit azx_pcm_create(struct azx *chip)
 {
+	static const char *dev_name[HDA_PCM_NTYPES] = {
+		"Audio", "SPDIF", "HDMI", "Modem"
+	};
+	/* starting device index for each PCM type */
+	static int dev_idx[HDA_PCM_NTYPES] = {
+		[HDA_PCM_TYPE_AUDIO] = 0,
+		[HDA_PCM_TYPE_SPDIF] = 1,
+		[HDA_PCM_TYPE_HDMI] = 3,
+		[HDA_PCM_TYPE_MODEM] = 6
+	};
+	/* normal audio device indices; not linear to keep compatibility */
+	static int audio_idx[4] = { 0, 2, 4, 5 };
 	struct hda_codec *codec;
 	int c, err;
-	int pcm_dev;
+	int num_devs[HDA_PCM_NTYPES];
 
 	err = snd_hda_build_pcms(chip->bus);
 	if (err < 0)
 		return err;
 
 	/* create audio PCMs */
-	pcm_dev = 0;
-	list_for_each_entry(codec, &chip->bus->codec_list, list) {
-		for (c = 0; c < codec->num_pcms; c++) {
-			if (codec->pcm_info[c].is_modem)
-				continue; /* create later */
-			if (pcm_dev >= AZX_MAX_AUDIO_PCMS) {
-				snd_printk(KERN_ERR SFX
-					   "Too many audio PCMs\n");
-				return -EINVAL;
-			}
-			err = create_codec_pcm(chip, codec,
-					       &codec->pcm_info[c], pcm_dev);
-			if (err < 0)
-				return err;
-			pcm_dev++;
-		}
-	}
-
-	/* create modem PCMs */
-	pcm_dev = AZX_MAX_AUDIO_PCMS;
+	memset(num_devs, 0, sizeof(num_devs));
 	list_for_each_entry(codec, &chip->bus->codec_list, list) {
 		for (c = 0; c < codec->num_pcms; c++) {
-			if (!codec->pcm_info[c].is_modem)
-				continue; /* already created */
-			if (pcm_dev >= AZX_MAX_PCMS) {
-				snd_printk(KERN_ERR SFX
-					   "Too many modem PCMs\n");
-				return -EINVAL;
+			struct hda_pcm *cpcm = &codec->pcm_info[c];
+			int type = cpcm->pcm_type;
+			switch (type) {
+			case HDA_PCM_TYPE_AUDIO:
+				if (num_devs[type] >= ARRAY_SIZE(audio_idx)) {
+					snd_printk(KERN_WARNING
+						   "Too many audio devices\n");
+					continue;
+				}
+				cpcm->device = audio_idx[num_devs[type]];
+				break;
+			case HDA_PCM_TYPE_SPDIF:
+			case HDA_PCM_TYPE_HDMI:
+			case HDA_PCM_TYPE_MODEM:
+				if (num_devs[type]) {
+					snd_printk(KERN_WARNING
+						   "%s already defined\n",
+						   dev_name[type]);
+					continue;
+				}
+				cpcm->device = dev_idx[type];
+				break;
+			default:
+				snd_printk(KERN_WARNING
+					   "Invalid PCM type %d\n", type);
+				continue;
 			}
-			err = create_codec_pcm(chip, codec,
-					       &codec->pcm_info[c], pcm_dev);
+			num_devs[type]++;
+			err = create_codec_pcm(chip, codec, cpcm);
 			if (err < 0)
 				return err;
-			chip->pcm[pcm_dev]->dev_class = SNDRV_PCM_CLASS_MODEM;
-			pcm_dev++;
 		}
 	}
 	return 0;
@@ -1587,7 +1592,7 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state)
 	int i;
 
 	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
-	for (i = 0; i < chip->pcm_devs; i++)
+	for (i = 0; i < AZX_MAX_PCMS; i++)
 		snd_pcm_suspend_all(chip->pcm[i]);
 	if (chip->initialized)
 		snd_hda_suspend(chip->bus, state);
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index c8649282c2c..7286ab86ecc 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -359,6 +359,7 @@ static int ad198x_build_pcms(struct hda_codec *codec)
 		info++;
 		codec->num_pcms++;
 		info->name = "AD198x Digital";
+		info->pcm_type = HDA_PCM_TYPE_SPDIF;
 		info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback;
 		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
 		if (spec->dig_in_nid) {
diff --git a/sound/pci/hda/patch_atihdmi.c b/sound/pci/hda/patch_atihdmi.c
index 27d2e007404..e0e9ea99568 100644
--- a/sound/pci/hda/patch_atihdmi.c
+++ b/sound/pci/hda/patch_atihdmi.c
@@ -116,6 +116,7 @@ static int atihdmi_build_pcms(struct hda_codec *codec)
 	codec->pcm_info = info;
 
 	info->name = "ATI HDMI";
+	info->pcm_type = HDA_PCM_TYPE_HDMI;
 	info->stream[SNDRV_PCM_STREAM_PLAYBACK] = atihdmi_pcm_digital_playback;
 
 	return 0;
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c
index 3d6097ba1d6..99ce74b4e9f 100644
--- a/sound/pci/hda/patch_cmedia.c
+++ b/sound/pci/hda/patch_cmedia.c
@@ -571,6 +571,7 @@ static int cmi9880_build_pcms(struct hda_codec *codec)
 		codec->num_pcms++;
 		info++;
 		info->name = "CMI9880 Digital";
+		info->pcm_type = HDA_PCM_TYPE_SPDIF;
 		if (spec->multiout.dig_out_nid) {
 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = cmi9880_pcm_digital_playback;
 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 7206b30cbf9..bb915ede0ce 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -284,6 +284,7 @@ static int conexant_build_pcms(struct hda_codec *codec)
 		info++;
 		codec->num_pcms++;
 		info->name = "Conexant Digital";
+		info->pcm_type = HDA_PCM_TYPE_SPDIF;
 		info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
 			conexant_pcm_digital_playback;
 		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 45e661e42c0..85ea3f82de1 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -2499,6 +2499,7 @@ static int alc_build_pcms(struct hda_codec *codec)
 		codec->num_pcms = 2;
 		info = spec->pcm_rec + 1;
 		info->name = spec->stream_name_digital;
+		info->pcm_type = HDA_PCM_TYPE_SPDIF;
 		if (spec->multiout.dig_out_nid &&
 		    spec->stream_digital_playback) {
 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback);
diff --git a/sound/pci/hda/patch_si3054.c b/sound/pci/hda/patch_si3054.c
index d22f5a6b850..598ee2119bb 100644
--- a/sound/pci/hda/patch_si3054.c
+++ b/sound/pci/hda/patch_si3054.c
@@ -206,7 +206,7 @@ static int si3054_build_pcms(struct hda_codec *codec)
 	info->name = "Si3054 Modem";
 	info->stream[SNDRV_PCM_STREAM_PLAYBACK] = si3054_pcm;
 	info->stream[SNDRV_PCM_STREAM_CAPTURE]  = si3054_pcm;
-	info->is_modem = 1;
+	info->pcm_type = HDA_PCM_TYPE_MODEM;
 	return 0;
 }
 
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 4c3c4e6ce3d..f693011d25a 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -1899,6 +1899,7 @@ static int stac92xx_build_pcms(struct hda_codec *codec)
 		codec->num_pcms++;
 		info++;
 		info->name = "STAC92xx Digital";
+		info->pcm_type = HDA_PCM_TYPE_SPDIF;
 		if (spec->multiout.dig_out_nid) {
 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_digital_playback;
 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index 4e5dd4cf36f..d9a5c6a2dd9 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -523,6 +523,7 @@ static int via_build_pcms(struct hda_codec *codec)
 		codec->num_pcms++;
 		info++;
 		info->name = spec->stream_name_digital;
+		info->pcm_type = HDA_PCM_TYPE_SPDIF;
 		if (spec->multiout.dig_out_nid) {
 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
 				*(spec->stream_digital_playback);
-- 
cgit v1.2.3-70-g09d2


From 7d664ed58fb54bc421d5fe8e5e0adec736fd0558 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Wed, 6 Feb 2008 14:41:59 +0100
Subject: [ALSA] hda-codec - Add ID for an unknown HDMI codec chip

Added the ID for an unknown HDMI codec chip on Jetway J9F2.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_atihdmi.c | 1 +
 1 file changed, 1 insertion(+)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_atihdmi.c b/sound/pci/hda/patch_atihdmi.c
index e0e9ea99568..e6fbd5d8fba 100644
--- a/sound/pci/hda/patch_atihdmi.c
+++ b/sound/pci/hda/patch_atihdmi.c
@@ -164,5 +164,6 @@ struct hda_codec_preset snd_hda_preset_atihdmi[] = {
 	{ .id = 0x1002791a, .name = "ATI RS690/780 HDMI", .patch = patch_atihdmi },
 	{ .id = 0x1002aa01, .name = "ATI R6xx HDMI", .patch = patch_atihdmi },
 	{ .id = 0x10951392, .name = "SI HDMI", .patch = patch_atihdmi },
+	{ .id = 0x17e80047, .name = "Unknown HDMI",  .patch = patch_atihdmi },
 	{} /* terminator */
 };
-- 
cgit v1.2.3-70-g09d2


From d043143d803ad9a9f4a66d6a833876735fb7b869 Mon Sep 17 00:00:00 2001
From: Alan Horstmann <gineera@aspect135.co.uk>
Date: Wed, 6 Feb 2008 14:43:54 +0100
Subject: [ALSA] ice1712 - Fix hoontech MIDI input

Fixes the problems with Midi In on Hoontech/STA dsp24 cards, for example with
DSP2000 box, without restricting the box configurations available.  Also adds
mpu_401 name strings.

Signed-off-by: Alan Horstmann <gineera@aspect135.co.uk>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/ice1712/hoontech.c | 21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/ice1712/hoontech.c b/sound/pci/ice1712/hoontech.c
index cf5c7c0898f..6914189073a 100644
--- a/sound/pci/ice1712/hoontech.c
+++ b/sound/pci/ice1712/hoontech.c
@@ -208,6 +208,19 @@ static int __devinit snd_ice1712_hoontech_init(struct snd_ice1712 *ice)
 			    /* ICE1712_STDSP24_MUTE |
 			       ICE1712_STDSP24_INSEL |
 			       ICE1712_STDSP24_DAREAR; */
+	/*  These boxconfigs have caused problems in the past.
+	 *  The code is not optimal, but should now enable a working config to
+	 *  be achieved.
+	 *  ** MIDI IN can only be configured on one box **
+	 *  ICE1712_STDSP24_BOX_MIDI1 needs to be set for that box.
+	 *  Tests on a ADAC2000 box suggest the box config flags do not
+	 *  work as would be expected, and the inputs are crossed.
+	 *  Setting ICE1712_STDSP24_BOX_MIDI1 and ICE1712_STDSP24_BOX_MIDI2
+	 *  on the same box connects MIDI-In to both 401 uarts; both outputs
+	 *  are then active on all boxes.
+	 *  The default config here sets up everything on the first box.
+	 *  Alan Horstmann  5.2.2008
+	 */
 	spec->boxconfig[0] = ICE1712_STDSP24_BOX_CHN1 |
 				     ICE1712_STDSP24_BOX_CHN2 |
 				     ICE1712_STDSP24_BOX_CHN3 |
@@ -223,14 +236,14 @@ static int __devinit snd_ice1712_hoontech_init(struct snd_ice1712 *ice)
 		(spec->config & ICE1712_STDSP24_MUTE) ? 1 : 0);
 	snd_ice1712_stdsp24_insel(ice,
 		(spec->config & ICE1712_STDSP24_INSEL) ? 1 : 0);
-	for (box = 0; box < 1; box++) {
+	for (box = 0; box < 4; box++) {
 		if (spec->boxconfig[box] & ICE1712_STDSP24_BOX_MIDI2)
                         snd_ice1712_stdsp24_midi2(ice, 1);
 		for (chn = 0; chn < 4; chn++)
 			snd_ice1712_stdsp24_box_channel(ice, box, chn,
 				(spec->boxconfig[box] & (1 << chn)) ? 1 : 0);
-		snd_ice1712_stdsp24_box_midi(ice, box,
-				(spec->boxconfig[box] & ICE1712_STDSP24_BOX_MIDI1) ? 1 : 0);
+		if (spec->boxconfig[box] & ICE1712_STDSP24_BOX_MIDI1)
+			snd_ice1712_stdsp24_box_midi(ice, box, 1);
 	}
 
 	return 0;
@@ -322,6 +335,8 @@ struct snd_ice1712_card_info snd_ice1712_hoontech_cards[] __devinitdata = {
 		.name = "Hoontech SoundTrack Audio DSP24",
 		.model = "dsp24",
 		.chip_init = snd_ice1712_hoontech_init,
+		.mpu401_1_name = "MIDI-1 Hoontech/STA DSP24",
+		.mpu401_2_name = "MIDI-2 Hoontech/STA DSP24",
 	},
 	{
 		.subvendor = ICE1712_SUBDEVICE_STDSP24_VALUE,	/* a dummy id */
-- 
cgit v1.2.3-70-g09d2


From b76c850fbc280d6c0ff786653915f3a9700b5912 Mon Sep 17 00:00:00 2001
From: Matthew Ranostay <mranostay@embeddedalley.com>
Date: Wed, 6 Feb 2008 14:49:44 +0100
Subject: [ALSA] hda: STAC927x power down inactive DACs

On several laptops that have STAC9228 codecs have unused DACs,
this powers them down to a D3 state.

Signed-off-by: Matthew Ranostay <mranostay@embeddedalley.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_sigmatel.c | 24 +++++++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index f693011d25a..7f506ef0acc 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -136,6 +136,7 @@ struct sigmatel_spec {
 	/* power management */
 	unsigned int num_pwrs;
 	hda_nid_t *pwr_nids;
+	hda_nid_t *dac_list;
 
 	/* playback */
 	struct hda_input_mux *mono_mux;
@@ -291,6 +292,10 @@ static hda_nid_t stac927x_mux_nids[3] = {
         0x15, 0x16, 0x17
 };
 
+static hda_nid_t stac927x_dac_nids[6] = {
+	0x02, 0x03, 0x04, 0x05, 0x06, 0
+};
+
 static hda_nid_t stac927x_dmux_nids[1] = {
 	0x1b,
 };
@@ -2877,6 +2882,18 @@ static int is_nid_hp_pin(struct auto_pin_cfg *cfg, hda_nid_t nid)
 	return 0; /* nid is not a HP-Out */
 };
 
+static void stac92xx_power_down(struct hda_codec *codec)
+{
+	struct sigmatel_spec *spec = codec->spec;
+
+	/* power down inactive DACs */
+	hda_nid_t *dac;
+	for (dac = spec->dac_list; *dac; dac++)
+		if (!is_in_dac_nids(spec, *dac))
+			snd_hda_codec_write_cache(codec, *dac, 0,
+					AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+}
+
 static int stac92xx_init(struct hda_codec *codec)
 {
 	struct sigmatel_spec *spec = codec->spec;
@@ -2929,7 +2946,8 @@ static int stac92xx_init(struct hda_codec *codec)
 		enable_pin_detect(codec, spec->pwr_nids[i], event | i);
 		codec->patch_ops.unsol_event(codec, (event | i) << 26);
 	}
-
+	if (spec->dac_list)
+		stac92xx_power_down(codec);
 	if (cfg->dig_out_pin)
 		stac92xx_auto_set_pinctl(codec, cfg->dig_out_pin,
 					 AC_PINCTL_OUT_EN);
@@ -3102,6 +3120,9 @@ static int stac92xx_resume(struct hda_codec *codec)
 		spec->gpio_dir, spec->gpio_data);
 	snd_hda_codec_resume_amp(codec);
 	snd_hda_codec_resume_cache(codec);
+	/* power down inactive DACs */
+	if (spec->dac_list)
+		stac92xx_power_down(codec);
 	/* invoke unsolicited event to reset the HP state */
 	if (spec->hp_detect)
 		codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26);
@@ -3589,6 +3610,7 @@ static int patch_stac927x(struct hda_codec *codec)
 	spec->num_adcs = ARRAY_SIZE(stac927x_adc_nids);
 	spec->mux_nids = stac927x_mux_nids;
 	spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids);
+	spec->dac_list = stac927x_dac_nids;
 	spec->multiout.dac_nids = spec->dac_nids;
 
 	switch (spec->board_config) {
-- 
cgit v1.2.3-70-g09d2


From 4ce107b990d994a0fccea9b1e885b08a0daea495 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Wed, 6 Feb 2008 14:50:19 +0100
Subject: [ALSA] hda-intel - Use SG buffer

Use SG buffers for the HD-audio instead of linear buffers.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/hda_intel.c | 114 +++++++++++++++++++++++++++++-----------------
 1 file changed, 71 insertions(+), 43 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 18475de074b..b38a5a70ff0 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -206,8 +206,9 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
 #define MAX_AZX_DEV		16
 
 /* max number of fragments - we may use more if allocating more pages for BDL */
-#define BDL_SIZE		PAGE_ALIGN(8192)
-#define AZX_MAX_FRAG		(BDL_SIZE / (MAX_AZX_DEV * 16))
+#define BDL_SIZE		4096
+#define AZX_MAX_BDL_ENTRIES	(BDL_SIZE / 16)
+#define AZX_MAX_FRAG		32
 /* max buffer size - no h/w limit, you can increase as you like */
 #define AZX_MAX_BUF_SIZE	(1024*1024*1024)
 /* max number of PCM devics per card */
@@ -282,12 +283,10 @@ enum {
  */
 
 struct azx_dev {
-	u32 *bdl;		/* virtual address of the BDL */
-	dma_addr_t bdl_addr;	/* physical address of the BDL */
+	struct snd_dma_buffer bdl; /* BDL buffer */
 	u32 *posbuf;		/* position buffer pointer */
 
 	unsigned int bufsize;	/* size of the play buffer in bytes */
-	unsigned int fragsize;	/* size of each period in bytes */
 	unsigned int frags;	/* number for period in the play buffer */
 	unsigned int fifo_size;	/* FIFO size */
 
@@ -358,8 +357,7 @@ struct azx {
 	struct azx_rb corb;
 	struct azx_rb rirb;
 
-	/* BDL, CORB/RIRB and position buffers */
-	struct snd_dma_buffer bdl;
+	/* CORB/RIRB and position buffers */
 	struct snd_dma_buffer rb;
 	struct snd_dma_buffer posbuf;
 
@@ -962,30 +960,57 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id)
 /*
  * set up BDL entries
  */
-static void azx_setup_periods(struct azx_dev *azx_dev)
+static int azx_setup_periods(struct snd_pcm_substream *substream,
+			     struct azx_dev *azx_dev)
 {
-	u32 *bdl = azx_dev->bdl;
-	dma_addr_t dma_addr = azx_dev->substream->runtime->dma_addr;
-	int idx;
+	struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
+	u32 *bdl;
+	int i, ofs, periods, period_bytes;
 
 	/* reset BDL address */
 	azx_sd_writel(azx_dev, SD_BDLPL, 0);
 	azx_sd_writel(azx_dev, SD_BDLPU, 0);
 
+	period_bytes = snd_pcm_lib_period_bytes(substream);
+	periods = azx_dev->bufsize / period_bytes;
+
 	/* program the initial BDL entries */
-	for (idx = 0; idx < azx_dev->frags; idx++) {
-		unsigned int off = idx << 2; /* 4 dword step */
-		dma_addr_t addr = dma_addr + idx * azx_dev->fragsize;
-		/* program the address field of the BDL entry */
-		bdl[off] = cpu_to_le32((u32)addr);
-		bdl[off+1] = cpu_to_le32(upper_32bit(addr));
-
-		/* program the size field of the BDL entry */
-		bdl[off+2] = cpu_to_le32(azx_dev->fragsize);
-
-		/* program the IOC to enable interrupt when buffer completes */
-		bdl[off+3] = cpu_to_le32(0x01);
+	bdl = (u32 *)azx_dev->bdl.area;
+	ofs = 0;
+	azx_dev->frags = 0;
+	for (i = 0; i < periods; i++) {
+		int size, rest;
+		if (i >= AZX_MAX_BDL_ENTRIES) {
+			snd_printk(KERN_ERR "Too many BDL entries: "
+				   "buffer=%d, period=%d\n",
+				   azx_dev->bufsize, period_bytes);
+			/* reset */
+			azx_sd_writel(azx_dev, SD_BDLPL, 0);
+			azx_sd_writel(azx_dev, SD_BDLPU, 0);
+			return -EINVAL;
+		}
+		rest = period_bytes;
+		do {
+			dma_addr_t addr = snd_pcm_sgbuf_get_addr(sgbuf, ofs);
+			/* program the address field of the BDL entry */
+			bdl[0] = cpu_to_le32((u32)addr);
+			bdl[1] = cpu_to_le32(upper_32bit(addr));
+			/* program the size field of the BDL entry */
+			size = PAGE_SIZE - (ofs % PAGE_SIZE);
+			if (rest < size)
+				size = rest;
+			bdl[2] = cpu_to_le32(size);
+			/* program the IOC to enable interrupt
+			 * only when the whole fragment is processed
+			 */
+			rest -= size;
+			bdl[3] = rest ? 0 : cpu_to_le32(0x01);
+			bdl += 4;
+			azx_dev->frags++;
+			ofs += size;
+		} while (rest > 0);
 	}
+	return 0;
 }
 
 /*
@@ -1034,9 +1059,9 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
 
 	/* program the BDL address */
 	/* lower BDL address */
-	azx_sd_writel(azx_dev, SD_BDLPL, (u32)azx_dev->bdl_addr);
+	azx_sd_writel(azx_dev, SD_BDLPL, (u32)azx_dev->bdl.addr);
 	/* upper BDL address */
-	azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl_addr));
+	azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl.addr));
 
 	/* enable the position buffer */
 	if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
@@ -1272,8 +1297,6 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
 	struct snd_pcm_runtime *runtime = substream->runtime;
 
 	azx_dev->bufsize = snd_pcm_lib_buffer_bytes(substream);
-	azx_dev->fragsize = snd_pcm_lib_period_bytes(substream);
-	azx_dev->frags = azx_dev->bufsize / azx_dev->fragsize;
 	azx_dev->format_val = snd_hda_calc_stream_format(runtime->rate,
 							 runtime->channels,
 							 runtime->format,
@@ -1288,7 +1311,8 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
 	snd_printdd("azx_pcm_prepare: bufsize=0x%x, fragsize=0x%x, "
 		    "format=0x%x\n",
 		    azx_dev->bufsize, azx_dev->fragsize, azx_dev->format_val);
-	azx_setup_periods(azx_dev);
+	if (azx_setup_periods(substream, azx_dev) < 0)
+		return -EINVAL;
 	azx_setup_controller(chip, azx_dev);
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 		azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1;
@@ -1375,6 +1399,7 @@ static struct snd_pcm_ops azx_pcm_ops = {
 	.prepare = azx_pcm_prepare,
 	.trigger = azx_pcm_trigger,
 	.pointer = azx_pcm_pointer,
+	.page = snd_pcm_sgbuf_ops_page,
 };
 
 static void azx_pcm_free(struct snd_pcm *pcm)
@@ -1417,7 +1442,7 @@ static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec,
 		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &azx_pcm_ops);
 	if (cpcm->stream[1].substreams)
 		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &azx_pcm_ops);
-	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
 					      snd_dma_pci_data(chip->pci),
 					      1024 * 64, 1024 * 1024);
 	chip->pcm[cpcm->device] = pcm;
@@ -1507,10 +1532,7 @@ static int __devinit azx_init_stream(struct azx *chip)
 	 * and initialize
 	 */
 	for (i = 0; i < chip->num_streams; i++) {
-		unsigned int off = sizeof(u32) * (i * AZX_MAX_FRAG * 4);
 		struct azx_dev *azx_dev = &chip->azx_dev[i];
-		azx_dev->bdl = (u32 *)(chip->bdl.area + off);
-		azx_dev->bdl_addr = chip->bdl.addr + off;
 		azx_dev->posbuf = (u32 __iomem *)(chip->posbuf.area + i * 8);
 		/* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */
 		azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80);
@@ -1646,8 +1668,9 @@ static int azx_resume(struct pci_dev *pci)
  */
 static int azx_free(struct azx *chip)
 {
+	int i;
+
 	if (chip->initialized) {
-		int i;
 		for (i = 0; i < chip->num_streams; i++)
 			azx_stream_stop(chip, &chip->azx_dev[i]);
 		azx_stop_chip(chip);
@@ -1662,8 +1685,11 @@ static int azx_free(struct azx *chip)
 	if (chip->remap_addr)
 		iounmap(chip->remap_addr);
 
-	if (chip->bdl.area)
-		snd_dma_free_pages(&chip->bdl);
+	if (chip->azx_dev) {
+		for (i = 0; i < chip->num_streams; i++)
+			if (chip->azx_dev[i].bdl.area)
+				snd_dma_free_pages(&chip->azx_dev[i].bdl);
+	}
 	if (chip->rb.area)
 		snd_dma_free_pages(&chip->rb);
 	if (chip->posbuf.area)
@@ -1745,7 +1771,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
 				struct azx **rchip)
 {
 	struct azx *chip;
-	int err;
+	int i, err;
 	unsigned short gcap;
 	static struct snd_device_ops ops = {
 		.dev_free = azx_dev_free,
@@ -1857,13 +1883,15 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
 		goto errout;
 	}
 
-	/* allocate memory for the BDL for each stream */
-	err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
-				  snd_dma_pci_data(chip->pci),
-				  BDL_SIZE, &chip->bdl);
-	if (err < 0) {
-		snd_printk(KERN_ERR SFX "cannot allocate BDL\n");
-		goto errout;
+	for (i = 0; i < chip->num_streams; i++) {
+		/* allocate memory for the BDL for each stream */
+		err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
+					  snd_dma_pci_data(chip->pci),
+					  BDL_SIZE, &chip->azx_dev[i].bdl);
+		if (err < 0) {
+			snd_printk(KERN_ERR SFX "cannot allocate BDL\n");
+			goto errout;
+		}
 	}
 	/* allocate memory for the position buffer */
 	err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
-- 
cgit v1.2.3-70-g09d2


From cf7aaca8bae3a719db47ff6eca5f6f2f42eba05a Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Wed, 6 Feb 2008 15:05:57 +0100
Subject: [ALSA] hda-intel - Support 64bit buffer allocation

The HD-audio hardware usually supports 64bit address for DMA and other
buffers.  The patch enables the feature if supported.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/hda_intel.c | 4 ++++
 1 file changed, 4 insertions(+)

(limited to 'sound')

diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index b38a5a70ff0..ec3ddda30be 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -1843,6 +1843,10 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
 	gcap = azx_readw(chip, GCAP);
 	snd_printdd("chipset global capabilities = 0x%x\n", gcap);
 
+	/* allow 64bit DMA address if supported by H/W */
+	if ((gcap & 0x01) && !pci_set_dma_mask(pci, DMA_64BIT_MASK))
+		pci_set_consistent_dma_mask(pci, DMA_64BIT_MASK);
+
 	if (gcap) {
 		/* read number of streams from GCAP register instead of using
 		 * hardcoded value
-- 
cgit v1.2.3-70-g09d2


From a60567d13c047b03167df4aed6b7a8730f267234 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Wed, 6 Feb 2008 15:48:06 +0100
Subject: [ALSA] Added support for Delta1010E (newer revisions of Delta1010)

For more details, see ALSA bug#3327 .

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
 sound/pci/ice1712/delta.c | 9 +++++++++
 sound/pci/ice1712/delta.h | 1 +
 2 files changed, 10 insertions(+)

(limited to 'sound')

diff --git a/sound/pci/ice1712/delta.c b/sound/pci/ice1712/delta.c
index efd180b40e5..c78894f110b 100644
--- a/sound/pci/ice1712/delta.c
+++ b/sound/pci/ice1712/delta.c
@@ -86,6 +86,7 @@ static unsigned char ap_cs8427_codec_select(struct snd_ice1712 *ice)
 	unsigned char tmp;
 	tmp = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA);
 	switch (ice->eeprom.subvendor) {
+	case ICE1712_SUBDEVICE_DELTA1010E:
 	case ICE1712_SUBDEVICE_DELTA1010LT:
 		tmp &= ~ICE1712_DELTA_1010LT_CS;
 		tmp |= ICE1712_DELTA_1010LT_CCLK | ICE1712_DELTA_1010LT_CS_CS8427;
@@ -109,6 +110,7 @@ static unsigned char ap_cs8427_codec_select(struct snd_ice1712 *ice)
 static void ap_cs8427_codec_deassert(struct snd_ice1712 *ice, unsigned char tmp)
 {
 	switch (ice->eeprom.subvendor) {
+	case ICE1712_SUBDEVICE_DELTA1010E:
 	case ICE1712_SUBDEVICE_DELTA1010LT:
 		tmp &= ~ICE1712_DELTA_1010LT_CS;
 		tmp |= ICE1712_DELTA_1010LT_CS_NONE;
@@ -534,6 +536,9 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
 	int err;
 	struct snd_akm4xxx *ak;
 
+	if (ice->eeprom.subvendor && ice->eeprom.gpiodir == 0x7b)
+		ice->eeprom.subvendor = ICE1712_SUBDEVICE_DELTA1010E;
+
 	/* determine I2C, DACs and ADCs */
 	switch (ice->eeprom.subvendor) {
 	case ICE1712_SUBDEVICE_AUDIOPHILE:
@@ -550,6 +555,7 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
 		ice->num_total_adcs = ice->omni ? 8 : 4;
 		break;
 	case ICE1712_SUBDEVICE_DELTA1010:
+	case ICE1712_SUBDEVICE_DELTA1010E:
 	case ICE1712_SUBDEVICE_DELTA1010LT:
 	case ICE1712_SUBDEVICE_MEDIASTATION:
 		ice->num_total_dacs = 8;
@@ -568,6 +574,7 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
 	switch (ice->eeprom.subvendor) {
 	case ICE1712_SUBDEVICE_AUDIOPHILE:
 	case ICE1712_SUBDEVICE_DELTA410:
+	case ICE1712_SUBDEVICE_DELTA1010E:
 	case ICE1712_SUBDEVICE_DELTA1010LT:
 	case ICE1712_SUBDEVICE_VX442:
 		if ((err = snd_i2c_bus_create(ice->card, "ICE1712 GPIO 1", NULL, &ice->i2c)) < 0) {
@@ -601,6 +608,7 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
 	/* no analog? */
 	switch (ice->eeprom.subvendor) {
 	case ICE1712_SUBDEVICE_DELTA1010:
+	case ICE1712_SUBDEVICE_DELTA1010E:
 	case ICE1712_SUBDEVICE_DELTADIO2496:
 	case ICE1712_SUBDEVICE_MEDIASTATION:
 		return 0;
@@ -674,6 +682,7 @@ static int __devinit snd_ice1712_delta_add_controls(struct snd_ice1712 *ice)
 		if (err < 0)
 			return err;
 		break;
+	case ICE1712_SUBDEVICE_DELTA1010E:
 	case ICE1712_SUBDEVICE_DELTA1010LT:
 		err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_delta1010lt_wordclock_select, ice));
 		if (err < 0)
diff --git a/sound/pci/ice1712/delta.h b/sound/pci/ice1712/delta.h
index 26ea05a32f5..d07c49b4b66 100644
--- a/sound/pci/ice1712/delta.h
+++ b/sound/pci/ice1712/delta.h
@@ -36,6 +36,7 @@
 		"{Lionstracs,Mediastation},"
 
 #define ICE1712_SUBDEVICE_DELTA1010	0x121430d6
+#define ICE1712_SUBDEVICE_DELTA1010E	0xff1430d6
 #define ICE1712_SUBDEVICE_DELTADIO2496	0x121431d6
 #define ICE1712_SUBDEVICE_DELTA66	0x121432d6
 #define ICE1712_SUBDEVICE_DELTA44	0x121433d6
-- 
cgit v1.2.3-70-g09d2


From ef2cd2ccad66b4aba518eca7514eface267ee0f3 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Wed, 6 Feb 2008 20:04:49 +0100
Subject: [ALSA] ice1712 - added support for M-Audio Delta 66E

See ALSA bug#3327 for more details. Experimental.
Also fix support for M-Audio Delta 1010E - subdevice check.

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
 sound/pci/ice1712/delta.c | 15 ++++++++++++---
 sound/pci/ice1712/delta.h |  1 +
 2 files changed, 13 insertions(+), 3 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/ice1712/delta.c b/sound/pci/ice1712/delta.c
index c78894f110b..0ed96c17805 100644
--- a/sound/pci/ice1712/delta.c
+++ b/sound/pci/ice1712/delta.c
@@ -1,8 +1,8 @@
 /*
  *   ALSA driver for ICEnsemble ICE1712 (Envy24)
  *
- *   Lowlevel functions for M-Audio Delta 1010, 44, 66, Dio2496, Audiophile
- *                          Digigram VX442
+ *   Lowlevel functions for M-Audio Delta 1010, 1010E, 44, 66, 66E, Dio2496,
+ *			    Audiophile, Digigram VX442
  *
  *	Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz>
  *
@@ -536,9 +536,14 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
 	int err;
 	struct snd_akm4xxx *ak;
 
-	if (ice->eeprom.subvendor && ice->eeprom.gpiodir == 0x7b)
+	if (ice->eeprom.subvendor == ICE1712_SUBDEVICE_DELTA1010 &&
+	    ice->eeprom.gpiodir == 0x7b)
 		ice->eeprom.subvendor = ICE1712_SUBDEVICE_DELTA1010E;
 
+	if (ice->eeprom.subvendor == ICE1712_SUBDEVICE_DELTA66 &&
+	    ice->eeprom.gpiodir == 0xfb)
+	    	ice->eeprom.subvendor = ICE1712_SUBDEVICE_DELTA66E;
+
 	/* determine I2C, DACs and ADCs */
 	switch (ice->eeprom.subvendor) {
 	case ICE1712_SUBDEVICE_AUDIOPHILE:
@@ -565,6 +570,7 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
 		ice->num_total_dacs = 4;	/* two AK4324 codecs */
 		break;
 	case ICE1712_SUBDEVICE_VX442:
+	case ICE1712_SUBDEVICE_DELTA66E:	/* omni not suported yet */
 		ice->num_total_dacs = 4;
 		ice->num_total_adcs = 4;
 		break;
@@ -577,6 +583,7 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
 	case ICE1712_SUBDEVICE_DELTA1010E:
 	case ICE1712_SUBDEVICE_DELTA1010LT:
 	case ICE1712_SUBDEVICE_VX442:
+	case ICE1712_SUBDEVICE_DELTA66E:
 		if ((err = snd_i2c_bus_create(ice->card, "ICE1712 GPIO 1", NULL, &ice->i2c)) < 0) {
 			snd_printk(KERN_ERR "unable to create I2C bus\n");
 			return err;
@@ -635,6 +642,7 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
 		err = snd_ice1712_akm4xxx_init(ak, &akm_delta44, &akm_delta44_priv, ice);
 		break;
 	case ICE1712_SUBDEVICE_VX442:
+	case ICE1712_SUBDEVICE_DELTA66E:
 		err = snd_ice1712_akm4xxx_init(ak, &akm_vx442, &akm_vx442_priv, ice);
 		break;
 	default:
@@ -725,6 +733,7 @@ static int __devinit snd_ice1712_delta_add_controls(struct snd_ice1712 *ice)
 	case ICE1712_SUBDEVICE_DELTA44:
 	case ICE1712_SUBDEVICE_DELTA66:
 	case ICE1712_SUBDEVICE_VX442:
+	case ICE1712_SUBDEVICE_DELTA66E:
 		err = snd_ice1712_akm4xxx_build_controls(ice);
 		if (err < 0)
 			return err;
diff --git a/sound/pci/ice1712/delta.h b/sound/pci/ice1712/delta.h
index d07c49b4b66..ea7116c304c 100644
--- a/sound/pci/ice1712/delta.h
+++ b/sound/pci/ice1712/delta.h
@@ -39,6 +39,7 @@
 #define ICE1712_SUBDEVICE_DELTA1010E	0xff1430d6
 #define ICE1712_SUBDEVICE_DELTADIO2496	0x121431d6
 #define ICE1712_SUBDEVICE_DELTA66	0x121432d6
+#define ICE1712_SUBDEVICE_DELTA66E	0xff1432d6
 #define ICE1712_SUBDEVICE_DELTA44	0x121433d6
 #define ICE1712_SUBDEVICE_AUDIOPHILE	0x121434d6
 #define ICE1712_SUBDEVICE_DELTA410	0x121438d6
-- 
cgit v1.2.3-70-g09d2


From 21c7b0819f0d04788b2d3341f5062744373589a1 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Thu, 7 Feb 2008 12:06:32 +0100
Subject: [ALSA] hda-intel - Fix a compile error with CONFIG_SND_DEBUG_DETECT=y

Forgot to get rid of the obsolete fragsize field from a debug print.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/hda_intel.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index ec3ddda30be..f3242e1a731 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -1308,9 +1308,8 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
 		return -EINVAL;
 	}
 
-	snd_printdd("azx_pcm_prepare: bufsize=0x%x, fragsize=0x%x, "
-		    "format=0x%x\n",
-		    azx_dev->bufsize, azx_dev->fragsize, azx_dev->format_val);
+	snd_printdd("azx_pcm_prepare: bufsize=0x%x, format=0x%x\n",
+		    azx_dev->bufsize, azx_dev->format_val);
 	if (azx_setup_periods(substream, azx_dev) < 0)
 		return -EINVAL;
 	azx_setup_controller(chip, azx_dev);
-- 
cgit v1.2.3-70-g09d2


From cc4d13873aeacf89901861706a7a083d5a82e26a Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Thu, 7 Feb 2008 17:12:01 +0100
Subject: [ALSA] hda-codec - Correct HDMI transmitter names

Give better names to the new HDMI transmitter chips.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_atihdmi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_atihdmi.c b/sound/pci/hda/patch_atihdmi.c
index e6fbd5d8fba..45a2e30cbf4 100644
--- a/sound/pci/hda/patch_atihdmi.c
+++ b/sound/pci/hda/patch_atihdmi.c
@@ -163,7 +163,7 @@ struct hda_codec_preset snd_hda_preset_atihdmi[] = {
 	{ .id = 0x10027919, .name = "ATI RS600 HDMI", .patch = patch_atihdmi },
 	{ .id = 0x1002791a, .name = "ATI RS690/780 HDMI", .patch = patch_atihdmi },
 	{ .id = 0x1002aa01, .name = "ATI R6xx HDMI", .patch = patch_atihdmi },
-	{ .id = 0x10951392, .name = "SI HDMI", .patch = patch_atihdmi },
-	{ .id = 0x17e80047, .name = "Unknown HDMI",  .patch = patch_atihdmi },
+	{ .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_atihdmi },
+	{ .id = 0x17e80047, .name = "Chrontel HDMI",  .patch = patch_atihdmi },
 	{} /* terminator */
 };
-- 
cgit v1.2.3-70-g09d2


From aa27a44395c3d35bc16e52f1e709e0fb2a3709e4 Mon Sep 17 00:00:00 2001
From: Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
Date: Fri, 8 Feb 2008 12:44:17 +0100
Subject: [ALSA] hda-codec - remove duplicate controls in alc268 test mixer

I've just noticed that there are a handful of duplicate controls in the
ALC268 test model mixer.  This patch (against alsa-driver 1.0.16) removes
them.

Signed-off-by: Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c | 5 -----
 1 file changed, 5 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 85ea3f82de1..e4a7c50e9f7 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -9840,11 +9840,6 @@ static struct hda_input_mux alc268_capture_source = {
 
 #ifdef CONFIG_SND_DEBUG
 static struct snd_kcontrol_new alc268_test_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
-
 	/* Volume widgets */
 	HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x02, 0x0, HDA_OUTPUT),
 	HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x03, 0x0, HDA_OUTPUT),
-- 
cgit v1.2.3-70-g09d2


From fdafad6fc24a11070bcd0885100be7143cc038f8 Mon Sep 17 00:00:00 2001
From: Pavel Hofman <dustin@seznam.cz>
Date: Mon, 11 Feb 2008 14:48:06 +0100
Subject: [ALSA] AK4114 - listing regs in proc

A simple patch for listing AK4114 regs in proc.

Signed-off-by: Pavel Hofman <dustin@seznam.cz>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/i2c/other/ak4114.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

(limited to 'sound')

diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c
index 15061bd7277..9a90e830c42 100644
--- a/sound/i2c/other/ak4114.c
+++ b/sound/i2c/other/ak4114.c
@@ -27,6 +27,7 @@
 #include <sound/pcm.h>
 #include <sound/ak4114.h>
 #include <sound/asoundef.h>
+#include <sound/info.h>
 
 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
 MODULE_DESCRIPTION("AK4114 IEC958 (S/PDIF) receiver by Asahi Kasei");
@@ -446,6 +447,26 @@ static struct snd_kcontrol_new snd_ak4114_iec958_controls[] = {
 }
 };
 
+
+static void snd_ak4114_proc_regs_read(struct snd_info_entry *entry,
+		struct snd_info_buffer *buffer)
+{
+	struct ak4114 *ak4114 = entry->private_data;
+	int reg, val;
+	/* all ak4114 registers 0x00 - 0x1f */
+	for (reg = 0; reg < 0x20; reg++) {
+		val = reg_read(ak4114, reg);
+		snd_iprintf(buffer, "0x%02x = 0x%02x\n", reg, val);
+	}
+}
+
+static void snd_ak4114_proc_init(struct ak4114 *ak4114)
+{
+	struct snd_info_entry *entry;
+	if (!snd_card_proc_new(ak4114->card, "ak4114", &entry))
+		snd_info_set_text_ops(entry, ak4114, snd_ak4114_proc_regs_read);
+}
+
 int snd_ak4114_build(struct ak4114 *ak4114,
 		     struct snd_pcm_substream *ply_substream,
 		     struct snd_pcm_substream *cap_substream)
@@ -478,6 +499,7 @@ int snd_ak4114_build(struct ak4114 *ak4114,
 			return err;
 		ak4114->kctls[idx] = kctl;
 	}
+	snd_ak4114_proc_init(ak4114);
 	/* trigger workq */
 	schedule_delayed_work(&ak4114->work, HZ / 10);
 	return 0;
-- 
cgit v1.2.3-70-g09d2


From 937b416027d8f79d7b37bb63b6585ea8fdf125de Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 11 Feb 2008 14:52:36 +0100
Subject: [ALSA] hda-codec - Fix ALC880 F1734 model

Fixed some issues with ALC880 F1734 model
 - fix capture via mic
 - enable volume-wheel control

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index e4a7c50e9f7..3a735870a07 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -1320,11 +1320,19 @@ static struct snd_kcontrol_new alc880_f1734_mixer[] = {
 	HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
 	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
 	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
 	{ } /* end */
 };
 
+static struct hda_input_mux alc880_f1734_capture_source = {
+	.num_items = 2,
+	.items = {
+		{ "Mic", 0x1 },
+		{ "CD", 0x4 },
+	},
+};
+
 
 /*
  * ALC880 ASUS model
@@ -1936,6 +1944,9 @@ static struct hda_verb alc880_pin_f1734_init_verbs[] = {
 	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
 	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
 
+	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT},
+	{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_DCVOL_EVENT},
+
 	{ }
 };
 
@@ -3059,7 +3070,9 @@ static struct alc_config_preset alc880_presets[] = {
 		.hp_nid = 0x02,
 		.num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
 		.channel_mode = alc880_2_jack_modes,
-		.input_mux = &alc880_capture_source,
+		.input_mux = &alc880_f1734_capture_source,
+		.unsol_event = alc880_uniwill_p53_unsol_event,
+		.init_hook = alc880_uniwill_p53_hp_automute,
 	},
 	[ALC880_ASUS] = {
 		.mixers = { alc880_asus_mixer },
-- 
cgit v1.2.3-70-g09d2


From f0824812af1bf4f7d27e054a2ca2686385d770bb Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 11 Feb 2008 15:54:34 +0100
Subject: [ALSA] hda-codec - Fix automute of AD1981HD hp model

Reprogram the speaker-pin setting at each HP pin plug to make sure
the spekaer auto-muting on AD1981HD hp model.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_analog.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 7286ab86ecc..9d0d2a1bbd6 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -1366,7 +1366,10 @@ static int ad1981_hp_master_sw_put(struct snd_kcontrol *kcontrol,
 
 	if (! ad198x_eapd_put(kcontrol, ucontrol))
 		return 0;
-
+	/* change speaker pin appropriately */
+	snd_hda_codec_write(codec, 0x05, 0,
+			    AC_VERB_SET_PIN_WIDGET_CONTROL,
+			    spec->cur_eapd ? PIN_OUT : 0);
 	/* toggle HP mute appropriately */
 	snd_hda_codec_amp_stereo(codec, 0x06, HDA_OUTPUT, 0,
 				 HDA_AMP_MUTE,
-- 
cgit v1.2.3-70-g09d2


From e1406348129dc2db60ccad079c3d014200590557 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 11 Feb 2008 18:32:32 +0100
Subject: [ALSA] hda-codec - Clean up capture source selection of Realtek
 codecs

Clean up the codes of the capture source selection for Realtek codecs.
Now using common helper functions with the new capsrc_nids field.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c | 216 ++++++++----------------------------------
 1 file changed, 42 insertions(+), 174 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 3a735870a07..f1fa1d24936 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -238,6 +238,7 @@ struct alc_spec {
 	/* capture */
 	unsigned int num_adc_nids;
 	hda_nid_t *adc_nids;
+	hda_nid_t *capsrc_nids;
 	hda_nid_t dig_in_nid;		/* digital-in NID; optional */
 
 	/* capture source */
@@ -291,6 +292,7 @@ struct alc_config_preset {
 	hda_nid_t hp_nid;		/* optional */
 	unsigned int num_adc_nids;
 	hda_nid_t *adc_nids;
+	hda_nid_t *capsrc_nids;
 	hda_nid_t dig_in_nid;
 	unsigned int num_channel_mode;
 	const struct hda_channel_mode *channel_mode;
@@ -337,9 +339,10 @@ static int alc_mux_enum_put(struct snd_kcontrol *kcontrol,
 	struct alc_spec *spec = codec->spec;
 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
 	unsigned int mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
+	hda_nid_t nid = spec->capsrc_nids ?
+		spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx];
 	return snd_hda_input_mux_put(codec, &spec->input_mux[mux_idx], ucontrol,
-				     spec->adc_nids[adc_idx],
-				     &spec->cur_mux[adc_idx]);
+				     nid, &spec->cur_mux[adc_idx]);
 }
 
 
@@ -708,6 +711,7 @@ static void setup_preset(struct alc_spec *spec,
 
 	spec->num_adc_nids = preset->num_adc_nids;
 	spec->adc_nids = preset->adc_nids;
+	spec->capsrc_nids = preset->capsrc_nids;
 	spec->dig_in_nid = preset->dig_in_nid;
 
 	spec->unsol_event = preset->unsol_event;
@@ -5219,6 +5223,9 @@ static hda_nid_t alc882_dac_nids[4] = {
 #define alc882_adc_nids		alc880_adc_nids
 #define alc882_adc_nids_alt	alc880_adc_nids_alt
 
+static hda_nid_t alc882_capsrc_nids[3] = { 0x24, 0x23, 0x22 };
+static hda_nid_t alc882_capsrc_nids_alt[2] = { 0x23, 0x22 };
+
 /* input MUX */
 /* FIXME: should be a matrix-type input source selection */
 
@@ -5241,15 +5248,10 @@ static int alc882_mux_enum_put(struct snd_kcontrol *kcontrol,
 	struct alc_spec *spec = codec->spec;
 	const struct hda_input_mux *imux = spec->input_mux;
 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
-	static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 };
-	hda_nid_t nid;
+	hda_nid_t nid = spec->capsrc_nids[adc_idx];
 	unsigned int *cur_val = &spec->cur_mux[adc_idx];
 	unsigned int i, idx;
 
-	if (spec->num_adc_nids < 3)
-		nid = capture_mixers[adc_idx + 1];
-	else
-		nid = capture_mixers[adc_idx];
 	idx = ucontrol->value.enumerated.item[0];
 	if (idx >= imux->num_items)
 		idx = imux->num_items - 1;
@@ -6126,6 +6128,7 @@ static struct alc_config_preset alc882_presets[] = {
 		.dig_out_nid = ALC882_DIGOUT_NID,
 		.num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
 		.adc_nids = alc882_adc_nids,
+		.capsrc_nids = alc882_capsrc_nids,
 		.num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes),
 		.channel_mode = alc882_3ST_6ch_modes,
 		.need_dac_fix = 1,
@@ -6142,6 +6145,7 @@ static struct alc_config_preset alc882_presets[] = {
 		.dig_out_nid = ALC882_DIGOUT_NID,
 		.num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
 		.adc_nids = alc882_adc_nids,
+		.capsrc_nids = alc882_capsrc_nids,
 		.num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes),
 		.channel_mode = alc882_3ST_6ch_modes,
 		.need_dac_fix = 1,
@@ -6387,12 +6391,14 @@ static int patch_alc882(struct hda_codec *codec)
 		if (wcap != AC_WID_AUD_IN) {
 			spec->adc_nids = alc882_adc_nids_alt;
 			spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids_alt);
+			spec->capsrc_nids = alc882_capsrc_nids_alt;
 			spec->mixers[spec->num_mixers] =
 				alc882_capture_alt_mixer;
 			spec->num_mixers++;
 		} else {
 			spec->adc_nids = alc882_adc_nids;
 			spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids);
+			spec->capsrc_nids = alc882_capsrc_nids;
 			spec->mixers[spec->num_mixers] = alc882_capture_mixer;
 			spec->num_mixers++;
 		}
@@ -6435,6 +6441,8 @@ static hda_nid_t alc883_adc_nids[2] = {
 	0x08, 0x09,
 };
 
+static hda_nid_t alc883_capsrc_nids[2] = { 0x23, 0x22 };
+
 /* input MUX */
 /* FIXME: should be a matrix-type input source selection */
 
@@ -6468,33 +6476,8 @@ static struct hda_input_mux alc883_lenovo_nb0763_capture_source = {
 
 #define alc883_mux_enum_info alc_mux_enum_info
 #define alc883_mux_enum_get alc_mux_enum_get
-
-static int alc883_mux_enum_put(struct snd_kcontrol *kcontrol,
-			       struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct alc_spec *spec = codec->spec;
-	const struct hda_input_mux *imux = spec->input_mux;
-	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
-	static hda_nid_t capture_mixers[2] = { 0x23, 0x22 };
-	hda_nid_t nid = capture_mixers[adc_idx];
-	unsigned int *cur_val = &spec->cur_mux[adc_idx];
-	unsigned int i, idx;
-
-	idx = ucontrol->value.enumerated.item[0];
-	if (idx >= imux->num_items)
-		idx = imux->num_items - 1;
-	if (*cur_val == idx)
-		return 0;
-	for (i = 0; i < imux->num_items; i++) {
-		unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
-		snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
-					 imux->items[i].index,
-					 HDA_AMP_MUTE, v);
-	}
-	*cur_val = idx;
-	return 1;
-}
+/* ALC883 has the ALC882-type input selection */
+#define alc883_mux_enum_put alc882_mux_enum_put
 
 /*
  * 2ch mode
@@ -7667,8 +7650,6 @@ static struct alc_config_preset alc883_presets[] = {
 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
 		.dac_nids = alc883_dac_nids,
 		.dig_out_nid = ALC883_DIGOUT_NID,
-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-		.adc_nids = alc883_adc_nids,
 		.dig_in_nid = ALC883_DIGIN_NID,
 		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
 		.channel_mode = alc883_3ST_2ch_modes,
@@ -7680,8 +7661,6 @@ static struct alc_config_preset alc883_presets[] = {
 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
 		.dac_nids = alc883_dac_nids,
 		.dig_out_nid = ALC883_DIGOUT_NID,
-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-		.adc_nids = alc883_adc_nids,
 		.dig_in_nid = ALC883_DIGIN_NID,
 		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
 		.channel_mode = alc883_3ST_6ch_modes,
@@ -7693,8 +7672,6 @@ static struct alc_config_preset alc883_presets[] = {
 		.init_verbs = { alc883_init_verbs },
 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
 		.dac_nids = alc883_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-		.adc_nids = alc883_adc_nids,
 		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
 		.channel_mode = alc883_3ST_6ch_modes,
 		.need_dac_fix = 1,
@@ -7706,8 +7683,6 @@ static struct alc_config_preset alc883_presets[] = {
 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
 		.dac_nids = alc883_dac_nids,
 		.dig_out_nid = ALC883_DIGOUT_NID,
-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-		.adc_nids = alc883_adc_nids,
 		.dig_in_nid = ALC883_DIGIN_NID,
 		.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
 		.channel_mode = alc883_sixstack_modes,
@@ -7719,8 +7694,6 @@ static struct alc_config_preset alc883_presets[] = {
 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
 		.dac_nids = alc883_dac_nids,
 		.dig_out_nid = ALC883_DIGOUT_NID,
-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-		.adc_nids = alc883_adc_nids,
 		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
 		.channel_mode = alc883_3ST_6ch_modes,
 		.need_dac_fix = 1,
@@ -7734,8 +7707,6 @@ static struct alc_config_preset alc883_presets[] = {
 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
 		.dac_nids = alc883_dac_nids,
 		.dig_out_nid = ALC883_DIGOUT_NID,
-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-		.adc_nids = alc883_adc_nids,
 		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
 		.channel_mode = alc883_3ST_2ch_modes,
 		.input_mux = &alc883_capture_source,
@@ -7752,8 +7723,6 @@ static struct alc_config_preset alc883_presets[] = {
 		.init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs },
 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
 		.dac_nids = alc883_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-		.adc_nids = alc883_adc_nids,
 		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
 		.channel_mode = alc883_3ST_2ch_modes,
 		.input_mux = &alc883_capture_source,
@@ -7764,8 +7733,6 @@ static struct alc_config_preset alc883_presets[] = {
 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
 		.dac_nids = alc883_dac_nids,
 		.dig_out_nid = ALC883_DIGOUT_NID,
-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-		.adc_nids = alc883_adc_nids,
 		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
 		.channel_mode = alc883_3ST_2ch_modes,
 		.input_mux = &alc883_capture_source,
@@ -7779,8 +7746,6 @@ static struct alc_config_preset alc883_presets[] = {
 				alc883_medion_eapd_verbs },
 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
 		.dac_nids = alc883_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-		.adc_nids = alc883_adc_nids,
 		.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
 		.channel_mode = alc883_sixstack_modes,
 		.input_mux = &alc883_capture_source,
@@ -7791,8 +7756,6 @@ static struct alc_config_preset alc883_presets[] = {
 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
 		.dac_nids = alc883_dac_nids,
 		.dig_out_nid = ALC883_DIGOUT_NID,
-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-		.adc_nids = alc883_adc_nids,
 		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
 		.channel_mode = alc883_3ST_2ch_modes,
 		.input_mux = &alc883_capture_source,
@@ -7804,8 +7767,6 @@ static struct alc_config_preset alc883_presets[] = {
 		.init_verbs = { alc883_init_verbs, alc882_eapd_verbs },
 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
 		.dac_nids = alc883_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-		.adc_nids = alc883_adc_nids,
 		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
 		.channel_mode = alc883_3ST_2ch_modes,
 		.input_mux = &alc883_capture_source,
@@ -7815,8 +7776,6 @@ static struct alc_config_preset alc883_presets[] = {
 		.init_verbs = { alc883_init_verbs, alc883_lenovo_101e_verbs},
 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
 		.dac_nids = alc883_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-		.adc_nids = alc883_adc_nids,
 		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
 		.channel_mode = alc883_3ST_2ch_modes,
 		.input_mux = &alc883_lenovo_101e_capture_source,
@@ -7828,8 +7787,6 @@ static struct alc_config_preset alc883_presets[] = {
 		.init_verbs = { alc883_init_verbs, alc883_lenovo_nb0763_verbs},
 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
 		.dac_nids = alc883_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-		.adc_nids = alc883_adc_nids,
 		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
 		.channel_mode = alc883_3ST_2ch_modes,
 		.need_dac_fix = 1,
@@ -7843,8 +7800,6 @@ static struct alc_config_preset alc883_presets[] = {
 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
 		.dac_nids = alc883_dac_nids,
 		.dig_out_nid = ALC883_DIGOUT_NID,
-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-		.adc_nids = alc883_adc_nids,
 		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
 		.channel_mode = alc883_3ST_6ch_modes,
 		.need_dac_fix = 1,
@@ -7858,8 +7813,6 @@ static struct alc_config_preset alc883_presets[] = {
 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
 		.dac_nids = alc883_dac_nids,
 		.dig_out_nid = ALC883_DIGOUT_NID,
-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-		.adc_nids = alc883_adc_nids,
 		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
 		.channel_mode = alc883_3ST_2ch_modes,
 		.input_mux = &alc883_capture_source,
@@ -7872,8 +7825,6 @@ static struct alc_config_preset alc883_presets[] = {
 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
 		.dac_nids = alc883_dac_nids,
 		.dig_out_nid = ALC883_DIGOUT_NID,
-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-		.adc_nids = alc883_adc_nids,
 		.dig_in_nid = ALC883_DIGIN_NID,
 		.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
 		.channel_mode = alc883_sixstack_modes,
@@ -7884,8 +7835,6 @@ static struct alc_config_preset alc883_presets[] = {
 		.init_verbs = { alc883_init_verbs, alc888_3st_hp_verbs },
 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
 		.dac_nids = alc883_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-		.adc_nids = alc883_adc_nids,
 		.num_channel_mode = ARRAY_SIZE(alc888_3st_hp_modes),
 		.channel_mode = alc888_3st_hp_modes,
 		.need_dac_fix = 1,
@@ -7897,8 +7846,6 @@ static struct alc_config_preset alc883_presets[] = {
 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
 		.dac_nids = alc883_dac_nids,
 		.dig_out_nid = ALC883_DIGOUT_NID,
-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-		.adc_nids = alc883_adc_nids,
 		.dig_in_nid = ALC883_DIGIN_NID,
 		.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
 		.channel_mode = alc883_sixstack_modes,
@@ -7911,8 +7858,6 @@ static struct alc_config_preset alc883_presets[] = {
 		.init_verbs = { alc883_init_verbs, alc883_mitac_verbs },
 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
 		.dac_nids = alc883_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-		.adc_nids = alc883_adc_nids,
 		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
 		.channel_mode = alc883_3ST_2ch_modes,
 		.input_mux = &alc883_capture_source,
@@ -8072,10 +8017,9 @@ static int patch_alc883(struct hda_codec *codec)
 	spec->stream_digital_playback = &alc883_pcm_digital_playback;
 	spec->stream_digital_capture = &alc883_pcm_digital_capture;
 
-	if (!spec->adc_nids && spec->input_mux) {
-		spec->adc_nids = alc883_adc_nids;
-		spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids);
-	}
+	spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids);
+	spec->adc_nids = alc883_adc_nids;
+	spec->capsrc_nids = alc883_capsrc_nids;
 
 	spec->vmaster_nid = 0x0c;
 
@@ -9532,6 +9476,8 @@ static hda_nid_t alc268_adc_nids_alt[1] = {
 	0x08
 };
 
+static hda_nid_t alc268_capsrc_nids[2] = { 0x23, 0x24 };
+
 static struct snd_kcontrol_new alc268_base_mixer[] = {
 	/* output mixer control */
 	HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
@@ -9787,21 +9733,7 @@ static struct hda_verb alc268_volume_init_verbs[] = {
 
 #define alc268_mux_enum_info alc_mux_enum_info
 #define alc268_mux_enum_get alc_mux_enum_get
-
-static int alc268_mux_enum_put(struct snd_kcontrol *kcontrol,
-			       struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct alc_spec *spec = codec->spec;
-
-	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
-	static hda_nid_t capture_mixers[3] = { 0x23, 0x24 };
-	hda_nid_t nid = capture_mixers[adc_idx];
-
-	return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
-				     nid,
-				     &spec->cur_mux[adc_idx]);
-}
+#define alc268_mux_enum_put alc_mux_enum_put
 
 static struct snd_kcontrol_new alc268_capture_alt_mixer[] = {
 	HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
@@ -10145,6 +10077,7 @@ static struct alc_config_preset alc268_presets[] = {
 		.dac_nids = alc268_dac_nids,
                 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
                 .adc_nids = alc268_adc_nids_alt,
+		.capsrc_nids = alc268_capsrc_nids,
 		.hp_nid = 0x03,
 		.dig_out_nid = ALC268_DIGOUT_NID,
 		.num_channel_mode = ARRAY_SIZE(alc268_modes),
@@ -10159,6 +10092,7 @@ static struct alc_config_preset alc268_presets[] = {
 		.dac_nids = alc268_dac_nids,
 		.num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
 		.adc_nids = alc268_adc_nids_alt,
+		.capsrc_nids = alc268_capsrc_nids,
 		.hp_nid = 0x03,
 		.num_channel_mode = ARRAY_SIZE(alc268_modes),
 		.channel_mode = alc268_modes,
@@ -10174,6 +10108,7 @@ static struct alc_config_preset alc268_presets[] = {
 		.dac_nids = alc268_dac_nids,
 		.num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
 		.adc_nids = alc268_adc_nids_alt,
+		.capsrc_nids = alc268_capsrc_nids,
 		.hp_nid = 0x02,
 		.num_channel_mode = ARRAY_SIZE(alc268_modes),
 		.channel_mode = alc268_modes,
@@ -10202,6 +10137,7 @@ static struct alc_config_preset alc268_presets[] = {
 		.dac_nids = alc268_dac_nids,
 		.num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
 		.adc_nids = alc268_adc_nids_alt,
+		.capsrc_nids = alc268_capsrc_nids,
 		.hp_nid = 0x03,
 		.dig_out_nid = ALC268_DIGOUT_NID,
 		.num_channel_mode = ARRAY_SIZE(alc268_modes),
@@ -10219,6 +10155,7 @@ static struct alc_config_preset alc268_presets[] = {
 		.dac_nids = alc268_dac_nids,
 		.num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
 		.adc_nids = alc268_adc_nids_alt,
+		.capsrc_nids = alc268_capsrc_nids,
 		.hp_nid = 0x03,
 		.dig_out_nid = ALC268_DIGOUT_NID,
 		.num_channel_mode = ARRAY_SIZE(alc268_modes),
@@ -10294,6 +10231,7 @@ static int patch_alc268(struct hda_codec *codec)
 				alc268_capture_mixer;
 			spec->num_mixers++;
 		}
+		spec->capsrc_nids = alc268_capsrc_nids;
 	}
 
 	spec->vmaster_nid = 0x02;
@@ -11850,6 +11788,8 @@ static hda_nid_t alc861vd_adc_nids[1] = {
 	0x09,
 };
 
+static hda_nid_t alc861vd_capsrc_nids[1] = { 0x22 };
+
 /* input MUX */
 /* FIXME: should be a matrix-type input source selection */
 static struct hda_input_mux alc861vd_capture_source = {
@@ -11881,33 +11821,8 @@ static struct hda_input_mux alc861vd_hp_capture_source = {
 
 #define alc861vd_mux_enum_info alc_mux_enum_info
 #define alc861vd_mux_enum_get alc_mux_enum_get
-
-static int alc861vd_mux_enum_put(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct alc_spec *spec = codec->spec;
-	const struct hda_input_mux *imux = spec->input_mux;
-	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
-	static hda_nid_t capture_mixers[1] = { 0x22 };
-	hda_nid_t nid = capture_mixers[adc_idx];
-	unsigned int *cur_val = &spec->cur_mux[adc_idx];
-	unsigned int i, idx;
-
-	idx = ucontrol->value.enumerated.item[0];
-	if (idx >= imux->num_items)
-		idx = imux->num_items - 1;
-	if (*cur_val == idx)
-		return 0;
-	for (i = 0; i < imux->num_items; i++) {
-		unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
-		snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
-					 imux->items[i].index,
-					 HDA_AMP_MUTE, v);
-	}
-	*cur_val = idx;
-	return 1;
-}
+/* ALC861VD has the ALC882-type input selection (but has only one ADC) */
+#define alc861vd_mux_enum_put alc882_mux_enum_put
 
 /*
  * 2ch mode
@@ -12390,8 +12305,6 @@ static struct alc_config_preset alc861vd_presets[] = {
 				 alc861vd_3stack_init_verbs },
 		.num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
 		.dac_nids = alc660vd_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
-		.adc_nids = alc861vd_adc_nids,
 		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
 		.channel_mode = alc861vd_3stack_2ch_modes,
 		.input_mux = &alc861vd_capture_source,
@@ -12403,8 +12316,6 @@ static struct alc_config_preset alc861vd_presets[] = {
 		.num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
 		.dac_nids = alc660vd_dac_nids,
 		.dig_out_nid = ALC861VD_DIGOUT_NID,
-		.num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
-		.adc_nids = alc861vd_adc_nids,
 		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
 		.channel_mode = alc861vd_3stack_2ch_modes,
 		.input_mux = &alc861vd_capture_source,
@@ -12449,8 +12360,6 @@ static struct alc_config_preset alc861vd_presets[] = {
 				alc861vd_lenovo_unsol_verbs },
 		.num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
 		.dac_nids = alc660vd_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
-		.adc_nids = alc861vd_adc_nids,
 		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
 		.channel_mode = alc861vd_3stack_2ch_modes,
 		.input_mux = &alc861vd_capture_source,
@@ -12462,8 +12371,6 @@ static struct alc_config_preset alc861vd_presets[] = {
 		.init_verbs = { alc861vd_dallas_verbs },
 		.num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
 		.dac_nids = alc861vd_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
-		.adc_nids = alc861vd_adc_nids,
 		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
 		.channel_mode = alc861vd_3stack_2ch_modes,
 		.input_mux = &alc861vd_dallas_capture_source,
@@ -12475,9 +12382,7 @@ static struct alc_config_preset alc861vd_presets[] = {
 		.init_verbs = { alc861vd_dallas_verbs, alc861vd_eapd_verbs },
 		.num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
 		.dac_nids = alc861vd_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
 		.dig_out_nid = ALC861VD_DIGOUT_NID,
-		.adc_nids = alc861vd_adc_nids,
 		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
 		.channel_mode = alc861vd_3stack_2ch_modes,
 		.input_mux = &alc861vd_hp_capture_source,
@@ -12779,6 +12684,7 @@ static int patch_alc861vd(struct hda_codec *codec)
 
 	spec->adc_nids = alc861vd_adc_nids;
 	spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids);
+	spec->capsrc_nids = alc861vd_capsrc_nids;
 
 	spec->mixers[spec->num_mixers] = alc861vd_capture_mixer;
 	spec->num_mixers++;
@@ -12820,9 +12726,11 @@ static hda_nid_t alc662_adc_nids[1] = {
 	/* ADC1-2 */
 	0x09,
 };
+
+static hda_nid_t alc662_capsrc_nids[1] = { 0x23 };
+
 /* input MUX */
 /* FIXME: should be a matrix-type input source selection */
-
 static struct hda_input_mux alc662_capture_source = {
 	.num_items = 4,
 	.items = {
@@ -12851,33 +12759,8 @@ static struct hda_input_mux alc662_eeepc_capture_source = {
 
 #define alc662_mux_enum_info alc_mux_enum_info
 #define alc662_mux_enum_get alc_mux_enum_get
+#define alc662_mux_enum_put alc882_mux_enum_put
 
-static int alc662_mux_enum_put(struct snd_kcontrol *kcontrol,
-			       struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct alc_spec *spec = codec->spec;
-	const struct hda_input_mux *imux = spec->input_mux;
-	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
-	static hda_nid_t capture_mixers[2] = { 0x23, 0x22 };
-	hda_nid_t nid = capture_mixers[adc_idx];
-	unsigned int *cur_val = &spec->cur_mux[adc_idx];
-	unsigned int i, idx;
-
-	idx = ucontrol->value.enumerated.item[0];
-	if (idx >= imux->num_items)
-		idx = imux->num_items - 1;
-	if (*cur_val == idx)
-		return 0;
-	for (i = 0; i < imux->num_items; i++) {
-		unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
-		snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
-					 imux->items[i].index,
-					 HDA_AMP_MUTE, v);
-	}
-	*cur_val = idx;
-	return 1;
-}
 /*
  * 2ch mode
  */
@@ -13354,8 +13237,6 @@ static struct alc_config_preset alc662_presets[] = {
 		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
 		.dac_nids = alc662_dac_nids,
 		.dig_out_nid = ALC662_DIGOUT_NID,
-		.num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
-		.adc_nids = alc662_adc_nids,
 		.dig_in_nid = ALC662_DIGIN_NID,
 		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
 		.channel_mode = alc662_3ST_2ch_modes,
@@ -13368,8 +13249,6 @@ static struct alc_config_preset alc662_presets[] = {
 		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
 		.dac_nids = alc662_dac_nids,
 		.dig_out_nid = ALC662_DIGOUT_NID,
-		.num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
-		.adc_nids = alc662_adc_nids,
 		.dig_in_nid = ALC662_DIGIN_NID,
 		.num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
 		.channel_mode = alc662_3ST_6ch_modes,
@@ -13382,8 +13261,6 @@ static struct alc_config_preset alc662_presets[] = {
 		.init_verbs = { alc662_init_verbs },
 		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
 		.dac_nids = alc662_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
-		.adc_nids = alc662_adc_nids,
 		.num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
 		.channel_mode = alc662_3ST_6ch_modes,
 		.need_dac_fix = 1,
@@ -13396,8 +13273,6 @@ static struct alc_config_preset alc662_presets[] = {
 		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
 		.dac_nids = alc662_dac_nids,
 		.dig_out_nid = ALC662_DIGOUT_NID,
-		.num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
-		.adc_nids = alc662_adc_nids,
 		.dig_in_nid = ALC662_DIGIN_NID,
 		.num_channel_mode = ARRAY_SIZE(alc662_5stack_modes),
 		.channel_mode = alc662_5stack_modes,
@@ -13408,8 +13283,6 @@ static struct alc_config_preset alc662_presets[] = {
 		.init_verbs = { alc662_init_verbs, alc662_sue_init_verbs },
 		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
 		.dac_nids = alc662_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
-		.adc_nids = alc662_adc_nids,
 		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
 		.channel_mode = alc662_3ST_2ch_modes,
 		.input_mux = &alc662_lenovo_101e_capture_source,
@@ -13422,8 +13295,6 @@ static struct alc_config_preset alc662_presets[] = {
 				alc662_eeepc_sue_init_verbs },
 		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
 		.dac_nids = alc662_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
-		.adc_nids = alc662_adc_nids,
 		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
 		.channel_mode = alc662_3ST_2ch_modes,
 		.input_mux = &alc662_eeepc_capture_source,
@@ -13437,8 +13308,6 @@ static struct alc_config_preset alc662_presets[] = {
 				alc662_eeepc_ep20_sue_init_verbs },
 		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
 		.dac_nids = alc662_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
-		.adc_nids = alc662_adc_nids,
 		.num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
 		.channel_mode = alc662_3ST_6ch_modes,
 		.input_mux = &alc662_lenovo_101e_capture_source,
@@ -13750,10 +13619,9 @@ static int patch_alc662(struct hda_codec *codec)
 	spec->stream_digital_playback = &alc662_pcm_digital_playback;
 	spec->stream_digital_capture = &alc662_pcm_digital_capture;
 
-	if (!spec->adc_nids && spec->input_mux) {
-		spec->adc_nids = alc662_adc_nids;
-		spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids);
-	}
+	spec->adc_nids = alc662_adc_nids;
+	spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids);
+	spec->capsrc_nids = alc662_capsrc_nids;
 
 	spec->vmaster_nid = 0x02;
 
-- 
cgit v1.2.3-70-g09d2


From 5d5d5f43f1b835c375de9bd270cce030d16e2871 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Tue, 12 Feb 2008 12:11:36 +0100
Subject: [ALSA] hda-codec - Implement auto-mic jack sensing on Samsung laptops

Implemented the auto-mic jack sensing for Samsung laptops with AD1986A
codec chip (model=laptop-eapd).

The hardware uses pin 0x1d and 0x1f for the internal and external
mics, respectively.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_analog.c | 53 ++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 49 insertions(+), 4 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 9d0d2a1bbd6..266c35e32b6 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -612,13 +612,19 @@ static struct hda_input_mux ad1986a_laptop_eapd_capture_source = {
 	},
 };
 
+static struct hda_input_mux ad1986a_automic_capture_source = {
+	.num_items = 2,
+	.items = {
+		{ "Mic", 0x0 },
+		{ "Mix", 0x5 },
+	},
+};
+
 static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {
 	HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
 	HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
 	HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
 	HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0x0, HDA_OUTPUT),
 	HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
 	HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
 	HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
@@ -642,6 +648,33 @@ static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {
 	{ } /* end */
 };
 
+/* re-connect the mic boost input according to the jack sensing */
+static void ad1986a_automic(struct hda_codec *codec)
+{
+	unsigned int present;
+	present = snd_hda_codec_read(codec, 0x1f, 0, AC_VERB_GET_PIN_SENSE, 0);
+	/* 0 = 0x1f, 2 = 0x1d, 4 = mixed */
+	snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_CONNECT_SEL,
+			    (present & AC_PINSENSE_PRESENCE) ? 0 : 2);
+}
+
+#define AD1986A_MIC_EVENT		0x36
+
+static void ad1986a_automic_unsol_event(struct hda_codec *codec,
+					    unsigned int res)
+{
+	if ((res >> 26) != AD1986A_MIC_EVENT)
+		return;
+	ad1986a_automic(codec);
+}
+
+static int ad1986a_automic_init(struct hda_codec *codec)
+{
+	ad198x_init(codec);
+	ad1986a_automic(codec);
+	return 0;
+}
+
 /* laptop-automute - 2ch only */
 
 static void ad1986a_update_hp(struct hda_codec *codec)
@@ -845,6 +878,15 @@ static struct hda_verb ad1986a_eapd_init_verbs[] = {
 	{}
 };
 
+static struct hda_verb ad1986a_automic_verbs[] = {
+	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	/*{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},*/
+	{0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
+	{0x1f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_MIC_EVENT},
+	{}
+};
+
 /* Ultra initialization */
 static struct hda_verb ad1986a_ultra_init[] = {
 	/* eapd initialization */
@@ -987,14 +1029,17 @@ static int patch_ad1986a(struct hda_codec *codec)
 		break;
 	case AD1986A_LAPTOP_EAPD:
 		spec->mixers[0] = ad1986a_laptop_eapd_mixers;
-		spec->num_init_verbs = 2;
+		spec->num_init_verbs = 3;
 		spec->init_verbs[1] = ad1986a_eapd_init_verbs;
+		spec->init_verbs[2] = ad1986a_automic_verbs;
 		spec->multiout.max_channels = 2;
 		spec->multiout.num_dacs = 1;
 		spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
 		if (!is_jack_available(codec, 0x25))
 			spec->multiout.dig_out_nid = 0;
-		spec->input_mux = &ad1986a_laptop_eapd_capture_source;
+		spec->input_mux = &ad1986a_automic_capture_source;
+		codec->patch_ops.unsol_event = ad1986a_automic_unsol_event;
+		codec->patch_ops.init = ad1986a_automic_init;
 		break;
 	case AD1986A_LAPTOP_AUTOMUTE:
 		spec->mixers[0] = ad1986a_laptop_automute_mixers;
-- 
cgit v1.2.3-70-g09d2


From 5832fcf8b55cfdbd7d8511f747d15fd20ed4703d Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Tue, 12 Feb 2008 18:30:12 +0100
Subject: [ALSA] hda-codec - More fix-up for auto-configuration

In some cases, the BIOS sets up only the HP pins with different assoc
and sequence numbers, e.g. on FSC Esprimo with ALC262.

This patch adds a fix-up for such a case.  When multiple HPs are defined
and no line-outs is found, the configurator tries to re-assign some pins
from HP list to line-out, judging from the sequence number.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/hda_codec.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

(limited to 'sound')

diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index ab3bb7997cd..af2c8943b30 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -2821,6 +2821,30 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
 		}
 	}
 
+	/* FIX-UP:
+	 * If no line-out is defined but multiple HPs are found,
+	 * some of them might be the real line-outs.
+	 */
+	if (!cfg->line_outs && cfg->hp_outs > 1) {
+		int i = 0;
+		while (i < cfg->hp_outs) {
+			/* The real HPs should have the sequence 0x0f */
+			if ((sequences_hp[i] & 0x0f) == 0x0f) {
+				i++;
+				continue;
+			}
+			/* Move it to the line-out table */
+			cfg->line_out_pins[cfg->line_outs] = cfg->hp_pins[i];
+			sequences_line_out[cfg->line_outs] = sequences_hp[i];
+			cfg->line_outs++;
+			cfg->hp_outs--;
+			memmove(cfg->hp_pins + i, cfg->hp_pins + i + 1,
+				sizeof(cfg->hp_pins[0]) * (cfg->hp_outs - i));
+			memmove(sequences_hp + i - 1, sequences_hp + i,
+				sizeof(sequences_hp[0]) * (cfg->hp_outs - i));
+		}
+	}
+
 	/* sort by sequence */
 	sort_pins_by_sequence(cfg->line_out_pins, sequences_line_out,
 			      cfg->line_outs);
-- 
cgit v1.2.3-70-g09d2


From f6c7e5461e9046445d50c5c7a9a4587824239623 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Tue, 12 Feb 2008 18:32:23 +0100
Subject: [ALSA] hda-codec - Fix auto-configuration of Realtek codecs

This patch fixes some bugs in the auto-configurator of Realtek codecs:
- add missing pin set-up for speaker pins
- fix the speaker auto-mute function not to conflict with the existing
  "Speaker" mixer switch

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c | 111 ++++++++++++++++++++++++------------------
 1 file changed, 63 insertions(+), 48 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index f1fa1d24936..d41eafacd86 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -746,7 +746,6 @@ static struct hda_verb alc_gpio3_init_verbs[] = {
 static void alc_sku_automute(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
-	unsigned int mute;
 	unsigned int present;
 	unsigned int hp_nid = spec->autocfg.hp_pins[0];
 	unsigned int sp_nid = spec->autocfg.speaker_pins[0];
@@ -756,16 +755,8 @@ static void alc_sku_automute(struct hda_codec *codec)
 	present = snd_hda_codec_read(codec, hp_nid, 0,
 				     AC_VERB_GET_PIN_SENSE, 0);
 	spec->jack_present = (present & 0x80000000) != 0;
-	if (spec->jack_present) {
-		/* mute internal speaker */
-		snd_hda_codec_amp_stereo(codec, sp_nid, HDA_OUTPUT, 0,
-					 HDA_AMP_MUTE, HDA_AMP_MUTE);
-	} else {
-		/* unmute internal speaker if necessary */
-		mute = snd_hda_codec_amp_read(codec, hp_nid, 0, HDA_OUTPUT, 0);
-		snd_hda_codec_amp_stereo(codec, sp_nid, HDA_OUTPUT, 0,
-					 HDA_AMP_MUTE, mute);
-	}
+	snd_hda_codec_write(codec, sp_nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+			    spec->jack_present ? 0 : PIN_OUT);
 }
 
 /* unsolicited event for HP jack sensing */
@@ -3486,15 +3477,20 @@ static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec,
 	return 0;
 }
 
+static void alc_set_pin_output(struct hda_codec *codec, hda_nid_t nid,
+			       unsigned int pin_type)
+{
+	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+			    pin_type);
+	/* unmute pin */
+	snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, 0xff, 0x00);
+}
+
 static void alc880_auto_set_output_and_unmute(struct hda_codec *codec,
 					      hda_nid_t nid, int pin_type,
 					      int dac_idx)
 {
-	/* set as output */
-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
-			    pin_type);
-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
-			    AMP_OUT_UNMUTE);
+	alc_set_pin_output(codec, nid, pin_type);
 	/* need the manual connection? */
 	if (alc880_is_multi_pin(nid)) {
 		struct alc_spec *spec = codec->spec;
@@ -3616,9 +3612,12 @@ static int alc880_parse_auto_config(struct hda_codec *codec)
 /* additional initialization for auto-configuration model */
 static void alc880_auto_init(struct hda_codec *codec)
 {
+	struct alc_spec *spec = codec->spec;
 	alc880_auto_init_multi_out(codec);
 	alc880_auto_init_extra_out(codec);
 	alc880_auto_init_analog_input(codec);
+	if (spec->unsol_event)
+		alc_sku_automute(codec);
 }
 
 /*
@@ -4814,11 +4813,7 @@ static void alc260_auto_set_output_and_unmute(struct hda_codec *codec,
 					      hda_nid_t nid, int pin_type,
 					      int sel_idx)
 {
-	/* set as output */
-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
-			    pin_type);
-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
-			    AMP_OUT_UNMUTE);
+	alc_set_pin_output(codec, nid, pin_type);
 	/* need the manual connection? */
 	if (nid >= 0x12) {
 		int idx = nid - 0x12;
@@ -4965,8 +4960,11 @@ static int alc260_parse_auto_config(struct hda_codec *codec)
 /* additional initialization for auto-configuration model */
 static void alc260_auto_init(struct hda_codec *codec)
 {
+	struct alc_spec *spec = codec->spec;
 	alc260_auto_init_multi_out(codec);
 	alc260_auto_init_analog_input(codec);
+	if (spec->unsol_event)
+		alc_sku_automute(codec);
 }
 
 #ifdef CONFIG_SND_HDA_POWER_SAVE
@@ -6201,15 +6199,11 @@ static void alc882_auto_set_output_and_unmute(struct hda_codec *codec,
 	struct alc_spec *spec = codec->spec;
 	int idx;
 
+	alc_set_pin_output(codec, nid, pin_type);
 	if (spec->multiout.dac_nids[dac_idx] == 0x25)
 		idx = 4;
 	else
 		idx = spec->multiout.dac_nids[dac_idx] - 2;
-
-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
-			    pin_type);
-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
-			    AMP_OUT_UNMUTE);
 	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
 
 }
@@ -6238,6 +6232,9 @@ static void alc882_auto_init_hp_out(struct hda_codec *codec)
 	if (pin) /* connect to front */
 		/* use dac 0 */
 		alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
+	pin = spec->autocfg.speaker_pins[0];
+	if (pin)
+		alc882_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
 }
 
 #define alc882_is_input_pin(nid)	alc880_is_input_pin(nid)
@@ -6313,9 +6310,12 @@ static int alc882_parse_auto_config(struct hda_codec *codec)
 /* additional initialization for auto-configuration model */
 static void alc882_auto_init(struct hda_codec *codec)
 {
+	struct alc_spec *spec = codec->spec;
 	alc882_auto_init_multi_out(codec);
 	alc882_auto_init_hp_out(codec);
 	alc882_auto_init_analog_input(codec);
+	if (spec->unsol_event)
+		alc_sku_automute(codec);
 }
 
 static int patch_alc882(struct hda_codec *codec)
@@ -7878,15 +7878,11 @@ static void alc883_auto_set_output_and_unmute(struct hda_codec *codec,
 	struct alc_spec *spec = codec->spec;
 	int idx;
 
+	alc_set_pin_output(codec, nid, pin_type);
 	if (spec->multiout.dac_nids[dac_idx] == 0x25)
 		idx = 4;
 	else
 		idx = spec->multiout.dac_nids[dac_idx] - 2;
-
-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
-			    pin_type);
-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
-			    AMP_OUT_UNMUTE);
 	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
 
 }
@@ -7915,6 +7911,9 @@ static void alc883_auto_init_hp_out(struct hda_codec *codec)
 	if (pin) /* connect to front */
 		/* use dac 0 */
 		alc883_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
+	pin = spec->autocfg.speaker_pins[0];
+	if (pin)
+		alc883_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
 }
 
 #define alc883_is_input_pin(nid)	alc880_is_input_pin(nid)
@@ -7966,9 +7965,12 @@ static int alc883_parse_auto_config(struct hda_codec *codec)
 /* additional initialization for auto-configuration model */
 static void alc883_auto_init(struct hda_codec *codec)
 {
+	struct alc_spec *spec = codec->spec;
 	alc883_auto_init_multi_out(codec);
 	alc883_auto_init_hp_out(codec);
 	alc883_auto_init_analog_input(codec);
+	if (spec->unsol_event)
+		alc_sku_automute(codec);
 }
 
 static int patch_alc883(struct hda_codec *codec)
@@ -9144,9 +9146,12 @@ static int alc262_parse_auto_config(struct hda_codec *codec)
 /* init callback for auto-configuration model -- overriding the default init */
 static void alc262_auto_init(struct hda_codec *codec)
 {
+	struct alc_spec *spec = codec->spec;
 	alc262_auto_init_multi_out(codec);
 	alc262_auto_init_hp_out(codec);
 	alc262_auto_init_analog_input(codec);
+	if (spec->unsol_event)
+		alc_sku_automute(codec);
 }
 
 /*
@@ -10033,10 +10038,13 @@ static int alc268_parse_auto_config(struct hda_codec *codec)
 /* init callback for auto-configuration model -- overriding the default init */
 static void alc268_auto_init(struct hda_codec *codec)
 {
+	struct alc_spec *spec = codec->spec;
 	alc268_auto_init_multi_out(codec);
 	alc268_auto_init_hp_out(codec);
 	alc268_auto_init_mono_speaker_out(codec);
 	alc268_auto_init_analog_input(codec);
+	if (spec->unsol_event)
+		alc_sku_automute(codec);
 }
 
 /*
@@ -10505,9 +10513,12 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
 /* init callback for auto-configuration model -- overriding the default init */
 static void alc269_auto_init(struct hda_codec *codec)
 {
+	struct alc_spec *spec = codec->spec;
 	alc269_auto_init_multi_out(codec);
 	alc269_auto_init_hp_out(codec);
 	alc269_auto_init_analog_input(codec);
+	if (spec->unsol_event)
+		alc_sku_automute(codec);
 }
 
 /*
@@ -11429,13 +11440,7 @@ static void alc861_auto_set_output_and_unmute(struct hda_codec *codec,
 					      hda_nid_t nid,
 					      int pin_type, int dac_idx)
 {
-	/* set as output */
-
-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
-			    pin_type);
-	snd_hda_codec_write(codec, dac_idx, 0, AC_VERB_SET_AMP_GAIN_MUTE,
-			    AMP_OUT_UNMUTE);
-
+	alc_set_pin_output(codec, nid, pin_type);
 }
 
 static void alc861_auto_init_multi_out(struct hda_codec *codec)
@@ -11462,6 +11467,9 @@ static void alc861_auto_init_hp_out(struct hda_codec *codec)
 	if (pin) /* connect to front */
 		alc861_auto_set_output_and_unmute(codec, pin, PIN_HP,
 						  spec->multiout.dac_nids[0]);
+	pin = spec->autocfg.speaker_pins[0];
+	if (pin)
+		alc861_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
 }
 
 static void alc861_auto_init_analog_input(struct hda_codec *codec)
@@ -11534,9 +11542,12 @@ static int alc861_parse_auto_config(struct hda_codec *codec)
 /* additional initialization for auto-configuration model */
 static void alc861_auto_init(struct hda_codec *codec)
 {
+	struct alc_spec *spec = codec->spec;
 	alc861_auto_init_multi_out(codec);
 	alc861_auto_init_hp_out(codec);
 	alc861_auto_init_analog_input(codec);
+	if (spec->unsol_event)
+		alc_sku_automute(codec);
 }
 
 #ifdef CONFIG_SND_HDA_POWER_SAVE
@@ -12397,11 +12408,7 @@ static struct alc_config_preset alc861vd_presets[] = {
 static void alc861vd_auto_set_output_and_unmute(struct hda_codec *codec,
 				hda_nid_t nid, int pin_type, int dac_idx)
 {
-	/* set as output */
-	snd_hda_codec_write(codec, nid, 0,
-				AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
-	snd_hda_codec_write(codec, nid, 0,
-				AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
+	alc_set_pin_output(codec, nid, pin_type);
 }
 
 static void alc861vd_auto_init_multi_out(struct hda_codec *codec)
@@ -12428,6 +12435,9 @@ static void alc861vd_auto_init_hp_out(struct hda_codec *codec)
 	pin = spec->autocfg.hp_pins[0];
 	if (pin) /* connect to front and  use dac 0 */
 		alc861vd_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
+	pin = spec->autocfg.speaker_pins[0];
+	if (pin)
+		alc861vd_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
 }
 
 #define alc861vd_is_input_pin(nid)	alc880_is_input_pin(nid)
@@ -12631,9 +12641,12 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec)
 /* additional initialization for auto-configuration model */
 static void alc861vd_auto_init(struct hda_codec *codec)
 {
+	struct alc_spec *spec = codec->spec;
 	alc861vd_auto_init_multi_out(codec);
 	alc861vd_auto_init_hp_out(codec);
 	alc861vd_auto_init_analog_input(codec);
+	if (spec->unsol_event)
+		alc_sku_automute(codec);
 }
 
 static int patch_alc861vd(struct hda_codec *codec)
@@ -13453,11 +13466,7 @@ static void alc662_auto_set_output_and_unmute(struct hda_codec *codec,
 					      hda_nid_t nid, int pin_type,
 					      int dac_idx)
 {
-	/* set as output */
-	snd_hda_codec_write(codec, nid, 0,
-			    AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
-	snd_hda_codec_write(codec, nid, 0,
-			    AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
+	alc_set_pin_output(codec, nid, pin_type);
 	/* need the manual connection? */
 	if (alc880_is_multi_pin(nid)) {
 		struct alc_spec *spec = codec->spec;
@@ -13492,6 +13501,9 @@ static void alc662_auto_init_hp_out(struct hda_codec *codec)
 	if (pin) /* connect to front */
 		/* use dac 0 */
 		alc662_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
+	pin = spec->autocfg.speaker_pins[0];
+	if (pin)
+		alc662_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
 }
 
 #define alc662_is_input_pin(nid)	alc880_is_input_pin(nid)
@@ -13569,9 +13581,12 @@ static int alc662_parse_auto_config(struct hda_codec *codec)
 /* additional initialization for auto-configuration model */
 static void alc662_auto_init(struct hda_codec *codec)
 {
+	struct alc_spec *spec = codec->spec;
 	alc662_auto_init_multi_out(codec);
 	alc662_auto_init_hp_out(codec);
 	alc662_auto_init_analog_input(codec);
+	if (spec->unsol_event)
+		alc_sku_automute(codec);
 }
 
 static int patch_alc662(struct hda_codec *codec)
-- 
cgit v1.2.3-70-g09d2


From 9a08160bdbe3148a405f72798f76e2a5d30bd243 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Tue, 12 Feb 2008 18:37:26 +0100
Subject: [ALSA] hda-codec - Add "IEC958 Default PCM" switch

Added a new mixer switch to enable/disable the sharing of the default
PCM stream with analog and SPDIF outputs.  When "IEC958 Default PCM"
switch is on, the PCM stream is routed both to analog and SPDIF outputs.
This is the behavior in the earlier version.

Turning this switch off has a merit for some codecs, though.  Some codec
chips don't support 24bit formats for SPDIF but only for analog outputs.
In this case, you can use 24bit format by disabling this switch.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/hda_codec.c      | 73 +++++++++++++++++++++++++++++++++++++++---
 sound/pci/hda/hda_local.h      | 13 +++++++-
 sound/pci/hda/patch_analog.c   |  8 ++++-
 sound/pci/hda/patch_cmedia.c   |  8 ++++-
 sound/pci/hda/patch_conexant.c |  8 ++++-
 sound/pci/hda/patch_realtek.c  |  8 ++++-
 sound/pci/hda/patch_sigmatel.c |  8 ++++-
 sound/pci/hda/patch_via.c      |  8 ++++-
 8 files changed, 123 insertions(+), 11 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index af2c8943b30..853e5c786c3 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -1532,6 +1532,43 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
 	return 0;
 }
 
+/*
+ * SPDIF sharing with analog output
+ */
+static int spdif_share_sw_get(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
+	ucontrol->value.integer.value[0] = mout->share_spdif;
+	return 0;
+}
+
+static int spdif_share_sw_put(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
+	mout->share_spdif = !!ucontrol->value.integer.value[0];
+	return 0;
+}
+
+static struct snd_kcontrol_new spdif_share_sw = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "IEC958 Default PCM Playback Switch",
+	.info = snd_ctl_boolean_mono_info,
+	.get = spdif_share_sw_get,
+	.put = spdif_share_sw_put,
+};
+
+int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
+				  struct hda_multi_out *mout)
+{
+	if (!mout->dig_out_nid)
+		return 0;
+	/* ATTENTION: here mout is passed as private_data, instead of codec */
+	return snd_ctl_add(codec->bus->card,
+			   snd_ctl_new1(&spdif_share_sw, mout));
+}
+
 /*
  * SPDIF input
  */
@@ -2557,9 +2594,36 @@ int snd_hda_multi_out_dig_close(struct hda_codec *codec,
  */
 int snd_hda_multi_out_analog_open(struct hda_codec *codec,
 				  struct hda_multi_out *mout,
-				  struct snd_pcm_substream *substream)
-{
-	substream->runtime->hw.channels_max = mout->max_channels;
+				  struct snd_pcm_substream *substream,
+				  struct hda_pcm_stream *hinfo)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	runtime->hw.channels_max = mout->max_channels;
+	if (mout->dig_out_nid) {
+		if (!mout->analog_rates) {
+			mout->analog_rates = hinfo->rates;
+			mout->analog_formats = hinfo->formats;
+			mout->analog_maxbps = hinfo->maxbps;
+		} else {
+			runtime->hw.rates = mout->analog_rates;
+			runtime->hw.formats = mout->analog_formats;
+			hinfo->maxbps = mout->analog_maxbps;
+		}
+		if (!mout->spdif_rates) {
+			snd_hda_query_supported_pcm(codec, mout->dig_out_nid,
+						    &mout->spdif_rates,
+						    &mout->spdif_formats,
+						    &mout->spdif_maxbps);
+		}
+		mutex_lock(&codec->spdif_mutex);
+		if (mout->share_spdif) {
+			runtime->hw.rates &= mout->spdif_rates;
+			runtime->hw.formats &= mout->spdif_formats;
+			if (mout->spdif_maxbps < hinfo->maxbps)
+				hinfo->maxbps = mout->spdif_maxbps;
+		}
+	}
+	mutex_unlock(&codec->spdif_mutex);
 	return snd_pcm_hw_constraint_step(substream->runtime, 0,
 					  SNDRV_PCM_HW_PARAM_CHANNELS, 2);
 }
@@ -2579,7 +2643,8 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
 	int i;
 
 	mutex_lock(&codec->spdif_mutex);
-	if (mout->dig_out_nid && mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
+	if (mout->dig_out_nid && mout->share_spdif &&
+	    mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
 		if (chs == 2 &&
 		    snd_hda_is_supported_format(codec, mout->dig_out_nid,
 						format) &&
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index ad0014ab71f..ce2ad42a8a8 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -228,8 +228,18 @@ struct hda_multi_out {
 	int max_channels;	/* currently supported analog channels */
 	int dig_out_used;	/* current usage of digital out (HDA_DIG_XXX) */
 	int no_share_stream;	/* don't share a stream with multiple pins */
+	int share_spdif;	/* share SPDIF pin */
+	/* PCM information for both analog and SPDIF DACs */
+	unsigned int analog_rates;
+	unsigned int analog_maxbps;
+	u64 analog_formats;
+	unsigned int spdif_rates;
+	unsigned int spdif_maxbps;
+	u64 spdif_formats;
 };
 
+int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
+				  struct hda_multi_out *mout);
 int snd_hda_multi_out_dig_open(struct hda_codec *codec,
 			       struct hda_multi_out *mout);
 int snd_hda_multi_out_dig_close(struct hda_codec *codec,
@@ -241,7 +251,8 @@ int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
 				  struct snd_pcm_substream *substream);
 int snd_hda_multi_out_analog_open(struct hda_codec *codec,
 				  struct hda_multi_out *mout,
-				  struct snd_pcm_substream *substream);
+				  struct snd_pcm_substream *substream,
+				  struct hda_pcm_stream *hinfo);
 int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
 				     struct hda_multi_out *mout,
 				     unsigned int stream_tag,
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 266c35e32b6..1f2102860fe 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -171,6 +171,11 @@ static int ad198x_build_controls(struct hda_codec *codec)
 		err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
 		if (err < 0)
 			return err;
+		err = snd_hda_create_spdif_share_sw(codec,
+						    &spec->multiout);
+		if (err < 0)
+			return err;
+		spec->multiout.share_spdif = 1;
 	} 
 	if (spec->dig_in_nid) {
 		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
@@ -217,7 +222,8 @@ static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo,
 				    struct snd_pcm_substream *substream)
 {
 	struct ad198x_spec *spec = codec->spec;
-	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
+	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
+					     hinfo);
 }
 
 static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c
index 99ce74b4e9f..9794d4166ae 100644
--- a/sound/pci/hda/patch_cmedia.c
+++ b/sound/pci/hda/patch_cmedia.c
@@ -329,6 +329,11 @@ static int cmi9880_build_controls(struct hda_codec *codec)
 		err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
 		if (err < 0)
 			return err;
+		err = snd_hda_create_spdif_share_sw(codec,
+						    &spec->multiout);
+		if (err < 0)
+			return err;
+		spec->multiout.share_spdif = 1;
 	}
 	if (spec->dig_in_nid) {
 		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
@@ -432,7 +437,8 @@ static int cmi9880_playback_pcm_open(struct hda_pcm_stream *hinfo,
 				     struct snd_pcm_substream *substream)
 {
 	struct cmi_spec *spec = codec->spec;
-	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
+	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
+					     hinfo);
 }
 
 static int cmi9880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index bb915ede0ce..2bb9a58db9f 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -98,7 +98,8 @@ static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo,
 				      struct snd_pcm_substream *substream)
 {
 	struct conexant_spec *spec = codec->spec;
-	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
+	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
+					     hinfo);
 }
 
 static int conexant_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
@@ -372,6 +373,11 @@ static int conexant_build_controls(struct hda_codec *codec)
 						    spec->multiout.dig_out_nid);
 		if (err < 0)
 			return err;
+		err = snd_hda_create_spdif_share_sw(codec,
+						    &spec->multiout);
+		if (err < 0)
+			return err;
+		spec->multiout.share_spdif = 1;
 	} 
 	if (spec->dig_in_nid) {
 		err = snd_hda_create_spdif_in_ctls(codec,spec->dig_in_nid);
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index d41eafacd86..6c605813fc6 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -1520,6 +1520,11 @@ static int alc_build_controls(struct hda_codec *codec)
 						    spec->multiout.dig_out_nid);
 		if (err < 0)
 			return err;
+		err = snd_hda_create_spdif_share_sw(codec,
+						    &spec->multiout);
+		if (err < 0)
+			return err;
+		spec->multiout.share_spdif = 1;
 	}
 	if (spec->dig_in_nid) {
 		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
@@ -2325,7 +2330,8 @@ static int alc880_playback_pcm_open(struct hda_pcm_stream *hinfo,
 				    struct snd_pcm_substream *substream)
 {
 	struct alc_spec *spec = codec->spec;
-	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
+	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
+					     hinfo);
 }
 
 static int alc880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 7f506ef0acc..7901e76f269 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -916,6 +916,11 @@ static int stac92xx_build_controls(struct hda_codec *codec)
 		err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
 		if (err < 0)
 			return err;
+		err = snd_hda_create_spdif_share_sw(codec,
+						    &spec->multiout);
+		if (err < 0)
+			return err;
+		spec->multiout.share_spdif = 1;
 	}
 	if (spec->dig_in_nid) {
 		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
@@ -1748,7 +1753,8 @@ static int stac92xx_playback_pcm_open(struct hda_pcm_stream *hinfo,
 				      struct snd_pcm_substream *substream)
 {
 	struct sigmatel_spec *spec = codec->spec;
-	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
+	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
+					     hinfo);
 }
 
 static int stac92xx_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index d9a5c6a2dd9..3515a3fb5d9 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -357,7 +357,8 @@ static int via_playback_pcm_open(struct hda_pcm_stream *hinfo,
 				 struct snd_pcm_substream *substream)
 {
 	struct via_spec *spec = codec->spec;
-	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
+	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
+					     hinfo);
 }
 
 static int via_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
@@ -493,6 +494,11 @@ static int via_build_controls(struct hda_codec *codec)
 						    spec->multiout.dig_out_nid);
 		if (err < 0)
 			return err;
+		err = snd_hda_create_spdif_share_sw(codec,
+						    &spec->multiout);
+		if (err < 0)
+			return err;
+		spec->multiout.share_spdif = 1;
 	}
 	if (spec->dig_in_nid) {
 		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
-- 
cgit v1.2.3-70-g09d2


From c8cd1281171602033861d0888273e0512f9b165c Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Wed, 13 Feb 2008 16:59:29 +0100
Subject: [ALSA] hda-codec - Add more names to vendor list

Added more known names to the vendor id list.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/hda_codec.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

(limited to 'sound')

diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 853e5c786c3..8ab88d9ba3b 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -51,13 +51,18 @@ struct hda_vendor_id {
 
 /* codec vendor labels */
 static struct hda_vendor_id hda_vendor_ids[] = {
-	{ 0x10ec, "Realtek" },
+	{ 0x1002, "ATI" },
 	{ 0x1057, "Motorola" },
+	{ 0x1095, "Silicon Image" },
+	{ 0x10ec, "Realtek" },
 	{ 0x1106, "VIA" },
 	{ 0x111d, "IDT" },
+	{ 0x11c1, "LSI" },
 	{ 0x11d4, "Analog Devices" },
 	{ 0x13f6, "C-Media" },
 	{ 0x14f1, "Conexant" },
+	{ 0x17e8, "Chrontel" },
+	{ 0x1854, "LG" },
 	{ 0x434d, "C-Media" },
 	{ 0x8384, "SigmaTel" },
 	{} /* terminator */
-- 
cgit v1.2.3-70-g09d2


From d260cdf65657382c4cde366a1c7d4ddce669a427 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Wed, 13 Feb 2008 17:19:35 +0100
Subject: [ALSA] hda-codec - Fix breakage of resume in auto-config of realtek
 codecs

The last patch for fixing the auto-config pin setting breaks the resume
due to a wrong use of snd_hda_codec_amp_stereo().  The code in the init
hook shouldn't touch the amp cache.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 6c605813fc6..355d88d07ea 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -3489,7 +3489,8 @@ static void alc_set_pin_output(struct hda_codec *codec, hda_nid_t nid,
 	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
 			    pin_type);
 	/* unmute pin */
-	snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, 0xff, 0x00);
+	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+			    AMP_OUT_UNMUTE);
 }
 
 static void alc880_auto_set_output_and_unmute(struct hda_codec *codec,
-- 
cgit v1.2.3-70-g09d2


From 814b1a5ce6b35bafd583ae813da97e8254bb1930 Mon Sep 17 00:00:00 2001
From: Libin Yang <Libin.yang@amd.com>
Date: Thu, 14 Feb 2008 12:55:13 +0100
Subject: [ALSA] HDA-Intel - Patch to support RV7xx HDMI Audio

This patch is to add R7xx HDMI audio support.

Signed-off-by: Libin Yang <Libin.yang@amd.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/hda_intel.c | 3 +++
 1 file changed, 3 insertions(+)

(limited to 'sound')

diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index f3242e1a731..66dceffa121 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -2051,6 +2051,9 @@ static struct pci_device_id azx_ids[] = {
 	{ 0x1002, 0xaa20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RV635 HDMI */
 	{ 0x1002, 0xaa28, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RV620 HDMI */
 	{ 0x1002, 0xaa30, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RV770 HDMI */
+	{ 0x1002, 0xaa38, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RV730 HDMI */
+	{ 0x1002, 0xaa40, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RV710 HDMI */
+	{ 0x1002, 0xaa48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RV740 HDMI */
 	{ 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_VIA }, /* VIA VT8251/VT8237A */
 	{ 0x1039, 0x7502, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_SIS }, /* SIS966 */
 	{ 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ULI }, /* ULI M5461 */
-- 
cgit v1.2.3-70-g09d2


From 88c71a9974693f2b2824b09340269511dd7cbe18 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Thu, 14 Feb 2008 17:27:17 +0100
Subject: [ALSA] hda-codec - Fix missing capsrc_nids for ALC262

ALC262 must have capsrc_nids defined as well as in ALC882.
Also, add a NULL check in alc882_mux_enum_put to avoid Oops.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 355d88d07ea..eea18b3336d 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -5253,7 +5253,8 @@ static int alc882_mux_enum_put(struct snd_kcontrol *kcontrol,
 	struct alc_spec *spec = codec->spec;
 	const struct hda_input_mux *imux = spec->input_mux;
 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
-	hda_nid_t nid = spec->capsrc_nids[adc_idx];
+	hda_nid_t nid = spec->capsrc_nids ?
+		spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx];
 	unsigned int *cur_val = &spec->cur_mux[adc_idx];
 	unsigned int i, idx;
 
@@ -8053,6 +8054,8 @@ static int patch_alc883(struct hda_codec *codec)
 #define alc262_dac_nids		alc260_dac_nids
 #define alc262_adc_nids		alc882_adc_nids
 #define alc262_adc_nids_alt	alc882_adc_nids_alt
+#define alc262_capsrc_nids	alc882_capsrc_nids
+#define alc262_capsrc_nids_alt	alc882_capsrc_nids_alt
 
 #define alc262_modes		alc260_modes
 #define alc262_capture_source	alc882_capture_source
@@ -9443,12 +9446,14 @@ static int patch_alc262(struct hda_codec *codec)
 		if (wcap != AC_WID_AUD_IN) {
 			spec->adc_nids = alc262_adc_nids_alt;
 			spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids_alt);
+			spec->capsrc_nids = alc262_capsrc_nids_alt;
 			spec->mixers[spec->num_mixers] =
 				alc262_capture_alt_mixer;
 			spec->num_mixers++;
 		} else {
 			spec->adc_nids = alc262_adc_nids;
 			spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids);
+			spec->capsrc_nids = alc262_capsrc_nids;
 			spec->mixers[spec->num_mixers] = alc262_capture_mixer;
 			spec->num_mixers++;
 		}
-- 
cgit v1.2.3-70-g09d2


From 83ac08c0846bc6106d6c7fbb342eab02b32dd399 Mon Sep 17 00:00:00 2001
From: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
Date: Fri, 15 Feb 2008 16:43:11 +0100
Subject: [ALSA] ASoC: WM9713 driver

This patch adds an ASoC driver for the WM9713 AC97 codec.

Signed-off-by: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/soc/codecs/Kconfig  |    4 +
 sound/soc/codecs/Makefile |    2 +
 sound/soc/codecs/wm9713.c | 1289 +++++++++++++++++++++++++++++++++++++++++++++
 sound/soc/codecs/wm9713.h |   53 ++
 4 files changed, 1348 insertions(+)
 create mode 100644 sound/soc/codecs/wm9713.c
 create mode 100644 sound/soc/codecs/wm9713.h

(limited to 'sound')

diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 898a7d36328..3903ab7dfa4 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -18,6 +18,10 @@ config SND_SOC_WM9712
 	tristate
 	depends on SND_SOC
 
+config SND_SOC_WM9713
+	tristate
+	depends on SND_SOC
+
 # Cirrus Logic CS4270 Codec
 config SND_SOC_CS4270
 	tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index c6e5338c266..4e1314c9d3e 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -3,6 +3,7 @@ snd-soc-wm8731-objs := wm8731.o
 snd-soc-wm8750-objs := wm8750.o
 snd-soc-wm8753-objs := wm8753.o
 snd-soc-wm9712-objs := wm9712.o
+snd-soc-wm9713-objs := wm9713.o
 snd-soc-cs4270-objs := cs4270.o
 snd-soc-tlv320aic3x-objs := tlv320aic3x.o
 
@@ -11,5 +12,6 @@ obj-$(CONFIG_SND_SOC_WM8731)	+= snd-soc-wm8731.o
 obj-$(CONFIG_SND_SOC_WM8750)	+= snd-soc-wm8750.o
 obj-$(CONFIG_SND_SOC_WM8753)	+= snd-soc-wm8753.o
 obj-$(CONFIG_SND_SOC_WM9712)	+= snd-soc-wm9712.o
+obj-$(CONFIG_SND_SOC_WM9713)	+= snd-soc-wm9713.o
 obj-$(CONFIG_SND_SOC_CS4270)	+= snd-soc-cs4270.o
 obj-$(CONFIG_SND_SOC_TLV320AIC3X)	+= snd-soc-tlv320aic3x.o
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
new file mode 100644
index 00000000000..c3d0afdc099
--- /dev/null
+++ b/sound/soc/codecs/wm9713.c
@@ -0,0 +1,1289 @@
+/*
+ * wm9713.c  --  ALSA Soc WM9713 codec support
+ *
+ * Copyright 2006 Wolfson Microelectronics PLC.
+ * Author: Liam Girdwood
+ *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  Revision history
+ *    4th Feb 2006   Initial version.
+ *
+ *  Features:-
+ *
+ *   o Support for AC97 Codec, Voice DAC and Aux DAC
+ *   o Support for DAPM
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/ac97_codec.h>
+#include <sound/initval.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include "wm9713.h"
+
+#define WM9713_VERSION "0.15"
+
+struct wm9713_priv {
+	u32 pll_in; /* PLL input frequency */
+	u32 pll_out; /* PLL output frequency */
+};
+
+static unsigned int ac97_read(struct snd_soc_codec *codec,
+	unsigned int reg);
+static int ac97_write(struct snd_soc_codec *codec,
+	unsigned int reg, unsigned int val);
+
+/*
+ * WM9713 register cache
+ * Reg 0x3c bit 15 is used by touch driver.
+ */
+static const u16 wm9713_reg[] = {
+	0x6174, 0x8080, 0x8080, 0x8080,
+	0xc880, 0xe808, 0xe808, 0x0808,
+	0x00da, 0x8000, 0xd600, 0xaaa0,
+	0xaaa0, 0xaaa0, 0x0000, 0x0000,
+	0x0f0f, 0x0040, 0x0000, 0x7f00,
+	0x0405, 0x0410, 0xbb80, 0xbb80,
+	0x0000, 0xbb80, 0x0000, 0x4523,
+	0x0000, 0x2000, 0x7eff, 0xffff,
+	0x0000, 0x0000, 0x0080, 0x0000,
+	0x0000, 0x0000, 0xfffe, 0xffff,
+	0x0000, 0x0000, 0x0000, 0xfffe,
+	0x4000, 0x0000, 0x0000, 0x0000,
+	0xb032, 0x3e00, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0006,
+	0x0001, 0x0000, 0x574d, 0x4c13,
+	0x0000, 0x0000, 0x0000
+};
+
+/* virtual HP mixers regs */
+#define HPL_MIXER	0x80
+#define HPR_MIXER	0x82
+#define MICB_MUX	0x82
+
+static const char *wm9713_mic_mixer[] = {"Stereo", "Mic 1", "Mic 2", "Mute"};
+static const char *wm9713_rec_mux[] = {"Stereo", "Left", "Right", "Mute"};
+static const char *wm9713_rec_src[] =
+	{"Mic 1", "Mic 2", "Line", "Mono In", "Headphone", "Speaker",
+	"Mono Out", "Zh"};
+static const char *wm9713_rec_gain[] = {"+1.5dB Steps", "+0.75dB Steps"};
+static const char *wm9713_alc_select[] = {"None", "Left", "Right", "Stereo"};
+static const char *wm9713_mono_pga[] = {"Vmid", "Zh", "Mono", "Inv",
+	"Mono Vmid", "Inv Vmid"};
+static const char *wm9713_spk_pga[] =
+	{"Vmid", "Zh", "Headphone", "Speaker", "Inv", "Headphone Vmid",
+	"Speaker Vmid", "Inv Vmid"};
+static const char *wm9713_hp_pga[] = {"Vmid", "Zh", "Headphone",
+	"Headphone Vmid"};
+static const char *wm9713_out3_pga[] = {"Vmid", "Zh", "Inv 1", "Inv 1 Vmid"};
+static const char *wm9713_out4_pga[] = {"Vmid", "Zh", "Inv 2", "Inv 2 Vmid"};
+static const char *wm9713_dac_inv[] =
+	{"Off", "Mono", "Speaker", "Left Headphone", "Right Headphone",
+	"Headphone Mono", "NC", "Vmid"};
+static const char *wm9713_bass[] = {"Linear Control", "Adaptive Boost"};
+static const char *wm9713_ng_type[] = {"Constant Gain", "Mute"};
+static const char *wm9713_mic_select[] = {"Mic 1", "Mic 2 A", "Mic 2 B"};
+static const char *wm9713_micb_select[] = {"MPB", "MPA"};
+
+static const struct soc_enum wm9713_enum[] = {
+SOC_ENUM_SINGLE(AC97_LINE, 3, 4, wm9713_mic_mixer), /* record mic mixer 0 */
+SOC_ENUM_SINGLE(AC97_VIDEO, 14, 4, wm9713_rec_mux), /* record mux hp 1 */
+SOC_ENUM_SINGLE(AC97_VIDEO, 9, 4, wm9713_rec_mux),  /* record mux mono 2 */
+SOC_ENUM_SINGLE(AC97_VIDEO, 3, 8, wm9713_rec_src),  /* record mux left 3 */
+SOC_ENUM_SINGLE(AC97_VIDEO, 0, 8, wm9713_rec_src),  /* record mux right 4*/
+SOC_ENUM_DOUBLE(AC97_CD, 14, 6, 2, wm9713_rec_gain), /* record step size 5 */
+SOC_ENUM_SINGLE(AC97_PCI_SVID, 14, 4, wm9713_alc_select), /* alc source select 6*/
+SOC_ENUM_SINGLE(AC97_REC_GAIN, 14, 4, wm9713_mono_pga), /* mono input select 7 */
+SOC_ENUM_SINGLE(AC97_REC_GAIN, 11, 8, wm9713_spk_pga), /* speaker left input select 8 */
+SOC_ENUM_SINGLE(AC97_REC_GAIN, 8, 8, wm9713_spk_pga), /* speaker right input select 9 */
+SOC_ENUM_SINGLE(AC97_REC_GAIN, 6, 3, wm9713_hp_pga), /* headphone left input 10 */
+SOC_ENUM_SINGLE(AC97_REC_GAIN, 4, 3, wm9713_hp_pga), /* headphone right input 11 */
+SOC_ENUM_SINGLE(AC97_REC_GAIN, 2, 4, wm9713_out3_pga), /* out 3 source 12 */
+SOC_ENUM_SINGLE(AC97_REC_GAIN, 0, 4, wm9713_out4_pga), /* out 4 source 13 */
+SOC_ENUM_SINGLE(AC97_REC_GAIN_MIC, 13, 8, wm9713_dac_inv), /* dac invert 1 14 */
+SOC_ENUM_SINGLE(AC97_REC_GAIN_MIC, 10, 8, wm9713_dac_inv), /* dac invert 2 15 */
+SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 15, 2, wm9713_bass), /* bass control 16 */
+SOC_ENUM_SINGLE(AC97_PCI_SVID, 5, 2, wm9713_ng_type), /* noise gate type 17 */
+SOC_ENUM_SINGLE(AC97_3D_CONTROL, 12, 3, wm9713_mic_select), /* mic selection 18 */
+SOC_ENUM_SINGLE(MICB_MUX, 0, 2, wm9713_micb_select), /* mic selection 19 */
+};
+
+static const struct snd_kcontrol_new wm9713_snd_ac97_controls[] = {
+SOC_DOUBLE("Speaker Playback Volume", AC97_MASTER, 8, 0, 31, 1),
+SOC_DOUBLE("Speaker Playback Switch", AC97_MASTER, 15, 7, 1, 1),
+SOC_DOUBLE("Headphone Playback Volume", AC97_HEADPHONE, 8, 0, 31, 1),
+SOC_DOUBLE("Headphone Playback Switch", AC97_HEADPHONE, 15, 7, 1, 1),
+SOC_DOUBLE("Line In Volume", AC97_PC_BEEP, 8, 0, 31, 1),
+SOC_DOUBLE("PCM Playback Volume", AC97_PHONE, 8, 0, 31, 1),
+SOC_SINGLE("Mic 1 Volume", AC97_MIC, 8, 31, 1),
+SOC_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1),
+
+SOC_SINGLE("Mic Boost (+20dB) Switch", AC97_LINE, 5, 1, 0),
+SOC_SINGLE("Mic Headphone Mixer Volume", AC97_LINE, 0, 7, 1),
+
+SOC_SINGLE("Capture Switch", AC97_CD, 15, 1, 1),
+SOC_ENUM("Capture Volume Steps", wm9713_enum[5]),
+SOC_DOUBLE("Capture Volume", AC97_CD, 8, 0, 31, 0),
+SOC_SINGLE("Capture ZC Switch", AC97_CD, 7, 1, 0),
+
+SOC_SINGLE("Capture to Headphone Volume", AC97_VIDEO, 11, 7, 1),
+SOC_SINGLE("Capture to Mono Boost (+20dB) Switch", AC97_VIDEO, 8, 1, 0),
+SOC_SINGLE("Capture ADC Boost (+20dB) Switch", AC97_VIDEO, 6, 1, 0),
+
+SOC_SINGLE("ALC Target Volume", AC97_CODEC_CLASS_REV, 12, 15, 0),
+SOC_SINGLE("ALC Hold Time", AC97_CODEC_CLASS_REV, 8, 15, 0),
+SOC_SINGLE("ALC Decay Time ", AC97_CODEC_CLASS_REV, 4, 15, 0),
+SOC_SINGLE("ALC Attack Time", AC97_CODEC_CLASS_REV, 0, 15, 0),
+SOC_ENUM("ALC Function", wm9713_enum[6]),
+SOC_SINGLE("ALC Max Volume", AC97_PCI_SVID, 11, 7, 0),
+SOC_SINGLE("ALC ZC Timeout", AC97_PCI_SVID, 9, 3, 0),
+SOC_SINGLE("ALC ZC Switch", AC97_PCI_SVID, 8, 1, 0),
+SOC_SINGLE("ALC NG Switch", AC97_PCI_SVID, 7, 1, 0),
+SOC_ENUM("ALC NG Type", wm9713_enum[17]),
+SOC_SINGLE("ALC NG Threshold", AC97_PCI_SVID, 0, 31, 0),
+
+SOC_DOUBLE("Speaker Playback ZC Switch", AC97_MASTER, 14, 6, 1, 0),
+SOC_DOUBLE("Headphone Playback ZC Switch", AC97_HEADPHONE, 14, 6, 1, 0),
+
+SOC_SINGLE("Out4 Playback Switch", AC97_MASTER_MONO, 15, 1, 1),
+SOC_SINGLE("Out4 Playback ZC Switch", AC97_MASTER_MONO, 14, 1, 0),
+SOC_SINGLE("Out4 Playback Volume", AC97_MASTER_MONO, 8, 63, 1),
+
+SOC_SINGLE("Out3 Playback Switch", AC97_MASTER_MONO, 7, 1, 1),
+SOC_SINGLE("Out3 Playback ZC Switch", AC97_MASTER_MONO, 6, 1, 0),
+SOC_SINGLE("Out3 Playback Volume", AC97_MASTER_MONO, 0, 63, 1),
+
+SOC_SINGLE("Mono Capture Volume", AC97_MASTER_TONE, 8, 31, 1),
+SOC_SINGLE("Mono Playback Switch", AC97_MASTER_TONE, 7, 1, 1),
+SOC_SINGLE("Mono Playback ZC Switch", AC97_MASTER_TONE, 6, 1, 0),
+SOC_SINGLE("Mono Playback Volume", AC97_MASTER_TONE, 0, 31, 1),
+
+SOC_SINGLE("PC Beep Playback Headphone Volume", AC97_AUX, 12, 7, 1),
+SOC_SINGLE("PC Beep Playback Speaker Volume", AC97_AUX, 8, 7, 1),
+SOC_SINGLE("PC Beep Playback Mono Volume", AC97_AUX, 4, 7, 1),
+
+SOC_SINGLE("Voice Playback Headphone Volume", AC97_PCM, 12, 7, 1),
+SOC_SINGLE("Voice Playback Master Volume", AC97_PCM, 8, 7, 1),
+SOC_SINGLE("Voice Playback Mono Volume", AC97_PCM, 4, 7, 1),
+
+SOC_SINGLE("Aux Playback Headphone Volume", AC97_REC_SEL, 12, 7, 1),
+SOC_SINGLE("Aux Playback Master Volume", AC97_REC_SEL, 8, 7, 1),
+SOC_SINGLE("Aux Playback Mono Volume", AC97_REC_SEL, 4, 7, 1),
+
+SOC_ENUM("Bass Control", wm9713_enum[16]),
+SOC_SINGLE("Bass Cut-off Switch", AC97_GENERAL_PURPOSE, 12, 1, 1),
+SOC_SINGLE("Tone Cut-off Switch", AC97_GENERAL_PURPOSE, 4, 1, 1),
+SOC_SINGLE("Playback Attenuate (-6dB) Switch", AC97_GENERAL_PURPOSE, 6, 1, 0),
+SOC_SINGLE("Bass Volume", AC97_GENERAL_PURPOSE, 8, 15, 1),
+SOC_SINGLE("Tone Volume", AC97_GENERAL_PURPOSE, 0, 15, 1),
+
+SOC_SINGLE("3D Upper Cut-off Switch", AC97_REC_GAIN_MIC, 5, 1, 0),
+SOC_SINGLE("3D Lower Cut-off Switch", AC97_REC_GAIN_MIC, 4, 1, 0),
+SOC_SINGLE("3D Depth", AC97_REC_GAIN_MIC, 0, 15, 1),
+};
+
+/* add non dapm controls */
+static int wm9713_add_controls(struct snd_soc_codec *codec)
+{
+	int err, i;
+
+	for (i = 0; i < ARRAY_SIZE(wm9713_snd_ac97_controls); i++) {
+		err = snd_ctl_add(codec->card,
+				snd_soc_cnew(&wm9713_snd_ac97_controls[i],
+					codec, NULL));
+		if (err < 0)
+			return err;
+	}
+	return 0;
+}
+
+/* We have to create a fake left and right HP mixers because
+ * the codec only has a single control that is shared by both channels.
+ * This makes it impossible to determine the audio path using the current
+ * register map, thus we add a new (virtual) register to help determine the
+ * audio route within the device.
+ */
+static int mixer_event(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	u16 l, r, beep, tone, phone, rec, pcm, aux;
+
+	l = ac97_read(w->codec, HPL_MIXER);
+	r = ac97_read(w->codec, HPR_MIXER);
+	beep = ac97_read(w->codec, AC97_PC_BEEP);
+	tone = ac97_read(w->codec, AC97_MASTER_TONE);
+	phone = ac97_read(w->codec, AC97_PHONE);
+	rec = ac97_read(w->codec, AC97_REC_SEL);
+	pcm = ac97_read(w->codec, AC97_PCM);
+	aux = ac97_read(w->codec, AC97_AUX);
+
+	if (event & SND_SOC_DAPM_PRE_REG)
+		return 0;
+	if ((l & 0x1) || (r & 0x1))
+		ac97_write(w->codec, AC97_PC_BEEP, beep & 0x7fff);
+	else
+		ac97_write(w->codec, AC97_PC_BEEP, beep | 0x8000);
+
+	if ((l & 0x2) || (r & 0x2))
+		ac97_write(w->codec, AC97_MASTER_TONE, tone & 0x7fff);
+	else
+		ac97_write(w->codec, AC97_MASTER_TONE, tone | 0x8000);
+
+	if ((l & 0x4) || (r & 0x4))
+		ac97_write(w->codec, AC97_PHONE, phone & 0x7fff);
+	else
+		ac97_write(w->codec, AC97_PHONE, phone | 0x8000);
+
+	if ((l & 0x8) || (r & 0x8))
+		ac97_write(w->codec, AC97_REC_SEL, rec & 0x7fff);
+	else
+		ac97_write(w->codec, AC97_REC_SEL, rec | 0x8000);
+
+	if ((l & 0x10) || (r & 0x10))
+		ac97_write(w->codec, AC97_PCM, pcm & 0x7fff);
+	else
+		ac97_write(w->codec, AC97_PCM, pcm | 0x8000);
+
+	if ((l & 0x20) || (r & 0x20))
+		ac97_write(w->codec, AC97_AUX, aux & 0x7fff);
+	else
+		ac97_write(w->codec, AC97_AUX, aux | 0x8000);
+
+	return 0;
+}
+
+/* Left Headphone Mixers */
+static const struct snd_kcontrol_new wm9713_hpl_mixer_controls[] = {
+SOC_DAPM_SINGLE("PC Beep Playback Switch", HPL_MIXER, 5, 1, 0),
+SOC_DAPM_SINGLE("Voice Playback Switch", HPL_MIXER, 4, 1, 0),
+SOC_DAPM_SINGLE("Aux Playback Switch", HPL_MIXER, 3, 1, 0),
+SOC_DAPM_SINGLE("PCM Playback Switch", HPL_MIXER, 2, 1, 0),
+SOC_DAPM_SINGLE("MonoIn Playback Switch", HPL_MIXER, 1, 1, 0),
+SOC_DAPM_SINGLE("Bypass Playback Switch", HPL_MIXER, 0, 1, 0),
+};
+
+/* Right Headphone Mixers */
+static const struct snd_kcontrol_new wm9713_hpr_mixer_controls[] = {
+SOC_DAPM_SINGLE("PC Beep Playback Switch", HPR_MIXER, 5, 1, 0),
+SOC_DAPM_SINGLE("Voice Playback Switch", HPR_MIXER, 4, 1, 0),
+SOC_DAPM_SINGLE("Aux Playback Switch", HPR_MIXER, 3, 1, 0),
+SOC_DAPM_SINGLE("PCM Playback Switch", HPR_MIXER, 2, 1, 0),
+SOC_DAPM_SINGLE("MonoIn Playback Switch", HPR_MIXER, 1, 1, 0),
+SOC_DAPM_SINGLE("Bypass Playback Switch", HPR_MIXER, 0, 1, 0),
+};
+
+/* headphone capture mux */
+static const struct snd_kcontrol_new wm9713_hp_rec_mux_controls =
+SOC_DAPM_ENUM("Route", wm9713_enum[1]);
+
+/* headphone mic mux */
+static const struct snd_kcontrol_new wm9713_hp_mic_mux_controls =
+SOC_DAPM_ENUM("Route", wm9713_enum[0]);
+
+/* Speaker Mixer */
+static const struct snd_kcontrol_new wm9713_speaker_mixer_controls[] = {
+SOC_DAPM_SINGLE("PC Beep Playback Switch", AC97_AUX, 11, 1, 1),
+SOC_DAPM_SINGLE("Voice Playback Switch", AC97_PCM, 11, 1, 1),
+SOC_DAPM_SINGLE("Aux Playback Switch", AC97_REC_SEL, 11, 1, 1),
+SOC_DAPM_SINGLE("PCM Playback Switch", AC97_PHONE, 14, 1, 1),
+SOC_DAPM_SINGLE("MonoIn Playback Switch", AC97_MASTER_TONE, 14, 1, 1),
+SOC_DAPM_SINGLE("Bypass Playback Switch", AC97_PC_BEEP, 14, 1, 1),
+};
+
+/* Mono Mixer */
+static const struct snd_kcontrol_new wm9713_mono_mixer_controls[] = {
+SOC_DAPM_SINGLE("PC Beep Playback Switch", AC97_AUX, 7, 1, 1),
+SOC_DAPM_SINGLE("Voice Playback Switch", AC97_PCM, 7, 1, 1),
+SOC_DAPM_SINGLE("Aux Playback Switch", AC97_REC_SEL, 7, 1, 1),
+SOC_DAPM_SINGLE("PCM Playback Switch", AC97_PHONE, 13, 1, 1),
+SOC_DAPM_SINGLE("MonoIn Playback Switch", AC97_MASTER_TONE, 13, 1, 1),
+SOC_DAPM_SINGLE("Bypass Playback Switch", AC97_PC_BEEP, 13, 1, 1),
+SOC_DAPM_SINGLE("Mic 1 Sidetone Switch", AC97_LINE, 7, 1, 1),
+SOC_DAPM_SINGLE("Mic 2 Sidetone Switch", AC97_LINE, 6, 1, 1),
+};
+
+/* mono mic mux */
+static const struct snd_kcontrol_new wm9713_mono_mic_mux_controls =
+SOC_DAPM_ENUM("Route", wm9713_enum[2]);
+
+/* mono output mux */
+static const struct snd_kcontrol_new wm9713_mono_mux_controls =
+SOC_DAPM_ENUM("Route", wm9713_enum[7]);
+
+/* speaker left output mux */
+static const struct snd_kcontrol_new wm9713_hp_spkl_mux_controls =
+SOC_DAPM_ENUM("Route", wm9713_enum[8]);
+
+/* speaker right output mux */
+static const struct snd_kcontrol_new wm9713_hp_spkr_mux_controls =
+SOC_DAPM_ENUM("Route", wm9713_enum[9]);
+
+/* headphone left output mux */
+static const struct snd_kcontrol_new wm9713_hpl_out_mux_controls =
+SOC_DAPM_ENUM("Route", wm9713_enum[10]);
+
+/* headphone right output mux */
+static const struct snd_kcontrol_new wm9713_hpr_out_mux_controls =
+SOC_DAPM_ENUM("Route", wm9713_enum[11]);
+
+/* Out3 mux */
+static const struct snd_kcontrol_new wm9713_out3_mux_controls =
+SOC_DAPM_ENUM("Route", wm9713_enum[12]);
+
+/* Out4 mux */
+static const struct snd_kcontrol_new wm9713_out4_mux_controls =
+SOC_DAPM_ENUM("Route", wm9713_enum[13]);
+
+/* DAC inv mux 1 */
+static const struct snd_kcontrol_new wm9713_dac_inv1_mux_controls =
+SOC_DAPM_ENUM("Route", wm9713_enum[14]);
+
+/* DAC inv mux 2 */
+static const struct snd_kcontrol_new wm9713_dac_inv2_mux_controls =
+SOC_DAPM_ENUM("Route", wm9713_enum[15]);
+
+/* Capture source left */
+static const struct snd_kcontrol_new wm9713_rec_srcl_mux_controls =
+SOC_DAPM_ENUM("Route", wm9713_enum[3]);
+
+/* Capture source right */
+static const struct snd_kcontrol_new wm9713_rec_srcr_mux_controls =
+SOC_DAPM_ENUM("Route", wm9713_enum[4]);
+
+/* mic source */
+static const struct snd_kcontrol_new wm9713_mic_sel_mux_controls =
+SOC_DAPM_ENUM("Route", wm9713_enum[18]);
+
+/* mic source B virtual control */
+static const struct snd_kcontrol_new wm9713_micb_sel_mux_controls =
+SOC_DAPM_ENUM("Route", wm9713_enum[19]);
+
+static const struct snd_soc_dapm_widget wm9713_dapm_widgets[] = {
+SND_SOC_DAPM_MUX("Capture Headphone Mux", SND_SOC_NOPM, 0, 0,
+	&wm9713_hp_rec_mux_controls),
+SND_SOC_DAPM_MUX("Sidetone Mux", SND_SOC_NOPM, 0, 0,
+	&wm9713_hp_mic_mux_controls),
+SND_SOC_DAPM_MUX("Capture Mono Mux", SND_SOC_NOPM, 0, 0,
+	&wm9713_mono_mic_mux_controls),
+SND_SOC_DAPM_MUX("Mono Out Mux", SND_SOC_NOPM, 0, 0,
+	&wm9713_mono_mux_controls),
+SND_SOC_DAPM_MUX("Left Speaker Out Mux", SND_SOC_NOPM, 0, 0,
+	&wm9713_hp_spkl_mux_controls),
+SND_SOC_DAPM_MUX("Right Speaker Out Mux", SND_SOC_NOPM, 0, 0,
+	&wm9713_hp_spkr_mux_controls),
+SND_SOC_DAPM_MUX("Left Headphone Out Mux", SND_SOC_NOPM, 0, 0,
+	&wm9713_hpl_out_mux_controls),
+SND_SOC_DAPM_MUX("Right Headphone Out Mux", SND_SOC_NOPM, 0, 0,
+	&wm9713_hpr_out_mux_controls),
+SND_SOC_DAPM_MUX("Out 3 Mux", SND_SOC_NOPM, 0, 0,
+	&wm9713_out3_mux_controls),
+SND_SOC_DAPM_MUX("Out 4 Mux", SND_SOC_NOPM, 0, 0,
+	&wm9713_out4_mux_controls),
+SND_SOC_DAPM_MUX("DAC Inv Mux 1", SND_SOC_NOPM, 0, 0,
+	&wm9713_dac_inv1_mux_controls),
+SND_SOC_DAPM_MUX("DAC Inv Mux 2", SND_SOC_NOPM, 0, 0,
+	&wm9713_dac_inv2_mux_controls),
+SND_SOC_DAPM_MUX("Left Capture Source", SND_SOC_NOPM, 0, 0,
+	&wm9713_rec_srcl_mux_controls),
+SND_SOC_DAPM_MUX("Right Capture Source", SND_SOC_NOPM, 0, 0,
+	&wm9713_rec_srcr_mux_controls),
+SND_SOC_DAPM_MUX("Mic A Source", SND_SOC_NOPM, 0, 0,
+	&wm9713_mic_sel_mux_controls),
+SND_SOC_DAPM_MUX("Mic B Source", SND_SOC_NOPM, 0, 0,
+	&wm9713_micb_sel_mux_controls),
+SND_SOC_DAPM_MIXER_E("Left HP Mixer", AC97_EXTENDED_MID, 3, 1,
+	&wm9713_hpl_mixer_controls[0], ARRAY_SIZE(wm9713_hpl_mixer_controls),
+	mixer_event, SND_SOC_DAPM_POST_REG),
+SND_SOC_DAPM_MIXER_E("Right HP Mixer", AC97_EXTENDED_MID, 2, 1,
+	&wm9713_hpr_mixer_controls[0], ARRAY_SIZE(wm9713_hpr_mixer_controls),
+	mixer_event, SND_SOC_DAPM_POST_REG),
+SND_SOC_DAPM_MIXER("Mono Mixer", AC97_EXTENDED_MID, 0, 1,
+	&wm9713_mono_mixer_controls[0], ARRAY_SIZE(wm9713_mono_mixer_controls)),
+SND_SOC_DAPM_MIXER("Speaker Mixer", AC97_EXTENDED_MID, 1, 1,
+	&wm9713_speaker_mixer_controls[0],
+	ARRAY_SIZE(wm9713_speaker_mixer_controls)),
+SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playback", AC97_EXTENDED_MID, 7, 1),
+SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Playback", AC97_EXTENDED_MID, 6, 1),
+SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+SND_SOC_DAPM_MIXER("HP Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+SND_SOC_DAPM_MIXER("Line Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+SND_SOC_DAPM_MIXER("Capture Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+SND_SOC_DAPM_DAC("Voice DAC", "Voice Playback", AC97_EXTENDED_MID, 12, 1),
+SND_SOC_DAPM_DAC("Aux DAC", "Aux Playback", AC97_EXTENDED_MID, 11, 1),
+SND_SOC_DAPM_ADC("Left ADC", "Left HiFi Capture", AC97_EXTENDED_MID, 5, 1),
+SND_SOC_DAPM_ADC("Right ADC", "Right HiFi Capture", AC97_EXTENDED_MID, 4, 1),
+SND_SOC_DAPM_PGA("Left Headphone", AC97_EXTENDED_MSTATUS, 10, 1, NULL, 0),
+SND_SOC_DAPM_PGA("Right Headphone", AC97_EXTENDED_MSTATUS, 9, 1, NULL, 0),
+SND_SOC_DAPM_PGA("Left Speaker", AC97_EXTENDED_MSTATUS, 8, 1, NULL, 0),
+SND_SOC_DAPM_PGA("Right Speaker", AC97_EXTENDED_MSTATUS, 7, 1, NULL, 0),
+SND_SOC_DAPM_PGA("Out 3", AC97_EXTENDED_MSTATUS, 11, 1, NULL, 0),
+SND_SOC_DAPM_PGA("Out 4", AC97_EXTENDED_MSTATUS, 12, 1, NULL, 0),
+SND_SOC_DAPM_PGA("Mono Out", AC97_EXTENDED_MSTATUS, 13, 1, NULL, 0),
+SND_SOC_DAPM_PGA("Left Line In", AC97_EXTENDED_MSTATUS, 6, 1, NULL, 0),
+SND_SOC_DAPM_PGA("Right Line In", AC97_EXTENDED_MSTATUS, 5, 1, NULL, 0),
+SND_SOC_DAPM_PGA("Mono In", AC97_EXTENDED_MSTATUS, 4, 1, NULL, 0),
+SND_SOC_DAPM_PGA("Mic A PGA", AC97_EXTENDED_MSTATUS, 3, 1, NULL, 0),
+SND_SOC_DAPM_PGA("Mic B PGA", AC97_EXTENDED_MSTATUS, 2, 1, NULL, 0),
+SND_SOC_DAPM_PGA("Mic A Pre Amp", AC97_EXTENDED_MSTATUS, 1, 1, NULL, 0),
+SND_SOC_DAPM_PGA("Mic B Pre Amp", AC97_EXTENDED_MSTATUS, 0, 1, NULL, 0),
+SND_SOC_DAPM_MICBIAS("Mic Bias", AC97_EXTENDED_MSTATUS, 14, 1),
+SND_SOC_DAPM_OUTPUT("MONO"),
+SND_SOC_DAPM_OUTPUT("HPL"),
+SND_SOC_DAPM_OUTPUT("HPR"),
+SND_SOC_DAPM_OUTPUT("SPKL"),
+SND_SOC_DAPM_OUTPUT("SPKR"),
+SND_SOC_DAPM_OUTPUT("OUT3"),
+SND_SOC_DAPM_OUTPUT("OUT4"),
+SND_SOC_DAPM_INPUT("LINEL"),
+SND_SOC_DAPM_INPUT("LINER"),
+SND_SOC_DAPM_INPUT("MONOIN"),
+SND_SOC_DAPM_INPUT("PCBEEP"),
+SND_SOC_DAPM_INPUT("MIC1"),
+SND_SOC_DAPM_INPUT("MIC2A"),
+SND_SOC_DAPM_INPUT("MIC2B"),
+SND_SOC_DAPM_VMID("VMID"),
+};
+
+static const char *audio_map[][3] = {
+	/* left HP mixer */
+	{"Left HP Mixer", "PC Beep Playback Switch", "PCBEEP"},
+	{"Left HP Mixer", "Voice Playback Switch",   "Voice DAC"},
+	{"Left HP Mixer", "Aux Playback Switch",     "Aux DAC"},
+	{"Left HP Mixer", "Bypass Playback Switch",  "Left Line In"},
+	{"Left HP Mixer", "PCM Playback Switch",     "Left DAC"},
+	{"Left HP Mixer", "MonoIn Playback Switch",  "Mono In"},
+	{"Left HP Mixer", NULL,  "Capture Headphone Mux"},
+
+	/* right HP mixer */
+	{"Right HP Mixer", "PC Beep Playback Switch", "PCBEEP"},
+	{"Right HP Mixer", "Voice Playback Switch",   "Voice DAC"},
+	{"Right HP Mixer", "Aux Playback Switch",     "Aux DAC"},
+	{"Right HP Mixer", "Bypass Playback Switch",  "Right Line In"},
+	{"Right HP Mixer", "PCM Playback Switch",     "Right DAC"},
+	{"Right HP Mixer", "MonoIn Playback Switch",  "Mono In"},
+	{"Right HP Mixer", NULL,  "Capture Headphone Mux"},
+
+	/* virtual mixer - mixes left & right channels for spk and mono */
+	{"AC97 Mixer", NULL, "Left DAC"},
+	{"AC97 Mixer", NULL, "Right DAC"},
+	{"Line Mixer", NULL, "Right Line In"},
+	{"Line Mixer", NULL, "Left Line In"},
+	{"HP Mixer", NULL, "Left HP Mixer"},
+	{"HP Mixer", NULL, "Right HP Mixer"},
+	{"Capture Mixer", NULL, "Left Capture Source"},
+	{"Capture Mixer", NULL, "Right Capture Source"},
+
+	/* speaker mixer */
+	{"Speaker Mixer", "PC Beep Playback Switch", "PCBEEP"},
+	{"Speaker Mixer", "Voice Playback Switch",   "Voice DAC"},
+	{"Speaker Mixer", "Aux Playback Switch",     "Aux DAC"},
+	{"Speaker Mixer", "Bypass Playback Switch",  "Line Mixer"},
+	{"Speaker Mixer", "PCM Playback Switch",     "AC97 Mixer"},
+	{"Speaker Mixer", "MonoIn Playback Switch",  "Mono In"},
+
+	/* mono mixer */
+	{"Mono Mixer", "PC Beep Playback Switch", "PCBEEP"},
+	{"Mono Mixer", "Voice Playback Switch",   "Voice DAC"},
+	{"Mono Mixer", "Aux Playback Switch",     "Aux DAC"},
+	{"Mono Mixer", "Bypass Playback Switch",  "Line Mixer"},
+	{"Mono Mixer", "PCM Playback Switch",     "AC97 Mixer"},
+	{"Mono Mixer", NULL,  "Capture Mono Mux"},
+
+	/* DAC inv mux 1 */
+	{"DAC Inv Mux 1", "Mono", "Mono Mixer"},
+	{"DAC Inv Mux 1", "Speaker", "Speaker Mixer"},
+	{"DAC Inv Mux 1", "Left Headphone", "Left HP Mixer"},
+	{"DAC Inv Mux 1", "Right Headphone", "Right HP Mixer"},
+	{"DAC Inv Mux 1", "Headphone Mono", "HP Mixer"},
+
+	/* DAC inv mux 2 */
+	{"DAC Inv Mux 2", "Mono", "Mono Mixer"},
+	{"DAC Inv Mux 2", "Speaker", "Speaker Mixer"},
+	{"DAC Inv Mux 2", "Left Headphone", "Left HP Mixer"},
+	{"DAC Inv Mux 2", "Right Headphone", "Right HP Mixer"},
+	{"DAC Inv Mux 2", "Headphone Mono", "HP Mixer"},
+
+	/* headphone left mux */
+	{"Left Headphone Out Mux", "Headphone", "Left HP Mixer"},
+
+	/* headphone right mux */
+	{"Right Headphone Out Mux", "Headphone", "Right HP Mixer"},
+
+	/* speaker left mux */
+	{"Left Speaker Out Mux", "Headphone", "Left HP Mixer"},
+	{"Left Speaker Out Mux", "Speaker", "Speaker Mixer"},
+	{"Left Speaker Out Mux", "Inv", "DAC Inv Mux 1"},
+
+	/* speaker right mux */
+	{"Right Speaker Out Mux", "Headphone", "Right HP Mixer"},
+	{"Right Speaker Out Mux", "Speaker", "Speaker Mixer"},
+	{"Right Speaker Out Mux", "Inv", "DAC Inv Mux 2"},
+
+	/* mono mux */
+	{"Mono Out Mux", "Mono", "Mono Mixer"},
+	{"Mono Out Mux", "Inv", "DAC Inv Mux 1"},
+
+	/* out 3 mux */
+	{"Out 3 Mux", "Inv 1", "DAC Inv Mux 1"},
+
+	/* out 4 mux */
+	{"Out 4 Mux", "Inv 2", "DAC Inv Mux 2"},
+
+	/* output pga */
+	{"HPL", NULL, "Left Headphone"},
+	{"Left Headphone", NULL, "Left Headphone Out Mux"},
+	{"HPR", NULL, "Right Headphone"},
+	{"Right Headphone", NULL, "Right Headphone Out Mux"},
+	{"OUT3", NULL, "Out 3"},
+	{"Out 3", NULL, "Out 3 Mux"},
+	{"OUT4", NULL, "Out 4"},
+	{"Out 4", NULL, "Out 4 Mux"},
+	{"SPKL", NULL, "Left Speaker"},
+	{"Left Speaker", NULL, "Left Speaker Out Mux"},
+	{"SPKR", NULL, "Right Speaker"},
+	{"Right Speaker", NULL, "Right Speaker Out Mux"},
+	{"MONO", NULL, "Mono Out"},
+	{"Mono Out", NULL, "Mono Out Mux"},
+
+	/* input pga */
+	{"Left Line In", NULL, "LINEL"},
+	{"Right Line In", NULL, "LINER"},
+	{"Mono In", NULL, "MONOIN"},
+	{"Mic A PGA", NULL, "Mic A Pre Amp"},
+	{"Mic B PGA", NULL, "Mic B Pre Amp"},
+
+	/* left capture select */
+	{"Left Capture Source", "Mic 1", "Mic A Pre Amp"},
+	{"Left Capture Source", "Mic 2", "Mic B Pre Amp"},
+	{"Left Capture Source", "Line", "LINEL"},
+	{"Left Capture Source", "Mono In", "MONOIN"},
+	{"Left Capture Source", "Headphone", "Left HP Mixer"},
+	{"Left Capture Source", "Speaker", "Speaker Mixer"},
+	{"Left Capture Source", "Mono Out", "Mono Mixer"},
+
+	/* right capture select */
+	{"Right Capture Source", "Mic 1", "Mic A Pre Amp"},
+	{"Right Capture Source", "Mic 2", "Mic B Pre Amp"},
+	{"Right Capture Source", "Line", "LINER"},
+	{"Right Capture Source", "Mono In", "MONOIN"},
+	{"Right Capture Source", "Headphone", "Right HP Mixer"},
+	{"Right Capture Source", "Speaker", "Speaker Mixer"},
+	{"Right Capture Source", "Mono Out", "Mono Mixer"},
+
+	/* left ADC */
+	{"Left ADC", NULL, "Left Capture Source"},
+
+	/* right ADC */
+	{"Right ADC", NULL, "Right Capture Source"},
+
+	/* mic */
+	{"Mic A Pre Amp", NULL, "Mic A Source"},
+	{"Mic A Source", "Mic 1", "MIC1"},
+	{"Mic A Source", "Mic 2 A", "MIC2A"},
+	{"Mic A Source", "Mic 2 B", "Mic B Source"},
+	{"Mic B Pre Amp", "MPB", "Mic B Source"},
+	{"Mic B Source", NULL, "MIC2B"},
+
+	/* headphone capture */
+	{"Capture Headphone Mux", "Stereo", "Capture Mixer"},
+	{"Capture Headphone Mux", "Left", "Left Capture Source"},
+	{"Capture Headphone Mux", "Right", "Right Capture Source"},
+
+	/* mono capture */
+	{"Capture Mono Mux", "Stereo", "Capture Mixer"},
+	{"Capture Mono Mux", "Left", "Left Capture Source"},
+	{"Capture Mono Mux", "Right", "Right Capture Source"},
+
+	{NULL, NULL, NULL},
+};
+
+static int wm9713_add_widgets(struct snd_soc_codec *codec)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(wm9713_dapm_widgets); i++)
+		snd_soc_dapm_new_control(codec, &wm9713_dapm_widgets[i]);
+
+	/* set up audio path audio_mapnects */
+	for (i = 0; audio_map[i][0] != NULL; i++)
+		snd_soc_dapm_connect_input(codec, audio_map[i][0],
+			audio_map[i][1], audio_map[i][2]);
+
+	snd_soc_dapm_new_widgets(codec);
+	return 0;
+}
+
+static unsigned int ac97_read(struct snd_soc_codec *codec,
+	unsigned int reg)
+{
+	u16 *cache = codec->reg_cache;
+
+	if (reg == AC97_RESET || reg == AC97_GPIO_STATUS ||
+		reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 ||
+		reg == AC97_CD)
+		return soc_ac97_ops.read(codec->ac97, reg);
+	else {
+		reg = reg >> 1;
+
+		if (reg > (ARRAY_SIZE(wm9713_reg)))
+			return -EIO;
+
+		return cache[reg];
+	}
+}
+
+static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
+	unsigned int val)
+{
+	u16 *cache = codec->reg_cache;
+	if (reg < 0x7c)
+		soc_ac97_ops.write(codec->ac97, reg, val);
+	reg = reg >> 1;
+	if (reg <= (ARRAY_SIZE(wm9713_reg)))
+		cache[reg] = val;
+
+	return 0;
+}
+
+/* PLL divisors */
+struct _pll_div {
+	u32 divsel:1;
+	u32 divctl:1;
+	u32 lf:1;
+	u32 n:4;
+	u32 k:24;
+};
+
+/* The size in bits of the PLL divide multiplied by 10
+ * to allow rounding later */
+#define FIXED_PLL_SIZE ((1 << 22) * 10)
+
+static void pll_factors(struct _pll_div *pll_div, unsigned int source)
+{
+	u64 Kpart;
+	unsigned int K, Ndiv, Nmod, target;
+
+	/* The the PLL output is always 98.304MHz. */
+	target = 98304000;
+
+	/* If the input frequency is over 14.4MHz then scale it down. */
+	if (source > 14400000) {
+		source >>= 1;
+		pll_div->divsel = 1;
+
+		if (source > 14400000) {
+			source >>= 1;
+			pll_div->divctl = 1;
+		} else
+			pll_div->divctl = 0;
+
+	} else {
+		pll_div->divsel = 0;
+		pll_div->divctl = 0;
+	}
+
+	/* Low frequency sources require an additional divide in the
+	 * loop.
+	 */
+	if (source < 8192000) {
+		pll_div->lf = 1;
+		target >>= 2;
+	} else
+		pll_div->lf = 0;
+
+	Ndiv = target / source;
+	if ((Ndiv < 5) || (Ndiv > 12))
+		printk(KERN_WARNING
+			"WM9713 PLL N value %d out of recommended range!\n",
+			Ndiv);
+
+	pll_div->n = Ndiv;
+	Nmod = target % source;
+	Kpart = FIXED_PLL_SIZE * (long long)Nmod;
+
+	do_div(Kpart, source);
+
+	K = Kpart & 0xFFFFFFFF;
+
+	/* Check if we need to round */
+	if ((K % 10) >= 5)
+		K += 5;
+
+	/* Move down to proper range now rounding is done */
+	K /= 10;
+
+	pll_div->k = K;
+}
+
+/**
+ * Please note that changing the PLL input frequency may require
+ * resynchronisation with the AC97 controller.
+ */
+static int wm9713_set_pll(struct snd_soc_codec *codec,
+	int pll_id, unsigned int freq_in, unsigned int freq_out)
+{
+	struct wm9713_priv *wm9713 = codec->private_data;
+	u16 reg, reg2;
+	struct _pll_div pll_div;
+
+	/* turn PLL off ? */
+	if (freq_in == 0 || freq_out == 0) {
+		/* disable PLL power and select ext source */
+		reg = ac97_read(codec, AC97_HANDSET_RATE);
+		ac97_write(codec, AC97_HANDSET_RATE, reg | 0x0080);
+		reg = ac97_read(codec, AC97_EXTENDED_MID);
+		ac97_write(codec, AC97_EXTENDED_MID, reg | 0x0200);
+		wm9713->pll_out = 0;
+		return 0;
+	}
+
+	pll_factors(&pll_div, freq_in);
+
+	if (pll_div.k == 0) {
+		reg = (pll_div.n << 12) | (pll_div.lf << 11) |
+			(pll_div.divsel << 9) | (pll_div.divctl << 8);
+		ac97_write(codec, AC97_LINE1_LEVEL, reg);
+	} else {
+		/* write the fractional k to the reg 0x46 pages */
+		reg2 = (pll_div.n << 12) | (pll_div.lf << 11) | (1 << 10) |
+			(pll_div.divsel << 9) | (pll_div.divctl << 8);
+
+		/* K [21:20] */
+		reg = reg2 | (0x5 << 4) | (pll_div.k >> 20);
+		ac97_write(codec, AC97_LINE1_LEVEL, reg);
+
+		/* K [19:16] */
+		reg = reg2 | (0x4 << 4) | ((pll_div.k >> 16) & 0xf);
+		ac97_write(codec, AC97_LINE1_LEVEL, reg);
+
+		/* K [15:12] */
+		reg = reg2 | (0x3 << 4) | ((pll_div.k >> 12) & 0xf);
+		ac97_write(codec, AC97_LINE1_LEVEL, reg);
+
+		/* K [11:8] */
+		reg = reg2 | (0x2 << 4) | ((pll_div.k >> 8) & 0xf);
+		ac97_write(codec, AC97_LINE1_LEVEL, reg);
+
+		/* K [7:4] */
+		reg = reg2 | (0x1 << 4) | ((pll_div.k >> 4) & 0xf);
+		ac97_write(codec, AC97_LINE1_LEVEL, reg);
+
+		reg = reg2 | (0x0 << 4) | (pll_div.k & 0xf); /* K [3:0] */
+		ac97_write(codec, AC97_LINE1_LEVEL, reg);
+	}
+
+	/* turn PLL on and select as source */
+	reg = ac97_read(codec, AC97_EXTENDED_MID);
+	ac97_write(codec, AC97_EXTENDED_MID, reg & 0xfdff);
+	reg = ac97_read(codec, AC97_HANDSET_RATE);
+	ac97_write(codec, AC97_HANDSET_RATE, reg & 0xff7f);
+	wm9713->pll_out = freq_out;
+	wm9713->pll_in = freq_in;
+
+	/* wait 10ms AC97 link frames for the link to stabilise */
+	schedule_timeout_interruptible(msecs_to_jiffies(10));
+	return 0;
+}
+
+static int wm9713_set_dai_pll(struct snd_soc_codec_dai *codec_dai,
+		int pll_id, unsigned int freq_in, unsigned int freq_out)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	return wm9713_set_pll(codec, pll_id, freq_in, freq_out);
+}
+
+/*
+ * Tristate the PCM DAI lines, tristate can be disabled by calling
+ * wm9713_set_dai_fmt()
+ */
+static int wm9713_set_dai_tristate(struct snd_soc_codec_dai *codec_dai,
+	int tristate)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	u16 reg = ac97_read(codec, AC97_CENTER_LFE_MASTER) & 0x9fff;
+
+	if (tristate)
+		ac97_write(codec, AC97_CENTER_LFE_MASTER, reg);
+
+	return 0;
+}
+
+/*
+ * Configure WM9713 clock dividers.
+ * Voice DAC needs 256 FS
+ */
+static int wm9713_set_dai_clkdiv(struct snd_soc_codec_dai *codec_dai,
+		int div_id, int div)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	u16 reg;
+
+	switch (div_id) {
+	case WM9713_PCMCLK_DIV:
+		reg = ac97_read(codec, AC97_HANDSET_RATE) & 0xf0ff;
+		ac97_write(codec, AC97_HANDSET_RATE, reg | div);
+		break;
+	case WM9713_CLKA_MULT:
+		reg = ac97_read(codec, AC97_HANDSET_RATE) & 0xfffd;
+		ac97_write(codec, AC97_HANDSET_RATE, reg | div);
+		break;
+	case WM9713_CLKB_MULT:
+		reg = ac97_read(codec, AC97_HANDSET_RATE) & 0xfffb;
+		ac97_write(codec, AC97_HANDSET_RATE, reg | div);
+		break;
+	case WM9713_HIFI_DIV:
+		reg = ac97_read(codec, AC97_HANDSET_RATE) & 0x8fff;
+		ac97_write(codec, AC97_HANDSET_RATE, reg | div);
+		break;
+	case WM9713_PCMBCLK_DIV:
+		reg = ac97_read(codec, AC97_CENTER_LFE_MASTER) & 0xf1ff;
+		ac97_write(codec, AC97_CENTER_LFE_MASTER, reg | div);
+		break;
+	case WM9713_PCMCLK_PLL_DIV:
+		reg = ac97_read(codec, AC97_LINE1_LEVEL) & 0xff80;
+		ac97_write(codec, AC97_LINE1_LEVEL, reg | 0x60 | div);
+		break;
+	case WM9713_HIFI_PLL_DIV:
+		reg = ac97_read(codec, AC97_LINE1_LEVEL) & 0xff80;
+		ac97_write(codec, AC97_LINE1_LEVEL, reg | 0x70 | div);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int wm9713_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
+		unsigned int fmt)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	u16 gpio = ac97_read(codec, AC97_GPIO_CFG) & 0xffc5;
+	u16 reg = 0x8000;
+
+	/* clock masters */
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBM_CFM:
+		reg |= 0x4000;
+		gpio |= 0x0010;
+		break;
+	case SND_SOC_DAIFMT_CBM_CFS:
+		reg |= 0x6000;
+		gpio |= 0x0018;
+		break;
+	case SND_SOC_DAIFMT_CBS_CFS:
+		reg |= 0x0200;
+		gpio |= 0x001a;
+		break;
+	case SND_SOC_DAIFMT_CBS_CFM:
+		gpio |= 0x0012;
+		break;
+	}
+
+	/* clock inversion */
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_IB_IF:
+		reg |= 0x00c0;
+		break;
+	case SND_SOC_DAIFMT_IB_NF:
+		reg |= 0x0080;
+		break;
+	case SND_SOC_DAIFMT_NB_IF:
+		reg |= 0x0040;
+		break;
+	}
+
+	/* DAI format */
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		reg |= 0x0002;
+		break;
+	case SND_SOC_DAIFMT_RIGHT_J:
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		reg |= 0x0001;
+		break;
+	case SND_SOC_DAIFMT_DSP_A:
+		reg |= 0x0003;
+		break;
+	case SND_SOC_DAIFMT_DSP_B:
+		reg |= 0x0043;
+		break;
+	}
+
+	ac97_write(codec, AC97_GPIO_CFG, gpio);
+	ac97_write(codec, AC97_CENTER_LFE_MASTER, reg);
+	return 0;
+}
+
+static int wm9713_pcm_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_device *socdev = rtd->socdev;
+	struct snd_soc_codec *codec = socdev->codec;
+	u16 reg = ac97_read(codec, AC97_CENTER_LFE_MASTER) & 0xfff3;
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		break;
+	case SNDRV_PCM_FORMAT_S20_3LE:
+		reg |= 0x0004;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		reg |= 0x0008;
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		reg |= 0x000c;
+		break;
+	}
+
+	/* enable PCM interface in master mode */
+	ac97_write(codec, AC97_CENTER_LFE_MASTER, reg);
+	return 0;
+}
+
+static void wm9713_voiceshutdown(struct snd_pcm_substream *substream)
+{
+    struct snd_soc_pcm_runtime *rtd = substream->private_data;
+    struct snd_soc_device *socdev = rtd->socdev;
+    struct snd_soc_codec *codec = socdev->codec;
+    u16 status;
+
+    /* Gracefully shut down the voice interface. */
+    status = ac97_read(codec, AC97_EXTENDED_STATUS) | 0x1000;
+    ac97_write(codec, AC97_HANDSET_RATE, 0x0280);
+    schedule_timeout_interruptible(msecs_to_jiffies(1));
+    ac97_write(codec, AC97_HANDSET_RATE, 0x0F80);
+    ac97_write(codec, AC97_EXTENDED_MID, status);
+}
+
+static int ac97_hifi_prepare(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_device *socdev = rtd->socdev;
+	struct snd_soc_codec *codec = socdev->codec;
+	int reg;
+	u16 vra;
+
+	vra = ac97_read(codec, AC97_EXTENDED_STATUS);
+	ac97_write(codec, AC97_EXTENDED_STATUS, vra | 0x1);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		reg = AC97_PCM_FRONT_DAC_RATE;
+	else
+		reg = AC97_PCM_LR_ADC_RATE;
+
+	return ac97_write(codec, reg, runtime->rate);
+}
+
+static int ac97_aux_prepare(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_device *socdev = rtd->socdev;
+	struct snd_soc_codec *codec = socdev->codec;
+	u16 vra, xsle;
+
+	vra = ac97_read(codec, AC97_EXTENDED_STATUS);
+	ac97_write(codec, AC97_EXTENDED_STATUS, vra | 0x1);
+	xsle = ac97_read(codec, AC97_PCI_SID);
+	ac97_write(codec, AC97_PCI_SID, xsle | 0x8000);
+
+	if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
+		return -ENODEV;
+
+	return ac97_write(codec, AC97_PCM_SURR_DAC_RATE, runtime->rate);
+}
+
+#define WM9713_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
+		SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 |\
+		SNDRV_PCM_RATE_48000)
+
+#define WM9713_PCM_FORMATS \
+	(SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \
+	 SNDRV_PCM_FORMAT_S24_LE)
+
+struct snd_soc_codec_dai wm9713_dai[] = {
+{
+	.name = "AC97 HiFi",
+	.type = SND_SOC_DAI_AC97_BUS,
+	.playback = {
+		.stream_name = "HiFi Playback",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = WM9713_RATES,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
+	.capture = {
+		.stream_name = "HiFi Capture",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = WM9713_RATES,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
+	.ops = {
+		.prepare = ac97_hifi_prepare,},
+	.dai_ops = {
+		.set_clkdiv = wm9713_set_dai_clkdiv,
+		.set_pll = wm9713_set_dai_pll,},
+	},
+	{
+	.name = "AC97 Aux",
+	.playback = {
+		.stream_name = "Aux Playback",
+		.channels_min = 1,
+		.channels_max = 1,
+		.rates = WM9713_RATES,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
+	.ops = {
+		.prepare = ac97_aux_prepare,},
+	.dai_ops = {
+		.set_clkdiv = wm9713_set_dai_clkdiv,
+		.set_pll = wm9713_set_dai_pll,},
+	},
+	{
+	.name = "WM9713 Voice",
+	.playback = {
+		.stream_name = "Voice Playback",
+		.channels_min = 1,
+		.channels_max = 1,
+		.rates = WM9713_RATES,
+		.formats = WM9713_PCM_FORMATS,},
+	.capture = {
+		.stream_name = "Voice Capture",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = WM9713_RATES,
+		.formats = WM9713_PCM_FORMATS,},
+	.ops = {
+		.hw_params = wm9713_pcm_hw_params,
+		.shutdown = wm9713_voiceshutdown,},
+	.dai_ops = {
+		.set_clkdiv = wm9713_set_dai_clkdiv,
+		.set_pll = wm9713_set_dai_pll,
+		.set_fmt = wm9713_set_dai_fmt,
+		.set_tristate = wm9713_set_dai_tristate,
+	},
+	},
+};
+EXPORT_SYMBOL_GPL(wm9713_dai);
+
+int wm9713_reset(struct snd_soc_codec *codec, int try_warm)
+{
+	if (try_warm && soc_ac97_ops.warm_reset) {
+		soc_ac97_ops.warm_reset(codec->ac97);
+		if (!(ac97_read(codec, 0) & 0x8000))
+			return 1;
+	}
+
+	soc_ac97_ops.reset(codec->ac97);
+	if (ac97_read(codec, 0) & 0x8000)
+		return -EIO;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(wm9713_reset);
+
+static int wm9713_dapm_event(struct snd_soc_codec *codec, int event)
+{
+	u16 reg;
+
+	switch (event) {
+	case SNDRV_CTL_POWER_D0: /* full On */
+		/* enable thermal shutdown */
+		reg = ac97_read(codec, AC97_EXTENDED_MID) & 0x1bff;
+		ac97_write(codec, AC97_EXTENDED_MID, reg);
+		break;
+	case SNDRV_CTL_POWER_D1: /* partial On */
+	case SNDRV_CTL_POWER_D2: /* partial On */
+		break;
+	case SNDRV_CTL_POWER_D3hot: /* Off, with power */
+		/* enable master bias and vmid */
+		reg = ac97_read(codec, AC97_EXTENDED_MID) & 0x3bff;
+		ac97_write(codec, AC97_EXTENDED_MID, reg);
+		ac97_write(codec, AC97_POWERDOWN, 0x0000);
+		break;
+	case SNDRV_CTL_POWER_D3cold: /* Off, without power */
+		/* disable everything including AC link */
+		ac97_write(codec, AC97_EXTENDED_MID, 0xffff);
+		ac97_write(codec, AC97_EXTENDED_MSTATUS, 0xffff);
+		ac97_write(codec, AC97_POWERDOWN, 0xffff);
+		break;
+	}
+	codec->dapm_state = event;
+	return 0;
+}
+
+static int wm9713_soc_suspend(struct platform_device *pdev,
+	pm_message_t state)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_codec *codec = socdev->codec;
+
+	wm9713_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
+	return 0;
+}
+
+static int wm9713_soc_resume(struct platform_device *pdev)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_codec *codec = socdev->codec;
+	struct wm9713_priv *wm9713 = codec->private_data;
+	int i, ret;
+	u16 *cache = codec->reg_cache;
+
+	ret = wm9713_reset(codec, 1);
+	if (ret < 0) {
+		printk(KERN_ERR "could not reset AC97 codec\n");
+		return ret;
+	}
+
+	wm9713_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
+
+	/* do we need to re-start the PLL ? */
+	if (wm9713->pll_out)
+		wm9713_set_pll(codec, 0, wm9713->pll_in, wm9713->pll_out);
+
+	/* only synchronise the codec if warm reset failed */
+	if (ret == 0) {
+		for (i = 2; i < ARRAY_SIZE(wm9713_reg) << 1; i += 2) {
+			if (i == AC97_POWERDOWN || i == AC97_EXTENDED_MID ||
+				i == AC97_EXTENDED_MSTATUS || i > 0x66)
+				continue;
+			soc_ac97_ops.write(codec->ac97, i, cache[i>>1]);
+		}
+	}
+
+	if (codec->suspend_dapm_state == SNDRV_CTL_POWER_D0)
+		wm9713_dapm_event(codec, SNDRV_CTL_POWER_D0);
+
+	return ret;
+}
+
+static int wm9713_soc_probe(struct platform_device *pdev)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_codec *codec;
+	int ret = 0, reg;
+
+	printk(KERN_INFO "WM9713/WM9714 SoC Audio Codec %s\n", WM9713_VERSION);
+
+	socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
+	if (socdev->codec == NULL)
+		return -ENOMEM;
+	codec = socdev->codec;
+	mutex_init(&codec->mutex);
+
+	codec->reg_cache = kmemdup(wm9713_reg, sizeof(wm9713_reg), GFP_KERNEL);
+	if (codec->reg_cache == NULL) {
+		ret = -ENOMEM;
+		goto cache_err;
+	}
+	codec->reg_cache_size = sizeof(wm9713_reg);
+	codec->reg_cache_step = 2;
+
+	codec->private_data = kzalloc(sizeof(struct wm9713_priv), GFP_KERNEL);
+	if (codec->private_data == NULL) {
+		ret = -ENOMEM;
+		goto priv_err;
+	}
+
+	codec->name = "WM9713";
+	codec->owner = THIS_MODULE;
+	codec->dai = wm9713_dai;
+	codec->num_dai = ARRAY_SIZE(wm9713_dai);
+	codec->write = ac97_write;
+	codec->read = ac97_read;
+	codec->dapm_event = wm9713_dapm_event;
+	INIT_LIST_HEAD(&codec->dapm_widgets);
+	INIT_LIST_HEAD(&codec->dapm_paths);
+
+	ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
+	if (ret < 0)
+		goto codec_err;
+
+	/* register pcms */
+	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+	if (ret < 0)
+		goto pcm_err;
+
+	/* do a cold reset for the controller and then try
+	 * a warm reset followed by an optional cold reset for codec */
+	wm9713_reset(codec, 0);
+	ret = wm9713_reset(codec, 1);
+	if (ret < 0) {
+		printk(KERN_ERR "AC97 link error\n");
+		goto reset_err;
+	}
+
+	wm9713_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
+
+	/* unmute the adc - move to kcontrol */
+	reg = ac97_read(codec, AC97_CD) & 0x7fff;
+	ac97_write(codec, AC97_CD, reg);
+
+	wm9713_add_controls(codec);
+	wm9713_add_widgets(codec);
+	ret = snd_soc_register_card(socdev);
+	if (ret < 0)
+		goto reset_err;
+	return 0;
+
+reset_err:
+	snd_soc_free_pcms(socdev);
+
+pcm_err:
+	snd_soc_free_ac97_codec(codec);
+
+codec_err:
+	kfree(codec->private_data);
+
+priv_err:
+	kfree(codec->reg_cache);
+
+cache_err:
+	kfree(socdev->codec);
+	socdev->codec = NULL;
+	return ret;
+}
+
+static int wm9713_soc_remove(struct platform_device *pdev)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_codec *codec = socdev->codec;
+
+	if (codec == NULL)
+		return 0;
+
+	snd_soc_dapm_free(socdev);
+	snd_soc_free_pcms(socdev);
+	snd_soc_free_ac97_codec(codec);
+	kfree(codec->private_data);
+	kfree(codec->reg_cache);
+	kfree(codec->dai);
+	kfree(codec);
+	return 0;
+}
+
+struct snd_soc_codec_device soc_codec_dev_wm9713 = {
+	.probe = 	wm9713_soc_probe,
+	.remove = 	wm9713_soc_remove,
+	.suspend =	wm9713_soc_suspend,
+	.resume = 	wm9713_soc_resume,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_wm9713);
+
+MODULE_DESCRIPTION("ASoC WM9713/WM9714 driver");
+MODULE_AUTHOR("Liam Girdwood");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm9713.h b/sound/soc/codecs/wm9713.h
new file mode 100644
index 00000000000..d357b6c8134
--- /dev/null
+++ b/sound/soc/codecs/wm9713.h
@@ -0,0 +1,53 @@
+/*
+ * wm9713.h  --  WM9713 Soc Audio driver
+ */
+
+#ifndef _WM9713_H
+#define _WM9713_H
+
+/* clock inputs */
+#define WM9713_CLKA_PIN			0
+#define WM9713_CLKB_PIN			1
+
+/* clock divider ID's */
+#define WM9713_PCMCLK_DIV		0
+#define WM9713_CLKA_MULT		1
+#define WM9713_CLKB_MULT		2
+#define WM9713_HIFI_DIV			3
+#define WM9713_PCMBCLK_DIV		4
+#define WM9713_PCMCLK_PLL_DIV           5
+#define WM9713_HIFI_PLL_DIV             6
+
+/* Calculate the appropriate bit mask for the external PCM clock divider */
+#define WM9713_PCMDIV(x)	((x - 1) << 8)
+
+/* Calculate the appropriate bit mask for the external HiFi clock divider */
+#define WM9713_HIFIDIV(x)	((x - 1) << 12)
+
+/* MCLK clock mulitipliers */
+#define WM9713_CLKA_X1		(0 << 1)
+#define WM9713_CLKA_X2		(1 << 1)
+#define WM9713_CLKB_X1		(0 << 2)
+#define WM9713_CLKB_X2		(1 << 2)
+
+/* MCLK clock MUX */
+#define WM9713_CLK_MUX_A		(0 << 0)
+#define WM9713_CLK_MUX_B		(1 << 0)
+
+/* Voice DAI BCLK divider */
+#define WM9713_PCMBCLK_DIV_1	(0 << 9)
+#define WM9713_PCMBCLK_DIV_2	(1 << 9)
+#define WM9713_PCMBCLK_DIV_4	(2 << 9)
+#define WM9713_PCMBCLK_DIV_8	(3 << 9)
+#define WM9713_PCMBCLK_DIV_16	(4 << 9)
+
+#define WM9713_DAI_AC97_HIFI	0
+#define WM9713_DAI_AC97_AUX		1
+#define WM9713_DAI_PCM_VOICE	2
+
+extern struct snd_soc_codec_device soc_codec_dev_wm9713;
+extern struct snd_soc_codec_dai wm9713_dai[3];
+
+int wm9713_reset(struct snd_soc_codec *codec,  int try_warm);
+
+#endif
-- 
cgit v1.2.3-70-g09d2


From c5059259688ab76f14f2f69a93e13575a36b614b Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Sat, 16 Feb 2008 09:43:56 +0100
Subject: [ALSA] hda-codec - Add support of AD1883/1884A/1984A/1984B

Added the support of new AD codecs: AD1883, AD1884A, AD1984A and AD1984B.
These are almost compatible except for additional digital pins, etc.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 Documentation/sound/alsa/ALSA-Configuration.txt |   4 +
 sound/pci/hda/patch_analog.c                    | 327 ++++++++++++++++++++++++
 2 files changed, 331 insertions(+)

(limited to 'sound')

diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 9a56b9b273c..bfc6d486ad9 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -912,6 +912,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
 	  3stack	3-stack mode (default)
 	  6stack	6-stack mode
 
+	AD1884A / AD1883 / AD1984A / AD1984B
+	  desktop	3-stack desktop (default)
+	  laptop	laptop with HP jack sensing
+
 	AD1884
 	  N/A
 
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 1f2102860fe..b037fca1b44 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -3410,6 +3410,329 @@ static int patch_ad1984(struct hda_codec *codec)
 }
 
 
+/*
+ * AD1883 / AD1884A / AD1984A / AD1984B
+ *
+ * port-B (0x14) - front mic-in
+ * port-E (0x1c) - rear mic-in
+ * port-F (0x16) - CD / ext out
+ * port-C (0x15) - rear line-in
+ * port-D (0x12) - rear line-out
+ * port-A (0x11) - front hp-out
+ *
+ * AD1984A = AD1884A + digital-mic
+ * AD1883 = equivalent with AD1984A
+ * AD1984B = AD1984A + extra SPDIF-out
+ *
+ * FIXME:
+ * We share the single DAC for both HP and line-outs (see AD1884/1984).
+ */
+
+static hda_nid_t ad1884a_dac_nids[1] = {
+	0x03,
+};
+
+#define ad1884a_adc_nids	ad1884_adc_nids
+#define ad1884a_capsrc_nids	ad1884_capsrc_nids
+
+#define AD1884A_SPDIF_OUT	0x02
+
+static struct hda_input_mux ad1884a_capture_source = {
+	.num_items = 5,
+	.items = {
+		{ "Front Mic", 0x0 },
+		{ "Mic", 0x4 },
+		{ "Line", 0x1 },
+		{ "CD", 0x2 },
+		{ "Mix", 0x3 },
+	},
+};
+
+static struct snd_kcontrol_new ad1884a_base_mixers[] = {
+	HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
+	HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
+	HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Boost", 0x15, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		/* The multiple "Capture Source" controls confuse alsamixer
+		 * So call somewhat different..
+		 */
+		/* .name = "Capture Source", */
+		.name = "Input Source",
+		.count = 2,
+		.info = ad198x_mux_enum_info,
+		.get = ad198x_mux_enum_get,
+		.put = ad198x_mux_enum_put,
+	},
+	/* SPDIF controls */
+	HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
+		/* identical with ad1983 */
+		.info = ad1983_spdif_route_info,
+		.get = ad1983_spdif_route_get,
+		.put = ad1983_spdif_route_put,
+	},
+	{ } /* end */
+};
+
+/*
+ * initialization verbs
+ */
+static struct hda_verb ad1884a_init_verbs[] = {
+	/* DACs; unmute as default */
+	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
+	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
+	/* Port-A (HP) mixer - route only from analog mixer */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	/* Port-A pin */
+	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Port-D (Line-out) mixer - route only from analog mixer */
+	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	/* Port-D pin */
+	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Mono-out mixer - route only from analog mixer */
+	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	/* Mono-out pin */
+	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Port-B (front mic) pin */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Port-C (rear line-in) pin */
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Port-E (rear mic) pin */
+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* no boost */
+	/* Port-F (CD) pin */
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Analog mixer; mute as default */
+	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, /* aux */
+	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
+	/* Analog Mix output amp */
+	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* capture sources */
+	{0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* SPDIF output amp */
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
+	{ } /* end */
+};
+
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static struct hda_amp_list ad1884a_loopbacks[] = {
+	{ 0x20, HDA_INPUT, 0 }, /* Front Mic */
+	{ 0x20, HDA_INPUT, 1 }, /* Mic */
+	{ 0x20, HDA_INPUT, 2 }, /* CD */
+	{ 0x20, HDA_INPUT, 4 }, /* Docking */
+	{ } /* end */
+};
+#endif
+
+/*
+ * Laptop model
+ *
+ * Port A: Headphone jack
+ * Port B: MIC jack
+ * Port C: Internal MIC
+ * Port D: Dock Line Out (if enabled)
+ * Port E: Dock Line In (if enabled)
+ * Port F: Internal speakers
+ */
+
+static struct hda_input_mux ad1884a_laptop_capture_source = {
+	.num_items = 4,
+	.items = {
+		{ "Mic", 0x0 },		/* port-B */
+		{ "Internal Mic", 0x1 }, /* port-C */
+		{ "Dock Mic", 0x4 },	/* port-E */
+		{ "Mix", 0x3 },
+	},
+};
+
+static struct snd_kcontrol_new ad1884a_laptop_mixers[] = {
+	HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Dock Playback Switch", 0x12, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
+	HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
+	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
+	HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
+	HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Dock Mic Boost", 0x25, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		/* The multiple "Capture Source" controls confuse alsamixer
+		 * So call somewhat different..
+		 */
+		/* .name = "Capture Source", */
+		.name = "Input Source",
+		.count = 2,
+		.info = ad198x_mux_enum_info,
+		.get = ad198x_mux_enum_get,
+		.put = ad198x_mux_enum_put,
+	},
+	{ } /* end */
+};
+
+/* mute internal speaker if HP is plugged */
+static void ad1884a_hp_automute(struct hda_codec *codec)
+{
+	unsigned int present;
+
+	present = snd_hda_codec_read(codec, 0x11, 0,
+				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+	snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
+				 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+	snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
+			    present ? 0x00 : 0x02);
+}
+
+#define AD1884A_HP_EVENT		0x37
+
+/* unsolicited event for HP jack sensing */
+static void ad1884a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+	if ((res >> 26) != AD1884A_HP_EVENT)
+		return;
+	ad1884a_hp_automute(codec);
+}
+
+/* initialize jack-sensing, too */
+static int ad1884a_hp_init(struct hda_codec *codec)
+{
+	ad198x_init(codec);
+	ad1884a_hp_automute(codec);
+	return 0;
+}
+
+/* additional verbs for laptop model */
+static struct hda_verb ad1884a_laptop_verbs[] = {
+	/* Port-A (HP) pin - always unmuted */
+	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* Port-F (int speaker) mixer - route only from analog mixer */
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	/* Port-F pin */
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* analog mix */
+	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+	/* unsolicited event for pin-sense */
+	{0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
+	{ } /* end */
+};
+
+/*
+ */
+
+enum {
+	AD1884A_DESKTOP,
+	AD1884A_LAPTOP,
+	AD1884A_MODELS
+};
+
+static const char *ad1884a_models[AD1884A_MODELS] = {
+	[AD1884A_DESKTOP]	= "desktop",
+	[AD1884A_LAPTOP]	= "laptop",
+};
+
+static int patch_ad1884a(struct hda_codec *codec)
+{
+	struct ad198x_spec *spec;
+	int board_config;
+
+	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+	if (spec == NULL)
+		return -ENOMEM;
+
+	mutex_init(&spec->amp_mutex);
+	codec->spec = spec;
+
+	spec->multiout.max_channels = 2;
+	spec->multiout.num_dacs = ARRAY_SIZE(ad1884a_dac_nids);
+	spec->multiout.dac_nids = ad1884a_dac_nids;
+	spec->multiout.dig_out_nid = AD1884A_SPDIF_OUT;
+	spec->num_adc_nids = ARRAY_SIZE(ad1884a_adc_nids);
+	spec->adc_nids = ad1884a_adc_nids;
+	spec->capsrc_nids = ad1884a_capsrc_nids;
+	spec->input_mux = &ad1884a_capture_source;
+	spec->num_mixers = 1;
+	spec->mixers[0] = ad1884a_base_mixers;
+	spec->num_init_verbs = 1;
+	spec->init_verbs[0] = ad1884a_init_verbs;
+	spec->spdif_route = 0;
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+	spec->loopback.amplist = ad1884a_loopbacks;
+#endif
+	codec->patch_ops = ad198x_patch_ops;
+
+	/* override some parameters */
+	board_config = snd_hda_check_board_config(codec, AD1884A_MODELS,
+						  ad1884a_models, NULL);
+	switch (board_config) {
+	case AD1884A_LAPTOP:
+		spec->mixers[0] = ad1884a_laptop_mixers;
+		spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs;
+		spec->multiout.dig_out_nid = 0;
+		spec->input_mux = &ad1884a_laptop_capture_source;
+		codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
+		codec->patch_ops.init = ad1884a_hp_init;
+		break;
+	}
+
+	return 0;
+}
+
+
 /*
  * AD1882
  *
@@ -3709,8 +4032,12 @@ static int patch_ad1882(struct hda_codec *codec)
  * patch entries
  */
 struct hda_codec_preset snd_hda_preset_analog[] = {
+	{ .id = 0x11d4184a, .name = "AD1884A", .patch = patch_ad1884a },
 	{ .id = 0x11d41882, .name = "AD1882", .patch = patch_ad1882 },
+	{ .id = 0x11d41883, .name = "AD1883", .patch = patch_ad1884a },
 	{ .id = 0x11d41884, .name = "AD1884", .patch = patch_ad1884 },
+	{ .id = 0x11d4194a, .name = "AD1984A", .patch = patch_ad1884a },
+	{ .id = 0x11d4194b, .name = "AD1984B", .patch = patch_ad1884a },
 	{ .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 },
 	{ .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
 	{ .id = 0x11d41984, .name = "AD1984", .patch = patch_ad1984 },
-- 
cgit v1.2.3-70-g09d2


From b40b04ad380ad641e5740486e4b9a56fd32b64cc Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Sat, 16 Feb 2008 09:44:56 +0100
Subject: [ALSA] hda-codec - Add model=mobile for AD1884A & co

Added the new model mobile for AD1884A and compatible codecs.
It's a reduced version of model=laptop.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 Documentation/sound/alsa/ALSA-Configuration.txt |  1 +
 sound/pci/hda/patch_analog.c                    | 48 ++++++++++++++++++++++++-
 2 files changed, 48 insertions(+), 1 deletion(-)

(limited to 'sound')

diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index bfc6d486ad9..2cfb8b469c5 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -915,6 +915,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
 	AD1884A / AD1883 / AD1984A / AD1984B
 	  desktop	3-stack desktop (default)
 	  laptop	laptop with HP jack sensing
+	  mobile	mobile devices with HP jack sensing
 
 	AD1884
 	  N/A
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index b037fca1b44..3f3905cc4e0 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -3623,6 +3623,36 @@ static struct snd_kcontrol_new ad1884a_laptop_mixers[] = {
 	{ } /* end */
 };
 
+static struct hda_input_mux ad1884a_mobile_capture_source = {
+	.num_items = 2,
+	.items = {
+		{ "Mic", 0x1 }, /* port-C */
+		{ "Mix", 0x3 },
+	},
+};
+
+static struct snd_kcontrol_new ad1884a_mobile_mixers[] = {
+	HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
+	HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
+	HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
+	HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost", 0x15, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Capture Source",
+		.info = ad198x_mux_enum_info,
+		.get = ad198x_mux_enum_get,
+		.put = ad198x_mux_enum_put,
+	},
+	{ } /* end */
+};
+
 /* mute internal speaker if HP is plugged */
 static void ad1884a_hp_automute(struct hda_codec *codec)
 {
@@ -3677,12 +3707,19 @@ static struct hda_verb ad1884a_laptop_verbs[] = {
 enum {
 	AD1884A_DESKTOP,
 	AD1884A_LAPTOP,
+	AD1884A_MOBILE,
 	AD1884A_MODELS
 };
 
 static const char *ad1884a_models[AD1884A_MODELS] = {
 	[AD1884A_DESKTOP]	= "desktop",
 	[AD1884A_LAPTOP]	= "laptop",
+	[AD1884A_MOBILE]	= "mobile",
+};
+
+static struct snd_pci_quirk ad1884a_cfg_tbl[] = {
+	SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE),
+	{}
 };
 
 static int patch_ad1884a(struct hda_codec *codec)
@@ -3717,7 +3754,8 @@ static int patch_ad1884a(struct hda_codec *codec)
 
 	/* override some parameters */
 	board_config = snd_hda_check_board_config(codec, AD1884A_MODELS,
-						  ad1884a_models, NULL);
+						  ad1884a_models,
+						  ad1884a_cfg_tbl);
 	switch (board_config) {
 	case AD1884A_LAPTOP:
 		spec->mixers[0] = ad1884a_laptop_mixers;
@@ -3727,6 +3765,14 @@ static int patch_ad1884a(struct hda_codec *codec)
 		codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
 		codec->patch_ops.init = ad1884a_hp_init;
 		break;
+	case AD1884A_MOBILE:
+		spec->mixers[0] = ad1884a_mobile_mixers;
+		spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs;
+		spec->multiout.dig_out_nid = 0;
+		spec->input_mux = &ad1884a_mobile_capture_source;
+		codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
+		codec->patch_ops.init = ad1884a_hp_init;
+		break;
 	}
 
 	return 0;
-- 
cgit v1.2.3-70-g09d2


From 310355c111dbae005269fe3fc39afdd60779bf5d Mon Sep 17 00:00:00 2001
From: Vladimir Barinov <vbarinov@ru.mvista.com>
Date: Mon, 18 Feb 2008 11:40:22 +0100
Subject: [ALSA] Davinci ASoC support

Add ASoC support for the TI Davinci SoC and the Davicni-EVM reference board.
It includes:
- ASoC Davinci DMA driver
- ASoC Davinci I2S (Davinci McBSP module based) driver
- ASoC Davinci-EVM reference board

Signed-off-by: Vladimir Barinov <vbarinov@ru.mvista.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/soc/Kconfig               |   1 +
 sound/soc/Makefile              |   2 +-
 sound/soc/davinci/Kconfig       |  19 ++
 sound/soc/davinci/Makefile      |  11 ++
 sound/soc/davinci/davinci-evm.c | 208 ++++++++++++++++++++
 sound/soc/davinci/davinci-i2s.c | 407 ++++++++++++++++++++++++++++++++++++++++
 sound/soc/davinci/davinci-i2s.h |  17 ++
 sound/soc/davinci/davinci-pcm.c | 389 ++++++++++++++++++++++++++++++++++++++
 sound/soc/davinci/davinci-pcm.h |  29 +++
 9 files changed, 1082 insertions(+), 1 deletion(-)
 create mode 100644 sound/soc/davinci/Kconfig
 create mode 100644 sound/soc/davinci/Makefile
 create mode 100644 sound/soc/davinci/davinci-evm.c
 create mode 100644 sound/soc/davinci/davinci-i2s.c
 create mode 100644 sound/soc/davinci/davinci-i2s.h
 create mode 100644 sound/soc/davinci/davinci-pcm.c
 create mode 100644 sound/soc/davinci/davinci-pcm.h

(limited to 'sound')

diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index 27658521516..a3b51df2bea 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -29,6 +29,7 @@ source "sound/soc/pxa/Kconfig"
 source "sound/soc/s3c24xx/Kconfig"
 source "sound/soc/sh/Kconfig"
 source "sound/soc/fsl/Kconfig"
+source "sound/soc/davinci/Kconfig"
 
 # Supported codecs
 source "sound/soc/codecs/Kconfig"
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 4869c9ae7a0..e489dbdde45 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -1,4 +1,4 @@
 snd-soc-core-objs := soc-core.o soc-dapm.o
 
 obj-$(CONFIG_SND_SOC)	+= snd-soc-core.o
-obj-$(CONFIG_SND_SOC)	+= codecs/ at91/ pxa/ s3c24xx/ sh/ fsl/
+obj-$(CONFIG_SND_SOC)	+= codecs/ at91/ pxa/ s3c24xx/ sh/ fsl/ davinci/
diff --git a/sound/soc/davinci/Kconfig b/sound/soc/davinci/Kconfig
new file mode 100644
index 00000000000..20680c551aa
--- /dev/null
+++ b/sound/soc/davinci/Kconfig
@@ -0,0 +1,19 @@
+config SND_DAVINCI_SOC
+	tristate "SoC Audio for the TI DAVINCI chip"
+	depends on ARCH_DAVINCI && SND_SOC
+	help
+	  Say Y or M if you want to add support for codecs attached to
+	  the DAVINCI AC97 or I2S interface. You will also need
+	  to select the audio interfaces to support below.
+
+config SND_DAVINCI_SOC_I2S
+	tristate
+
+config SND_DAVINCI_SOC_EVM
+	tristate "SoC Audio support for DaVinci EVM"
+	depends on SND_DAVINCI_SOC && MACH_DAVINCI_EVM
+	select SND_DAVINCI_SOC_I2S
+	select SND_SOC_TLV320AIC3X
+	help
+	  Say Y if you want to add support for SoC audio on TI
+	  DaVinci EVM platform.
diff --git a/sound/soc/davinci/Makefile b/sound/soc/davinci/Makefile
new file mode 100644
index 00000000000..ca772e5b463
--- /dev/null
+++ b/sound/soc/davinci/Makefile
@@ -0,0 +1,11 @@
+# DAVINCI Platform Support
+snd-soc-davinci-objs := davinci-pcm.o
+snd-soc-davinci-i2s-objs := davinci-i2s.o
+
+obj-$(CONFIG_SND_DAVINCI_SOC) += snd-soc-davinci.o
+obj-$(CONFIG_SND_DAVINCI_SOC_I2S) += snd-soc-davinci-i2s.o
+
+# DAVINCI Machine Support
+snd-soc-evm-objs := davinci-evm.o
+
+obj-$(CONFIG_SND_DAVINCI_SOC_EVM) += snd-soc-evm.o
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c
new file mode 100644
index 00000000000..fcd16524033
--- /dev/null
+++ b/sound/soc/davinci/davinci-evm.c
@@ -0,0 +1,208 @@
+/*
+ * ASoC driver for TI DAVINCI EVM platform
+ *
+ * Author:      Vladimir Barinov, <vbarinov@ru.mvista.com>
+ * Copyright:   (C) 2007 MontaVista Software, Inc., <source@mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <asm/mach-types.h>
+#include <asm/dma.h>
+#include <asm/arch/hardware.h>
+
+#include "../codecs/tlv320aic3x.h"
+#include "davinci-pcm.h"
+#include "davinci-i2s.h"
+
+#define EVM_CODEC_CLOCK 22579200
+
+static int evm_hw_params(struct snd_pcm_substream *substream,
+			 struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
+	struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+	int ret = 0;
+
+	/* set codec DAI configuration */
+	ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+					 SND_SOC_DAIFMT_CBM_CFM);
+	if (ret < 0)
+		return ret;
+
+	/* set cpu DAI configuration */
+	ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_CBM_CFM |
+				       SND_SOC_DAIFMT_IB_NF);
+	if (ret < 0)
+		return ret;
+
+	/* set the codec system clock */
+	ret = codec_dai->dai_ops.set_sysclk(codec_dai, 0, EVM_CODEC_CLOCK,
+					    SND_SOC_CLOCK_OUT);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static struct snd_soc_ops evm_ops = {
+	.hw_params = evm_hw_params,
+};
+
+/* davinci-evm machine dapm widgets */
+static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
+	SND_SOC_DAPM_HP("Headphone Jack", NULL),
+	SND_SOC_DAPM_LINE("Line Out", NULL),
+	SND_SOC_DAPM_MIC("Mic Jack", NULL),
+	SND_SOC_DAPM_LINE("Line In", NULL),
+};
+
+/* davinci-evm machine audio_mapnections to the codec pins */
+static const char *audio_map[][3] = {
+	/* Headphone connected to HPLOUT, HPROUT */
+	{"Headphone Jack", NULL, "HPLOUT"},
+	{"Headphone Jack", NULL, "HPROUT"},
+
+	/* Line Out connected to LLOUT, RLOUT */
+	{"Line Out", NULL, "LLOUT"},
+	{"Line Out", NULL, "RLOUT"},
+
+	/* Mic connected to (MIC3L | MIC3R) */
+	{"MIC3L", NULL, "Mic Bias 2V"},
+	{"MIC3R", NULL, "Mic Bias 2V"},
+	{"Mic Bias 2V", NULL, "Mic Jack"},
+
+	/* Line In connected to (LINE1L | LINE2L), (LINE1R | LINE2R) */
+	{"LINE1L", NULL, "Line In"},
+	{"LINE2L", NULL, "Line In"},
+	{"LINE1R", NULL, "Line In"},
+	{"LINE2R", NULL, "Line In"},
+
+	{NULL, NULL, NULL},
+};
+
+/* Logic for a aic3x as connected on a davinci-evm */
+static int evm_aic3x_init(struct snd_soc_codec *codec)
+{
+	int i;
+
+	/* Add davinci-evm specific widgets */
+	for (i = 0; i < ARRAY_SIZE(aic3x_dapm_widgets); i++)
+		snd_soc_dapm_new_control(codec, &aic3x_dapm_widgets[i]);
+
+	/* Set up davinci-evm specific audio path audio_map */
+	for (i = 0; audio_map[i][0] != NULL; i++)
+		snd_soc_dapm_connect_input(codec, audio_map[i][0],
+					   audio_map[i][1], audio_map[i][2]);
+
+	/* not connected */
+	snd_soc_dapm_set_endpoint(codec, "MONO_LOUT", 0);
+	snd_soc_dapm_set_endpoint(codec, "HPLCOM", 0);
+	snd_soc_dapm_set_endpoint(codec, "HPRCOM", 0);
+
+	/* always connected */
+	snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 1);
+	snd_soc_dapm_set_endpoint(codec, "Line Out", 1);
+	snd_soc_dapm_set_endpoint(codec, "Mic Jack", 1);
+	snd_soc_dapm_set_endpoint(codec, "Line In", 1);
+
+	snd_soc_dapm_sync_endpoints(codec);
+
+	return 0;
+}
+
+/* davinci-evm digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link evm_dai = {
+	.name = "TLV320AIC3X",
+	.stream_name = "AIC3X",
+	.cpu_dai = &davinci_i2s_dai,
+	.codec_dai = &aic3x_dai,
+	.init = evm_aic3x_init,
+	.ops = &evm_ops,
+};
+
+/* davinci-evm audio machine driver */
+static struct snd_soc_machine snd_soc_machine_evm = {
+	.name = "DaVinci EVM",
+	.dai_link = &evm_dai,
+	.num_links = 1,
+};
+
+/* evm audio private data */
+static struct aic3x_setup_data evm_aic3x_setup = {
+	.i2c_address = 0x1b,
+};
+
+/* evm audio subsystem */
+static struct snd_soc_device evm_snd_devdata = {
+	.machine = &snd_soc_machine_evm,
+	.platform = &davinci_soc_platform,
+	.codec_dev = &soc_codec_dev_aic3x,
+	.codec_data = &evm_aic3x_setup,
+};
+
+static struct resource evm_snd_resources[] = {
+	{
+		.start = DAVINCI_MCBSP_BASE,
+		.end = DAVINCI_MCBSP_BASE + SZ_8K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+static struct evm_snd_platform_data evm_snd_data = {
+	.tx_dma_ch	= DM644X_DMACH_MCBSP_TX,
+	.rx_dma_ch	= DM644X_DMACH_MCBSP_RX,
+};
+
+static struct platform_device *evm_snd_device;
+
+static int __init evm_init(void)
+{
+	int ret;
+
+	evm_snd_device = platform_device_alloc("soc-audio", 0);
+	if (!evm_snd_device)
+		return -ENOMEM;
+
+	platform_set_drvdata(evm_snd_device, &evm_snd_devdata);
+	evm_snd_devdata.dev = &evm_snd_device->dev;
+	evm_snd_device->dev.platform_data = &evm_snd_data;
+
+	ret = platform_device_add_resources(evm_snd_device, evm_snd_resources,
+					    ARRAY_SIZE(evm_snd_resources));
+	if (ret) {
+		platform_device_put(evm_snd_device);
+		return ret;
+	}
+
+	ret = platform_device_add(evm_snd_device);
+	if (ret)
+		platform_device_put(evm_snd_device);
+
+	return ret;
+}
+
+static void __exit evm_exit(void)
+{
+	platform_device_unregister(evm_snd_device);
+}
+
+module_init(evm_init);
+module_exit(evm_exit);
+
+MODULE_AUTHOR("Vladimir Barinov");
+MODULE_DESCRIPTION("TI DAVINCI EVM ASoC driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c
new file mode 100644
index 00000000000..c421774b33e
--- /dev/null
+++ b/sound/soc/davinci/davinci-i2s.c
@@ -0,0 +1,407 @@
+/*
+ * ALSA SoC I2S (McBSP) Audio Layer for TI DAVINCI processor
+ *
+ * Author:      Vladimir Barinov, <vbarinov@ru.mvista.com>
+ * Copyright:   (C) 2007 MontaVista Software, Inc., <source@mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+#include "davinci-pcm.h"
+
+#define DAVINCI_MCBSP_DRR_REG	0x00
+#define DAVINCI_MCBSP_DXR_REG	0x04
+#define DAVINCI_MCBSP_SPCR_REG	0x08
+#define DAVINCI_MCBSP_RCR_REG	0x0c
+#define DAVINCI_MCBSP_XCR_REG	0x10
+#define DAVINCI_MCBSP_SRGR_REG	0x14
+#define DAVINCI_MCBSP_PCR_REG	0x24
+
+#define DAVINCI_MCBSP_SPCR_RRST		(1 << 0)
+#define DAVINCI_MCBSP_SPCR_RINTM(v)	((v) << 4)
+#define DAVINCI_MCBSP_SPCR_XRST		(1 << 16)
+#define DAVINCI_MCBSP_SPCR_XINTM(v)	((v) << 20)
+#define DAVINCI_MCBSP_SPCR_GRST		(1 << 22)
+#define DAVINCI_MCBSP_SPCR_FRST		(1 << 23)
+#define DAVINCI_MCBSP_SPCR_FREE		(1 << 25)
+
+#define DAVINCI_MCBSP_RCR_RWDLEN1(v)	((v) << 5)
+#define DAVINCI_MCBSP_RCR_RFRLEN1(v)	((v) << 8)
+#define DAVINCI_MCBSP_RCR_RDATDLY(v)	((v) << 16)
+#define DAVINCI_MCBSP_RCR_RWDLEN2(v)	((v) << 21)
+
+#define DAVINCI_MCBSP_XCR_XWDLEN1(v)	((v) << 5)
+#define DAVINCI_MCBSP_XCR_XFRLEN1(v)	((v) << 8)
+#define DAVINCI_MCBSP_XCR_XDATDLY(v)	((v) << 16)
+#define DAVINCI_MCBSP_XCR_XFIG		(1 << 18)
+#define DAVINCI_MCBSP_XCR_XWDLEN2(v)	((v) << 21)
+
+#define DAVINCI_MCBSP_SRGR_FWID(v)	((v) << 8)
+#define DAVINCI_MCBSP_SRGR_FPER(v)	((v) << 16)
+#define DAVINCI_MCBSP_SRGR_FSGM		(1 << 28)
+
+#define DAVINCI_MCBSP_PCR_CLKRP		(1 << 0)
+#define DAVINCI_MCBSP_PCR_CLKXP		(1 << 1)
+#define DAVINCI_MCBSP_PCR_FSRP		(1 << 2)
+#define DAVINCI_MCBSP_PCR_FSXP		(1 << 3)
+#define DAVINCI_MCBSP_PCR_CLKRM		(1 << 8)
+#define DAVINCI_MCBSP_PCR_CLKXM		(1 << 9)
+#define DAVINCI_MCBSP_PCR_FSRM		(1 << 10)
+#define DAVINCI_MCBSP_PCR_FSXM		(1 << 11)
+
+#define MOD_REG_BIT(val, mask, set) do { \
+	if (set) { \
+		val |= mask; \
+	} else { \
+		val &= ~mask; \
+	} \
+} while (0)
+
+enum {
+	DAVINCI_MCBSP_WORD_8 = 0,
+	DAVINCI_MCBSP_WORD_12,
+	DAVINCI_MCBSP_WORD_16,
+	DAVINCI_MCBSP_WORD_20,
+	DAVINCI_MCBSP_WORD_24,
+	DAVINCI_MCBSP_WORD_32,
+};
+
+static struct davinci_pcm_dma_params davinci_i2s_pcm_out = {
+	.name = "I2S PCM Stereo out",
+};
+
+static struct davinci_pcm_dma_params davinci_i2s_pcm_in = {
+	.name = "I2S PCM Stereo in",
+};
+
+struct davinci_mcbsp_dev {
+	void __iomem			*base;
+	struct clk			*clk;
+	struct davinci_pcm_dma_params	*dma_params[2];
+};
+
+static inline void davinci_mcbsp_write_reg(struct davinci_mcbsp_dev *dev,
+					   int reg, u32 val)
+{
+	__raw_writel(val, dev->base + reg);
+}
+
+static inline u32 davinci_mcbsp_read_reg(struct davinci_mcbsp_dev *dev, int reg)
+{
+	return __raw_readl(dev->base + reg);
+}
+
+static void davinci_mcbsp_start(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
+	u32 w;
+
+	/* Start the sample generator and enable transmitter/receiver */
+	w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
+	MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_GRST, 1);
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 1);
+	else
+		MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_RRST, 1);
+	davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
+
+	/* Start frame sync */
+	w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
+	MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_FRST, 1);
+	davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
+}
+
+static void davinci_mcbsp_stop(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
+	u32 w;
+
+	/* Reset transmitter/receiver and sample rate/frame sync generators */
+	w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
+	MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_GRST |
+		       DAVINCI_MCBSP_SPCR_FRST, 0);
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 0);
+	else
+		MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_RRST, 0);
+	davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
+}
+
+static int davinci_i2s_startup(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+	struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
+
+	cpu_dai->dma_data = dev->dma_params[substream->stream];
+
+	return 0;
+}
+
+static int davinci_i2s_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai,
+				   unsigned int fmt)
+{
+	struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
+	u32 w;
+
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBS_CFS:
+		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG,
+					DAVINCI_MCBSP_PCR_FSXM |
+					DAVINCI_MCBSP_PCR_FSRM |
+					DAVINCI_MCBSP_PCR_CLKXM |
+					DAVINCI_MCBSP_PCR_CLKRM);
+		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG,
+					DAVINCI_MCBSP_SRGR_FSGM);
+		break;
+	case SND_SOC_DAIFMT_CBM_CFM:
+		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, 0);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_IB_NF:
+		w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_PCR_REG);
+		MOD_REG_BIT(w, DAVINCI_MCBSP_PCR_CLKXP |
+			       DAVINCI_MCBSP_PCR_CLKRP, 1);
+		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, w);
+		break;
+	case SND_SOC_DAIFMT_NB_IF:
+		w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_PCR_REG);
+		MOD_REG_BIT(w, DAVINCI_MCBSP_PCR_FSXP |
+			       DAVINCI_MCBSP_PCR_FSRP, 1);
+		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, w);
+		break;
+	case SND_SOC_DAIFMT_IB_IF:
+		w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_PCR_REG);
+		MOD_REG_BIT(w, DAVINCI_MCBSP_PCR_CLKXP |
+			       DAVINCI_MCBSP_PCR_CLKRP |
+			       DAVINCI_MCBSP_PCR_FSXP |
+			       DAVINCI_MCBSP_PCR_FSRP, 1);
+		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, w);
+		break;
+	case SND_SOC_DAIFMT_NB_NF:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
+				 struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct davinci_pcm_dma_params *dma_params = rtd->dai->cpu_dai->dma_data;
+	struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
+	struct snd_interval *i = NULL;
+	int mcbsp_word_length;
+	u32 w;
+
+	/* general line settings */
+	davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG,
+				DAVINCI_MCBSP_SPCR_RINTM(3) |
+				DAVINCI_MCBSP_SPCR_XINTM(3) |
+				DAVINCI_MCBSP_SPCR_FREE);
+	davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG,
+				DAVINCI_MCBSP_RCR_RFRLEN1(1) |
+				DAVINCI_MCBSP_RCR_RDATDLY(1));
+	davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG,
+				DAVINCI_MCBSP_XCR_XFRLEN1(1) |
+				DAVINCI_MCBSP_XCR_XDATDLY(1) |
+				DAVINCI_MCBSP_XCR_XFIG);
+
+	i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
+	w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SRGR_REG);
+	MOD_REG_BIT(w, DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1), 1);
+	davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, w);
+
+	i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_FRAME_BITS);
+	w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SRGR_REG);
+	MOD_REG_BIT(w, DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1), 1);
+	davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, w);
+
+	/* Determine xfer data type */
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S8:
+		dma_params->data_type = 1;
+		mcbsp_word_length = DAVINCI_MCBSP_WORD_8;
+		break;
+	case SNDRV_PCM_FORMAT_S16_LE:
+		dma_params->data_type = 2;
+		mcbsp_word_length = DAVINCI_MCBSP_WORD_16;
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		dma_params->data_type = 4;
+		mcbsp_word_length = DAVINCI_MCBSP_WORD_32;
+		break;
+	default:
+		printk(KERN_WARNING "davinci-i2s: unsupported PCM format");
+		return -EINVAL;
+	}
+
+	w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_RCR_REG);
+	MOD_REG_BIT(w, DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) |
+		       DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length), 1);
+	davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, w);
+
+	w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_XCR_REG);
+	MOD_REG_BIT(w, DAVINCI_MCBSP_XCR_XWDLEN1(mcbsp_word_length) |
+		       DAVINCI_MCBSP_XCR_XWDLEN2(mcbsp_word_length), 1);
+	davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, w);
+
+	return 0;
+}
+
+static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	int ret = 0;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		davinci_mcbsp_start(substream);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		davinci_mcbsp_stop(substream);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int davinci_i2s_probe(struct platform_device *pdev)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_machine *machine = socdev->machine;
+	struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[pdev->id].cpu_dai;
+	struct davinci_mcbsp_dev *dev;
+	struct resource *mem, *ioarea;
+	struct evm_snd_platform_data *pdata;
+	int ret;
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		dev_err(&pdev->dev, "no mem resource?\n");
+		return -ENODEV;
+	}
+
+	ioarea = request_mem_region(mem->start, (mem->end - mem->start) + 1,
+				    pdev->name);
+	if (!ioarea) {
+		dev_err(&pdev->dev, "McBSP region already claimed\n");
+		return -EBUSY;
+	}
+
+	dev = kzalloc(sizeof(struct davinci_mcbsp_dev), GFP_KERNEL);
+	if (!dev) {
+		ret = -ENOMEM;
+		goto err_release_region;
+	}
+
+	cpu_dai->private_data = dev;
+
+	dev->clk = clk_get(&pdev->dev, "McBSPCLK");
+	if (IS_ERR(dev->clk)) {
+		ret = -ENODEV;
+		goto err_free_mem;
+	}
+	clk_enable(dev->clk);
+
+	dev->base = (void __iomem *)IO_ADDRESS(mem->start);
+	pdata = pdev->dev.platform_data;
+
+	dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK] = &davinci_i2s_pcm_out;
+	dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]->channel = pdata->tx_dma_ch;
+	dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]->dma_addr =
+	    (dma_addr_t)(io_v2p(dev->base) + DAVINCI_MCBSP_DXR_REG);
+
+	dev->dma_params[SNDRV_PCM_STREAM_CAPTURE] = &davinci_i2s_pcm_in;
+	dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]->channel = pdata->rx_dma_ch;
+	dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]->dma_addr =
+	    (dma_addr_t)(io_v2p(dev->base) + DAVINCI_MCBSP_DRR_REG);
+
+	return 0;
+
+err_free_mem:
+	kfree(dev);
+err_release_region:
+	release_mem_region(mem->start, (mem->end - mem->start) + 1);
+
+	return ret;
+}
+
+static void davinci_i2s_remove(struct platform_device *pdev)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_machine *machine = socdev->machine;
+	struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[pdev->id].cpu_dai;
+	struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
+	struct resource *mem;
+
+	clk_disable(dev->clk);
+	clk_put(dev->clk);
+	dev->clk = NULL;
+
+	kfree(dev);
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(mem->start, (mem->end - mem->start) + 1);
+}
+
+#define DAVINCI_I2S_RATES	SNDRV_PCM_RATE_8000_96000
+
+struct snd_soc_cpu_dai davinci_i2s_dai = {
+	.name = "davinci-i2s",
+	.id = 0,
+	.type = SND_SOC_DAI_I2S,
+	.probe = davinci_i2s_probe,
+	.remove = davinci_i2s_remove,
+	.playback = {
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = DAVINCI_I2S_RATES,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
+	.capture = {
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = DAVINCI_I2S_RATES,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
+	.ops = {
+		.startup = davinci_i2s_startup,
+		.trigger = davinci_i2s_trigger,
+		.hw_params = davinci_i2s_hw_params,},
+	.dai_ops = {
+		.set_fmt = davinci_i2s_set_dai_fmt,
+	},
+};
+EXPORT_SYMBOL_GPL(davinci_i2s_dai);
+
+MODULE_AUTHOR("Vladimir Barinov");
+MODULE_DESCRIPTION("TI DAVINCI I2S (McBSP) SoC Interface");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/davinci/davinci-i2s.h b/sound/soc/davinci/davinci-i2s.h
new file mode 100644
index 00000000000..9592d17db32
--- /dev/null
+++ b/sound/soc/davinci/davinci-i2s.h
@@ -0,0 +1,17 @@
+/*
+ * ALSA SoC I2S (McBSP) Audio Layer for TI DAVINCI processor
+ *
+ * Author:      Vladimir Barinov, <vbarinov@ru.mvista.com>
+ * Copyright:   (C) 2007 MontaVista Software, Inc., <source@mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _DAVINCI_I2S_H
+#define _DAVINCI_I2S_H
+
+extern struct snd_soc_cpu_dai davinci_i2s_dai;
+
+#endif
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c
new file mode 100644
index 00000000000..6a76927c997
--- /dev/null
+++ b/sound/soc/davinci/davinci-pcm.c
@@ -0,0 +1,389 @@
+/*
+ * ALSA PCM interface for the TI DAVINCI processor
+ *
+ * Author:      Vladimir Barinov, <vbarinov@ru.mvista.com>
+ * Copyright:   (C) 2007 MontaVista Software, Inc., <source@mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include <asm/dma.h>
+
+#include "davinci-pcm.h"
+
+#define DAVINCI_PCM_DEBUG 0
+#if DAVINCI_PCM_DEBUG
+#define DPRINTK(x...) printk(KERN_DEBUG x)
+#else
+#define DPRINTK(x...)
+#endif
+
+static struct snd_pcm_hardware davinci_pcm_hardware = {
+	.info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
+		 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
+		 SNDRV_PCM_INFO_PAUSE),
+	.formats = (SNDRV_PCM_FMTBIT_S16_LE),
+	.rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
+		  SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
+		  SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
+		  SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
+		  SNDRV_PCM_RATE_KNOT),
+	.rate_min = 8000,
+	.rate_max = 96000,
+	.channels_min = 2,
+	.channels_max = 2,
+	.buffer_bytes_max = 128 * 1024,
+	.period_bytes_min = 32,
+	.period_bytes_max = 8 * 1024,
+	.periods_min = 16,
+	.periods_max = 255,
+	.fifo_size = 0,
+};
+
+struct davinci_runtime_data {
+	spinlock_t lock;
+	int period;		/* current DMA period */
+	int master_lch;		/* Master DMA channel */
+	int slave_lch;		/* Slave DMA channel */
+	struct davinci_pcm_dma_params *params;	/* DMA params */
+};
+
+static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
+{
+	struct davinci_runtime_data *prtd = substream->runtime->private_data;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	int lch = prtd->slave_lch;
+	unsigned int period_size;
+	unsigned int dma_offset;
+	dma_addr_t dma_pos;
+	dma_addr_t src, dst;
+	unsigned short src_bidx, dst_bidx;
+	unsigned int data_type;
+	unsigned int count;
+
+	period_size = snd_pcm_lib_period_bytes(substream);
+	dma_offset = prtd->period * period_size;
+	dma_pos = runtime->dma_addr + dma_offset;
+
+	DPRINTK("audio_set_dma_params_play channel = %d dma_ptr = %x "
+		"period_size=%x\n", lch, dma_pos, period_size);
+
+	data_type = prtd->params->data_type;
+	count = period_size / data_type;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		src = dma_pos;
+		dst = prtd->params->dma_addr;
+		src_bidx = data_type;
+		dst_bidx = 0;
+	} else {
+		src = prtd->params->dma_addr;
+		dst = dma_pos;
+		src_bidx = 0;
+		dst_bidx = data_type;
+	}
+
+	davinci_set_dma_src_params(lch, src, INCR, W8BIT);
+	davinci_set_dma_dest_params(lch, dst, INCR, W8BIT);
+	davinci_set_dma_src_index(lch, src_bidx, 0);
+	davinci_set_dma_dest_index(lch, dst_bidx, 0);
+	davinci_set_dma_transfer_params(lch, data_type, count, 1, 0, ASYNC);
+
+	prtd->period++;
+	if (unlikely(prtd->period >= runtime->periods))
+		prtd->period = 0;
+}
+
+static void davinci_pcm_dma_irq(int lch, u16 ch_status, void *data)
+{
+	struct snd_pcm_substream *substream = data;
+	struct davinci_runtime_data *prtd = substream->runtime->private_data;
+
+	DPRINTK("lch=%d, status=0x%x\n", lch, ch_status);
+
+	if (unlikely(ch_status != DMA_COMPLETE))
+		return;
+
+	if (snd_pcm_running(substream)) {
+		snd_pcm_period_elapsed(substream);
+
+		spin_lock(&prtd->lock);
+		davinci_pcm_enqueue_dma(substream);
+		spin_unlock(&prtd->lock);
+	}
+}
+
+static int davinci_pcm_dma_request(struct snd_pcm_substream *substream)
+{
+	struct davinci_runtime_data *prtd = substream->runtime->private_data;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct davinci_pcm_dma_params *dma_data = rtd->dai->cpu_dai->dma_data;
+	int tcc = TCC_ANY;
+	int ret;
+
+	if (!dma_data)
+		return -ENODEV;
+
+	prtd->params = dma_data;
+
+	/* Request master DMA channel */
+	ret = davinci_request_dma(prtd->params->channel, prtd->params->name,
+				  davinci_pcm_dma_irq, substream,
+				  &prtd->master_lch, &tcc, EVENTQ_0);
+	if (ret)
+		return ret;
+
+	/* Request slave DMA channel */
+	ret = davinci_request_dma(PARAM_ANY, "Link",
+				  NULL, NULL, &prtd->slave_lch, &tcc, EVENTQ_0);
+	if (ret) {
+		davinci_free_dma(prtd->master_lch);
+		return ret;
+	}
+
+	/* Link slave DMA channel in loopback */
+	davinci_dma_link_lch(prtd->slave_lch, prtd->slave_lch);
+
+	return 0;
+}
+
+static int davinci_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct davinci_runtime_data *prtd = substream->runtime->private_data;
+	int ret = 0;
+
+	spin_lock(&prtd->lock);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		davinci_start_dma(prtd->master_lch);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		davinci_stop_dma(prtd->master_lch);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	spin_unlock(&prtd->lock);
+
+	return ret;
+}
+
+static int davinci_pcm_prepare(struct snd_pcm_substream *substream)
+{
+	struct davinci_runtime_data *prtd = substream->runtime->private_data;
+	struct paramentry_descriptor temp;
+
+	prtd->period = 0;
+	davinci_pcm_enqueue_dma(substream);
+
+	/* Get slave channel dma params for master channel startup */
+	davinci_get_dma_params(prtd->slave_lch, &temp);
+	davinci_set_dma_params(prtd->master_lch, &temp);
+
+	return 0;
+}
+
+static snd_pcm_uframes_t
+davinci_pcm_pointer(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct davinci_runtime_data *prtd = runtime->private_data;
+	unsigned int offset;
+	dma_addr_t count;
+	dma_addr_t src, dst;
+
+	spin_lock(&prtd->lock);
+
+	davinci_dma_getposition(prtd->master_lch, &src, &dst);
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		count = src - runtime->dma_addr;
+	else
+		count = dst - runtime->dma_addr;;
+
+	spin_unlock(&prtd->lock);
+
+	offset = bytes_to_frames(runtime, count);
+	if (offset >= runtime->buffer_size)
+		offset = 0;
+
+	return offset;
+}
+
+static int davinci_pcm_open(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct davinci_runtime_data *prtd;
+	int ret = 0;
+
+	snd_soc_set_runtime_hwparams(substream, &davinci_pcm_hardware);
+
+	prtd = kzalloc(sizeof(struct davinci_runtime_data), GFP_KERNEL);
+	if (prtd == NULL)
+		return -ENOMEM;
+
+	spin_lock_init(&prtd->lock);
+
+	runtime->private_data = prtd;
+
+	ret = davinci_pcm_dma_request(substream);
+	if (ret) {
+		printk(KERN_ERR "davinci_pcm: Failed to get dma channels\n");
+		kfree(prtd);
+	}
+
+	return ret;
+}
+
+static int davinci_pcm_close(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct davinci_runtime_data *prtd = runtime->private_data;
+
+	davinci_dma_unlink_lch(prtd->slave_lch, prtd->slave_lch);
+
+	davinci_free_dma(prtd->slave_lch);
+	davinci_free_dma(prtd->master_lch);
+
+	kfree(prtd);
+
+	return 0;
+}
+
+static int davinci_pcm_hw_params(struct snd_pcm_substream *substream,
+				 struct snd_pcm_hw_params *hw_params)
+{
+	return snd_pcm_lib_malloc_pages(substream,
+					params_buffer_bytes(hw_params));
+}
+
+static int davinci_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+	return snd_pcm_lib_free_pages(substream);
+}
+
+static int davinci_pcm_mmap(struct snd_pcm_substream *substream,
+			    struct vm_area_struct *vma)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+
+	return dma_mmap_writecombine(substream->pcm->card->dev, vma,
+				     runtime->dma_area,
+				     runtime->dma_addr,
+				     runtime->dma_bytes);
+}
+
+struct snd_pcm_ops davinci_pcm_ops = {
+	.open = 	davinci_pcm_open,
+	.close = 	davinci_pcm_close,
+	.ioctl = 	snd_pcm_lib_ioctl,
+	.hw_params = 	davinci_pcm_hw_params,
+	.hw_free = 	davinci_pcm_hw_free,
+	.prepare = 	davinci_pcm_prepare,
+	.trigger = 	davinci_pcm_trigger,
+	.pointer = 	davinci_pcm_pointer,
+	.mmap = 	davinci_pcm_mmap,
+};
+
+static int davinci_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
+{
+	struct snd_pcm_substream *substream = pcm->streams[stream].substream;
+	struct snd_dma_buffer *buf = &substream->dma_buffer;
+	size_t size = davinci_pcm_hardware.buffer_bytes_max;
+
+	buf->dev.type = SNDRV_DMA_TYPE_DEV;
+	buf->dev.dev = pcm->card->dev;
+	buf->private_data = NULL;
+	buf->area = dma_alloc_writecombine(pcm->card->dev, size,
+					   &buf->addr, GFP_KERNEL);
+
+	DPRINTK("preallocate_dma_buffer: area=%p, addr=%p, size=%d\n",
+		(void *) buf->area, (void *) buf->addr, size);
+
+	if (!buf->area)
+		return -ENOMEM;
+
+	buf->bytes = size;
+	return 0;
+}
+
+static void davinci_pcm_free(struct snd_pcm *pcm)
+{
+	struct snd_pcm_substream *substream;
+	struct snd_dma_buffer *buf;
+	int stream;
+
+	for (stream = 0; stream < 2; stream++) {
+		substream = pcm->streams[stream].substream;
+		if (!substream)
+			continue;
+
+		buf = &substream->dma_buffer;
+		if (!buf->area)
+			continue;
+
+		dma_free_writecombine(pcm->card->dev, buf->bytes,
+				      buf->area, buf->addr);
+		buf->area = NULL;
+	}
+}
+
+static u64 davinci_pcm_dmamask = 0xffffffff;
+
+static int davinci_pcm_new(struct snd_card *card,
+			   struct snd_soc_codec_dai *dai, struct snd_pcm *pcm)
+{
+	int ret;
+
+	if (!card->dev->dma_mask)
+		card->dev->dma_mask = &davinci_pcm_dmamask;
+	if (!card->dev->coherent_dma_mask)
+		card->dev->coherent_dma_mask = 0xffffffff;
+
+	if (dai->playback.channels_min) {
+		ret = davinci_pcm_preallocate_dma_buffer(pcm,
+			SNDRV_PCM_STREAM_PLAYBACK);
+		if (ret)
+			return ret;
+	}
+
+	if (dai->capture.channels_min) {
+		ret = davinci_pcm_preallocate_dma_buffer(pcm,
+			SNDRV_PCM_STREAM_CAPTURE);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+struct snd_soc_platform davinci_soc_platform = {
+	.name = 	"davinci-audio",
+	.pcm_ops = 	&davinci_pcm_ops,
+	.pcm_new = 	davinci_pcm_new,
+	.pcm_free = 	davinci_pcm_free,
+};
+EXPORT_SYMBOL_GPL(davinci_soc_platform);
+
+MODULE_AUTHOR("Vladimir Barinov");
+MODULE_DESCRIPTION("TI DAVINCI PCM DMA module");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/davinci/davinci-pcm.h b/sound/soc/davinci/davinci-pcm.h
new file mode 100644
index 00000000000..8d6a45e75a6
--- /dev/null
+++ b/sound/soc/davinci/davinci-pcm.h
@@ -0,0 +1,29 @@
+/*
+ * ALSA PCM interface for the TI DAVINCI processor
+ *
+ * Author:      Vladimir Barinov, <vbarinov@ru.mvista.com>
+ * Copyright:   (C) 2007 MontaVista Software, Inc., <source@mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _DAVINCI_PCM_H
+#define _DAVINCI_PCM_H
+
+struct davinci_pcm_dma_params {
+	char *name;		/* stream identifier */
+	int channel;		/* sync dma channel ID */
+	dma_addr_t dma_addr;	/* device physical address for DMA */
+	unsigned int data_type;	/* xfer data type */
+};
+
+struct evm_snd_platform_data {
+	int tx_dma_ch;
+	int rx_dma_ch;
+};
+
+extern struct snd_soc_platform davinci_soc_platform;
+
+#endif
-- 
cgit v1.2.3-70-g09d2


From 2eef1258e54722b1c4efac6e5760d2153f96c4b4 Mon Sep 17 00:00:00 2001
From: Hans-Christian Egtvedt <hcegtvedt@atmel.com>
Date: Mon, 18 Feb 2008 11:44:56 +0100
Subject: [ALSA] Add __devinit macro to at73c213 sound driver probe functions

This patch adds __devinit to the functions used when probing. Will also reduce
the memory footprint a bit if CONFIG_HOTPLUG is not enabled.

Signed-off-by: Hans-Christian Egtvedt <hcegtvedt@atmel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/spi/at73c213.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'sound')

diff --git a/sound/spi/at73c213.c b/sound/spi/at73c213.c
index 89d6e9c3514..b8860b26fc6 100644
--- a/sound/spi/at73c213.c
+++ b/sound/spi/at73c213.c
@@ -737,7 +737,7 @@ cleanup:
 /*
  * Device functions
  */
-static int snd_at73c213_ssc_init(struct snd_at73c213 *chip)
+static int __devinit snd_at73c213_ssc_init(struct snd_at73c213 *chip)
 {
 	/*
 	 * Continuous clock output.
@@ -767,7 +767,7 @@ static int snd_at73c213_ssc_init(struct snd_at73c213 *chip)
 	return 0;
 }
 
-static int snd_at73c213_chip_init(struct snd_at73c213 *chip)
+static int __devinit snd_at73c213_chip_init(struct snd_at73c213 *chip)
 {
 	int retval;
 	unsigned char dac_ctrl = 0;
@@ -933,7 +933,7 @@ out:
 	return retval;
 }
 
-static int snd_at73c213_probe(struct spi_device *spi)
+static int __devinit snd_at73c213_probe(struct spi_device *spi)
 {
 	struct snd_card			*card;
 	struct snd_at73c213		*chip;
-- 
cgit v1.2.3-70-g09d2


From 4235a31784f59c9be5ff71534743c055091f9735 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 18 Feb 2008 12:23:13 +0100
Subject: [ALSA] intel8x0 - Add support of 8 channel sound

Added the support of 8 channel sound for codecs that are known to work.
So far, only ALC850 is marked as a 8ch-support codec.

This fix is a modified version of the patch on ALSA BTS#2097 by
Martin Ellis:
	https://bugtrack.alsa-project.org/alsa-bug/view.php?id=2097

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 include/sound/ac97_codec.h  |  1 +
 sound/pci/ac97/ac97_patch.c | 46 ++++++++++++++++++++++++++++++++-------------
 sound/pci/intel8x0.c        | 28 ++++++++++++++++++++++++---
 3 files changed, 59 insertions(+), 16 deletions(-)

(limited to 'sound')

diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h
index 01480581f82..049edc5e646 100644
--- a/include/sound/ac97_codec.h
+++ b/include/sound/ac97_codec.h
@@ -397,6 +397,7 @@
 #define AC97_HAS_NO_TONE	(1<<16) /* no Tone volume */
 #define AC97_HAS_NO_STD_PCM	(1<<17)	/* no standard AC97 PCM volume and mute */
 #define AC97_HAS_NO_AUX		(1<<18) /* no standard AC97 AUX volume and mute */
+#define AC97_HAS_8CH		(1<<19) /* supports 8-channel output */
 
 /* rates indexes */
 #define AC97_RATES_FRONT_DAC	0
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
index 50c637e55ff..39198e505b1 100644
--- a/sound/pci/ac97/ac97_patch.c
+++ b/sound/pci/ac97/ac97_patch.c
@@ -114,10 +114,9 @@ static int ac97_surround_jack_mode_put(struct snd_kcontrol *kcontrol, struct snd
 
 static int ac97_channel_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 {
-	static const char *texts[] = { "2ch", "4ch", "6ch" };
-	if (kcontrol->private_value)
-		return ac97_enum_text_info(kcontrol, uinfo, texts, 2); /* 4ch only */
-	return ac97_enum_text_info(kcontrol, uinfo, texts, 3);
+	static const char *texts[] = { "2ch", "4ch", "6ch", "8ch" };
+	return ac97_enum_text_info(kcontrol, uinfo, texts,
+		kcontrol->private_value);
 }
 
 static int ac97_channel_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
@@ -133,13 +132,8 @@ static int ac97_channel_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
 	struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
 	unsigned char mode = ucontrol->value.enumerated.item[0];
 
-	if (kcontrol->private_value) {
-		if (mode >= 2)
-			return -EINVAL;
-	} else {
-		if (mode >= 3)
-			return -EINVAL;
-	}
+	if (mode >= kcontrol->private_value)
+		return -EINVAL;
 
 	if (mode != ac97->channel_mode) {
 		ac97->channel_mode = mode;
@@ -158,6 +152,7 @@ static int ac97_channel_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
 		.get = ac97_surround_jack_mode_get, \
 		.put = ac97_surround_jack_mode_put, \
 	}
+/* 6ch */
 #define AC97_CHANNEL_MODE_CTL \
 	{ \
 		.iface	= SNDRV_CTL_ELEM_IFACE_MIXER, \
@@ -165,7 +160,9 @@ static int ac97_channel_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
 		.info = ac97_channel_mode_info, \
 		.get = ac97_channel_mode_get, \
 		.put = ac97_channel_mode_put, \
+		.private_value = 3, \
 	}
+/* 4ch */
 #define AC97_CHANNEL_MODE_4CH_CTL \
 	{ \
 		.iface	= SNDRV_CTL_ELEM_IFACE_MIXER, \
@@ -173,7 +170,17 @@ static int ac97_channel_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
 		.info = ac97_channel_mode_info, \
 		.get = ac97_channel_mode_get, \
 		.put = ac97_channel_mode_put, \
-		.private_value = 1, \
+		.private_value = 2, \
+	}
+/* 8ch */
+#define AC97_CHANNEL_MODE_8CH_CTL \
+	{ \
+		.iface  = SNDRV_CTL_ELEM_IFACE_MIXER, \
+		.name   = "Channel Mode", \
+		.info = ac97_channel_mode_info, \
+		.get = ac97_channel_mode_get, \
+		.put = ac97_channel_mode_put, \
+		.private_value = 4, \
 	}
 
 static inline int is_surround_on(struct snd_ac97 *ac97)
@@ -210,6 +217,10 @@ static inline int is_shared_micin(struct snd_ac97 *ac97)
 	return !ac97->indep_surround && !is_clfe_on(ac97);
 }
 
+static inline int alc850_is_aux_back_surround(struct snd_ac97 *ac97)
+{
+	return is_surround_on(ac97);
+}
 
 /* The following snd_ac97_ymf753_... items added by David Shust (dshust@shustring.com) */
 /* Modified for YMF743 by Keita Maehara <maehara@debian.org> */
@@ -2816,10 +2827,12 @@ static int patch_alc655(struct snd_ac97 * ac97)
 
 #define AC97_ALC850_JACK_SELECT	0x76
 #define AC97_ALC850_MISC1	0x7a
+#define AC97_ALC850_MULTICH    0x6a
 
 static void alc850_update_jacks(struct snd_ac97 *ac97)
 {
 	int shared;
+	int aux_is_back_surround;
 	
 	/* shared Line-In / Surround Out */
 	shared = is_shared_surrout(ac97);
@@ -2837,13 +2850,18 @@ static void alc850_update_jacks(struct snd_ac97 *ac97)
 	/* MIC-IN = 1, CENTER-LFE = 5 */
 	snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 4,
 			     shared ? (5<<4) : (1<<4));
+
+	aux_is_back_surround = alc850_is_aux_back_surround(ac97);
+	/* Aux is Back Surround */
+	snd_ac97_update_bits(ac97, AC97_ALC850_MULTICH, 1 << 10,
+				 aux_is_back_surround ? (1<<10) : (0<<10));
 }
 
 static const struct snd_kcontrol_new snd_ac97_controls_alc850[] = {
 	AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0),
 	AC97_SINGLE("Mic Front Input Switch", AC97_ALC850_JACK_SELECT, 15, 1, 1),
 	AC97_SURROUND_JACK_MODE_CTL,
-	AC97_CHANNEL_MODE_CTL,
+	AC97_CHANNEL_MODE_8CH_CTL,
 };
 
 static int patch_alc850_specific(struct snd_ac97 *ac97)
@@ -2869,6 +2887,7 @@ static int patch_alc850(struct snd_ac97 *ac97)
 	ac97->build_ops = &patch_alc850_ops;
 
 	ac97->spec.dev_flags = 0; /* for IEC958 playback route - ALC655 compatible */
+	ac97->flags |= AC97_HAS_8CH;
 
 	/* assume only page 0 for writing cache */
 	snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR);
@@ -2878,6 +2897,7 @@ static int patch_alc850(struct snd_ac97 *ac97)
 	   spdif-in monitor off, spdif-in PCM off
 	   center on mic off, surround on line-in off
 	   duplicate front off
+	   NB default bit 10=0 = Aux is Capture, not Back Surround
 	*/
 	snd_ac97_write_cache(ac97, AC97_ALC650_MULTICH, 1<<15);
 	/* SURR_OUT: on, Surr 1kOhm: on, Surr Amp: off, Front 1kOhm: off
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index c52abd0bf22..07782ba9c74 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -155,7 +155,8 @@ DEFINE_REGSET(SP, 0x60);	/* SPDIF out */
 #define   ICH_PCM_SPDIF_69	0x80000000	/* s/pdif pcm on slots 6&9 */
 #define   ICH_PCM_SPDIF_1011	0xc0000000	/* s/pdif pcm on slots 10&11 */
 #define   ICH_PCM_20BIT		0x00400000	/* 20-bit samples (ICH4) */
-#define   ICH_PCM_246_MASK	0x00300000	/* 6 channels (not all chips) */
+#define   ICH_PCM_246_MASK	0x00300000	/* chan mask (not all chips) */
+#define   ICH_PCM_8		0x00300000      /* 8 channels (not all chips) */
 #define   ICH_PCM_6		0x00200000	/* 6 channels (not all chips) */
 #define   ICH_PCM_4		0x00100000	/* 4 channels (not all chips) */
 #define   ICH_PCM_2		0x00000000	/* 2 channels (stereo) */
@@ -382,6 +383,7 @@ struct intel8x0 {
 
 	unsigned multi4: 1,
 		 multi6: 1,
+		 multi8 :1,
 		 dra: 1,
 		 smp20bit: 1;
 	unsigned in_ac97_init: 1,
@@ -997,6 +999,8 @@ static void snd_intel8x0_setup_pcm_out(struct intel8x0 *chip,
 			cnt |= ICH_PCM_4;
 		else if (runtime->channels == 6)
 			cnt |= ICH_PCM_6;
+		else if (runtime->channels == 8)
+			cnt |= ICH_PCM_8;
 		if (chip->device_type == DEVICE_NFORCE) {
 			/* reset to 2ch once to keep the 6 channel data in alignment,
 			 * to start from Front Left always
@@ -1106,6 +1110,16 @@ static struct snd_pcm_hw_constraint_list hw_constraints_channels6 = {
 	.mask = 0,
 };
 
+static unsigned int channels8[] = {
+	2, 4, 6, 8,
+};
+
+static struct snd_pcm_hw_constraint_list hw_constraints_channels8 = {
+	.count = ARRAY_SIZE(channels8),
+	.list = channels8,
+	.mask = 0,
+};
+
 static int snd_intel8x0_pcm_open(struct snd_pcm_substream *substream, struct ichdev *ichdev)
 {
 	struct intel8x0 *chip = snd_pcm_substream_chip(substream);
@@ -1136,7 +1150,12 @@ static int snd_intel8x0_playback_open(struct snd_pcm_substream *substream)
 	if (err < 0)
 		return err;
 
-	if (chip->multi6) {
+	if (chip->multi8) {
+		runtime->hw.channels_max = 8;
+		snd_pcm_hw_constraint_list(runtime, 0,
+						SNDRV_PCM_HW_PARAM_CHANNELS,
+						&hw_constraints_channels8);
+	} else if (chip->multi6) {
 		runtime->hw.channels_max = 6;
 		snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
 					   &hw_constraints_channels6);
@@ -2203,8 +2222,11 @@ static int __devinit snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock,
 	}
 	if (pbus->pcms[0].r[0].slots & (1 << AC97_SLOT_PCM_SLEFT)) {
 		chip->multi4 = 1;
-		if (pbus->pcms[0].r[0].slots & (1 << AC97_SLOT_LFE))
+		if (pbus->pcms[0].r[0].slots & (1 << AC97_SLOT_LFE)) {
 			chip->multi6 = 1;
+			if (chip->ac97[0]->flags & AC97_HAS_8CH)
+				chip->multi8 = 1;
+		}
 	}
 	if (pbus->pcms[0].r[1].rslots[0]) {
 		chip->dra = 1;
-- 
cgit v1.2.3-70-g09d2


From e922b0028fad87de0d262f9fa51f98595d2df258 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 18 Feb 2008 13:03:13 +0100
Subject: [ALSA] Move vmaster code to sound core

Move the codes for virtual master controls to sound core part so that
not only hda-intel drivers can use it.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 include/sound/control.h   |   7 +
 sound/core/Kconfig        |   4 +
 sound/core/Makefile       |   1 +
 sound/core/vmaster.c      | 368 ++++++++++++++++++++++++++++++++++++++++++++++
 sound/pci/Kconfig         |   1 +
 sound/pci/hda/hda_local.h |   7 -
 sound/pci/hda/vmaster.c   | 364 ---------------------------------------------
 7 files changed, 381 insertions(+), 371 deletions(-)
 create mode 100644 sound/core/vmaster.c
 delete mode 100644 sound/pci/hda/vmaster.c

(limited to 'sound')

diff --git a/include/sound/control.h b/include/sound/control.h
index e79baa63912..3dc1291f52d 100644
--- a/include/sound/control.h
+++ b/include/sound/control.h
@@ -169,4 +169,11 @@ int snd_ctl_boolean_mono_info(struct snd_kcontrol *kcontrol,
 int snd_ctl_boolean_stereo_info(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_info *uinfo);
 
+/*
+ * virtual master control
+ */
+struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
+						 const unsigned int *tlv);
+int snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave);
+		      
 #endif	/* __SOUND_CONTROL_H */
diff --git a/sound/core/Kconfig b/sound/core/Kconfig
index 829ca38b595..a8d71c6c8e7 100644
--- a/sound/core/Kconfig
+++ b/sound/core/Kconfig
@@ -181,3 +181,7 @@ config SND_PCM_XRUN_DEBUG
 	  It is usually not required, but if you have trouble with
 	  sound clicking when system is loaded, it may help to determine
 	  the process or driver which causes the scheduling gaps.
+
+config SND_VMASTER
+	bool
+	depends on SND
diff --git a/sound/core/Makefile b/sound/core/Makefile
index 267039a97bd..da8e685eef9 100644
--- a/sound/core/Makefile
+++ b/sound/core/Makefile
@@ -6,6 +6,7 @@
 snd-y     := sound.o init.o memory.o info.o control.o misc.o device.o
 snd-$(CONFIG_ISA_DMA_API) += isadma.o
 snd-$(CONFIG_SND_OSSEMUL) += sound_oss.o info_oss.o
+snd-$(CONFIG_SND_VMASTER) += vmaster.o
 
 snd-pcm-objs := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \
 		pcm_memory.o
diff --git a/sound/core/vmaster.c b/sound/core/vmaster.c
new file mode 100644
index 00000000000..7cfd8b8fb4e
--- /dev/null
+++ b/sound/core/vmaster.c
@@ -0,0 +1,368 @@
+/*
+ * Virtual master and slave controls
+ *
+ *  Copyright (c) 2008 by Takashi Iwai <tiwai@suse.de>
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License as
+ *  published by the Free Software Foundation, version 2.
+ *
+ */
+
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/control.h>
+
+/*
+ * a subset of information returned via ctl info callback
+ */
+struct link_ctl_info {
+	int type;		/* value type */
+	int count;		/* item count */
+	int min_val, max_val;	/* min, max values */
+};
+
+/*
+ * link master - this contains a list of slave controls that are
+ * identical types, i.e. info returns the same value type and value
+ * ranges, but may have different number of counts.
+ *
+ * The master control is so far only mono volume/switch for simplicity.
+ * The same value will be applied to all slaves.
+ */
+struct link_master {
+	struct list_head slaves;
+	struct link_ctl_info info;
+	int val;		/* the master value */
+};
+
+/*
+ * link slave - this contains a slave control element
+ *
+ * It fakes the control callbacsk with additional attenuation by the
+ * master control.  A slave may have either one or two channels.
+ */
+
+struct link_slave {
+	struct list_head list;
+	struct link_master *master;
+	struct link_ctl_info info;
+	int vals[2];		/* current values */
+	struct snd_kcontrol slave; /* the copy of original control entry */
+};
+
+/* get the slave ctl info and save the initial values */
+static int slave_init(struct link_slave *slave)
+{
+	struct snd_ctl_elem_info *uinfo;
+	struct snd_ctl_elem_value *uctl;
+	int err, ch;
+
+	if (slave->info.count)
+		return 0; /* already initialized */
+
+	uinfo = kmalloc(sizeof(*uinfo), GFP_KERNEL);
+	if (!uinfo)
+		return -ENOMEM;
+	uinfo->id = slave->slave.id;
+	err = slave->slave.info(&slave->slave, uinfo);
+	if (err < 0) {
+		kfree(uinfo);
+		return err;
+	}
+	slave->info.type = uinfo->type;
+	slave->info.count = uinfo->count;
+	if (slave->info.count > 2  ||
+	    (slave->info.type != SNDRV_CTL_ELEM_TYPE_INTEGER &&
+	     slave->info.type != SNDRV_CTL_ELEM_TYPE_BOOLEAN)) {
+		snd_printk(KERN_ERR "invalid slave element\n");
+		kfree(uinfo);
+		return -EINVAL;
+	}
+	slave->info.min_val = uinfo->value.integer.min;
+	slave->info.max_val = uinfo->value.integer.max;
+	kfree(uinfo);
+
+	uctl = kmalloc(sizeof(*uctl), GFP_KERNEL);
+	if (!uctl)
+		return -ENOMEM;
+	uctl->id = slave->slave.id;
+	err = slave->slave.get(&slave->slave, uctl);
+	for (ch = 0; ch < slave->info.count; ch++)
+		slave->vals[ch] = uctl->value.integer.value[ch];
+	kfree(uctl);
+	return 0;
+}
+
+/* initialize master volume */
+static int master_init(struct link_master *master)
+{
+	struct link_slave *slave;
+
+	if (master->info.count)
+		return 0; /* already initialized */
+
+	list_for_each_entry(slave, &master->slaves, list) {
+		int err = slave_init(slave);
+		if (err < 0)
+			return err;
+		master->info = slave->info;
+		master->info.count = 1; /* always mono */
+		/* set full volume as default (= no attenuation) */
+		master->val = master->info.max_val;
+		return 0;
+	}
+	return -ENOENT;
+}
+
+static int slave_get_val(struct link_slave *slave,
+			 struct snd_ctl_elem_value *ucontrol)
+{
+	int err, ch;
+
+	err = slave_init(slave);
+	if (err < 0)
+		return err;
+	for (ch = 0; ch < slave->info.count; ch++)
+		ucontrol->value.integer.value[ch] = slave->vals[ch];
+	return 0;
+}
+
+static int slave_put_val(struct link_slave *slave,
+			 struct snd_ctl_elem_value *ucontrol)
+{
+	int err, ch, vol;
+
+	err = master_init(slave->master);
+	if (err < 0)
+		return err;
+
+	switch (slave->info.type) {
+	case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
+		for (ch = 0; ch < slave->info.count; ch++)
+			ucontrol->value.integer.value[ch] &=
+				!!slave->master->val;
+		break;
+	case SNDRV_CTL_ELEM_TYPE_INTEGER:
+		for (ch = 0; ch < slave->info.count; ch++) {
+			/* max master volume is supposed to be 0 dB */
+			vol = ucontrol->value.integer.value[ch];
+			vol += slave->master->val - slave->master->info.max_val;
+			if (vol < slave->info.min_val)
+				vol = slave->info.min_val;
+			else if (vol > slave->info.max_val)
+				vol = slave->info.max_val;
+			ucontrol->value.integer.value[ch] = vol;
+		}
+		break;
+	}
+	return slave->slave.put(&slave->slave, ucontrol);
+}
+
+/*
+ * ctl callbacks for slaves
+ */
+static int slave_info(struct snd_kcontrol *kcontrol,
+		      struct snd_ctl_elem_info *uinfo)
+{
+	struct link_slave *slave = snd_kcontrol_chip(kcontrol);
+	return slave->slave.info(&slave->slave, uinfo);
+}
+
+static int slave_get(struct snd_kcontrol *kcontrol,
+		     struct snd_ctl_elem_value *ucontrol)
+{
+	struct link_slave *slave = snd_kcontrol_chip(kcontrol);
+	return slave_get_val(slave, ucontrol);
+}
+
+static int slave_put(struct snd_kcontrol *kcontrol,
+		     struct snd_ctl_elem_value *ucontrol)
+{
+	struct link_slave *slave = snd_kcontrol_chip(kcontrol);
+	int err, ch, changed = 0;
+
+	err = slave_init(slave);
+	if (err < 0)
+		return err;
+	for (ch = 0; ch < slave->info.count; ch++) {
+		if (slave->vals[ch] != ucontrol->value.integer.value[ch]) {
+			changed = 1;
+			slave->vals[ch] = ucontrol->value.integer.value[ch];
+		}
+	}
+	if (!changed)
+		return 0;
+	return slave_put_val(slave, ucontrol);
+}
+
+static int slave_tlv_cmd(struct snd_kcontrol *kcontrol,
+			 int op_flag, unsigned int size,
+			 unsigned int __user *tlv)
+{
+	struct link_slave *slave = snd_kcontrol_chip(kcontrol);
+	/* FIXME: this assumes that the max volume is 0 dB */
+	return slave->slave.tlv.c(&slave->slave, op_flag, size, tlv);
+}
+
+static void slave_free(struct snd_kcontrol *kcontrol)
+{
+	struct link_slave *slave = snd_kcontrol_chip(kcontrol);
+	if (slave->slave.private_free)
+		slave->slave.private_free(&slave->slave);
+	if (slave->master)
+		list_del(&slave->list);
+	kfree(slave);
+}
+
+/*
+ * Add a slave control to the group with the given master control
+ *
+ * All slaves must be the same type (returning the same information
+ * via info callback).  The fucntion doesn't check it, so it's your
+ * responsibility.
+ *
+ * Also, some additional limitations:
+ * - at most two channels
+ * - logarithmic volume control (dB level), no linear volume
+ * - master can only attenuate the volume, no gain
+ */
+int snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave)
+{
+	struct link_master *master_link = snd_kcontrol_chip(master);
+	struct link_slave *srec;
+
+	srec = kzalloc(sizeof(*srec) +
+		       slave->count * sizeof(*slave->vd), GFP_KERNEL);
+	if (!srec)
+		return -ENOMEM;
+	srec->slave = *slave;
+	memcpy(srec->slave.vd, slave->vd, slave->count * sizeof(*slave->vd));
+	srec->master = master_link;
+
+	/* override callbacks */
+	slave->info = slave_info;
+	slave->get = slave_get;
+	slave->put = slave_put;
+	if (slave->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK)
+		slave->tlv.c = slave_tlv_cmd;
+	slave->private_data = srec;
+	slave->private_free = slave_free;
+
+	list_add_tail(&srec->list, &master_link->slaves);
+	return 0;
+}
+
+EXPORT_SYMBOL(snd_ctl_add_slave);
+
+/*
+ * ctl callbacks for master controls
+ */
+static int master_info(struct snd_kcontrol *kcontrol,
+		      struct snd_ctl_elem_info *uinfo)
+{
+	struct link_master *master = snd_kcontrol_chip(kcontrol);
+	int ret;
+
+	ret = master_init(master);
+	if (ret < 0)
+		return ret;
+	uinfo->type = master->info.type;
+	uinfo->count = master->info.count;
+	uinfo->value.integer.min = master->info.min_val;
+	uinfo->value.integer.max = master->info.max_val;
+	return 0;
+}
+
+static int master_get(struct snd_kcontrol *kcontrol,
+		      struct snd_ctl_elem_value *ucontrol)
+{
+	struct link_master *master = snd_kcontrol_chip(kcontrol);
+	int err = master_init(master);
+	if (err < 0)
+		return err;
+	ucontrol->value.integer.value[0] = master->val;
+	return 0;
+}
+
+static int master_put(struct snd_kcontrol *kcontrol,
+		      struct snd_ctl_elem_value *ucontrol)
+{
+	struct link_master *master = snd_kcontrol_chip(kcontrol);
+	struct link_slave *slave;
+	struct snd_ctl_elem_value *uval;
+	int err, old_val;
+
+	err = master_init(master);
+	if (err < 0)
+		return err;
+	old_val = master->val;
+	if (ucontrol->value.integer.value[0] == old_val)
+		return 0;
+
+	uval = kmalloc(sizeof(*uval), GFP_KERNEL);
+	if (!uval)
+		return -ENOMEM;
+	list_for_each_entry(slave, &master->slaves, list) {
+		master->val = old_val;
+		uval->id = slave->slave.id;
+		slave_get_val(slave, uval);
+		master->val = ucontrol->value.integer.value[0];
+		slave_put_val(slave, uval);
+	}
+	kfree(uval);
+	return 1;
+}
+
+static void master_free(struct snd_kcontrol *kcontrol)
+{
+	struct link_master *master = snd_kcontrol_chip(kcontrol);
+	struct link_slave *slave;
+
+	list_for_each_entry(slave, &master->slaves, list)
+		slave->master = NULL;
+	kfree(master);
+}
+
+
+/*
+ * Create a virtual master control with the given name
+ */
+struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
+						 const unsigned int *tlv)
+{
+	struct link_master *master;
+	struct snd_kcontrol *kctl;
+	struct snd_kcontrol_new knew;
+
+	memset(&knew, 0, sizeof(knew));
+	knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+	knew.name = name;
+	knew.info = master_info;
+
+	master = kzalloc(sizeof(*master), GFP_KERNEL);
+	if (!master)
+		return NULL;
+	INIT_LIST_HEAD(&master->slaves);
+
+	kctl = snd_ctl_new1(&knew, master);
+	if (!kctl) {
+		kfree(master);
+		return NULL;
+	}
+	/* override some callbacks */
+	kctl->info = master_info;
+	kctl->get = master_get;
+	kctl->put = master_put;
+	kctl->private_free = master_free;
+
+	/* additional (constant) TLV read */
+	if (tlv) {
+		/* FIXME: this assumes that the max volume is 0 dB */
+		kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
+		kctl->tlv.p = tlv;
+	}
+	return kctl;
+}
+
+EXPORT_SYMBOL(snd_ctl_make_virtual_master);
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 812085d521f..48296d97bf3 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -517,6 +517,7 @@ config SND_HDA_INTEL
 	tristate "Intel HD Audio"
 	depends on SND
 	select SND_PCM
+	select SND_VMASTER
 	help
 	  Say Y here to include support for Intel "High Definition
 	  Audio" (Azalia) motherboard devices.
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index ce2ad42a8a8..5c9e578f7f2 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -418,11 +418,4 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec,
 				 hda_nid_t nid);
 #endif /* CONFIG_SND_HDA_POWER_SAVE */
 
-/*
- * virtual master control
- */
-struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
-						 const unsigned int *tlv);
-int snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave);
-		      
 #endif /* __SOUND_HDA_LOCAL_H */
diff --git a/sound/pci/hda/vmaster.c b/sound/pci/hda/vmaster.c
deleted file mode 100644
index 2da49d20a1f..00000000000
--- a/sound/pci/hda/vmaster.c
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * Virtual master and slave controls
- *
- *  Copyright (c) 2008 by Takashi Iwai <tiwai@suse.de>
- *
- *  This program is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU General Public License as
- *  published by the Free Software Foundation, version 2.
- *
- */
-
-#include <linux/slab.h>
-#include <sound/core.h>
-#include <sound/control.h>
-
-/*
- * a subset of information returned via ctl info callback
- */
-struct link_ctl_info {
-	int type;		/* value type */
-	int count;		/* item count */
-	int min_val, max_val;	/* min, max values */
-};
-
-/*
- * link master - this contains a list of slave controls that are
- * identical types, i.e. info returns the same value type and value
- * ranges, but may have different number of counts.
- *
- * The master control is so far only mono volume/switch for simplicity.
- * The same value will be applied to all slaves.
- */
-struct link_master {
-	struct list_head slaves;
-	struct link_ctl_info info;
-	int val;		/* the master value */
-};
-
-/*
- * link slave - this contains a slave control element
- *
- * It fakes the control callbacsk with additional attenuation by the
- * master control.  A slave may have either one or two channels.
- */
-
-struct link_slave {
-	struct list_head list;
-	struct link_master *master;
-	struct link_ctl_info info;
-	int vals[2];		/* current values */
-	struct snd_kcontrol slave; /* the copy of original control entry */
-};
-
-/* get the slave ctl info and save the initial values */
-static int slave_init(struct link_slave *slave)
-{
-	struct snd_ctl_elem_info *uinfo;
-	struct snd_ctl_elem_value *uctl;
-	int err, ch;
-
-	if (slave->info.count)
-		return 0; /* already initialized */
-
-	uinfo = kmalloc(sizeof(*uinfo), GFP_KERNEL);
-	if (!uinfo)
-		return -ENOMEM;
-	uinfo->id = slave->slave.id;
-	err = slave->slave.info(&slave->slave, uinfo);
-	if (err < 0) {
-		kfree(uinfo);
-		return err;
-	}
-	slave->info.type = uinfo->type;
-	slave->info.count = uinfo->count;
-	if (slave->info.count > 2  ||
-	    (slave->info.type != SNDRV_CTL_ELEM_TYPE_INTEGER &&
-	     slave->info.type != SNDRV_CTL_ELEM_TYPE_BOOLEAN)) {
-		snd_printk(KERN_ERR "invalid slave element\n");
-		kfree(uinfo);
-		return -EINVAL;
-	}
-	slave->info.min_val = uinfo->value.integer.min;
-	slave->info.max_val = uinfo->value.integer.max;
-	kfree(uinfo);
-
-	uctl = kmalloc(sizeof(*uctl), GFP_KERNEL);
-	if (!uctl)
-		return -ENOMEM;
-	uctl->id = slave->slave.id;
-	err = slave->slave.get(&slave->slave, uctl);
-	for (ch = 0; ch < slave->info.count; ch++)
-		slave->vals[ch] = uctl->value.integer.value[ch];
-	kfree(uctl);
-	return 0;
-}
-
-/* initialize master volume */
-static int master_init(struct link_master *master)
-{
-	struct link_slave *slave;
-
-	if (master->info.count)
-		return 0; /* already initialized */
-
-	list_for_each_entry(slave, &master->slaves, list) {
-		int err = slave_init(slave);
-		if (err < 0)
-			return err;
-		master->info = slave->info;
-		master->info.count = 1; /* always mono */
-		/* set full volume as default (= no attenuation) */
-		master->val = master->info.max_val;
-		return 0;
-	}
-	return -ENOENT;
-}
-
-static int slave_get_val(struct link_slave *slave,
-			 struct snd_ctl_elem_value *ucontrol)
-{
-	int err, ch;
-
-	err = slave_init(slave);
-	if (err < 0)
-		return err;
-	for (ch = 0; ch < slave->info.count; ch++)
-		ucontrol->value.integer.value[ch] = slave->vals[ch];
-	return 0;
-}
-
-static int slave_put_val(struct link_slave *slave,
-			 struct snd_ctl_elem_value *ucontrol)
-{
-	int err, ch, vol;
-
-	err = master_init(slave->master);
-	if (err < 0)
-		return err;
-
-	switch (slave->info.type) {
-	case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
-		for (ch = 0; ch < slave->info.count; ch++)
-			ucontrol->value.integer.value[ch] &=
-				!!slave->master->val;
-		break;
-	case SNDRV_CTL_ELEM_TYPE_INTEGER:
-		for (ch = 0; ch < slave->info.count; ch++) {
-			/* max master volume is supposed to be 0 dB */
-			vol = ucontrol->value.integer.value[ch];
-			vol += slave->master->val - slave->master->info.max_val;
-			if (vol < slave->info.min_val)
-				vol = slave->info.min_val;
-			else if (vol > slave->info.max_val)
-				vol = slave->info.max_val;
-			ucontrol->value.integer.value[ch] = vol;
-		}
-		break;
-	}
-	return slave->slave.put(&slave->slave, ucontrol);
-}
-
-/*
- * ctl callbacks for slaves
- */
-static int slave_info(struct snd_kcontrol *kcontrol,
-		      struct snd_ctl_elem_info *uinfo)
-{
-	struct link_slave *slave = snd_kcontrol_chip(kcontrol);
-	return slave->slave.info(&slave->slave, uinfo);
-}
-
-static int slave_get(struct snd_kcontrol *kcontrol,
-		     struct snd_ctl_elem_value *ucontrol)
-{
-	struct link_slave *slave = snd_kcontrol_chip(kcontrol);
-	return slave_get_val(slave, ucontrol);
-}
-
-static int slave_put(struct snd_kcontrol *kcontrol,
-		     struct snd_ctl_elem_value *ucontrol)
-{
-	struct link_slave *slave = snd_kcontrol_chip(kcontrol);
-	int err, ch, changed = 0;
-
-	err = slave_init(slave);
-	if (err < 0)
-		return err;
-	for (ch = 0; ch < slave->info.count; ch++) {
-		if (slave->vals[ch] != ucontrol->value.integer.value[ch]) {
-			changed = 1;
-			slave->vals[ch] = ucontrol->value.integer.value[ch];
-		}
-	}
-	if (!changed)
-		return 0;
-	return slave_put_val(slave, ucontrol);
-}
-
-static int slave_tlv_cmd(struct snd_kcontrol *kcontrol,
-			 int op_flag, unsigned int size,
-			 unsigned int __user *tlv)
-{
-	struct link_slave *slave = snd_kcontrol_chip(kcontrol);
-	/* FIXME: this assumes that the max volume is 0 dB */
-	return slave->slave.tlv.c(&slave->slave, op_flag, size, tlv);
-}
-
-static void slave_free(struct snd_kcontrol *kcontrol)
-{
-	struct link_slave *slave = snd_kcontrol_chip(kcontrol);
-	if (slave->slave.private_free)
-		slave->slave.private_free(&slave->slave);
-	if (slave->master)
-		list_del(&slave->list);
-	kfree(slave);
-}
-
-/*
- * Add a slave control to the group with the given master control
- *
- * All slaves must be the same type (returning the same information
- * via info callback).  The fucntion doesn't check it, so it's your
- * responsibility.
- *
- * Also, some additional limitations:
- * - at most two channels
- * - logarithmic volume control (dB level), no linear volume
- * - master can only attenuate the volume, no gain
- */
-int snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave)
-{
-	struct link_master *master_link = snd_kcontrol_chip(master);
-	struct link_slave *srec;
-
-	srec = kzalloc(sizeof(*srec) +
-		       slave->count * sizeof(*slave->vd), GFP_KERNEL);
-	if (!srec)
-		return -ENOMEM;
-	srec->slave = *slave;
-	memcpy(srec->slave.vd, slave->vd, slave->count * sizeof(*slave->vd));
-	srec->master = master_link;
-
-	/* override callbacks */
-	slave->info = slave_info;
-	slave->get = slave_get;
-	slave->put = slave_put;
-	if (slave->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK)
-		slave->tlv.c = slave_tlv_cmd;
-	slave->private_data = srec;
-	slave->private_free = slave_free;
-
-	list_add_tail(&srec->list, &master_link->slaves);
-	return 0;
-}
-
-/*
- * ctl callbacks for master controls
- */
-static int master_info(struct snd_kcontrol *kcontrol,
-		      struct snd_ctl_elem_info *uinfo)
-{
-	struct link_master *master = snd_kcontrol_chip(kcontrol);
-	int ret;
-
-	ret = master_init(master);
-	if (ret < 0)
-		return ret;
-	uinfo->type = master->info.type;
-	uinfo->count = master->info.count;
-	uinfo->value.integer.min = master->info.min_val;
-	uinfo->value.integer.max = master->info.max_val;
-	return 0;
-}
-
-static int master_get(struct snd_kcontrol *kcontrol,
-		      struct snd_ctl_elem_value *ucontrol)
-{
-	struct link_master *master = snd_kcontrol_chip(kcontrol);
-	int err = master_init(master);
-	if (err < 0)
-		return err;
-	ucontrol->value.integer.value[0] = master->val;
-	return 0;
-}
-
-static int master_put(struct snd_kcontrol *kcontrol,
-		      struct snd_ctl_elem_value *ucontrol)
-{
-	struct link_master *master = snd_kcontrol_chip(kcontrol);
-	struct link_slave *slave;
-	struct snd_ctl_elem_value *uval;
-	int err, old_val;
-
-	err = master_init(master);
-	if (err < 0)
-		return err;
-	old_val = master->val;
-	if (ucontrol->value.integer.value[0] == old_val)
-		return 0;
-
-	uval = kmalloc(sizeof(*uval), GFP_KERNEL);
-	if (!uval)
-		return -ENOMEM;
-	list_for_each_entry(slave, &master->slaves, list) {
-		master->val = old_val;
-		uval->id = slave->slave.id;
-		slave_get_val(slave, uval);
-		master->val = ucontrol->value.integer.value[0];
-		slave_put_val(slave, uval);
-	}
-	kfree(uval);
-	return 1;
-}
-
-static void master_free(struct snd_kcontrol *kcontrol)
-{
-	struct link_master *master = snd_kcontrol_chip(kcontrol);
-	struct link_slave *slave;
-
-	list_for_each_entry(slave, &master->slaves, list)
-		slave->master = NULL;
-	kfree(master);
-}
-
-
-/*
- * Create a virtual master control with the given name
- */
-struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
-						 const unsigned int *tlv)
-{
-	struct link_master *master;
-	struct snd_kcontrol *kctl;
-	struct snd_kcontrol_new knew;
-
-	memset(&knew, 0, sizeof(knew));
-	knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
-	knew.name = name;
-	knew.info = master_info;
-
-	master = kzalloc(sizeof(*master), GFP_KERNEL);
-	if (!master)
-		return NULL;
-	INIT_LIST_HEAD(&master->slaves);
-
-	kctl = snd_ctl_new1(&knew, master);
-	if (!kctl) {
-		kfree(master);
-		return NULL;
-	}
-	/* override some callbacks */
-	kctl->info = master_info;
-	kctl->get = master_get;
-	kctl->put = master_put;
-	kctl->private_free = master_free;
-
-	/* additional (constant) TLV read */
-	if (tlv) {
-		/* FIXME: this assumes that the max volume is 0 dB */
-		kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
-		kctl->tlv.p = tlv;
-	}
-	return kctl;
-}
-- 
cgit v1.2.3-70-g09d2


From 1c82ed1bc531746a8fa9b46c593ddce546f28026 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 18 Feb 2008 13:05:50 +0100
Subject: [ALSA] Keep private TLV entry in vmaster itself

Use a private array for TLV entries of virtual master controls instead
of (supposed) static array.  This cleans up the existing codes.

Also, now vmaster assumes the simple dB-range TLV that is the only type
it can handle.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/core/vmaster.c           | 9 ++++++---
 sound/pci/hda/Makefile         | 2 +-
 sound/pci/hda/patch_analog.c   | 6 +++---
 sound/pci/hda/patch_realtek.c  | 6 +++---
 sound/pci/hda/patch_sigmatel.c | 8 +++-----
 5 files changed, 16 insertions(+), 15 deletions(-)

(limited to 'sound')

diff --git a/sound/core/vmaster.c b/sound/core/vmaster.c
index 7cfd8b8fb4e..4cc57f902e2 100644
--- a/sound/core/vmaster.c
+++ b/sound/core/vmaster.c
@@ -12,6 +12,7 @@
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/control.h>
+#include <sound/tlv.h>
 
 /*
  * a subset of information returned via ctl info callback
@@ -34,6 +35,7 @@ struct link_master {
 	struct list_head slaves;
 	struct link_ctl_info info;
 	int val;		/* the master value */
+	unsigned int tlv[4];
 };
 
 /*
@@ -357,11 +359,12 @@ struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
 	kctl->private_free = master_free;
 
 	/* additional (constant) TLV read */
-	if (tlv) {
-		/* FIXME: this assumes that the max volume is 0 dB */
+	if (tlv && tlv[0] == SNDRV_CTL_TLVT_DB_SCALE) {
 		kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
-		kctl->tlv.p = tlv;
+		memcpy(master->tlv, tlv, sizeof(master->tlv));
+		kctl->tlv.p = master->tlv;
 	}
+
 	return kctl;
 }
 
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
index 9e0d8a1268a..ab0c726d648 100644
--- a/sound/pci/hda/Makefile
+++ b/sound/pci/hda/Makefile
@@ -2,7 +2,7 @@ snd-hda-intel-y := hda_intel.o
 # since snd-hda-intel is the only driver using hda-codec,
 # merge it into a single module although it was originally
 # designed to be individual modules
-snd-hda-intel-y += hda_codec.o vmaster.o
+snd-hda-intel-y += hda_codec.o
 snd-hda-intel-$(CONFIG_PROC_FS) += hda_proc.o
 snd-hda-intel-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o
 snd-hda-intel-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 3f3905cc4e0..e0f3559f8b1 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -80,7 +80,6 @@ struct ad198x_spec {
 #endif
 	/* for virtual master */
 	hda_nid_t vmaster_nid;
-	u32 vmaster_tlv[4];
 	const char **slave_vols;
 	const char **slave_sws;
 };
@@ -185,10 +184,11 @@ static int ad198x_build_controls(struct hda_codec *codec)
 
 	/* if we have no master control, let's create it */
 	if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
+		unsigned int vmaster_tlv[4];
 		snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
-					HDA_OUTPUT, spec->vmaster_tlv);
+					HDA_OUTPUT, vmaster_tlv);
 		err = snd_hda_add_vmaster(codec, "Master Playback Volume",
-					  spec->vmaster_tlv,
+					  vmaster_tlv,
 					  (spec->slave_vols ?
 					   spec->slave_vols : ad_slave_vols));
 		if (err < 0)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index eea18b3336d..e8ce525d297 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -272,7 +272,6 @@ struct alc_spec {
 
 	/* for virtual master */
 	hda_nid_t vmaster_nid;
-	u32 vmaster_tlv[4];
 #ifdef CONFIG_SND_HDA_POWER_SAVE
 	struct hda_loopback_check loopback;
 #endif
@@ -1534,10 +1533,11 @@ static int alc_build_controls(struct hda_codec *codec)
 
 	/* if we have no master control, let's create it */
 	if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
+		unsigned int vmaster_tlv[4];
 		snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
-					HDA_OUTPUT, spec->vmaster_tlv);
+					HDA_OUTPUT, vmaster_tlv);
 		err = snd_hda_add_vmaster(codec, "Master Playback Volume",
-					  spec->vmaster_tlv, alc_slave_vols);
+					  vmaster_tlv, alc_slave_vols);
 		if (err < 0)
 			return err;
 	}
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 7901e76f269..132d1e3eafa 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -186,9 +186,6 @@ struct sigmatel_spec {
 	struct hda_input_mux private_dimux;
 	struct hda_input_mux private_imux;
 	struct hda_input_mux private_mono_mux;
-
-	/* virtual master */
-	unsigned int vmaster_tlv[4];
 };
 
 static hda_nid_t stac9200_adc_nids[1] = {
@@ -930,10 +927,11 @@ static int stac92xx_build_controls(struct hda_codec *codec)
 
 	/* if we have no master control, let's create it */
 	if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
+		unsigned int vmaster_tlv[4];
 		snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0],
-					HDA_OUTPUT, spec->vmaster_tlv);
+					HDA_OUTPUT, vmaster_tlv);
 		err = snd_hda_add_vmaster(codec, "Master Playback Volume",
-					  spec->vmaster_tlv, slave_vols);
+					  vmaster_tlv, slave_vols);
 		if (err < 0)
 			return err;
 	}
-- 
cgit v1.2.3-70-g09d2


From 49c88b85b53767f97eb8c9171cb0b976c62a0114 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 18 Feb 2008 13:06:49 +0100
Subject: [ALSA] ca0106 - Add master volume controls

Added master volume and switch controls for ca0106 using vmaster.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/Kconfig               |  1 +
 sound/pci/ca0106/ca0106_mixer.c | 51 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 52 insertions(+)

(limited to 'sound')

diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 48296d97bf3..b05435cfee1 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -162,6 +162,7 @@ config SND_CA0106
 	depends on SND
 	select SND_AC97_CODEC
 	select SND_RAWMIDI
+	select SND_VMASTER
 	help
 	  Say Y here to include support for the Sound Blaster Audigy LS
 	  and Live 24bit.
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c
index af736869d9b..94618ecaab6 100644
--- a/sound/pci/ca0106/ca0106_mixer.c
+++ b/sound/pci/ca0106/ca0106_mixer.c
@@ -658,11 +658,47 @@ static int __devinit rename_ctl(struct snd_card *card, const char *src, const ch
 		}							\
 	} while (0)
 
+static __devinitdata
+DECLARE_TLV_DB_SCALE(snd_ca0106_master_db_scale, -6375, 50, 1);
+
+static char *slave_vols[] __devinitdata = {
+	"Analog Front Playback Volume",
+        "Analog Rear Playback Volume",
+	"Analog Center/LFE Playback Volume",
+        "Analog Side Playback Volume",
+        "IEC958 Front Playback Volume",
+	"IEC958 Rear Playback Volume",
+	"IEC958 Center/LFE Playback Volume",
+	"IEC958 Unknown Playback Volume",
+        "CAPTURE feedback Playback Volume",
+	NULL
+};
+
+static char *slave_sws[] __devinitdata = {
+	"Analog Front Playback Switch",
+	"Analog Rear Playback Switch",
+	"Analog Center/LFE Playback Switch",
+	"Analog Side Playback Switch",
+	"IEC958 Playback Switch",
+	NULL
+};
+
+static void __devinit add_slaves(struct snd_card *card,
+				 struct snd_kcontrol *master, char **list)
+{
+	for (; *list; list++) {
+		struct snd_kcontrol *slave = ctl_find(card, *list);
+		if (slave)
+			snd_ctl_add_slave(master, slave);
+	}
+}
+
 int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu)
 {
 	int err;
         struct snd_card *card = emu->card;
 	char **c;
+	struct snd_kcontrol *vmaster;
 	static char *ca0106_remove_ctls[] = {
 		"Master Mono Playback Switch",
 		"Master Mono Playback Volume",
@@ -719,6 +755,21 @@ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu)
 	}
 	if (emu->details->spi_dac == 1)
 		ADD_CTLS(emu, snd_ca0106_volume_spi_dac_ctls);
+
+	/* Create virtual master controls */
+	vmaster = snd_ctl_make_virtual_master("Master Playback Volume",
+					      snd_ca0106_master_db_scale);
+	if (!vmaster)
+		return -ENOMEM;
+	add_slaves(card, vmaster, slave_vols);
+
+	if (emu->details->spi_dac == 1) {
+		vmaster = snd_ctl_make_virtual_master("Master Playback Switch",
+						      NULL);
+		if (!vmaster)
+			return -ENOMEM;
+		add_slaves(card, vmaster, slave_sws);
+	}
         return 0;
 }
 
-- 
cgit v1.2.3-70-g09d2


From 8b6ed8e70d9a7c39748a9902d64138e070d4064b Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Tue, 19 Feb 2008 11:36:35 +0100
Subject: [ALSA] hda-intel - Clean up stream definitions

Clean up the code to define playback/capture streams.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/hda_intel.c | 29 ++++++++---------------------
 1 file changed, 8 insertions(+), 21 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 66dceffa121..cf1a1d0124f 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -185,21 +185,15 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
 
 /* max number of SDs */
 /* ICH, ATI and VIA have 4 playback and 4 capture */
-#define ICH6_CAPTURE_INDEX	0
 #define ICH6_NUM_CAPTURE	4
-#define ICH6_PLAYBACK_INDEX	4
 #define ICH6_NUM_PLAYBACK	4
 
 /* ULI has 6 playback and 5 capture */
-#define ULI_CAPTURE_INDEX	0
 #define ULI_NUM_CAPTURE		5
-#define ULI_PLAYBACK_INDEX	5
 #define ULI_NUM_PLAYBACK	6
 
 /* ATI HDMI has 1 playback and 0 capture */
-#define ATIHDMI_CAPTURE_INDEX	0
 #define ATIHDMI_NUM_CAPTURE	0
-#define ATIHDMI_PLAYBACK_INDEX	0
 #define ATIHDMI_NUM_PLAYBACK	1
 
 /* this number is statically defined for simplicity */
@@ -1846,38 +1840,31 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
 	if ((gcap & 0x01) && !pci_set_dma_mask(pci, DMA_64BIT_MASK))
 		pci_set_consistent_dma_mask(pci, DMA_64BIT_MASK);
 
-	if (gcap) {
-		/* read number of streams from GCAP register instead of using
-		 * hardcoded value
-		 */
-		chip->playback_streams = (gcap & (0xF << 12)) >> 12;
-		chip->capture_streams = (gcap & (0xF << 8)) >> 8;
-		chip->playback_index_offset = chip->capture_streams;
-		chip->capture_index_offset = 0;
-	} else {
+	/* read number of streams from GCAP register instead of using
+	 * hardcoded value
+	 */
+	chip->capture_streams = (gcap >> 8) & 0x0f;
+	chip->playback_streams = (gcap >> 12) & 0x0f;
+	if (!chip->playback_streams && !chip->capture_streams) {
 		/* gcap didn't give any info, switching to old method */
 
 		switch (chip->driver_type) {
 		case AZX_DRIVER_ULI:
 			chip->playback_streams = ULI_NUM_PLAYBACK;
 			chip->capture_streams = ULI_NUM_CAPTURE;
-			chip->playback_index_offset = ULI_PLAYBACK_INDEX;
-			chip->capture_index_offset = ULI_CAPTURE_INDEX;
 			break;
 		case AZX_DRIVER_ATIHDMI:
 			chip->playback_streams = ATIHDMI_NUM_PLAYBACK;
 			chip->capture_streams = ATIHDMI_NUM_CAPTURE;
-			chip->playback_index_offset = ATIHDMI_PLAYBACK_INDEX;
-			chip->capture_index_offset = ATIHDMI_CAPTURE_INDEX;
 			break;
 		default:
 			chip->playback_streams = ICH6_NUM_PLAYBACK;
 			chip->capture_streams = ICH6_NUM_CAPTURE;
-			chip->playback_index_offset = ICH6_PLAYBACK_INDEX;
-			chip->capture_index_offset = ICH6_CAPTURE_INDEX;
 			break;
 		}
 	}
+	chip->capture_index_offset = 0;
+	chip->playback_index_offset = chip->capture_streams;
 	chip->num_streams = chip->playback_streams + chip->capture_streams;
 	chip->azx_dev = kcalloc(chip->num_streams, sizeof(*chip->azx_dev),
 				GFP_KERNEL);
-- 
cgit v1.2.3-70-g09d2


From 77a261b75521564dcc5f22355cce4830f6b1376a Mon Sep 17 00:00:00 2001
From: Kailang Yang <kailang@realtek.com.tw>
Date: Tue, 19 Feb 2008 11:38:05 +0100
Subject: [ALSA] hda-codec - Fix ALC662 recording

Fixed ALC662 recording issue.

Signed-off-by: Kailang Yang <kailang@realtek.com.tw>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index e8ce525d297..62e1bd882a5 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -12752,7 +12752,7 @@ static hda_nid_t alc662_adc_nids[1] = {
 	0x09,
 };
 
-static hda_nid_t alc662_capsrc_nids[1] = { 0x23 };
+static hda_nid_t alc662_capsrc_nids[1] = { 0x22 };
 
 /* input MUX */
 /* FIXME: should be a matrix-type input source selection */
-- 
cgit v1.2.3-70-g09d2


From aef9d318b1d741d80486ff7ea3507a8321dedf6b Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Tue, 19 Feb 2008 13:16:41 +0100
Subject: [ALSA] hda-codec - Add beep volume control to ALC268

Added the beep volume control to ALC268 codec support code.
Since the codec doesn't return the correct AMP caps, we need to override
the value.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c | 53 ++++++++++++++++++++++++++++++++++++-------
 1 file changed, 45 insertions(+), 8 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 62e1bd882a5..6c8423dbace 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -9507,6 +9507,22 @@ static struct snd_kcontrol_new alc268_base_mixer[] = {
 	{ }
 };
 
+/* bind Beep switches of both NID 0x0f and 0x10 */
+static struct hda_bind_ctls alc268_bind_beep_sw = {
+	.ops = &snd_hda_bind_sw,
+	.values = {
+		HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT),
+		HDA_COMPOSE_AMP_VAL(0x10, 3, 1, HDA_INPUT),
+		0
+	},
+};
+
+static struct snd_kcontrol_new alc268_beep_mixer[] = {
+	HDA_CODEC_VOLUME("Beep Playback Volume", 0x1d, 0x0, HDA_INPUT),
+	HDA_BIND_SW("Beep Playback Switch", &alc268_bind_beep_sw),
+	{ }
+};
+
 static struct hda_verb alc268_eapd_verbs[] = {
 	{0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
 	{0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
@@ -9703,7 +9719,11 @@ static struct hda_verb alc268_base_init_verbs[] = {
 	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
 	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
 	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+
+	/* set PCBEEP vol = 0, mute connections */
+	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
 
 	/* Unmute Selector 23h,24h and set the default input to mic-in */
 	
@@ -9742,8 +9762,10 @@ static struct hda_verb alc268_volume_init_verbs[] = {
 	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
 	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
 
-	/* set PCBEEP vol = 0 */
-	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, (0xb000 | (0x00 << 8))},
+	/* set PCBEEP vol = 0, mute connections */
+	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
 
 	{ }
 };
@@ -10032,6 +10054,9 @@ static int alc268_parse_auto_config(struct hda_codec *codec)
 	if (spec->kctl_alloc)
 		spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
 
+	if (spec->autocfg.speaker_pins[0] != 0x1d)
+		spec->mixers[spec->num_mixers++] = alc268_beep_mixer;
+
 	spec->init_verbs[spec->num_init_verbs++] = alc268_volume_init_verbs;
 	spec->num_mux_defs = 1;
 	spec->input_mux = &spec->private_imux;
@@ -10091,7 +10116,8 @@ static struct snd_pci_quirk alc268_cfg_tbl[] = {
 
 static struct alc_config_preset alc268_presets[] = {
 	[ALC268_3ST] = {
-		.mixers = { alc268_base_mixer, alc268_capture_alt_mixer },
+		.mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
+			    alc268_beep_mixer },
 		.init_verbs = { alc268_base_init_verbs },
 		.num_dacs = ARRAY_SIZE(alc268_dac_nids),
 		.dac_nids = alc268_dac_nids,
@@ -10105,7 +10131,8 @@ static struct alc_config_preset alc268_presets[] = {
 		.input_mux = &alc268_capture_source,
 	},
 	[ALC268_TOSHIBA] = {
-		.mixers = { alc268_base_mixer, alc268_capture_alt_mixer },
+		.mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
+			    alc268_beep_mixer },
 		.init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
 				alc268_toshiba_verbs },
 		.num_dacs = ARRAY_SIZE(alc268_dac_nids),
@@ -10121,7 +10148,8 @@ static struct alc_config_preset alc268_presets[] = {
 		.init_hook = alc268_toshiba_automute,
 	},
 	[ALC268_ACER] = {
-		.mixers = { alc268_acer_mixer, alc268_capture_alt_mixer },
+		.mixers = { alc268_acer_mixer, alc268_capture_alt_mixer,
+			    alc268_beep_mixer },
 		.init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
 				alc268_acer_verbs },
 		.num_dacs = ARRAY_SIZE(alc268_dac_nids),
@@ -10137,7 +10165,7 @@ static struct alc_config_preset alc268_presets[] = {
 		.init_hook = alc268_acer_init_hook,
 	},
 	[ALC268_DELL] = {
-		.mixers = { alc268_dell_mixer },
+		.mixers = { alc268_dell_mixer, alc268_beep_mixer },
 		.init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
 				alc268_dell_verbs },
 		.num_dacs = ARRAY_SIZE(alc268_dac_nids),
@@ -10150,7 +10178,8 @@ static struct alc_config_preset alc268_presets[] = {
 		.input_mux = &alc268_capture_source,
 	},
 	[ALC268_ZEPTO] = {
-		.mixers = { alc268_base_mixer, alc268_capture_alt_mixer },
+		.mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
+			    alc268_beep_mixer },
 		.init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
 				alc268_toshiba_verbs },
 		.num_dacs = ARRAY_SIZE(alc268_dac_nids),
@@ -10232,6 +10261,14 @@ static int patch_alc268(struct hda_codec *codec)
 	spec->stream_name_digital = "ALC268 Digital";
 	spec->stream_digital_playback = &alc268_pcm_digital_playback;
 
+	if (!query_amp_caps(codec, 0x1d, HDA_INPUT))
+		/* override the amp caps for beep generator */
+		snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT,
+					  (0x0c << AC_AMPCAP_OFFSET_SHIFT) |
+					  (0x0c << AC_AMPCAP_NUM_STEPS_SHIFT) |
+					  (0x07 << AC_AMPCAP_STEP_SIZE_SHIFT) |
+					  (0 << AC_AMPCAP_MUTE_SHIFT));
+
 	if (!spec->adc_nids && spec->input_mux) {
 		/* check whether NID 0x07 is valid */
 		unsigned int wcap = get_wcaps(codec, 0x07);
-- 
cgit v1.2.3-70-g09d2


From 85860c06aba5e145805ad840553a2388e60a7e23 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Tue, 19 Feb 2008 15:00:15 +0100
Subject: [ALSA] hda-codec - Fix ALC268 capture source

Initialize the capture source properly for auto model.
It's especially important for cases that only mic is detected.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c | 6 ++++++
 1 file changed, 6 insertions(+)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 6c8423dbace..630c7b22542 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -10272,6 +10272,7 @@ static int patch_alc268(struct hda_codec *codec)
 	if (!spec->adc_nids && spec->input_mux) {
 		/* check whether NID 0x07 is valid */
 		unsigned int wcap = get_wcaps(codec, 0x07);
+		int i;
 
 		/* get type */
 		wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
@@ -10289,6 +10290,11 @@ static int patch_alc268(struct hda_codec *codec)
 			spec->num_mixers++;
 		}
 		spec->capsrc_nids = alc268_capsrc_nids;
+		/* set default input source */
+		for (i = 0; i < spec->num_adc_nids; i++)
+			snd_hda_codec_write_cache(codec, alc268_capsrc_nids[i],
+				0, AC_VERB_SET_CONNECT_SEL,
+				spec->input_mux->items[0].index);
 	}
 
 	spec->vmaster_nid = 0x02;
-- 
cgit v1.2.3-70-g09d2


From 67ebcb0311110dc7268bb5b135bf437d8033337e Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Tue, 19 Feb 2008 15:03:57 +0100
Subject: [ALSA] hda-codec - Don't create multiple capture streams for single
 inputs

When the device has only one input source, it makes no sense to have
multiple capture streams.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 630c7b22542..2100ee48080 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -4950,7 +4950,7 @@ static int alc260_parse_auto_config(struct hda_codec *codec)
 	/* check whether NID 0x04 is valid */
 	wcap = get_wcaps(codec, 0x04);
 	wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
-	if (wcap != AC_WID_AUD_IN) {
+	if (wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) {
 		spec->adc_nids = alc260_adc_nids_alt;
 		spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt);
 		spec->mixers[spec->num_mixers] = alc260_capture_alt_mixer;
@@ -10276,7 +10276,7 @@ static int patch_alc268(struct hda_codec *codec)
 
 		/* get type */
 		wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
-		if (wcap != AC_WID_AUD_IN) {
+		if (wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) {
 			spec->adc_nids = alc268_adc_nids_alt;
 			spec->num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt);
 			spec->mixers[spec->num_mixers] =
-- 
cgit v1.2.3-70-g09d2


From 98f2a97f207a776603173ee96327d977e592579d Mon Sep 17 00:00:00 2001
From: Cedric Bregardis <cedric.bregardis@free.fr>
Date: Wed, 20 Feb 2008 12:05:13 +0100
Subject: [ALSA] Emagic Audiowerk 2 ALSA driver.

Signed-off-by: Cedric Bregardis <cedric.bregardis@free.fr>
Signed-off-by: Jean-Christian Hassler <jhassler@free.fr>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/Kconfig           |  15 +
 sound/pci/Makefile          |   1 +
 sound/pci/aw2/Makefile      |   3 +
 sound/pci/aw2/aw2-alsa.c    | 787 ++++++++++++++++++++++++++++++++++++++++++++
 sound/pci/aw2/aw2-saa7146.c | 464 ++++++++++++++++++++++++++
 sound/pci/aw2/aw2-saa7146.h | 105 ++++++
 sound/pci/aw2/aw2-tsl.h     | 116 +++++++
 sound/pci/aw2/saa7146.h     | 168 ++++++++++
 8 files changed, 1659 insertions(+)
 create mode 100644 sound/pci/aw2/Makefile
 create mode 100644 sound/pci/aw2/aw2-alsa.c
 create mode 100644 sound/pci/aw2/aw2-saa7146.c
 create mode 100644 sound/pci/aw2/aw2-saa7146.h
 create mode 100644 sound/pci/aw2/aw2-tsl.h
 create mode 100644 sound/pci/aw2/saa7146.h

(limited to 'sound')

diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index b05435cfee1..868183bef24 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -122,6 +122,21 @@ config SND_AU8830
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-au8830.
 
+config SND_AW2
+	tristate "Emagic Audiowerk 2"
+	depends on SND
+	help
+	  Say Y here to include support for Emagic Audiowerk 2 soundcards.
+
+	  Supported features: Analog and SPDIF output. Analog or SPDIF input.
+	  Note: Switch between analog and digital input does not always work.
+	  It can produce continuous noise. The workaround is to switch again
+	  (and again) between digital and analog input until it works.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-aw2.
+
+
 config SND_AZT3328
 	tristate "Aztech AZF3328 / PCI168 (EXPERIMENTAL)"
 	depends on SND && EXPERIMENTAL
diff --git a/sound/pci/Makefile b/sound/pci/Makefile
index 2d42fd28f4e..85ef14bc805 100644
--- a/sound/pci/Makefile
+++ b/sound/pci/Makefile
@@ -58,6 +58,7 @@ obj-$(CONFIG_SND) += \
 	ac97/ \
 	ali5451/ \
 	au88x0/ \
+	aw2/ \
 	ca0106/ \
 	cs46xx/ \
 	cs5535audio/ \
diff --git a/sound/pci/aw2/Makefile b/sound/pci/aw2/Makefile
new file mode 100644
index 00000000000..842335d3b73
--- /dev/null
+++ b/sound/pci/aw2/Makefile
@@ -0,0 +1,3 @@
+snd-aw2-objs := aw2-alsa.o aw2-saa7146.o
+
+obj-$(CONFIG_SND_AW2) += snd-aw2.o
diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c
new file mode 100644
index 00000000000..74af639b913
--- /dev/null
+++ b/sound/pci/aw2/aw2-alsa.c
@@ -0,0 +1,787 @@
+/*****************************************************************************
+ *
+ * Copyright (C) 2008 Cedric Bregardis <cedric.bregardis@free.fr> and
+ * Jean-Christian Hassler <jhassler@free.fr>
+ *
+ * This file is part of the Audiowerk2 ALSA driver
+ *
+ * The Audiowerk2 ALSA driver is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2.
+ *
+ * The Audiowerk2 ALSA driver is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the Audiowerk2 ALSA driver; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+ * USA.
+ *
+ *****************************************************************************/
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/control.h>
+
+#include "saa7146.h"
+#include "aw2-saa7146.h"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Cedric Bregardis <cedric.bregardis@free.fr>, "
+	      "Jean-Christian Hassler <jhassler@free.fr>");
+MODULE_DESCRIPTION("Emagic Audiowerk 2 sound driver");
+MODULE_LICENSE("GPL");
+
+/*********************************
+ * DEFINES
+ ********************************/
+#define PCI_VENDOR_ID_SAA7146		  0x1131
+#define PCI_DEVICE_ID_SAA7146		  0x7146
+
+#define CTL_ROUTE_ANALOG 0
+#define CTL_ROUTE_DIGITAL 1
+
+/*********************************
+ * TYPEDEFS
+ ********************************/
+  /* hardware definition */
+static struct snd_pcm_hardware snd_aw2_playback_hw = {
+	.info = (SNDRV_PCM_INFO_MMAP |
+		 SNDRV_PCM_INFO_INTERLEAVED |
+		 SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID),
+	.formats = SNDRV_PCM_FMTBIT_S16_LE,
+	.rates = SNDRV_PCM_RATE_44100,
+	.rate_min = 44100,
+	.rate_max = 44100,
+	.channels_min = 2,
+	.channels_max = 4,
+	.buffer_bytes_max = 32768,
+	.period_bytes_min = 4096,
+	.period_bytes_max = 32768,
+	.periods_min = 1,
+	.periods_max = 1024,
+};
+
+static struct snd_pcm_hardware snd_aw2_capture_hw = {
+	.info = (SNDRV_PCM_INFO_MMAP |
+		 SNDRV_PCM_INFO_INTERLEAVED |
+		 SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID),
+	.formats = SNDRV_PCM_FMTBIT_S16_LE,
+	.rates = SNDRV_PCM_RATE_44100,
+	.rate_min = 44100,
+	.rate_max = 44100,
+	.channels_min = 2,
+	.channels_max = 2,
+	.buffer_bytes_max = 32768,
+	.period_bytes_min = 4096,
+	.period_bytes_max = 32768,
+	.periods_min = 1,
+	.periods_max = 1024,
+};
+
+struct aw2_pcm_device {
+	struct snd_pcm *pcm;
+	unsigned int stream_number;
+	struct aw2 *chip;
+};
+
+struct aw2 {
+	struct snd_aw2_saa7146 saa7146;
+
+	struct pci_dev *pci;
+	int irq;
+	spinlock_t reg_lock;
+	struct mutex mtx;
+
+	unsigned long iobase_phys;
+	void __iomem *iobase_virt;
+
+	struct snd_card *card;
+
+	struct aw2_pcm_device device_playback[NB_STREAM_PLAYBACK];
+	struct aw2_pcm_device device_capture[NB_STREAM_CAPTURE];
+};
+
+/*********************************
+ * FUNCTION DECLARATIONS
+ ********************************/
+static int __init alsa_card_aw2_init(void);
+static void __exit alsa_card_aw2_exit(void);
+static int snd_aw2_dev_free(struct snd_device *device);
+static int __devinit snd_aw2_create(struct snd_card *card,
+				    struct pci_dev *pci, struct aw2 **rchip);
+static int __devinit snd_aw2_probe(struct pci_dev *pci,
+				   const struct pci_device_id *pci_id);
+static void __devexit snd_aw2_remove(struct pci_dev *pci);
+static int snd_aw2_pcm_playback_open(struct snd_pcm_substream *substream);
+static int snd_aw2_pcm_playback_close(struct snd_pcm_substream *substream);
+static int snd_aw2_pcm_capture_open(struct snd_pcm_substream *substream);
+static int snd_aw2_pcm_capture_close(struct snd_pcm_substream *substream);
+static int snd_aw2_pcm_hw_params(struct snd_pcm_substream *substream,
+				 struct snd_pcm_hw_params *hw_params);
+static int snd_aw2_pcm_hw_free(struct snd_pcm_substream *substream);
+static int snd_aw2_pcm_prepare_playback(struct snd_pcm_substream *substream);
+static int snd_aw2_pcm_prepare_capture(struct snd_pcm_substream *substream);
+static int snd_aw2_pcm_trigger_playback(struct snd_pcm_substream *substream,
+					int cmd);
+static int snd_aw2_pcm_trigger_capture(struct snd_pcm_substream *substream,
+				       int cmd);
+static snd_pcm_uframes_t snd_aw2_pcm_pointer_playback(struct snd_pcm_substream
+						      *substream);
+static snd_pcm_uframes_t snd_aw2_pcm_pointer_capture(struct snd_pcm_substream
+						     *substream);
+static int __devinit snd_aw2_new_pcm(struct aw2 *chip);
+
+static int snd_aw2_control_switch_capture_info(struct snd_kcontrol *kcontrol,
+					       struct snd_ctl_elem_info *uinfo);
+static int snd_aw2_control_switch_capture_get(struct snd_kcontrol *kcontrol,
+					      struct snd_ctl_elem_value
+					      *ucontrol);
+static int snd_aw2_control_switch_capture_put(struct snd_kcontrol *kcontrol,
+					      struct snd_ctl_elem_value
+					      *ucontrol);
+
+/*********************************
+ * VARIABLES
+ ********************************/
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+
+static struct pci_device_id snd_aw2_ids[] = {
+	{PCI_VENDOR_ID_SAA7146, PCI_DEVICE_ID_SAA7146, PCI_ANY_ID, PCI_ANY_ID,
+	 0, 0, 0},
+	{0}
+};
+
+MODULE_DEVICE_TABLE(pci, snd_aw2_ids);
+
+/* pci_driver definition */
+static struct pci_driver driver = {
+	.name = "Emagic Audiowerk 2",
+	.id_table = snd_aw2_ids,
+	.probe = snd_aw2_probe,
+	.remove = __devexit_p(snd_aw2_remove),
+};
+
+/* operators for playback PCM alsa interface */
+static struct snd_pcm_ops snd_aw2_playback_ops = {
+	.open = snd_aw2_pcm_playback_open,
+	.close = snd_aw2_pcm_playback_close,
+	.ioctl = snd_pcm_lib_ioctl,
+	.hw_params = snd_aw2_pcm_hw_params,
+	.hw_free = snd_aw2_pcm_hw_free,
+	.prepare = snd_aw2_pcm_prepare_playback,
+	.trigger = snd_aw2_pcm_trigger_playback,
+	.pointer = snd_aw2_pcm_pointer_playback,
+};
+
+/* operators for capture PCM alsa interface */
+static struct snd_pcm_ops snd_aw2_capture_ops = {
+	.open = snd_aw2_pcm_capture_open,
+	.close = snd_aw2_pcm_capture_close,
+	.ioctl = snd_pcm_lib_ioctl,
+	.hw_params = snd_aw2_pcm_hw_params,
+	.hw_free = snd_aw2_pcm_hw_free,
+	.prepare = snd_aw2_pcm_prepare_capture,
+	.trigger = snd_aw2_pcm_trigger_capture,
+	.pointer = snd_aw2_pcm_pointer_capture,
+};
+
+static struct snd_kcontrol_new aw2_control __devinitdata = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "PCM Capture Route",
+	.index = 0,
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+	.private_value = 0xffff,
+	.info = snd_aw2_control_switch_capture_info,
+	.get = snd_aw2_control_switch_capture_get,
+	.put = snd_aw2_control_switch_capture_put
+};
+
+/*********************************
+ * FUNCTION IMPLEMENTATIONS
+ ********************************/
+
+/* initialization of the module */
+static int __init alsa_card_aw2_init(void)
+{
+	snd_printdd(KERN_DEBUG "aw2: Load aw2 module\n");
+	return pci_register_driver(&driver);
+}
+
+/* clean up the module */
+static void __exit alsa_card_aw2_exit(void)
+{
+	snd_printdd(KERN_DEBUG "aw2: Unload aw2 module\n");
+	pci_unregister_driver(&driver);
+}
+
+module_init(alsa_card_aw2_init);
+module_exit(alsa_card_aw2_exit);
+
+/* component-destructor */
+static int snd_aw2_dev_free(struct snd_device *device)
+{
+	struct aw2 *chip = device->device_data;
+
+	/* Free hardware */
+	snd_aw2_saa7146_free(&chip->saa7146);
+
+	/* release the irq */
+	if (chip->irq >= 0)
+		free_irq(chip->irq, (void *)chip);
+	/* release the i/o ports & memory */
+	if (chip->iobase_virt)
+		iounmap(chip->iobase_virt);
+
+	pci_release_regions(chip->pci);
+	/* disable the PCI entry */
+	pci_disable_device(chip->pci);
+	/* release the data */
+	kfree(chip);
+
+	return 0;
+}
+
+/* chip-specific constructor */
+static int __devinit snd_aw2_create(struct snd_card *card,
+				    struct pci_dev *pci, struct aw2 **rchip)
+{
+	struct aw2 *chip;
+	int err;
+	static struct snd_device_ops ops = {
+		.dev_free = snd_aw2_dev_free,
+	};
+
+	*rchip = NULL;
+
+	/* initialize the PCI entry */
+	err = pci_enable_device(pci);
+	if (err < 0)
+		return err;
+	pci_set_master(pci);
+
+	/* check PCI availability (32bit DMA) */
+	if ((pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0) ||
+	    (pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) < 0)) {
+		printk(KERN_ERR "aw2: Impossible to set 32bit mask DMA\n");
+		pci_disable_device(pci);
+		return -ENXIO;
+	}
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+	if (chip == NULL) {
+		pci_disable_device(pci);
+		return -ENOMEM;
+	}
+
+	/* initialize the stuff */
+	chip->card = card;
+	chip->pci = pci;
+	chip->irq = -1;
+
+	/* (1) PCI resource allocation */
+	err = pci_request_regions(pci, "Audiowerk2");
+	if (err < 0) {
+		pci_disable_device(pci);
+		kfree(chip);
+		return err;
+	}
+	chip->iobase_phys = pci_resource_start(pci, 0);
+	chip->iobase_virt =
+		ioremap_nocache(chip->iobase_phys,
+				pci_resource_len(pci, 0));
+
+	if (chip->iobase_virt == NULL) {
+		printk(KERN_ERR "aw2: unable to remap memory region");
+		pci_release_regions(pci);
+		pci_disable_device(pci);
+		kfree(chip);
+		return -ENOMEM;
+	}
+
+
+	if (request_irq(pci->irq, snd_aw2_saa7146_interrupt,
+			IRQF_SHARED, "Audiowerk2", chip)) {
+		printk(KERN_ERR "aw2: Cannot grab irq %d\n", pci->irq);
+
+		iounmap(chip->iobase_virt);
+		pci_release_regions(chip->pci);
+		pci_disable_device(chip->pci);
+		kfree(chip);
+		return -EBUSY;
+	}
+	chip->irq = pci->irq;
+
+	/* (2) initialization of the chip hardware */
+	snd_aw2_saa7146_setup(&chip->saa7146, chip->iobase_virt);
+	err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
+	if (err < 0) {
+		free_irq(chip->irq, (void *)chip);
+		iounmap(chip->iobase_virt);
+		pci_release_regions(chip->pci);
+		pci_disable_device(chip->pci);
+		kfree(chip);
+		return err;
+	}
+
+	snd_card_set_dev(card, &pci->dev);
+	*rchip = chip;
+
+	printk(KERN_INFO
+	       "Audiowerk 2 sound card (saa7146 chipset) detected and "
+	       "managed\n");
+	return 0;
+}
+
+/* constructor */
+static int __devinit snd_aw2_probe(struct pci_dev *pci,
+				   const struct pci_device_id *pci_id)
+{
+	static int dev;
+	struct snd_card *card;
+	struct aw2 *chip;
+	int err;
+
+	/* (1) Continue if device is not enabled, else inc dev */
+	if (dev >= SNDRV_CARDS)
+		return -ENODEV;
+	if (!enable[dev]) {
+		dev++;
+		return -ENOENT;
+	}
+
+	/* (2) Create card instance */
+	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
+	if (card == NULL)
+		return -ENOMEM;
+
+	/* (3) Create main component */
+	err = snd_aw2_create(card, pci, &chip);
+	if (err < 0) {
+		snd_card_free(card);
+		return err;
+	}
+
+	/* initialize mutex */
+	mutex_init(&chip->mtx);
+	/* init spinlock */
+	spin_lock_init(&chip->reg_lock);
+	/* (4) Define driver ID and name string */
+	strcpy(card->driver, "aw2");
+	strcpy(card->shortname, "Audiowerk2");
+
+	sprintf(card->longname, "%s with SAA7146 irq %i",
+		card->shortname, chip->irq);
+
+	/* (5) Create other components */
+	snd_aw2_new_pcm(chip);
+
+	/* (6) Register card instance */
+	err = snd_card_register(card);
+	if (err < 0) {
+		snd_card_free(card);
+		return err;
+	}
+
+	/* (7) Set PCI driver data */
+	pci_set_drvdata(pci, card);
+
+	dev++;
+	return 0;
+}
+
+/* destructor */
+static void __devexit snd_aw2_remove(struct pci_dev *pci)
+{
+	snd_card_free(pci_get_drvdata(pci));
+	pci_set_drvdata(pci, NULL);
+}
+
+/* open callback */
+static int snd_aw2_pcm_playback_open(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+
+	snd_printdd(KERN_DEBUG "aw2: Playback_open \n");
+	runtime->hw = snd_aw2_playback_hw;
+	return 0;
+}
+
+/* close callback */
+static int snd_aw2_pcm_playback_close(struct snd_pcm_substream *substream)
+{
+	return 0;
+
+}
+
+static int snd_aw2_pcm_capture_open(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+
+	snd_printdd(KERN_DEBUG "aw2: Capture_open \n");
+	runtime->hw = snd_aw2_capture_hw;
+	return 0;
+}
+
+/* close callback */
+static int snd_aw2_pcm_capture_close(struct snd_pcm_substream *substream)
+{
+	/* TODO: something to do ? */
+	return 0;
+}
+
+ /* hw_params callback */
+static int snd_aw2_pcm_hw_params(struct snd_pcm_substream *substream,
+				 struct snd_pcm_hw_params *hw_params)
+{
+	return snd_pcm_lib_malloc_pages(substream,
+					params_buffer_bytes(hw_params));
+}
+
+/* hw_free callback */
+static int snd_aw2_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+	return snd_pcm_lib_free_pages(substream);
+}
+
+/* prepare callback for playback */
+static int snd_aw2_pcm_prepare_playback(struct snd_pcm_substream *substream)
+{
+	struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream);
+	struct aw2 *chip = pcm_device->chip;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	unsigned long period_size, buffer_size;
+
+	mutex_lock(&chip->mtx);
+
+	period_size = snd_pcm_lib_period_bytes(substream);
+	buffer_size = snd_pcm_lib_buffer_bytes(substream);
+
+	snd_aw2_saa7146_pcm_init_playback(&chip->saa7146,
+					  pcm_device->stream_number,
+					  runtime->dma_addr, period_size,
+					  buffer_size);
+
+	/* Define Interrupt callback */
+	snd_aw2_saa7146_define_it_playback_callback(pcm_device->stream_number,
+						    (snd_aw2_saa7146_it_cb)
+						    snd_pcm_period_elapsed,
+						    (void *)substream);
+
+	mutex_unlock(&chip->mtx);
+
+	return 0;
+}
+
+/* prepare callback for capture */
+static int snd_aw2_pcm_prepare_capture(struct snd_pcm_substream *substream)
+{
+	struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream);
+	struct aw2 *chip = pcm_device->chip;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	unsigned long period_size, buffer_size;
+
+	mutex_lock(&chip->mtx);
+
+	period_size = snd_pcm_lib_period_bytes(substream);
+	buffer_size = snd_pcm_lib_buffer_bytes(substream);
+
+	snd_aw2_saa7146_pcm_init_capture(&chip->saa7146,
+					 pcm_device->stream_number,
+					 runtime->dma_addr, period_size,
+					 buffer_size);
+
+	/* Define Interrupt callback */
+	snd_aw2_saa7146_define_it_capture_callback(pcm_device->stream_number,
+						   (snd_aw2_saa7146_it_cb)
+						   snd_pcm_period_elapsed,
+						   (void *)substream);
+
+	mutex_unlock(&chip->mtx);
+
+	return 0;
+}
+
+/* playback trigger callback */
+static int snd_aw2_pcm_trigger_playback(struct snd_pcm_substream *substream,
+					int cmd)
+{
+	int status = 0;
+	struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream);
+	struct aw2 *chip = pcm_device->chip;
+	spin_lock(&chip->reg_lock);
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		snd_aw2_saa7146_pcm_trigger_start_playback(&chip->saa7146,
+							   pcm_device->
+							   stream_number);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+		snd_aw2_saa7146_pcm_trigger_stop_playback(&chip->saa7146,
+							  pcm_device->
+							  stream_number);
+		break;
+	default:
+		status = -EINVAL;
+	}
+	spin_unlock(&chip->reg_lock);
+	return status;
+}
+
+/* capture trigger callback */
+static int snd_aw2_pcm_trigger_capture(struct snd_pcm_substream *substream,
+				       int cmd)
+{
+	int status = 0;
+	struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream);
+	struct aw2 *chip = pcm_device->chip;
+	spin_lock(&chip->reg_lock);
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		snd_aw2_saa7146_pcm_trigger_start_capture(&chip->saa7146,
+							  pcm_device->
+							  stream_number);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+		snd_aw2_saa7146_pcm_trigger_stop_capture(&chip->saa7146,
+							 pcm_device->
+							 stream_number);
+		break;
+	default:
+		status = -EINVAL;
+	}
+	spin_unlock(&chip->reg_lock);
+	return status;
+}
+
+/* playback pointer callback */
+static snd_pcm_uframes_t snd_aw2_pcm_pointer_playback(struct snd_pcm_substream
+						      *substream)
+{
+	struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream);
+	struct aw2 *chip = pcm_device->chip;
+	unsigned int current_ptr;
+
+	/* get the current hardware pointer */
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	current_ptr =
+		snd_aw2_saa7146_get_hw_ptr_playback(&chip->saa7146,
+						    pcm_device->stream_number,
+						    runtime->dma_area,
+						    runtime->buffer_size);
+
+	return bytes_to_frames(substream->runtime, current_ptr);
+}
+
+/* capture pointer callback */
+static snd_pcm_uframes_t snd_aw2_pcm_pointer_capture(struct snd_pcm_substream
+						     *substream)
+{
+	struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream);
+	struct aw2 *chip = pcm_device->chip;
+	unsigned int current_ptr;
+
+	/* get the current hardware pointer */
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	current_ptr =
+		snd_aw2_saa7146_get_hw_ptr_capture(&chip->saa7146,
+						   pcm_device->stream_number,
+						   runtime->dma_area,
+						   runtime->buffer_size);
+
+	return bytes_to_frames(substream->runtime, current_ptr);
+}
+
+/* create a pcm device */
+static int __devinit snd_aw2_new_pcm(struct aw2 *chip)
+{
+	struct snd_pcm *pcm_playback_ana;
+	struct snd_pcm *pcm_playback_num;
+	struct snd_pcm *pcm_capture;
+	struct aw2_pcm_device *pcm_device;
+	int err = 0;
+
+	/* Create new Alsa PCM device */
+
+	err = snd_pcm_new(chip->card, "Audiowerk2 analog playback", 0, 1, 0,
+			  &pcm_playback_ana);
+	if (err < 0) {
+		printk(KERN_ERR "aw2: snd_pcm_new error (0x%X)\n", err);
+		return err;
+	}
+
+	/* Creation ok */
+	pcm_device = &chip->device_playback[NUM_STREAM_PLAYBACK_ANA];
+
+	/* Set PCM device name */
+	strcpy(pcm_playback_ana->name, "Analog playback");
+	/* Associate private data to PCM device */
+	pcm_playback_ana->private_data = pcm_device;
+	/* set operators of PCM device */
+	snd_pcm_set_ops(pcm_playback_ana, SNDRV_PCM_STREAM_PLAYBACK,
+			&snd_aw2_playback_ops);
+	/* store PCM device */
+	pcm_device->pcm = pcm_playback_ana;
+	/* give base chip pointer to our internal pcm device
+	   structure */
+	pcm_device->chip = chip;
+	/* Give stream number to PCM device */
+	pcm_device->stream_number = NUM_STREAM_PLAYBACK_ANA;
+
+	/* pre-allocation of buffers */
+	/* Preallocate continuous pages. */
+	err = snd_pcm_lib_preallocate_pages_for_all(pcm_playback_ana,
+						    SNDRV_DMA_TYPE_DEV,
+						    snd_dma_pci_data
+						    (chip->pci),
+						    64 * 1024, 64 * 1024);
+	if (err)
+		printk(KERN_ERR "aw2: snd_pcm_lib_preallocate_pages_for_all "
+		       "error (0x%X)\n", err);
+
+	err = snd_pcm_new(chip->card, "Audiowerk2 digital playback", 1, 1, 0,
+			  &pcm_playback_num);
+
+	if (err < 0) {
+		printk(KERN_ERR "aw2: snd_pcm_new error (0x%X)\n", err);
+		return err;
+	}
+	/* Creation ok */
+	pcm_device = &chip->device_playback[NUM_STREAM_PLAYBACK_DIG];
+
+	/* Set PCM device name */
+	strcpy(pcm_playback_num->name, "Digital playback");
+	/* Associate private data to PCM device */
+	pcm_playback_num->private_data = pcm_device;
+	/* set operators of PCM device */
+	snd_pcm_set_ops(pcm_playback_num, SNDRV_PCM_STREAM_PLAYBACK,
+			&snd_aw2_playback_ops);
+	/* store PCM device */
+	pcm_device->pcm = pcm_playback_num;
+	/* give base chip pointer to our internal pcm device
+	   structure */
+	pcm_device->chip = chip;
+	/* Give stream number to PCM device */
+	pcm_device->stream_number = NUM_STREAM_PLAYBACK_DIG;
+
+	/* pre-allocation of buffers */
+	/* Preallocate continuous pages. */
+	err = snd_pcm_lib_preallocate_pages_for_all(pcm_playback_num,
+						    SNDRV_DMA_TYPE_DEV,
+						    snd_dma_pci_data
+						    (chip->pci),
+						    64 * 1024, 64 * 1024);
+	if (err)
+		printk(KERN_ERR
+		       "aw2: snd_pcm_lib_preallocate_pages_for_all error "
+		       "(0x%X)\n", err);
+
+
+
+	err = snd_pcm_new(chip->card, "Audiowerk2 capture", 2, 0, 1,
+			  &pcm_capture);
+
+	if (err < 0) {
+		printk(KERN_ERR "aw2: snd_pcm_new error (0x%X)\n", err);
+		return err;
+	}
+
+	/* Creation ok */
+	pcm_device = &chip->device_capture[NUM_STREAM_CAPTURE_ANA];
+
+	/* Set PCM device name */
+	strcpy(pcm_capture->name, "Capture");
+	/* Associate private data to PCM device */
+	pcm_capture->private_data = pcm_device;
+	/* set operators of PCM device */
+	snd_pcm_set_ops(pcm_capture, SNDRV_PCM_STREAM_CAPTURE,
+			&snd_aw2_capture_ops);
+	/* store PCM device */
+	pcm_device->pcm = pcm_capture;
+	/* give base chip pointer to our internal pcm device
+	   structure */
+	pcm_device->chip = chip;
+	/* Give stream number to PCM device */
+	pcm_device->stream_number = NUM_STREAM_CAPTURE_ANA;
+
+	/* pre-allocation of buffers */
+	/* Preallocate continuous pages. */
+	err = snd_pcm_lib_preallocate_pages_for_all(pcm_capture,
+						    SNDRV_DMA_TYPE_DEV,
+						    snd_dma_pci_data
+						    (chip->pci),
+						    64 * 1024, 64 * 1024);
+	if (err)
+		printk(KERN_ERR
+		       "aw2: snd_pcm_lib_preallocate_pages_for_all error "
+		       "(0x%X)\n", err);
+
+
+	/* Create control */
+	err = snd_ctl_add(chip->card, snd_ctl_new1(&aw2_control, chip));
+	if (err < 0) {
+		printk(KERN_ERR "aw2: snd_ctl_add error (0x%X)\n", err);
+		return err;
+	}
+
+	return 0;
+}
+
+static int snd_aw2_control_switch_capture_info(struct snd_kcontrol *kcontrol,
+					       struct snd_ctl_elem_info *uinfo)
+{
+	static char *texts[2] = {
+		"Analog", "Digital"
+	};
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 2;
+	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) {
+		uinfo->value.enumerated.item =
+		    uinfo->value.enumerated.items - 1;
+	}
+	strcpy(uinfo->value.enumerated.name,
+	       texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
+static int snd_aw2_control_switch_capture_get(struct snd_kcontrol *kcontrol,
+					      struct snd_ctl_elem_value
+					      *ucontrol)
+{
+	struct aw2 *chip = snd_kcontrol_chip(kcontrol);
+	if (snd_aw2_saa7146_is_using_digital_input(&chip->saa7146))
+		ucontrol->value.enumerated.item[0] = CTL_ROUTE_DIGITAL;
+	else
+		ucontrol->value.enumerated.item[0] = CTL_ROUTE_ANALOG;
+	return 0;
+}
+
+static int snd_aw2_control_switch_capture_put(struct snd_kcontrol *kcontrol,
+					      struct snd_ctl_elem_value
+					      *ucontrol)
+{
+	struct aw2 *chip = snd_kcontrol_chip(kcontrol);
+	int changed = 0;
+	int is_disgital =
+	    snd_aw2_saa7146_is_using_digital_input(&chip->saa7146);
+
+	if (((ucontrol->value.integer.value[0] == CTL_ROUTE_DIGITAL)
+	     && !is_disgital)
+	    || ((ucontrol->value.integer.value[0] == CTL_ROUTE_ANALOG)
+		&& is_disgital)) {
+		snd_aw2_saa7146_use_digital_input(&chip->saa7146, !is_disgital);
+		changed = 1;
+	}
+	return changed;
+}
diff --git a/sound/pci/aw2/aw2-saa7146.c b/sound/pci/aw2/aw2-saa7146.c
new file mode 100644
index 00000000000..f20f213489a
--- /dev/null
+++ b/sound/pci/aw2/aw2-saa7146.c
@@ -0,0 +1,464 @@
+/*****************************************************************************
+ *
+ * Copyright (C) 2008 Cedric Bregardis <cedric.bregardis@free.fr> and
+ * Jean-Christian Hassler <jhassler@free.fr>
+ *
+ * This file is part of the Audiowerk2 ALSA driver
+ *
+ * The Audiowerk2 ALSA driver is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2.
+ *
+ * The Audiowerk2 ALSA driver is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the Audiowerk2 ALSA driver; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+ * USA.
+ *
+ *****************************************************************************/
+
+#define AW2_SAA7146_M
+
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+
+#include "aw2-tsl.h"
+#include "saa7146.h"
+#include "aw2-saa7146.h"
+
+#define WRITEREG(value, addr) writel((value), chip->base_addr + (addr))
+#define READREG(addr) readl(chip->base_addr + (addr))
+
+static struct snd_aw2_saa7146_cb_param
+ arr_substream_it_playback_cb[NB_STREAM_PLAYBACK];
+static struct snd_aw2_saa7146_cb_param
+ arr_substream_it_capture_cb[NB_STREAM_CAPTURE];
+
+static int snd_aw2_saa7146_get_limit(int size);
+
+/* chip-specific destructor */
+int snd_aw2_saa7146_free(struct snd_aw2_saa7146 *chip)
+{
+	/* disable all irqs */
+	WRITEREG(0, IER);
+
+	/* reset saa7146 */
+	WRITEREG((MRST_N << 16), MC1);
+
+	/* Unset base addr */
+	chip->base_addr = NULL;
+
+	return 0;
+}
+
+void snd_aw2_saa7146_setup(struct snd_aw2_saa7146 *chip,
+			   void __iomem *pci_base_addr)
+{
+	/* set PCI burst/threshold
+
+	   Burst length definition
+	   VALUE    BURST LENGTH
+	   000      1 Dword
+	   001      2 Dwords
+	   010      4 Dwords
+	   011      8 Dwords
+	   100      16 Dwords
+	   101      32 Dwords
+	   110      64 Dwords
+	   111      128 Dwords
+
+	   Threshold definition
+	   VALUE    WRITE MODE              READ MODE
+	   00       1 Dword of valid data   1 empty Dword
+	   01       4 Dwords of valid data  4 empty Dwords
+	   10       8 Dwords of valid data  8 empty Dwords
+	   11       16 Dwords of valid data 16 empty Dwords */
+
+	unsigned int acon2;
+	unsigned int acon1 = 0;
+	int i;
+
+	/* Set base addr */
+	chip->base_addr = pci_base_addr;
+
+	/* disable all irqs */
+	WRITEREG(0, IER);
+
+	/* reset saa7146 */
+	WRITEREG((MRST_N << 16), MC1);
+
+	/* enable audio interface */
+#ifdef __BIG_ENDIAN
+	acon1 |= A1_SWAP;
+	acon1 |= A2_SWAP;
+#endif
+	/* WS0_CTRL, WS0_SYNC: input TSL1, I2S */
+
+	/* At initialization WS1 and WS2 are disbaled (configured as input */
+	acon1 |= 0 * WS1_CTRL;
+	acon1 |= 0 * WS2_CTRL;
+
+	/* WS4 is not used. So it must not restart A2.
+	   This is why it is configured as output (force to low) */
+	acon1 |= 3 * WS4_CTRL;
+
+	/* WS3_CTRL, WS3_SYNC: output TSL2, I2S */
+	acon1 |= 2 * WS3_CTRL;
+
+	/* A1 and A2 are active and asynchronous */
+	acon1 |= 3 * AUDIO_MODE;
+	WRITEREG(acon1, ACON1);
+
+	/* The following comes from original windows driver.
+	   It is needed to have a correct behavior of input and output
+	   simultenously, but I don't know why ! */
+	WRITEREG(3 * (BurstA1_in) + 3 * (ThreshA1_in) +
+		 3 * (BurstA1_out) + 3 * (ThreshA1_out) +
+		 3 * (BurstA2_out) + 3 * (ThreshA2_out), PCI_BT_A);
+
+	/* enable audio port pins */
+	WRITEREG((EAP << 16) | EAP, MC1);
+
+	/* enable I2C */
+	WRITEREG((EI2C << 16) | EI2C, MC1);
+	/* enable interrupts */
+	WRITEREG(A1_out | A2_out | A1_in | IIC_S | IIC_E, IER);
+
+	/* audio configuration */
+	acon2 = A2_CLKSRC | BCLK1_OEN;
+	WRITEREG(acon2, ACON2);
+
+	/* By default use analog input */
+	snd_aw2_saa7146_use_digital_input(chip, 0);
+
+	/* TSL setup */
+	for (i = 0; i < 8; ++i) {
+		WRITEREG(tsl1[i], TSL1 + (i * 4));
+		WRITEREG(tsl2[i], TSL2 + (i * 4));
+	}
+
+}
+
+void snd_aw2_saa7146_pcm_init_playback(struct snd_aw2_saa7146 *chip,
+				       int stream_number,
+				       unsigned long dma_addr,
+				       unsigned long period_size,
+				       unsigned long buffer_size)
+{
+	unsigned long dw_page, dw_limit;
+
+	/* Configure DMA for substream
+	   Configuration informations: ALSA has allocated continuous memory
+	   pages. So we don't need to use MMU of saa7146.
+	 */
+
+	/* No MMU -> nothing to do with PageA1, we only configure the limit of
+	   PageAx_out register */
+	/* Disable MMU */
+	dw_page = (0L << 11);
+
+	/* Configure Limit for DMA access.
+	   The limit register defines an address limit, which generates
+	   an interrupt if passed by the actual PCI address pointer.
+	   '0001' means an interrupt will be generated if the lower
+	   6 bits (64 bytes) of the PCI address are zero. '0010'
+	   defines a limit of 128 bytes, '0011' one of 256 bytes, and
+	   so on up to 1 Mbyte defined by '1111'. This interrupt range
+	   can be calculated as follows:
+	   Range = 2^(5 + Limit) bytes.
+	 */
+	dw_limit = snd_aw2_saa7146_get_limit(period_size);
+	dw_page |= (dw_limit << 4);
+
+	if (stream_number == 0) {
+		WRITEREG(dw_page, PageA2_out);
+
+		/* Base address for DMA transfert. */
+		/* This address has been reserved by ALSA. */
+		/* This is a physical address */
+		WRITEREG(dma_addr, BaseA2_out);
+
+		/* Define upper limit for DMA access */
+		WRITEREG(dma_addr + buffer_size, ProtA2_out);
+
+	} else if (stream_number == 1) {
+		WRITEREG(dw_page, PageA1_out);
+
+		/* Base address for DMA transfert. */
+		/* This address has been reserved by ALSA. */
+		/* This is a physical address */
+		WRITEREG(dma_addr, BaseA1_out);
+
+		/* Define upper limit for DMA access */
+		WRITEREG(dma_addr + buffer_size, ProtA1_out);
+	} else {
+		printk(KERN_ERR
+		       "aw2: snd_aw2_saa7146_pcm_init_playback: "
+		       "Substream number is not 0 or 1 -> not managed\n");
+	}
+}
+
+void snd_aw2_saa7146_pcm_init_capture(struct snd_aw2_saa7146 *chip,
+				      int stream_number, unsigned long dma_addr,
+				      unsigned long period_size,
+				      unsigned long buffer_size)
+{
+	unsigned long dw_page, dw_limit;
+
+	/* Configure DMA for substream
+	   Configuration informations: ALSA has allocated continuous memory
+	   pages. So we don't need to use MMU of saa7146.
+	 */
+
+	/* No MMU -> nothing to do with PageA1, we only configure the limit of
+	   PageAx_out register */
+	/* Disable MMU */
+	dw_page = (0L << 11);
+
+	/* Configure Limit for DMA access.
+	   The limit register defines an address limit, which generates
+	   an interrupt if passed by the actual PCI address pointer.
+	   '0001' means an interrupt will be generated if the lower
+	   6 bits (64 bytes) of the PCI address are zero. '0010'
+	   defines a limit of 128 bytes, '0011' one of 256 bytes, and
+	   so on up to 1 Mbyte defined by '1111'. This interrupt range
+	   can be calculated as follows:
+	   Range = 2^(5 + Limit) bytes.
+	 */
+	dw_limit = snd_aw2_saa7146_get_limit(period_size);
+	dw_page |= (dw_limit << 4);
+
+	if (stream_number == 0) {
+		WRITEREG(dw_page, PageA1_in);
+
+		/* Base address for DMA transfert. */
+		/* This address has been reserved by ALSA. */
+		/* This is a physical address */
+		WRITEREG(dma_addr, BaseA1_in);
+
+		/* Define upper limit for DMA access  */
+		WRITEREG(dma_addr + buffer_size, ProtA1_in);
+	} else {
+		printk(KERN_ERR
+		       "aw2: snd_aw2_saa7146_pcm_init_capture: "
+		       "Substream number is not 0 -> not managed\n");
+	}
+}
+
+void snd_aw2_saa7146_define_it_playback_callback(unsigned int stream_number,
+						 snd_aw2_saa7146_it_cb
+						 p_it_callback,
+						 void *p_callback_param)
+{
+	if (stream_number < NB_STREAM_PLAYBACK) {
+		arr_substream_it_playback_cb[stream_number].p_it_callback =
+		    (snd_aw2_saa7146_it_cb) p_it_callback;
+		arr_substream_it_playback_cb[stream_number].p_callback_param =
+		    (void *)p_callback_param;
+	}
+}
+
+void snd_aw2_saa7146_define_it_capture_callback(unsigned int stream_number,
+						snd_aw2_saa7146_it_cb
+						p_it_callback,
+						void *p_callback_param)
+{
+	if (stream_number < NB_STREAM_CAPTURE) {
+		arr_substream_it_capture_cb[stream_number].p_it_callback =
+		    (snd_aw2_saa7146_it_cb) p_it_callback;
+		arr_substream_it_capture_cb[stream_number].p_callback_param =
+		    (void *)p_callback_param;
+	}
+}
+
+void snd_aw2_saa7146_pcm_trigger_start_playback(struct snd_aw2_saa7146 *chip,
+						int stream_number)
+{
+	unsigned int acon1 = 0;
+	/* In aw8 driver, dma transfert is always active. It is
+	   started and stopped in a larger "space" */
+	acon1 = READREG(ACON1);
+	if (stream_number == 0) {
+		WRITEREG((TR_E_A2_OUT << 16) | TR_E_A2_OUT, MC1);
+
+		/* WS2_CTRL, WS2_SYNC: output TSL2, I2S */
+		acon1 |= 2 * WS2_CTRL;
+		WRITEREG(acon1, ACON1);
+
+	} else if (stream_number == 1) {
+		WRITEREG((TR_E_A1_OUT << 16) | TR_E_A1_OUT, MC1);
+
+		/* WS1_CTRL, WS1_SYNC: output TSL1, I2S */
+		acon1 |= 1 * WS1_CTRL;
+		WRITEREG(acon1, ACON1);
+	}
+}
+
+void snd_aw2_saa7146_pcm_trigger_stop_playback(struct snd_aw2_saa7146 *chip,
+					       int stream_number)
+{
+	unsigned int acon1 = 0;
+	acon1 = READREG(ACON1);
+	if (stream_number == 0) {
+		/* WS2_CTRL, WS2_SYNC: output TSL2, I2S */
+		acon1 &= ~(3 * WS2_CTRL);
+		WRITEREG(acon1, ACON1);
+
+		WRITEREG((TR_E_A2_OUT << 16), MC1);
+	} else if (stream_number == 1) {
+		/* WS1_CTRL, WS1_SYNC: output TSL1, I2S */
+		acon1 &= ~(3 * WS1_CTRL);
+		WRITEREG(acon1, ACON1);
+
+		WRITEREG((TR_E_A1_OUT << 16), MC1);
+	}
+}
+
+void snd_aw2_saa7146_pcm_trigger_start_capture(struct snd_aw2_saa7146 *chip,
+					       int stream_number)
+{
+	/* In aw8 driver, dma transfert is always active. It is
+	   started and stopped in a larger "space" */
+	if (stream_number == 0)
+		WRITEREG((TR_E_A1_IN << 16) | TR_E_A1_IN, MC1);
+}
+
+void snd_aw2_saa7146_pcm_trigger_stop_capture(struct snd_aw2_saa7146 *chip,
+					      int stream_number)
+{
+	if (stream_number == 0)
+		WRITEREG((TR_E_A1_IN << 16), MC1);
+}
+
+irqreturn_t snd_aw2_saa7146_interrupt(int irq, void *dev_id)
+{
+	unsigned int isr;
+	unsigned int iicsta;
+	struct snd_aw2_saa7146 *chip = dev_id;
+
+	isr = READREG(ISR);
+	if (!isr)
+		return IRQ_NONE;
+
+	WRITEREG(isr, ISR);
+
+	if (isr & (IIC_S | IIC_E)) {
+		iicsta = READREG(IICSTA);
+		WRITEREG(0x100, IICSTA);
+	}
+
+	if (isr & A1_out) {
+		if (arr_substream_it_playback_cb[1].p_it_callback != NULL) {
+			arr_substream_it_playback_cb[1].
+			    p_it_callback(arr_substream_it_playback_cb[1].
+					  p_callback_param);
+		}
+	}
+	if (isr & A2_out) {
+		if (arr_substream_it_playback_cb[0].p_it_callback != NULL) {
+			arr_substream_it_playback_cb[0].
+			    p_it_callback(arr_substream_it_playback_cb[0].
+					  p_callback_param);
+		}
+
+	}
+	if (isr & A1_in) {
+		if (arr_substream_it_capture_cb[0].p_it_callback != NULL) {
+			arr_substream_it_capture_cb[0].
+			    p_it_callback(arr_substream_it_capture_cb[0].
+					  p_callback_param);
+		}
+	}
+	return IRQ_HANDLED;
+}
+
+unsigned int snd_aw2_saa7146_get_hw_ptr_playback(struct snd_aw2_saa7146 *chip,
+						 int stream_number,
+						 unsigned char *start_addr,
+						 unsigned int buffer_size)
+{
+	long pci_adp = 0;
+	size_t ptr = 0;
+
+	if (stream_number == 0) {
+		pci_adp = READREG(PCI_ADP3);
+		ptr = pci_adp - (long)start_addr;
+
+		if (ptr == buffer_size)
+			ptr = 0;
+	}
+	if (stream_number == 1) {
+		pci_adp = READREG(PCI_ADP1);
+		ptr = pci_adp - (size_t) start_addr;
+
+		if (ptr == buffer_size)
+			ptr = 0;
+	}
+	return ptr;
+}
+
+unsigned int snd_aw2_saa7146_get_hw_ptr_capture(struct snd_aw2_saa7146 *chip,
+						int stream_number,
+						unsigned char *start_addr,
+						unsigned int buffer_size)
+{
+	size_t pci_adp = 0;
+	size_t ptr = 0;
+	if (stream_number == 0) {
+		pci_adp = READREG(PCI_ADP2);
+		ptr = pci_adp - (size_t) start_addr;
+
+		if (ptr == buffer_size)
+			ptr = 0;
+	}
+	return ptr;
+}
+
+void snd_aw2_saa7146_use_digital_input(struct snd_aw2_saa7146 *chip,
+				       int use_digital)
+{
+	/* FIXME: switch between analog and digital input does not always work.
+	   It can produce a kind of white noise. It seams that received data
+	   are inverted sometime (endian inversion). Why ? I don't know, maybe
+	   a problem of synchronization... However for the time being I have
+	   not found the problem. Workaround: switch again (and again) between
+	   digital and analog input until it works. */
+	if (use_digital)
+		WRITEREG(0x40, GPIO_CTRL);
+	else
+		WRITEREG(0x50, GPIO_CTRL);
+}
+
+int snd_aw2_saa7146_is_using_digital_input(struct snd_aw2_saa7146 *chip)
+{
+	unsigned int reg_val = READREG(GPIO_CTRL);
+	if ((reg_val & 0xFF) == 0x40)
+		return 1;
+	else
+		return 0;
+}
+
+
+static int snd_aw2_saa7146_get_limit(int size)
+{
+	int limitsize = 32;
+	int limit = 0;
+	while (limitsize < size) {
+		limitsize *= 2;
+		limit++;
+	}
+	return limit;
+}
diff --git a/sound/pci/aw2/aw2-saa7146.h b/sound/pci/aw2/aw2-saa7146.h
new file mode 100644
index 00000000000..5b35e358937
--- /dev/null
+++ b/sound/pci/aw2/aw2-saa7146.h
@@ -0,0 +1,105 @@
+/*****************************************************************************
+ *
+ * Copyright (C) 2008 Cedric Bregardis <cedric.bregardis@free.fr> and
+ * Jean-Christian Hassler <jhassler@free.fr>
+ *
+ * This file is part of the Audiowerk2 ALSA driver
+ *
+ * The Audiowerk2 ALSA driver is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2.
+ *
+ * The Audiowerk2 ALSA driver is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the Audiowerk2 ALSA driver; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+ * USA.
+ *
+ *****************************************************************************/
+
+#ifndef AW2_SAA7146_H
+#define AW2_SAA7146_H
+
+#define NB_STREAM_PLAYBACK 2
+#define NB_STREAM_CAPTURE 1
+
+#define NUM_STREAM_PLAYBACK_ANA 0
+#define NUM_STREAM_PLAYBACK_DIG 1
+
+#define NUM_STREAM_CAPTURE_ANA 0
+
+typedef void (*snd_aw2_saa7146_it_cb) (void *);
+
+struct snd_aw2_saa7146_cb_param {
+	snd_aw2_saa7146_it_cb p_it_callback;
+	void *p_callback_param;
+};
+
+/* definition of the chip-specific record */
+
+struct snd_aw2_saa7146 {
+	void __iomem *base_addr;
+};
+
+extern void snd_aw2_saa7146_setup(struct snd_aw2_saa7146 *chip,
+				  void __iomem *pci_base_addr);
+extern int snd_aw2_saa7146_free(struct snd_aw2_saa7146 *chip);
+
+extern void snd_aw2_saa7146_pcm_init_playback(struct snd_aw2_saa7146 *chip,
+					      int stream_number,
+					      unsigned long dma_addr,
+					      unsigned long period_size,
+					      unsigned long buffer_size);
+extern void snd_aw2_saa7146_pcm_init_capture(struct snd_aw2_saa7146 *chip,
+					     int stream_number,
+					     unsigned long dma_addr,
+					     unsigned long period_size,
+					     unsigned long buffer_size);
+extern void snd_aw2_saa7146_define_it_playback_callback(unsigned int
+							stream_number,
+							snd_aw2_saa7146_it_cb
+							p_it_callback,
+							void *p_callback_param);
+extern void snd_aw2_saa7146_define_it_capture_callback(unsigned int
+						       stream_number,
+						       snd_aw2_saa7146_it_cb
+						       p_it_callback,
+						       void *p_callback_param);
+extern void snd_aw2_saa7146_pcm_trigger_start_capture(struct snd_aw2_saa7146
+						      *chip, int stream_number);
+extern void snd_aw2_saa7146_pcm_trigger_stop_capture(struct snd_aw2_saa7146
+						     *chip, int stream_number);
+
+extern void snd_aw2_saa7146_pcm_trigger_start_playback(struct snd_aw2_saa7146
+						       *chip,
+						       int stream_number);
+extern void snd_aw2_saa7146_pcm_trigger_stop_playback(struct snd_aw2_saa7146
+						      *chip, int stream_number);
+
+extern irqreturn_t snd_aw2_saa7146_interrupt(int irq, void *dev_id);
+extern unsigned int snd_aw2_saa7146_get_hw_ptr_playback(struct snd_aw2_saa7146
+							*chip,
+							int stream_number,
+							unsigned char
+							*start_addr,
+							unsigned int
+							buffer_size);
+extern unsigned int snd_aw2_saa7146_get_hw_ptr_capture(struct snd_aw2_saa7146
+						       *chip,
+						       int stream_number,
+						       unsigned char
+						       *start_addr,
+						       unsigned int
+						       buffer_size);
+
+extern void snd_aw2_saa7146_use_digital_input(struct snd_aw2_saa7146 *chip,
+					      int use_digital);
+
+extern int snd_aw2_saa7146_is_using_digital_input(struct snd_aw2_saa7146
+						  *chip);
+
+#endif
diff --git a/sound/pci/aw2/aw2-tsl.h b/sound/pci/aw2/aw2-tsl.h
new file mode 100644
index 00000000000..e8afaa0a468
--- /dev/null
+++ b/sound/pci/aw2/aw2-tsl.h
@@ -0,0 +1,116 @@
+/*****************************************************************************
+ *
+ * Copyright (C) 2008 Cedric Bregardis <cedric.bregardis@free.fr> and
+ * Jean-Christian Hassler <jhassler@free.fr>
+ * Copyright 1998 Emagic Soft- und Hardware GmbH
+ * Copyright 2002 Martijn Sipkema
+ *
+ * This file is part of the Audiowerk2 ALSA driver
+ *
+ * The Audiowerk2 ALSA driver is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2.
+ *
+ * The Audiowerk2 ALSA driver is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the Audiowerk2 ALSA driver; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+ * USA.
+ *
+ *****************************************************************************/
+
+#define TSL_WS0		(1UL << 31)
+#define	TSL_WS1		(1UL << 30)
+#define	TSL_WS2		(1UL << 29)
+#define TSL_WS3		(1UL << 28)
+#define TSL_WS4		(1UL << 27)
+#define	TSL_DIS_A1	(1UL << 24)
+#define TSL_SDW_A1	(1UL << 23)
+#define TSL_SIB_A1	(1UL << 22)
+#define TSL_SF_A1	(1UL << 21)
+#define	TSL_LF_A1	(1UL << 20)
+#define TSL_BSEL_A1	(1UL << 17)
+#define TSL_DOD_A1	(1UL << 15)
+#define TSL_LOW_A1	(1UL << 14)
+#define TSL_DIS_A2	(1UL << 11)
+#define TSL_SDW_A2	(1UL << 10)
+#define TSL_SIB_A2	(1UL << 9)
+#define TSL_SF_A2	(1UL << 8)
+#define TSL_LF_A2	(1UL << 7)
+#define TSL_BSEL_A2	(1UL << 4)
+#define TSL_DOD_A2	(1UL << 2)
+#define TSL_LOW_A2	(1UL << 1)
+#define TSL_EOS		(1UL << 0)
+
+    /* Audiowerk8 hardware setup: */
+    /*      WS0, SD4, TSL1  - Analog/ digital in */
+    /*      WS1, SD0, TSL1  - Analog out #1, digital out */
+    /*      WS2, SD2, TSL1  - Analog out #2 */
+    /*      WS3, SD1, TSL2  - Analog out #3 */
+    /*      WS4, SD3, TSL2  - Analog out #4 */
+
+    /* Audiowerk8 timing: */
+    /*      Timeslot:     | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ... */
+
+    /*      A1_INPUT: */
+    /*      SD4:          <_ADC-L_>-------<_ADC-R_>-------< */
+    /*      WS0:          _______________/---------------\_ */
+
+    /*      A1_OUTPUT: */
+    /*      SD0:          <_1-L___>-------<_1-R___>-------< */
+    /*      WS1:          _______________/---------------\_ */
+    /*      SD2:          >-------<_2-L___>-------<_2-R___> */
+    /*      WS2:          -------\_______________/--------- */
+
+    /*      A2_OUTPUT: */
+    /*      SD1:          <_3-L___>-------<_3-R___>-------< */
+    /*      WS3:          _______________/---------------\_ */
+    /*      SD3:          >-------<_4-L___>-------<_4-R___> */
+    /*      WS4:          -------\_______________/--------- */
+
+#ifdef __BIG_ENDIAN
+    /* TODO: not yet implemented */
+#else /*  */
+
+static int tsl1[8] = {
+	1 * TSL_SDW_A1 | 3 * TSL_BSEL_A1 |
+	0 * TSL_DIS_A1 | 0 * TSL_DOD_A1 | TSL_LF_A1,
+
+	1 * TSL_SDW_A1 | 2 * TSL_BSEL_A1 |
+	0 * TSL_DIS_A1 | 0 * TSL_DOD_A1,
+
+	0 * TSL_SDW_A1 | 3 * TSL_BSEL_A1 |
+	0 * TSL_DIS_A1 | 0 * TSL_DOD_A1,
+
+	0 * TSL_SDW_A1 | 2 * TSL_BSEL_A1 |
+	0 * TSL_DIS_A1 | 0 * TSL_DOD_A1,
+
+	1 * TSL_SDW_A1 | 1 * TSL_BSEL_A1 |
+	0 * TSL_DIS_A1 | 0 * TSL_DOD_A1 | TSL_WS1 | TSL_WS0,
+
+	1 * TSL_SDW_A1 | 0 * TSL_BSEL_A1 |
+	0 * TSL_DIS_A1 | 0 * TSL_DOD_A1 | TSL_WS1 | TSL_WS0,
+
+	0 * TSL_SDW_A1 | 1 * TSL_BSEL_A1 |
+	0 * TSL_DIS_A1 | 0 * TSL_DOD_A1 | TSL_WS1 | TSL_WS0,
+
+	0 * TSL_SDW_A1 | 0 * TSL_BSEL_A1 | 0 * TSL_DIS_A1 |
+	0 * TSL_DOD_A1 | TSL_WS1 | TSL_WS0 | TSL_SF_A1 | TSL_EOS,
+};
+
+static int tsl2[8] = {
+	0 * TSL_SDW_A2 | 3 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_LF_A2,
+	0 * TSL_SDW_A2 | 2 * TSL_BSEL_A2 | 2 * TSL_DOD_A2,
+	0 * TSL_SDW_A2 | 3 * TSL_BSEL_A2 | 2 * TSL_DOD_A2,
+	0 * TSL_SDW_A2 | 2 * TSL_BSEL_A2 | 2 * TSL_DOD_A2,
+	0 * TSL_SDW_A2 | 1 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_WS2,
+	0 * TSL_SDW_A2 | 0 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_WS2,
+	0 * TSL_SDW_A2 | 1 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_WS2,
+	0 * TSL_SDW_A2 | 0 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_WS2 | TSL_EOS
+};
+
+#endif /*  */
diff --git a/sound/pci/aw2/saa7146.h b/sound/pci/aw2/saa7146.h
new file mode 100644
index 00000000000..ce0ab5f9ee9
--- /dev/null
+++ b/sound/pci/aw2/saa7146.h
@@ -0,0 +1,168 @@
+/*****************************************************************************
+ *
+ * Copyright (C) 2008 Cedric Bregardis <cedric.bregardis@free.fr> and
+ * Jean-Christian Hassler <jhassler@free.fr>
+ *
+ * This file is part of the Audiowerk2 ALSA driver
+ *
+ * The Audiowerk2 ALSA driver is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2.
+ *
+ * The Audiowerk2 ALSA driver is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the Audiowerk2 ALSA driver; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+ * USA.
+ *
+ *****************************************************************************/
+
+/* SAA7146 registers */
+#define PCI_BT_A	0x4C
+#define IICTFR		0x8C
+#define IICSTA		0x90
+#define BaseA1_in	0x94
+#define ProtA1_in	0x98
+#define PageA1_in	0x9C
+#define BaseA1_out	0xA0
+#define ProtA1_out	0xA4
+#define PageA1_out	0xA8
+#define BaseA2_in	0xAC
+#define ProtA2_in	0xB0
+#define PageA2_in	0xB4
+#define BaseA2_out	0xB8
+#define ProtA2_out	0xBC
+#define PageA2_out	0xC0
+#define IER		0xDC
+#define GPIO_CTRL	0xE0
+#define ACON1		0xF4
+#define ACON2		0xF8
+#define MC1		0xFC
+#define MC2		0x100
+#define ISR		0x10C
+#define PSR		0x110
+#define SSR		0x114
+#define PCI_ADP1	0x12C
+#define PCI_ADP2	0x130
+#define PCI_ADP3	0x134
+#define PCI_ADP4	0x138
+#define LEVEL_REP	0x140
+#define FB_BUFFER1	0x144
+#define FB_BUFFER2	0x148
+#define TSL1		0x180
+#define TSL2		0x1C0
+
+#define ME	(1UL << 11)
+#define LIMIT	(1UL << 4)
+#define PV	(1UL << 3)
+
+/* PSR/ISR/IER */
+#define PPEF		(1UL << 31)
+#define PABO		(1UL << 30)
+#define IIC_S		(1UL << 17)
+#define IIC_E		(1UL << 16)
+#define A2_in		(1UL << 15)
+#define A2_out		(1UL << 14)
+#define A1_in		(1UL << 13)
+#define A1_out		(1UL << 12)
+#define AFOU		(1UL << 11)
+#define PIN3		(1UL << 6)
+#define PIN2		(1UL << 5)
+#define PIN1		(1UL << 4)
+#define PIN0		(1UL << 3)
+#define ECS		(1UL << 2)
+#define EC3S		(1UL << 1)
+#define EC0S		(1UL << 0)
+
+/* SSR */
+#define PRQ		(1UL << 31)
+#define PMA		(1UL << 30)
+#define IIC_EA		(1UL << 21)
+#define IIC_EW		(1UL << 20)
+#define IIC_ER		(1UL << 19)
+#define IIC_EL		(1UL << 18)
+#define IIC_EF		(1UL << 17)
+#define AF2_in		(1UL << 10)
+#define AF2_out		(1UL << 9)
+#define AF1_in		(1UL << 8)
+#define AF1_out		(1UL << 7)
+#define EC5S		(1UL << 3)
+#define EC4S		(1UL << 2)
+#define EC2S		(1UL << 1)
+#define EC1S		(1UL << 0)
+
+/* PCI_BT_A */
+#define BurstA1_in	(1UL << 26)
+#define ThreshA1_in	(1UL << 24)
+#define BurstA1_out	(1UL << 18)
+#define ThreshA1_out	(1UL << 16)
+#define BurstA2_in	(1UL << 10)
+#define ThreshA2_in	(1UL << 8)
+#define BurstA2_out	(1UL << 2)
+#define ThreshA2_out	(1UL << 0)
+
+/* MC1 */
+#define MRST_N		(1UL << 15)
+#define EAP		(1UL << 9)
+#define EI2C		(1UL << 8)
+#define TR_E_A2_OUT	(1UL << 3)
+#define TR_E_A2_IN	(1UL << 2)
+#define TR_E_A1_OUT	(1UL << 1)
+#define TR_E_A1_IN	(1UL << 0)
+
+/* MC2 */
+#define UPLD_IIC	(1UL << 0)
+
+/* ACON1 */
+#define AUDIO_MODE	(1UL << 29)
+#define MAXLEVEL	(1UL << 22)
+#define A1_SWAP		(1UL << 21)
+#define A2_SWAP		(1UL << 20)
+#define WS0_CTRL	(1UL << 18)
+#define WS0_SYNC	(1UL << 16)
+#define WS1_CTRL	(1UL << 14)
+#define WS1_SYNC	(1UL << 12)
+#define WS2_CTRL	(1UL << 10)
+#define WS2_SYNC	(1UL << 8)
+#define WS3_CTRL	(1UL << 6)
+#define WS3_SYNC	(1UL << 4)
+#define WS4_CTRL	(1UL << 2)
+#define WS4_SYNC	(1UL << 0)
+
+/* ACON2 */
+#define A1_CLKSRC	(1UL << 27)
+#define A2_CLKSRC	(1UL << 22)
+#define INVERT_BCLK1	(1UL << 21)
+#define INVERT_BCLK2	(1UL << 20)
+#define BCLK1_OEN	(1UL << 19)
+#define BCLK2_OEN	(1UL << 18)
+
+/* IICSTA */
+#define IICCC		(1UL << 8)
+#define ABORT		(1UL << 7)
+#define SPERR		(1UL << 6)
+#define APERR		(1UL << 5)
+#define DTERR		(1UL << 4)
+#define DRERR		(1UL << 3)
+#define AL		(1UL << 2)
+#define ERR		(1UL << 1)
+#define BUSY		(1UL << 0)
+
+/* IICTFR */
+#define BYTE2		(1UL << 24)
+#define BYTE1		(1UL << 16)
+#define BYTE0		(1UL << 8)
+#define ATRR2		(1UL << 6)
+#define ATRR1		(1UL << 4)
+#define ATRR0		(1UL << 2)
+#define ERR		(1UL << 1)
+#define BUSY		(1UL << 0)
+
+#define START	3
+#define CONT	2
+#define STOP	1
+#define NOP	0
-- 
cgit v1.2.3-70-g09d2


From 34b6757dc7ce0e9d5d3930b29d53a7bcb0fde047 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Wed, 20 Feb 2008 12:12:58 +0100
Subject: [ALSA] aw2 - Add missing module parameters

Added the missing declarations for module parameters.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/aw2/aw2-alsa.c | 7 +++++++
 1 file changed, 7 insertions(+)

(limited to 'sound')

diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c
index 74af639b913..24e3e4961d9 100644
--- a/sound/pci/aw2/aw2-alsa.c
+++ b/sound/pci/aw2/aw2-alsa.c
@@ -157,6 +157,13 @@ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
 
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for Audiowerk2 soundcard.");
+module_param_array(id, charp, NULL, 0444);
+MODULE_PARM_DESC(id, "ID string for the Audiowerk2 soundcard.");
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable Audiowerk2 soundcard.");
+
 static struct pci_device_id snd_aw2_ids[] = {
 	{PCI_VENDOR_ID_SAA7146, PCI_DEVICE_ID_SAA7146, PCI_ANY_ID, PCI_ANY_ID,
 	 0, 0, 0},
-- 
cgit v1.2.3-70-g09d2


From 6876a5323f6169f9321354a398f7364b41ca82fa Mon Sep 17 00:00:00 2001
From: Jarkko Nikula <jarkko.nikula@nokia.com>
Date: Wed, 20 Feb 2008 17:13:44 +0100
Subject: [ALSA] ASoC: Add support for 12 MHz MCLK in TLV320AIC3X

Signed-off-by: Jarkko Nikula <jarkko.nikula@nokia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/soc/codecs/tlv320aic3x.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

(limited to 'sound')

diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 889a897d41a..e6a730b0dd2 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -660,33 +660,43 @@ struct aic3x_rate_divs {
 /* AIC3X codec mclk clock divider coefficients */
 static const struct aic3x_rate_divs aic3x_divs[] = {
 	/* 8k */
+	{12000000, 8000, 48000, 0xa, 16, 3840},
 	{22579200, 8000, 48000, 0xa, 8, 7075},
 	{33868800, 8000, 48000, 0xa, 5, 8049},
 	/* 11.025k */
+	{12000000, 11025, 44100, 0x6, 15, 528},
 	{22579200, 11025, 44100, 0x6, 8, 0},
 	{33868800, 11025, 44100, 0x6, 5, 3333},
 	/* 16k */
+	{12000000, 16000, 48000, 0x4, 16, 3840},
 	{22579200, 16000, 48000, 0x4, 8, 7075},
 	{33868800, 16000, 48000, 0x4, 5, 8049},
 	/* 22.05k */
+	{12000000, 22050, 44100, 0x2, 15, 528},
 	{22579200, 22050, 44100, 0x2, 8, 0},
 	{33868800, 22050, 44100, 0x2, 5, 3333},
 	/* 32k */
+	{12000000, 32000, 48000, 0x1, 16, 3840},
 	{22579200, 32000, 48000, 0x1, 8, 7075},
 	{33868800, 32000, 48000, 0x1, 5, 8049},
 	/* 44.1k */
+	{12000000, 44100, 44100, 0x0, 15, 528},
 	{22579200, 44100, 44100, 0x0, 8, 0},
 	{33868800, 44100, 44100, 0x0, 5, 3333},
 	/* 48k */
+	{12000000, 48000, 48000, 0x0, 16, 3840},
 	{22579200, 48000, 48000, 0x0, 8, 7075},
 	{33868800, 48000, 48000, 0x0, 5, 8049},
 	/* 64k */
+	{12000000, 64000, 96000, 0x1, 16, 3840},
 	{22579200, 64000, 96000, 0x1, 8, 7075},
 	{33868800, 64000, 96000, 0x1, 5, 8049},
 	/* 88.2k */
+	{12000000, 88200, 88200, 0x0, 15, 528},
 	{22579200, 88200, 88200, 0x0, 8, 0},
 	{33868800, 88200, 88200, 0x0, 5, 3333},
 	/* 96k */
+	{12000000, 96000, 96000, 0x0, 16, 3840},
 	{22579200, 96000, 96000, 0x0, 8, 7075},
 	{33868800, 96000, 96000, 0x0, 5, 8049},
 };
@@ -807,6 +817,7 @@ static int aic3x_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai,
 	struct aic3x_priv *aic3x = codec->private_data;
 
 	switch (freq) {
+	case 12000000:
 	case 22579200:
 	case 33868800:
 		aic3x->sysclk = freq;
-- 
cgit v1.2.3-70-g09d2


From 4451089e2aafba87d7574e27c839895131a80293 Mon Sep 17 00:00:00 2001
From: Matthew Ranostay <mranostay@embeddedalley.com>
Date: Thu, 21 Feb 2008 07:49:31 +0100
Subject: [ALSA] hda: fix STAC927x power management

Fix issue on STAC927x codecs that first DAC was getting powered down
even if was being used.

Signed-off-by: Matthew Ranostay <mranostay@embeddedalley.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_sigmatel.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 132d1e3eafa..a31155d4140 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -2893,7 +2893,8 @@ static void stac92xx_power_down(struct hda_codec *codec)
 	/* power down inactive DACs */
 	hda_nid_t *dac;
 	for (dac = spec->dac_list; *dac; dac++)
-		if (!is_in_dac_nids(spec, *dac))
+		if (!is_in_dac_nids(spec, *dac) &&
+			spec->multiout.hp_nid != *dac)
 			snd_hda_codec_write_cache(codec, *dac, 0,
 					AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
 }
-- 
cgit v1.2.3-70-g09d2


From 7989fba979daea99285079dc0099ab658e4db759 Mon Sep 17 00:00:00 2001
From: Matthew Ranostay <mranostay@embeddedalley.com>
Date: Thu, 21 Feb 2008 07:50:12 +0100
Subject: [ALSA] hda: STAC927x invalid association value

STAC_DELL_BIOS quirks were setting the association value wrong
for port 0x0f, which prevented it from being included in hp_outs[].

Signed-off-by: Matthew Ranostay <mranostay@embeddedalley.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_sigmatel.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index a31155d4140..70c56945975 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -3631,7 +3631,7 @@ static int patch_stac927x(struct hda_codec *codec)
 		break;
 	case STAC_DELL_BIOS:
 		/* correct the front output jack as a hp out */
-		stac92xx_set_config_reg(codec, 0x0f, 0x02270110);
+		stac92xx_set_config_reg(codec, 0x0f, 0x0227011f);
 		/* correct the front input jack as a mic */
 		stac92xx_set_config_reg(codec, 0x0e, 0x02a79130);
 		/* fallthru */
-- 
cgit v1.2.3-70-g09d2


From a7662640104599249e15cda7839e9050f92e6a0e Mon Sep 17 00:00:00 2001
From: Matthew Ranostay <mranostay@embeddedalley.com>
Date: Thu, 21 Feb 2008 07:51:14 +0100
Subject: [ALSA] hda: 92HDxxxx PCI Quirks

Added PCI_QUIRKS for laptop that have the 92HDxxx family of codecs.

Signed-off-by: Matthew Ranostay <mranostay@embeddedalley.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_sigmatel.c | 103 ++++++++++++++++++++++++++++++++++++++---
 1 file changed, 97 insertions(+), 6 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 70c56945975..a0c290cef76 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -64,11 +64,14 @@ enum {
 
 enum {
 	STAC_92HD73XX_REF,
+	STAC_DELL_M6,
 	STAC_92HD73XX_MODELS
 };
 
 enum {
 	STAC_92HD71BXX_REF,
+	STAC_DELL_M4_1,
+	STAC_DELL_M4_2,
 	STAC_92HD71BXX_MODELS
 };
 
@@ -334,10 +337,10 @@ static hda_nid_t stac922x_pin_nids[10] = {
 	0x0f, 0x10, 0x11, 0x15, 0x1b,
 };
 
-static hda_nid_t stac92hd73xx_pin_nids[12] = {
+static hda_nid_t stac92hd73xx_pin_nids[13] = {
 	0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
 	0x0f, 0x10, 0x11, 0x12, 0x13,
-	0x14, 0x22
+	0x14, 0x1e, 0x22
 };
 
 static hda_nid_t stac92hd71bxx_pin_nids[10] = {
@@ -1220,24 +1223,48 @@ static struct snd_pci_quirk stac925x_cfg_tbl[] = {
 	{} /* terminator */
 };
 
-static unsigned int ref92hd73xx_pin_configs[12] = {
+static unsigned int ref92hd73xx_pin_configs[13] = {
 	0x02214030, 0x02a19040, 0x01a19020, 0x02214030,
 	0x0181302e, 0x01014010, 0x01014020, 0x01014030,
 	0x02319040, 0x90a000f0, 0x90a000f0, 0x01452050,
+	0x01452050,
+};
+
+static unsigned int dell_m6_pin_configs[13] = {
+	0x0321101f, 0x4f00000f, 0x4f0000f0, 0x90170110,
+	0x03a11020, 0x03011050, 0x4f0000f0, 0x4f0000f0,
+	0x4f0000f0, 0x90a60160, 0x4f0000f0, 0x4f0000f0,
+	0x4f0000f0,
 };
 
 static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = {
-	[STAC_92HD73XX_REF] = ref92hd73xx_pin_configs,
+	[STAC_92HD73XX_REF]	= ref92hd73xx_pin_configs,
+	[STAC_DELL_M6]	= dell_m6_pin_configs,
 };
 
 static const char *stac92hd73xx_models[STAC_92HD73XX_MODELS] = {
 	[STAC_92HD73XX_REF] = "ref",
+	[STAC_DELL_M6] = "dell-m6",
 };
 
 static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = {
 	/* SigmaTel reference board */
 	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
-		      "DFI LanParty", STAC_92HD73XX_REF),
+				"DFI LanParty", STAC_92HD73XX_REF),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0254,
+				"unknown Dell", STAC_DELL_M6),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0255,
+				"unknown Dell", STAC_DELL_M6),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0256,
+				"unknown Dell", STAC_DELL_M6),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0257,
+				"unknown Dell", STAC_DELL_M6),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x025e,
+				"unknown Dell", STAC_DELL_M6),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x025f,
+				"unknown Dell", STAC_DELL_M6),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0271,
+				"unknown Dell", STAC_DELL_M6),
 	{} /* terminator */
 };
 
@@ -1247,18 +1274,56 @@ static unsigned int ref92hd71bxx_pin_configs[10] = {
 	0x90a000f0, 0x01452050,
 };
 
+static unsigned int dell_m4_1_pin_configs[13] = {
+	0x0421101f, 0x04a11221, 0x40f000f0, 0x90170110,
+	0x23a1902e, 0x23014250, 0x40f000f0, 0x4f0000f0,
+	0x40f000f0, 0x4f0000f0,
+};
+
+static unsigned int dell_m4_2_pin_configs[13] = {
+	0x0421101f, 0x04a11221, 0x90a70330, 0x90170110,
+	0x23a1902e, 0x23014250, 0x40f000f0, 0x40f000f0,
+	0x40f000f0, 0x044413b0,
+};
+
 static unsigned int *stac92hd71bxx_brd_tbl[STAC_92HD71BXX_MODELS] = {
 	[STAC_92HD71BXX_REF] = ref92hd71bxx_pin_configs,
+	[STAC_DELL_M4_1]	= dell_m4_1_pin_configs,
+	[STAC_DELL_M4_2]	= dell_m4_2_pin_configs,
 };
 
 static const char *stac92hd71bxx_models[STAC_92HD71BXX_MODELS] = {
 	[STAC_92HD71BXX_REF] = "ref",
+	[STAC_DELL_M4_1] = "dell-m4-1",
+	[STAC_DELL_M4_2] = "dell-m4-2",
 };
 
 static struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = {
 	/* SigmaTel reference board */
 	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
 		      "DFI LanParty", STAC_92HD71BXX_REF),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0233,
+				"unknown Dell", STAC_DELL_M4_1),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0234,
+				"unknown Dell", STAC_DELL_M4_1),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0250,
+				"unknown Dell", STAC_DELL_M4_1),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x024f,
+				"unknown Dell", STAC_DELL_M4_1),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x024d,
+				"unknown Dell", STAC_DELL_M4_1),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0251,
+				"unknown Dell", STAC_DELL_M4_1),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0277,
+				"unknown Dell", STAC_DELL_M4_1),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0263,
+				"unknown Dell", STAC_DELL_M4_2),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0265,
+				"unknown Dell", STAC_DELL_M4_2),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0262,
+				"unknown Dell", STAC_DELL_M4_2),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0264,
+				"unknown Dell", STAC_DELL_M4_2),
 	{} /* terminator */
 };
 
@@ -3356,13 +3421,39 @@ again:
 
 	spec->num_muxes = ARRAY_SIZE(stac92hd73xx_mux_nids);
 	spec->num_adcs = ARRAY_SIZE(stac92hd73xx_adc_nids);
-	spec->num_dmics = STAC92HD73XX_NUM_DMICS;
 	spec->num_dmuxes = ARRAY_SIZE(stac92hd73xx_dmux_nids);
 	spec->dinput_mux = &stac92hd73xx_dmux;
 	/* GPIO0 High = Enable EAPD */
 	spec->gpio_mask = spec->gpio_dir = 0x1;
 	spec->gpio_data = 0x01;
 
+	switch (spec->board_config) {
+	case STAC_DELL_M6:
+		switch (codec->subsystem_id) {
+		case 0x1028025e: /* Analog Mics */
+		case 0x1028025f:
+			stac92xx_set_config_reg(codec, 0x0b, 0x90A70170);
+			spec->num_dmics = 0;
+			break;
+		case 0x10280254: /* Digital Mics */
+		case 0x10280255:
+		case 0x10280271:
+		case 0x10280272:
+			stac92xx_set_config_reg(codec, 0x13, 0x90A60160);
+			spec->num_dmics = 1;
+			break;
+		case 0x10280256: /* Both */
+		case 0x10280057:
+			stac92xx_set_config_reg(codec, 0x0b, 0x90A70170);
+			stac92xx_set_config_reg(codec, 0x13, 0x90A60160);
+			spec->num_dmics = 1;
+			break;
+		}
+		break;
+	default:
+		spec->num_dmics = STAC92HD73XX_NUM_DMICS;
+	}
+
 	spec->num_pwrs = ARRAY_SIZE(stac92hd73xx_pwr_nids);
 	spec->pwr_nids = stac92hd73xx_pwr_nids;
 
-- 
cgit v1.2.3-70-g09d2


From 03d7ca177fd2ecac8eb22f482f327ecaae4ac8cb Mon Sep 17 00:00:00 2001
From: Matthew Ranostay <mranostay@embeddedalley.com>
Date: Thu, 21 Feb 2008 07:51:46 +0100
Subject: [ALSA] hda: STAC927x analog mic

Some laptops have a internal analog microphone that is not setup by the BIOS.

Signed-off-by: Matthew Ranostay <mranostay@embeddedalley.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_sigmatel.c | 2 ++
 1 file changed, 2 insertions(+)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index a0c290cef76..314ea51538b 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -3721,6 +3721,8 @@ static int patch_stac927x(struct hda_codec *codec)
 		spec->mixer = stac927x_mixer;
 		break;
 	case STAC_DELL_BIOS:
+		/* configure the analog microphone on some laptops */
+		stac92xx_set_config_reg(codec, 0x0c, 0x90a79130);
 		/* correct the front output jack as a hp out */
 		stac92xx_set_config_reg(codec, 0x0f, 0x0227011f);
 		/* correct the front input jack as a mic */
-- 
cgit v1.2.3-70-g09d2


From 53463a8302d0c3148c4c64c034312215e76429c2 Mon Sep 17 00:00:00 2001
From: Ahmet Ä°nan <ainan at>
Date: Thu, 21 Feb 2008 07:55:30 +0100
Subject: [ALSA] snd-dummy - improved timing, silence on prepare
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Ahmet Ä°nan <ainan <at> mathematik.uni-freiburg.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/drivers/dummy.c | 26 +++++++++++++++-----------
 1 file changed, 15 insertions(+), 11 deletions(-)

(limited to 'sound')

diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index a240eaeb5c6..f67f65829f3 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -181,10 +181,10 @@ struct snd_dummy_pcm {
 	struct snd_dummy *dummy;
 	spinlock_t lock;
 	struct timer_list timer;
-	unsigned int pcm_size;
-	unsigned int pcm_count;
+	unsigned int pcm_buffer_size;
+	unsigned int pcm_period_size;
 	unsigned int pcm_bps;		/* bytes per second */
-	unsigned int pcm_jiffie;	/* bytes per one jiffie */
+	unsigned int pcm_hz;		/* HZ */
 	unsigned int pcm_irq_pos;	/* IRQ position */
 	unsigned int pcm_buf_pos;	/* position in buffer */
 	struct snd_pcm_substream *substream;
@@ -238,11 +238,15 @@ static int snd_card_dummy_pcm_prepare(struct snd_pcm_substream *substream)
 	if (bps <= 0)
 		return -EINVAL;
 	dpcm->pcm_bps = bps;
-	dpcm->pcm_jiffie = bps / HZ;
-	dpcm->pcm_size = snd_pcm_lib_buffer_bytes(substream);
-	dpcm->pcm_count = snd_pcm_lib_period_bytes(substream);
+	dpcm->pcm_hz = HZ;
+	dpcm->pcm_buffer_size = snd_pcm_lib_buffer_bytes(substream);
+	dpcm->pcm_period_size = snd_pcm_lib_period_bytes(substream);
 	dpcm->pcm_irq_pos = 0;
 	dpcm->pcm_buf_pos = 0;
+
+	snd_pcm_format_set_silence(runtime->format, runtime->dma_area,
+			bytes_to_samples(runtime, runtime->dma_bytes));
+
 	return 0;
 }
 
@@ -254,11 +258,11 @@ static void snd_card_dummy_pcm_timer_function(unsigned long data)
 	spin_lock_irqsave(&dpcm->lock, flags);
 	dpcm->timer.expires = 1 + jiffies;
 	add_timer(&dpcm->timer);
-	dpcm->pcm_irq_pos += dpcm->pcm_jiffie;
-	dpcm->pcm_buf_pos += dpcm->pcm_jiffie;
-	dpcm->pcm_buf_pos %= dpcm->pcm_size;
-	if (dpcm->pcm_irq_pos >= dpcm->pcm_count) {
-		dpcm->pcm_irq_pos %= dpcm->pcm_count;
+	dpcm->pcm_irq_pos += dpcm->pcm_bps;
+	if (dpcm->pcm_irq_pos >= dpcm->pcm_period_size * dpcm->pcm_hz) {
+		dpcm->pcm_irq_pos %= dpcm->pcm_period_size * dpcm->pcm_hz;
+		dpcm->pcm_buf_pos += dpcm->pcm_period_size;
+		dpcm->pcm_buf_pos %= dpcm->pcm_buffer_size;
 		spin_unlock_irqrestore(&dpcm->lock, flags);
 		snd_pcm_period_elapsed(dpcm->substream);
 	} else
-- 
cgit v1.2.3-70-g09d2


From 87218e9c6e7f7908baf98030b6d724e14aa8b5cd Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Thu, 21 Feb 2008 08:13:11 +0100
Subject: [ALSA] hda-intel - Use PCI_DEVICE() macro

Clean up the pci id table using PCI_DEVICE() macro.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/hda_intel.c | 98 +++++++++++++++++++++++++----------------------
 1 file changed, 53 insertions(+), 45 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index cf1a1d0124f..c495ca01294 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -2017,51 +2017,59 @@ static void __devexit azx_remove(struct pci_dev *pci)
 
 /* PCI IDs */
 static struct pci_device_id azx_ids[] = {
-	{ 0x8086, 0x2668, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH6 */
-	{ 0x8086, 0x27d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH7 */
-	{ 0x8086, 0x269a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ESB2 */
-	{ 0x8086, 0x284b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH8 */
-	{ 0x8086, 0x293e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH9 */
-	{ 0x8086, 0x293f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH9 */
-	{ 0x8086, 0x3a3e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH10 */
-	{ 0x8086, 0x3a6e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH10 */
-	{ 0x8086, 0x811b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_SCH }, /* SCH*/
-	{ 0x1002, 0x437b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB450 */
-	{ 0x1002, 0x4383, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB600 */
-	{ 0x1002, 0x793b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RS600 HDMI */
-	{ 0x1002, 0x7919, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RS690 HDMI */
-	{ 0x1002, 0x960f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RS780 HDMI */
-	{ 0x1002, 0xaa00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI R600 HDMI */
-	{ 0x1002, 0xaa08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RV630 HDMI */
-	{ 0x1002, 0xaa10, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RV610 HDMI */
-	{ 0x1002, 0xaa18, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RV670 HDMI */
-	{ 0x1002, 0xaa20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RV635 HDMI */
-	{ 0x1002, 0xaa28, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RV620 HDMI */
-	{ 0x1002, 0xaa30, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RV770 HDMI */
-	{ 0x1002, 0xaa38, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RV730 HDMI */
-	{ 0x1002, 0xaa40, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RV710 HDMI */
-	{ 0x1002, 0xaa48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RV740 HDMI */
-	{ 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_VIA }, /* VIA VT8251/VT8237A */
-	{ 0x1039, 0x7502, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_SIS }, /* SIS966 */
-	{ 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ULI }, /* ULI M5461 */
-	{ 0x10de, 0x026c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP51 */
-	{ 0x10de, 0x0371, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP55 */
-	{ 0x10de, 0x03e4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP61 */
-	{ 0x10de, 0x03f0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP61 */
-	{ 0x10de, 0x044a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP65 */
-	{ 0x10de, 0x044b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP65 */
-	{ 0x10de, 0x055c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP67 */
-	{ 0x10de, 0x055d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP67 */
-	{ 0x10de, 0x07fc, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP73 */
-	{ 0x10de, 0x07fd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP73 */
-	{ 0x10de, 0x0774, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */
-	{ 0x10de, 0x0775, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */
-	{ 0x10de, 0x0776, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */
-	{ 0x10de, 0x0777, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */
-	{ 0x10de, 0x0ac0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP79 */
-	{ 0x10de, 0x0ac1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP79 */
-	{ 0x10de, 0x0ac2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP79 */
-	{ 0x10de, 0x0ac3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP79 */
+	/* ICH 6..10 */
+	{ PCI_DEVICE(0x8086, 0x2668), .driver_data = AZX_DRIVER_ICH },
+	{ PCI_DEVICE(0x8086, 0x27d8), .driver_data = AZX_DRIVER_ICH },
+	{ PCI_DEVICE(0x8086, 0x269a), .driver_data = AZX_DRIVER_ICH },
+	{ PCI_DEVICE(0x8086, 0x284b), .driver_data = AZX_DRIVER_ICH },
+	{ PCI_DEVICE(0x8086, 0x293e), .driver_data = AZX_DRIVER_ICH },
+	{ PCI_DEVICE(0x8086, 0x293f), .driver_data = AZX_DRIVER_ICH },
+	{ PCI_DEVICE(0x8086, 0x3a3e), .driver_data = AZX_DRIVER_ICH },
+	{ PCI_DEVICE(0x8086, 0x3a6e), .driver_data = AZX_DRIVER_ICH },
+	/* SCH */
+	{ PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH },
+	/* ATI SB 450/600 */
+	{ PCI_DEVICE(0x1002, 0x437b), .driver_data = AZX_DRIVER_ATI },
+	{ PCI_DEVICE(0x1002, 0x4383), .driver_data = AZX_DRIVER_ATI },
+	/* ATI HDMI */
+	{ PCI_DEVICE(0x1002, 0x793b), .driver_data = AZX_DRIVER_ATIHDMI },
+	{ PCI_DEVICE(0x1002, 0x7919), .driver_data = AZX_DRIVER_ATIHDMI },
+	{ PCI_DEVICE(0x1002, 0x960f), .driver_data = AZX_DRIVER_ATIHDMI },
+	{ PCI_DEVICE(0x1002, 0xaa00), .driver_data = AZX_DRIVER_ATIHDMI },
+	{ PCI_DEVICE(0x1002, 0xaa08), .driver_data = AZX_DRIVER_ATIHDMI },
+	{ PCI_DEVICE(0x1002, 0xaa10), .driver_data = AZX_DRIVER_ATIHDMI },
+	{ PCI_DEVICE(0x1002, 0xaa18), .driver_data = AZX_DRIVER_ATIHDMI },
+	{ PCI_DEVICE(0x1002, 0xaa20), .driver_data = AZX_DRIVER_ATIHDMI },
+	{ PCI_DEVICE(0x1002, 0xaa28), .driver_data = AZX_DRIVER_ATIHDMI },
+	{ PCI_DEVICE(0x1002, 0xaa30), .driver_data = AZX_DRIVER_ATIHDMI },
+	{ PCI_DEVICE(0x1002, 0xaa38), .driver_data = AZX_DRIVER_ATIHDMI },
+	{ PCI_DEVICE(0x1002, 0xaa40), .driver_data = AZX_DRIVER_ATIHDMI },
+	{ PCI_DEVICE(0x1002, 0xaa48), .driver_data = AZX_DRIVER_ATIHDMI },
+	/* VIA VT8251/VT8237A */
+	{ PCI_DEVICE(0x1106, 0x3288), .driver_data = AZX_DRIVER_VIA },
+	/* SIS966 */
+	{ PCI_DEVICE(0x1039, 0x7502), .driver_data = AZX_DRIVER_SIS },
+	/* ULI M5461 */
+	{ PCI_DEVICE(0x10b9, 0x5461), .driver_data = AZX_DRIVER_ULI },
+	/* NVIDIA MCP */
+	{ PCI_DEVICE(0x10de, 0x026c), .driver_data = AZX_DRIVER_NVIDIA },
+	{ PCI_DEVICE(0x10de, 0x0371), .driver_data = AZX_DRIVER_NVIDIA },
+	{ PCI_DEVICE(0x10de, 0x03e4), .driver_data = AZX_DRIVER_NVIDIA },
+	{ PCI_DEVICE(0x10de, 0x03f0), .driver_data = AZX_DRIVER_NVIDIA },
+	{ PCI_DEVICE(0x10de, 0x044a), .driver_data = AZX_DRIVER_NVIDIA },
+	{ PCI_DEVICE(0x10de, 0x044b), .driver_data = AZX_DRIVER_NVIDIA },
+	{ PCI_DEVICE(0x10de, 0x055c), .driver_data = AZX_DRIVER_NVIDIA },
+	{ PCI_DEVICE(0x10de, 0x055d), .driver_data = AZX_DRIVER_NVIDIA },
+	{ PCI_DEVICE(0x10de, 0x0774), .driver_data = AZX_DRIVER_NVIDIA },
+	{ PCI_DEVICE(0x10de, 0x0775), .driver_data = AZX_DRIVER_NVIDIA },
+	{ PCI_DEVICE(0x10de, 0x0776), .driver_data = AZX_DRIVER_NVIDIA },
+	{ PCI_DEVICE(0x10de, 0x0777), .driver_data = AZX_DRIVER_NVIDIA },
+	{ PCI_DEVICE(0x10de, 0x07fc), .driver_data = AZX_DRIVER_NVIDIA },
+	{ PCI_DEVICE(0x10de, 0x07fd), .driver_data = AZX_DRIVER_NVIDIA },
+	{ PCI_DEVICE(0x10de, 0x0ac0), .driver_data = AZX_DRIVER_NVIDIA },
+	{ PCI_DEVICE(0x10de, 0x0ac1), .driver_data = AZX_DRIVER_NVIDIA },
+	{ PCI_DEVICE(0x10de, 0x0ac2), .driver_data = AZX_DRIVER_NVIDIA },
+	{ PCI_DEVICE(0x10de, 0x0ac3), .driver_data = AZX_DRIVER_NVIDIA },
 	{ 0, }
 };
 MODULE_DEVICE_TABLE(pci, azx_ids);
-- 
cgit v1.2.3-70-g09d2


From c354cd7d9627930dcfbcff8355d422fa1bca948a Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Thu, 21 Feb 2008 12:40:00 +0100
Subject: [ALSA] seq-oss - Remove invalid BUG()

Removed invalid BUG() - the driver should handle the error case properly
rather than issuing BUG().

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/core/seq/oss/seq_oss_synth.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

(limited to 'sound')

diff --git a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c
index ab570a0a618..558dadbf45f 100644
--- a/sound/core/seq/oss/seq_oss_synth.c
+++ b/sound/core/seq/oss/seq_oss_synth.c
@@ -245,8 +245,13 @@ snd_seq_oss_synth_setup(struct seq_oss_devinfo *dp)
 		info->nr_voices = rec->nr_voices;
 		if (info->nr_voices > 0) {
 			info->ch = kcalloc(info->nr_voices, sizeof(struct seq_oss_chinfo), GFP_KERNEL);
-			if (!info->ch)
-				BUG();
+			if (!info->ch) {
+				snd_printk(KERN_ERR "Cannot malloc\n");
+				rec->oper.close(&info->arg);
+				module_put(rec->oper.owner);
+				snd_use_lock_free(&rec->use_lock);
+				continue;
+			}
 			reset_channels(info);
 		}
 		debug_printk(("synth %d assigned\n", i));
-- 
cgit v1.2.3-70-g09d2


From ae0afd81b34ce287ffda7dd4e33b5144de2ad39d Mon Sep 17 00:00:00 2001
From: Matthew Ranostay <mranostay@embeddedalley.com>
Date: Fri, 22 Feb 2008 17:55:05 +0100
Subject: [ALSA] hda: Mic as output fix

Added logic to check if AUTO_PIN_FRONT_MIC is available for output
switch, if AUTO_PIN_MIC isn't.

Signed-off-by: Matthew Ranostay <mranostay@embeddedalley.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_sigmatel.c | 58 ++++++++++++++++++++++++------------------
 1 file changed, 33 insertions(+), 25 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 314ea51538b..ef86402d7e6 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -2307,6 +2307,29 @@ static int create_controls(struct sigmatel_spec *spec, const char *pfx, hda_nid_
 	return 0;
 }
 
+static int add_spec_dacs(struct sigmatel_spec *spec, hda_nid_t nid)
+{
+	if (!spec->multiout.hp_nid)
+		spec->multiout.hp_nid = nid;
+	else if (spec->multiout.num_dacs > 4) {
+		printk(KERN_WARNING "stac92xx: No space for DAC 0x%x\n", nid);
+		return 1;
+	} else {
+		spec->multiout.dac_nids[spec->multiout.num_dacs] = nid;
+		spec->multiout.num_dacs++;
+	}
+	return 0;
+}
+
+static int check_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid)
+{
+	if (is_in_dac_nids(spec, nid))
+		return 1;
+	if (spec->multiout.hp_nid == nid)
+		return 1;
+	return 0;
+}
+
 /* add playback controls from the parsed DAC table */
 static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
 					       const struct auto_pin_cfg *cfg)
@@ -2369,10 +2392,11 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
 
 	if (spec->mic_switch) {
 		unsigned int def_conf;
-		nid = cfg->input_pins[AUTO_PIN_MIC];
+		unsigned int mic_pin = AUTO_PIN_MIC;
+again:
+		nid = cfg->input_pins[mic_pin];
 		def_conf = snd_hda_codec_read(codec, nid, 0,
 						AC_VERB_GET_CONFIG_DEFAULT, 0);
-
 		/* some laptops have an internal analog microphone
 		 * which can't be used as a output */
 		if (get_defcfg_connect(def_conf) != AC_JACK_PORT_FIXED) {
@@ -2382,38 +2406,22 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
 				err = stac92xx_add_control(spec,
 					STAC_CTL_WIDGET_IO_SWITCH,
 					"Mic as Output Switch", (nid << 8) | 1);
+				nid = snd_hda_codec_read(codec, nid, 0,
+					 AC_VERB_GET_CONNECT_LIST, 0) & 0xff;
+				if (!check_in_dac_nids(spec, nid))
+					add_spec_dacs(spec, nid);
 				if (err < 0)
 					return err;
 			}
+		} else if (mic_pin == AUTO_PIN_MIC) {
+			mic_pin = AUTO_PIN_FRONT_MIC;
+			goto again;
 		}
 	}
 
 	return 0;
 }
 
-static int check_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid)
-{
-	if (is_in_dac_nids(spec, nid))
-		return 1;
-	if (spec->multiout.hp_nid == nid)
-		return 1;
-	return 0;
-}
-
-static int add_spec_dacs(struct sigmatel_spec *spec, hda_nid_t nid)
-{
-	if (!spec->multiout.hp_nid)
-		spec->multiout.hp_nid = nid;
-	else if (spec->multiout.num_dacs > 4) {
-		printk(KERN_WARNING "stac92xx: No space for DAC 0x%x\n", nid);
-		return 1;
-	} else {
-		spec->multiout.dac_nids[spec->multiout.num_dacs] = nid;
-		spec->multiout.num_dacs++;
-	}
-	return 0;
-}
-
 /* add playback controls for Speaker and HP outputs */
 static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec,
 					struct auto_pin_cfg *cfg)
-- 
cgit v1.2.3-70-g09d2


From 47ba97f8fa01bb5b48e73b4b1271fbf1436a2d4b Mon Sep 17 00:00:00 2001
From: Remy Bruno <remy.bruno@trinnov.com>
Date: Fri, 22 Feb 2008 17:57:02 +0100
Subject: [ALSA] hdsp - RME 9632 fix at 192kHz

The bits indicating SPDIF frequency in the status register are not the same for
the 9632 than for the other cards, because it also supports 192kHz. A specific
bitmask has thus been added (used in hdsp_spdif_sample_rate()).
The 9632 does not seem to report external sample rates greater than 96kHz. In
this case, the best seems to report spdif rate when autosync reference is
spdif. This also required to move function hdsp_spdif_sample_rate().

Signed-off-by: Remy Bruno <remy.bruno@trinnov.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/rme9652/hdsp.c | 54 ++++++++++++++++++++++++++++++++----------------
 1 file changed, 36 insertions(+), 18 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index 1be84f22d0d..4d6fbb36ab8 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -318,6 +318,10 @@ MODULE_FIRMWARE("digiface_firmware_rev11.bin");
 #define HDSP_midi1IRQPending    (1<<31)
 
 #define HDSP_spdifFrequencyMask    (HDSP_spdifFrequency0|HDSP_spdifFrequency1|HDSP_spdifFrequency2)
+#define HDSP_spdifFrequencyMask_9632 (HDSP_spdifFrequency0|\
+				      HDSP_spdifFrequency1|\
+				      HDSP_spdifFrequency2|\
+				      HDSP_spdifFrequency3)
 
 #define HDSP_spdifFrequency32KHz   (HDSP_spdifFrequency0)
 #define HDSP_spdifFrequency44_1KHz (HDSP_spdifFrequency1)
@@ -328,7 +332,9 @@ MODULE_FIRMWARE("digiface_firmware_rev11.bin");
 #define HDSP_spdifFrequency96KHz   (HDSP_spdifFrequency2|HDSP_spdifFrequency1)
 
 /* This is for H9632 cards */
-#define HDSP_spdifFrequency128KHz   HDSP_spdifFrequencyMask
+#define HDSP_spdifFrequency128KHz   (HDSP_spdifFrequency0|\
+				     HDSP_spdifFrequency1|\
+				     HDSP_spdifFrequency2)
 #define HDSP_spdifFrequency176_4KHz HDSP_spdifFrequency3
 #define HDSP_spdifFrequency192KHz   (HDSP_spdifFrequency3|HDSP_spdifFrequency0)
 
@@ -885,28 +891,15 @@ static int snd_hdsp_use_is_exclusive(struct hdsp *hdsp)
 	return ret;
 }
 
-static int hdsp_external_sample_rate (struct hdsp *hdsp)
-{
-	unsigned int status2 = hdsp_read(hdsp, HDSP_status2Register);
-	unsigned int rate_bits = status2 & HDSP_systemFrequencyMask;
-
-	switch (rate_bits) {
-	case HDSP_systemFrequency32:   return 32000;
-	case HDSP_systemFrequency44_1: return 44100;
-	case HDSP_systemFrequency48:   return 48000;
-	case HDSP_systemFrequency64:   return 64000;
-	case HDSP_systemFrequency88_2: return 88200;
-	case HDSP_systemFrequency96:   return 96000;
-	default:
-		return 0;
-	}
-}
-
 static int hdsp_spdif_sample_rate(struct hdsp *hdsp)
 {
 	unsigned int status = hdsp_read(hdsp, HDSP_statusRegister);
 	unsigned int rate_bits = (status & HDSP_spdifFrequencyMask);
 
+	/* For the 9632, the mask is different */
+	if (hdsp->io_type == H9632)
+		 rate_bits = (status & HDSP_spdifFrequencyMask_9632);
+
 	if (status & HDSP_SPDIFErrorFlag)
 		return 0;
 	
@@ -933,6 +926,31 @@ static int hdsp_spdif_sample_rate(struct hdsp *hdsp)
 	return 0;
 }
 
+static int hdsp_external_sample_rate(struct hdsp *hdsp)
+{
+	unsigned int status2 = hdsp_read(hdsp, HDSP_status2Register);
+	unsigned int rate_bits = status2 & HDSP_systemFrequencyMask;
+
+	/* For the 9632 card, there seems to be no bit for indicating external
+	 * sample rate greater than 96kHz. The card reports the corresponding
+	 * single speed. So the best means seems to get spdif rate when
+	 * autosync reference is spdif */
+	if (hdsp->io_type == H9632 &&
+	    hdsp_autosync_ref(hdsp) == HDSP_AUTOSYNC_FROM_SPDIF)
+		 return hdsp_spdif_sample_rate(hdsp);
+
+	switch (rate_bits) {
+	case HDSP_systemFrequency32:   return 32000;
+	case HDSP_systemFrequency44_1: return 44100;
+	case HDSP_systemFrequency48:   return 48000;
+	case HDSP_systemFrequency64:   return 64000;
+	case HDSP_systemFrequency88_2: return 88200;
+	case HDSP_systemFrequency96:   return 96000;
+	default:
+		return 0;
+	}
+}
+
 static void hdsp_compute_period_size(struct hdsp *hdsp)
 {
 	hdsp->period_bytes = 1 << ((hdsp_decode_latency(hdsp->control_register) + 8));
-- 
cgit v1.2.3-70-g09d2


From ea6b5828cdbbedaf26b12ae64befbec18084ea3c Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Mon, 25 Feb 2008 10:59:52 +0100
Subject: [ALSA] mpu401: reduce tx loop timeout

Reduce the number of times to check for a non-empty Tx FIFO from 100 to
2 because there is no MPU-401 implementation that needs more than one or
two reads to determine the actual FIFO status.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
---
 sound/drivers/mpu401/mpu401_uart.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

(limited to 'sound')

diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c
index 5993864acbd..dd6ec426673 100644
--- a/sound/drivers/mpu401/mpu401_uart.c
+++ b/sound/drivers/mpu401/mpu401_uart.c
@@ -425,16 +425,17 @@ static void snd_mpu401_uart_input_read(struct snd_mpu401 * mpu)
 static void snd_mpu401_uart_output_write(struct snd_mpu401 * mpu)
 {
 	unsigned char byte;
-	int max = 256, timeout;
+	int max = 256;
 
 	do {
 		if (snd_rawmidi_transmit_peek(mpu->substream_output,
 					      &byte, 1) == 1) {
-			for (timeout = 100; timeout > 0; timeout--) {
-				if (snd_mpu401_output_ready(mpu))
-					break;
-			}
-			if (timeout == 0)
+			/*
+			 * Try twice because there is hardware that insists on
+			 * setting the output busy bit after each write.
+			 */
+			if (!snd_mpu401_output_ready(mpu) &&
+			    !snd_mpu401_output_ready(mpu))
 				break;	/* Tx FIFO full - try again later */
 			mpu->write(mpu, byte, MPU401D(mpu));
 			snd_rawmidi_transmit_ack(mpu->substream_output, 1);
-- 
cgit v1.2.3-70-g09d2


From 25a47b6b01314f027553d231c1a67dee27ff02b0 Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Mon, 25 Feb 2008 11:04:19 +0100
Subject: [ALSA] usb-audio: sort quirks list

Move some entries to their proper position so that the list is again
sorted by vendor/product ID.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
---
 sound/usb/usbquirks.h | 75 ++++++++++++++++++++++++++-------------------------
 1 file changed, 38 insertions(+), 37 deletions(-)

(limited to 'sound')

diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h
index 938dff5f9ce..82a8d14c26a 100644
--- a/sound/usb/usbquirks.h
+++ b/sound/usb/usbquirks.h
@@ -39,6 +39,30 @@
 	.idProduct = prod, \
 	.bInterfaceClass = USB_CLASS_VENDOR_SPEC
 
+/* Creative/E-Mu devices */
+{
+	USB_DEVICE(0x041e, 0x3010),
+	.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+		.vendor_name = "Creative Labs",
+		.product_name = "Sound Blaster MP3+",
+		.ifnum = QUIRK_NO_INTERFACE
+	}
+},
+{
+	/* E-Mu 0202 USB */
+	.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor = 0x041e,
+	.idProduct = 0x3f02,
+	.bInterfaceClass = USB_CLASS_AUDIO,
+},
+{
+	/* E-Mu 0404 USB */
+	.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor = 0x041e,
+	.idProduct = 0x3f04,
+	.bInterfaceClass = USB_CLASS_AUDIO,
+},
+
 /*
  * Logitech QuickCam: bDeviceClass is vendor-specific, so generic interface
  * class matches do not take effect without an explicit ID match.
@@ -97,19 +121,7 @@
 	.bInterfaceClass = USB_CLASS_AUDIO,
 	.bInterfaceSubClass = USB_SUBCLASS_AUDIO_CONTROL
 },
-/* E-Mu devices */
-{
-	.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
-	.idVendor = 0x041e,
-	.idProduct = 0x3f02,
-	.bInterfaceClass = USB_CLASS_AUDIO,
-},
-{
-	.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
-	.idVendor = 0x041e,
-	.idProduct = 0x3f04,
-	.bInterfaceClass = USB_CLASS_AUDIO,
-},
+
 /*
  * Yamaha devices
  */
@@ -1165,19 +1177,6 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 		}
 	}
 },
-{
-	USB_DEVICE(0x582, 0x00a6),
-	.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
-		.vendor_name = "Roland",
-		.product_name = "Juno-G",
-		.ifnum = 0,
-		.type = QUIRK_MIDI_FIXED_ENDPOINT,
-		.data = & (const struct snd_usb_midi_endpoint_info) {
-			.out_cables = 0x0001,
-			.in_cables  = 0x0001
-		}
-	}
-},
 {	/*
 	 * This quirk is for the "Advanced" modes of the Edirol UA-25.
 	 * If the switch is not in an advanced setting, the UA-25 has
@@ -1335,6 +1334,19 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 	}
 },
 	/* TODO: add Edirol MD-P1 support */
+{
+	USB_DEVICE(0x582, 0x00a6),
+	.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+		.vendor_name = "Roland",
+		.product_name = "Juno-G",
+		.ifnum = 0,
+		.type = QUIRK_MIDI_FIXED_ENDPOINT,
+		.data = & (const struct snd_usb_midi_endpoint_info) {
+			.out_cables = 0x0001,
+			.in_cables  = 0x0001
+		}
+	}
+},
 {
 	/* Roland SH-201 */
 	USB_DEVICE(0x0582, 0x00ad),
@@ -1719,17 +1731,6 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 	}
 },
 
-{
-	/* Creative Sound Blaster MP3+ */
-	USB_DEVICE(0x041e, 0x3010),
-	.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
-		.vendor_name = "Creative Labs",
-		.product_name = "Sound Blaster MP3+",
-		.ifnum = QUIRK_NO_INTERFACE
-	}
-	
-},
-
 /* Emagic devices */
 {
 	USB_DEVICE(0x086a, 0x0001),
-- 
cgit v1.2.3-70-g09d2


From aea7bb0a6ff5e751ef611ba9c1146c3c8489f25e Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 25 Feb 2008 18:26:41 +0100
Subject: [ALSA] hda-codec - Fix initial DAC numbers of 92HD71bxx codecs

Fix the initial num_dacs of 92HD71bxx codecs.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_sigmatel.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index ef86402d7e6..4bc7d8646fa 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -246,7 +246,7 @@ static hda_nid_t stac92hd71bxx_dmux_nids[1] = {
 	0x1c,
 };
 
-static hda_nid_t stac92hd71bxx_dac_nids[2] = {
+static hda_nid_t stac92hd71bxx_dac_nids[1] = {
 	0x10, /*0x11, */
 };
 
@@ -3550,7 +3550,7 @@ again:
 	spec->num_pwrs = ARRAY_SIZE(stac92hd71bxx_pwr_nids);
 	spec->pwr_nids = stac92hd71bxx_pwr_nids;
 
-	spec->multiout.num_dacs = 2;
+	spec->multiout.num_dacs = 1;
 	spec->multiout.hp_nid = 0x11;
 	spec->multiout.dac_nids = stac92hd71bxx_dac_nids;
 
-- 
cgit v1.2.3-70-g09d2


From b26451c059e741ec5e3389f7758627cb094b3766 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Tue, 26 Feb 2008 11:56:35 +0100
Subject: [ALSA] hda-codec - Add docking-station mic input for Thinkpad X61

Added the docking-stationc mic input to the capture source list
for Thinkpad X61.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_analog.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index e0f3559f8b1..20446e320b2 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -3188,11 +3188,12 @@ static int patch_ad1884(struct hda_codec *codec)
  * Lenovo Thinkpad T61/X61
  */
 static struct hda_input_mux ad1984_thinkpad_capture_source = {
-	.num_items = 3,
+	.num_items = 4,
 	.items = {
 		{ "Mic", 0x0 },
 		{ "Internal Mic", 0x1 },
 		{ "Mix", 0x3 },
+		{ "Docking-Station", 0x4 },
 	},
 };
 
-- 
cgit v1.2.3-70-g09d2


From 964a788e0ba64aa4ce2e6488718f3ee28cc2e61e Mon Sep 17 00:00:00 2001
From: Mark Brown <broonie@opensource.wolfsonmicro.com>
Date: Tue, 26 Feb 2008 13:16:08 +0100
Subject: [ALSA] soc - Report errors from snd_soc_dapm_set_endpoint()

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/soc/soc-dapm.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'sound')

diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 620d7ea3c15..abac6847eca 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -1334,10 +1334,11 @@ int snd_soc_dapm_set_endpoint(struct snd_soc_codec *codec,
 	list_for_each_entry(w, &codec->dapm_widgets, list) {
 		if (!strcmp(w->name, endpoint)) {
 			w->connected = status;
+			return 0;
 		}
 	}
 
-	return 0;
+	return -ENODEV;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_set_endpoint);
 
-- 
cgit v1.2.3-70-g09d2


From 7dfa31ed5e1fc0ace7f1959b9564ad43d78fd7af Mon Sep 17 00:00:00 2001
From: Harvey Harrison <harvey.harrison@gmail.com>
Date: Thu, 28 Feb 2008 11:52:17 +0100
Subject: [ALSA] sound: cmipci.c fix shadowed variable warning

A temporary variable for each mixer element is used in an initialization
loop, use the name elem_id.

sound/pci/cmipci.c:2747:26: warning: symbol 'id' shadows an earlier one
sound/pci/cmipci.c:56:13: originally declared here

[tiwai - fixed a coding style issue as well]

Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/cmipci.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
index 135f3086075..4074584a7d9 100644
--- a/sound/pci/cmipci.c
+++ b/sound/pci/cmipci.c
@@ -2744,12 +2744,13 @@ static int __devinit snd_cmipci_mixer_new(struct cmipci *cm, int pcm_spdif_devic
 	}
 
 	for (idx = 0; idx < CM_SAVED_MIXERS; idx++) {
-		struct snd_ctl_elem_id id;
+		struct snd_ctl_elem_id elem_id;
 		struct snd_kcontrol *ctl;
-		memset(&id, 0, sizeof(id));
-		id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
-		strcpy(id.name, cm_saved_mixer[idx].name);
-		if ((ctl = snd_ctl_find_id(cm->card, &id)) != NULL)
+		memset(&elem_id, 0, sizeof(elem_id));
+		elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+		strcpy(elem_id.name, cm_saved_mixer[idx].name);
+		ctl = snd_ctl_find_id(cm->card, &elem_id);
+		if (ctl)
 			cm->mixer_res_ctl[idx] = ctl;
 	}
 
-- 
cgit v1.2.3-70-g09d2


From 405b0a377cfe3750f4af54b80d0402c3fe777b87 Mon Sep 17 00:00:00 2001
From: Harvey Harrison <harvey.harrison@gmail.com>
Date: Thu, 28 Feb 2008 11:53:07 +0100
Subject: [ALSA] sound: ens1370.c fix shadowed variable warning

index is incremented only when AC97_EI_SPDIF and then assigned to
the index field.  Change the temporary name to is_spdif.

sound/pci/ens1370.c:1638:10: warning: symbol 'index' shadows an earlier one
sound/pci/ens1370.c:84:12: originally declared here

Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/ens1370.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index 72d85a5ae6a..52fae4a7cfd 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -1635,20 +1635,20 @@ static int __devinit snd_ensoniq_1371_mixer(struct ensoniq *ensoniq,
 	if (has_spdif > 0 ||
 	    (!has_spdif && es1371_quirk_lookup(ensoniq, es1371_spdif_present))) {
 		struct snd_kcontrol *kctl;
-		int i, index = 0;
+		int i, is_spdif = 0;
 
 		ensoniq->spdif_default = ensoniq->spdif_stream =
 			SNDRV_PCM_DEFAULT_CON_SPDIF;
 		outl(ensoniq->spdif_default, ES_REG(ensoniq, CHANNEL_STATUS));
 
 		if (ensoniq->u.es1371.ac97->ext_id & AC97_EI_SPDIF)
-			index++;
+			is_spdif++;
 
 		for (i = 0; i < ARRAY_SIZE(snd_es1371_mixer_spdif); i++) {
 			kctl = snd_ctl_new1(&snd_es1371_mixer_spdif[i], ensoniq);
 			if (!kctl)
 				return -ENOMEM;
-			kctl->id.index = index;
+			kctl->id.index = is_spdif;
 			err = snd_ctl_add(card, kctl);
 			if (err < 0)
 				return err;
-- 
cgit v1.2.3-70-g09d2


From 3463d8fa14ba2e00ede9894efdaa65189eb04b36 Mon Sep 17 00:00:00 2001
From: Harvey Harrison <harvey.harrison@gmail.com>
Date: Thu, 28 Feb 2008 11:53:41 +0100
Subject: [ALSA] sound: es1968.c fox shadowed variable warning

id is used when initializing the mixer elements, use elem_id here
instead.
sound/pci/es1968.c:1963:25: warning: symbol 'id' shadows an earlier one
sound/pci/es1968.c:129:13: originally declared here

Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/es1968.c | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index 7d911a18c08..67f03264f87 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -1972,7 +1972,7 @@ snd_es1968_mixer(struct es1968 *chip)
 {
 	struct snd_ac97_bus *pbus;
 	struct snd_ac97_template ac97;
-	struct snd_ctl_elem_id id;
+	struct snd_ctl_elem_id elem_id;
 	int err;
 	static struct snd_ac97_bus_ops ops = {
 		.write = snd_es1968_ac97_write,
@@ -1989,14 +1989,14 @@ snd_es1968_mixer(struct es1968 *chip)
 		return err;
 
 	/* attach master switch / volumes for h/w volume control */
-	memset(&id, 0, sizeof(id));
-	id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
-	strcpy(id.name, "Master Playback Switch");
-	chip->master_switch = snd_ctl_find_id(chip->card, &id);
-	memset(&id, 0, sizeof(id));
-	id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
-	strcpy(id.name, "Master Playback Volume");
-	chip->master_volume = snd_ctl_find_id(chip->card, &id);
+	memset(&elem_id, 0, sizeof(elem_id));
+	elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+	strcpy(elem_id.name, "Master Playback Switch");
+	chip->master_switch = snd_ctl_find_id(chip->card, &elem_id);
+	memset(&elem_id, 0, sizeof(elem_id));
+	elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+	strcpy(elem_id.name, "Master Playback Volume");
+	chip->master_volume = snd_ctl_find_id(chip->card, &elem_id);
 
 	return 0;
 }
-- 
cgit v1.2.3-70-g09d2


From 58e4334e82c0f4eb0147a905a127bd14f0ea0a2d Mon Sep 17 00:00:00 2001
From: Harvey Harrison <harvey.harrison@gmail.com>
Date: Thu, 28 Feb 2008 11:55:07 +0100
Subject: [ALSA] sound: fm801.c fix shadowed variable warning

id was only used as a counter in a for loop, move the declaration
to where it is used and change it to i.
sound/pci/fm801.c:1288:6: warning: symbol 'id' shadows an earlier one
sound/pci/fm801.c:51:13: originally declared here

[tiwai - fixed a coding style issue as well]

Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/fm801.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index 4c300e6149f..c129f9e2072 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -1285,7 +1285,6 @@ static int wait_for_codec(struct fm801 *chip, unsigned int codec_id,
 
 static int snd_fm801_chip_init(struct fm801 *chip, int resume)
 {
-	int id;
 	unsigned short cmdw;
 
 	if (chip->tea575x_tuner & 0x0010)
@@ -1310,13 +1309,14 @@ static int snd_fm801_chip_init(struct fm801 *chip, int resume)
 		} else {
 			/* my card has the secondary codec */
 			/* at address #3, so the loop is inverted */
-			for (id = 3; id > 0; id--) {
-				if (! wait_for_codec(chip, id, AC97_VENDOR_ID1,
+			int i;
+			for (i = 3; i > 0; i--) {
+				if (!wait_for_codec(chip, i, AC97_VENDOR_ID1,
 						     msecs_to_jiffies(50))) {
 					cmdw = inw(FM801_REG(chip, AC97_DATA));
 					if (cmdw != 0xffff && cmdw != 0) {
 						chip->secondary = 1;
-						chip->secondary_addr = id;
+						chip->secondary_addr = i;
 						break;
 					}
 				}
-- 
cgit v1.2.3-70-g09d2


From e37273d3484e241063fefb2611a0c93eb0d9ddbd Mon Sep 17 00:00:00 2001
From: Harvey Harrison <harvey.harrison@gmail.com>
Date: Thu, 28 Feb 2008 11:56:37 +0100
Subject: [ALSA] sound: maestro3.c fix shadowed variable warnings

change id to elem_id as it is used to initialize each mixer element
sound/pci/maestro3.c:2071:25: warning: symbol 'id' shadows an earlier one
sound/pci/maestro3.c:67:13: originally declared here

index is used in each of these places to count over the dsp's memory,
change to the name dsp_index
sound/pci/maestro3.c:2572:9: warning: symbol 'index' shadows an earlier one
sound/pci/maestro3.c:66:12: originally declared here
sound/pci/maestro3.c:2604:9: warning: symbol 'index' shadows an earlier one
sound/pci/maestro3.c:66:12: originally declared here

[tiwai - fixed coding style issues as well]

Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/maestro3.c | 34 +++++++++++++++++-----------------
 1 file changed, 17 insertions(+), 17 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index 04fa0a68416..a753dae65ab 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -2068,7 +2068,7 @@ static int __devinit snd_m3_mixer(struct snd_m3 *chip)
 {
 	struct snd_ac97_bus *pbus;
 	struct snd_ac97_template ac97;
-	struct snd_ctl_elem_id id;
+	struct snd_ctl_elem_id elem_id;
 	int err;
 	static struct snd_ac97_bus_ops ops = {
 		.write = snd_m3_ac97_write,
@@ -2088,14 +2088,14 @@ static int __devinit snd_m3_mixer(struct snd_m3 *chip)
 	schedule_timeout_uninterruptible(msecs_to_jiffies(100));
 	snd_ac97_write(chip->ac97, AC97_PCM, 0);
 
-	memset(&id, 0, sizeof(id));
-	id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
-	strcpy(id.name, "Master Playback Switch");
-	chip->master_switch = snd_ctl_find_id(chip->card, &id);
-	memset(&id, 0, sizeof(id));
-	id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
-	strcpy(id.name, "Master Playback Volume");
-	chip->master_volume = snd_ctl_find_id(chip->card, &id);
+	memset(&elem_id, 0, sizeof(elem_id));
+	elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+	strcpy(elem_id.name, "Master Playback Switch");
+	chip->master_switch = snd_ctl_find_id(chip->card, &elem_id);
+	memset(&elem_id, 0, sizeof(elem_id));
+	elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+	strcpy(elem_id.name, "Master Playback Volume");
+	chip->master_volume = snd_ctl_find_id(chip->card, &elem_id);
 
 	return 0;
 }
@@ -2569,7 +2569,7 @@ static int m3_suspend(struct pci_dev *pci, pm_message_t state)
 {
 	struct snd_card *card = pci_get_drvdata(pci);
 	struct snd_m3 *chip = card->private_data;
-	int i, index;
+	int i, dsp_index;
 
 	if (chip->suspend_mem == NULL)
 		return 0;
@@ -2583,12 +2583,12 @@ static int m3_suspend(struct pci_dev *pci, pm_message_t state)
 	snd_m3_assp_halt(chip);
 
 	/* save dsp image */
-	index = 0;
+	dsp_index = 0;
 	for (i = REV_B_CODE_MEMORY_BEGIN; i <= REV_B_CODE_MEMORY_END; i++)
-		chip->suspend_mem[index++] = 
+		chip->suspend_mem[dsp_index++] =
 			snd_m3_assp_read(chip, MEMTYPE_INTERNAL_CODE, i);
 	for (i = REV_B_DATA_MEMORY_BEGIN ; i <= REV_B_DATA_MEMORY_END; i++)
-		chip->suspend_mem[index++] = 
+		chip->suspend_mem[dsp_index++] =
 			snd_m3_assp_read(chip, MEMTYPE_INTERNAL_DATA, i);
 
 	pci_disable_device(pci);
@@ -2601,7 +2601,7 @@ static int m3_resume(struct pci_dev *pci)
 {
 	struct snd_card *card = pci_get_drvdata(pci);
 	struct snd_m3 *chip = card->private_data;
-	int i, index;
+	int i, dsp_index;
 
 	if (chip->suspend_mem == NULL)
 		return 0;
@@ -2625,13 +2625,13 @@ static int m3_resume(struct pci_dev *pci)
 	snd_m3_ac97_reset(chip);
 
 	/* restore dsp image */
-	index = 0;
+	dsp_index = 0;
 	for (i = REV_B_CODE_MEMORY_BEGIN; i <= REV_B_CODE_MEMORY_END; i++)
 		snd_m3_assp_write(chip, MEMTYPE_INTERNAL_CODE, i, 
-				  chip->suspend_mem[index++]);
+				  chip->suspend_mem[dsp_index++]);
 	for (i = REV_B_DATA_MEMORY_BEGIN ; i <= REV_B_DATA_MEMORY_END; i++)
 		snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, i, 
-				  chip->suspend_mem[index++]);
+				  chip->suspend_mem[dsp_index++]);
 
 	/* tell the dma engine to restart itself */
 	snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, 
-- 
cgit v1.2.3-70-g09d2


From 4db9e4f2b5278338ff9487eefdc8e32109aa0552 Mon Sep 17 00:00:00 2001
From: Harvey Harrison <harvey.harrison@gmail.com>
Date: Thu, 28 Feb 2008 11:57:23 +0100
Subject: [ALSA] sound: rme32.c fix integer as NULL pointer warning

kernel style does assignment outside of if() statements.
sound/pci/rme32.c:1353:71: warning: Using plain integer as NULL pointer

Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/rme32.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'sound')

diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
index df184aabce8..e7ef3a1a25a 100644
--- a/sound/pci/rme32.c
+++ b/sound/pci/rme32.c
@@ -1350,7 +1350,8 @@ static int __devinit snd_rme32_create(struct rme32 * rme32)
 		return err;
 	rme32->port = pci_resource_start(rme32->pci, 0);
 
-	if ((rme32->iobase = ioremap_nocache(rme32->port, RME32_IO_SIZE)) == 0) {
+	rme32->iobase = ioremap_nocache(rme32->port, RME32_IO_SIZE);
+	if (!rme32->iobase) {
 		snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n",
 			   rme32->port, rme32->port + RME32_IO_SIZE - 1);
 		return -ENOMEM;
-- 
cgit v1.2.3-70-g09d2


From 44977b719f7425ddb1cb67d647a4f588a9718163 Mon Sep 17 00:00:00 2001
From: Harvey Harrison <harvey.harrison@gmail.com>
Date: Thu, 28 Feb 2008 11:57:47 +0100
Subject: [ALSA] sound: rme96.c fix integer as NULL pointer warning

kernel style does assignment outside of if() block
sound/pci/rme96.c:1562:71: warning: Using plain integer as NULL pointer

Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/rme96.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'sound')

diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
index fb0a4ee8bc0..3fdd488d097 100644
--- a/sound/pci/rme96.c
+++ b/sound/pci/rme96.c
@@ -1559,7 +1559,8 @@ snd_rme96_create(struct rme96 *rme96)
 		return err;
 	rme96->port = pci_resource_start(rme96->pci, 0);
 
-	if ((rme96->iobase = ioremap_nocache(rme96->port, RME96_IO_SIZE)) == 0) {
+	rme96->iobase = ioremap_nocache(rme96->port, RME96_IO_SIZE);
+	if (!rme96->iobase) {
 		snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n", rme96->port, rme96->port + RME96_IO_SIZE - 1);
 		return -ENOMEM;
 	}
-- 
cgit v1.2.3-70-g09d2


From 608b10bad3563e2349393136ce421d9f67329170 Mon Sep 17 00:00:00 2001
From: Harvey Harrison <harvey.harrison@gmail.com>
Date: Thu, 28 Feb 2008 11:58:18 +0100
Subject: [ALSA] sound: ac97_pcm.c fix shadowed variable warning

err is always assigned before it is used, no need to declare another
inside the if statement.
sound/pci/ac97/ac97_pcm.c:577:7: warning: symbol 'err' shadows an earlier one
sound/pci/ac97/ac97_pcm.c:572:6: originally declared here

Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/ac97/ac97_pcm.c | 1 -
 1 file changed, 1 deletion(-)

(limited to 'sound')

diff --git a/sound/pci/ac97/ac97_pcm.c b/sound/pci/ac97/ac97_pcm.c
index 3674f35c4a7..48cbda9378c 100644
--- a/sound/pci/ac97/ac97_pcm.c
+++ b/sound/pci/ac97/ac97_pcm.c
@@ -574,7 +574,6 @@ int snd_ac97_pcm_open(struct ac97_pcm *pcm, unsigned int rate,
 	r = rate > 48000;
 	bus = pcm->bus;
 	if (cfg == AC97_PCM_CFG_SPDIF) {
-		int err;
 		for (cidx = 0; cidx < 4; cidx++)
 			if (bus->codec[cidx] && (bus->codec[cidx]->ext_id & AC97_EI_SPDIF)) {
 				err = set_spdif_rate(bus->codec[cidx], rate);
-- 
cgit v1.2.3-70-g09d2


From c74056d437401dc7d43970cd845c34a7e28723c0 Mon Sep 17 00:00:00 2001
From: Harvey Harrison <harvey.harrison@gmail.com>
Date: Thu, 28 Feb 2008 12:00:48 +0100
Subject: [ALSA] sound: ali5451.c fix shadowed variable warnings

enable is used to test for whether or not spdif should be enabled,
change to spdif_enable.

sound/pci/ali5451/ali5451.c:1812:15: warning: symbol 'enable' shadows an earlier one
sound/pci/ali5451/ali5451.c:63:12: originally declared here
sound/pci/ali5451/ali5451.c:1840:27: warning: symbol 'enable' shadows an earlier one
sound/pci/ali5451/ali5451.c:63:12: originally declared here

Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/ali5451/ali5451.c | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index 6a905ed9cbd..fc04d3da1af 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -1809,26 +1809,26 @@ static int snd_ali5451_spdif_get(struct snd_kcontrol *kcontrol,
 				 struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_ali *codec = kcontrol->private_data;
-	unsigned int enable;
+	unsigned int spdif_enable;
 
-	enable = ucontrol->value.integer.value[0] ? 1 : 0;
+	spdif_enable = ucontrol->value.integer.value[0] ? 1 : 0;
 
 	spin_lock_irq(&codec->reg_lock);
 	switch (kcontrol->private_value) {
 	case 0:
-		enable = (codec->spdif_mask & 0x02) ? 1 : 0;
+		spdif_enable = (codec->spdif_mask & 0x02) ? 1 : 0;
 		break;
 	case 1:
-		enable = ((codec->spdif_mask & 0x02) &&
+		spdif_enable = ((codec->spdif_mask & 0x02) &&
 			  (codec->spdif_mask & 0x04)) ? 1 : 0;
 		break;
 	case 2:
-		enable = (codec->spdif_mask & 0x01) ? 1 : 0;
+		spdif_enable = (codec->spdif_mask & 0x01) ? 1 : 0;
 		break;
 	default:
 		break;
 	}
-	ucontrol->value.integer.value[0] = enable;
+	ucontrol->value.integer.value[0] = spdif_enable;
 	spin_unlock_irq(&codec->reg_lock);
 	return 0;
 }
@@ -1837,17 +1837,17 @@ static int snd_ali5451_spdif_put(struct snd_kcontrol *kcontrol,
 				 struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_ali *codec = kcontrol->private_data;
-	unsigned int change = 0, enable = 0;
+	unsigned int change = 0, spdif_enable = 0;
 
-	enable = ucontrol->value.integer.value[0] ? 1 : 0;
+	spdif_enable = ucontrol->value.integer.value[0] ? 1 : 0;
 
 	spin_lock_irq(&codec->reg_lock);
 	switch (kcontrol->private_value) {
 	case 0:
 		change = (codec->spdif_mask & 0x02) ? 1 : 0;
-		change = change ^ enable;
+		change = change ^ spdif_enable;
 		if (change) {
-			if (enable) {
+			if (spdif_enable) {
 				codec->spdif_mask |= 0x02;
 				snd_ali_enable_spdif_out(codec);
 			} else {
@@ -1859,9 +1859,9 @@ static int snd_ali5451_spdif_put(struct snd_kcontrol *kcontrol,
 		break;
 	case 1: 
 		change = (codec->spdif_mask & 0x04) ? 1 : 0;
-		change = change ^ enable;
+		change = change ^ spdif_enable;
 		if (change && (codec->spdif_mask & 0x02)) {
-			if (enable) {
+			if (spdif_enable) {
 				codec->spdif_mask |= 0x04;
 				snd_ali_enable_spdif_chnout(codec);
 			} else {
@@ -1872,9 +1872,9 @@ static int snd_ali5451_spdif_put(struct snd_kcontrol *kcontrol,
 		break;
 	case 2:
 		change = (codec->spdif_mask & 0x01) ? 1 : 0;
-		change = change ^ enable;
+		change = change ^ spdif_enable;
 		if (change) {
-			if (enable) {
+			if (spdif_enable) {
 				codec->spdif_mask |= 0x01;
 				snd_ali_enable_spdif_in(codec);
 			} else {
-- 
cgit v1.2.3-70-g09d2


From d967a02712f09265b3c357f35f125715f5dffd2f Mon Sep 17 00:00:00 2001
From: Harvey Harrison <harvey.harrison@gmail.com>
Date: Thu, 28 Feb 2008 12:02:22 +0100
Subject: [ALSA] sound: ca0106_main.c fix shadowed variable warnings

change to intr_enable as per the two functions it is defined in.
sound/pci/ca0106/ca0106_main.c:438:15: warning: symbol 'enable' shadows an earlier one
sound/pci/ca0106/ca0106_main.c:159:12: originally declared here
sound/pci/ca0106/ca0106_main.c:449:15: warning: symbol 'enable' shadows an earlier one
sound/pci/ca0106/ca0106_main.c:159:12: originally declared here

Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/ca0106/ca0106_main.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index 176e0f0e805..3818249fcc8 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -435,22 +435,22 @@ int snd_ca0106_i2c_write(struct snd_ca0106 *emu,
 static void snd_ca0106_intr_enable(struct snd_ca0106 *emu, unsigned int intrenb)
 {
 	unsigned long flags;
-	unsigned int enable;
-  
+	unsigned int intr_enable;
+
 	spin_lock_irqsave(&emu->emu_lock, flags);
-	enable = inl(emu->port + INTE) | intrenb;
-	outl(enable, emu->port + INTE);
+	intr_enable = inl(emu->port + INTE) | intrenb;
+	outl(intr_enable, emu->port + INTE);
 	spin_unlock_irqrestore(&emu->emu_lock, flags);
 }
 
 static void snd_ca0106_intr_disable(struct snd_ca0106 *emu, unsigned int intrenb)
 {
 	unsigned long flags;
-	unsigned int enable;
-  
+	unsigned int intr_enable;
+
 	spin_lock_irqsave(&emu->emu_lock, flags);
-	enable = inl(emu->port + INTE) & ~intrenb;
-	outl(enable, emu->port + INTE);
+	intr_enable = inl(emu->port + INTE) & ~intrenb;
+	outl(intr_enable, emu->port + INTE);
 	spin_unlock_irqrestore(&emu->emu_lock, flags);
 }
 
-- 
cgit v1.2.3-70-g09d2


From bed515b0dfdcf8f440c7e6c5bad8ce3eb96fb625 Mon Sep 17 00:00:00 2001
From: Harvey Harrison <harvey.harrison@gmail.com>
Date: Thu, 28 Feb 2008 12:02:56 +0100
Subject: [ALSA] sound: ca0106_mixer.c fix shadowed variable warnings

Change the variable err to _err within the ADD_CTLS macro to avoid
shadowing the local variable.

sound/pci/ca0106/ca0106_mixer.c:710:2: warning: symbol 'err' shadows an earlier one
sound/pci/ca0106/ca0106_mixer.c:663:6: originally declared here
sound/pci/ca0106/ca0106_mixer.c:712:3: warning: symbol 'err' shadows an earlier one
sound/pci/ca0106/ca0106_mixer.c:663:6: originally declared here
sound/pci/ca0106/ca0106_mixer.c:721:3: warning: symbol 'err' shadows an earlier one
sound/pci/ca0106/ca0106_mixer.c:663:6: originally declared here

Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/ca0106/ca0106_mixer.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c
index 94618ecaab6..3025ed1b6e1 100644
--- a/sound/pci/ca0106/ca0106_mixer.c
+++ b/sound/pci/ca0106/ca0106_mixer.c
@@ -650,11 +650,11 @@ static int __devinit rename_ctl(struct snd_card *card, const char *src, const ch
 
 #define ADD_CTLS(emu, ctls)						\
 	do {								\
-		int i, err;						\
+		int i, _err;						\
 		for (i = 0; i < ARRAY_SIZE(ctls); i++) {		\
-			err = snd_ctl_add(card, snd_ctl_new1(&ctls[i], emu)); \
-			if (err < 0)					\
-				return err;				\
+			_err = snd_ctl_add(card, snd_ctl_new1(&ctls[i], emu)); \
+			if (_err < 0)					\
+				return _err;				\
 		}							\
 	} while (0)
 
-- 
cgit v1.2.3-70-g09d2


From 470f23b873679b045908551302fec6b1edf05a5a Mon Sep 17 00:00:00 2001
From: Ahmet Ä°nan <ainan at>
Date: Thu, 28 Feb 2008 12:46:32 +0100
Subject: [ALSA] snd-dummy - better realtime app support
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

when the time interval for a period is smaller than kernel HZ, then
snd-aloop and snd-dummy cannot call snd_pcm_period_elapsed as fast enough
annymore. this happens for example with games. but the app still needs to
see, that the buffer actually did go further, which is provided by these
patches.

Signed-off-by: Ahmet Ä°nan <ainan <at> mathematik.uni-freiburg.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/drivers/dummy.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'sound')

diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index f67f65829f3..83ac4980c5f 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -259,10 +259,10 @@ static void snd_card_dummy_pcm_timer_function(unsigned long data)
 	dpcm->timer.expires = 1 + jiffies;
 	add_timer(&dpcm->timer);
 	dpcm->pcm_irq_pos += dpcm->pcm_bps;
+	dpcm->pcm_buf_pos += dpcm->pcm_bps;
+	dpcm->pcm_buf_pos %= dpcm->pcm_buffer_size * dpcm->pcm_hz;
 	if (dpcm->pcm_irq_pos >= dpcm->pcm_period_size * dpcm->pcm_hz) {
 		dpcm->pcm_irq_pos %= dpcm->pcm_period_size * dpcm->pcm_hz;
-		dpcm->pcm_buf_pos += dpcm->pcm_period_size;
-		dpcm->pcm_buf_pos %= dpcm->pcm_buffer_size;
 		spin_unlock_irqrestore(&dpcm->lock, flags);
 		snd_pcm_period_elapsed(dpcm->substream);
 	} else
@@ -274,7 +274,7 @@ static snd_pcm_uframes_t snd_card_dummy_pcm_pointer(struct snd_pcm_substream *su
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct snd_dummy_pcm *dpcm = runtime->private_data;
 
-	return bytes_to_frames(runtime, dpcm->pcm_buf_pos);
+	return bytes_to_frames(runtime, dpcm->pcm_buf_pos / dpcm->pcm_hz);
 }
 
 static struct snd_pcm_hardware snd_card_dummy_playback =
-- 
cgit v1.2.3-70-g09d2


From 3fa4a9073886a1031400c19e8b09fca3eebb645f Mon Sep 17 00:00:00 2001
From: Harvey Harrison <harvey.harrison@gmail.com>
Date: Fri, 29 Feb 2008 11:41:56 +0100
Subject: [ALSA] sound: au88x0_pcm.c fix integer as NULL pointer warning

sound/pci/au88x0/au88x0_pcm.c:508:15: warning: Using plain integer as NULL pointer

Also some small codingstyle fixes.

Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/au88x0/au88x0_pcm.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/au88x0/au88x0_pcm.c b/sound/pci/au88x0/au88x0_pcm.c
index 526c6c5ecf7..f9a58b4a30e 100644
--- a/sound/pci/au88x0/au88x0_pcm.c
+++ b/sound/pci/au88x0/au88x0_pcm.c
@@ -498,14 +498,14 @@ static struct snd_kcontrol_new snd_vortex_mixer_spdif[] __devinitdata = {
 };
 
 /* create a pcm device */
-static int __devinit snd_vortex_new_pcm(vortex_t * chip, int idx, int nr)
+static int __devinit snd_vortex_new_pcm(vortex_t *chip, int idx, int nr)
 {
 	struct snd_pcm *pcm;
 	struct snd_kcontrol *kctl;
 	int i;
 	int err, nr_capt;
 
-	if ((chip == 0) || (idx < 0) || (idx >= VORTEX_PCM_LAST))
+	if (!chip || idx < 0 || idx >= VORTEX_PCM_LAST)
 		return -ENODEV;
 
 	/* idx indicates which kind of PCM device. ADB, SPDIF, I2S and A3D share the 
@@ -514,9 +514,9 @@ static int __devinit snd_vortex_new_pcm(vortex_t * chip, int idx, int nr)
 		nr_capt = nr;
 	else
 		nr_capt = 0;
-	if ((err =
-	     snd_pcm_new(chip->card, vortex_pcm_prettyname[idx], idx, nr,
-			 nr_capt, &pcm)) < 0)
+	err = snd_pcm_new(chip->card, vortex_pcm_prettyname[idx], idx, nr,
+			  nr_capt, &pcm);
+	if (err < 0)
 		return err;
 	strcpy(pcm->name, vortex_pcm_name[idx]);
 	chip->pcm[idx] = pcm;
-- 
cgit v1.2.3-70-g09d2


From 4677df07e551d64167f64eba5e3563b3df7f4ca8 Mon Sep 17 00:00:00 2001
From: Harvey Harrison <harvey.harrison@gmail.com>
Date: Fri, 29 Feb 2008 11:44:26 +0100
Subject: [ALSA] sound: emuproc.c fix signedness warning

Reading regs from the fpga into an int instead of a u32, trivial
fix.
sound/pci/emu10k1/emuproc.c:422:34: warning: incorrect type in argument 3 (different signedness)
sound/pci/emu10k1/emuproc.c:422:34:    expected unsigned int [usertype] *value
sound/pci/emu10k1/emuproc.c:422:34:    got int *<noident>

Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/emu10k1/emuproc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'sound')

diff --git a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c
index f3caa3f890c..216f9748aff 100644
--- a/sound/pci/emu10k1/emuproc.c
+++ b/sound/pci/emu10k1/emuproc.c
@@ -412,7 +412,7 @@ static void snd_emu_proc_emu1010_reg_read(struct snd_info_entry *entry,
 				     struct snd_info_buffer *buffer)
 {
 	struct snd_emu10k1 *emu = entry->private_data;
-	int value;
+	u32 value;
 	unsigned long flags;
 	int i;
 	snd_iprintf(buffer, "EMU1010 Registers:\n\n");
-- 
cgit v1.2.3-70-g09d2


From f2948fc2f0e1c19b8bea77a14338d338e941ac9a Mon Sep 17 00:00:00 2001
From: Harvey Harrison <harvey.harrison@gmail.com>
Date: Fri, 29 Feb 2008 11:44:57 +0100
Subject: [ALSA] sound: emu10k1x.c fix shadowed variable warnings

enable in these contexts refers specifically to intr enable, as
per the two functions it is found in.  Use intr_enable instead.
sound/pci/emu10k1/emu10k1x.c:330:15: warning: symbol 'enable' shadows an earlier one
sound/pci/emu10k1/emu10k1x.c:53:12: originally declared here
sound/pci/emu10k1/emu10k1x.c:341:15: warning: symbol 'enable' shadows an earlier one
sound/pci/emu10k1/emu10k1x.c:53:12: originally declared here

instead of shadowing, use cap_voice as we test for the capture
voice in this statement.
sound/pci/emu10k1/emu10k1x.c:798:25: warning: symbol 'pvoice' shadows an earlier one
sound/pci/emu10k1/emu10k1x.c:787:24: originally declared here

Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/emu10k1/emu10k1x.c | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
index 5512abd98bd..341f34e19f3 100644
--- a/sound/pci/emu10k1/emu10k1x.c
+++ b/sound/pci/emu10k1/emu10k1x.c
@@ -327,22 +327,22 @@ static void snd_emu10k1x_ptr_write(struct emu10k1x *emu,
 static void snd_emu10k1x_intr_enable(struct emu10k1x *emu, unsigned int intrenb)
 {
 	unsigned long flags;
-	unsigned int enable;
-  
+	unsigned int intr_enable;
+
 	spin_lock_irqsave(&emu->emu_lock, flags);
-	enable = inl(emu->port + INTE) | intrenb;
-	outl(enable, emu->port + INTE);
+	intr_enable = inl(emu->port + INTE) | intrenb;
+	outl(intr_enable, emu->port + INTE);
 	spin_unlock_irqrestore(&emu->emu_lock, flags);
 }
 
 static void snd_emu10k1x_intr_disable(struct emu10k1x *emu, unsigned int intrenb)
 {
 	unsigned long flags;
-	unsigned int enable;
-  
+	unsigned int intr_enable;
+
 	spin_lock_irqsave(&emu->emu_lock, flags);
-	enable = inl(emu->port + INTE) & ~intrenb;
-	outl(enable, emu->port + INTE);
+	intr_enable = inl(emu->port + INTE) & ~intrenb;
+	outl(intr_enable, emu->port + INTE);
 	spin_unlock_irqrestore(&emu->emu_lock, flags);
 }
 
@@ -795,9 +795,9 @@ static irqreturn_t snd_emu10k1x_interrupt(int irq, void *dev_id)
 
 	// capture interrupt
 	if (status & (IPR_CAP_0_LOOP | IPR_CAP_0_HALF_LOOP)) {
-		struct emu10k1x_voice *pvoice = &chip->capture_voice;
-		if (pvoice->use)
-			snd_emu10k1x_pcm_interrupt(chip, pvoice);
+		struct emu10k1x_voice *cap_voice = &chip->capture_voice;
+		if (cap_voice->use)
+			snd_emu10k1x_pcm_interrupt(chip, cap_voice);
 		else
 			snd_emu10k1x_intr_disable(chip, 
 						  INTE_CAP_0_LOOP |
-- 
cgit v1.2.3-70-g09d2


From c3daa92d60552891057b65f278d882348b76fffe Mon Sep 17 00:00:00 2001
From: Harvey Harrison <harvey.harrison@gmail.com>
Date: Fri, 29 Feb 2008 11:52:50 +0100
Subject: [ALSA] sound: ice1712.c fix shadowed variable warnings

In all four case, adding a private value to the iooff index,
call it priv_idx.
sound/pci/ice1712/ice1712.c:1300:6: warning: symbol 'index' shadows an earlier one
sound/pci/ice1712/ice1712.c:85:12: originally declared here
sound/pci/ice1712/ice1712.c:1312:6: warning: symbol 'index' shadows an earlier one
sound/pci/ice1712/ice1712.c:85:12: originally declared here
sound/pci/ice1712/ice1712.c:1338:6: warning: symbol 'index' shadows an earlier one
sound/pci/ice1712/ice1712.c:85:12: originally declared here
sound/pci/ice1712/ice1712.c:1350:6: warning: symbol 'index' shadows an earlier one
sound/pci/ice1712/ice1712.c:85:12: originally declared here

[tiwai - fixed coding issues as well]

Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/ice1712/ice1712.c | 40 ++++++++++++++++++++++++----------------
 1 file changed, 24 insertions(+), 16 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
index df292af6738..38e93ca12e2 100644
--- a/sound/pci/ice1712/ice1712.c
+++ b/sound/pci/ice1712/ice1712.c
@@ -1297,11 +1297,14 @@ static void snd_ice1712_update_volume(struct snd_ice1712 *ice, int index)
 static int snd_ice1712_pro_mixer_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
-	int index = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + kcontrol->private_value;
+	int priv_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) +
+		kcontrol->private_value;
 	
 	spin_lock_irq(&ice->reg_lock);
-	ucontrol->value.integer.value[0] = !((ice->pro_volumes[index] >> 15) & 1);
-	ucontrol->value.integer.value[1] = !((ice->pro_volumes[index] >> 31) & 1);
+	ucontrol->value.integer.value[0] =
+		!((ice->pro_volumes[priv_idx] >> 15) & 1);
+	ucontrol->value.integer.value[1] =
+		!((ice->pro_volumes[priv_idx] >> 31) & 1);
 	spin_unlock_irq(&ice->reg_lock);
 	return 0;
 }
@@ -1309,16 +1312,17 @@ static int snd_ice1712_pro_mixer_switch_get(struct snd_kcontrol *kcontrol, struc
 static int snd_ice1712_pro_mixer_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
-	int index = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + kcontrol->private_value;
+	int priv_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) +
+		kcontrol->private_value;
 	unsigned int nval, change;
 
 	nval = (ucontrol->value.integer.value[0] ? 0 : 0x00008000) |
 	       (ucontrol->value.integer.value[1] ? 0 : 0x80000000);
 	spin_lock_irq(&ice->reg_lock);
-	nval |= ice->pro_volumes[index] & ~0x80008000;
-	change = nval != ice->pro_volumes[index];
-	ice->pro_volumes[index] = nval;
-	snd_ice1712_update_volume(ice, index);
+	nval |= ice->pro_volumes[priv_idx] & ~0x80008000;
+	change = nval != ice->pro_volumes[priv_idx];
+	ice->pro_volumes[priv_idx] = nval;
+	snd_ice1712_update_volume(ice, priv_idx);
 	spin_unlock_irq(&ice->reg_lock);
 	return change;
 }
@@ -1335,11 +1339,14 @@ static int snd_ice1712_pro_mixer_volume_info(struct snd_kcontrol *kcontrol, stru
 static int snd_ice1712_pro_mixer_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
-	int index = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + kcontrol->private_value;
+	int priv_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) +
+		kcontrol->private_value;
 	
 	spin_lock_irq(&ice->reg_lock);
-	ucontrol->value.integer.value[0] = (ice->pro_volumes[index] >> 0) & 127;
-	ucontrol->value.integer.value[1] = (ice->pro_volumes[index] >> 16) & 127;
+	ucontrol->value.integer.value[0] =
+		(ice->pro_volumes[priv_idx] >> 0) & 127;
+	ucontrol->value.integer.value[1] =
+		(ice->pro_volumes[priv_idx] >> 16) & 127;
 	spin_unlock_irq(&ice->reg_lock);
 	return 0;
 }
@@ -1347,16 +1354,17 @@ static int snd_ice1712_pro_mixer_volume_get(struct snd_kcontrol *kcontrol, struc
 static int snd_ice1712_pro_mixer_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
-	int index = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + kcontrol->private_value;
+	int priv_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) +
+		kcontrol->private_value;
 	unsigned int nval, change;
 
 	nval = (ucontrol->value.integer.value[0] & 127) |
 	       ((ucontrol->value.integer.value[1] & 127) << 16);
 	spin_lock_irq(&ice->reg_lock);
-	nval |= ice->pro_volumes[index] & ~0x007f007f;
-	change = nval != ice->pro_volumes[index];
-	ice->pro_volumes[index] = nval;
-	snd_ice1712_update_volume(ice, index);
+	nval |= ice->pro_volumes[priv_idx] & ~0x007f007f;
+	change = nval != ice->pro_volumes[priv_idx];
+	ice->pro_volumes[priv_idx] = nval;
+	snd_ice1712_update_volume(ice, priv_idx);
 	spin_unlock_irq(&ice->reg_lock);
 	return change;
 }
-- 
cgit v1.2.3-70-g09d2


From ff143874d09a5850e7bf6c68d141243cb12a7b58 Mon Sep 17 00:00:00 2001
From: Harvey Harrison <harvey.harrison@gmail.com>
Date: Fri, 29 Feb 2008 11:46:57 +0100
Subject: [ALSA] sound: virtuoso.c fix shadowed variable warning

Use priv_idx as an identifier.
sound/pci/oxygen/virtuoso.c:277:15: warning: symbol 'index' shadows an earlier one
sound/pci/oxygen/virtuoso.c:56:12: originally declared here

Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/oxygen/virtuoso.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
index d163397b85c..e4e23789080 100644
--- a/sound/pci/oxygen/virtuoso.c
+++ b/sound/pci/oxygen/virtuoso.c
@@ -274,12 +274,12 @@ static void xonar_gpio_changed(struct oxygen *chip)
 
 static void mute_ac97_ctl(struct oxygen *chip, unsigned int control)
 {
-	unsigned int index = chip->controls[control]->private_value & 0xff;
+	unsigned int priv_idx = chip->controls[control]->private_value & 0xff;
 	u16 value;
 
-	value = oxygen_read_ac97(chip, 0, index);
+	value = oxygen_read_ac97(chip, 0, priv_idx);
 	if (!(value & 0x8000)) {
-		oxygen_write_ac97(chip, 0, index, value | 0x8000);
+		oxygen_write_ac97(chip, 0, priv_idx, value | 0x8000);
 		snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
 			       &chip->controls[control]->id);
 	}
-- 
cgit v1.2.3-70-g09d2


From caba7f70fce924dc5da2019f7678189086d0acd4 Mon Sep 17 00:00:00 2001
From: Harvey Harrison <harvey.harrison@gmail.com>
Date: Fri, 29 Feb 2008 11:53:59 +0100
Subject: [ALSA] sound: pcxhr_core.c fix shadowed variable warning

Inner loop redeclares err with u32 rather than int, stupid fix here
is to change the inner err to err2.
sound/pci/pcxhr/pcxhr_core.c:1008:8: warning: symbol 'err' shadows an earlier one
sound/pci/pcxhr/pcxhr_core.c:983:6: originally declared here

Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/pcxhr/pcxhr_core.c | 31 +++++++++++++++++++------------
 1 file changed, 19 insertions(+), 12 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/pcxhr/pcxhr_core.c b/sound/pci/pcxhr/pcxhr_core.c
index c4e415d0738..846afbd3068 100644
--- a/sound/pci/pcxhr/pcxhr_core.c
+++ b/sound/pci/pcxhr/pcxhr_core.c
@@ -1005,30 +1005,37 @@ void pcxhr_msg_tasklet(unsigned long arg)
 			int nb_stream = (prmh->stat[i] >> (2*FIELD_SIZE)) & MASK_FIRST_FIELD;
 			int pipe = prmh->stat[i] & MASK_FIRST_FIELD;
 			int is_capture = prmh->stat[i] & 0x400000;
-			u32 err;
+			u32 err2;
 
 			if (prmh->stat[i] & 0x800000) {	/* if BIT_END */
 				snd_printdd("TASKLET : End%sPipe %d\n",
 					    is_capture ? "Record" : "Play", pipe);
 			}
 			i++;
-			err = prmh->stat[i] ? prmh->stat[i] : prmh->stat[i+1];
-			if (err)
-				pcxhr_handle_async_err(mgr, err, PCXHR_ERR_PIPE,
+			err2 = prmh->stat[i] ? prmh->stat[i] : prmh->stat[i+1];
+			if (err2)
+				pcxhr_handle_async_err(mgr, err2,
+						       PCXHR_ERR_PIPE,
 						       pipe, is_capture);
 			i += 2;
 			for (j = 0; j < nb_stream; j++) {
-				err = prmh->stat[i] ? prmh->stat[i] : prmh->stat[i+1];
-				if (err)
-					pcxhr_handle_async_err(mgr, err, PCXHR_ERR_STREAM,
-							       pipe, is_capture);
+				err2 = prmh->stat[i] ?
+					prmh->stat[i] : prmh->stat[i+1];
+				if (err2)
+					pcxhr_handle_async_err(mgr, err2,
+							       PCXHR_ERR_STREAM,
+							       pipe,
+							       is_capture);
 				i += 2;
 			}
 			for (j = 0; j < nb_audio; j++) {
-				err = prmh->stat[i] ? prmh->stat[i] : prmh->stat[i+1];
-				if (err)
-					pcxhr_handle_async_err(mgr, err, PCXHR_ERR_AUDIO,
-							       pipe, is_capture);
+				err2 = prmh->stat[i] ?
+					prmh->stat[i] : prmh->stat[i+1];
+				if (err2)
+					pcxhr_handle_async_err(mgr, err2,
+							       PCXHR_ERR_AUDIO,
+							       pipe,
+							       is_capture);
 				i += 2;
 			}
 		}
-- 
cgit v1.2.3-70-g09d2


From 0cd87b10ca29a351c61c8c63761ab8fb48e47b2f Mon Sep 17 00:00:00 2001
From: Harvey Harrison <harvey.harrison@gmail.com>
Date: Fri, 29 Feb 2008 11:54:26 +0100
Subject: [ALSA] sound: riptide.c fix shadowed variable warnings

In both cases we are passing around the substream number, use
sub_num for this.
sound/pci/riptide/riptide.c:1633:6: warning: symbol 'index' shadows an earlier one
sound/pci/riptide/riptide.c:121:12: originally declared here
sound/pci/riptide/riptide.c:1673:6: warning: symbol 'index' shadows an earlier one
sound/pci/riptide/riptide.c:121:12: originally declared here

Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/riptide/riptide.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c
index 9408b1eeec4..979f7da641c 100644
--- a/sound/pci/riptide/riptide.c
+++ b/sound/pci/riptide/riptide.c
@@ -1630,14 +1630,14 @@ static int snd_riptide_playback_open(struct snd_pcm_substream *substream)
 	struct snd_riptide *chip = snd_pcm_substream_chip(substream);
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct pcmhw *data;
-	int index = substream->number;
+	int sub_num = substream->number;
 
-	chip->playback_substream[index] = substream;
+	chip->playback_substream[sub_num] = substream;
 	runtime->hw = snd_riptide_playback;
 	data = kzalloc(sizeof(struct pcmhw), GFP_KERNEL);
-	data->paths = lbus_play_paths[index];
-	data->id = play_ids[index];
-	data->source = play_sources[index];
+	data->paths = lbus_play_paths[sub_num];
+	data->id = play_ids[sub_num];
+	data->source = play_sources[sub_num];
 	data->intdec[0] = 0xff;
 	data->intdec[1] = 0xff;
 	data->state = ST_STOP;
@@ -1670,10 +1670,10 @@ static int snd_riptide_playback_close(struct snd_pcm_substream *substream)
 {
 	struct snd_riptide *chip = snd_pcm_substream_chip(substream);
 	struct pcmhw *data = get_pcmhwdev(substream);
-	int index = substream->number;
+	int sub_num = substream->number;
 
 	substream->runtime->private_data = NULL;
-	chip->playback_substream[index] = NULL;
+	chip->playback_substream[sub_num] = NULL;
 	kfree(data);
 	return 0;
 }
-- 
cgit v1.2.3-70-g09d2


From 0b76b51e5807951995a39ea791b39971a7ae945f Mon Sep 17 00:00:00 2001
From: Harvey Harrison <harvey.harrison@gmail.com>
Date: Fri, 29 Feb 2008 11:54:49 +0100
Subject: [ALSA] sound: hdspm.c fix returning void expression warnings

Just drop the returns.
sound/pci/rme9652/hdspm.c:1031:3: warning: returning void-valued expression
sound/pci/rme9652/hdspm.c:1033:3: warning: returning void-valued expression

Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/rme9652/hdspm.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index 9a19ae6a64d..38c931c480d 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -1028,9 +1028,9 @@ static inline void snd_hdspm_midi_write_byte (struct hdspm *hdspm, int id,
 {
 	/* the hardware already does the relevant bit-mask with 0xff */
 	if (id)
-		return hdspm_write(hdspm, HDSPM_midiDataOut1, val);
+		hdspm_write(hdspm, HDSPM_midiDataOut1, val);
 	else
-		return hdspm_write(hdspm, HDSPM_midiDataOut0, val);
+		hdspm_write(hdspm, HDSPM_midiDataOut0, val);
 }
 
 static inline int snd_hdspm_midi_input_available (struct hdspm *hdspm, int id)
-- 
cgit v1.2.3-70-g09d2


From 8b55178515e8872670dc830203dad0e9e51e16be Mon Sep 17 00:00:00 2001
From: Harvey Harrison <harvey.harrison@gmail.com>
Date: Fri, 29 Feb 2008 11:56:48 +0100
Subject: [ALSA] sound: patch_sigmatel.c fix shadowed variable warning

Temp variable in the loop shadows the second argument (which is otherwise
unused in this function).  Change this to defcfg as it is used to hold
the default config.
sound/pci/hda/patch_sigmatel.c:2759:18: warning: symbol 'cfg' shadows an earlier one
sound/pci/hda/patch_sigmatel.c:2734:26: originally declared here

Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_sigmatel.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 4bc7d8646fa..3bf528d8fc2 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -2849,11 +2849,11 @@ static int stac9200_auto_create_lfe_ctls(struct hda_codec *codec,
 	if (lfe_pin == 0 && spec->autocfg.speaker_outs == 0) {
 		for (i = 0; i < spec->autocfg.line_outs && lfe_pin == 0x0; i++) {
 			hda_nid_t pin = spec->autocfg.line_out_pins[i];
-			unsigned long cfg;
-			cfg = snd_hda_codec_read(codec, pin, 0,
+			unsigned long defcfg;
+			defcfg = snd_hda_codec_read(codec, pin, 0,
 						 AC_VERB_GET_CONFIG_DEFAULT,
 						 0x00);
-			if (get_defcfg_device(cfg) == AC_JACK_SPEAKER) {
+			if (get_defcfg_device(defcfg) == AC_JACK_SPEAKER) {
 				unsigned long wcaps = get_wcaps(codec, pin);
 				wcaps &= (AC_WCAP_STEREO | AC_WCAP_OUT_AMP);
 				if (wcaps == AC_WCAP_OUT_AMP)
-- 
cgit v1.2.3-70-g09d2


From 64ed0dfd1f42edb15f4d18c13d7696edbc2f7e4c Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Fri, 29 Feb 2008 11:57:53 +0100
Subject: [ALSA] hda-codec - Use int instead of long in patch_sigmatel.c

The HD-audio parameters are at most 32bit int.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_sigmatel.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 3bf528d8fc2..e1d61a035ba 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -2838,7 +2838,7 @@ static int stac9200_auto_create_lfe_ctls(struct hda_codec *codec,
 	 */
 	for (i = 0; i < spec->autocfg.speaker_outs && lfe_pin == 0x0; i++) {
 		hda_nid_t pin = spec->autocfg.speaker_pins[i];
-		unsigned long wcaps = get_wcaps(codec, pin);
+		unsigned int wcaps = get_wcaps(codec, pin);
 		wcaps &= (AC_WCAP_STEREO | AC_WCAP_OUT_AMP);
 		if (wcaps == AC_WCAP_OUT_AMP)
 			/* found a mono speaker with an amp, must be lfe */
@@ -2849,12 +2849,12 @@ static int stac9200_auto_create_lfe_ctls(struct hda_codec *codec,
 	if (lfe_pin == 0 && spec->autocfg.speaker_outs == 0) {
 		for (i = 0; i < spec->autocfg.line_outs && lfe_pin == 0x0; i++) {
 			hda_nid_t pin = spec->autocfg.line_out_pins[i];
-			unsigned long defcfg;
+			unsigned int defcfg;
 			defcfg = snd_hda_codec_read(codec, pin, 0,
 						 AC_VERB_GET_CONFIG_DEFAULT,
 						 0x00);
 			if (get_defcfg_device(defcfg) == AC_JACK_SPEAKER) {
-				unsigned long wcaps = get_wcaps(codec, pin);
+				unsigned int wcaps = get_wcaps(codec, pin);
 				wcaps &= (AC_WCAP_STEREO | AC_WCAP_OUT_AMP);
 				if (wcaps == AC_WCAP_OUT_AMP)
 					/* found a mono speaker with an amp,
-- 
cgit v1.2.3-70-g09d2


From 3c9a3203ff9863fbe798030928f496347c2ed3bd Mon Sep 17 00:00:00 2001
From: Harvey Harrison <harvey.harrison@gmail.com>
Date: Fri, 29 Feb 2008 11:59:26 +0100
Subject: [ALSA] sound: hda: missing includes of hda_patch.h

Move the array declaration to hda_codec.c where it is used and add includes
where the individual presets are declared.

Fixes the following sparse warnings:
sound/pci/hda/patch_realtek.c:13744:25: warning: symbol 'snd_hda_preset_realtek' was not declared. Should it be static?
sound/pci/hda/patch_cmedia.c:729:25: warning: symbol 'snd_hda_preset_cmedia' was not declared. Should it be static?
sound/pci/hda/patch_analog.c:3656:25: warning: symbol 'snd_hda_preset_analog' was not declared. Should it be static?
sound/pci/hda/patch_sigmatel.c:3995:25: warning: symbol 'snd_hda_preset_sigmatel' was not declared. Should it be static?
sound/pci/hda/patch_si3054.c:286:25: warning: symbol 'snd_hda_preset_si3054' was not declared. Should it be static?
sound/pci/hda/patch_atihdmi.c:156:25: warning: symbol 'snd_hda_preset_atihdmi' was not declared. Should it be static?
sound/pci/hda/patch_conexant.c:1721:25: warning: symbol 'snd_hda_preset_conexant' was not declared. Should it be static?
sound/pci/hda/patch_via.c:1962:25: warning: symbol 'snd_hda_preset_via' was not declared. Should it be static?

Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/hda_codec.c      | 31 ++++++++++++++++++++++++++++---
 sound/pci/hda/hda_patch.h      | 28 ----------------------------
 sound/pci/hda/patch_analog.c   |  1 +
 sound/pci/hda/patch_atihdmi.c  |  1 +
 sound/pci/hda/patch_cmedia.c   |  1 +
 sound/pci/hda/patch_conexant.c |  1 +
 sound/pci/hda/patch_realtek.c  |  1 +
 sound/pci/hda/patch_si3054.c   |  2 +-
 sound/pci/hda/patch_sigmatel.c |  1 +
 sound/pci/hda/patch_via.c      |  2 +-
 10 files changed, 36 insertions(+), 33 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 8ab88d9ba3b..e6bace83e7c 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -31,6 +31,7 @@
 #include <sound/initval.h>
 #include "hda_local.h"
 #include <sound/hda_hwdep.h>
+#include "hda_patch.h"	/* codec presets */
 
 #ifdef CONFIG_SND_HDA_POWER_SAVE
 /* define this option here to hide as static */
@@ -68,9 +69,33 @@ static struct hda_vendor_id hda_vendor_ids[] = {
 	{} /* terminator */
 };
 
-/* codec presets */
-#include "hda_patch.h"
-
+static const struct hda_codec_preset *hda_preset_tables[] = {
+#ifdef CONFIG_SND_HDA_CODEC_REALTEK
+	snd_hda_preset_realtek,
+#endif
+#ifdef CONFIG_SND_HDA_CODEC_CMEDIA
+	snd_hda_preset_cmedia,
+#endif
+#ifdef CONFIG_SND_HDA_CODEC_ANALOG
+	snd_hda_preset_analog,
+#endif
+#ifdef CONFIG_SND_HDA_CODEC_SIGMATEL
+	snd_hda_preset_sigmatel,
+#endif
+#ifdef CONFIG_SND_HDA_CODEC_SI3054
+	snd_hda_preset_si3054,
+#endif
+#ifdef CONFIG_SND_HDA_CODEC_ATIHDMI
+	snd_hda_preset_atihdmi,
+#endif
+#ifdef CONFIG_SND_HDA_CODEC_CONEXANT
+	snd_hda_preset_conexant,
+#endif
+#ifdef CONFIG_SND_HDA_CODEC_VIA
+	snd_hda_preset_via,
+#endif
+	NULL
+};
 
 #ifdef CONFIG_SND_HDA_POWER_SAVE
 static void hda_power_work(struct work_struct *work);
diff --git a/sound/pci/hda/hda_patch.h b/sound/pci/hda/hda_patch.h
index f5c23bb16d7..2fdf2358dbc 100644
--- a/sound/pci/hda/hda_patch.h
+++ b/sound/pci/hda/hda_patch.h
@@ -18,31 +18,3 @@ extern struct hda_codec_preset snd_hda_preset_atihdmi[];
 extern struct hda_codec_preset snd_hda_preset_conexant[];
 /* VIA codecs */
 extern struct hda_codec_preset snd_hda_preset_via[];
-
-static const struct hda_codec_preset *hda_preset_tables[] = {
-#ifdef CONFIG_SND_HDA_CODEC_REALTEK
-	snd_hda_preset_realtek,
-#endif
-#ifdef CONFIG_SND_HDA_CODEC_CMEDIA
-	snd_hda_preset_cmedia,
-#endif
-#ifdef CONFIG_SND_HDA_CODEC_ANALOG
-	snd_hda_preset_analog,
-#endif
-#ifdef CONFIG_SND_HDA_CODEC_SIGMATEL
-	snd_hda_preset_sigmatel,
-#endif
-#ifdef CONFIG_SND_HDA_CODEC_SI3054
-	snd_hda_preset_si3054,
-#endif
-#ifdef CONFIG_SND_HDA_CODEC_ATIHDMI
-	snd_hda_preset_atihdmi,
-#endif
-#ifdef CONFIG_SND_HDA_CODEC_CONEXANT
-	snd_hda_preset_conexant,
-#endif
-#ifdef CONFIG_SND_HDA_CODEC_VIA
-	snd_hda_preset_via,
-#endif
-	NULL
-};
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 20446e320b2..87db3c410a1 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -28,6 +28,7 @@
 #include <sound/core.h>
 #include "hda_codec.h"
 #include "hda_local.h"
+#include "hda_patch.h"
 
 struct ad198x_spec {
 	struct snd_kcontrol_new *mixers[5];
diff --git a/sound/pci/hda/patch_atihdmi.c b/sound/pci/hda/patch_atihdmi.c
index 45a2e30cbf4..12272508b11 100644
--- a/sound/pci/hda/patch_atihdmi.c
+++ b/sound/pci/hda/patch_atihdmi.c
@@ -27,6 +27,7 @@
 #include <sound/core.h>
 #include "hda_codec.h"
 #include "hda_local.h"
+#include "hda_patch.h"
 
 struct atihdmi_spec {
 	struct hda_multi_out multiout;
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c
index 9794d4166ae..1892c81f1d1 100644
--- a/sound/pci/hda/patch_cmedia.c
+++ b/sound/pci/hda/patch_cmedia.c
@@ -28,6 +28,7 @@
 #include <sound/core.h>
 #include "hda_codec.h"
 #include "hda_local.h"
+#include "hda_patch.h"
 #define NUM_PINS	11
 
 
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 2bb9a58db9f..e4fa9a35848 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -27,6 +27,7 @@
 #include <sound/core.h>
 #include "hda_codec.h"
 #include "hda_local.h"
+#include "hda_patch.h"
 
 #define CXT_PIN_DIR_IN              0x00
 #define CXT_PIN_DIR_OUT             0x01
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 2100ee48080..33c9505adba 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -30,6 +30,7 @@
 #include <sound/core.h>
 #include "hda_codec.h"
 #include "hda_local.h"
+#include "hda_patch.h"
 
 #define ALC880_FRONT_EVENT		0x01
 #define ALC880_DCVOL_EVENT		0x02
diff --git a/sound/pci/hda/patch_si3054.c b/sound/pci/hda/patch_si3054.c
index 598ee2119bb..9332b63e406 100644
--- a/sound/pci/hda/patch_si3054.c
+++ b/sound/pci/hda/patch_si3054.c
@@ -28,7 +28,7 @@
 #include <sound/core.h>
 #include "hda_codec.h"
 #include "hda_local.h"
-
+#include "hda_patch.h"
 
 /* si3054 verbs */
 #define SI3054_VERB_READ_NODE  0x900
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index e1d61a035ba..47d3536a657 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -32,6 +32,7 @@
 #include <sound/asoundef.h>
 #include "hda_codec.h"
 #include "hda_local.h"
+#include "hda_patch.h"
 
 #define NUM_CONTROL_ALLOC	32
 #define STAC_PWR_EVENT		0x20
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index 3515a3fb5d9..09f1c25eb7e 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -39,7 +39,7 @@
 #include <sound/core.h>
 #include "hda_codec.h"
 #include "hda_local.h"
-
+#include "hda_patch.h"
 
 /* amp values */
 #define AMP_VAL_IDX_SHIFT	19
-- 
cgit v1.2.3-70-g09d2


From bce6c2b5b4dbe8cd97c48c633b62adeb535954ad Mon Sep 17 00:00:00 2001
From: Matthew Ranostay <mranostay@embeddedalley.com>
Date: Fri, 29 Feb 2008 12:07:43 +0100
Subject: [ALSA] hda: disable power management on fixed ports

Power management can't be enabled on fixed ports, since the presence
will always return false and prevent output.

Signed-off-by: Matthew Ranostay <mranostay@embeddedalley.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_sigmatel.c | 4 ++++
 1 file changed, 4 insertions(+)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 47d3536a657..9b242a26363 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -3016,12 +3016,16 @@ static int stac92xx_init(struct hda_codec *codec)
 					? STAC_HP_EVENT : STAC_PWR_EVENT;
 		int pinctl = snd_hda_codec_read(codec, spec->pwr_nids[i],
 					0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+		int def_conf = snd_hda_codec_read(codec, spec->pwr_nids[i],
+					0, AC_VERB_GET_CONFIG_DEFAULT, 0);
 		/* outputs are only ports capable of power management
 		 * any attempts on powering down a input port cause the
 		 * referenced VREF to act quirky.
 		 */
 		if (pinctl & AC_PINCTL_IN_EN)
 			continue;
+		if (get_defcfg_connect(def_conf) != AC_JACK_PORT_FIXED)
+			continue;
 		enable_pin_detect(codec, spec->pwr_nids[i], event | i);
 		codec->patch_ops.unsol_event(codec, (event | i) << 26);
 	}
-- 
cgit v1.2.3-70-g09d2


From 52fe0f9d59cf4f5842bd319e4f212f907abd2e5d Mon Sep 17 00:00:00 2001
From: Matthew Ranostay <mranostay@embeddedalley.com>
Date: Fri, 29 Feb 2008 12:08:20 +0100
Subject: [ALSA] hda: add verbs for 92hd73xxx laptops

Added core_init[] for several 92hd73xxx laptops.

Signed-off-by: Matthew Ranostay <mranostay@embeddedalley.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_sigmatel.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 9b242a26363..f6c02c0b1f8 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -534,6 +534,24 @@ static struct hda_verb stac92hd73xx_6ch_core_init[] = {
 	{}
 };
 
+static struct hda_verb dell_m6_core_init[] = {
+	/* set master volume and direct control */
+	{ 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
+	/* setup audio connections */
+	{ 0x0a, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{ 0x0d, AC_VERB_SET_CONNECT_SEL, 0x01},
+	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x02},
+	/* setup adcs to point to mixer */
+	{ 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b},
+	{ 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b},
+	/* setup import muxs */
+	{ 0x28, AC_VERB_SET_CONNECT_SEL, 0x01},
+	{ 0x29, AC_VERB_SET_CONNECT_SEL, 0x01},
+	{ 0x2a, AC_VERB_SET_CONNECT_SEL, 0x01},
+	{ 0x2b, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{}
+};
+
 static struct hda_verb stac92hd73xx_8ch_core_init[] = {
 	/* set master volume and direct control */
 	{ 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
@@ -3442,6 +3460,7 @@ again:
 
 	switch (spec->board_config) {
 	case STAC_DELL_M6:
+		spec->init = dell_m6_core_init;
 		switch (codec->subsystem_id) {
 		case 0x1028025e: /* Analog Mics */
 		case 0x1028025f:
-- 
cgit v1.2.3-70-g09d2


From 40ac8c4f208111cdc1542ccc9feb21b98a6b0219 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Fri, 29 Feb 2008 14:16:17 +0100
Subject: [ALSA] hda-codec - Fix the array over-range access with stac92hd71bxx
 codec

Add the check of the array range for dac_nids to prevent the over-range
access.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_sigmatel.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index f6c02c0b1f8..6c85e7e8103 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -2363,7 +2363,7 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
 	unsigned int wid_caps, pincap;
 
 
-	for (i = 0; i < cfg->line_outs; i++) {
+	for (i = 0; i < cfg->line_outs && i < spec->multiout.num_dacs; i++) {
 		if (!spec->multiout.dac_nids[i])
 			continue;
 
-- 
cgit v1.2.3-70-g09d2


From 9ab4d072ad67793d70b8707e14fb9261749c4e07 Mon Sep 17 00:00:00 2001
From: Stas Sergeev <stsp@aknet.ru>
Date: Mon, 3 Mar 2008 10:53:54 +0100
Subject: [ALSA] Add PC-speaker sound driver

Added PC-speaker sound driver (snd-pcsp).

Signed-off-by: Stas Sergeev <stsp@aknet.ru>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/drivers/Kconfig           |  17 ++
 sound/drivers/Makefile          |   2 +-
 sound/drivers/pcsp/Makefile     |   2 +
 sound/drivers/pcsp/pcsp.c       | 241 ++++++++++++++++++++++++++++
 sound/drivers/pcsp/pcsp.h       |  82 ++++++++++
 sound/drivers/pcsp/pcsp_input.c | 116 ++++++++++++++
 sound/drivers/pcsp/pcsp_input.h |  14 ++
 sound/drivers/pcsp/pcsp_lib.c   | 347 ++++++++++++++++++++++++++++++++++++++++
 sound/drivers/pcsp/pcsp_mixer.c | 143 +++++++++++++++++
 9 files changed, 963 insertions(+), 1 deletion(-)
 create mode 100644 sound/drivers/pcsp/Makefile
 create mode 100644 sound/drivers/pcsp/pcsp.c
 create mode 100644 sound/drivers/pcsp/pcsp.h
 create mode 100644 sound/drivers/pcsp/pcsp_input.c
 create mode 100644 sound/drivers/pcsp/pcsp_input.h
 create mode 100644 sound/drivers/pcsp/pcsp_lib.c
 create mode 100644 sound/drivers/pcsp/pcsp_mixer.c

(limited to 'sound')

diff --git a/sound/drivers/Kconfig b/sound/drivers/Kconfig
index 75d4fe09fdf..78648c4e9e7 100644
--- a/sound/drivers/Kconfig
+++ b/sound/drivers/Kconfig
@@ -4,6 +4,23 @@ menu "Generic devices"
 	depends on SND!=n
 
 
+config SND_PCSP
+	tristate "Internal PC speaker support"
+	depends on X86_PC && HIGH_RES_TIMERS
+	help
+	  If you don't have a sound card in your computer, you can include a
+	  driver for the PC speaker which allows it to act like a primitive
+	  sound card.
+	  This driver also replaces the pcspkr driver for beeps.
+
+	  You can compile this as a module which will be called snd-pcsp.
+
+	  You don't need this driver if you only want your pc-speaker to beep.
+	  You don't need this driver if you have a tablet piezo beeper
+	  in your PC instead of the real speaker.
+
+	  It should not hurt to say Y or M here in all other cases.
+
 config SND_MPU401_UART
         tristate
         select SND_RAWMIDI
diff --git a/sound/drivers/Makefile b/sound/drivers/Makefile
index 8e5530006e1..d4a07f9ff2c 100644
--- a/sound/drivers/Makefile
+++ b/sound/drivers/Makefile
@@ -20,4 +20,4 @@ obj-$(CONFIG_SND_MTS64) += snd-mts64.o
 obj-$(CONFIG_SND_PORTMAN2X4) += snd-portman2x4.o
 obj-$(CONFIG_SND_ML403_AC97CR) += snd-ml403-ac97cr.o
 
-obj-$(CONFIG_SND) += opl3/ opl4/ mpu401/ vx/
+obj-$(CONFIG_SND) += opl3/ opl4/ mpu401/ vx/ pcsp/
diff --git a/sound/drivers/pcsp/Makefile b/sound/drivers/pcsp/Makefile
new file mode 100644
index 00000000000..b19555b440d
--- /dev/null
+++ b/sound/drivers/pcsp/Makefile
@@ -0,0 +1,2 @@
+snd-pcsp-objs := pcsp.o pcsp_lib.o pcsp_mixer.o pcsp_input.o
+obj-$(CONFIG_SND_PCSP) += snd-pcsp.o
diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c
new file mode 100644
index 00000000000..34477286b39
--- /dev/null
+++ b/sound/drivers/pcsp/pcsp.c
@@ -0,0 +1,241 @@
+/*
+ * PC-Speaker driver for Linux
+ *
+ * Copyright (C) 1997-2001  David Woodhouse
+ * Copyright (C) 2001-2008  Stas Sergeev
+ */
+
+#include <linux/init.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+
+#include <linux/input.h>
+#include <linux/delay.h>
+#include <asm/bitops.h>
+#include "pcsp_input.h"
+#include "pcsp.h"
+
+MODULE_AUTHOR("Stas Sergeev <stsp@users.sourceforge.net>");
+MODULE_DESCRIPTION("PC-Speaker driver");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{PC-Speaker, pcsp}}");
+MODULE_ALIAS("platform:pcspkr");
+
+static int index = SNDRV_DEFAULT_IDX1;	/* Index 0-MAX */
+static char *id = SNDRV_DEFAULT_STR1;	/* ID for this card */
+static int enable = SNDRV_DEFAULT_ENABLE1;	/* Enable this card */
+
+module_param(index, int, 0444);
+MODULE_PARM_DESC(index, "Index value for pcsp soundcard.");
+module_param(id, charp, 0444);
+MODULE_PARM_DESC(id, "ID string for pcsp soundcard.");
+module_param(enable, bool, 0444);
+MODULE_PARM_DESC(enable, "dummy");
+
+struct snd_pcsp pcsp_chip;
+
+static int __devinit snd_pcsp_create(struct snd_card *card)
+{
+	static struct snd_device_ops ops = { };
+	struct timespec tp;
+	int err;
+	int div, min_div, order;
+
+	hrtimer_get_res(CLOCK_MONOTONIC, &tp);
+	if (tp.tv_sec || tp.tv_nsec > PCSP_MAX_PERIOD_NS) {
+		printk(KERN_ERR "PCSP: Timer resolution is not sufficient "
+		       "(%linS)\n", tp.tv_nsec);
+		printk(KERN_ERR "PCSP: Make sure you have HPET and ACPI "
+		       "enabled.\n");
+		return -EIO;
+	}
+
+	if (loops_per_jiffy >= PCSP_MIN_LPJ && tp.tv_nsec <= PCSP_MIN_PERIOD_NS)
+		min_div = MIN_DIV;
+	else
+		min_div = MAX_DIV;
+#if PCSP_DEBUG
+	printk("PCSP: lpj=%li, min_div=%i, res=%li\n",
+	       loops_per_jiffy, min_div, tp.tv_nsec);
+#endif
+
+	div = MAX_DIV / min_div;
+	order = fls(div) - 1;
+
+	pcsp_chip.max_treble = min(order, PCSP_MAX_TREBLE);
+	pcsp_chip.treble = min(pcsp_chip.max_treble, PCSP_DEFAULT_TREBLE);
+	pcsp_chip.playback_ptr = 0;
+	pcsp_chip.period_ptr = 0;
+	atomic_set(&pcsp_chip.timer_active, 0);
+	pcsp_chip.enable = 1;
+	pcsp_chip.pcspkr = 1;
+
+	spin_lock_init(&pcsp_chip.substream_lock);
+
+	pcsp_chip.card = card;
+	pcsp_chip.port = 0x61;
+	pcsp_chip.irq = -1;
+	pcsp_chip.dma = -1;
+
+	/* Register device */
+	err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, &pcsp_chip, &ops);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static int __devinit snd_card_pcsp_probe(int devnum, struct device *dev)
+{
+	struct snd_card *card;
+	int err;
+
+	if (devnum != 0)
+		return -EINVAL;
+
+	hrtimer_init(&pcsp_chip.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+	pcsp_chip.timer.cb_mode = HRTIMER_CB_IRQSAFE;
+	pcsp_chip.timer.function = pcsp_do_timer;
+
+	card = snd_card_new(index, id, THIS_MODULE, 0);
+	if (!card)
+		return -ENOMEM;
+
+	err = snd_pcsp_create(card);
+	if (err < 0) {
+		snd_card_free(card);
+		return err;
+	}
+	err = snd_pcsp_new_pcm(&pcsp_chip);
+	if (err < 0) {
+		snd_card_free(card);
+		return err;
+	}
+	err = snd_pcsp_new_mixer(&pcsp_chip);
+	if (err < 0) {
+		snd_card_free(card);
+		return err;
+	}
+
+	snd_card_set_dev(pcsp_chip.card, dev);
+
+	strcpy(card->driver, "PC-Speaker");
+	strcpy(card->shortname, "pcsp");
+	sprintf(card->longname, "Internal PC-Speaker at port 0x%x",
+		pcsp_chip.port);
+
+	err = snd_card_register(card);
+	if (err < 0) {
+		snd_card_free(card);
+		return err;
+	}
+
+	return 0;
+}
+
+static int __devinit alsa_card_pcsp_init(struct device *dev)
+{
+	int devnum = 0, cards = 0;
+
+#ifdef CONFIG_DEBUG_PAGEALLOC
+	/* Well, CONFIG_DEBUG_PAGEALLOC makes the sound horrible. Lets alert */
+	printk(KERN_WARNING
+	       "PCSP: Warning, CONFIG_DEBUG_PAGEALLOC is enabled!\n"
+	       "You have to disable it if you want to use the PC-Speaker "
+	       "driver.\n"
+	       "Unless it is disabled, enjoy the horrible, distorted "
+	       "and crackling noise.\n");
+#endif
+
+	if (enable) {
+		if (snd_card_pcsp_probe(devnum, dev) >= 0)
+			cards++;
+		if (!cards) {
+			printk(KERN_ERR "PC-Speaker initialization failed.\n");
+			return -ENODEV;
+		}
+	}
+
+	return 0;
+}
+
+static void __devexit alsa_card_pcsp_exit(struct snd_pcsp *chip)
+{
+	snd_card_free(chip->card);
+}
+
+static int __devinit pcsp_probe(struct platform_device *dev)
+{
+	int err;
+	err = pcspkr_input_init(&pcsp_chip.input_dev, &dev->dev);
+	if (err < 0)
+		return err;
+
+	err = alsa_card_pcsp_init(&dev->dev);
+	if (err < 0) {
+		pcspkr_input_remove(pcsp_chip.input_dev);
+		return err;
+	}
+
+	platform_set_drvdata(dev, &pcsp_chip);
+	return 0;
+}
+
+static int __devexit pcsp_remove(struct platform_device *dev)
+{
+	struct snd_pcsp *chip = platform_get_drvdata(dev);
+	alsa_card_pcsp_exit(chip);
+	pcspkr_input_remove(chip->input_dev);
+	platform_set_drvdata(dev, NULL);
+	return 0;
+}
+
+static void pcsp_stop_beep(struct snd_pcsp *chip)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&chip->substream_lock, flags);
+	if (!chip->playback_substream)
+		pcspkr_stop_sound();
+	spin_unlock_irqrestore(&chip->substream_lock, flags);
+}
+
+static int pcsp_suspend(struct platform_device *dev, pm_message_t state)
+{
+	struct snd_pcsp *chip = platform_get_drvdata(dev);
+	pcsp_stop_beep(chip);
+	snd_pcm_suspend_all(chip->pcm);
+	return 0;
+}
+
+static void pcsp_shutdown(struct platform_device *dev)
+{
+	struct snd_pcsp *chip = platform_get_drvdata(dev);
+	pcsp_stop_beep(chip);
+}
+
+static struct platform_driver pcsp_platform_driver = {
+	.driver		= {
+		.name	= "pcspkr",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= pcsp_probe,
+	.remove		= __devexit_p(pcsp_remove),
+	.suspend	= pcsp_suspend,
+	.shutdown	= pcsp_shutdown,
+};
+
+static int __init pcsp_init(void)
+{
+	return platform_driver_register(&pcsp_platform_driver);
+}
+
+static void __exit pcsp_exit(void)
+{
+	platform_driver_unregister(&pcsp_platform_driver);
+}
+
+module_init(pcsp_init);
+module_exit(pcsp_exit);
diff --git a/sound/drivers/pcsp/pcsp.h b/sound/drivers/pcsp/pcsp.h
new file mode 100644
index 00000000000..f07cc1ee1fe
--- /dev/null
+++ b/sound/drivers/pcsp/pcsp.h
@@ -0,0 +1,82 @@
+/*
+ * PC-Speaker driver for Linux
+ *
+ * Copyright (C) 1993-1997  Michael Beck
+ * Copyright (C) 1997-2001  David Woodhouse
+ * Copyright (C) 2001-2008  Stas Sergeev
+ */
+
+#ifndef __PCSP_H__
+#define __PCSP_H__
+
+#include <linux/hrtimer.h>
+#if defined(CONFIG_MIPS) || defined(CONFIG_X86)
+/* Use the global PIT lock ! */
+#include <asm/i8253.h>
+#else
+#include <asm/8253pit.h>
+static DEFINE_SPINLOCK(i8253_lock);
+#endif
+
+#define PCSP_SOUND_VERSION 0x400	/* read 4.00 */
+#define PCSP_DEBUG 0
+
+/* default timer freq for PC-Speaker: 18643 Hz */
+#define DIV_18KHZ 64
+#define MAX_DIV DIV_18KHZ
+#define CUR_DIV() (MAX_DIV >> chip->treble)
+#define PCSP_MAX_TREBLE 1
+
+/* unfortunately, with hrtimers 37KHz does not work very well :( */
+#define PCSP_DEFAULT_TREBLE 0
+#define MIN_DIV (MAX_DIV >> PCSP_MAX_TREBLE)
+
+/* wild guess */
+#define PCSP_MIN_LPJ 1000000
+#define PCSP_DEFAULT_SDIV (DIV_18KHZ >> 1)
+#define PCSP_DEFAULT_SRATE (PIT_TICK_RATE / PCSP_DEFAULT_SDIV)
+#define PCSP_INDEX_INC() (1 << (PCSP_MAX_TREBLE - chip->treble))
+#define PCSP_RATE() (PIT_TICK_RATE / CUR_DIV())
+#define PCSP_MIN_RATE__1 MAX_DIV/PIT_TICK_RATE
+#define PCSP_MAX_RATE__1 MIN_DIV/PIT_TICK_RATE
+#define PCSP_MAX_PERIOD_NS (1000000000ULL * PCSP_MIN_RATE__1)
+#define PCSP_MIN_PERIOD_NS (1000000000ULL * PCSP_MAX_RATE__1)
+#define PCSP_CALC_NS(div) ({ \
+	u64 __val = 1000000000ULL * (div); \
+	do_div(__val, PIT_TICK_RATE); \
+	__val; \
+})
+#define PCSP_PERIOD_NS() PCSP_CALC_NS(CUR_DIV())
+
+#define PCSP_MAX_PERIOD_SIZE	(64*1024)
+#define PCSP_MAX_PERIODS	512
+#define PCSP_BUFFER_SIZE	(128*1024)
+
+struct snd_pcsp {
+	struct snd_card *card;
+	struct snd_pcm *pcm;
+	struct input_dev *input_dev;
+	struct hrtimer timer;
+	unsigned short port, irq, dma;
+	spinlock_t substream_lock;
+	struct snd_pcm_substream *playback_substream;
+	size_t playback_ptr;
+	size_t period_ptr;
+	atomic_t timer_active;
+	int thalf;
+	u64 ns_rem;
+	unsigned char val61;
+	int enable;
+	int max_treble;
+	int treble;
+	int pcspkr;
+};
+
+extern struct snd_pcsp pcsp_chip;
+
+extern enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle);
+
+extern int snd_pcsp_new_pcm(struct snd_pcsp *chip);
+extern int snd_pcsp_new_mixer(struct snd_pcsp *chip);
+
+#endif
diff --git a/sound/drivers/pcsp/pcsp_input.c b/sound/drivers/pcsp/pcsp_input.c
new file mode 100644
index 00000000000..cd9b83e7f7d
--- /dev/null
+++ b/sound/drivers/pcsp/pcsp_input.c
@@ -0,0 +1,116 @@
+/*
+ *  PC Speaker beeper driver for Linux
+ *
+ *  Copyright (c) 2002 Vojtech Pavlik
+ *  Copyright (c) 1992 Orest Zborowski
+ *
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation
+ */
+
+#include <linux/init.h>
+#include <linux/input.h>
+#include <asm/io.h>
+#include "pcsp.h"
+
+static void pcspkr_do_sound(unsigned int count)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&i8253_lock, flags);
+
+	if (count) {
+		/* enable counter 2 */
+		outb_p(inb_p(0x61) | 3, 0x61);
+		/* set command for counter 2, 2 byte write */
+		outb_p(0xB6, 0x43);
+		/* select desired HZ */
+		outb_p(count & 0xff, 0x42);
+		outb((count >> 8) & 0xff, 0x42);
+	} else {
+		/* disable counter 2 */
+		outb(inb_p(0x61) & 0xFC, 0x61);
+	}
+
+	spin_unlock_irqrestore(&i8253_lock, flags);
+}
+
+void pcspkr_stop_sound(void)
+{
+	pcspkr_do_sound(0);
+}
+
+static int pcspkr_input_event(struct input_dev *dev, unsigned int type,
+			      unsigned int code, int value)
+{
+	unsigned int count = 0;
+
+	if (atomic_read(&pcsp_chip.timer_active) || !pcsp_chip.pcspkr)
+		return 0;
+
+	switch (type) {
+	case EV_SND:
+		switch (code) {
+		case SND_BELL:
+			if (value)
+				value = 1000;
+		case SND_TONE:
+			break;
+		default:
+			return -1;
+		}
+		break;
+
+	default:
+		return -1;
+	}
+
+	if (value > 20 && value < 32767)
+		count = PIT_TICK_RATE / value;
+
+	pcspkr_do_sound(count);
+
+	return 0;
+}
+
+int __devinit pcspkr_input_init(struct input_dev **rdev, struct device *dev)
+{
+	int err;
+
+	struct input_dev *input_dev = input_allocate_device();
+	if (!input_dev)
+		return -ENOMEM;
+
+	input_dev->name = "PC Speaker";
+	input_dev->phys = "isa0061/input0";
+	input_dev->id.bustype = BUS_ISA;
+	input_dev->id.vendor = 0x001f;
+	input_dev->id.product = 0x0001;
+	input_dev->id.version = 0x0100;
+	input_dev->dev.parent = dev;
+
+	input_dev->evbit[0] = BIT(EV_SND);
+	input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
+	input_dev->event = pcspkr_input_event;
+
+	err = input_register_device(input_dev);
+	if (err) {
+		input_free_device(input_dev);
+		return err;
+	}
+
+	*rdev = input_dev;
+	return 0;
+}
+
+int pcspkr_input_remove(struct input_dev *dev)
+{
+	pcspkr_stop_sound();
+	input_unregister_device(dev);	/* this also does kfree() */
+
+	return 0;
+}
diff --git a/sound/drivers/pcsp/pcsp_input.h b/sound/drivers/pcsp/pcsp_input.h
new file mode 100644
index 00000000000..e66738c7833
--- /dev/null
+++ b/sound/drivers/pcsp/pcsp_input.h
@@ -0,0 +1,14 @@
+/*
+ * PC-Speaker driver for Linux
+ *
+ * Copyright (C) 2001-2008  Stas Sergeev
+ */
+
+#ifndef __PCSP_INPUT_H__
+#define __PCSP_INPUT_H__
+
+int __devinit pcspkr_input_init(struct input_dev **rdev, struct device *dev);
+int pcspkr_input_remove(struct input_dev *dev);
+void pcspkr_stop_sound(void);
+
+#endif
diff --git a/sound/drivers/pcsp/pcsp_lib.c b/sound/drivers/pcsp/pcsp_lib.c
new file mode 100644
index 00000000000..6bdcb89129d
--- /dev/null
+++ b/sound/drivers/pcsp/pcsp_lib.c
@@ -0,0 +1,347 @@
+/*
+ * PC-Speaker driver for Linux
+ *
+ * Copyright (C) 1993-1997  Michael Beck
+ * Copyright (C) 1997-2001  David Woodhouse
+ * Copyright (C) 2001-2008  Stas Sergeev
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <linux/interrupt.h>
+#include <asm/io.h>
+#include <asm/i8253.h>
+#include "pcsp.h"
+
+static int nforce_wa;
+module_param(nforce_wa, bool, 0444);
+MODULE_PARM_DESC(nforce_wa, "Apply NForce chipset workaround "
+		"(expect bad sound)");
+
+#define DMIX_WANTS_S16	1
+
+static void pcsp_start_timer(unsigned long dummy)
+{
+	hrtimer_start(&pcsp_chip.timer, ktime_set(0, 0), HRTIMER_MODE_REL);
+}
+
+/*
+ * We need the hrtimer_start as a tasklet to avoid
+ * the nasty locking problem. :(
+ * The problem:
+ * - The timer handler is called with the cpu_base->lock
+ *   already held by hrtimer code.
+ * - snd_pcm_period_elapsed() takes the
+ *   substream->self_group.lock.
+ * So far so good.
+ * But the snd_pcsp_trigger() is called with the
+ * substream->self_group.lock held, and it calls
+ * hrtimer_start(), which takes the cpu_base->lock.
+ * You see the problem. We have the code pathes
+ * which take two locks in a reverse order. This
+ * can deadlock and the lock validator complains.
+ * The only solution I could find was to move the
+ * hrtimer_start() into a tasklet. -stsp
+ */
+DECLARE_TASKLET(pcsp_start_timer_tasklet, pcsp_start_timer, 0);
+
+enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle)
+{
+	unsigned long flags;
+	unsigned char timer_cnt, val;
+	int fmt_size, periods_elapsed;
+	u64 ns;
+	size_t period_bytes, buffer_bytes;
+	struct snd_pcm_substream *substream;
+	struct snd_pcm_runtime *runtime;
+	struct snd_pcsp *chip = container_of(handle, struct snd_pcsp, timer);
+
+	if (chip->thalf) {
+		outb(chip->val61, 0x61);
+		chip->thalf = 0;
+		if (!atomic_read(&chip->timer_active))
+			return HRTIMER_NORESTART;
+		hrtimer_forward(&chip->timer, chip->timer.expires,
+				ktime_set(0, chip->ns_rem));
+		return HRTIMER_RESTART;
+	}
+
+	/* hrtimer calls us from both hardirq and softirq contexts,
+	 * so irqsave :( */
+	spin_lock_irqsave(&chip->substream_lock, flags);
+	/* Takashi Iwai says regarding this extra lock:
+
+	If the irq handler handles some data on the DMA buffer, it should
+	do snd_pcm_stream_lock().
+	That protects basically against all races among PCM callbacks, yes.
+	However, there are two remaining issues:
+	1. The substream pointer you try to lock isn't protected _before_
+	  this lock yet.
+	2. snd_pcm_period_elapsed() itself acquires the lock.
+	The requirement of another lock is because of 1.  When you get
+	chip->playback_substream, it's not protected.
+	Keeping this lock while snd_pcm_period_elapsed() assures the substream
+	is still protected (at least, not released).  And the other status is
+	handled properly inside snd_pcm_stream_lock() in
+	snd_pcm_period_elapsed().
+
+	*/
+	if (!chip->playback_substream)
+		goto exit_nr_unlock1;
+	substream = chip->playback_substream;
+	snd_pcm_stream_lock(substream);
+	if (!atomic_read(&chip->timer_active))
+		goto exit_nr_unlock2;
+
+	runtime = substream->runtime;
+	fmt_size = snd_pcm_format_physical_width(runtime->format) >> 3;
+	/* assume it is mono! */
+	val = runtime->dma_area[chip->playback_ptr + fmt_size - 1];
+	if (snd_pcm_format_signed(runtime->format))
+		val ^= 0x80;
+	timer_cnt = val * CUR_DIV() / 256;
+
+	if (timer_cnt && chip->enable) {
+		spin_lock(&i8253_lock);
+		if (!nforce_wa) {
+			outb_p(chip->val61, 0x61);
+			outb_p(timer_cnt, 0x42);
+			outb(chip->val61 ^ 1, 0x61);
+		} else {
+			outb(chip->val61 ^ 2, 0x61);
+			chip->thalf = 1;
+		}
+		spin_unlock(&i8253_lock);
+	}
+
+	period_bytes = snd_pcm_lib_period_bytes(substream);
+	buffer_bytes = snd_pcm_lib_buffer_bytes(substream);
+	chip->playback_ptr += PCSP_INDEX_INC() * fmt_size;
+	periods_elapsed = chip->playback_ptr - chip->period_ptr;
+	if (periods_elapsed < 0) {
+		printk(KERN_WARNING "PCSP: playback_ptr inconsistent "
+			"(%zi %zi %zi)\n",
+			chip->playback_ptr, period_bytes, buffer_bytes);
+		periods_elapsed += buffer_bytes;
+	}
+	periods_elapsed /= period_bytes;
+	/* wrap the pointer _before_ calling snd_pcm_period_elapsed(),
+	 * or ALSA will BUG on us. */
+	chip->playback_ptr %= buffer_bytes;
+
+	snd_pcm_stream_unlock(substream);
+
+	if (periods_elapsed) {
+		snd_pcm_period_elapsed(substream);
+		chip->period_ptr += periods_elapsed * period_bytes;
+		chip->period_ptr %= buffer_bytes;
+	}
+
+	spin_unlock_irqrestore(&chip->substream_lock, flags);
+
+	if (!atomic_read(&chip->timer_active))
+		return HRTIMER_NORESTART;
+
+	chip->ns_rem = PCSP_PERIOD_NS();
+	ns = (chip->thalf ? PCSP_CALC_NS(timer_cnt) : chip->ns_rem);
+	chip->ns_rem -= ns;
+	hrtimer_forward(&chip->timer, chip->timer.expires, ktime_set(0, ns));
+	return HRTIMER_RESTART;
+
+exit_nr_unlock2:
+	snd_pcm_stream_unlock(substream);
+exit_nr_unlock1:
+	spin_unlock_irqrestore(&chip->substream_lock, flags);
+	return HRTIMER_NORESTART;
+}
+
+static void pcsp_start_playing(struct snd_pcsp *chip)
+{
+#if PCSP_DEBUG
+	printk(KERN_INFO "PCSP: start_playing called\n");
+#endif
+	if (atomic_read(&chip->timer_active)) {
+		printk(KERN_ERR "PCSP: Timer already active\n");
+		return;
+	}
+
+	spin_lock(&i8253_lock);
+	chip->val61 = inb(0x61) | 0x03;
+	outb_p(0x92, 0x43);	/* binary, mode 1, LSB only, ch 2 */
+	spin_unlock(&i8253_lock);
+	atomic_set(&chip->timer_active, 1);
+	chip->thalf = 0;
+
+	tasklet_schedule(&pcsp_start_timer_tasklet);
+}
+
+static void pcsp_stop_playing(struct snd_pcsp *chip)
+{
+#if PCSP_DEBUG
+	printk(KERN_INFO "PCSP: stop_playing called\n");
+#endif
+	if (!atomic_read(&chip->timer_active))
+		return;
+
+	atomic_set(&chip->timer_active, 0);
+	spin_lock(&i8253_lock);
+	/* restore the timer */
+	outb_p(0xb6, 0x43);	/* binary, mode 3, LSB/MSB, ch 2 */
+	outb(chip->val61 & 0xFC, 0x61);
+	spin_unlock(&i8253_lock);
+}
+
+static int snd_pcsp_playback_close(struct snd_pcm_substream *substream)
+{
+	struct snd_pcsp *chip = snd_pcm_substream_chip(substream);
+#if PCSP_DEBUG
+	printk(KERN_INFO "PCSP: close called\n");
+#endif
+	if (atomic_read(&chip->timer_active)) {
+		printk(KERN_ERR "PCSP: timer still active\n");
+		pcsp_stop_playing(chip);
+	}
+	spin_lock_irq(&chip->substream_lock);
+	chip->playback_substream = NULL;
+	spin_unlock_irq(&chip->substream_lock);
+	return 0;
+}
+
+static int snd_pcsp_playback_hw_params(struct snd_pcm_substream *substream,
+				       struct snd_pcm_hw_params *hw_params)
+{
+	int err;
+	err = snd_pcm_lib_malloc_pages(substream,
+				      params_buffer_bytes(hw_params));
+	if (err < 0)
+		return err;
+	return 0;
+}
+
+static int snd_pcsp_playback_hw_free(struct snd_pcm_substream *substream)
+{
+#if PCSP_DEBUG
+	printk(KERN_INFO "PCSP: hw_free called\n");
+#endif
+	return snd_pcm_lib_free_pages(substream);
+}
+
+static int snd_pcsp_playback_prepare(struct snd_pcm_substream *substream)
+{
+	struct snd_pcsp *chip = snd_pcm_substream_chip(substream);
+#if PCSP_DEBUG
+	printk(KERN_INFO "PCSP: prepare called, "
+			"size=%zi psize=%zi f=%zi f1=%i\n",
+			snd_pcm_lib_buffer_bytes(substream),
+			snd_pcm_lib_period_bytes(substream),
+			snd_pcm_lib_buffer_bytes(substream) /
+			snd_pcm_lib_period_bytes(substream),
+			substream->runtime->periods);
+#endif
+	chip->playback_ptr = 0;
+	chip->period_ptr = 0;
+	return 0;
+}
+
+static int snd_pcsp_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct snd_pcsp *chip = snd_pcm_substream_chip(substream);
+#if PCSP_DEBUG
+	printk(KERN_INFO "PCSP: trigger called\n");
+#endif
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+		pcsp_start_playing(chip);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+		pcsp_stop_playing(chip);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static snd_pcm_uframes_t snd_pcsp_playback_pointer(struct snd_pcm_substream
+						   *substream)
+{
+	struct snd_pcsp *chip = snd_pcm_substream_chip(substream);
+	return bytes_to_frames(substream->runtime, chip->playback_ptr);
+}
+
+static struct snd_pcm_hardware snd_pcsp_playback = {
+	.info = (SNDRV_PCM_INFO_INTERLEAVED |
+		 SNDRV_PCM_INFO_HALF_DUPLEX |
+		 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),
+	.formats = (SNDRV_PCM_FMTBIT_U8
+#if DMIX_WANTS_S16
+		    | SNDRV_PCM_FMTBIT_S16_LE
+#endif
+	    ),
+	.rates = SNDRV_PCM_RATE_KNOT,
+	.rate_min = PCSP_DEFAULT_SRATE,
+	.rate_max = PCSP_DEFAULT_SRATE,
+	.channels_min = 1,
+	.channels_max = 1,
+	.buffer_bytes_max = PCSP_BUFFER_SIZE,
+	.period_bytes_min = 64,
+	.period_bytes_max = PCSP_MAX_PERIOD_SIZE,
+	.periods_min = 2,
+	.periods_max = PCSP_MAX_PERIODS,
+	.fifo_size = 0,
+};
+
+static int snd_pcsp_playback_open(struct snd_pcm_substream *substream)
+{
+	struct snd_pcsp *chip = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+#if PCSP_DEBUG
+	printk(KERN_INFO "PCSP: open called\n");
+#endif
+	if (atomic_read(&chip->timer_active)) {
+		printk(KERN_ERR "PCSP: still active!!\n");
+		return -EBUSY;
+	}
+	runtime->hw = snd_pcsp_playback;
+	chip->playback_substream = substream;
+	return 0;
+}
+
+static struct snd_pcm_ops snd_pcsp_playback_ops = {
+	.open = snd_pcsp_playback_open,
+	.close = snd_pcsp_playback_close,
+	.ioctl = snd_pcm_lib_ioctl,
+	.hw_params = snd_pcsp_playback_hw_params,
+	.hw_free = snd_pcsp_playback_hw_free,
+	.prepare = snd_pcsp_playback_prepare,
+	.trigger = snd_pcsp_trigger,
+	.pointer = snd_pcsp_playback_pointer,
+};
+
+int __devinit snd_pcsp_new_pcm(struct snd_pcsp *chip)
+{
+	int err;
+
+	err = snd_pcm_new(chip->card, "pcspeaker", 0, 1, 0, &chip->pcm);
+	if (err < 0)
+		return err;
+
+	snd_pcm_set_ops(chip->pcm, SNDRV_PCM_STREAM_PLAYBACK,
+			&snd_pcsp_playback_ops);
+
+	chip->pcm->private_data = chip;
+	chip->pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
+	strcpy(chip->pcm->name, "pcsp");
+
+	snd_pcm_lib_preallocate_pages_for_all(chip->pcm,
+					      SNDRV_DMA_TYPE_CONTINUOUS,
+					      snd_dma_continuous_data
+					      (GFP_KERNEL), PCSP_BUFFER_SIZE,
+					      PCSP_BUFFER_SIZE);
+
+	return 0;
+}
diff --git a/sound/drivers/pcsp/pcsp_mixer.c b/sound/drivers/pcsp/pcsp_mixer.c
new file mode 100644
index 00000000000..64a695fef74
--- /dev/null
+++ b/sound/drivers/pcsp/pcsp_mixer.c
@@ -0,0 +1,143 @@
+/*
+ * PC-Speaker driver for Linux
+ *
+ * Mixer implementation.
+ * Copyright (C) 2001-2008  Stas Sergeev
+ */
+
+#include <sound/core.h>
+#include <sound/control.h>
+#include "pcsp.h"
+
+
+static int pcsp_enable_info(struct snd_kcontrol *kcontrol,
+			    struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+static int pcsp_enable_get(struct snd_kcontrol *kcontrol,
+			   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
+	ucontrol->value.integer.value[0] = chip->enable;
+	return 0;
+}
+
+static int pcsp_enable_put(struct snd_kcontrol *kcontrol,
+			   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
+	int changed = 0;
+	int enab = ucontrol->value.integer.value[0];
+	if (enab != chip->enable) {
+		chip->enable = enab;
+		changed = 1;
+	}
+	return changed;
+}
+
+static int pcsp_treble_info(struct snd_kcontrol *kcontrol,
+			    struct snd_ctl_elem_info *uinfo)
+{
+	struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = chip->max_treble + 1;
+	if (uinfo->value.enumerated.item > chip->max_treble)
+		uinfo->value.enumerated.item = chip->max_treble;
+	sprintf(uinfo->value.enumerated.name, "%d", PCSP_RATE());
+	return 0;
+}
+
+static int pcsp_treble_get(struct snd_kcontrol *kcontrol,
+			   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
+	ucontrol->value.enumerated.item[0] = chip->treble;
+	return 0;
+}
+
+static int pcsp_treble_put(struct snd_kcontrol *kcontrol,
+			   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
+	int changed = 0;
+	int treble = ucontrol->value.enumerated.item[0];
+	if (treble != chip->treble) {
+		chip->treble = treble;
+#if PCSP_DEBUG
+		printk(KERN_INFO "PCSP: rate set to %i\n", PCSP_RATE());
+#endif
+		changed = 1;
+	}
+	return changed;
+}
+
+static int pcsp_pcspkr_info(struct snd_kcontrol *kcontrol,
+			    struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+static int pcsp_pcspkr_get(struct snd_kcontrol *kcontrol,
+			   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
+	ucontrol->value.integer.value[0] = chip->pcspkr;
+	return 0;
+}
+
+static int pcsp_pcspkr_put(struct snd_kcontrol *kcontrol,
+			   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
+	int changed = 0;
+	int spkr = ucontrol->value.integer.value[0];
+	if (spkr != chip->pcspkr) {
+		chip->pcspkr = spkr;
+		changed = 1;
+	}
+	return changed;
+}
+
+#define PCSP_MIXER_CONTROL(ctl_type, ctl_name) \
+{ \
+	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER, \
+	.name =		ctl_name, \
+	.info =		pcsp_##ctl_type##_info, \
+	.get =		pcsp_##ctl_type##_get, \
+	.put =		pcsp_##ctl_type##_put, \
+}
+
+static struct snd_kcontrol_new __devinitdata snd_pcsp_controls[] = {
+	PCSP_MIXER_CONTROL(enable, "Master Playback Switch"),
+	PCSP_MIXER_CONTROL(treble, "BaseFRQ Playback Volume"),
+	PCSP_MIXER_CONTROL(pcspkr, "PC Speaker Playback Switch"),
+};
+
+int __devinit snd_pcsp_new_mixer(struct snd_pcsp *chip)
+{
+	struct snd_card *card = chip->card;
+	int i, err;
+
+	for (i = 0; i < ARRAY_SIZE(snd_pcsp_controls); i++) {
+		err = snd_ctl_add(card,
+				 snd_ctl_new1(snd_pcsp_controls + i,
+					      chip));
+		if (err < 0)
+			return err;
+	}
+
+	strcpy(card->mixername, "PC-Speaker");
+
+	return 0;
+}
-- 
cgit v1.2.3-70-g09d2


From ae092c9ede515bd6864b44efc2d83135bd3c535b Mon Sep 17 00:00:00 2001
From: Graeme Gregory <graeme@openmoko.org>
Date: Mon, 3 Mar 2008 17:19:45 +0100
Subject: [ALSA] soc - Add Invert Switch for ROUT2

GTA02 device has a speaker between LOUT2 & ROUT2 and in this mode ROUT2
needs to be inverted. This patch adds a mixer control for this.

Signed-off-by: Graeme Gregory <graeme@openmoko.org>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/soc/codecs/wm8753.c | 3 +++
 1 file changed, 3 insertions(+)

(limited to 'sound')

diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index 02882758415..76a5c7b05df 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -198,6 +198,7 @@ static const char *wm8753_mic_sel[] = {"Mic 1", "Mic 2", "Mic 3"};
 static const char *wm8753_dai_mode[] = {"DAI 0", "DAI 1", "DAI 2", "DAI 3"};
 static const char *wm8753_dat_sel[] = {"Stereo", "Left ADC", "Right ADC",
 	"Channel Swap"};
+static const char *wm8753_rout2_phase[] = {"Non Inverted", "Inverted"};
 
 static const struct soc_enum wm8753_enum[] = {
 SOC_ENUM_SINGLE(WM8753_BASS, 7, 2, wm8753_base),
@@ -228,6 +229,7 @@ SOC_ENUM_SINGLE(WM8753_ADC, 4, 2, wm8753_adc_filter),
 SOC_ENUM_SINGLE(WM8753_MICBIAS, 6, 3, wm8753_mic_sel),
 SOC_ENUM_SINGLE(WM8753_IOCTL, 2, 4, wm8753_dai_mode),
 SOC_ENUM_SINGLE(WM8753_ADC, 7, 4, wm8753_dat_sel),
+SOC_ENUM_SINGLE(WM8753_OUTCTL, 2, 2, wm8753_rout2_phase),
 };
 
 
@@ -330,6 +332,7 @@ SOC_SINGLE("Mic1 Capture Volume", WM8753_INCTL1, 5, 3, 0),
 SOC_ENUM_EXT("DAI Mode", wm8753_enum[26], wm8753_get_dai, wm8753_set_dai),
 
 SOC_ENUM("ADC Data Select", wm8753_enum[27]),
+SOC_ENUM("ROUT2 Phase", wm8753_enum[28]),
 };
 
 /* add non dapm controls */
-- 
cgit v1.2.3-70-g09d2


From 24982c5f7feca2f4d1b0b562a28b767d93a01ce0 Mon Sep 17 00:00:00 2001
From: Andrew Morton <akpm@linux-foundation.org>
Date: Tue, 4 Mar 2008 10:08:58 +0100
Subject: [ALSA] hda_intel needs dma-mapping.h

sparc32:

sound/pci/hda/hda_intel.c: In function 'azx_create':
sound/pci/hda/hda_intel.c:1838: error: 'DMA_64BIT_MASK' undeclared (first use in this function)
sound/pci/hda/hda_intel.c:1838: error: (Each undeclared identifier is reported only once
sound/pci/hda/hda_intel.c:1838: error: for each function it appears in.)

Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/hda_intel.c | 1 +
 1 file changed, 1 insertion(+)

(limited to 'sound')

diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index c495ca01294..48677f36f5e 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -39,6 +39,7 @@
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/dma-mapping.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/slab.h>
-- 
cgit v1.2.3-70-g09d2


From 9bf8e7ddeaf57f1ec534014c447705ad31d5d721 Mon Sep 17 00:00:00 2001
From: Harvey Harrison <harvey.harrison@gmail.com>
Date: Mon, 3 Mar 2008 15:32:18 -0800
Subject: [ALSA] sound: replace remaining __FUNCTION__ occurences

__FUNCTION__ is gcc-specific, use __func__

Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/arm/pxa2xx-ac97.c         |  8 ++++----
 sound/core/init.c               |  2 +-
 sound/isa/sb/sb16_csp.c         | 28 ++++++++++++++--------------
 sound/isa/sb/sb_common.c        |  6 +++---
 sound/oss/trident.h             |  2 +-
 sound/oss/vwsnd.c               |  6 +++---
 sound/pci/ad1889.c              |  4 ++--
 sound/pci/als300.c              |  4 ++--
 sound/pci/azt3328.c             |  4 ++--
 sound/pci/intel8x0.c            |  2 +-
 sound/soc/pxa/pxa2xx-ac97.c     |  8 ++++----
 sound/soc/s3c24xx/s3c24xx-i2s.c | 20 ++++++++++----------
 sound/soc/s3c24xx/s3c24xx-pcm.c | 28 ++++++++++++++--------------
 sound/soc/soc-dapm.c            |  2 +-
 14 files changed, 62 insertions(+), 62 deletions(-)

(limited to 'sound')

diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c
index 8704e2825b1..490729799e5 100644
--- a/sound/arm/pxa2xx-ac97.c
+++ b/sound/arm/pxa2xx-ac97.c
@@ -72,7 +72,7 @@ static unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg
 	if (wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1) <= 0 &&
 	    !((GSR | gsr_bits) & GSR_SDONE)) {
 		printk(KERN_ERR "%s: read error (ac97_reg=%d GSR=%#lx)\n",
-				__FUNCTION__, reg, GSR | gsr_bits);
+				__func__, reg, GSR | gsr_bits);
 		val = -1;
 		goto out;
 	}
@@ -104,7 +104,7 @@ static void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigne
 	if (wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_CDONE, 1) <= 0 &&
 	    !((GSR | gsr_bits) & GSR_CDONE))
 		printk(KERN_ERR "%s: write error (ac97_reg=%d GSR=%#lx)\n",
-				__FUNCTION__, reg, GSR | gsr_bits);
+				__func__, reg, GSR | gsr_bits);
 
 	mutex_unlock(&car_mutex);
 }
@@ -131,7 +131,7 @@ static void pxa2xx_ac97_reset(struct snd_ac97 *ac97)
 
 	if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR))) {
 		printk(KERN_INFO "%s: cold reset timeout (GSR=%#lx)\n",
-				 __FUNCTION__, gsr_bits);
+				 __func__, gsr_bits);
 
 		/* let's try warm reset */
 		gsr_bits = 0;
@@ -150,7 +150,7 @@ static void pxa2xx_ac97_reset(struct snd_ac97 *ac97)
 
 		if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)))
 			printk(KERN_INFO "%s: warm reset timeout (GSR=%#lx)\n",
-					 __FUNCTION__, gsr_bits);
+					 __func__, gsr_bits);
 	}
 
 	GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
diff --git a/sound/core/init.c b/sound/core/init.c
index e3338d6071e..f045f7db3ab 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -254,7 +254,7 @@ static int snd_disconnect_release(struct inode *inode, struct file *file)
 	if (likely(df))
 		return df->disconnected_f_op->release(inode, file);
 
-	panic("%s(%p, %p) failed!", __FUNCTION__, inode, file);
+	panic("%s(%p, %p) failed!", __func__, inode, file);
 }
 
 static unsigned int snd_disconnect_poll(struct file * file, poll_table * wait)
diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c
index bed29ca2223..f3fd7b4f466 100644
--- a/sound/isa/sb/sb16_csp.c
+++ b/sound/isa/sb/sb16_csp.c
@@ -331,7 +331,7 @@ static int snd_sb_csp_riff_load(struct snd_sb_csp * p,
 		return -EFAULT;
 	if ((file_h.name != RIFF_HEADER) ||
 	    (le32_to_cpu(file_h.len) >= SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE - sizeof(file_h))) {
-		snd_printd("%s: Invalid RIFF header\n", __FUNCTION__);
+		snd_printd("%s: Invalid RIFF header\n", __func__);
 		return -EINVAL;
 	}
 	data_ptr += sizeof(file_h);
@@ -340,7 +340,7 @@ static int snd_sb_csp_riff_load(struct snd_sb_csp * p,
 	if (copy_from_user(&item_type, data_ptr, sizeof(item_type)))
 		return -EFAULT;
 	if (item_type != CSP__HEADER) {
-		snd_printd("%s: Invalid RIFF file type\n", __FUNCTION__);
+		snd_printd("%s: Invalid RIFF file type\n", __func__);
 		return -EINVAL;
 	}
 	data_ptr += sizeof (item_type);
@@ -395,7 +395,7 @@ static int snd_sb_csp_riff_load(struct snd_sb_csp * p,
 				return -EFAULT;
 
 			if (code_h.name != MAIN_HEADER) {
-				snd_printd("%s: Missing 'main' microcode\n", __FUNCTION__);
+				snd_printd("%s: Missing 'main' microcode\n", __func__);
 				return -EINVAL;
 			}
 			data_ptr += sizeof(code_h);
@@ -439,7 +439,7 @@ static int snd_sb_csp_riff_load(struct snd_sb_csp * p,
 				p->acc_format = p->acc_width = p->acc_rates = 0;
 				p->mode = 0;
 				snd_printd("%s: Unsupported CSP codec type: 0x%04x\n",
-					   __FUNCTION__,
+					   __func__,
 					   le16_to_cpu(funcdesc_h.VOC_type));
 				return -EINVAL;
 			}
@@ -458,7 +458,7 @@ static int snd_sb_csp_riff_load(struct snd_sb_csp * p,
 			return 0;
 		}
 	}
-	snd_printd("%s: Function #%d not found\n", __FUNCTION__, info.func_req);
+	snd_printd("%s: Function #%d not found\n", __func__, info.func_req);
 	return -EINVAL;
 }
 
@@ -612,7 +612,7 @@ static int get_version(struct snd_sb *chip)
 static int snd_sb_csp_check_version(struct snd_sb_csp * p)
 {
 	if (p->version < 0x10 || p->version > 0x1f) {
-		snd_printd("%s: Invalid CSP version: 0x%x\n", __FUNCTION__, p->version);
+		snd_printd("%s: Invalid CSP version: 0x%x\n", __func__, p->version);
 		return 1;
 	}
 	return 0;
@@ -631,7 +631,7 @@ static int snd_sb_csp_load(struct snd_sb_csp * p, const unsigned char *buf, int
 	spin_lock_irqsave(&p->chip->reg_lock, flags);
 	snd_sbdsp_command(p->chip, 0x01);	/* CSP download command */
 	if (snd_sbdsp_get_byte(p->chip)) {
-		snd_printd("%s: Download command failed\n", __FUNCTION__);
+		snd_printd("%s: Download command failed\n", __func__);
 		goto __fail;
 	}
 	/* Send CSP low byte (size - 1) */
@@ -658,7 +658,7 @@ static int snd_sb_csp_load(struct snd_sb_csp * p, const unsigned char *buf, int
 			udelay (10);
 		}
 		if (status != 0x55) {
-			snd_printd("%s: Microcode initialization failed\n", __FUNCTION__);
+			snd_printd("%s: Microcode initialization failed\n", __func__);
 			goto __fail;
 		}
 	} else {
@@ -824,19 +824,19 @@ static int snd_sb_csp_start(struct snd_sb_csp * p, int sample_width, int channel
 	unsigned long flags;
 
 	if (!(p->running & (SNDRV_SB_CSP_ST_LOADED | SNDRV_SB_CSP_ST_AUTO))) {
-		snd_printd("%s: Microcode not loaded\n", __FUNCTION__);
+		snd_printd("%s: Microcode not loaded\n", __func__);
 		return -ENXIO;
 	}
 	if (p->running & SNDRV_SB_CSP_ST_RUNNING) {
-		snd_printd("%s: CSP already running\n", __FUNCTION__);
+		snd_printd("%s: CSP already running\n", __func__);
 		return -EBUSY;
 	}
 	if (!(sample_width & p->acc_width)) {
-		snd_printd("%s: Unsupported PCM sample width\n", __FUNCTION__);
+		snd_printd("%s: Unsupported PCM sample width\n", __func__);
 		return -EINVAL;
 	}
 	if (!(channels & p->acc_channels)) {
-		snd_printd("%s: Invalid number of channels\n", __FUNCTION__);
+		snd_printd("%s: Invalid number of channels\n", __func__);
 		return -EINVAL;
 	}
 
@@ -858,11 +858,11 @@ static int snd_sb_csp_start(struct snd_sb_csp * p, int sample_width, int channel
 		s_type |= 0x22;	/* 00dX 00dX    (d = 1 if 8 bit samples) */
 
 	if (set_codec_parameter(p->chip, 0x81, s_type)) {
-		snd_printd("%s: Set sample type command failed\n", __FUNCTION__);
+		snd_printd("%s: Set sample type command failed\n", __func__);
 		goto __fail;
 	}
 	if (set_codec_parameter(p->chip, 0x80, 0x00)) {
-		snd_printd("%s: Codec start command failed\n", __FUNCTION__);
+		snd_printd("%s: Codec start command failed\n", __func__);
 		goto __fail;
 	}
 	p->run_width = sample_width;
diff --git a/sound/isa/sb/sb_common.c b/sound/isa/sb/sb_common.c
index d63c1af550d..b432d9ae874 100644
--- a/sound/isa/sb/sb_common.c
+++ b/sound/isa/sb/sb_common.c
@@ -51,7 +51,7 @@ int snd_sbdsp_command(struct snd_sb *chip, unsigned char val)
 			outb(val, SBP(chip, COMMAND));
 			return 1;
 		}
-	snd_printd("%s [0x%lx]: timeout (0x%x)\n", __FUNCTION__, chip->port, val);
+	snd_printd("%s [0x%lx]: timeout (0x%x)\n", __func__, chip->port, val);
 	return 0;
 }
 
@@ -68,7 +68,7 @@ int snd_sbdsp_get_byte(struct snd_sb *chip)
 			return val;
 		}
 	}
-	snd_printd("%s [0x%lx]: timeout\n", __FUNCTION__, chip->port);
+	snd_printd("%s [0x%lx]: timeout\n", __func__, chip->port);
 	return -ENODEV;
 }
 
@@ -87,7 +87,7 @@ int snd_sbdsp_reset(struct snd_sb *chip)
 			else
 				break;
 		}
-	snd_printdd("%s [0x%lx] failed...\n", __FUNCTION__, chip->port);
+	snd_printdd("%s [0x%lx] failed...\n", __func__, chip->port);
 	return -ENODEV;
 }
 
diff --git a/sound/oss/trident.h b/sound/oss/trident.h
index 4713b49fc91..ff30a1d7c2f 100644
--- a/sound/oss/trident.h
+++ b/sound/oss/trident.h
@@ -322,7 +322,7 @@ enum miscint_bits {
 #define VALIDATE_MAGIC(FOO,MAG)				\
 ({						  	\
 	if (!(FOO) || (FOO)->magic != MAG) { 		\
-		printk(invalid_magic,__FUNCTION__);	\
+		printk(invalid_magic,__func__);	\
 		return -ENXIO;			  	\
 	}					  	\
 })
diff --git a/sound/oss/vwsnd.c b/sound/oss/vwsnd.c
index d25249a932b..2c5aaa58046 100644
--- a/sound/oss/vwsnd.c
+++ b/sound/oss/vwsnd.c
@@ -194,11 +194,11 @@ static void dbgassert(const char *fcn, int line, const char *expr)
  *	DBGRV	- debug print function return when verbose
  */
 
-#define ASSERT(e)      ((e) ? (void) 0 : dbgassert(__FUNCTION__, __LINE__, #e))
+#define ASSERT(e)      ((e) ? (void) 0 : dbgassert(__func__, __LINE__, #e))
 #define DBGDO(x)            x
 #define DBGX(fmt, args...)  (in_interrupt() ? 0 : printk(KERN_ERR fmt, ##args))
-#define DBGP(fmt, args...)  (DBGX("%s: " fmt, __FUNCTION__ , ##args))
-#define DBGE(fmt, args...)  (DBGX("%s" fmt, __FUNCTION__ , ##args))
+#define DBGP(fmt, args...)  (DBGX("%s: " fmt, __func__ , ##args))
+#define DBGE(fmt, args...)  (DBGX("%s" fmt, __func__ , ##args))
 #define DBGC(rtn)           (DBGP("calling %s\n", rtn))
 #define DBGR()              (DBGP("returning\n"))
 #define DBGXV(fmt, args...) (shut_up ? 0 : DBGX(fmt, ##args))
diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c
index a66d5150bb7..1edb6448946 100644
--- a/sound/pci/ad1889.c
+++ b/sound/pci/ad1889.c
@@ -264,10 +264,10 @@ snd_ad1889_ac97_ready(struct snd_ad1889 *chip)
 		mdelay(1);
 	if (!retry) {
 		snd_printk(KERN_ERR PFX "[%s] Link is not ready.\n",
-		       __FUNCTION__);
+		       __func__);
 		return -EIO;
 	}
-	ad1889_debug("[%s] ready after %d ms\n", __FUNCTION__, 400 - retry);
+	ad1889_debug("[%s] ready after %d ms\n", __func__, 400 - retry);
 
 	return 0;
 }
diff --git a/sound/pci/als300.c b/sound/pci/als300.c
index 0e990a73582..8df6824b51c 100644
--- a/sound/pci/als300.c
+++ b/sound/pci/als300.c
@@ -92,8 +92,8 @@
 
 #if DEBUG_CALLS
 #define snd_als300_dbgcalls(format, args...) printk(format, ##args)
-#define snd_als300_dbgcallenter() printk(KERN_ERR "--> %s\n", __FUNCTION__)
-#define snd_als300_dbgcallleave() printk(KERN_ERR "<-- %s\n", __FUNCTION__)
+#define snd_als300_dbgcallenter() printk(KERN_ERR "--> %s\n", __func__)
+#define snd_als300_dbgcallleave() printk(KERN_ERR "<-- %s\n", __func__)
 #else
 #define snd_als300_dbgcalls(format, args...)
 #define snd_als300_dbgcallenter()
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index 4e71a55120a..be87d3113ee 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -157,8 +157,8 @@ MODULE_SUPPORTED_DEVICE("{{Aztech,AZF3328}}");
 
 #if DEBUG_CALLS
 #define snd_azf3328_dbgcalls(format, args...) printk(format, ##args)
-#define snd_azf3328_dbgcallenter() printk(KERN_ERR "--> %s\n", __FUNCTION__)
-#define snd_azf3328_dbgcallleave() printk(KERN_ERR "<-- %s\n", __FUNCTION__)
+#define snd_azf3328_dbgcallenter() printk(KERN_ERR "--> %s\n", __func__)
+#define snd_azf3328_dbgcallleave() printk(KERN_ERR "<-- %s\n", __func__)
 #else
 #define snd_azf3328_dbgcalls(format, args...)
 #define snd_azf3328_dbgcallenter()
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index 07782ba9c74..47485afcab5 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -2670,7 +2670,7 @@ static void __devinit intel8x0_measure_ac97_clock(struct intel8x0 *chip)
 	t = stop_time.tv_sec - start_time.tv_sec;
 	t *= 1000000;
 	t += stop_time.tv_usec - start_time.tv_usec;
-	printk(KERN_INFO "%s: measured %lu usecs\n", __FUNCTION__, t);
+	printk(KERN_INFO "%s: measured %lu usecs\n", __func__, t);
 	if (t == 0) {
 		snd_printk(KERN_ERR "?? calculation error..\n");
 		return;
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
index e1737999880..1092d58e852 100644
--- a/sound/soc/pxa/pxa2xx-ac97.c
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -87,7 +87,7 @@ static unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97,
 	wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1);
 	if (!((GSR | gsr_bits) & GSR_SDONE)) {
 		printk(KERN_ERR "%s: read error (ac97_reg=%x GSR=%#lx)\n",
-				__FUNCTION__, reg, GSR | gsr_bits);
+				__func__, reg, GSR | gsr_bits);
 		val = -1;
 		goto out;
 	}
@@ -127,7 +127,7 @@ static void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
 	wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_CDONE, 1);
 	if (!((GSR | gsr_bits) & GSR_CDONE))
 		printk(KERN_ERR "%s: write error (ac97_reg=%x GSR=%#lx)\n",
-				__FUNCTION__, reg, GSR | gsr_bits);
+				__func__, reg, GSR | gsr_bits);
 
 	mutex_unlock(&car_mutex);
 }
@@ -151,7 +151,7 @@ static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97)
 
 	if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)))
 		printk(KERN_INFO "%s: warm reset timeout (GSR=%#lx)\n",
-				 __FUNCTION__, gsr_bits);
+				 __func__, gsr_bits);
 
 	GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
 	GCR |= GCR_SDONE_IE|GCR_CDONE_IE;
@@ -178,7 +178,7 @@ static void pxa2xx_ac97_cold_reset(struct snd_ac97 *ac97)
 
 	if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)))
 		printk(KERN_INFO "%s: cold reset timeout (GSR=%#lx)\n",
-				 __FUNCTION__, gsr_bits);
+				 __func__, gsr_bits);
 
 	GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
 	GCR |= GCR_SDONE_IE|GCR_CDONE_IE;
diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.c b/sound/soc/s3c24xx/s3c24xx-i2s.c
index 0a3c630951b..301002cd3fc 100644
--- a/sound/soc/s3c24xx/s3c24xx-i2s.c
+++ b/sound/soc/s3c24xx/s3c24xx-i2s.c
@@ -89,7 +89,7 @@ static void s3c24xx_snd_txctrl(int on)
 	u32 iiscon;
 	u32 iismod;
 
-	DBG("Entered %s\n", __FUNCTION__);
+	DBG("Entered %s\n", __func__);
 
 	iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON);
 	iiscon  = readl(s3c24xx_i2s.regs + S3C2410_IISCON);
@@ -134,7 +134,7 @@ static void s3c24xx_snd_rxctrl(int on)
 	u32 iiscon;
 	u32 iismod;
 
-	DBG("Entered %s\n", __FUNCTION__);
+	DBG("Entered %s\n", __func__);
 
 	iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON);
 	iiscon  = readl(s3c24xx_i2s.regs + S3C2410_IISCON);
@@ -182,7 +182,7 @@ static int s3c24xx_snd_lrsync(void)
 	u32 iiscon;
 	unsigned long timeout = jiffies + msecs_to_jiffies(5);
 
-	DBG("Entered %s\n", __FUNCTION__);
+	DBG("Entered %s\n", __func__);
 
 	while (1) {
 		iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON);
@@ -201,7 +201,7 @@ static int s3c24xx_snd_lrsync(void)
  */
 static inline int s3c24xx_snd_is_clkmaster(void)
 {
-	DBG("Entered %s\n", __FUNCTION__);
+	DBG("Entered %s\n", __func__);
 
 	return (readl(s3c24xx_i2s.regs + S3C2410_IISMOD) & S3C2410_IISMOD_SLAVE) ? 0:1;
 }
@@ -214,7 +214,7 @@ static int s3c24xx_i2s_set_fmt(struct snd_soc_cpu_dai *cpu_dai,
 {
 	u32 iismod;
 
-	DBG("Entered %s\n", __FUNCTION__);
+	DBG("Entered %s\n", __func__);
 
 	iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
 	DBG("hw_params r: IISMOD: %lx \n", iismod);
@@ -250,7 +250,7 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream,
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	u32 iismod;
 
-	DBG("Entered %s\n", __FUNCTION__);
+	DBG("Entered %s\n", __func__);
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 		rtd->dai->cpu_dai->dma_data = &s3c24xx_i2s_pcm_stereo_out;
@@ -278,7 +278,7 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
 {
 	int ret = 0;
 
-	DBG("Entered %s\n", __FUNCTION__);
+	DBG("Entered %s\n", __func__);
 
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
@@ -320,7 +320,7 @@ static int s3c24xx_i2s_set_sysclk(struct snd_soc_cpu_dai *cpu_dai,
 {
 	u32 iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
 
-	DBG("Entered %s\n", __FUNCTION__);
+	DBG("Entered %s\n", __func__);
 
 	iismod &= ~S3C2440_IISMOD_MPLL;
 
@@ -346,7 +346,7 @@ static int s3c24xx_i2s_set_clkdiv(struct snd_soc_cpu_dai *cpu_dai,
 {
 	u32 reg;
 
-	DBG("Entered %s\n", __FUNCTION__);
+	DBG("Entered %s\n", __func__);
 
 	switch (div_id) {
 	case S3C24XX_DIV_BCLK:
@@ -381,7 +381,7 @@ EXPORT_SYMBOL_GPL(s3c24xx_i2s_get_clockrate);
 
 static int s3c24xx_i2s_probe(struct platform_device *pdev)
 {
-	DBG("Entered %s\n", __FUNCTION__);
+	DBG("Entered %s\n", __func__);
 
 	s3c24xx_i2s.regs = ioremap(S3C2410_PA_IIS, 0x100);
 	if (s3c24xx_i2s.regs == NULL)
diff --git a/sound/soc/s3c24xx/s3c24xx-pcm.c b/sound/soc/s3c24xx/s3c24xx-pcm.c
index 29a6c82f873..40112e2b1ec 100644
--- a/sound/soc/s3c24xx/s3c24xx-pcm.c
+++ b/sound/soc/s3c24xx/s3c24xx-pcm.c
@@ -88,7 +88,7 @@ static void s3c24xx_pcm_enqueue(struct snd_pcm_substream *substream)
 	dma_addr_t pos = prtd->dma_pos;
 	int ret;
 
-	DBG("Entered %s\n", __FUNCTION__);
+	DBG("Entered %s\n", __func__);
 
 	while (prtd->dma_loaded < prtd->dma_limit) {
 		unsigned long len = prtd->dma_period;
@@ -98,7 +98,7 @@ static void s3c24xx_pcm_enqueue(struct snd_pcm_substream *substream)
 		if ((pos + len) > prtd->dma_end) {
 			len  = prtd->dma_end - pos;
 			DBG(KERN_DEBUG "%s: corrected dma len %ld\n",
-			       __FUNCTION__, len);
+			       __func__, len);
 		}
 
 		ret = s3c2410_dma_enqueue(prtd->params->channel, 
@@ -123,7 +123,7 @@ static void s3c24xx_audio_buffdone(struct s3c2410_dma_chan *channel,
 	struct snd_pcm_substream *substream = dev_id;
 	struct s3c24xx_runtime_data *prtd;
 
-	DBG("Entered %s\n", __FUNCTION__);
+	DBG("Entered %s\n", __func__);
 
 	if (result == S3C2410_RES_ABORT || result == S3C2410_RES_ERR)
 		return;
@@ -152,7 +152,7 @@ static int s3c24xx_pcm_hw_params(struct snd_pcm_substream *substream,
 	unsigned long totbytes = params_buffer_bytes(params);
 	int ret=0;
 
-	DBG("Entered %s\n", __FUNCTION__);
+	DBG("Entered %s\n", __func__);
 
 	/* return if this is a bufferless transfer e.g.
 	 * codec <--> BT codec or GSM modem -- lg FIXME */
@@ -200,7 +200,7 @@ static int s3c24xx_pcm_hw_free(struct snd_pcm_substream *substream)
 {
 	struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
 
-	DBG("Entered %s\n", __FUNCTION__);
+	DBG("Entered %s\n", __func__);
 
 	/* TODO - do we need to ensure DMA flushed */
 	snd_pcm_set_runtime_buffer(substream, NULL);
@@ -218,7 +218,7 @@ static int s3c24xx_pcm_prepare(struct snd_pcm_substream *substream)
 	struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
 	int ret = 0;
 
-	DBG("Entered %s\n", __FUNCTION__);
+	DBG("Entered %s\n", __func__);
 
 	/* return if this is a bufferless transfer e.g.
 	 * codec <--> BT codec or GSM modem -- lg FIXME */
@@ -263,7 +263,7 @@ static int s3c24xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 	struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
 	int ret = 0;
 
-	DBG("Entered %s\n", __FUNCTION__);
+	DBG("Entered %s\n", __func__);
 
 	spin_lock(&prtd->lock);
 
@@ -301,7 +301,7 @@ static snd_pcm_uframes_t
 	unsigned long res;
 	dma_addr_t src, dst;
 
-	DBG("Entered %s\n", __FUNCTION__);
+	DBG("Entered %s\n", __func__);
 
 	spin_lock(&prtd->lock);
 	s3c2410_dma_getposition(prtd->params->channel, &src, &dst);
@@ -334,7 +334,7 @@ static int s3c24xx_pcm_open(struct snd_pcm_substream *substream)
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct s3c24xx_runtime_data *prtd;
 
-	DBG("Entered %s\n", __FUNCTION__);
+	DBG("Entered %s\n", __func__);
 
 	snd_soc_set_runtime_hwparams(substream, &s3c24xx_pcm_hardware);
 
@@ -353,7 +353,7 @@ static int s3c24xx_pcm_close(struct snd_pcm_substream *substream)
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct s3c24xx_runtime_data *prtd = runtime->private_data;
 
-	DBG("Entered %s\n", __FUNCTION__);
+	DBG("Entered %s\n", __func__);
 
 	if (prtd)
 		kfree(prtd);
@@ -368,7 +368,7 @@ static int s3c24xx_pcm_mmap(struct snd_pcm_substream *substream,
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
 
-	DBG("Entered %s\n", __FUNCTION__);
+	DBG("Entered %s\n", __func__);
 
 	return dma_mmap_writecombine(substream->pcm->card->dev, vma,
                                      runtime->dma_area,
@@ -394,7 +394,7 @@ static int s3c24xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
 	struct snd_dma_buffer *buf = &substream->dma_buffer;
 	size_t size = s3c24xx_pcm_hardware.buffer_bytes_max;
 
-	DBG("Entered %s\n", __FUNCTION__);
+	DBG("Entered %s\n", __func__);
 
 	buf->dev.type = SNDRV_DMA_TYPE_DEV;
 	buf->dev.dev = pcm->card->dev;
@@ -413,7 +413,7 @@ static void s3c24xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
 	struct snd_dma_buffer *buf;
 	int stream;
 
-	DBG("Entered %s\n", __FUNCTION__);
+	DBG("Entered %s\n", __func__);
 
 	for (stream = 0; stream < 2; stream++) {
 		substream = pcm->streams[stream].substream;
@@ -437,7 +437,7 @@ static int s3c24xx_pcm_new(struct snd_card *card,
 {
 	int ret = 0;
 
-	DBG("Entered %s\n", __FUNCTION__);
+	DBG("Entered %s\n", __func__);
 
 	if (!card->dev->dma_mask)
 		card->dev->dma_mask = &s3c24xx_pcm_dmamask;
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index abac6847eca..4c64560493f 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -1288,7 +1288,7 @@ int snd_soc_dapm_stream_event(struct snd_soc_codec *codec,
 	mutex_unlock(&codec->mutex);
 
 	dapm_power_widgets(codec, event);
-	dump_dapm(codec, __FUNCTION__);
+	dump_dapm(codec, __func__);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event);
-- 
cgit v1.2.3-70-g09d2


From fd2499f0ed765de3ab11c7fd6f37f9fbfaf059ec Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Tue, 4 Mar 2008 11:06:26 +0100
Subject: [ALSA] aw2 - Remove endian dependency

Removed unnecessary dependency on the little-endianess.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/aw2/aw2-tsl.h | 6 ------
 1 file changed, 6 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/aw2/aw2-tsl.h b/sound/pci/aw2/aw2-tsl.h
index e8afaa0a468..459b0311ea3 100644
--- a/sound/pci/aw2/aw2-tsl.h
+++ b/sound/pci/aw2/aw2-tsl.h
@@ -72,10 +72,6 @@
     /*      SD3:          >-------<_4-L___>-------<_4-R___> */
     /*      WS4:          -------\_______________/--------- */
 
-#ifdef __BIG_ENDIAN
-    /* TODO: not yet implemented */
-#else /*  */
-
 static int tsl1[8] = {
 	1 * TSL_SDW_A1 | 3 * TSL_BSEL_A1 |
 	0 * TSL_DIS_A1 | 0 * TSL_DOD_A1 | TSL_LF_A1,
@@ -112,5 +108,3 @@ static int tsl2[8] = {
 	0 * TSL_SDW_A2 | 1 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_WS2,
 	0 * TSL_SDW_A2 | 0 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_WS2 | TSL_EOS
 };
-
-#endif /*  */
-- 
cgit v1.2.3-70-g09d2


From 368c7a95ea324b3f9728ba1c901ac119d409bf4e Mon Sep 17 00:00:00 2001
From: Jiang zhe <zhe.jiang@intel.com>
Date: Tue, 4 Mar 2008 11:20:33 +0100
Subject: [ALSA] hda-codec - model for alc883 to support M720R

There is no suitable model for M720R (ALSA bug#3781).
This patch is to support HP jack-sensing and mixer.

Signed-off-by: Jiang zhe <zhe.jiang@intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c | 76 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 76 insertions(+)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 33c9505adba..f321abd91e0 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -201,6 +201,7 @@ enum {
 	ALC888_3ST_HP,
 	ALC888_6ST_DELL,
 	ALC883_MITAC,
+	ALC883_CLEVO_M720R,
 	ALC883_AUTO,
 	ALC883_MODEL_LAST,
 };
@@ -6645,6 +6646,33 @@ static struct snd_kcontrol_new alc883_mitac_mixer[] = {
 	{ } /* end */
 };
 
+static struct snd_kcontrol_new alc883_clevo_m720r_mixer[] = {
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		/* .name = "Capture Source", */
+		.name = "Input Source",
+		.count = 2,
+		.info = alc883_mux_enum_info,
+		.get = alc883_mux_enum_get,
+		.put = alc883_mux_enum_put,
+	},
+	{ } /* end */
+};
+
 static struct snd_kcontrol_new alc883_3ST_2ch_mixer[] = {
 	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
 	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
@@ -7178,6 +7206,20 @@ static struct hda_verb alc883_mitac_verbs[] = {
 	{ } /* end */
 };
 
+static struct hda_verb alc883_clevo_m720r_verbs[] = {
+	/* HP */
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	/* Int speaker */
+	{0x14, AC_VERB_SET_CONNECT_SEL, 0x01},
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+
+	/* enable unsolicited event */
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
+
+	{ } /* end */
+};
+
 static struct hda_verb alc883_tagra_verbs[] = {
 	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
@@ -7361,6 +7403,26 @@ static void alc883_tagra_unsol_event(struct hda_codec *codec, unsigned int res)
 		alc883_tagra_automute(codec);
 }
 
+/* toggle speaker-output according to the hp-jack state */
+static void alc883_clevo_m720r_automute(struct hda_codec *codec)
+{
+	unsigned int present;
+	unsigned char bits;
+
+	present = snd_hda_codec_read(codec, 0x15, 0, AC_VERB_GET_PIN_SENSE, 0)
+		& AC_PINSENSE_PRESENCE;
+	bits = present ? HDA_AMP_MUTE : 0;
+	snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+				 HDA_AMP_MUTE, bits);
+}
+
+static void alc883_clevo_m720r_unsol_event(struct hda_codec *codec,
+					   unsigned int res)
+{
+	if ((res >> 26) == ALC880_HP_EVENT)
+		alc883_clevo_m720r_automute(codec);
+}
+
 static void alc883_haier_w66_automute(struct hda_codec *codec)
 {
 	unsigned int present;
@@ -7598,6 +7660,7 @@ static const char *alc883_models[ALC883_MODEL_LAST] = {
 	[ALC888_3ST_HP]		= "3stack-hp",
 	[ALC888_6ST_DELL]	= "6stack-dell",
 	[ALC883_MITAC]		= "mitac",
+	[ALC883_CLEVO_M720R]	= "clevo-m720r",
 	[ALC883_AUTO]		= "auto",
 };
 
@@ -7638,6 +7701,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
 	SND_PCI_QUIRK(0x1462, 0x7327, "MSI", ALC883_6ST_DIG),
 	SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG),
 	SND_PCI_QUIRK(0x147b, 0x1083, "Abit IP35-PRO", ALC883_6ST_DIG),
+	SND_PCI_QUIRK(0x1558, 0x0721, "Clevo laptop M720R", ALC883_CLEVO_M720R),
 	SND_PCI_QUIRK(0x1558, 0, "Clevo laptop", ALC883_LAPTOP_EAPD),
 	SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch),
 	SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION),
@@ -7780,6 +7844,18 @@ static struct alc_config_preset alc883_presets[] = {
 		.channel_mode = alc883_3ST_2ch_modes,
 		.input_mux = &alc883_capture_source,
 	},
+	[ALC883_CLEVO_M720R] = {
+		.mixers = { alc883_clevo_m720r_mixer },
+		.init_verbs = { alc883_init_verbs, alc883_clevo_m720r_verbs },
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.dig_out_nid = ALC883_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+		.channel_mode = alc883_3ST_2ch_modes,
+		.input_mux = &alc883_capture_source,
+		.unsol_event = alc883_clevo_m720r_unsol_event,
+		.init_hook = alc883_clevo_m720r_automute,
+	},
 	[ALC883_LENOVO_101E_2ch] = {
 		.mixers = { alc883_lenovo_101e_2ch_mixer},
 		.init_verbs = { alc883_init_verbs, alc883_lenovo_101e_verbs},
-- 
cgit v1.2.3-70-g09d2


From a91605b86a234b01d2f99b38411ac30a40bdf067 Mon Sep 17 00:00:00 2001
From: Stas Sergeev <stsp@aknet.ru>
Date: Tue, 4 Mar 2008 11:28:43 +0100
Subject: [ALSA] pcsp - clean ups

- make pcsp_start_timer_tasklet static
- remove redundant includes. <asm/i8253.h> is not available on all platforms.

Signed-off-by: Stas Sergeev <stsp@aknet.ru>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/drivers/pcsp/pcsp.c     | 2 --
 sound/drivers/pcsp/pcsp_lib.c | 4 +---
 2 files changed, 1 insertion(+), 5 deletions(-)

(limited to 'sound')

diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c
index 34477286b39..264d2a56dcd 100644
--- a/sound/drivers/pcsp/pcsp.c
+++ b/sound/drivers/pcsp/pcsp.c
@@ -11,9 +11,7 @@
 #include <sound/core.h>
 #include <sound/initval.h>
 #include <sound/pcm.h>
-
 #include <linux/input.h>
-#include <linux/delay.h>
 #include <asm/bitops.h>
 #include "pcsp_input.h"
 #include "pcsp.h"
diff --git a/sound/drivers/pcsp/pcsp_lib.c b/sound/drivers/pcsp/pcsp_lib.c
index 6bdcb89129d..a302756eac7 100644
--- a/sound/drivers/pcsp/pcsp_lib.c
+++ b/sound/drivers/pcsp/pcsp_lib.c
@@ -9,10 +9,8 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <sound/pcm.h>
-#include <sound/pcm_params.h>
 #include <linux/interrupt.h>
 #include <asm/io.h>
-#include <asm/i8253.h>
 #include "pcsp.h"
 
 static int nforce_wa;
@@ -45,7 +43,7 @@ static void pcsp_start_timer(unsigned long dummy)
  * The only solution I could find was to move the
  * hrtimer_start() into a tasklet. -stsp
  */
-DECLARE_TASKLET(pcsp_start_timer_tasklet, pcsp_start_timer, 0);
+static DECLARE_TASKLET(pcsp_start_timer_tasklet, pcsp_start_timer, 0);
 
 enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle)
 {
-- 
cgit v1.2.3-70-g09d2


From 8280823668d42ed9695da759047b86074ad14ba4 Mon Sep 17 00:00:00 2001
From: Pascal Terjan <pterjan@mandriva.com>
Date: Tue, 4 Mar 2008 11:33:28 +0100
Subject: [ALSA] ALC288 - Add NEC S970 to the quirk table

NEC S970 has no sound in the internal speakers when autodetection is
used.
With targa-dig model, there is sound in the speakers and it gets
correctly muted when pluging headphones.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c | 1 +
 1 file changed, 1 insertion(+)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index f321abd91e0..d2e81d0fcd0 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -7685,6 +7685,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
 	SND_PCI_QUIRK(0x1462, 0x040d, "MSI", ALC883_TARGA_2ch_DIG),
 	SND_PCI_QUIRK(0x1462, 0x0579, "MSI", ALC883_TARGA_2ch_DIG),
 	SND_PCI_QUIRK(0x1462, 0x3729, "MSI S420", ALC883_TARGA_DIG),
+	SND_PCI_QUIRK(0x1462, 0x3783, "NEC S970", ALC883_TARGA_DIG),
 	SND_PCI_QUIRK(0x1462, 0x3b7f, "MSI", ALC883_TARGA_2ch_DIG),
 	SND_PCI_QUIRK(0x1462, 0x3ef9, "MSI", ALC883_TARGA_DIG),
 	SND_PCI_QUIRK(0x1462, 0x3fc1, "MSI", ALC883_TARGA_DIG),
-- 
cgit v1.2.3-70-g09d2


From 52337310af443278ee84ec4b9adaee0037cc0e30 Mon Sep 17 00:00:00 2001
From: Stas Sergeev <stsp@aknet.ru>
Date: Thu, 6 Mar 2008 11:01:16 +0100
Subject: [ALSA] pcsp: improve "enable" option handling

Simplify init code.

Signed-off-by: Stas Sergeev <stsp@aknet.ru>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/drivers/pcsp/pcsp.c | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

(limited to 'sound')

diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c
index 264d2a56dcd..547005cb094 100644
--- a/sound/drivers/pcsp/pcsp.c
+++ b/sound/drivers/pcsp/pcsp.c
@@ -31,7 +31,7 @@ MODULE_PARM_DESC(index, "Index value for pcsp soundcard.");
 module_param(id, charp, 0444);
 MODULE_PARM_DESC(id, "ID string for pcsp soundcard.");
 module_param(enable, bool, 0444);
-MODULE_PARM_DESC(enable, "dummy");
+MODULE_PARM_DESC(enable, "Enable PC-Speaker sound.");
 
 struct snd_pcsp pcsp_chip;
 
@@ -136,7 +136,13 @@ static int __devinit snd_card_pcsp_probe(int devnum, struct device *dev)
 
 static int __devinit alsa_card_pcsp_init(struct device *dev)
 {
-	int devnum = 0, cards = 0;
+	int err;
+
+	err = snd_card_pcsp_probe(0, dev);
+	if (err) {
+		printk(KERN_ERR "PC-Speaker initialization failed.\n");
+		return err;
+	}
 
 #ifdef CONFIG_DEBUG_PAGEALLOC
 	/* Well, CONFIG_DEBUG_PAGEALLOC makes the sound horrible. Lets alert */
@@ -148,15 +154,6 @@ static int __devinit alsa_card_pcsp_init(struct device *dev)
 	       "and crackling noise.\n");
 #endif
 
-	if (enable) {
-		if (snd_card_pcsp_probe(devnum, dev) >= 0)
-			cards++;
-		if (!cards) {
-			printk(KERN_ERR "PC-Speaker initialization failed.\n");
-			return -ENODEV;
-		}
-	}
-
 	return 0;
 }
 
@@ -168,6 +165,7 @@ static void __devexit alsa_card_pcsp_exit(struct snd_pcsp *chip)
 static int __devinit pcsp_probe(struct platform_device *dev)
 {
 	int err;
+
 	err = pcspkr_input_init(&pcsp_chip.input_dev, &dev->dev);
 	if (err < 0)
 		return err;
@@ -227,6 +225,8 @@ static struct platform_driver pcsp_platform_driver = {
 
 static int __init pcsp_init(void)
 {
+	if (!enable)
+		return -ENODEV;
 	return platform_driver_register(&pcsp_platform_driver);
 }
 
-- 
cgit v1.2.3-70-g09d2


From fb97dc67397c1ee63eb0094c28fc9a5dcc0a83a6 Mon Sep 17 00:00:00 2001
From: Jiang zhe <zhe.jiang@intel.com>
Date: Thu, 6 Mar 2008 11:07:11 +0100
Subject: [ALSA] hda-codec - model for alc883 to support FUJITSU Pi2515

There is no suitable model for Pi2515.
This model is to support it.  ALSA bug#3800.

Signed-off-by: Jiang zhe <zhe.jiang@intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c | 85 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 85 insertions(+)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index d2e81d0fcd0..41bcbfd1059 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -202,6 +202,7 @@ enum {
 	ALC888_6ST_DELL,
 	ALC883_MITAC,
 	ALC883_CLEVO_M720R,
+	ALC883_FUJITSU_PI2515,
 	ALC883_AUTO,
 	ALC883_MODEL_LAST,
 };
@@ -6484,6 +6485,14 @@ static struct hda_input_mux alc883_lenovo_nb0763_capture_source = {
 	},
 };
 
+static struct hda_input_mux alc883_fujitsu_pi2515_capture_source = {
+	.num_items = 2,
+	.items = {
+		{ "Mic", 0x0 },
+		{ "Int Mic", 0x1 },
+	},
+};
+
 #define alc883_mux_enum_info alc_mux_enum_info
 #define alc883_mux_enum_get alc_mux_enum_get
 /* ALC883 has the ALC882-type input selection */
@@ -6673,6 +6682,33 @@ static struct snd_kcontrol_new alc883_clevo_m720r_mixer[] = {
 	{ } /* end */
 };
 
+static struct snd_kcontrol_new alc883_2ch_fujitsu_pi2515_mixer[] = {
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		/* .name = "Capture Source", */
+		.name = "Input Source",
+		.count = 2,
+		.info = alc883_mux_enum_info,
+		.get = alc883_mux_enum_get,
+		.put = alc883_mux_enum_put,
+	},
+	{ } /* end */
+};
+
 static struct snd_kcontrol_new alc883_3ST_2ch_mixer[] = {
 	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
 	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
@@ -7220,6 +7256,20 @@ static struct hda_verb alc883_clevo_m720r_verbs[] = {
 	{ } /* end */
 };
 
+static struct hda_verb alc883_2ch_fujitsu_pi2515_verbs[] = {
+	/* HP */
+	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	/* Subwoofer */
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+
+	/* enable unsolicited event */
+	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
+
+	{ } /* end */
+};
+
 static struct hda_verb alc883_tagra_verbs[] = {
 	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
@@ -7423,6 +7473,26 @@ static void alc883_clevo_m720r_unsol_event(struct hda_codec *codec,
 		alc883_clevo_m720r_automute(codec);
 }
 
+/* toggle speaker-output according to the hp-jack state */
+static void alc883_2ch_fujitsu_pi2515_automute(struct hda_codec *codec)
+{
+ 	unsigned int present;
+	unsigned char bits;
+
+ 	present = snd_hda_codec_read(codec, 0x14, 0, AC_VERB_GET_PIN_SENSE, 0)
+		& AC_PINSENSE_PRESENCE;
+	bits = present ? HDA_AMP_MUTE : 0;
+	snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
+				 HDA_AMP_MUTE, bits);
+}
+
+static void alc883_2ch_fujitsu_pi2515_unsol_event(struct hda_codec *codec,
+						  unsigned int res)
+{
+	if ((res >> 26) == ALC880_HP_EVENT)
+		alc883_2ch_fujitsu_pi2515_automute(codec);
+}
+
 static void alc883_haier_w66_automute(struct hda_codec *codec)
 {
 	unsigned int present;
@@ -7661,6 +7731,7 @@ static const char *alc883_models[ALC883_MODEL_LAST] = {
 	[ALC888_6ST_DELL]	= "6stack-dell",
 	[ALC883_MITAC]		= "mitac",
 	[ALC883_CLEVO_M720R]	= "clevo-m720r",
+	[ALC883_FUJITSU_PI2515] = "fujitsu-pi2515",
 	[ALC883_AUTO]		= "auto",
 };
 
@@ -7706,6 +7777,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
 	SND_PCI_QUIRK(0x1558, 0, "Clevo laptop", ALC883_LAPTOP_EAPD),
 	SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch),
 	SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION),
+	SND_PCI_QUIRK(0x1734, 0x1108, "Fujitsu AMILO Pi2515", ALC883_FUJITSU_PI2515),
 	SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo 101e", ALC883_LENOVO_101E_2ch),
 	SND_PCI_QUIRK(0x17aa, 0x2085, "Lenovo NB0763", ALC883_LENOVO_NB0763),
 	SND_PCI_QUIRK(0x17aa, 0x3bfc, "Lenovo NB0763", ALC883_LENOVO_NB0763),
@@ -7950,6 +8022,19 @@ static struct alc_config_preset alc883_presets[] = {
 		.unsol_event = alc883_mitac_unsol_event,
 		.init_hook = alc883_mitac_automute,
 	},
+	[ALC883_FUJITSU_PI2515] = {
+		.mixers = { alc883_2ch_fujitsu_pi2515_mixer },
+		.init_verbs = { alc883_init_verbs,
+				alc883_2ch_fujitsu_pi2515_verbs},
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.dig_out_nid = ALC883_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+		.channel_mode = alc883_3ST_2ch_modes,
+		.input_mux = &alc883_fujitsu_pi2515_capture_source,
+		.unsol_event = alc883_2ch_fujitsu_pi2515_unsol_event,
+		.init_hook = alc883_2ch_fujitsu_pi2515_automute,
+	},
 };
 
 
-- 
cgit v1.2.3-70-g09d2


From 2de3c232a0050ee247ae6e97b055f39e15a08ee3 Mon Sep 17 00:00:00 2001
From: Jiang zhe <zhe.jiang@intel.com>
Date: Thu, 6 Mar 2008 11:09:09 +0100
Subject: [ALSA] hda-codec - model for cx20549 to support laptop HP530

Currently the model laptop-hpsense use the 0x12 as ExtMic,
and use 0x14 as Internal IntMic.
But the hp530 only have one ExtMic, the Pin widget is 0x14.

In this patch, I changed the mixer item for them.
I still reserved the IntMic item, it will be helpful if
other machine may use this model.

ALSA bug#3821.

Signed-off-by: Jiang zhe <zhe.jiang@intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_conexant.c | 51 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 50 insertions(+), 1 deletion(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index e4fa9a35848..c67613ff842 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -519,6 +519,14 @@ static struct hda_input_mux cxt5045_capture_source_benq = {
 	}
 };
 
+static struct hda_input_mux cxt5045_capture_source_hp530 = {
+	.num_items = 2,
+	.items = {
+		{ "ExtMic", 0x1 },
+		{ "IntMic", 0x2 },
+	}
+};
+
 /* turn on/off EAPD (+ mute HP) as a master switch */
 static int cxt5045_hp_master_sw_put(struct snd_kcontrol *kcontrol,
 				    struct snd_ctl_elem_value *ucontrol)
@@ -647,6 +655,37 @@ static struct snd_kcontrol_new cxt5045_benq_mixers[] = {
 	{}
 };
 
+static struct snd_kcontrol_new cxt5045_mixers_hp530[] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Capture Source",
+		.info = conexant_mux_enum_info,
+		.get = conexant_mux_enum_get,
+		.put = conexant_mux_enum_put
+	},
+	HDA_CODEC_VOLUME("Int Mic Capture Volume", 0x1a, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Int Mic Capture Switch", 0x1a, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Ext Mic Capture Volume", 0x1a, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Ext Mic Capture Switch", 0x1a, 0x01, HDA_INPUT),
+	HDA_CODEC_VOLUME("PCM Playback Volume", 0x17, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("PCM Playback Switch", 0x17, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x17, 0x2, HDA_INPUT),
+	HDA_CODEC_MUTE("Int Mic Playback Switch", 0x17, 0x2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Ext Mic Playback Volume", 0x17, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Ext Mic Playback Switch", 0x17, 0x1, HDA_INPUT),
+	HDA_BIND_VOL("Master Playback Volume", &cxt5045_hp_bind_master_vol),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Master Playback Switch",
+		.info = cxt_eapd_info,
+		.get = cxt_eapd_get,
+		.put = cxt5045_hp_master_sw_put,
+		.private_value = 0x10,
+	},
+
+	{}
+};
+
 static struct hda_verb cxt5045_init_verbs[] = {
 	/* Line in, Mic */
 	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
@@ -841,6 +880,7 @@ enum {
 	CXT5045_LAPTOP_MICSENSE,
 	CXT5045_LAPTOP_HPMICSENSE,
 	CXT5045_BENQ,
+	CXT5045_LAPTOP_HP530,
 #ifdef CONFIG_SND_DEBUG
 	CXT5045_TEST,
 #endif
@@ -852,6 +892,7 @@ static const char *cxt5045_models[CXT5045_MODELS] = {
 	[CXT5045_LAPTOP_MICSENSE]	= "laptop-micsense",
 	[CXT5045_LAPTOP_HPMICSENSE]	= "laptop-hpmicsense",
 	[CXT5045_BENQ]			= "benq",
+	[CXT5045_LAPTOP_HP530]		= "laptop-hp530",
 #ifdef CONFIG_SND_DEBUG
 	[CXT5045_TEST]		= "test",
 #endif
@@ -865,7 +906,7 @@ static struct snd_pci_quirk cxt5045_cfg_tbl[] = {
 	SND_PCI_QUIRK(0x103c, 0x30bb, "HP DV8000", CXT5045_LAPTOP_HPSENSE),
 	SND_PCI_QUIRK(0x103c, 0x30cd, "HP DV Series", CXT5045_LAPTOP_HPSENSE),
 	SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV9533EG", CXT5045_LAPTOP_HPSENSE),
-	SND_PCI_QUIRK(0x103c, 0x30d5, "HP 530", CXT5045_LAPTOP_HPSENSE),
+	SND_PCI_QUIRK(0x103c, 0x30d5, "HP 530", CXT5045_LAPTOP_HP530),
 	SND_PCI_QUIRK(0x103c, 0x30d9, "HP Spartan", CXT5045_LAPTOP_HPSENSE),
 	SND_PCI_QUIRK(0x152d, 0x0753, "Benq R55E", CXT5045_BENQ),
 	SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_LAPTOP_MICSENSE),
@@ -949,6 +990,14 @@ static int patch_cxt5045(struct hda_codec *codec)
 		spec->num_mixers = 2;
 		codec->patch_ops.init = cxt5045_init;
 		break;
+	case CXT5045_LAPTOP_HP530:
+		codec->patch_ops.unsol_event = cxt5045_hp_unsol_event;
+		spec->input_mux = &cxt5045_capture_source_hp530;
+		spec->num_init_verbs = 2;
+		spec->init_verbs[1] = cxt5045_hp_sense_init_verbs;
+		spec->mixers[0] = cxt5045_mixers_hp530;
+		codec->patch_ops.init = cxt5045_init;
+		break;
 #ifdef CONFIG_SND_DEBUG
 	case CXT5045_TEST:
 		spec->input_mux = &cxt5045_test_capture_source;
-- 
cgit v1.2.3-70-g09d2


From 487145a1984b78e9b194aa44f8079cc019779a58 Mon Sep 17 00:00:00 2001
From: Peer Chen <peerchen@gmail.com>
Date: Thu, 6 Mar 2008 15:15:11 +0100
Subject: [ALSA] hda_intel: Add the DIDs of nvidia MCP79 HD audio controller to
 hda_intel.c

Add the Device IDs of nvidia MCP79 HD audio controller to hda_intel.c

Signed-off-by: Peer Chen <peerchen@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/hda_intel.c | 4 ++++
 1 file changed, 4 insertions(+)

(limited to 'sound')

diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 48677f36f5e..3d9f0bd63ba 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -2071,6 +2071,10 @@ static struct pci_device_id azx_ids[] = {
 	{ PCI_DEVICE(0x10de, 0x0ac1), .driver_data = AZX_DRIVER_NVIDIA },
 	{ PCI_DEVICE(0x10de, 0x0ac2), .driver_data = AZX_DRIVER_NVIDIA },
 	{ PCI_DEVICE(0x10de, 0x0ac3), .driver_data = AZX_DRIVER_NVIDIA },
+	{ PCI_DEVICE(0x10de, 0x0bd4), .driver_data = AZX_DRIVER_NVIDIA },
+	{ PCI_DEVICE(0x10de, 0x0bd5), .driver_data = AZX_DRIVER_NVIDIA },
+	{ PCI_DEVICE(0x10de, 0x0bd6), .driver_data = AZX_DRIVER_NVIDIA },
+	{ PCI_DEVICE(0x10de, 0x0bd7), .driver_data = AZX_DRIVER_NVIDIA },
 	{ 0, }
 };
 MODULE_DEVICE_TABLE(pci, azx_ids);
-- 
cgit v1.2.3-70-g09d2


From 7194cae62e92c5db8b87df1120fbf24f83f488f8 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Thu, 6 Mar 2008 16:58:17 +0100
Subject: [ALSA] hda-codec - Fix dmics on ALC268 in auto configuration

Fixed the handling of dmics on ALC268 in the auto-configuration mode.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c | 27 ++++++++++++++++++---------
 1 file changed, 18 insertions(+), 9 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 41bcbfd1059..c67c32faa90 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -6258,16 +6258,21 @@ static void alc882_auto_init_analog_input(struct hda_codec *codec)
 
 	for (i = 0; i < AUTO_PIN_LAST; i++) {
 		hda_nid_t nid = spec->autocfg.input_pins[i];
-		if (alc882_is_input_pin(nid)) {
-			snd_hda_codec_write(codec, nid, 0,
-					    AC_VERB_SET_PIN_WIDGET_CONTROL,
-					    i <= AUTO_PIN_FRONT_MIC ?
-					    PIN_VREF80 : PIN_IN);
-			if (nid != ALC882_PIN_CD_NID)
-				snd_hda_codec_write(codec, nid, 0,
-						    AC_VERB_SET_AMP_GAIN_MUTE,
-						    AMP_OUT_MUTE);
+		unsigned int vref;
+		if (!nid)
+			continue;
+		vref = PIN_IN;
+		if (1 /*i <= AUTO_PIN_FRONT_MIC*/) {
+			if (snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP) &
+			    AC_PINCAP_VREF_80)
+				vref = PIN_VREF80;
 		}
+		snd_hda_codec_write(codec, nid, 0,
+				    AC_VERB_SET_PIN_WIDGET_CONTROL, vref);
+		if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
+			snd_hda_codec_write(codec, nid, 0,
+					    AC_VERB_SET_AMP_GAIN_MUTE,
+					    AMP_OUT_MUTE);
 	}
 }
 
@@ -10125,6 +10130,10 @@ static int alc268_auto_create_analog_input_ctls(struct alc_spec *spec,
 		case 0x1c:	
 			idx1 = 3;	/* CD */
 			break;
+		case 0x12:
+		case 0x13:
+			idx1 = 6;	/* digital mics */
+			break;
 		default:
 			continue;
 		}
-- 
cgit v1.2.3-70-g09d2


From 0ccb541c96e6d40844d00ec88fae734568bdd0bd Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Thu, 6 Mar 2008 16:58:35 +0100
Subject: [ALSA] hda-codec - Add internal mic item for ALC268 acer model

Added the internal mic as a capture source item for ALC268 acer model.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index c67c32faa90..7937d97219d 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -9775,8 +9775,12 @@ static struct snd_kcontrol_new alc268_acer_mixer[] = {
 };
 
 static struct hda_verb alc268_acer_verbs[] = {
+	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* internal dmic? */
+	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
 	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
 	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
 
 	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
 	{ }
@@ -9990,6 +9994,15 @@ static struct hda_input_mux alc268_capture_source = {
 	},
 };
 
+static struct hda_input_mux alc268_acer_capture_source = {
+	.num_items = 3,
+	.items = {
+		{ "Mic", 0x0 },
+		{ "Internal Mic", 0x6 },
+		{ "Line", 0x2 },
+	},
+};
+
 #ifdef CONFIG_SND_DEBUG
 static struct snd_kcontrol_new alc268_test_mixer[] = {
 	/* Volume widgets */
@@ -10332,7 +10345,7 @@ static struct alc_config_preset alc268_presets[] = {
 		.hp_nid = 0x02,
 		.num_channel_mode = ARRAY_SIZE(alc268_modes),
 		.channel_mode = alc268_modes,
-		.input_mux = &alc268_capture_source,
+		.input_mux = &alc268_acer_capture_source,
 		.unsol_event = alc268_acer_unsol_event,
 		.init_hook = alc268_acer_init_hook,
 	},
-- 
cgit v1.2.3-70-g09d2


From 21ac1f9934d33ea2ffa71d13fa2f6286127d3caf Mon Sep 17 00:00:00 2001
From: Julia Lawall <julia@diku.dk>
Date: Tue, 4 Mar 2008 15:07:24 -0800
Subject: sound: Use BUG_ON

if (...) BUG(); should be replaced with BUG_ON(...) when the test has no
side-effects to allow a definition of BUG_ON that drops the code completely.

The semantic patch that makes this change is as follows:
(http://www.emn.fr/x-info/coccinelle/)

// <smpl>
@ disable unlikely @ expression E,f; @@

(
  if (<... f(...) ...>) { BUG(); }
|
- if (unlikely(E)) { BUG(); }
+ BUG_ON(E);
)

@@ expression E,f; @@

(
  if (<... f(...) ...>) { BUG(); }
|
- if (E) { BUG(); }
+ BUG_ON(E);
)
// </smpl>

Signed-off-by: Julia Lawall <julia@diku.dk>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
 sound/oss/trident.c | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

(limited to 'sound')

diff --git a/sound/oss/trident.c b/sound/oss/trident.c
index d6af9065d1c..f43f91ef86c 100644
--- a/sound/oss/trident.c
+++ b/sound/oss/trident.c
@@ -3076,8 +3076,7 @@ ali_ac97_get(struct trident_card *card, int secondary, u8 reg)
 	u16 wcontrol;
 	unsigned long flags;
 
-	if (!card)
-		BUG();
+	BUG_ON(!card);
 
 	address = ALI_AC97_READ;
 	if (card->revision == ALI_5451_V02) {
@@ -3148,8 +3147,7 @@ ali_ac97_set(struct trident_card *card, int secondary, u8 reg, u16 val)
 
 	data = ((u32) val) << 16;
 
-	if (!card)
-		BUG();
+	BUG_ON(!card);
 
 	address = ALI_AC97_WRITE;
 	mask = ALI_AC97_WRITE_ACTION | ALI_AC97_AUDIO_BUSY;
@@ -3213,8 +3211,7 @@ ali_ac97_read(struct ac97_codec *codec, u8 reg)
 	struct trident_card *card = NULL;
 
 	/* Added by Matt Wu */
-	if (!codec)
-		BUG();
+	BUG_ON(!codec);
 
 	card = (struct trident_card *) codec->private_data;
 
@@ -3240,8 +3237,7 @@ ali_ac97_write(struct ac97_codec *codec, u8 reg, u16 val)
 	struct trident_card *card;
 
 	/*  Added by Matt Wu */
-	if (!codec)
-		BUG();
+	BUG_ON(!codec);
 
 	card = (struct trident_card *) codec->private_data;
 
-- 
cgit v1.2.3-70-g09d2


From b419f346994d4ba082244fb1327754bc839a4d8a Mon Sep 17 00:00:00 2001
From: Tobin Davis <tdavis@dsl-only.net>
Date: Fri, 7 Mar 2008 11:57:51 +0100
Subject: [ALSA] HDA Codecs: add support for Toshiba Equium L30

This patch adds support for the Toshiba Equium L30 laptop and renames the mixer
controls to match Laptop usages.

Signed-off-by: Tobin Davis <tdavis@dsl-only.net>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c | 30 ++++++++++++++++--------------
 1 file changed, 16 insertions(+), 14 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 7937d97219d..3c15bdf4d2c 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -12054,11 +12054,10 @@ static struct hda_input_mux alc861vd_capture_source = {
 };
 
 static struct hda_input_mux alc861vd_dallas_capture_source = {
-	.num_items = 3,
+	.num_items = 2,
 	.items = {
-		{ "Front Mic", 0x0 },
-		{ "ATAPI Mic", 0x1 },
-		{ "Line In", 0x5 },
+		{ "Ext Mic", 0x0 },
+		{ "Int Mic", 0x1 },
 	},
 };
 
@@ -12228,20 +12227,22 @@ static struct snd_kcontrol_new alc861vd_lenovo_mixer[] = {
 	{ } /* end */
 };
 
-/* Pin assignment: Front=0x14, HP = 0x15,
- *                 Front Mic=0x18, ATAPI Mic = 0x19, Line In = 0x1d
+/* Pin assignment: Speaker=0x14, HP = 0x15,
+ *                 Ext Mic=0x18, Int Mic = 0x19, CD = 0x1c, PC Beep = 0x1d
  */
 static struct snd_kcontrol_new alc861vd_dallas_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 2, HDA_INPUT),
 	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
 	HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x05, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x05, HDA_INPUT),
+	HDA_CODEC_VOLUME("Ext Mic Boost", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Ext Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Ext Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("PC Beep Volume", 0x0b, 0x05, HDA_INPUT),
+	HDA_CODEC_MUTE("PC Beep Switch", 0x0b, 0x05, HDA_INPUT),
 	{ } /* end */
 };
 
@@ -12542,6 +12543,7 @@ static struct snd_pci_quirk alc861vd_cfg_tbl[] = {
 	/*SND_PCI_QUIRK(0x1179, 0xff00, "DALLAS", ALC861VD_DALLAS),*/ /*lenovo*/
 	SND_PCI_QUIRK(0x1179, 0xff01, "DALLAS", ALC861VD_DALLAS),
 	SND_PCI_QUIRK(0x1179, 0xff03, "Toshiba P205", ALC861VD_LENOVO),
+	SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba L30-149", ALC861VD_DALLAS),
 	SND_PCI_QUIRK(0x1565, 0x820d, "Biostar NF61S SE", ALC861VD_6ST_DIG),
 	SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo", ALC861VD_LENOVO),
 	SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo 3000 C200", ALC861VD_LENOVO),
-- 
cgit v1.2.3-70-g09d2


From c67582b195fb5deb24808ebbafb41045f1a61425 Mon Sep 17 00:00:00 2001
From: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Date: Sat, 8 Mar 2008 11:07:26 +0100
Subject: [ALSA] at73c213: fix error checking for clk API

The clk_round_rate() and clk_set_rate() will return int, so not store thier
return value to unsigned long variable.  This bug hides real error on these
API.

Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/spi/at73c213.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'sound')

diff --git a/sound/spi/at73c213.c b/sound/spi/at73c213.c
index b8860b26fc6..c1b0b9dff81 100644
--- a/sound/spi/at73c213.c
+++ b/sound/spi/at73c213.c
@@ -133,7 +133,8 @@ static struct snd_pcm_hardware snd_at73c213_playback_hw = {
 static int snd_at73c213_set_bitrate(struct snd_at73c213 *chip)
 {
 	unsigned long ssc_rate = clk_get_rate(chip->ssc->clk);
-	unsigned long dac_rate_new, ssc_div, status;
+	unsigned long dac_rate_new, ssc_div;
+	int status;
 	unsigned long ssc_div_max, ssc_div_min;
 	int max_tries;
 
-- 
cgit v1.2.3-70-g09d2


From 4a295ca47424b48c993d5cea7c3fbeca75ddb608 Mon Sep 17 00:00:00 2001
From: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Date: Sat, 8 Mar 2008 11:08:32 +0100
Subject: [ALSA] at73c213: monaural support

Add support for monaural playback to at73c213 driver.  The sound will be apear
on L-channel.  Tested on AT91SAM9260-EK.

Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/spi/at73c213.c | 19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

(limited to 'sound')

diff --git a/sound/spi/at73c213.c b/sound/spi/at73c213.c
index c1b0b9dff81..1355fe0c667 100644
--- a/sound/spi/at73c213.c
+++ b/sound/spi/at73c213.c
@@ -118,7 +118,7 @@ static struct snd_pcm_hardware snd_at73c213_playback_hw = {
 	.rates		= SNDRV_PCM_RATE_CONTINUOUS,
 	.rate_min	= 8000,  /* Replaced by chip->bitrate later. */
 	.rate_max	= 50000, /* Replaced by chip->bitrate later. */
-	.channels_min	= 2,
+	.channels_min	= 1,
 	.channels_max	= 2,
 	.buffer_bytes_max = 64 * 1024 - 1,
 	.period_bytes_min = 512,
@@ -229,6 +229,14 @@ static int snd_at73c213_pcm_close(struct snd_pcm_substream *substream)
 static int snd_at73c213_pcm_hw_params(struct snd_pcm_substream *substream,
 				 struct snd_pcm_hw_params *hw_params)
 {
+	struct snd_at73c213 *chip = snd_pcm_substream_chip(substream);
+	int channels = params_channels(hw_params);
+	int val;
+
+	val = ssc_readl(chip->ssc->regs, TFMR);
+	val = SSC_BFINS(TFMR_DATNB, channels - 1, val);
+	ssc_writel(chip->ssc->regs, TFMR, val);
+
 	return snd_pcm_lib_malloc_pages(substream,
 					params_buffer_bytes(hw_params));
 }
@@ -250,10 +258,12 @@ static int snd_at73c213_pcm_prepare(struct snd_pcm_substream *substream)
 
 	ssc_writel(chip->ssc->regs, PDC_TPR,
 			(long)runtime->dma_addr);
-	ssc_writel(chip->ssc->regs, PDC_TCR, runtime->period_size * 2);
+	ssc_writel(chip->ssc->regs, PDC_TCR,
+			runtime->period_size * runtime->channels);
 	ssc_writel(chip->ssc->regs, PDC_TNPR,
 			(long)runtime->dma_addr + block_size);
-	ssc_writel(chip->ssc->regs, PDC_TNCR, runtime->period_size * 2);
+	ssc_writel(chip->ssc->regs, PDC_TNCR,
+			runtime->period_size * runtime->channels);
 
 	return 0;
 }
@@ -376,7 +386,8 @@ static irqreturn_t snd_at73c213_interrupt(int irq, void *dev_id)
 
 		ssc_writel(chip->ssc->regs, PDC_TNPR,
 				(long)runtime->dma_addr + offset);
-		ssc_writel(chip->ssc->regs, PDC_TNCR, runtime->period_size * 2);
+		ssc_writel(chip->ssc->regs, PDC_TNCR,
+				runtime->period_size * runtime->channels);
 		retval = IRQ_HANDLED;
 	}
 
-- 
cgit v1.2.3-70-g09d2


From 7747ecceb523d7b00c8dfe568154d0b4e70e0800 Mon Sep 17 00:00:00 2001
From: Matthew Ranostay <mranostay@embeddedalley.com>
Date: Mon, 10 Mar 2008 11:30:04 +0100
Subject: [ALSA] hda: Reorganized DAC outputs

Changed so that internal speakers point to the Front mixer instead of Surround.

Signed-off-by: Matthew Ranostay <mranostay@embeddedalley.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_sigmatel.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 6c85e7e8103..bf6142f5453 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -538,8 +538,8 @@ static struct hda_verb dell_m6_core_init[] = {
 	/* set master volume and direct control */
 	{ 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
 	/* setup audio connections */
-	{ 0x0a, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{ 0x0d, AC_VERB_SET_CONNECT_SEL, 0x01},
+	{ 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{ 0x0a, AC_VERB_SET_CONNECT_SEL, 0x01},
 	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x02},
 	/* setup adcs to point to mixer */
 	{ 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b},
-- 
cgit v1.2.3-70-g09d2


From ee7a9c7c2eb5cd09c15824323eac4cd95e2d18a8 Mon Sep 17 00:00:00 2001
From: Michael Gruber <lists.mg@googlemail.com>
Date: Mon, 10 Mar 2008 11:30:59 +0100
Subject: [ALSA] hda-intel - Fix microphone capture with ALC880 F1734 model

The default capture source should be the mic which is 0x01 on this model.
In addition to that the change to VREF50 allows for higher capture volume.

Signed-off-by: Michael Gruber <lists.mg@googlemail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 3c15bdf4d2c..bfb336de1dc 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -1927,6 +1927,7 @@ static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec,
  * HP = 0x14, speaker-out = 0x15, mic = 0x18
  */
 static struct hda_verb alc880_pin_f1734_init_verbs[] = {
+	{0x07, AC_VERB_SET_CONNECT_SEL, 0x01},
 	{0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
 	{0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
 	{0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
@@ -1939,7 +1940,7 @@ static struct hda_verb alc880_pin_f1734_init_verbs[] = {
 
 	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
 	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
 	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
 	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
 	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-- 
cgit v1.2.3-70-g09d2


From 91662577979cadf945cd3ffc4c470e5b91378370 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@alsa2.suse.de>
Date: Mon, 10 Mar 2008 12:19:12 +0100
Subject: [ALSA] aw2 - Rename aw2-tsl.h to aw2-tsl.c

aw2-tsl.h should be rather a C file to be included since it's referred
only in aw2-saa6146.c and includes a table data.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/aw2/aw2-saa7146.c |   3 +-
 sound/pci/aw2/aw2-tsl.c     | 110 ++++++++++++++++++++++++++++++++++++++++++++
 sound/pci/aw2/aw2-tsl.h     | 110 --------------------------------------------
 3 files changed, 112 insertions(+), 111 deletions(-)
 create mode 100644 sound/pci/aw2/aw2-tsl.c
 delete mode 100644 sound/pci/aw2/aw2-tsl.h

(limited to 'sound')

diff --git a/sound/pci/aw2/aw2-saa7146.c b/sound/pci/aw2/aw2-saa7146.c
index f20f213489a..6a3891ab69d 100644
--- a/sound/pci/aw2/aw2-saa7146.c
+++ b/sound/pci/aw2/aw2-saa7146.c
@@ -35,10 +35,11 @@
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 
-#include "aw2-tsl.h"
 #include "saa7146.h"
 #include "aw2-saa7146.h"
 
+#include "aw2-tsl.c"
+
 #define WRITEREG(value, addr) writel((value), chip->base_addr + (addr))
 #define READREG(addr) readl(chip->base_addr + (addr))
 
diff --git a/sound/pci/aw2/aw2-tsl.c b/sound/pci/aw2/aw2-tsl.c
new file mode 100644
index 00000000000..459b0311ea3
--- /dev/null
+++ b/sound/pci/aw2/aw2-tsl.c
@@ -0,0 +1,110 @@
+/*****************************************************************************
+ *
+ * Copyright (C) 2008 Cedric Bregardis <cedric.bregardis@free.fr> and
+ * Jean-Christian Hassler <jhassler@free.fr>
+ * Copyright 1998 Emagic Soft- und Hardware GmbH
+ * Copyright 2002 Martijn Sipkema
+ *
+ * This file is part of the Audiowerk2 ALSA driver
+ *
+ * The Audiowerk2 ALSA driver is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2.
+ *
+ * The Audiowerk2 ALSA driver is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the Audiowerk2 ALSA driver; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+ * USA.
+ *
+ *****************************************************************************/
+
+#define TSL_WS0		(1UL << 31)
+#define	TSL_WS1		(1UL << 30)
+#define	TSL_WS2		(1UL << 29)
+#define TSL_WS3		(1UL << 28)
+#define TSL_WS4		(1UL << 27)
+#define	TSL_DIS_A1	(1UL << 24)
+#define TSL_SDW_A1	(1UL << 23)
+#define TSL_SIB_A1	(1UL << 22)
+#define TSL_SF_A1	(1UL << 21)
+#define	TSL_LF_A1	(1UL << 20)
+#define TSL_BSEL_A1	(1UL << 17)
+#define TSL_DOD_A1	(1UL << 15)
+#define TSL_LOW_A1	(1UL << 14)
+#define TSL_DIS_A2	(1UL << 11)
+#define TSL_SDW_A2	(1UL << 10)
+#define TSL_SIB_A2	(1UL << 9)
+#define TSL_SF_A2	(1UL << 8)
+#define TSL_LF_A2	(1UL << 7)
+#define TSL_BSEL_A2	(1UL << 4)
+#define TSL_DOD_A2	(1UL << 2)
+#define TSL_LOW_A2	(1UL << 1)
+#define TSL_EOS		(1UL << 0)
+
+    /* Audiowerk8 hardware setup: */
+    /*      WS0, SD4, TSL1  - Analog/ digital in */
+    /*      WS1, SD0, TSL1  - Analog out #1, digital out */
+    /*      WS2, SD2, TSL1  - Analog out #2 */
+    /*      WS3, SD1, TSL2  - Analog out #3 */
+    /*      WS4, SD3, TSL2  - Analog out #4 */
+
+    /* Audiowerk8 timing: */
+    /*      Timeslot:     | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ... */
+
+    /*      A1_INPUT: */
+    /*      SD4:          <_ADC-L_>-------<_ADC-R_>-------< */
+    /*      WS0:          _______________/---------------\_ */
+
+    /*      A1_OUTPUT: */
+    /*      SD0:          <_1-L___>-------<_1-R___>-------< */
+    /*      WS1:          _______________/---------------\_ */
+    /*      SD2:          >-------<_2-L___>-------<_2-R___> */
+    /*      WS2:          -------\_______________/--------- */
+
+    /*      A2_OUTPUT: */
+    /*      SD1:          <_3-L___>-------<_3-R___>-------< */
+    /*      WS3:          _______________/---------------\_ */
+    /*      SD3:          >-------<_4-L___>-------<_4-R___> */
+    /*      WS4:          -------\_______________/--------- */
+
+static int tsl1[8] = {
+	1 * TSL_SDW_A1 | 3 * TSL_BSEL_A1 |
+	0 * TSL_DIS_A1 | 0 * TSL_DOD_A1 | TSL_LF_A1,
+
+	1 * TSL_SDW_A1 | 2 * TSL_BSEL_A1 |
+	0 * TSL_DIS_A1 | 0 * TSL_DOD_A1,
+
+	0 * TSL_SDW_A1 | 3 * TSL_BSEL_A1 |
+	0 * TSL_DIS_A1 | 0 * TSL_DOD_A1,
+
+	0 * TSL_SDW_A1 | 2 * TSL_BSEL_A1 |
+	0 * TSL_DIS_A1 | 0 * TSL_DOD_A1,
+
+	1 * TSL_SDW_A1 | 1 * TSL_BSEL_A1 |
+	0 * TSL_DIS_A1 | 0 * TSL_DOD_A1 | TSL_WS1 | TSL_WS0,
+
+	1 * TSL_SDW_A1 | 0 * TSL_BSEL_A1 |
+	0 * TSL_DIS_A1 | 0 * TSL_DOD_A1 | TSL_WS1 | TSL_WS0,
+
+	0 * TSL_SDW_A1 | 1 * TSL_BSEL_A1 |
+	0 * TSL_DIS_A1 | 0 * TSL_DOD_A1 | TSL_WS1 | TSL_WS0,
+
+	0 * TSL_SDW_A1 | 0 * TSL_BSEL_A1 | 0 * TSL_DIS_A1 |
+	0 * TSL_DOD_A1 | TSL_WS1 | TSL_WS0 | TSL_SF_A1 | TSL_EOS,
+};
+
+static int tsl2[8] = {
+	0 * TSL_SDW_A2 | 3 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_LF_A2,
+	0 * TSL_SDW_A2 | 2 * TSL_BSEL_A2 | 2 * TSL_DOD_A2,
+	0 * TSL_SDW_A2 | 3 * TSL_BSEL_A2 | 2 * TSL_DOD_A2,
+	0 * TSL_SDW_A2 | 2 * TSL_BSEL_A2 | 2 * TSL_DOD_A2,
+	0 * TSL_SDW_A2 | 1 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_WS2,
+	0 * TSL_SDW_A2 | 0 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_WS2,
+	0 * TSL_SDW_A2 | 1 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_WS2,
+	0 * TSL_SDW_A2 | 0 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_WS2 | TSL_EOS
+};
diff --git a/sound/pci/aw2/aw2-tsl.h b/sound/pci/aw2/aw2-tsl.h
deleted file mode 100644
index 459b0311ea3..00000000000
--- a/sound/pci/aw2/aw2-tsl.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*****************************************************************************
- *
- * Copyright (C) 2008 Cedric Bregardis <cedric.bregardis@free.fr> and
- * Jean-Christian Hassler <jhassler@free.fr>
- * Copyright 1998 Emagic Soft- und Hardware GmbH
- * Copyright 2002 Martijn Sipkema
- *
- * This file is part of the Audiowerk2 ALSA driver
- *
- * The Audiowerk2 ALSA driver is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2.
- *
- * The Audiowerk2 ALSA driver is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with the Audiowerk2 ALSA driver; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
- * USA.
- *
- *****************************************************************************/
-
-#define TSL_WS0		(1UL << 31)
-#define	TSL_WS1		(1UL << 30)
-#define	TSL_WS2		(1UL << 29)
-#define TSL_WS3		(1UL << 28)
-#define TSL_WS4		(1UL << 27)
-#define	TSL_DIS_A1	(1UL << 24)
-#define TSL_SDW_A1	(1UL << 23)
-#define TSL_SIB_A1	(1UL << 22)
-#define TSL_SF_A1	(1UL << 21)
-#define	TSL_LF_A1	(1UL << 20)
-#define TSL_BSEL_A1	(1UL << 17)
-#define TSL_DOD_A1	(1UL << 15)
-#define TSL_LOW_A1	(1UL << 14)
-#define TSL_DIS_A2	(1UL << 11)
-#define TSL_SDW_A2	(1UL << 10)
-#define TSL_SIB_A2	(1UL << 9)
-#define TSL_SF_A2	(1UL << 8)
-#define TSL_LF_A2	(1UL << 7)
-#define TSL_BSEL_A2	(1UL << 4)
-#define TSL_DOD_A2	(1UL << 2)
-#define TSL_LOW_A2	(1UL << 1)
-#define TSL_EOS		(1UL << 0)
-
-    /* Audiowerk8 hardware setup: */
-    /*      WS0, SD4, TSL1  - Analog/ digital in */
-    /*      WS1, SD0, TSL1  - Analog out #1, digital out */
-    /*      WS2, SD2, TSL1  - Analog out #2 */
-    /*      WS3, SD1, TSL2  - Analog out #3 */
-    /*      WS4, SD3, TSL2  - Analog out #4 */
-
-    /* Audiowerk8 timing: */
-    /*      Timeslot:     | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ... */
-
-    /*      A1_INPUT: */
-    /*      SD4:          <_ADC-L_>-------<_ADC-R_>-------< */
-    /*      WS0:          _______________/---------------\_ */
-
-    /*      A1_OUTPUT: */
-    /*      SD0:          <_1-L___>-------<_1-R___>-------< */
-    /*      WS1:          _______________/---------------\_ */
-    /*      SD2:          >-------<_2-L___>-------<_2-R___> */
-    /*      WS2:          -------\_______________/--------- */
-
-    /*      A2_OUTPUT: */
-    /*      SD1:          <_3-L___>-------<_3-R___>-------< */
-    /*      WS3:          _______________/---------------\_ */
-    /*      SD3:          >-------<_4-L___>-------<_4-R___> */
-    /*      WS4:          -------\_______________/--------- */
-
-static int tsl1[8] = {
-	1 * TSL_SDW_A1 | 3 * TSL_BSEL_A1 |
-	0 * TSL_DIS_A1 | 0 * TSL_DOD_A1 | TSL_LF_A1,
-
-	1 * TSL_SDW_A1 | 2 * TSL_BSEL_A1 |
-	0 * TSL_DIS_A1 | 0 * TSL_DOD_A1,
-
-	0 * TSL_SDW_A1 | 3 * TSL_BSEL_A1 |
-	0 * TSL_DIS_A1 | 0 * TSL_DOD_A1,
-
-	0 * TSL_SDW_A1 | 2 * TSL_BSEL_A1 |
-	0 * TSL_DIS_A1 | 0 * TSL_DOD_A1,
-
-	1 * TSL_SDW_A1 | 1 * TSL_BSEL_A1 |
-	0 * TSL_DIS_A1 | 0 * TSL_DOD_A1 | TSL_WS1 | TSL_WS0,
-
-	1 * TSL_SDW_A1 | 0 * TSL_BSEL_A1 |
-	0 * TSL_DIS_A1 | 0 * TSL_DOD_A1 | TSL_WS1 | TSL_WS0,
-
-	0 * TSL_SDW_A1 | 1 * TSL_BSEL_A1 |
-	0 * TSL_DIS_A1 | 0 * TSL_DOD_A1 | TSL_WS1 | TSL_WS0,
-
-	0 * TSL_SDW_A1 | 0 * TSL_BSEL_A1 | 0 * TSL_DIS_A1 |
-	0 * TSL_DOD_A1 | TSL_WS1 | TSL_WS0 | TSL_SF_A1 | TSL_EOS,
-};
-
-static int tsl2[8] = {
-	0 * TSL_SDW_A2 | 3 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_LF_A2,
-	0 * TSL_SDW_A2 | 2 * TSL_BSEL_A2 | 2 * TSL_DOD_A2,
-	0 * TSL_SDW_A2 | 3 * TSL_BSEL_A2 | 2 * TSL_DOD_A2,
-	0 * TSL_SDW_A2 | 2 * TSL_BSEL_A2 | 2 * TSL_DOD_A2,
-	0 * TSL_SDW_A2 | 1 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_WS2,
-	0 * TSL_SDW_A2 | 0 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_WS2,
-	0 * TSL_SDW_A2 | 1 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_WS2,
-	0 * TSL_SDW_A2 | 0 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_WS2 | TSL_EOS
-};
-- 
cgit v1.2.3-70-g09d2


From 9f2f0f7c4e997a74ff9fb8e2e2ed0daa21962e97 Mon Sep 17 00:00:00 2001
From: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Date: Tue, 11 Mar 2008 08:15:30 +0100
Subject: [ALSA] at73c213: remove redundant private_free routine

snd_pcm_lib_preallocate_free_for_all() is called from snd_pcm_free() just
after calling the private_free routine.  So there should be no need to call
it in driver's private_free routine.

Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/spi/at73c213.c | 10 ----------
 1 file changed, 10 deletions(-)

(limited to 'sound')

diff --git a/sound/spi/at73c213.c b/sound/spi/at73c213.c
index 1355fe0c667..aa571152f03 100644
--- a/sound/spi/at73c213.c
+++ b/sound/spi/at73c213.c
@@ -325,15 +325,6 @@ static struct snd_pcm_ops at73c213_playback_ops = {
 	.pointer	= snd_at73c213_pcm_pointer,
 };
 
-static void snd_at73c213_pcm_free(struct snd_pcm *pcm)
-{
-	struct snd_at73c213 *chip = snd_pcm_chip(pcm);
-	if (chip->pcm) {
-		snd_pcm_lib_preallocate_free_for_all(chip->pcm);
-		chip->pcm = NULL;
-	}
-}
-
 static int __devinit snd_at73c213_pcm_new(struct snd_at73c213 *chip, int device)
 {
 	struct snd_pcm *pcm;
@@ -345,7 +336,6 @@ static int __devinit snd_at73c213_pcm_new(struct snd_at73c213 *chip, int device)
 		goto out;
 
 	pcm->private_data = chip;
-	pcm->private_free = snd_at73c213_pcm_free;
 	pcm->info_flags = SNDRV_PCM_INFO_BLOCK_TRANSFER;
 	strcpy(pcm->name, "at73c213");
 	chip->pcm = pcm;
-- 
cgit v1.2.3-70-g09d2


From bb9f76cd5909b9da6b4d31b55a4086cc35614fe0 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Wed, 12 Mar 2008 12:51:09 +0100
Subject: [ALSA] hda-codec - Improve ALC262 ultra model

Improved ALC262 ultra model for Samsung Q1 Ultra series.

- clean up mixers
- support of input from HP jack as a mic
- add quirk for Q1 EL

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c | 132 +++++++++++++++++++++++++++++-------------
 1 file changed, 93 insertions(+), 39 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index bfb336de1dc..3965b7644ad 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -8870,59 +8870,72 @@ static struct hda_verb alc262_benq_t31_EAPD_verbs[] = {
 
 /* Samsung Q1 Ultra Vista model setup */
 static struct snd_kcontrol_new alc262_ultra_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
 	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
 	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
 	HDA_CODEC_VOLUME("Mic Boost", 0x19, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Headphone Mic Boost", 0x15, 0, HDA_INPUT),
 	{ } /* end */
 };
 
 static struct hda_verb alc262_ultra_verbs[] = {
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
+	/* output mixer */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	/* speaker */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* HP */
 	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-	/* Mic is on Node 0x19 */
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
-	{0x22, AC_VERB_SET_CONNECT_SEL, 0x01},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-	{0x23, AC_VERB_SET_CONNECT_SEL, 0x01},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-	{0x24, AC_VERB_SET_CONNECT_SEL, 0x01},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
+	/* internal mic */
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	/* ADC, choose mic */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(8)},
 	{}
 };
 
-static struct hda_input_mux alc262_ultra_capture_source = {
-	.num_items = 1,
-	.items = {
-		{ "Mic", 0x1 },
-	},
-};
-
 /* mute/unmute internal speaker according to the hp jack and mute state */
 static void alc262_ultra_automute(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
 	unsigned int mute;
-	unsigned int present;
 
-	/* need to execute and sync at first */
-	snd_hda_codec_read(codec, 0x15, 0, AC_VERB_SET_PIN_SENSE, 0);
-	present = snd_hda_codec_read(codec, 0x15, 0,
-				     AC_VERB_GET_PIN_SENSE, 0);
-	spec->jack_present = (present & 0x80000000) != 0;
-	if (spec->jack_present) {
-		/* mute internal speaker */
-		snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
-					 HDA_AMP_MUTE, HDA_AMP_MUTE);
-	} else {
-		/* unmute internal speaker if necessary */
-		mute = snd_hda_codec_amp_read(codec, 0x15, 0, HDA_OUTPUT, 0);
-		snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
-					 HDA_AMP_MUTE, mute);
+	mute = 0;
+	/* auto-mute only when HP is used as HP */
+	if (!spec->cur_mux[0]) {
+		unsigned int present;
+		/* need to execute and sync at first */
+		snd_hda_codec_read(codec, 0x15, 0, AC_VERB_SET_PIN_SENSE, 0);
+		present = snd_hda_codec_read(codec, 0x15, 0,
+					     AC_VERB_GET_PIN_SENSE, 0);
+		spec->jack_present = (present & AC_PINSENSE_PRESENCE) != 0;
+		if (spec->jack_present)
+			mute = HDA_AMP_MUTE;
 	}
+	/* mute/unmute internal speaker */
+	snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+				 HDA_AMP_MUTE, mute);
+	/* mute/unmute HP */
+	snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
+				 HDA_AMP_MUTE, mute ? 0 : HDA_AMP_MUTE);
 }
 
 /* unsolicited event for HP jack sensing */
@@ -8934,6 +8947,45 @@ static void alc262_ultra_unsol_event(struct hda_codec *codec,
 	alc262_ultra_automute(codec);
 }
 
+static struct hda_input_mux alc262_ultra_capture_source = {
+	.num_items = 2,
+	.items = {
+		{ "Mic", 0x1 },
+		{ "Headphone", 0x7 },
+	},
+};
+
+static int alc262_ultra_mux_enum_put(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct alc_spec *spec = codec->spec;
+	int ret;
+
+	ret = alc882_mux_enum_put(kcontrol, ucontrol);
+	if (!ret)
+		return 0;
+	/* reprogram the HP pin as mic or HP according to the input source */
+	snd_hda_codec_write_cache(codec, 0x15, 0,
+				  AC_VERB_SET_PIN_WIDGET_CONTROL,
+				  spec->cur_mux[0] ? PIN_VREF80 : PIN_HP);
+	alc262_ultra_automute(codec); /* mute/unmute HP */
+	return ret;
+}
+
+static struct snd_kcontrol_new alc262_ultra_capture_mixer[] = {
+	HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Capture Source",
+		.info = alc882_mux_enum_info,
+		.get = alc882_mux_enum_get,
+		.put = alc262_ultra_mux_enum_put,
+	},
+	{ } /* end */
+};
+
 /* add playback controls from the parsed DAC table */
 static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec,
 					     const struct auto_pin_cfg *cfg)
@@ -9384,6 +9436,7 @@ static struct snd_pci_quirk alc262_cfg_tbl[] = {
 	SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU),
 	SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FUJITSU),
 	SND_PCI_QUIRK(0x144d, 0xc032, "Samsung Q1 Ultra", ALC262_ULTRA),
+	SND_PCI_QUIRK(0x144d, 0xc039, "Samsung Q1U EL", ALC262_ULTRA),
 	SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8),
 	SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_BENQ_T31),
 	SND_PCI_QUIRK(0x17ff, 0x058f, "Benq Hippo", ALC262_HIPPO_1),
@@ -9533,15 +9586,16 @@ static struct alc_config_preset alc262_presets[] = {
 		.init_hook = alc262_hippo_automute,
 	},	
 	[ALC262_ULTRA] = {
-		.mixers = { alc262_ultra_mixer },
-		.init_verbs = { alc262_init_verbs, alc262_ultra_verbs },
+		.mixers = { alc262_ultra_mixer, alc262_ultra_capture_mixer },
+		.init_verbs = { alc262_ultra_verbs },
 		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
 		.dac_nids = alc262_dac_nids,
-		.hp_nid = 0x03,
-		.dig_out_nid = ALC262_DIGOUT_NID,
 		.num_channel_mode = ARRAY_SIZE(alc262_modes),
 		.channel_mode = alc262_modes,
 		.input_mux = &alc262_ultra_capture_source,
+		.adc_nids = alc262_adc_nids, /* ADC0 */
+		.capsrc_nids = alc262_capsrc_nids,
+		.num_adc_nids = 1, /* single ADC */
 		.unsol_event = alc262_ultra_unsol_event,
 		.init_hook = alc262_ultra_automute,
 	},
-- 
cgit v1.2.3-70-g09d2


From 1bc1f30565b561bafc51725fce336aec59029437 Mon Sep 17 00:00:00 2001
From: Stas Sergeev <stsp@aknet.ru>
Date: Wed, 12 Mar 2008 13:12:15 +0100
Subject: [ALSA] pcsp: locking fix

pcsp: locking fix.

Signed-off-by: Stas Sergeev <stsp@aknet.ru>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/drivers/pcsp/pcsp.c     | 5 ++---
 sound/drivers/pcsp/pcsp_lib.c | 2 ++
 2 files changed, 4 insertions(+), 3 deletions(-)

(limited to 'sound')

diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c
index 547005cb094..ac57e87d01b 100644
--- a/sound/drivers/pcsp/pcsp.c
+++ b/sound/drivers/pcsp/pcsp.c
@@ -191,11 +191,10 @@ static int __devexit pcsp_remove(struct platform_device *dev)
 
 static void pcsp_stop_beep(struct snd_pcsp *chip)
 {
-	unsigned long flags;
-	spin_lock_irqsave(&chip->substream_lock, flags);
+	spin_lock_irq(&chip->substream_lock);
 	if (!chip->playback_substream)
 		pcspkr_stop_sound();
-	spin_unlock_irqrestore(&chip->substream_lock, flags);
+	spin_unlock_irq(&chip->substream_lock);
 }
 
 static int pcsp_suspend(struct platform_device *dev, pm_message_t state)
diff --git a/sound/drivers/pcsp/pcsp_lib.c b/sound/drivers/pcsp/pcsp_lib.c
index a302756eac7..54253e9b4b0 100644
--- a/sound/drivers/pcsp/pcsp_lib.c
+++ b/sound/drivers/pcsp/pcsp_lib.c
@@ -305,7 +305,9 @@ static int snd_pcsp_playback_open(struct snd_pcm_substream *substream)
 		return -EBUSY;
 	}
 	runtime->hw = snd_pcsp_playback;
+	spin_lock_irq(&chip->substream_lock);
 	chip->playback_substream = substream;
+	spin_unlock_irq(&chip->substream_lock);
 	return 0;
 }
 
-- 
cgit v1.2.3-70-g09d2


From d654a660355f9dc30d3a6bf1493d32363bde8570 Mon Sep 17 00:00:00 2001
From: Matthew Ranostay <mranostay@embeddedalley.com>
Date: Fri, 14 Mar 2008 08:46:51 +0100
Subject: [ALSA] hda: 92HD73xxx distortion fix

Fixed issue on some laptops that if the Master mixer and DAC mixers are
turned all the way up that will cause distortion. This is fixed by limiting
the max volume with the volume knob nid.

Signed-off-by: Matthew Ranostay <mranostay@embeddedalley.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_sigmatel.c | 29 +++++++++++++++++++++++++----
 1 file changed, 25 insertions(+), 4 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index bf6142f5453..b75bf347565 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -534,6 +534,25 @@ static struct hda_verb stac92hd73xx_6ch_core_init[] = {
 	{}
 };
 
+static struct hda_verb dell_eq_core_init[] = {
+	/* set master volume to max value without distortion
+	 * and direct control */
+	{ 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xec},
+	/* setup audio connections */
+	{ 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{ 0x0a, AC_VERB_SET_CONNECT_SEL, 0x01},
+	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x02},
+	/* setup adcs to point to mixer */
+	{ 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b},
+	{ 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b},
+	/* setup import muxs */
+	{ 0x28, AC_VERB_SET_CONNECT_SEL, 0x01},
+	{ 0x29, AC_VERB_SET_CONNECT_SEL, 0x01},
+	{ 0x2a, AC_VERB_SET_CONNECT_SEL, 0x01},
+	{ 0x2b, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{}
+};
+
 static struct hda_verb dell_m6_core_init[] = {
 	/* set master volume and direct control */
 	{ 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
@@ -3460,17 +3479,19 @@ again:
 
 	switch (spec->board_config) {
 	case STAC_DELL_M6:
-		spec->init = dell_m6_core_init;
+		spec->init = dell_eq_core_init;
 		switch (codec->subsystem_id) {
 		case 0x1028025e: /* Analog Mics */
 		case 0x1028025f:
 			stac92xx_set_config_reg(codec, 0x0b, 0x90A70170);
 			spec->num_dmics = 0;
 			break;
-		case 0x10280254: /* Digital Mics */
-		case 0x10280255:
-		case 0x10280271:
+		case 0x10280271: /* Digital Mics */
 		case 0x10280272:
+			spec->init = dell_m6_core_init;
+			/* fall-through */
+		case 0x10280254:
+		case 0x10280255:
 			stac92xx_set_config_reg(codec, 0x13, 0x90A60160);
 			spec->num_dmics = 1;
 			break;
-- 
cgit v1.2.3-70-g09d2


From 2626a263ffc2369499442933b1c313de0a066ede Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Fri, 14 Mar 2008 09:18:32 +0100
Subject: [ALSA] hda-codec - Fix orphan Headphone controls in STAC codecs

Currently, the headphone controls are created as Master wrongly in
some cases, and this prevents the virtual master controls.
The patch fixes the problem by simply using "Headphone" always for
headphone controls.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_sigmatel.c | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index b75bf347565..b8e69a1b93f 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -2509,12 +2509,8 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec,
 			return err;
 	}
 	if (spec->multiout.hp_nid) {
-		const char *pfx;
-		if (old_num_dacs == spec->multiout.num_dacs)
-			pfx = "Master";
-		else
-			pfx = "Headphone";
-		err = create_controls(spec, pfx, spec->multiout.hp_nid, 3);
+		err = create_controls(spec, "Headphone",
+				      spec->multiout.hp_nid, 3);
 		if (err < 0)
 			return err;
 	}
-- 
cgit v1.2.3-70-g09d2


From 7055ad8a996b2b77f12242109c0b5bacc237e824 Mon Sep 17 00:00:00 2001
From: Herton Ronaldo Krzesinski <herton@mandriva.com>
Date: Fri, 14 Mar 2008 12:52:20 +0100
Subject: [ALSA] hda-codec - Fix ALC662 DAC mixer mutes

Currently ALC662 doesn't suport amp mute for AmpOut in nids 0x02, 0x03,
0x04 (see block diagram in ALC662 datasheet page 3, does M correspond to
mute?). The result is that currently mute for "Front Playback Switch",
"Surround Playback Switch", "Center Playback Switch" and "LFE Playback
Switch" mixer items doesn't work (tested on Asus P5GC-MX motherboard
with 3stack-6ch model).

The solution I found for this is to mute the proper inputs in 0x0c,
0x0d, 0x0e audio mixers.

Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 3965b7644ad..8eb64dbfc78 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -13139,13 +13139,13 @@ static struct hda_channel_mode alc662_5stack_modes[2] = {
 static struct snd_kcontrol_new alc662_base_mixer[] = {
 	/* output mixer control */
 	HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Front Playback Switch", 0x02, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
 	HDA_CODEC_VOLUME("Surround Playback Volume", 0x3, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Surround Playback Switch", 0x03, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Surround Playback Switch", 0x0d, 0x0, HDA_INPUT),
 	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
 	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x04, 1, 2, HDA_INPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x04, 2, 2, HDA_INPUT),
+	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x0e, 1, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x0, HDA_INPUT),
 	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
 
 	/*Input mixer control */
@@ -13162,7 +13162,7 @@ static struct snd_kcontrol_new alc662_base_mixer[] = {
 
 static struct snd_kcontrol_new alc662_3ST_2ch_mixer[] = {
 	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
 	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
 	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
 	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
@@ -13179,13 +13179,13 @@ static struct snd_kcontrol_new alc662_3ST_2ch_mixer[] = {
 
 static struct snd_kcontrol_new alc662_3ST_6ch_mixer[] = {
 	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
 	HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Surround Playback Switch", 0x03, 2, HDA_INPUT),
+	HDA_CODEC_MUTE("Surround Playback Switch", 0x0d, 0x0, HDA_INPUT),
 	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
 	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x04, 1, 2, HDA_INPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x04, 2, 2, HDA_INPUT),
+	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x0e, 1, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x0, HDA_INPUT),
 	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
 	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
 	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-- 
cgit v1.2.3-70-g09d2


From 3da23cac3d6b93803b8c381a755870cbafcd3212 Mon Sep 17 00:00:00 2001
From: Herton Ronaldo Krzesinski <herton@mandriva.com>
Date: Fri, 14 Mar 2008 12:52:59 +0100
Subject: [ALSA] hda-codec - Map 3stack-6ch-dig ALC662 model for Asus P5GC-MX

Map 3stack-6ch-dig ALC662 model for Asus P5GC-MX.

Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c | 1 +
 1 file changed, 1 insertion(+)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 8eb64dbfc78..c85da5766d3 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -13534,6 +13534,7 @@ static const char *alc662_models[ALC662_MODEL_LAST] = {
 };
 
 static struct snd_pci_quirk alc662_cfg_tbl[] = {
+	SND_PCI_QUIRK(0x1043, 0x8290, "ASUS P5GC-MX", ALC662_3ST_6ch_DIG),
 	SND_PCI_QUIRK(0x1043, 0x82a1, "ASUS Eeepc", ALC662_ASUS_EEEPC_P701),
 	SND_PCI_QUIRK(0x1043, 0x82d1, "ASUS Eeepc EP20", ALC662_ASUS_EEEPC_EP20),
 	SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E),
-- 
cgit v1.2.3-70-g09d2


From ee9d6b9a30ae83f15fe8c8d2337ebc0a38151d38 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Fri, 14 Mar 2008 15:52:20 +0100
Subject: [ALSA] hda-intel - Fix power-off hang on ASUS P5AD2

The hda-intel driver has a problem at power-off on ASUS P5AD2.
It's caused when the position-buffer is enabled -- most likely a
hardware-specific problem.

This patch adds a quirk to avoid the unnecessary enablement of
position-buffer.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/hda_intel.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 3d9f0bd63ba..9a20fb1bef4 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -1059,9 +1059,12 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
 	azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl.addr));
 
 	/* enable the position buffer */
-	if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
-		azx_writel(chip, DPLBASE,
-			   (u32)chip->posbuf.addr |ICH6_DPLBASE_ENABLE);
+	if (chip->position_fix == POS_FIX_POSBUF ||
+	    chip->position_fix == POS_FIX_AUTO) {
+		if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
+			azx_writel(chip, DPLBASE,
+				(u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE);
+	}
 
 	/* set the interrupt enable bits in the descriptor control register */
 	azx_sd_writel(azx_dev, SD_CTL,
@@ -1707,6 +1710,7 @@ static int azx_dev_free(struct snd_device *device)
 static struct snd_pci_quirk position_fix_list[] __devinitdata = {
 	SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_NONE),
 	SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_NONE),
+	SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_NONE),
 	{}
 };
 
-- 
cgit v1.2.3-70-g09d2


From 5d9fab2d84963ec598810c54a67332decdd922a8 Mon Sep 17 00:00:00 2001
From: Tony Vroon <tony@linx.net>
Date: Fri, 14 Mar 2008 17:09:18 +0100
Subject: [ALSA] hda-codec - Fujitsu Lifebook port replicator/dock headphone
 jack sense

The docking station headphone output had no audio and jack sense
was not considered.

Jack information from the laptop itself and the dock are combined, as
the dock does not obscure the connector.

Signed-off-by: Tony Vroon <tony@linx.net>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c | 30 +++++++++++++++++++-----------
 1 file changed, 19 insertions(+), 11 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index c85da5766d3..bf729f518f8 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -8725,7 +8725,8 @@ static void alc262_hippo1_unsol_event(struct hda_codec *codec,
 
 /*
  * fujitsu model
- *  0x14 = headphone/spdif-out, 0x15 = internal speaker
+ *  0x14 = headphone/spdif-out, 0x15 = internal speaker,
+ *  0x1b = port replicator headphone out
  */
 
 #define ALC_HP_EVENT	0x37
@@ -8733,6 +8734,8 @@ static void alc262_hippo1_unsol_event(struct hda_codec *codec,
 static struct hda_verb alc262_fujitsu_unsol_verbs[] = {
 	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
 	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
 	{}
 };
 
@@ -8773,12 +8776,16 @@ static void alc262_fujitsu_automute(struct hda_codec *codec, int force)
 	unsigned int mute;
 
 	if (force || !spec->sense_updated) {
-		unsigned int present;
+		unsigned int present_int_hp, present_dock_hp;
 		/* need to execute and sync at first */
 		snd_hda_codec_read(codec, 0x14, 0, AC_VERB_SET_PIN_SENSE, 0);
-		present = snd_hda_codec_read(codec, 0x14, 0,
-				    	 AC_VERB_GET_PIN_SENSE, 0);
-		spec->jack_present = (present & 0x80000000) != 0;
+		present_int_hp = snd_hda_codec_read(codec, 0x14, 0,
+					AC_VERB_GET_PIN_SENSE, 0);
+		snd_hda_codec_read(codec, 0x1B, 0, AC_VERB_SET_PIN_SENSE, 0);
+		present_dock_hp = snd_hda_codec_read(codec, 0x1b, 0,
+					AC_VERB_GET_PIN_SENSE, 0);
+		spec->jack_present = (present_int_hp & 0x80000000) != 0;
+		spec->jack_present |= (present_dock_hp & 0x80000000) != 0;
 		spec->sense_updated = 1;
 	}
 	if (spec->jack_present) {
@@ -8820,12 +8827,13 @@ static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol,
 	long *valp = ucontrol->value.integer.value;
 	int change;
 
-	change = snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
-					  HDA_AMP_MUTE,
-					  valp[0] ? 0 : HDA_AMP_MUTE);
-	change |= snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
-					   HDA_AMP_MUTE,
-					   valp[1] ? 0 : HDA_AMP_MUTE);
+	change = snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+						 HDA_AMP_MUTE,
+						 valp ? 0 : HDA_AMP_MUTE);
+	change |= snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
+						 HDA_AMP_MUTE,
+						 valp ? 0 : HDA_AMP_MUTE);
+
 	if (change)
 		alc262_fujitsu_automute(codec, 0);
 	return change;
-- 
cgit v1.2.3-70-g09d2


From c93f5a1eca1f6d662d791c14c469b6962e05a08f Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Fri, 14 Mar 2008 17:17:09 +0100
Subject: [ALSA] ice1724 - Fix the SPDIF input sample-rate on Juli@

AK4114 on Juli@ has the SPDIF input sample rate detection and
causes errors when an incompatible sample rate is chosen.
The patch adds the open hook to check the current rate and limit
the hw constraints.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/ice1712/ice1724.c |  8 ++++++++
 sound/pci/ice1712/juli.c    | 17 +++++++++++++++++
 2 files changed, 25 insertions(+)

(limited to 'sound')

diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index f533850ec6e..3bfd70577d7 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -970,6 +970,8 @@ static int snd_vt1724_playback_spdif_open(struct snd_pcm_substream *substream)
 				   VT1724_BUFFER_ALIGN);
 	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
 				   VT1724_BUFFER_ALIGN);
+	if (ice->spdif.ops.open)
+		ice->spdif.ops.open(ice, substream);
 	return 0;
 }
 
@@ -980,6 +982,8 @@ static int snd_vt1724_playback_spdif_close(struct snd_pcm_substream *substream)
 	if (PRO_RATE_RESET)
 		snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
 	ice->playback_con_substream = NULL;
+	if (ice->spdif.ops.close)
+		ice->spdif.ops.close(ice, substream);
 
 	return 0;
 }
@@ -1002,6 +1006,8 @@ static int snd_vt1724_capture_spdif_open(struct snd_pcm_substream *substream)
 				   VT1724_BUFFER_ALIGN);
 	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
 				   VT1724_BUFFER_ALIGN);
+	if (ice->spdif.ops.open)
+		ice->spdif.ops.open(ice, substream);
 	return 0;
 }
 
@@ -1012,6 +1018,8 @@ static int snd_vt1724_capture_spdif_close(struct snd_pcm_substream *substream)
 	if (PRO_RATE_RESET)
 		snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
 	ice->capture_con_substream = NULL;
+	if (ice->spdif.ops.close)
+		ice->spdif.ops.close(ice, substream);
 
 	return 0;
 }
diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c
index e8038c0ceb7..4550609b4d4 100644
--- a/sound/pci/ice1712/juli.c
+++ b/sound/pci/ice1712/juli.c
@@ -77,6 +77,22 @@ static unsigned char juli_ak4114_read(void *private_data, unsigned char reg)
 	return snd_vt1724_read_i2c((struct snd_ice1712 *)private_data, AK4114_ADDR, reg);
 }
 
+static void juli_spdif_in_open(struct snd_ice1712 *ice,
+			       struct snd_pcm_substream *substream)
+{
+	struct juli_spec *spec = ice->spec;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	int rate;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		return;
+	rate = snd_ak4114_external_rate(spec->ak4114);
+	if (rate >= runtime->hw.rate_min && rate <= runtime->hw.rate_max) {
+		runtime->hw.rate_min = rate;
+		runtime->hw.rate_max = rate;
+	}
+}
+
 /*
  * AK4358 section
  */
@@ -210,6 +226,7 @@ static int __devinit juli_init(struct snd_ice1712 *ice)
 			return err;
 	}
 	
+	ice->spdif.ops.open = juli_spdif_in_open;
 	return 0;
 }
 
-- 
cgit v1.2.3-70-g09d2


From 5949d2443d96f054d9a32d31edddb0be836968c6 Mon Sep 17 00:00:00 2001
From: Joachim Foerster <JOFT@gmx.de>
Date: Mon, 17 Mar 2008 08:40:12 +0100
Subject: [ALSA] [ML403-AC97CR] Remove duplicate snd_card_set_dev()

We want to have snd_card_set_dev() in _probe(), but not a second one in
snd_ml403_ac97cr_create().

Signed-off-by: Joachim Foerster <JOFT@gmx.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/drivers/ml403-ac97cr.c | 2 --
 1 file changed, 2 deletions(-)

(limited to 'sound')

diff --git a/sound/drivers/ml403-ac97cr.c b/sound/drivers/ml403-ac97cr.c
index 05a871aa7b8..b654007331d 100644
--- a/sound/drivers/ml403-ac97cr.c
+++ b/sound/drivers/ml403-ac97cr.c
@@ -1191,8 +1191,6 @@ snd_ml403_ac97cr_create(struct snd_card *card, struct platform_device *pfdev,
 		return err;
 	}
 
-	snd_card_set_dev(card, &pfdev->dev);
-
 	*rml403_ac97cr = ml403_ac97cr;
 	return 0;
 }
-- 
cgit v1.2.3-70-g09d2


From 841b23d4d7b554c8d74fc9c34a701f85abc04875 Mon Sep 17 00:00:00 2001
From: Pavel Hofman <dustin@seznam.cz>
Date: Mon, 17 Mar 2008 08:45:33 +0100
Subject: [ALSA] some fixes and cleanup for ICE1724 cards

* removing the hack with NON_AKM ak4xxx type
* support for card-specific flags in ak4114_stats
* definition of the flags for corresponding cards

Signed-off-by: Pavel Hofman <dustin@seznam.cz>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 include/sound/ak4114.h         |  1 +
 include/sound/ak4xxx-adda.h    |  2 +-
 sound/i2c/other/ak4114.c       |  2 +-
 sound/i2c/other/ak4xxx-adda.c  | 16 ++++++++--------
 sound/pci/ice1712/prodigy192.c | 33 ++++++++++-----------------------
 sound/pci/ice1712/revo.c       |  4 ++++
 6 files changed, 25 insertions(+), 33 deletions(-)

(limited to 'sound')

diff --git a/include/sound/ak4114.h b/include/sound/ak4114.h
index 4e80d3fe738..d293d36a66b 100644
--- a/include/sound/ak4114.h
+++ b/include/sound/ak4114.h
@@ -182,6 +182,7 @@ struct ak4114 {
 	unsigned char rcs0;
 	unsigned char rcs1;
 	struct delayed_work work;
+	unsigned int check_flags;
 	void *change_callback_private;
 	void (*change_callback)(struct ak4114 *ak4114, unsigned char c0, unsigned char c1);
 };
diff --git a/include/sound/ak4xxx-adda.h b/include/sound/ak4xxx-adda.h
index 6153b91cdc3..891cf1aea8b 100644
--- a/include/sound/ak4xxx-adda.h
+++ b/include/sound/ak4xxx-adda.h
@@ -68,7 +68,7 @@ struct snd_akm4xxx {
 	enum {
 		SND_AK4524, SND_AK4528, SND_AK4529,
 		SND_AK4355, SND_AK4358, SND_AK4381,
-		SND_AK5365, NON_AKM
+		SND_AK5365
 	} type;
 
 	/* (array) information of combined codecs */
diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c
index 9a90e830c42..d20d893b3b6 100644
--- a/sound/i2c/other/ak4114.c
+++ b/sound/i2c/other/ak4114.c
@@ -612,7 +612,7 @@ static void ak4114_stats(struct work_struct *work)
 	struct ak4114 *chip = container_of(work, struct ak4114, work.work);
 
 	if (!chip->init)
-		snd_ak4114_check_rate_and_errors(chip, 0);
+		snd_ak4114_check_rate_and_errors(chip, chip->check_flags);
 
 	schedule_delayed_work(&chip->work, HZ / 10);
 }
diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c
index 35fbbf2cb9f..288926d2e20 100644
--- a/sound/i2c/other/ak4xxx-adda.c
+++ b/sound/i2c/other/ak4xxx-adda.c
@@ -70,7 +70,8 @@ static void ak4524_reset(struct snd_akm4xxx *ak, int state)
 }
 
 /* reset procedure for AK4355 and AK4358 */
-static void ak4355_reset(struct snd_akm4xxx *ak, int state)
+static void ak435X_reset(struct snd_akm4xxx *ak, int state,
+		unsigned char total_regs)
 {
 	unsigned char reg;
 
@@ -78,7 +79,7 @@ static void ak4355_reset(struct snd_akm4xxx *ak, int state)
 		snd_akm4xxx_write(ak, 0, 0x01, 0x02); /* reset and soft-mute */
 		return;
 	}
-	for (reg = 0x00; reg < 0x0b; reg++)
+	for (reg = 0x00; reg < total_regs; reg++)
 		if (reg != 0x01)
 			snd_akm4xxx_write(ak, 0, reg,
 					  snd_akm4xxx_get(ak, 0, reg));
@@ -118,8 +119,10 @@ void snd_akm4xxx_reset(struct snd_akm4xxx *ak, int state)
 		/* FIXME: needed for ak4529? */
 		break;
 	case SND_AK4355:
+		ak435X_reset(ak, state, 0x0b);
+		break;
 	case SND_AK4358:
-		ak4355_reset(ak, state);
+		ak435X_reset(ak, state, 0x10);
 		break;
 	case SND_AK4381:
 		ak4381_reset(ak, state);
@@ -292,11 +295,6 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak)
 	case SND_AK5365:
 		/* FIXME: any init sequence? */
 		return;
-	case NON_AKM:
-		/* fake value for non-akm codecs using akm infrastructure
-		 * (e.g. of ice1724) - certainly FIXME
-		 */
-		return;
 	default:
 		snd_BUG();
 		return;
@@ -374,6 +372,8 @@ static int put_ak_reg(struct snd_kcontrol *kcontrol, int addr,
 		nval = mask - nval;
 	if (AK_GET_NEEDSMSB(kcontrol->private_value))
 		nval |= 0x80;
+	/* printk(KERN_DEBUG "DEBUG - AK writing reg: chip %x addr %x,
+	   nval %x\n", chip, addr, nval); */
 	snd_akm4xxx_write(ak, chip, addr, nval);
 	return 1;
 }
diff --git a/sound/pci/ice1712/prodigy192.c b/sound/pci/ice1712/prodigy192.c
index 48cf40a8f32..25ceb67a9c1 100644
--- a/sound/pci/ice1712/prodigy192.c
+++ b/sound/pci/ice1712/prodigy192.c
@@ -319,12 +319,11 @@ static int stac9460_mic_sw_put(struct snd_kcontrol *kcontrol,
 /*
  * Handler for setting correct codec rate - called when rate change is detected
  */
-static void stac9460_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate)
+static void stac9460_set_rate_val(struct snd_ice1712 *ice, unsigned int rate)
 {
 	unsigned char old, new;
 	int idx;
 	unsigned char changed[7];
-	struct snd_ice1712 *ice = ak->private_data[0];
 	struct prodigy192_spec *spec = ice->spec;
 
 	if (rate == 0)  /* no hint - S/PDIF input is master, simply return */
@@ -357,16 +356,6 @@ static void stac9460_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate)
 	mutex_unlock(&spec->mute_mutex);
 }
 
-/* using akm infrastructure for setting rate of the codec */
-static struct snd_akm4xxx akmlike_stac9460 __devinitdata = {
-	.type = NON_AKM,	/* special value */
-	.num_adcs = 6,		/* not used in any way, just for completeness */
-	.num_dacs = 2,
-	.ops = {
-		.set_rate_val = stac9460_set_rate_val
-	}
-};
-
 
 static const DECLARE_TLV_DB_SCALE(db_scale_dac, -19125, 75, 0);
 static const DECLARE_TLV_DB_SCALE(db_scale_adc, 0, 150, 0);
@@ -642,12 +631,19 @@ static int prodigy192_ak4114_init(struct snd_ice1712 *ice)
 		0x41, 0x02, 0x2c, 0x00, 0x00
 	};
 	struct prodigy192_spec *spec = ice->spec;
+	int err;
 
-	return snd_ak4114_create(ice->card,
+	err = snd_ak4114_create(ice->card,
 				 prodigy192_ak4114_read,
 				 prodigy192_ak4114_write,
 				 ak4114_init_vals, ak4114_init_txcsb,
 				 ice, &spec->ak4114);
+	if (err < 0)
+		return err;
+	/* AK4114 in Prodigy192 cannot detect external rate correctly.
+	 * No reason to stop capture stream due to incorrect checks */
+	spec->ak4114->check_flags = AK4114_CHECK_NO_RATE;
+	return 0;
 }
 
 static void stac9460_proc_regs_read(struct snd_info_entry *entry,
@@ -743,7 +739,6 @@ static int __devinit prodigy192_init(struct snd_ice1712 *ice)
 	};
 	const unsigned short *p;
 	int err = 0;
-	struct snd_akm4xxx *ak;
 	struct prodigy192_spec *spec;
 
 	/* prodigy 192 */
@@ -761,15 +756,7 @@ static int __devinit prodigy192_init(struct snd_ice1712 *ice)
 	p = stac_inits_prodigy;
 	for (; *p != (unsigned short)-1; p += 2)
 		stac9460_put(ice, p[0], p[1]);
-	/* reusing the akm codecs infrastructure,
-	 * for setting rate on stac9460 */
-	ak = ice->akm = kmalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
-	if (!ak)
-		return -ENOMEM;
-	ice->akm_codecs = 1;
-	err = snd_ice1712_akm4xxx_init(ak, &akmlike_stac9460, NULL, ice);
-	if (err < 0)
-		return err;
+	ice->gpio.set_pro_rate = stac9460_set_rate_val;
 
 	/* MI/ODI/O add on card with AK4114 */
 	if (prodigy192_miodio_exists(ice)) {
diff --git a/sound/pci/ice1712/revo.c b/sound/pci/ice1712/revo.c
index 7c930cc05f1..dba93d8efbe 100644
--- a/sound/pci/ice1712/revo.c
+++ b/sound/pci/ice1712/revo.c
@@ -488,6 +488,10 @@ static int __devinit ap192_ak4114_init(struct snd_ice1712 *ice)
 				 ap192_ak4114_write,
 				 ak4114_init_vals, ak4114_init_txcsb,
 				 ice, &ak);
+	/* AK4114 in Revo cannot detect external rate correctly.
+	 * No reason to stop capture stream due to incorrect checks */
+	ak->check_flags = AK4114_CHECK_NO_RATE;
+
 	return 0; /* error ignored; it's no fatal error */
 }
 
-- 
cgit v1.2.3-70-g09d2


From 5a220c868e395bc3662d13ad4c2a18769075af54 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 17 Mar 2008 09:59:32 +0100
Subject: [ALSA] usb-audio - Add a proper error check

The error in check_hw_params_convention() has to be checked and
handled properly.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/usbaudio.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

(limited to 'sound')

diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index f48838a078c..5c40c031dd5 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -1762,8 +1762,10 @@ static int check_hw_params_convention(struct snd_usb_substream *subs)
 
 	channels = kcalloc(MAX_MASK, sizeof(u32), GFP_KERNEL);
 	rates = kcalloc(MAX_MASK, sizeof(u32), GFP_KERNEL);
-	if (!channels || !rates)
+	if (!channels || !rates) {
+		err = -ENOMEM;
 		goto __out;
+	}
 
 	list_for_each(p, &subs->fmt_list) {
 		struct audioformat *f;
@@ -1916,7 +1918,10 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
 				     1000 * MIN_PACKS_URB,
 				     /*(nrpacks * MAX_URBS) * 1000*/ UINT_MAX);
 
-	if (check_hw_params_convention(subs)) {
+	err = check_hw_params_convention(subs);
+	if (err < 0)
+		return err;
+	else if (err) {
 		hwc_debug("setting extra hw constraints...\n");
 		if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
 					       hw_rule_rate, subs,
-- 
cgit v1.2.3-70-g09d2


From 43337ac0dec5fe507b3028d2ad4404c3f1a28034 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 17 Mar 2008 10:16:37 +0100
Subject: [ALSA] ice1724 - Fix return codes in some pointis callbacks

Fixed the return codes (1 for changed values) in put callbacks of
pontis.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/ice1712/pontis.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/ice1712/pontis.c b/sound/pci/ice1712/pontis.c
index 4945c81e8a9..203cdc1bf8d 100644
--- a/sound/pci/ice1712/pontis.c
+++ b/sound/pci/ice1712/pontis.c
@@ -246,7 +246,7 @@ static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val
 		wm_put(ice, WM_ADC_MUX, nval);
 	}
 	mutex_unlock(&ice->gpio_mutex);
-	return 0;
+	return change;
 }
 
 /*
@@ -450,7 +450,7 @@ static int cs_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu
 		change = 1;
 	}
 	mutex_unlock(&ice->gpio_mutex);
-	return 0;
+	return change;
 }
 
 
-- 
cgit v1.2.3-70-g09d2


From b32300a4ce78b4df92f33c455ffe644b36f0ff1a Mon Sep 17 00:00:00 2001
From: Julia Lawall <julia@diku.dk>
Date: Mon, 17 Mar 2008 10:23:35 +0100
Subject: [ALSA] sound/pci: remove unused variable

The variable is_capture is initialized but never used otherwise.

The semantic patch that makes this change is as follows:
(http://www.emn.fr/x-info/coccinelle/)

// <smpl>
@@
type T;
identifier i;
constant C;
@@

(
extern T i;
|
- T i;
  <+... when != i
- i = C;
  ...+>
)
// </smpl>

Signed-off-by: Julia Lawall <julia@diku.dk>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/pcxhr/pcxhr.c | 3 ---
 1 file changed, 3 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c
index 9d5bb76229a..beed5818338 100644
--- a/sound/pci/pcxhr/pcxhr.c
+++ b/sound/pci/pcxhr/pcxhr.c
@@ -846,7 +846,6 @@ static int pcxhr_open(struct snd_pcm_substream *subs)
 	struct pcxhr_mgr       *mgr = chip->mgr;
 	struct snd_pcm_runtime *runtime = subs->runtime;
 	struct pcxhr_stream    *stream;
-	int                 is_capture;
 
 	mutex_lock(&mgr->setup_mutex);
 
@@ -856,12 +855,10 @@ static int pcxhr_open(struct snd_pcm_substream *subs)
 	if( subs->stream == SNDRV_PCM_STREAM_PLAYBACK ) {
 		snd_printdd("pcxhr_open playback chip%d subs%d\n",
 			    chip->chip_idx, subs->number);
-		is_capture = 0;
 		stream = &chip->playback_stream[subs->number];
 	} else {
 		snd_printdd("pcxhr_open capture chip%d subs%d\n",
 			    chip->chip_idx, subs->number);
-		is_capture = 1;
 		if (mgr->mono_capture)
 			runtime->hw.channels_max = 1;
 		else
-- 
cgit v1.2.3-70-g09d2


From f5e09ef0985ff01af6b4a12954840467f153a41c Mon Sep 17 00:00:00 2001
From: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Date: Mon, 17 Mar 2008 14:36:24 +0100
Subject: [ALSA] at73c213: Add constraints for periods value

The interrupt handler always provide runtime->period_size data, so it
works correctly only if buffer_size was a multiple of period_size.

This patch fixes periodic click noise.

Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/spi/at73c213.c | 6 ++++++
 1 file changed, 6 insertions(+)

(limited to 'sound')

diff --git a/sound/spi/at73c213.c b/sound/spi/at73c213.c
index aa571152f03..09802e8a6fb 100644
--- a/sound/spi/at73c213.c
+++ b/sound/spi/at73c213.c
@@ -210,7 +210,13 @@ static int snd_at73c213_pcm_open(struct snd_pcm_substream *substream)
 {
 	struct snd_at73c213 *chip = snd_pcm_substream_chip(substream);
 	struct snd_pcm_runtime *runtime = substream->runtime;
+	int err;
 
+	/* ensure buffer_size is a multiple of period_size */
+	err = snd_pcm_hw_constraint_integer(runtime,
+					SNDRV_PCM_HW_PARAM_PERIODS);
+	if (err < 0)
+		return err;
 	snd_at73c213_playback_hw.rate_min = chip->bitrate;
 	snd_at73c213_playback_hw.rate_max = chip->bitrate;
 	runtime->hw = snd_at73c213_playback_hw;
-- 
cgit v1.2.3-70-g09d2


From 9ecaedae0de906f0b5f8dbc09cd610f7056ba975 Mon Sep 17 00:00:00 2001
From: Mariusz Kozlowski <m.kozlowski@tuxland.pl>
Date: Tue, 18 Mar 2008 09:03:03 +0100
Subject: [ALSA] sound/drivers/pcsp/pcsp.c build fix

sound/drivers/pcsp/pcsp.c: In function 'snd_pcsp_create':
sound/drivers/pcsp/pcsp.c:54: error: 'loops_per_jiffy' undeclared (first use in\ this function)
sound/drivers/pcsp/pcsp.c:54: error: (Each undeclared identifier is reported on\ ly once
sound/drivers/pcsp/pcsp.c:54: error: for each function it appears in.)

Signed-off-by: Mariusz Kozlowski <m.kozlowski@tuxland.pl>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/drivers/pcsp/pcsp.c | 1 +
 1 file changed, 1 insertion(+)

(limited to 'sound')

diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c
index ac57e87d01b..d8f96219fd3 100644
--- a/sound/drivers/pcsp/pcsp.c
+++ b/sound/drivers/pcsp/pcsp.c
@@ -12,6 +12,7 @@
 #include <sound/initval.h>
 #include <sound/pcm.h>
 #include <linux/input.h>
+#include <linux/delay.h>
 #include <asm/bitops.h>
 #include "pcsp_input.h"
 #include "pcsp.h"
-- 
cgit v1.2.3-70-g09d2


From f32a19e3e7e72cc896d02c3d104f58dc972d43ea Mon Sep 17 00:00:00 2001
From: Herton Ronaldo Krzesinski <herton@mandriva.com>
Date: Tue, 18 Mar 2008 09:27:08 +0100
Subject: [ALSA] hda-codec - Fix DAC assignment order in ALC883

Actually clfe and surround DACs are inverted in alc883_dac_nids array
(see ALC883 datasheet). I discovered this while testing multi-channel
setup (using 3stack-6ch-dig model) on MSI 945GCM5 V2 motherboard that
has an ALC883 codec. Simply Rear Left/Right and Center/LFE were swapped
in 6 channel mode (also in 4 channel mode you didn't get rear left/right
output). Other models also were affected by this bug, as can be seen by
the mixer layouts that "workaround" this (the real bug was not noticed,
and some other models simply played with mixer and initial verbs). Thus
along with fixing the order of dac nids, also change the models that
relied on previous dac ordering properly.

Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c | 56 +++++++++++++++++--------------------------
 1 file changed, 22 insertions(+), 34 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index bf729f518f8..d55987479dd 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -6450,7 +6450,7 @@ static int patch_alc882(struct hda_codec *codec)
 
 static hda_nid_t alc883_dac_nids[4] = {
 	/* front, rear, clfe, rear_surr */
-	0x02, 0x04, 0x03, 0x05
+	0x02, 0x03, 0x04, 0x05
 };
 
 static hda_nid_t alc883_adc_nids[2] = {
@@ -6958,12 +6958,12 @@ static struct snd_kcontrol_new alc883_medion_md2_mixer[] = {
 static struct snd_kcontrol_new alc888_6st_hp_mixer[] = {
 	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
 	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Surround Playback Switch", 0x0e, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
 	HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
 	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
 	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
@@ -6998,12 +6998,12 @@ static struct snd_kcontrol_new alc888_6st_hp_mixer[] = {
 static struct snd_kcontrol_new alc888_3st_hp_mixer[] = {
 	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
 	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Surround Playback Switch", 0x0e, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
 	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
 	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
 	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
@@ -7036,12 +7036,12 @@ static struct snd_kcontrol_new alc888_3st_hp_mixer[] = {
 static struct snd_kcontrol_new alc888_6st_dell_mixer[] = {
 	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
 	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Surround Playback Switch", 0x0e, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
 	HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
 	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
 	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
@@ -7332,26 +7332,14 @@ static struct hda_verb alc883_haier_w66_verbs[] = {
 	{ } /* end */
 };
 
-static struct hda_verb alc888_6st_hp_verbs[] = {
-	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},	/* Front: output 0 (0x0c) */
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x02},	/* Rear : output 2 (0x0e) */
-	{0x16, AC_VERB_SET_CONNECT_SEL, 0x01},	/* CLFE : output 1 (0x0d) */
-	{0x17, AC_VERB_SET_CONNECT_SEL, 0x03},	/* Side : output 3 (0x0f) */
-	{ }
-};
-
 static struct hda_verb alc888_3st_hp_verbs[] = {
 	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},	/* Front: output 0 (0x0c) */
-	{0x18, AC_VERB_SET_CONNECT_SEL, 0x01},	/* Rear : output 1 (0x0d) */
-	{0x16, AC_VERB_SET_CONNECT_SEL, 0x02},	/* CLFE : output 2 (0x0e) */
+	{0x16, AC_VERB_SET_CONNECT_SEL, 0x01},	/* Rear : output 1 (0x0d) */
+	{0x18, AC_VERB_SET_CONNECT_SEL, 0x02},	/* CLFE : output 2 (0x0e) */
 	{ }
 };
 
 static struct hda_verb alc888_6st_dell_verbs[] = {
-	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},	/* Front: output 0 (0x0c) */
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x02},	/* Rear : output 1 (0x0e) */
-	{0x16, AC_VERB_SET_CONNECT_SEL, 0x01},	/* CLFE : output 2 (0x0d) */
-	{0x17, AC_VERB_SET_CONNECT_SEL, 0x03},	/* Side : output 3 (0x0f) */
 	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
 	{ }
 };
@@ -7985,7 +7973,7 @@ static struct alc_config_preset alc883_presets[] = {
 	},	
 	[ALC888_6ST_HP] = {
 		.mixers = { alc888_6st_hp_mixer, alc883_chmode_mixer },
-		.init_verbs = { alc883_init_verbs, alc888_6st_hp_verbs },
+		.init_verbs = { alc883_init_verbs },
 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
 		.dac_nids = alc883_dac_nids,
 		.dig_out_nid = ALC883_DIGOUT_NID,
-- 
cgit v1.2.3-70-g09d2


From 86d34b7ec878ea4b4c9f33ce92f1722c4326dbe7 Mon Sep 17 00:00:00 2001
From: Herton Ronaldo Krzesinski <herton@mandriva.com>
Date: Tue, 18 Mar 2008 09:27:59 +0100
Subject: [ALSA] hda-codec - Map 3stack-6ch-dig ALC883 model for MSI 945GCM5 V2
 (MSI-7267)

Map 3stack-6ch-dig ALC883 model for MSI 945GCM5 V2 (MSI-7267).

Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c | 1 +
 1 file changed, 1 insertion(+)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index d55987479dd..c21d7863e0d 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -7763,6 +7763,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
 	SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC883_6ST_DIG),
 	SND_PCI_QUIRK(0x1462, 0x7187, "MSI", ALC883_6ST_DIG),
 	SND_PCI_QUIRK(0x1462, 0x7250, "MSI", ALC883_6ST_DIG),
+	SND_PCI_QUIRK(0x1462, 0x7267, "MSI", ALC883_3ST_6ch_DIG),
 	SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG),
 	SND_PCI_QUIRK(0x1462, 0x7327, "MSI", ALC883_6ST_DIG),
 	SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG),
-- 
cgit v1.2.3-70-g09d2


From 2add9b925394746eff692ff0875d21ea2d5289e2 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Tue, 18 Mar 2008 09:47:06 +0100
Subject: [ALSA] hda-intel - Add barrier

Add proper barriers in the RIRB communication code.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/hda_intel.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 9a20fb1bef4..557f269f83a 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -536,8 +536,9 @@ static void azx_update_rirb(struct azx *chip)
 		if (res_ex & ICH6_RIRB_EX_UNSOL_EV)
 			snd_hda_queue_unsol_event(chip->bus, res, res_ex);
 		else if (chip->rirb.cmds) {
-			chip->rirb.cmds--;
 			chip->rirb.res = res;
+			smp_wmb();
+			chip->rirb.cmds--;
 		}
 	}
 }
@@ -556,8 +557,10 @@ static unsigned int azx_rirb_get_response(struct hda_codec *codec)
 			azx_update_rirb(chip);
 			spin_unlock_irq(&chip->reg_lock);
 		}
-		if (!chip->rirb.cmds)
+		if (!chip->rirb.cmds) {
+			smp_rmb();
 			return chip->rirb.res; /* the last value */
+		}
 		if (time_after(jiffies, timeout))
 			break;
 		if (codec->bus->needs_damn_long_delay)
-- 
cgit v1.2.3-70-g09d2


From 117f257d7a9599ff9cb5ab7a6a10201c6294b5f1 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Tue, 18 Mar 2008 09:53:23 +0100
Subject: [ALSA] hda-codec - Fix spekaer output of Panasonic CF-74

Add a new model "panasonic" for Panasonic CF-74 with STAC9200 codec
to fix the speaker output.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 Documentation/sound/alsa/ALSA-Configuration.txt |  1 +
 sound/pci/hda/patch_sigmatel.c                  | 10 +++++++++-
 2 files changed, 10 insertions(+), 1 deletion(-)

(limited to 'sound')

diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 80a0629f491..b02404395e5 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -992,6 +992,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
 	  dell-m26	Dell Inspiron 1501
 	  dell-m27	Dell Inspiron E1705/9400
 	  gateway	Gateway laptops with EAPD control
+	  panasonic	Panasonic CF-74
 
 	STAC9205/9254
 	  ref		Reference board
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index b8e69a1b93f..a39fbd89a98 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -52,6 +52,7 @@ enum {
 	STAC_9200_DELL_M26,
 	STAC_9200_DELL_M27,
 	STAC_9200_GATEWAY,
+	STAC_9200_PANASONIC,
 	STAC_9200_MODELS
 };
 
@@ -1121,6 +1122,7 @@ static unsigned int *stac9200_brd_tbl[STAC_9200_MODELS] = {
 	[STAC_9200_DELL_M25] = dell9200_m25_pin_configs,
 	[STAC_9200_DELL_M26] = dell9200_m26_pin_configs,
 	[STAC_9200_DELL_M27] = dell9200_m27_pin_configs,
+	[STAC_9200_PANASONIC] = ref9200_pin_configs,
 };
 
 static const char *stac9200_models[STAC_9200_MODELS] = {
@@ -1137,6 +1139,7 @@ static const char *stac9200_models[STAC_9200_MODELS] = {
 	[STAC_9200_DELL_M26] = "dell-m26",
 	[STAC_9200_DELL_M27] = "dell-m27",
 	[STAC_9200_GATEWAY] = "gateway",
+	[STAC_9200_PANASONIC] = "panasonic",
 };
 
 static struct snd_pci_quirk stac9200_cfg_tbl[] = {
@@ -1203,7 +1206,7 @@ static struct snd_pci_quirk stac9200_cfg_tbl[] = {
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f6,
 		      "unknown Dell", STAC_9200_DELL_M26),
 	/* Panasonic */
-	SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-74", STAC_REF),
+	SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-74", STAC_9200_PANASONIC),
 	/* Gateway machines needs EAPD to be set on resume */
 	SND_PCI_QUIRK(0x107b, 0x0205, "Gateway S-7110M", STAC_9200_GATEWAY),
 	SND_PCI_QUIRK(0x107b, 0x0317, "Gateway MT3423, MX341*",
@@ -3302,6 +3305,11 @@ static int patch_stac9200(struct hda_codec *codec)
 		spec->init = stac9200_core_init;
 	spec->mixer = stac9200_mixer;
 
+	if (spec->board_config == STAC_9200_PANASONIC) {
+		spec->gpio_mask = spec->gpio_dir = 0x09;
+		spec->gpio_data = 0x00;
+	}
+
 	err = stac9200_parse_auto_config(codec);
 	if (err < 0) {
 		stac92xx_free(codec);
-- 
cgit v1.2.3-70-g09d2


From 888afa15418f001896bc11f498f9348e029611bd Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Tue, 18 Mar 2008 09:57:50 +0100
Subject: [ALSA] hda-codec - keep the format verb at closing PCM streams

Keep the format verb at closing PCM streams.
Introduced snd_hda_codec_cleanup_stream() for the parcicular purpose.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/hda_codec.c      | 31 +++++++++++++++++++++----------
 sound/pci/hda/hda_codec.h      |  1 +
 sound/pci/hda/hda_generic.c    |  4 ++--
 sound/pci/hda/patch_analog.c   |  6 ++----
 sound/pci/hda/patch_cmedia.c   |  2 +-
 sound/pci/hda/patch_conexant.c |  7 +++----
 sound/pci/hda/patch_realtek.c  |  4 ++--
 sound/pci/hda/patch_sigmatel.c |  2 +-
 sound/pci/hda/patch_via.c      |  3 +--
 9 files changed, 34 insertions(+), 26 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index e6bace83e7c..689d177c17b 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -720,6 +720,19 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
 	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format);
 }
 
+void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
+{
+	if (!nid)
+		return;
+
+	snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid);
+	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
+#if 0 /* keep the format */
+	msleep(1);
+	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0);
+#endif
+}
+
 /*
  * amp access functions
  */
@@ -2204,7 +2217,7 @@ static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo,
 				   struct hda_codec *codec,
 				   struct snd_pcm_substream *substream)
 {
-	snd_hda_codec_setup_stream(codec, hinfo->nid, 0, 0, 0);
+	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
 	return 0;
 }
 
@@ -2589,7 +2602,7 @@ int snd_hda_multi_out_dig_open(struct hda_codec *codec,
 	mutex_lock(&codec->spdif_mutex);
 	if (mout->dig_out_used == HDA_DIG_ANALOG_DUP)
 		/* already opened as analog dup; reset it once */
-		snd_hda_codec_setup_stream(codec, mout->dig_out_nid, 0, 0, 0);
+		snd_hda_codec_cleanup_stream(codec, mout->dig_out_nid);
 	mout->dig_out_used = HDA_DIG_EXCLUSIVE;
 	mutex_unlock(&codec->spdif_mutex);
 	return 0;
@@ -2684,8 +2697,7 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
 					     stream_tag, format);
 		} else {
 			mout->dig_out_used = 0;
-			snd_hda_codec_setup_stream(codec, mout->dig_out_nid,
-						   0, 0, 0);
+			snd_hda_codec_cleanup_stream(codec, mout->dig_out_nid);
 		}
 	}
 	mutex_unlock(&codec->spdif_mutex);
@@ -2727,17 +2739,16 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
 	int i;
 
 	for (i = 0; i < mout->num_dacs; i++)
-		snd_hda_codec_setup_stream(codec, nids[i], 0, 0, 0);
+		snd_hda_codec_cleanup_stream(codec, nids[i]);
 	if (mout->hp_nid)
-		snd_hda_codec_setup_stream(codec, mout->hp_nid, 0, 0, 0);
+		snd_hda_codec_cleanup_stream(codec, mout->hp_nid);
 	for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
 		if (mout->extra_out_nid[i])
-			snd_hda_codec_setup_stream(codec,
-						   mout->extra_out_nid[i],
-						   0, 0, 0);
+			snd_hda_codec_cleanup_stream(codec,
+						     mout->extra_out_nid[i]);
 	mutex_lock(&codec->spdif_mutex);
 	if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) {
-		snd_hda_codec_setup_stream(codec, mout->dig_out_nid, 0, 0, 0);
+		snd_hda_codec_cleanup_stream(codec, mout->dig_out_nid);
 		mout->dig_out_used = 0;
 	}
 	mutex_unlock(&codec->spdif_mutex);
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 301b5227bfb..dcd390b2bba 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -722,6 +722,7 @@ int snd_hda_build_pcms(struct hda_bus *bus);
 void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
 				u32 stream_tag,
 				int channel_id, int format);
+void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid);
 unsigned int snd_hda_calc_stream_format(unsigned int rate,
 					unsigned int channels,
 					unsigned int format,
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index f9de7c467c2..59e4389c94a 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -1007,8 +1007,8 @@ static int generic_pcm2_cleanup(struct hda_pcm_stream *hinfo,
 {
 	struct hda_gspec *spec = codec->spec;
 
-	snd_hda_codec_setup_stream(codec, hinfo->nid, 0, 0, 0);
-	snd_hda_codec_setup_stream(codec, spec->dac_node[1]->nid, 0, 0, 0);
+	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
+	snd_hda_codec_cleanup_stream(codec, spec->dac_node[1]->nid);
 	return 0;
 }
 
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 87db3c410a1..220784bb76a 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -296,8 +296,7 @@ static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
 				      struct snd_pcm_substream *substream)
 {
 	struct ad198x_spec *spec = codec->spec;
-	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
-				   0, 0, 0);
+	snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
 	return 0;
 }
 
@@ -3325,8 +3324,7 @@ static int ad1984_pcm_dmic_cleanup(struct hda_pcm_stream *hinfo,
 				   struct hda_codec *codec,
 				   struct snd_pcm_substream *substream)
 {
-	snd_hda_codec_setup_stream(codec, 0x05 + substream->number,
-				   0, 0, 0);
+	snd_hda_codec_cleanup_stream(codec, 0x05 + substream->number);
 	return 0;
 }
 
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c
index 1892c81f1d1..8d142851aac 100644
--- a/sound/pci/hda/patch_cmedia.c
+++ b/sound/pci/hda/patch_cmedia.c
@@ -513,7 +513,7 @@ static int cmi9880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
 {
 	struct cmi_spec *spec = codec->spec;
 
-	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0);
+	snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
 	return 0;
 }
 
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index c67613ff842..36fd8526003 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -174,8 +174,7 @@ static int conexant_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
 				      struct snd_pcm_substream *substream)
 {
 	struct conexant_spec *spec = codec->spec;
-	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
-				   0, 0, 0);
+	snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
 	return 0;
 }
 
@@ -243,7 +242,7 @@ static int cx5051_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
 				      struct snd_pcm_substream *substream)
 {
 	struct conexant_spec *spec = codec->spec;
-	snd_hda_codec_setup_stream(codec, spec->cur_adc, 0, 0, 0);
+	snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
 	spec->cur_adc = 0;
 	return 0;
 }
@@ -1594,7 +1593,7 @@ static void cxt5051_portc_automic(struct hda_codec *codec)
 	new_adc = spec->adc_nids[spec->cur_adc_idx];
 	if (spec->cur_adc && spec->cur_adc != new_adc) {
 		/* stream is running, let's swap the current ADC */
-		snd_hda_codec_setup_stream(codec, spec->cur_adc, 0, 0, 0);
+		snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
 		spec->cur_adc = new_adc;
 		snd_hda_codec_setup_stream(codec, new_adc,
 					   spec->cur_adc_stream_tag, 0,
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index c21d7863e0d..eb40f4820c8 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -2409,8 +2409,8 @@ static int alc880_alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
 {
 	struct alc_spec *spec = codec->spec;
 
-	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
-				   0, 0, 0);
+	snd_hda_codec_cleanup_stream(codec,
+				     spec->adc_nids[substream->number + 1]);
 	return 0;
 }
 
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index a39fbd89a98..8eff8fe9dcf 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -1932,7 +1932,7 @@ static int stac92xx_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
 {
 	struct sigmatel_spec *spec = codec->spec;
 
-	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0);
+	snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
 	return 0;
 }
 
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index 09f1c25eb7e..52b1d81a26f 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -431,8 +431,7 @@ static int via_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
 				   struct snd_pcm_substream *substream)
 {
 	struct via_spec *spec = codec->spec;
-	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
-				   0, 0, 0);
+	snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
 	return 0;
 }
 
-- 
cgit v1.2.3-70-g09d2


From c0bbf48db35fec29c39c8a7826ca271069537e57 Mon Sep 17 00:00:00 2001
From: Robert Jarzmik <rjarzmik@free.fr>
Date: Tue, 18 Mar 2008 12:08:35 +0100
Subject: [ALSA] soc - Add missing audio path between Mono Mixer and Mic PGAs

Signed-off-by: Robert Jarzmik <rjarzmik@free.fr>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/soc/codecs/wm9713.c | 2 ++
 1 file changed, 2 insertions(+)

(limited to 'sound')

diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index c3d0afdc099..e3174c4d980 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -499,6 +499,8 @@ static const char *audio_map[][3] = {
 	{"Mono Mixer", "Aux Playback Switch",     "Aux DAC"},
 	{"Mono Mixer", "Bypass Playback Switch",  "Line Mixer"},
 	{"Mono Mixer", "PCM Playback Switch",     "AC97 Mixer"},
+	{"Mono Mixer", "Mic 1 Sidetone Switch", "Mic A PGA"},
+	{"Mono Mixer", "Mic 2 Sidetone Switch", "Mic B PGA"},
 	{"Mono Mixer", NULL,  "Capture Mono Mux"},
 
 	/* DAC inv mux 1 */
-- 
cgit v1.2.3-70-g09d2


From f081374b607f2656ca79a94d96d99cd5a2f60b68 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Tue, 18 Mar 2008 12:13:03 +0100
Subject: [ALSA] hda-codec - Support of Lenovo Thinkpad X300

Added the model thinkpad for Lenovo Thinkpad X300 with AD1984A codec.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 Documentation/sound/alsa/ALSA-Configuration.txt |  1 +
 sound/pci/hda/patch_analog.c                    | 94 +++++++++++++++++++++++++
 2 files changed, 95 insertions(+)

(limited to 'sound')

diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index b02404395e5..42dd8f5855d 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -923,6 +923,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
 	  desktop	3-stack desktop (default)
 	  laptop	laptop with HP jack sensing
 	  mobile	mobile devices with HP jack sensing
+	  thinkpad	Lenovo Thinkpad X300
 
 	AD1884
 	  N/A
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 220784bb76a..2befeebd909 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -3701,6 +3701,88 @@ static struct hda_verb ad1884a_laptop_verbs[] = {
 	{ } /* end */
 };
 
+/*
+ * Thinkpad X300
+ * 0x11 - HP
+ * 0x12 - speaker
+ * 0x14 - mic-in
+ * 0x17 - built-in mic
+ */
+
+static struct hda_verb ad1984a_thinkpad_verbs[] = {
+	/* HP unmute */
+	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* analog mix */
+	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+	/* turn on EAPD */
+	{0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
+	/* unsolicited event for pin-sense */
+	{0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
+	/* internal mic - dmic */
+	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{ } /* end */
+};
+
+static struct snd_kcontrol_new ad1984a_thinkpad_mixers[] = {
+	HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
+	HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
+	HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
+	HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Capture Source",
+		.info = ad198x_mux_enum_info,
+		.get = ad198x_mux_enum_get,
+		.put = ad198x_mux_enum_put,
+	},
+	{ } /* end */
+};
+
+static struct hda_input_mux ad1984a_thinkpad_capture_source = {
+	.num_items = 3,
+	.items = {
+		{ "Mic", 0x0 },
+		{ "Internal Mic", 0x5 },
+		{ "Mix", 0x3 },
+	},
+};
+
+/* mute internal speaker if HP is plugged */
+static void ad1984a_thinkpad_automute(struct hda_codec *codec)
+{
+	unsigned int present;
+
+	present = snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0)
+		& AC_PINSENSE_PRESENCE;
+	snd_hda_codec_amp_stereo(codec, 0x12, HDA_OUTPUT, 0,
+				 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+}
+
+/* unsolicited event for HP jack sensing */
+static void ad1984a_thinkpad_unsol_event(struct hda_codec *codec,
+					 unsigned int res)
+{
+	if ((res >> 26) != AD1884A_HP_EVENT)
+		return;
+	ad1984a_thinkpad_automute(codec);
+}
+
+/* initialize jack-sensing, too */
+static int ad1984a_thinkpad_init(struct hda_codec *codec)
+{
+	ad198x_init(codec);
+	ad1984a_thinkpad_automute(codec);
+	return 0;
+}
+
 /*
  */
 
@@ -3708,6 +3790,7 @@ enum {
 	AD1884A_DESKTOP,
 	AD1884A_LAPTOP,
 	AD1884A_MOBILE,
+	AD1884A_THINKPAD,
 	AD1884A_MODELS
 };
 
@@ -3715,10 +3798,12 @@ static const char *ad1884a_models[AD1884A_MODELS] = {
 	[AD1884A_DESKTOP]	= "desktop",
 	[AD1884A_LAPTOP]	= "laptop",
 	[AD1884A_MOBILE]	= "mobile",
+	[AD1884A_THINKPAD]	= "thinkpad",
 };
 
 static struct snd_pci_quirk ad1884a_cfg_tbl[] = {
 	SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE),
+	SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD),
 	{}
 };
 
@@ -3773,6 +3858,15 @@ static int patch_ad1884a(struct hda_codec *codec)
 		codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
 		codec->patch_ops.init = ad1884a_hp_init;
 		break;
+	case AD1884A_THINKPAD:
+		spec->mixers[0] = ad1984a_thinkpad_mixers;
+		spec->init_verbs[spec->num_init_verbs++] =
+			ad1984a_thinkpad_verbs;
+		spec->multiout.dig_out_nid = 0;
+		spec->input_mux = &ad1984a_thinkpad_capture_source;
+		codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event;
+		codec->patch_ops.init = ad1984a_thinkpad_init;
+		break;
 	}
 
 	return 0;
-- 
cgit v1.2.3-70-g09d2


From 850f0e5212a73a548b9c29faf452b4a14d80f43b Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Tue, 18 Mar 2008 17:11:05 +0100
Subject: [ALSA] hda-intel - Add sync support

Addded the support of sync streams to hda-intel driver.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/hda_intel.c | 96 ++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 79 insertions(+), 17 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 557f269f83a..bc3867e1945 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -221,6 +221,9 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
 /* SD_CTL bits */
 #define SD_CTL_STREAM_RESET	0x01	/* stream reset bit */
 #define SD_CTL_DMA_START	0x02	/* stream DMA start bit */
+#define SD_CTL_STRIPE		(3 << 16)	/* stripe control */
+#define SD_CTL_TRAFFIC_PRIO	(1 << 18)	/* traffic priority */
+#define SD_CTL_DIR		(1 << 19)	/* bi-directional stream */
 #define SD_CTL_STREAM_TAG_MASK	(0xf << 20)
 #define SD_CTL_STREAM_TAG_SHIFT	20
 
@@ -1180,7 +1183,8 @@ static struct snd_pcm_hardware azx_pcm_hw = {
 				 SNDRV_PCM_INFO_MMAP_VALID |
 				 /* No full-resume yet implemented */
 				 /* SNDRV_PCM_INFO_RESUME |*/
-				 SNDRV_PCM_INFO_PAUSE),
+				 SNDRV_PCM_INFO_PAUSE |
+				 SNDRV_PCM_INFO_SYNC_START),
 	.formats =		SNDRV_PCM_FMTBIT_S16_LE,
 	.rates =		SNDRV_PCM_RATE_48000,
 	.rate_min =		48000,
@@ -1242,6 +1246,7 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
 	spin_unlock_irqrestore(&chip->reg_lock, flags);
 
 	runtime->private_data = azx_dev;
+	snd_pcm_set_sync(substream);
 	mutex_unlock(&chip->open_mutex);
 	return 0;
 }
@@ -1326,37 +1331,94 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
 static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 {
 	struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
-	struct azx_dev *azx_dev = get_azx_dev(substream);
 	struct azx *chip = apcm->chip;
-	int err = 0;
+	struct azx_dev *azx_dev;
+	struct snd_pcm_substream *s;
+	int start, nsync = 0, sbits = 0;
+	int nwait, timeout;
 
-	spin_lock(&chip->reg_lock);
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 	case SNDRV_PCM_TRIGGER_RESUME:
 	case SNDRV_PCM_TRIGGER_START:
-		azx_stream_start(chip, azx_dev);
-		azx_dev->running = 1;
+		start = 1;
 		break;
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 	case SNDRV_PCM_TRIGGER_SUSPEND:
 	case SNDRV_PCM_TRIGGER_STOP:
-		azx_stream_stop(chip, azx_dev);
-		azx_dev->running = 0;
+		start = 0;
 		break;
 	default:
-		err = -EINVAL;
+		return -EINVAL;
+	}
+
+	snd_pcm_group_for_each_entry(s, substream) {
+		if (s->pcm->card != substream->pcm->card)
+			continue;
+		azx_dev = get_azx_dev(s);
+		sbits |= 1 << azx_dev->index;
+		nsync++;
+		snd_pcm_trigger_done(s, substream);
+	}
+
+	spin_lock(&chip->reg_lock);
+	if (nsync > 1) {
+		/* first, set SYNC bits of corresponding streams */
+		azx_writel(chip, SYNC, azx_readl(chip, SYNC) | sbits);
+	}
+	snd_pcm_group_for_each_entry(s, substream) {
+		if (s->pcm->card != substream->pcm->card)
+			continue;
+		azx_dev = get_azx_dev(s);
+		if (start)
+			azx_stream_start(chip, azx_dev);
+		else
+			azx_stream_stop(chip, azx_dev);
+		azx_dev->running = start;
 	}
 	spin_unlock(&chip->reg_lock);
-	if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH ||
-	    cmd == SNDRV_PCM_TRIGGER_SUSPEND ||
-	    cmd == SNDRV_PCM_TRIGGER_STOP) {
-		int timeout = 5000;
-		while ((azx_sd_readb(azx_dev, SD_CTL) & SD_CTL_DMA_START) &&
-		       --timeout)
-			;
+	if (start) {
+		if (nsync == 1)
+			return 0;
+		/* wait until all FIFOs get ready */
+		for (timeout = 5000; timeout; timeout--) {
+			nwait = 0;
+			snd_pcm_group_for_each_entry(s, substream) {
+				if (s->pcm->card != substream->pcm->card)
+					continue;
+				azx_dev = get_azx_dev(s);
+				if (!(azx_sd_readb(azx_dev, SD_STS) &
+				      SD_STS_FIFO_READY))
+					nwait++;
+			}
+			if (!nwait)
+				break;
+			cpu_relax();
+		}
+	} else {
+		/* wait until all RUN bits are cleared */
+		for (timeout = 5000; timeout; timeout--) {
+			nwait = 0;
+			snd_pcm_group_for_each_entry(s, substream) {
+				if (s->pcm->card != substream->pcm->card)
+					continue;
+				azx_dev = get_azx_dev(s);
+				if (azx_sd_readb(azx_dev, SD_CTL) &
+				    SD_CTL_DMA_START)
+					nwait++;
+			}
+			if (!nwait)
+				break;
+			cpu_relax();
+		}
 	}
-	return err;
+	if (nsync > 1) {
+		spin_lock(&chip->reg_lock);
+		/* reset SYNC bits */
+		azx_writel(chip, SYNC, azx_readl(chip, SYNC) & ~sbits);
+		spin_unlock(&chip->reg_lock);
+	}
+	return 0;
 }
 
 static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream)
-- 
cgit v1.2.3-70-g09d2


From acf5850ea73bf82081fb65cf10dd36a9d7a890e9 Mon Sep 17 00:00:00 2001
From: Timur Tabi <timur@freescale.com>
Date: Tue, 18 Mar 2008 17:18:18 +0100
Subject: [ALSA] Removed deprecated sound/driver.h from Freescale MPC8610
 drivers

With commit 9004acc70e8c49c50c4c7b652f906f1e0ed5709d, include/sound/driver.h
is deprecated.  This patch removes the #include from fsl_ssi.c and fsl_dma.c.

Signed-off-by: Timur Tabi <timur@freescale.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/soc/fsl/fsl_dma.c | 1 -
 sound/soc/fsl/fsl_ssi.c | 1 -
 2 files changed, 2 deletions(-)

(limited to 'sound')

diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c
index 652514fc814..78de7168d2b 100644
--- a/sound/soc/fsl/fsl_dma.c
+++ b/sound/soc/fsl/fsl_dma.c
@@ -20,7 +20,6 @@
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 
-#include <sound/driver.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 145ad13d52d..b2a11b0d2e4 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -15,7 +15,6 @@
 #include <linux/device.h>
 #include <linux/delay.h>
 
-#include <sound/driver.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
-- 
cgit v1.2.3-70-g09d2


From f5b2368ba8c203eb5bb7e5bbd99f4d9064a6aac0 Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Wed, 19 Mar 2008 08:14:01 +0100
Subject: [ALSA] oxygen: move WM8785 symbols to a header file

Move the WM8786 register symbol definitions to their own header file.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/oxygen/oxygen.c | 42 +-----------------------------------------
 sound/pci/oxygen/wm8785.h | 45 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 46 insertions(+), 41 deletions(-)
 create mode 100644 sound/pci/oxygen/wm8785.h

(limited to 'sound')

diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c
index 9a9941bb046..542752442a9 100644
--- a/sound/pci/oxygen/oxygen.c
+++ b/sound/pci/oxygen/oxygen.c
@@ -40,6 +40,7 @@
 #include "oxygen.h"
 #include "ak4396.h"
 #include "cm9780.h"
+#include "wm8785.h"
 
 MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
 MODULE_DESCRIPTION("C-Media CMI8788 driver");
@@ -80,47 +81,6 @@ MODULE_DEVICE_TABLE(pci, oxygen_ids);
 
 #define GPIO_LINE_MUTE		CM9780_GPO0
 
-#define WM8785_R0	0
-#define WM8785_R1	1
-#define WM8785_R2	2
-#define WM8785_R7	7
-
-/* R0 */
-#define WM8785_MCR_MASK		0x007
-#define WM8785_MCR_SLAVE	0x000
-#define WM8785_MCR_MASTER_128	0x001
-#define WM8785_MCR_MASTER_192	0x002
-#define WM8785_MCR_MASTER_256	0x003
-#define WM8785_MCR_MASTER_384	0x004
-#define WM8785_MCR_MASTER_512	0x005
-#define WM8785_MCR_MASTER_768	0x006
-#define WM8785_OSR_MASK		0x018
-#define WM8785_OSR_SINGLE	0x000
-#define WM8785_OSR_DOUBLE	0x008
-#define WM8785_OSR_QUAD		0x010
-#define WM8785_FORMAT_MASK	0x060
-#define WM8785_FORMAT_RJUST	0x000
-#define WM8785_FORMAT_LJUST	0x020
-#define WM8785_FORMAT_I2S	0x040
-#define WM8785_FORMAT_DSP	0x060
-/* R1 */
-#define WM8785_WL_MASK		0x003
-#define WM8785_WL_16		0x000
-#define WM8785_WL_20		0x001
-#define WM8785_WL_24		0x002
-#define WM8785_WL_32		0x003
-#define WM8785_LRP		0x004
-#define WM8785_BCLKINV		0x008
-#define WM8785_LRSWAP		0x010
-#define WM8785_DEVNO_MASK	0x0e0
-/* R2 */
-#define WM8785_HPFR		0x001
-#define WM8785_HPFL		0x002
-#define WM8785_SDODIS		0x004
-#define WM8785_PWRDNR		0x008
-#define WM8785_PWRDNL		0x010
-#define WM8785_TDM_MASK		0x1c0
-
 struct generic_data {
 	u8 ak4396_ctl2;
 };
diff --git a/sound/pci/oxygen/wm8785.h b/sound/pci/oxygen/wm8785.h
new file mode 100644
index 00000000000..8c23e315ae6
--- /dev/null
+++ b/sound/pci/oxygen/wm8785.h
@@ -0,0 +1,45 @@
+#ifndef WM8785_H_INCLUDED
+#define WM8785_H_INCLUDED
+
+#define WM8785_R0	0
+#define WM8785_R1	1
+#define WM8785_R2	2
+#define WM8785_R7	7
+
+/* R0 */
+#define WM8785_MCR_MASK		0x007
+#define WM8785_MCR_SLAVE	0x000
+#define WM8785_MCR_MASTER_128	0x001
+#define WM8785_MCR_MASTER_192	0x002
+#define WM8785_MCR_MASTER_256	0x003
+#define WM8785_MCR_MASTER_384	0x004
+#define WM8785_MCR_MASTER_512	0x005
+#define WM8785_MCR_MASTER_768	0x006
+#define WM8785_OSR_MASK		0x018
+#define WM8785_OSR_SINGLE	0x000
+#define WM8785_OSR_DOUBLE	0x008
+#define WM8785_OSR_QUAD		0x010
+#define WM8785_FORMAT_MASK	0x060
+#define WM8785_FORMAT_RJUST	0x000
+#define WM8785_FORMAT_LJUST	0x020
+#define WM8785_FORMAT_I2S	0x040
+#define WM8785_FORMAT_DSP	0x060
+/* R1 */
+#define WM8785_WL_MASK		0x003
+#define WM8785_WL_16		0x000
+#define WM8785_WL_20		0x001
+#define WM8785_WL_24		0x002
+#define WM8785_WL_32		0x003
+#define WM8785_LRP		0x004
+#define WM8785_BCLKINV		0x008
+#define WM8785_LRSWAP		0x010
+#define WM8785_DEVNO_MASK	0x0e0
+/* R2 */
+#define WM8785_HPFR		0x001
+#define WM8785_HPFL		0x002
+#define WM8785_SDODIS		0x004
+#define WM8785_PWRDNR		0x008
+#define WM8785_PWRDNL		0x010
+#define WM8785_TDM_MASK		0x1c0
+
+#endif
-- 
cgit v1.2.3-70-g09d2


From 33fa724e291d3cc6c319f7db487e6e084ef5d4b5 Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Wed, 19 Mar 2008 08:16:40 +0100
Subject: [ALSA] virtuoso: move PCM1796 symbols to a header file

Move the PCM1796 register symbol definitions to their own header file.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/oxygen/pcm1796.h  | 58 +++++++++++++++++++++++++++++++++++++++++++++
 sound/pci/oxygen/virtuoso.c | 55 +-----------------------------------------
 2 files changed, 59 insertions(+), 54 deletions(-)
 create mode 100644 sound/pci/oxygen/pcm1796.h

(limited to 'sound')

diff --git a/sound/pci/oxygen/pcm1796.h b/sound/pci/oxygen/pcm1796.h
new file mode 100644
index 00000000000..698bf46c710
--- /dev/null
+++ b/sound/pci/oxygen/pcm1796.h
@@ -0,0 +1,58 @@
+#ifndef PCM1796_H_INCLUDED
+#define PCM1796_H_INCLUDED
+
+/* register 16 */
+#define PCM1796_ATL_MASK	0xff
+/* register 17 */
+#define PCM1796_ATR_MASK	0xff
+/* register 18 */
+#define PCM1796_MUTE		0x01
+#define PCM1796_DME		0x02
+#define PCM1796_DMF_MASK	0x0c
+#define PCM1796_DMF_DISABLED	0x00
+#define PCM1796_DMF_48		0x04
+#define PCM1796_DMF_441		0x08
+#define PCM1796_DMF_32		0x0c
+#define PCM1796_FMT_MASK	0x70
+#define PCM1796_FMT_16_RJUST	0x00
+#define PCM1796_FMT_20_RJUST	0x10
+#define PCM1796_FMT_24_RJUST	0x20
+#define PCM1796_FMT_24_LJUST	0x30
+#define PCM1796_FMT_16_I2S	0x40
+#define PCM1796_FMT_24_I2S	0x50
+#define PCM1796_ATLD		0x80
+/* register 19 */
+#define PCM1796_INZD		0x01
+#define PCM1796_FLT_MASK	0x02
+#define PCM1796_FLT_SHARP	0x00
+#define PCM1796_FLT_SLOW	0x02
+#define PCM1796_DFMS		0x04
+#define PCM1796_OPE		0x10
+#define PCM1796_ATS_MASK	0x60
+#define PCM1796_ATS_1		0x00
+#define PCM1796_ATS_2		0x20
+#define PCM1796_ATS_4		0x40
+#define PCM1796_ATS_8		0x60
+#define PCM1796_REV		0x80
+/* register 20 */
+#define PCM1796_OS_MASK		0x03
+#define PCM1796_OS_64		0x00
+#define PCM1796_OS_32		0x01
+#define PCM1796_OS_128		0x02
+#define PCM1796_CHSL_MASK	0x04
+#define PCM1796_CHSL_LEFT	0x00
+#define PCM1796_CHSL_RIGHT	0x04
+#define PCM1796_MONO		0x08
+#define PCM1796_DFTH		0x10
+#define PCM1796_DSD		0x20
+#define PCM1796_SRST		0x40
+/* register 21 */
+#define PCM1796_PCMZ		0x01
+#define PCM1796_DZ_MASK		0x06
+/* register 22 */
+#define PCM1796_ZFGL		0x01
+#define PCM1796_ZFGR		0x02
+/* register 23 */
+#define PCM1796_ID_MASK		0x1f
+
+#endif
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
index e4e23789080..127dd664fc1 100644
--- a/sound/pci/oxygen/virtuoso.c
+++ b/sound/pci/oxygen/virtuoso.c
@@ -47,6 +47,7 @@
 #include <sound/tlv.h>
 #include "oxygen.h"
 #include "cm9780.h"
+#include "pcm1796.h"
 
 MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
 MODULE_DESCRIPTION("Asus AV200 driver");
@@ -82,60 +83,6 @@ MODULE_DEVICE_TABLE(pci, xonar_ids);
 
 #define GPIO_LINE_MUTE		CM9780_GPO0
 
-/* register 16 */
-#define PCM1796_ATL_MASK	0xff
-/* register 17 */
-#define PCM1796_ATR_MASK	0xff
-/* register 18 */
-#define PCM1796_MUTE		0x01
-#define PCM1796_DME		0x02
-#define PCM1796_DMF_MASK	0x0c
-#define PCM1796_DMF_DISABLED	0x00
-#define PCM1796_DMF_48		0x04
-#define PCM1796_DMF_441		0x08
-#define PCM1796_DMF_32		0x0c
-#define PCM1796_FMT_MASK	0x70
-#define PCM1796_FMT_16_RJUST	0x00
-#define PCM1796_FMT_20_RJUST	0x10
-#define PCM1796_FMT_24_RJUST	0x20
-#define PCM1796_FMT_24_LJUST	0x30
-#define PCM1796_FMT_16_I2S	0x40
-#define PCM1796_FMT_24_I2S	0x50
-#define PCM1796_ATLD		0x80
-/* register 19 */
-#define PCM1796_INZD		0x01
-#define PCM1796_FLT_MASK	0x02
-#define PCM1796_FLT_SHARP	0x00
-#define PCM1796_FLT_SLOW	0x02
-#define PCM1796_DFMS		0x04
-#define PCM1796_OPE		0x10
-#define PCM1796_ATS_MASK	0x60
-#define PCM1796_ATS_1		0x00
-#define PCM1796_ATS_2		0x20
-#define PCM1796_ATS_4		0x40
-#define PCM1796_ATS_8		0x60
-#define PCM1796_REV		0x80
-/* register 20 */
-#define PCM1796_OS_MASK		0x03
-#define PCM1796_OS_64		0x00
-#define PCM1796_OS_32		0x01
-#define PCM1796_OS_128		0x02
-#define PCM1796_CHSL_MASK	0x04
-#define PCM1796_CHSL_LEFT	0x00
-#define PCM1796_CHSL_RIGHT	0x04
-#define PCM1796_MONO		0x08
-#define PCM1796_DFTH		0x10
-#define PCM1796_DSD		0x20
-#define PCM1796_SRST		0x40
-/* register 21 */
-#define PCM1796_PCMZ		0x01
-#define PCM1796_DZ_MASK		0x06
-/* register 22 */
-#define PCM1796_ZFGL		0x01
-#define PCM1796_ZFGR		0x02
-/* register 23 */
-#define PCM1796_ID_MASK		0x1f
-
 struct xonar_data {
 	u8 is_d2x;
 	u8 has_power;
-- 
cgit v1.2.3-70-g09d2


From fa5d8106cb52e5df28673f59cc25af520dc83382 Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Wed, 19 Mar 2008 08:17:33 +0100
Subject: [ALSA] oxygen: add monitor controls

Add controls to enable monitoring of the analog and digital inputs.

To allow monitoring after loading the driver when nothing has been
played back or recorded yet, the I2S input and outputs are initialized
to a valid configuration.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/oxygen/oxygen_lib.c   |  16 ++---
 sound/pci/oxygen/oxygen_mixer.c | 156 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 164 insertions(+), 8 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c
index 78c21155218..a1abb50eedb 100644
--- a/sound/pci/oxygen/oxygen_lib.c
+++ b/sound/pci/oxygen/oxygen_lib.c
@@ -267,20 +267,20 @@ static void oxygen_init(struct oxygen *chip)
 		      (OXYGEN_FORMAT_16 << OXYGEN_MULTICH_FORMAT_SHIFT));
 	oxygen_write8(chip, OXYGEN_REC_CHANNELS, OXYGEN_REC_CHANNELS_2_2_2);
 	oxygen_write16(chip, OXYGEN_I2S_MULTICH_FORMAT,
-		       OXYGEN_RATE_48000 | OXYGEN_I2S_FORMAT_LJUST |
-		       OXYGEN_I2S_MCLK_128 | OXYGEN_I2S_BITS_16 |
+		       OXYGEN_RATE_48000 | chip->model->dac_i2s_format |
+		       OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 |
 		       OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);
 	oxygen_write16(chip, OXYGEN_I2S_A_FORMAT,
-		       OXYGEN_RATE_48000 | OXYGEN_I2S_FORMAT_LJUST |
-		       OXYGEN_I2S_MCLK_128 | OXYGEN_I2S_BITS_16 |
+		       OXYGEN_RATE_48000 | chip->model->adc_i2s_format |
+		       OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 |
 		       OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);
 	oxygen_write16(chip, OXYGEN_I2S_B_FORMAT,
-		       OXYGEN_RATE_48000 | OXYGEN_I2S_FORMAT_LJUST |
-		       OXYGEN_I2S_MCLK_128 | OXYGEN_I2S_BITS_16 |
+		       OXYGEN_RATE_48000 | chip->model->adc_i2s_format |
+		       OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 |
 		       OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);
 	oxygen_write16(chip, OXYGEN_I2S_C_FORMAT,
-		       OXYGEN_RATE_48000 | OXYGEN_I2S_FORMAT_LJUST |
-		       OXYGEN_I2S_MCLK_128 | OXYGEN_I2S_BITS_16 |
+		       OXYGEN_RATE_48000 | chip->model->adc_i2s_format |
+		       OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 |
 		       OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);
 	oxygen_write32_masked(chip, OXYGEN_SPDIF_CONTROL,
 			      OXYGEN_SPDIF_SENSE_MASK |
diff --git a/sound/pci/oxygen/oxygen_mixer.c b/sound/pci/oxygen/oxygen_mixer.c
index a8e4623415d..4e77b79b3b6 100644
--- a/sound/pci/oxygen/oxygen_mixer.c
+++ b/sound/pci/oxygen/oxygen_mixer.c
@@ -446,6 +446,50 @@ static int spdif_loopback_put(struct snd_kcontrol *ctl,
 	return changed;
 }
 
+static int monitor_volume_info(struct snd_kcontrol *ctl,
+			       struct snd_ctl_elem_info *info)
+{
+	info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	info->count = 1;
+	info->value.integer.min = 0;
+	info->value.integer.max = 1;
+	return 0;
+}
+
+static int monitor_get(struct snd_kcontrol *ctl,
+		       struct snd_ctl_elem_value *value)
+{
+	struct oxygen *chip = ctl->private_data;
+	u8 bit = ctl->private_value;
+	int invert = ctl->private_value & (1 << 8);
+
+	value->value.integer.value[0] =
+		!!invert ^ !!(oxygen_read8(chip, OXYGEN_ADC_MONITOR) & bit);
+	return 0;
+}
+
+static int monitor_put(struct snd_kcontrol *ctl,
+		       struct snd_ctl_elem_value *value)
+{
+	struct oxygen *chip = ctl->private_data;
+	u8 bit = ctl->private_value;
+	int invert = ctl->private_value & (1 << 8);
+	u8 oldreg, newreg;
+	int changed;
+
+	spin_lock_irq(&chip->reg_lock);
+	oldreg = oxygen_read8(chip, OXYGEN_ADC_MONITOR);
+	if ((!!value->value.integer.value[0] ^ !!invert) != 0)
+		newreg = oldreg | bit;
+	else
+		newreg = oldreg & ~bit;
+	changed = newreg != oldreg;
+	if (changed)
+		oxygen_write8(chip, OXYGEN_ADC_MONITOR, newreg);
+	spin_unlock_irq(&chip->reg_lock);
+	return changed;
+}
+
 static int ac97_switch_get(struct snd_kcontrol *ctl,
 			   struct snd_ctl_elem_value *value)
 {
@@ -608,6 +652,7 @@ static int ac97_fp_rec_volume_put(struct snd_kcontrol *ctl,
 		.private_value = ((codec) << 24) | (index), \
 	}
 
+static DECLARE_TLV_DB_SCALE(monitor_db_scale, -1000, 1000, 0);
 static DECLARE_TLV_DB_SCALE(ac97_db_scale, -3450, 150, 0);
 static DECLARE_TLV_DB_SCALE(ac97_rec_db_scale, 0, 150, 0);
 
@@ -692,6 +737,93 @@ static const struct snd_kcontrol_new controls[] = {
 	},
 };
 
+static const struct snd_kcontrol_new monitor_a_controls[] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Analog Input Monitor Switch",
+		.info = snd_ctl_boolean_mono_info,
+		.get = monitor_get,
+		.put = monitor_put,
+		.private_value = OXYGEN_ADC_MONITOR_A,
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Analog Input Monitor Volume",
+		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+			  SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+		.info = monitor_volume_info,
+		.get = monitor_get,
+		.put = monitor_put,
+		.private_value = OXYGEN_ADC_MONITOR_A_HALF_VOL | (1 << 8),
+		.tlv = { .p = monitor_db_scale, },
+	},
+};
+static const struct snd_kcontrol_new monitor_b_controls[] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Analog Input Monitor Switch",
+		.info = snd_ctl_boolean_mono_info,
+		.get = monitor_get,
+		.put = monitor_put,
+		.private_value = OXYGEN_ADC_MONITOR_B,
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Analog Input Monitor Volume",
+		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+			  SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+		.info = monitor_volume_info,
+		.get = monitor_get,
+		.put = monitor_put,
+		.private_value = OXYGEN_ADC_MONITOR_B_HALF_VOL | (1 << 8),
+		.tlv = { .p = monitor_db_scale, },
+	},
+};
+static const struct snd_kcontrol_new monitor_2nd_b_controls[] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Analog Input Monitor Switch",
+		.index = 1,
+		.info = snd_ctl_boolean_mono_info,
+		.get = monitor_get,
+		.put = monitor_put,
+		.private_value = OXYGEN_ADC_MONITOR_B,
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Analog Input Monitor Volume",
+		.index = 1,
+		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+			  SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+		.info = monitor_volume_info,
+		.get = monitor_get,
+		.put = monitor_put,
+		.private_value = OXYGEN_ADC_MONITOR_B_HALF_VOL | (1 << 8),
+		.tlv = { .p = monitor_db_scale, },
+	},
+};
+static const struct snd_kcontrol_new monitor_c_controls[] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Digital Input Monitor Switch",
+		.info = snd_ctl_boolean_mono_info,
+		.get = monitor_get,
+		.put = monitor_put,
+		.private_value = OXYGEN_ADC_MONITOR_C,
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Digital Input Monitor Volume",
+		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+			  SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+		.info = monitor_volume_info,
+		.get = monitor_get,
+		.put = monitor_put,
+		.private_value = OXYGEN_ADC_MONITOR_C_HALF_VOL | (1 << 8),
+		.tlv = { .p = monitor_db_scale, },
+	},
+};
+
 static const struct snd_kcontrol_new ac97_controls[] = {
 	AC97_VOLUME("Mic Capture Volume", 0, AC97_MIC),
 	AC97_SWITCH("Mic Capture Switch", 0, AC97_MIC, 15, 1),
@@ -778,6 +910,30 @@ int oxygen_mixer_init(struct oxygen *chip)
 	err = add_controls(chip, controls, ARRAY_SIZE(controls));
 	if (err < 0)
 		return err;
+	if (chip->model->used_channels & OXYGEN_CHANNEL_A) {
+		err = add_controls(chip, monitor_a_controls,
+				   ARRAY_SIZE(monitor_a_controls));
+		if (err < 0)
+			return err;
+	} else if (chip->model->used_channels & OXYGEN_CHANNEL_B) {
+		err = add_controls(chip, monitor_b_controls,
+				   ARRAY_SIZE(monitor_b_controls));
+		if (err < 0)
+			return err;
+	}
+	if ((chip->model->used_channels & (OXYGEN_CHANNEL_A | OXYGEN_CHANNEL_B))
+	    == (OXYGEN_CHANNEL_A | OXYGEN_CHANNEL_B)) {
+		err = add_controls(chip, monitor_2nd_b_controls,
+				   ARRAY_SIZE(monitor_2nd_b_controls));
+		if (err < 0)
+			return err;
+	}
+	if (chip->model->used_channels & OXYGEN_CHANNEL_C) {
+		err = add_controls(chip, monitor_c_controls,
+				   ARRAY_SIZE(monitor_c_controls));
+		if (err < 0)
+			return err;
+	}
 	if (chip->has_ac97_0) {
 		err = add_controls(chip, ac97_controls,
 				   ARRAY_SIZE(ac97_controls));
-- 
cgit v1.2.3-70-g09d2


From f009ad9b39e6484d8e36e9e5029c07eab8c12e8f Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Wed, 19 Mar 2008 08:19:41 +0100
Subject: [ALSA] oxygen: change model-specific PCM device configuration

When specifying which PCM devices to use, model drivers now use flags
that also specify the routing between PCM devices and DMA channels
instead of just DMA channel bits.  This simplifies some code that checks
for these flags.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/oxygen/hifier.c       |   6 +-
 sound/pci/oxygen/oxygen.c       |  22 +++--
 sound/pci/oxygen/oxygen.h       |  12 ++-
 sound/pci/oxygen/oxygen_mixer.c | 202 +++++++++++++++++++++-------------------
 sound/pci/oxygen/oxygen_pcm.c   |  78 +++++++++-------
 sound/pci/oxygen/virtuoso.c     |   8 +-
 6 files changed, 176 insertions(+), 152 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/oxygen/hifier.c b/sound/pci/oxygen/hifier.c
index 666f69a3312..fa489ed3ed4 100644
--- a/sound/pci/oxygen/hifier.c
+++ b/sound/pci/oxygen/hifier.c
@@ -160,10 +160,10 @@ static const struct oxygen_model model_hifier = {
 	.update_dac_volume = update_ak4396_volume,
 	.update_dac_mute = update_ak4396_mute,
 	.model_data_size = sizeof(struct hifier_data),
+	.pcm_dev_cfg = PLAYBACK_0_TO_I2S |
+		       PLAYBACK_1_TO_SPDIF |
+		       CAPTURE_0_FROM_I2S_1,
 	.dac_channels = 2,
-	.used_channels = OXYGEN_CHANNEL_A |
-			 OXYGEN_CHANNEL_SPDIF |
-			 OXYGEN_CHANNEL_MULTICH,
 	.function_flags = 0,
 	.dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
 	.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c
index 542752442a9..9faf43c949b 100644
--- a/sound/pci/oxygen/oxygen.c
+++ b/sound/pci/oxygen/oxygen.c
@@ -303,12 +303,13 @@ static const struct oxygen_model model_generic = {
 	.update_dac_mute = update_ak4396_mute,
 	.ac97_switch_hook = cmi9780_switch_hook,
 	.model_data_size = sizeof(struct generic_data),
+	.pcm_dev_cfg = PLAYBACK_0_TO_I2S |
+		       PLAYBACK_1_TO_SPDIF |
+		       PLAYBACK_2_TO_AC97_1 |
+		       CAPTURE_0_FROM_I2S_1 |
+		       CAPTURE_1_FROM_SPDIF |
+		       CAPTURE_2_FROM_AC97_1,
 	.dac_channels = 8,
-	.used_channels = OXYGEN_CHANNEL_A |
-			 OXYGEN_CHANNEL_C |
-			 OXYGEN_CHANNEL_SPDIF |
-			 OXYGEN_CHANNEL_MULTICH |
-			 OXYGEN_CHANNEL_AC97,
 	.function_flags = OXYGEN_FUNCTION_ENABLE_SPI_4_5,
 	.dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
 	.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
@@ -327,12 +328,13 @@ static const struct oxygen_model model_meridian = {
 	.update_dac_mute = update_ak4396_mute,
 	.ac97_switch_hook = cmi9780_switch_hook,
 	.model_data_size = sizeof(struct generic_data),
+	.pcm_dev_cfg = PLAYBACK_0_TO_I2S |
+		       PLAYBACK_1_TO_SPDIF |
+		       PLAYBACK_2_TO_AC97_1 |
+		       CAPTURE_0_FROM_I2S_2 |
+		       CAPTURE_1_FROM_SPDIF |
+		       CAPTURE_2_FROM_AC97_1,
 	.dac_channels = 8,
-	.used_channels = OXYGEN_CHANNEL_B |
-			 OXYGEN_CHANNEL_C |
-			 OXYGEN_CHANNEL_SPDIF |
-			 OXYGEN_CHANNEL_MULTICH |
-			 OXYGEN_CHANNEL_AC97,
 	.function_flags = OXYGEN_FUNCTION_ENABLE_SPI_4_5,
 	.dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
 	.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
diff --git a/sound/pci/oxygen/oxygen.h b/sound/pci/oxygen/oxygen.h
index ad50fb8b206..fde995cf2ed 100644
--- a/sound/pci/oxygen/oxygen.h
+++ b/sound/pci/oxygen/oxygen.h
@@ -16,6 +16,16 @@
 #define PCM_AC97	5
 #define PCM_COUNT	6
 
+/* model-specific configuration of outputs/inputs */
+#define PLAYBACK_0_TO_I2S	0x001
+#define PLAYBACK_1_TO_SPDIF	0x004
+#define PLAYBACK_2_TO_AC97_1	0x008
+#define CAPTURE_0_FROM_I2S_1	0x010
+#define CAPTURE_0_FROM_I2S_2	0x020
+#define CAPTURE_1_FROM_SPDIF	0x080
+#define CAPTURE_2_FROM_I2S_2	0x100
+#define CAPTURE_2_FROM_AC97_1	0x200
+
 enum {
 	CONTROL_SPDIF_PCM,
 	CONTROL_SPDIF_INPUT_BITS,
@@ -91,8 +101,8 @@ struct oxygen_model {
 				 unsigned int reg, int mute);
 	void (*gpio_changed)(struct oxygen *chip);
 	size_t model_data_size;
+	unsigned int pcm_dev_cfg;
 	u8 dac_channels;
-	u8 used_channels;
 	u8 function_flags;
 	u16 dac_i2s_format;
 	u16 adc_i2s_format;
diff --git a/sound/pci/oxygen/oxygen_mixer.c b/sound/pci/oxygen/oxygen_mixer.c
index 4e77b79b3b6..6b5ff6e0fad 100644
--- a/sound/pci/oxygen/oxygen_mixer.c
+++ b/sound/pci/oxygen/oxygen_mixer.c
@@ -737,90 +737,111 @@ static const struct snd_kcontrol_new controls[] = {
 	},
 };
 
-static const struct snd_kcontrol_new monitor_a_controls[] = {
+static const struct {
+	unsigned int pcm_dev;
+	struct snd_kcontrol_new controls[2];
+} monitor_controls[] = {
 	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Analog Input Monitor Switch",
-		.info = snd_ctl_boolean_mono_info,
-		.get = monitor_get,
-		.put = monitor_put,
-		.private_value = OXYGEN_ADC_MONITOR_A,
+		.pcm_dev = CAPTURE_0_FROM_I2S_1,
+		.controls = {
+			{
+				.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+				.name = "Analog Input Monitor Switch",
+				.info = snd_ctl_boolean_mono_info,
+				.get = monitor_get,
+				.put = monitor_put,
+				.private_value = OXYGEN_ADC_MONITOR_A,
+			},
+			{
+				.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+				.name = "Analog Input Monitor Volume",
+				.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+					  SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+				.info = monitor_volume_info,
+				.get = monitor_get,
+				.put = monitor_put,
+				.private_value = OXYGEN_ADC_MONITOR_A_HALF_VOL
+						| (1 << 8),
+				.tlv = { .p = monitor_db_scale, },
+			},
+		},
 	},
 	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Analog Input Monitor Volume",
-		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
-			  SNDRV_CTL_ELEM_ACCESS_TLV_READ,
-		.info = monitor_volume_info,
-		.get = monitor_get,
-		.put = monitor_put,
-		.private_value = OXYGEN_ADC_MONITOR_A_HALF_VOL | (1 << 8),
-		.tlv = { .p = monitor_db_scale, },
+		.pcm_dev = CAPTURE_0_FROM_I2S_2,
+		.controls = {
+			{
+				.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+				.name = "Analog Input Monitor Switch",
+				.info = snd_ctl_boolean_mono_info,
+				.get = monitor_get,
+				.put = monitor_put,
+				.private_value = OXYGEN_ADC_MONITOR_B,
+			},
+			{
+				.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+				.name = "Analog Input Monitor Volume",
+				.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+					  SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+				.info = monitor_volume_info,
+				.get = monitor_get,
+				.put = monitor_put,
+				.private_value = OXYGEN_ADC_MONITOR_B_HALF_VOL
+						| (1 << 8),
+				.tlv = { .p = monitor_db_scale, },
+			},
+		},
 	},
-};
-static const struct snd_kcontrol_new monitor_b_controls[] = {
 	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Analog Input Monitor Switch",
-		.info = snd_ctl_boolean_mono_info,
-		.get = monitor_get,
-		.put = monitor_put,
-		.private_value = OXYGEN_ADC_MONITOR_B,
+		.pcm_dev = CAPTURE_2_FROM_I2S_2,
+		.controls = {
+			{
+				.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+				.name = "Analog Input Monitor Switch",
+				.index = 1,
+				.info = snd_ctl_boolean_mono_info,
+				.get = monitor_get,
+				.put = monitor_put,
+				.private_value = OXYGEN_ADC_MONITOR_B,
+			},
+			{
+				.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+				.name = "Analog Input Monitor Volume",
+				.index = 1,
+				.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+					  SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+				.info = monitor_volume_info,
+				.get = monitor_get,
+				.put = monitor_put,
+				.private_value = OXYGEN_ADC_MONITOR_B_HALF_VOL
+						| (1 << 8),
+				.tlv = { .p = monitor_db_scale, },
+			},
+		},
 	},
 	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Analog Input Monitor Volume",
-		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
-			  SNDRV_CTL_ELEM_ACCESS_TLV_READ,
-		.info = monitor_volume_info,
-		.get = monitor_get,
-		.put = monitor_put,
-		.private_value = OXYGEN_ADC_MONITOR_B_HALF_VOL | (1 << 8),
-		.tlv = { .p = monitor_db_scale, },
-	},
-};
-static const struct snd_kcontrol_new monitor_2nd_b_controls[] = {
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Analog Input Monitor Switch",
-		.index = 1,
-		.info = snd_ctl_boolean_mono_info,
-		.get = monitor_get,
-		.put = monitor_put,
-		.private_value = OXYGEN_ADC_MONITOR_B,
-	},
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Analog Input Monitor Volume",
-		.index = 1,
-		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
-			  SNDRV_CTL_ELEM_ACCESS_TLV_READ,
-		.info = monitor_volume_info,
-		.get = monitor_get,
-		.put = monitor_put,
-		.private_value = OXYGEN_ADC_MONITOR_B_HALF_VOL | (1 << 8),
-		.tlv = { .p = monitor_db_scale, },
-	},
-};
-static const struct snd_kcontrol_new monitor_c_controls[] = {
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Digital Input Monitor Switch",
-		.info = snd_ctl_boolean_mono_info,
-		.get = monitor_get,
-		.put = monitor_put,
-		.private_value = OXYGEN_ADC_MONITOR_C,
-	},
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Digital Input Monitor Volume",
-		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
-			  SNDRV_CTL_ELEM_ACCESS_TLV_READ,
-		.info = monitor_volume_info,
-		.get = monitor_get,
-		.put = monitor_put,
-		.private_value = OXYGEN_ADC_MONITOR_C_HALF_VOL | (1 << 8),
-		.tlv = { .p = monitor_db_scale, },
+		.pcm_dev = CAPTURE_1_FROM_SPDIF,
+		.controls = {
+			{
+				.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+				.name = "Digital Input Monitor Switch",
+				.info = snd_ctl_boolean_mono_info,
+				.get = monitor_get,
+				.put = monitor_put,
+				.private_value = OXYGEN_ADC_MONITOR_C,
+			},
+			{
+				.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+				.name = "Digital Input Monitor Volume",
+				.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+					  SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+				.info = monitor_volume_info,
+				.get = monitor_get,
+				.put = monitor_put,
+				.private_value = OXYGEN_ADC_MONITOR_C_HALF_VOL
+						| (1 << 8),
+				.tlv = { .p = monitor_db_scale, },
+			},
+		},
 	},
 };
 
@@ -905,32 +926,17 @@ static int add_controls(struct oxygen *chip,
 
 int oxygen_mixer_init(struct oxygen *chip)
 {
+	unsigned int i;
 	int err;
 
 	err = add_controls(chip, controls, ARRAY_SIZE(controls));
 	if (err < 0)
 		return err;
-	if (chip->model->used_channels & OXYGEN_CHANNEL_A) {
-		err = add_controls(chip, monitor_a_controls,
-				   ARRAY_SIZE(monitor_a_controls));
-		if (err < 0)
-			return err;
-	} else if (chip->model->used_channels & OXYGEN_CHANNEL_B) {
-		err = add_controls(chip, monitor_b_controls,
-				   ARRAY_SIZE(monitor_b_controls));
-		if (err < 0)
-			return err;
-	}
-	if ((chip->model->used_channels & (OXYGEN_CHANNEL_A | OXYGEN_CHANNEL_B))
-	    == (OXYGEN_CHANNEL_A | OXYGEN_CHANNEL_B)) {
-		err = add_controls(chip, monitor_2nd_b_controls,
-				   ARRAY_SIZE(monitor_2nd_b_controls));
-		if (err < 0)
-			return err;
-	}
-	if (chip->model->used_channels & OXYGEN_CHANNEL_C) {
-		err = add_controls(chip, monitor_c_controls,
-				   ARRAY_SIZE(monitor_c_controls));
+	for (i = 0; i < ARRAY_SIZE(monitor_controls); ++i) {
+		if (!(chip->model->pcm_dev_cfg & monitor_controls[i].pcm_dev))
+			continue;
+		err = add_controls(chip, monitor_controls[i].controls,
+				   ARRAY_SIZE(monitor_controls[i].controls));
 		if (err < 0)
 			return err;
 	}
diff --git a/sound/pci/oxygen/oxygen_pcm.c b/sound/pci/oxygen/oxygen_pcm.c
index b70046aca65..b17c405e069 100644
--- a/sound/pci/oxygen/oxygen_pcm.c
+++ b/sound/pci/oxygen/oxygen_pcm.c
@@ -119,7 +119,7 @@ static int oxygen_open(struct snd_pcm_substream *substream,
 
 	runtime->private_data = (void *)(uintptr_t)channel;
 	if (channel == PCM_B && chip->has_ac97_1 &&
-	    (chip->model->used_channels & OXYGEN_CHANNEL_AC97))
+	    (chip->model->pcm_dev_cfg & CAPTURE_2_FROM_AC97_1))
 		runtime->hw = oxygen_ac97_hardware;
 	else
 		runtime->hw = *oxygen_hardware[channel];
@@ -365,7 +365,7 @@ static int oxygen_rec_b_hw_params(struct snd_pcm_substream *substream,
 		return err;
 
 	is_ac97 = chip->has_ac97_1 &&
-		(chip->model->used_channels & OXYGEN_CHANNEL_AC97);
+		(chip->model->pcm_dev_cfg & CAPTURE_2_FROM_AC97_1);
 
 	spin_lock_irq(&chip->reg_lock);
 	oxygen_write8_masked(chip, OXYGEN_REC_FORMAT,
@@ -640,34 +640,39 @@ int oxygen_pcm_init(struct oxygen *chip)
 	int outs, ins;
 	int err;
 
-	outs = 1; /* OXYGEN_CHANNEL_MULTICH is always used */
-	ins = !!(chip->model->used_channels & (OXYGEN_CHANNEL_A |
-					       OXYGEN_CHANNEL_B));
-	err = snd_pcm_new(chip->card, "Analog", 0, outs, ins, &pcm);
-	if (err < 0)
-		return err;
-	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &oxygen_multich_ops);
-	if (chip->model->used_channels & OXYGEN_CHANNEL_A)
-		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
-				&oxygen_rec_a_ops);
-	else if (chip->model->used_channels & OXYGEN_CHANNEL_B)
-		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
-				&oxygen_rec_b_ops);
-	pcm->private_data = chip;
-	pcm->private_free = oxygen_pcm_free;
-	strcpy(pcm->name, "Analog");
-	snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
-				      SNDRV_DMA_TYPE_DEV,
-				      snd_dma_pci_data(chip->pci),
-				      512 * 1024, 2048 * 1024);
-	if (ins)
-		snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
-					      SNDRV_DMA_TYPE_DEV,
-					      snd_dma_pci_data(chip->pci),
-					      128 * 1024, 256 * 1024);
-
-	outs = !!(chip->model->used_channels & OXYGEN_CHANNEL_SPDIF);
-	ins = !!(chip->model->used_channels & OXYGEN_CHANNEL_C);
+	outs = !!(chip->model->pcm_dev_cfg & PLAYBACK_0_TO_I2S);
+	ins = !!(chip->model->pcm_dev_cfg & (CAPTURE_0_FROM_I2S_1 |
+					     CAPTURE_0_FROM_I2S_2));
+	if (outs | ins) {
+		err = snd_pcm_new(chip->card, "Analog", 0, outs, ins, &pcm);
+		if (err < 0)
+			return err;
+		if (outs)
+			snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+					&oxygen_multich_ops);
+		if (chip->model->pcm_dev_cfg & CAPTURE_0_FROM_I2S_1)
+			snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+					&oxygen_rec_a_ops);
+		else if (chip->model->pcm_dev_cfg & CAPTURE_0_FROM_I2S_2)
+			snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+					&oxygen_rec_b_ops);
+		pcm->private_data = chip;
+		pcm->private_free = oxygen_pcm_free;
+		strcpy(pcm->name, "Analog");
+		if (outs)
+			snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
+						      SNDRV_DMA_TYPE_DEV,
+						      snd_dma_pci_data(chip->pci),
+						      512 * 1024, 2048 * 1024);
+		if (ins)
+			snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
+						      SNDRV_DMA_TYPE_DEV,
+						      snd_dma_pci_data(chip->pci),
+						      128 * 1024, 256 * 1024);
+	}
+
+	outs = !!(chip->model->pcm_dev_cfg & PLAYBACK_1_TO_SPDIF);
+	ins = !!(chip->model->pcm_dev_cfg & CAPTURE_1_FROM_SPDIF);
 	if (outs | ins) {
 		err = snd_pcm_new(chip->card, "Digital", 1, outs, ins, &pcm);
 		if (err < 0)
@@ -686,12 +691,13 @@ int oxygen_pcm_init(struct oxygen *chip)
 						      128 * 1024, 256 * 1024);
 	}
 
-	outs = chip->has_ac97_1 &&
-		(chip->model->used_channels & OXYGEN_CHANNEL_AC97);
-	ins = outs ||
-		(chip->model->used_channels & (OXYGEN_CHANNEL_A |
-					       OXYGEN_CHANNEL_B))
-		== (OXYGEN_CHANNEL_A | OXYGEN_CHANNEL_B);
+	if (chip->has_ac97_1) {
+		outs = !!(chip->model->pcm_dev_cfg & PLAYBACK_2_TO_AC97_1);
+		ins = !!(chip->model->pcm_dev_cfg & CAPTURE_2_FROM_AC97_1);
+	} else {
+		outs = 0;
+		ins = !!(chip->model->pcm_dev_cfg & CAPTURE_2_FROM_I2S_2);
+	}
 	if (outs | ins) {
 		err = snd_pcm_new(chip->card, outs ? "AC97" : "Analog2",
 				  2, outs, ins, &pcm);
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
index 127dd664fc1..5cd1fac1413 100644
--- a/sound/pci/oxygen/virtuoso.c
+++ b/sound/pci/oxygen/virtuoso.c
@@ -348,11 +348,11 @@ static const struct oxygen_model model_xonar = {
 	.ac97_switch_hook = xonar_ac97_switch_hook,
 	.gpio_changed = xonar_gpio_changed,
 	.model_data_size = sizeof(struct xonar_data),
+	.pcm_dev_cfg = PLAYBACK_0_TO_I2S |
+		       PLAYBACK_1_TO_SPDIF |
+		       CAPTURE_0_FROM_I2S_2 |
+		       CAPTURE_1_FROM_SPDIF,
 	.dac_channels = 8,
-	.used_channels = OXYGEN_CHANNEL_B |
-			 OXYGEN_CHANNEL_C |
-			 OXYGEN_CHANNEL_SPDIF |
-			 OXYGEN_CHANNEL_MULTICH,
 	.function_flags = OXYGEN_FUNCTION_ENABLE_SPI_4_5,
 	.dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
 	.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
-- 
cgit v1.2.3-70-g09d2


From 87eedd2fd409d5cd515ccd6fc454cef15c5fa38b Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Wed, 19 Mar 2008 08:20:13 +0100
Subject: [ALSA] oxygen: make SPI/2-wire configuration model-specific

Allow the model drivers to specify if the codec communication goes over
SPI or a 2-wire bus.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/oxygen/hifier.c     |  2 +-
 sound/pci/oxygen/oxygen.c     |  6 ++++--
 sound/pci/oxygen/oxygen_lib.c | 10 +++++-----
 sound/pci/oxygen/virtuoso.c   |  3 ++-
 4 files changed, 12 insertions(+), 9 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/oxygen/hifier.c b/sound/pci/oxygen/hifier.c
index fa489ed3ed4..143d83d916d 100644
--- a/sound/pci/oxygen/hifier.c
+++ b/sound/pci/oxygen/hifier.c
@@ -164,7 +164,7 @@ static const struct oxygen_model model_hifier = {
 		       PLAYBACK_1_TO_SPDIF |
 		       CAPTURE_0_FROM_I2S_1,
 	.dac_channels = 2,
-	.function_flags = 0,
+	.function_flags = OXYGEN_FUNCTION_SPI,
 	.dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
 	.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
 };
diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c
index 9faf43c949b..e9031ede962 100644
--- a/sound/pci/oxygen/oxygen.c
+++ b/sound/pci/oxygen/oxygen.c
@@ -310,7 +310,8 @@ static const struct oxygen_model model_generic = {
 		       CAPTURE_1_FROM_SPDIF |
 		       CAPTURE_2_FROM_AC97_1,
 	.dac_channels = 8,
-	.function_flags = OXYGEN_FUNCTION_ENABLE_SPI_4_5,
+	.function_flags = OXYGEN_FUNCTION_SPI |
+			  OXYGEN_FUNCTION_ENABLE_SPI_4_5,
 	.dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
 	.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
 };
@@ -335,7 +336,8 @@ static const struct oxygen_model model_meridian = {
 		       CAPTURE_1_FROM_SPDIF |
 		       CAPTURE_2_FROM_AC97_1,
 	.dac_channels = 8,
-	.function_flags = OXYGEN_FUNCTION_ENABLE_SPI_4_5,
+	.function_flags = OXYGEN_FUNCTION_SPI |
+			  OXYGEN_FUNCTION_ENABLE_SPI_4_5,
 	.dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
 	.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
 };
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c
index a1abb50eedb..b7c7eb33106 100644
--- a/sound/pci/oxygen/oxygen_lib.c
+++ b/sound/pci/oxygen/oxygen_lib.c
@@ -240,12 +240,12 @@ static void oxygen_init(struct oxygen *chip)
 	chip->has_ac97_0 = (i & OXYGEN_AC97_CODEC_0) != 0;
 	chip->has_ac97_1 = (i & OXYGEN_AC97_CODEC_1) != 0;
 
-	oxygen_set_bits8(chip, OXYGEN_FUNCTION,
-			 OXYGEN_FUNCTION_RESET_CODEC |
-			 chip->model->function_flags);
 	oxygen_write8_masked(chip, OXYGEN_FUNCTION,
-			     OXYGEN_FUNCTION_SPI,
-			     OXYGEN_FUNCTION_2WIRE_SPI_MASK);
+			     OXYGEN_FUNCTION_RESET_CODEC |
+			     chip->model->function_flags,
+			     OXYGEN_FUNCTION_RESET_CODEC |
+			     OXYGEN_FUNCTION_2WIRE_SPI_MASK |
+			     OXYGEN_FUNCTION_ENABLE_SPI_4_5);
 	oxygen_write8(chip, OXYGEN_DMA_STATUS, 0);
 	oxygen_write8(chip, OXYGEN_DMA_PAUSE, 0);
 	oxygen_write8(chip, OXYGEN_PLAY_CHANNELS,
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
index 5cd1fac1413..5bf3661ab1f 100644
--- a/sound/pci/oxygen/virtuoso.c
+++ b/sound/pci/oxygen/virtuoso.c
@@ -353,7 +353,8 @@ static const struct oxygen_model model_xonar = {
 		       CAPTURE_0_FROM_I2S_2 |
 		       CAPTURE_1_FROM_SPDIF,
 	.dac_channels = 8,
-	.function_flags = OXYGEN_FUNCTION_ENABLE_SPI_4_5,
+	.function_flags = OXYGEN_FUNCTION_SPI |
+			  OXYGEN_FUNCTION_ENABLE_SPI_4_5,
 	.dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
 	.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
 };
-- 
cgit v1.2.3-70-g09d2


From db12b8e301455cf18644aa3b765ae10869eb947c Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Wed, 19 Mar 2008 08:20:59 +0100
Subject: [ALSA] oxygen: move MIDI flag to model struct

Put the flag that enables the MIDI port into the model structure instead
of passing it as a separate parameter to oxygen_pci_probe().

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/oxygen/hifier.c     |  2 +-
 sound/pci/oxygen/oxygen.c     |  3 ++-
 sound/pci/oxygen/oxygen.h     |  3 ++-
 sound/pci/oxygen/oxygen_lib.c | 12 ++++++------
 sound/pci/oxygen/virtuoso.c   |  3 ++-
 5 files changed, 13 insertions(+), 10 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/oxygen/hifier.c b/sound/pci/oxygen/hifier.c
index 143d83d916d..1e54a3cd721 100644
--- a/sound/pci/oxygen/hifier.c
+++ b/sound/pci/oxygen/hifier.c
@@ -181,7 +181,7 @@ static int __devinit hifier_probe(struct pci_dev *pci,
 		++dev;
 		return -ENOENT;
 	}
-	err = oxygen_pci_probe(pci, index[dev], id[dev], 0, &model_hifier);
+	err = oxygen_pci_probe(pci, index[dev], id[dev], &model_hifier);
 	if (err >= 0)
 		++dev;
 	return err;
diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c
index e9031ede962..511ef34a43c 100644
--- a/sound/pci/oxygen/oxygen.c
+++ b/sound/pci/oxygen/oxygen.c
@@ -336,6 +336,7 @@ static const struct oxygen_model model_meridian = {
 		       CAPTURE_1_FROM_SPDIF |
 		       CAPTURE_2_FROM_AC97_1,
 	.dac_channels = 8,
+	.misc_flags = OXYGEN_MISC_MIDI,
 	.function_flags = OXYGEN_FUNCTION_SPI |
 			  OXYGEN_FUNCTION_ENABLE_SPI_4_5,
 	.dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
@@ -356,7 +357,7 @@ static int __devinit generic_oxygen_probe(struct pci_dev *pci,
 		return -ENOENT;
 	}
 	is_meridian = pci_id->driver_data;
-	err = oxygen_pci_probe(pci, index[dev], id[dev], is_meridian,
+	err = oxygen_pci_probe(pci, index[dev], id[dev],
 			       is_meridian ? &model_meridian : &model_generic);
 	if (err >= 0)
 		++dev;
diff --git a/sound/pci/oxygen/oxygen.h b/sound/pci/oxygen/oxygen.h
index fde995cf2ed..5103482f65e 100644
--- a/sound/pci/oxygen/oxygen.h
+++ b/sound/pci/oxygen/oxygen.h
@@ -103,6 +103,7 @@ struct oxygen_model {
 	size_t model_data_size;
 	unsigned int pcm_dev_cfg;
 	u8 dac_channels;
+	u8 misc_flags;
 	u8 function_flags;
 	u16 dac_i2s_format;
 	u16 adc_i2s_format;
@@ -110,7 +111,7 @@ struct oxygen_model {
 
 /* oxygen_lib.c */
 
-int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, int midi,
+int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
 		     const struct oxygen_model *model);
 void oxygen_pci_remove(struct pci_dev *pci);
 
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c
index b7c7eb33106..87df2b81c57 100644
--- a/sound/pci/oxygen/oxygen_lib.c
+++ b/sound/pci/oxygen/oxygen_lib.c
@@ -253,11 +253,13 @@ static void oxygen_init(struct oxygen *chip)
 		      OXYGEN_DMA_A_BURST_8 |
 		      OXYGEN_DMA_MULTICH_BURST_8);
 	oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0);
-	oxygen_write8_masked(chip, OXYGEN_MISC, 0,
+	oxygen_write8_masked(chip, OXYGEN_MISC,
+			     chip->model->misc_flags,
 			     OXYGEN_MISC_WRITE_PCI_SUBID |
 			     OXYGEN_MISC_REC_C_FROM_SPDIF |
 			     OXYGEN_MISC_REC_B_FROM_AC97 |
-			     OXYGEN_MISC_REC_A_FROM_MULTICH);
+			     OXYGEN_MISC_REC_A_FROM_MULTICH |
+			     OXYGEN_MISC_MIDI);
 	oxygen_write8(chip, OXYGEN_REC_FORMAT,
 		      (OXYGEN_FORMAT_16 << OXYGEN_REC_FORMAT_A_SHIFT) |
 		      (OXYGEN_FORMAT_16 << OXYGEN_REC_FORMAT_B_SHIFT) |
@@ -400,7 +402,7 @@ static void oxygen_card_free(struct snd_card *card)
 }
 
 int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
-		     int midi, const struct oxygen_model *model)
+		     const struct oxygen_model *model)
 {
 	struct snd_card *card;
 	struct oxygen *chip;
@@ -472,9 +474,7 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
 	if (err < 0)
 		goto err_card;
 
-	oxygen_write8_masked(chip, OXYGEN_MISC,
-			     midi ? OXYGEN_MISC_MIDI : 0, OXYGEN_MISC_MIDI);
-	if (midi) {
+	if (model->misc_flags & OXYGEN_MISC_MIDI) {
 		err = snd_mpu401_uart_new(card, 0, MPU401_HW_CMIPCI,
 					  chip->addr + OXYGEN_MPU401,
 					  MPU401_INFO_INTEGRATED, 0, 0,
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
index 5bf3661ab1f..fa79db696e2 100644
--- a/sound/pci/oxygen/virtuoso.c
+++ b/sound/pci/oxygen/virtuoso.c
@@ -353,6 +353,7 @@ static const struct oxygen_model model_xonar = {
 		       CAPTURE_0_FROM_I2S_2 |
 		       CAPTURE_1_FROM_SPDIF,
 	.dac_channels = 8,
+	.misc_flags = OXYGEN_MISC_MIDI,
 	.function_flags = OXYGEN_FUNCTION_SPI |
 			  OXYGEN_FUNCTION_ENABLE_SPI_4_5,
 	.dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
@@ -371,7 +372,7 @@ static int __devinit xonar_probe(struct pci_dev *pci,
 		++dev;
 		return -ENOENT;
 	}
-	err = oxygen_pci_probe(pci, index[dev], id[dev], 1, &model_xonar);
+	err = oxygen_pci_probe(pci, index[dev], id[dev], &model_xonar);
 	if (err >= 0)
 		++dev;
 	return err;
-- 
cgit v1.2.3-70-g09d2


From 43dd89c7e7cde6b42edac88ca852ec61af610863 Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Wed, 19 Mar 2008 08:21:32 +0100
Subject: [ALSA] oxygen: disable clock of unused I2S inputs

Disable the master clock outputs of any unused I2S inputs.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/oxygen/oxygen_lib.c | 29 ++++++++++++++++++-----------
 1 file changed, 18 insertions(+), 11 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c
index 87df2b81c57..858e6d4c919 100644
--- a/sound/pci/oxygen/oxygen_lib.c
+++ b/sound/pci/oxygen/oxygen_lib.c
@@ -272,18 +272,25 @@ static void oxygen_init(struct oxygen *chip)
 		       OXYGEN_RATE_48000 | chip->model->dac_i2s_format |
 		       OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 |
 		       OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);
-	oxygen_write16(chip, OXYGEN_I2S_A_FORMAT,
-		       OXYGEN_RATE_48000 | chip->model->adc_i2s_format |
-		       OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 |
-		       OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);
-	oxygen_write16(chip, OXYGEN_I2S_B_FORMAT,
-		       OXYGEN_RATE_48000 | chip->model->adc_i2s_format |
-		       OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 |
-		       OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);
+	if (chip->model->pcm_dev_cfg & CAPTURE_0_FROM_I2S_1)
+		oxygen_write16(chip, OXYGEN_I2S_A_FORMAT,
+			       OXYGEN_RATE_48000 | chip->model->adc_i2s_format |
+			       OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 |
+			       OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);
+	else
+		oxygen_write16(chip, OXYGEN_I2S_A_FORMAT,
+			       OXYGEN_I2S_MASTER | OXYGEN_I2S_MUTE_MCLK);
+	if (chip->model->pcm_dev_cfg & (CAPTURE_0_FROM_I2S_2 |
+					CAPTURE_2_FROM_I2S_2))
+		oxygen_write16(chip, OXYGEN_I2S_B_FORMAT,
+			       OXYGEN_RATE_48000 | chip->model->adc_i2s_format |
+			       OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 |
+			       OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);
+	else
+		oxygen_write16(chip, OXYGEN_I2S_B_FORMAT,
+			       OXYGEN_I2S_MASTER | OXYGEN_I2S_MUTE_MCLK);
 	oxygen_write16(chip, OXYGEN_I2S_C_FORMAT,
-		       OXYGEN_RATE_48000 | chip->model->adc_i2s_format |
-		       OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 |
-		       OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);
+		       OXYGEN_I2S_MASTER | OXYGEN_I2S_MUTE_MCLK);
 	oxygen_write32_masked(chip, OXYGEN_SPDIF_CONTROL,
 			      OXYGEN_SPDIF_SENSE_MASK |
 			      OXYGEN_SPDIF_LOCK_MASK |
-- 
cgit v1.2.3-70-g09d2


From 91e24faa556548e0705e8940410b8dc3bd1d949d Mon Sep 17 00:00:00 2001
From: Andrew Morton <akpm@linux-foundation.org>
Date: Thu, 20 Mar 2008 12:04:46 +0100
Subject: [ALSA] sound/pci/aw2/aw2-alsa.c needs dma-mapping.h

sparc32:

sound/pci/aw2/aw2-alsa.c: In function 'snd_aw2_create':
sound/pci/aw2/aw2-alsa.c:282: error: 'DMA_32BIT_MASK' undeclared (first use in this function)
sound/pci/aw2/aw2-alsa.c:282: error: (Each undeclared identifier is reported only once
sound/pci/aw2/aw2-alsa.c:282: error: for each function it appears in.)

Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/aw2/aw2-alsa.c | 1 +
 1 file changed, 1 insertion(+)

(limited to 'sound')

diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c
index 24e3e4961d9..12d01c9c663 100644
--- a/sound/pci/aw2/aw2-alsa.c
+++ b/sound/pci/aw2/aw2-alsa.c
@@ -22,6 +22,7 @@
  *****************************************************************************/
 #include <linux/init.h>
 #include <linux/pci.h>
+#include <linux/dma-mapping.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
-- 
cgit v1.2.3-70-g09d2


From ee0abefde5273c816bd3d4158e5cb9c591b82684 Mon Sep 17 00:00:00 2001
From: Andrew Morton <akpm@linux-foundation.org>
Date: Thu, 20 Mar 2008 12:05:33 +0100
Subject: [ALSA] sound/pci/pcxhr/pcxhr_core.c: fix printk warning

sound/pci/pcxhr/pcxhr_core.c: In function `pcxhr_set_pipe_state':
sound/pci/pcxhr/pcxhr_core.c:899: warning: long int format, different type arg (arg 4)

suseconds_t is int on sparc64.

Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/pcxhr/pcxhr_core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'sound')

diff --git a/sound/pci/pcxhr/pcxhr_core.c b/sound/pci/pcxhr/pcxhr_core.c
index 846afbd3068..78aa81feaa4 100644
--- a/sound/pci/pcxhr/pcxhr_core.c
+++ b/sound/pci/pcxhr/pcxhr_core.c
@@ -897,7 +897,7 @@ int pcxhr_set_pipe_state(struct pcxhr_mgr *mgr, int playback_mask, int capture_m
 #ifdef CONFIG_SND_DEBUG_DETECT
 	do_gettimeofday(&my_tv2);
 	snd_printdd("***SET PIPE STATE*** TIME = %ld (err = %x)\n",
-		    my_tv2.tv_usec - my_tv1.tv_usec, err);
+		    (long)(my_tv2.tv_usec - my_tv1.tv_usec), err);
 #endif
 	return 0;
 }
-- 
cgit v1.2.3-70-g09d2


From ff73317ea7c648cf5f59b8bda4a810f7b5d0312c Mon Sep 17 00:00:00 2001
From: Andrew Morton <akpm@linux-foundation.org>
Date: Thu, 20 Mar 2008 12:07:31 +0100
Subject: [ALSA] sound/pci/pcxhr/pcxhr.c: fix warnings

sparc64:

sound/pci/pcxhr/pcxhr.c: In function `pcxhr_update_r_buffer':
sound/pci/pcxhr/pcxhr.c:459: warning: cast to pointer from integer of different size
sound/pci/pcxhr/pcxhr.c: In function `pcxhr_trigger_tasklet':
sound/pci/pcxhr/pcxhr.c:628: warning: long int format, different type arg (arg 4)

Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/pcxhr/pcxhr.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c
index beed5818338..7fdcdc8c6b6 100644
--- a/sound/pci/pcxhr/pcxhr.c
+++ b/sound/pci/pcxhr/pcxhr.c
@@ -458,7 +458,7 @@ static int pcxhr_update_r_buffer(struct pcxhr_stream *stream)
 
 	snd_printdd("pcxhr_update_r_buffer(pcm%c%d) : addr(%p) bytes(%zx) subs(%d)\n",
 		    is_capture ? 'c' : 'p',
-		    chip->chip_idx, (void*)subs->runtime->dma_addr,
+		    chip->chip_idx, (void *)(long)subs->runtime->dma_addr,
 		    subs->runtime->dma_bytes, subs->number);
 
 	pcxhr_init_rmh(&rmh, CMD_UPDATE_R_BUFFERS);
@@ -626,7 +626,7 @@ static void pcxhr_trigger_tasklet(unsigned long arg)
 #ifdef CONFIG_SND_DEBUG_DETECT
 	do_gettimeofday(&my_tv2);
 	snd_printdd("***TRIGGER TASKLET*** TIME = %ld (err = %x)\n",
-		    my_tv2.tv_usec - my_tv1.tv_usec, err);
+		    (long)(my_tv2.tv_usec - my_tv1.tv_usec), err);
 #endif
 }
 
-- 
cgit v1.2.3-70-g09d2


From d16be8ed69f3e59d36be8c422508c3a10082fdaa Mon Sep 17 00:00:00 2001
From: Pavel Hofman <dustin@seznam.cz>
Date: Thu, 20 Mar 2008 12:10:27 +0100
Subject: [ALSA] ice1724 - Improved the Juli rate setting

* moving most of clock-specific code to card-specific routines
* support for ESI Juli
* to-be-researched - monitoring of analog/digital inputs

Signed-off-by: Pavel Hofman <dustin@seznam.cz>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/Kconfig           |   1 +
 sound/pci/ice1712/ice1712.h |   9 +
 sound/pci/ice1712/ice1724.c | 313 ++++++++++++++---------------
 sound/pci/ice1712/juli.c    | 471 +++++++++++++++++++++++++++++++++++++++++---
 4 files changed, 599 insertions(+), 195 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 868183bef24..b5903eed6ef 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -697,6 +697,7 @@ config SND_ICE1724
 	depends on SND
 	select SND_MPU401_UART
 	select SND_AC97_CODEC
+	select SND_VMASTER
 	help
 	  Say Y here to include support for soundcards based on
 	  ICE/VT1724/1720 (Envy24HT/PT) chips.
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h
index 303cffe08bd..a3bea2247c7 100644
--- a/sound/pci/ice1712/ice1712.h
+++ b/sound/pci/ice1712/ice1712.h
@@ -367,6 +367,15 @@ struct snd_ice1712 {
 
 	/* other board-specific data */
 	void *spec;
+
+	/* VT172x specific */
+	int pro_rate_default;
+	int (*is_spdif_master)(struct snd_ice1712 *ice);
+	unsigned int (*get_rate)(struct snd_ice1712 *ice);
+	void (*set_rate)(struct snd_ice1712 *ice, unsigned int rate);
+	unsigned char (*set_mclk)(struct snd_ice1712 *ice, unsigned int rate);
+	void (*set_spdif_clock)(struct snd_ice1712 *ice);
+
 };
 
 
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index 3bfd70577d7..ceac8705626 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -106,15 +106,19 @@ static unsigned int PRO_RATE_DEFAULT = 44100;
  *  Basic I/O
  */
  
+/*
+ *  default rates, default clock routines
+ */
+
 /* check whether the clock mode is spdif-in */
-static inline int is_spdif_master(struct snd_ice1712 *ice)
+static inline int stdclock_is_spdif_master(struct snd_ice1712 *ice)
 {
 	return (inb(ICEMT1724(ice, RATE)) & VT1724_SPDIF_MASTER) ? 1 : 0;
 }
 
 static inline int is_pro_rate_locked(struct snd_ice1712 *ice)
 {
-	return is_spdif_master(ice) || PRO_RATE_LOCKED;
+	return ice->is_spdif_master(ice) || PRO_RATE_LOCKED;
 }
 
 /*
@@ -391,51 +395,61 @@ static int snd_vt1724_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 #define DMA_PAUSES	(VT1724_RDMA0_PAUSE|VT1724_PDMA0_PAUSE|VT1724_RDMA1_PAUSE|\
 	VT1724_PDMA1_PAUSE|VT1724_PDMA2_PAUSE|VT1724_PDMA3_PAUSE|VT1724_PDMA4_PAUSE)
 
-static int get_max_rate(struct snd_ice1712 *ice)
+static const unsigned int stdclock_rate_list[16] = {
+	48000, 24000, 12000, 9600, 32000, 16000, 8000, 96000, 44100,
+	22050, 11025, 88200, 176400, 0, 192000, 64000
+};
+
+static unsigned int stdclock_get_rate(struct snd_ice1712 *ice)
 {
+	unsigned int rate;
+	rate = stdclock_rate_list[inb(ICEMT1724(ice, RATE)) & 15];
+	return rate;
+}
+
+static void stdclock_set_rate(struct snd_ice1712 *ice, unsigned int rate)
+{
+	int i;
+	for (i = 0; i < ARRAY_SIZE(stdclock_rate_list); i++) {
+		if (stdclock_rate_list[i] == rate) {
+			outb(i, ICEMT1724(ice, RATE));
+			return;
+		}
+	}
+}
+
+static unsigned char stdclock_set_mclk(struct snd_ice1712 *ice,
+				       unsigned int rate)
+{
+	unsigned char val, old;
+	/* check MT02 */
 	if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) {
-		if ((ice->eeprom.data[ICE_EEP2_I2S] & 0x08) && !ice->vt1720)
-			return 192000;
+		val = old = inb(ICEMT1724(ice, I2S_FORMAT));
+		if (rate > 96000)
+			val |= VT1724_MT_I2S_MCLK_128X; /* 128x MCLK */
 		else
-			return 96000;
-	} else
-		return 48000;
+			val &= ~VT1724_MT_I2S_MCLK_128X; /* 256x MCLK */
+		if (val != old) {
+			outb(val, ICEMT1724(ice, I2S_FORMAT));
+			/* master clock changed */
+			return 1;
+		}
+	}
+	/* no change in master clock */
+	return 0;
 }
 
 static void snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate,
 				    int force)
 {
 	unsigned long flags;
-	unsigned char val, old;
-	unsigned int i, mclk_change;
+	unsigned char mclk_change;
+	unsigned int i, old_rate;
 
-	if (rate > get_max_rate(ice))
+	if (rate > ice->hw_rates->list[ice->hw_rates->count - 1])
 		return;
-
-	switch (rate) {
-	case 8000: val = 6; break;
-	case 9600: val = 3; break;
-	case 11025: val = 10; break;
-	case 12000: val = 2; break;
-	case 16000: val = 5; break;
-	case 22050: val = 9; break;
-	case 24000: val = 1; break;
-	case 32000: val = 4; break;
-	case 44100: val = 8; break;
-	case 48000: val = 0; break;
-	case 64000: val = 15; break;
-	case 88200: val = 11; break;
-	case 96000: val = 7; break;
-	case 176400: val = 12; break;
-	case 192000: val = 14; break;
-	default:
-		snd_BUG();
-		val = 0;
-		break;
-	}
-
 	spin_lock_irqsave(&ice->reg_lock, flags);
-	if ((inb(ICEMT1724(ice, DMA_CONTROL)) & DMA_STARTS) || 
+	if ((inb(ICEMT1724(ice, DMA_CONTROL)) & DMA_STARTS) ||
 	    (inb(ICEMT1724(ice, DMA_PAUSE)) & DMA_PAUSES)) {
 		/* running? we cannot change the rate now... */
 		spin_unlock_irqrestore(&ice->reg_lock, flags);
@@ -446,9 +460,9 @@ static void snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate,
 		return;
 	}
 
-	old = inb(ICEMT1724(ice, RATE));
-	if (force || old != val)
-		outb(val, ICEMT1724(ice, RATE));
+	old_rate = ice->get_rate(ice);
+	if (force || (old_rate != rate))
+		ice->set_rate(ice, rate);
 	else if (rate == ice->cur_rate) {
 		spin_unlock_irqrestore(&ice->reg_lock, flags);
 		return;
@@ -456,19 +470,9 @@ static void snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate,
 
 	ice->cur_rate = rate;
 
-	/* check MT02 */
-	mclk_change = 0;
-	if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) {
-		val = old = inb(ICEMT1724(ice, I2S_FORMAT));
-		if (rate > 96000)
-			val |= VT1724_MT_I2S_MCLK_128X; /* 128x MCLK */
-		else
-			val &= ~VT1724_MT_I2S_MCLK_128X; /* 256x MCLK */
-		if (val != old) {
-			outb(val, ICEMT1724(ice, I2S_FORMAT));
-			mclk_change = 1;
-		}
-	}
+	/* setting master clock */
+	mclk_change = ice->set_mclk(ice, rate);
+
 	spin_unlock_irqrestore(&ice->reg_lock, flags);
 
 	if (mclk_change && ice->gpio.i2s_mclk_changed)
@@ -727,43 +731,32 @@ static const struct snd_pcm_hardware snd_vt1724_2ch_stereo =
 /*
  * set rate constraints
  */
-static int set_rate_constraints(struct snd_ice1712 *ice,
-				struct snd_pcm_substream *substream)
+static void set_std_hw_rates(struct snd_ice1712 *ice)
 {
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	if (ice->hw_rates) {
-		/* hardware specific */
-		runtime->hw.rate_min = ice->hw_rates->list[0];
-		runtime->hw.rate_max = ice->hw_rates->list[ice->hw_rates->count - 1];
-		runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
-		return snd_pcm_hw_constraint_list(runtime, 0,
-						  SNDRV_PCM_HW_PARAM_RATE,
-						  ice->hw_rates);
-	}
 	if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) {
 		/* I2S */
 		/* VT1720 doesn't support more than 96kHz */
 		if ((ice->eeprom.data[ICE_EEP2_I2S] & 0x08) && !ice->vt1720)
-			return snd_pcm_hw_constraint_list(runtime, 0,
-							  SNDRV_PCM_HW_PARAM_RATE,
-							  &hw_constraints_rates_192);
-		else {
-			runtime->hw.rates = SNDRV_PCM_RATE_KNOT |
-				SNDRV_PCM_RATE_8000_96000;
-			runtime->hw.rate_max = 96000;
-			return snd_pcm_hw_constraint_list(runtime, 0,
-							  SNDRV_PCM_HW_PARAM_RATE,
-							  &hw_constraints_rates_96);
-		}
-	} else if (ice->ac97) {
+			ice->hw_rates = &hw_constraints_rates_192;
+		else
+			ice->hw_rates = &hw_constraints_rates_96;
+	} else {
 		/* ACLINK */
-		runtime->hw.rate_max = 48000;
-		runtime->hw.rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000;
-		return snd_pcm_hw_constraint_list(runtime, 0,
-						  SNDRV_PCM_HW_PARAM_RATE,
-						  &hw_constraints_rates_48);
+		ice->hw_rates = &hw_constraints_rates_48;
 	}
-	return 0;
+}
+
+static int set_rate_constraints(struct snd_ice1712 *ice,
+				struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+
+	runtime->hw.rate_min = ice->hw_rates->list[0];
+	runtime->hw.rate_max = ice->hw_rates->list[ice->hw_rates->count - 1];
+	runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
+	return snd_pcm_hw_constraint_list(runtime, 0,
+					  SNDRV_PCM_HW_PARAM_RATE,
+					  ice->hw_rates);
 }
 
 /* multi-channel playback needs alignment 8x32bit regardless of the channels
@@ -824,7 +817,7 @@ static int snd_vt1724_playback_pro_close(struct snd_pcm_substream *substream)
 	struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
 
 	if (PRO_RATE_RESET)
-		snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
+		snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 0);
 	ice->playback_pro_substream = NULL;
 
 	return 0;
@@ -835,7 +828,7 @@ static int snd_vt1724_capture_pro_close(struct snd_pcm_substream *substream)
 	struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
 
 	if (PRO_RATE_RESET)
-		snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
+		snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 0);
 	ice->capture_pro_substream = NULL;
 	return 0;
 }
@@ -980,7 +973,7 @@ static int snd_vt1724_playback_spdif_close(struct snd_pcm_substream *substream)
 	struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
 
 	if (PRO_RATE_RESET)
-		snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
+		snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 0);
 	ice->playback_con_substream = NULL;
 	if (ice->spdif.ops.close)
 		ice->spdif.ops.close(ice, substream);
@@ -1016,7 +1009,7 @@ static int snd_vt1724_capture_spdif_close(struct snd_pcm_substream *substream)
 	struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
 
 	if (PRO_RATE_RESET)
-		snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
+		snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 0);
 	ice->capture_con_substream = NULL;
 	if (ice->spdif.ops.close)
 		ice->spdif.ops.close(ice, substream);
@@ -1162,7 +1155,7 @@ static int snd_vt1724_playback_indep_close(struct snd_pcm_substream *substream)
 	struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
 
 	if (PRO_RATE_RESET)
-		snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
+		snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 0);
 	ice->playback_con_substream_ds[substream->number] = NULL;
 	ice->pcm_reserved[substream->number] = NULL;
 
@@ -1580,50 +1573,18 @@ int snd_ice1712_gpio_put(struct snd_kcontrol *kcontrol,
 static int snd_vt1724_pro_internal_clock_info(struct snd_kcontrol *kcontrol,
 					      struct snd_ctl_elem_info *uinfo)
 {
-	static const char * const texts_1724[] = {
-		"8000",		/* 0: 6 */
-		"9600",		/* 1: 3 */
-		"11025",	/* 2: 10 */
-		"12000",	/* 3: 2 */
-		"16000",	/* 4: 5 */
-		"22050",	/* 5: 9 */
-		"24000",	/* 6: 1 */
-		"32000",	/* 7: 4 */
-		"44100",	/* 8: 8 */
-		"48000",	/* 9: 0 */
-		"64000",	/* 10: 15 */
-		"88200",	/* 11: 11 */
-		"96000",	/* 12: 7 */
-		"176400",	/* 13: 12 */
-		"192000",	/* 14: 14 */
-		"IEC958 Input",	/* 15: -- */
-	};
-	static const char * const texts_1720[] = {
-		"8000",		/* 0: 6 */
-		"9600",		/* 1: 3 */
-		"11025",	/* 2: 10 */
-		"12000",	/* 3: 2 */
-		"16000",	/* 4: 5 */
-		"22050",	/* 5: 9 */
-		"24000",	/* 6: 1 */
-		"32000",	/* 7: 4 */
-		"44100",	/* 8: 8 */
-		"48000",	/* 9: 0 */
-		"64000",	/* 10: 15 */
-		"88200",	/* 11: 11 */
-		"96000",	/* 12: 7 */
-		"IEC958 Input",	/* 13: -- */
-	};
 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 	uinfo->count = 1;
-	uinfo->value.enumerated.items = ice->vt1720 ? 14 : 16;
+	uinfo->value.enumerated.items = ice->hw_rates->count + 1;
 	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
 		uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
-	strcpy(uinfo->value.enumerated.name,
-	       ice->vt1720 ? texts_1720[uinfo->value.enumerated.item] :
-	       texts_1724[uinfo->value.enumerated.item]);
+	if (uinfo->value.enumerated.item == uinfo->value.enumerated.items - 1)
+		strcpy(uinfo->value.enumerated.name, "IEC958 Input");
+	else
+		sprintf(uinfo->value.enumerated.name, "%d",
+			ice->hw_rates->list[uinfo->value.enumerated.item]);
 	return 0;
 }
 
@@ -1631,68 +1592,79 @@ static int snd_vt1724_pro_internal_clock_get(struct snd_kcontrol *kcontrol,
 					     struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
-	static const unsigned char xlate[16] = {
-		9, 6, 3, 1, 7, 4, 0, 12, 8, 5, 2, 11, 13, 255, 14, 10
-	};
-	unsigned char val;
+	unsigned int i, rate;
 	
 	spin_lock_irq(&ice->reg_lock);
-	if (is_spdif_master(ice)) {
-		ucontrol->value.enumerated.item[0] = ice->vt1720 ? 13 : 15;
+	if (ice->is_spdif_master(ice)) {
+		ucontrol->value.enumerated.item[0] = ice->hw_rates->count;
 	} else {
-		val = xlate[inb(ICEMT1724(ice, RATE)) & 15];
-		if (val == 255) {
-			snd_BUG();
-			val = 0;
+		rate = ice->get_rate(ice);
+		ucontrol->value.enumerated.item[0] = 0;
+		for (i = 0; i < ice->hw_rates->count; i++) {
+			if (ice->hw_rates->list[i] == rate) {
+				ucontrol->value.enumerated.item[0] = i;
+				break;
+			}
 		}
-		ucontrol->value.enumerated.item[0] = val;
 	}
 	spin_unlock_irq(&ice->reg_lock);
 	return 0;
 }
 
+/* setting clock to external - SPDIF */
+static void stdclock_set_spdif_clock(struct snd_ice1712 *ice)
+{
+	unsigned char oval;
+	unsigned char i2s_oval;
+	oval = inb(ICEMT1724(ice, RATE));
+	outb(oval | VT1724_SPDIF_MASTER, ICEMT1724(ice, RATE));
+	/* setting 256fs */
+	i2s_oval = inb(ICEMT1724(ice, I2S_FORMAT));
+	outb(i2s_oval & ~VT1724_MT_I2S_MCLK_128X, ICEMT1724(ice, I2S_FORMAT));
+}
+
 static int snd_vt1724_pro_internal_clock_put(struct snd_kcontrol *kcontrol,
 					     struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
-	unsigned char oval;
-	int rate;
-	int change = 0;
-	int spdif = ice->vt1720 ? 13 : 15;
+	unsigned int old_rate, new_rate;
+	unsigned int item = ucontrol->value.enumerated.item[0];
+	unsigned int spdif = ice->hw_rates->count;
+
+	if (item > spdif)
+		return -EINVAL;
 
 	spin_lock_irq(&ice->reg_lock);
-	oval = inb(ICEMT1724(ice, RATE));
-	if (ucontrol->value.enumerated.item[0] == spdif) {
-		unsigned char i2s_oval;
-		outb(oval | VT1724_SPDIF_MASTER, ICEMT1724(ice, RATE));
-		/* setting 256fs */
-		i2s_oval = inb(ICEMT1724(ice, I2S_FORMAT));
-		outb(i2s_oval & ~VT1724_MT_I2S_MCLK_128X,
-		     ICEMT1724(ice, I2S_FORMAT));
+	if (ice->is_spdif_master(ice))
+		old_rate = 0;
+	else
+		old_rate = ice->get_rate(ice);
+	if (item == spdif) {
+		/* switching to external clock via SPDIF */
+		ice->set_spdif_clock(ice);
+		new_rate = 0;
 	} else {
-		rate = rates[ucontrol->value.integer.value[0] % 15];
-		if (rate <= get_max_rate(ice)) {
-			PRO_RATE_DEFAULT = rate;
-			spin_unlock_irq(&ice->reg_lock);
-			snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 1);
-			spin_lock_irq(&ice->reg_lock);
-		}
+		/* internal on-card clock */
+		new_rate = ice->hw_rates->list[item];
+		ice->pro_rate_default = new_rate;
+		spin_unlock_irq(&ice->reg_lock);
+		snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 1);
+		spin_lock_irq(&ice->reg_lock);
 	}
-	change = inb(ICEMT1724(ice, RATE)) != oval;
 	spin_unlock_irq(&ice->reg_lock);
 
-	if ((oval & VT1724_SPDIF_MASTER) !=
-	    (inb(ICEMT1724(ice, RATE)) & VT1724_SPDIF_MASTER)) {
+	/* the first reset to the SPDIF master mode? */
+	if (old_rate != new_rate && !new_rate) {
 		/* notify akm chips as well */
-		if (is_spdif_master(ice)) {
-			unsigned int i;
-			for (i = 0; i < ice->akm_codecs; i++) {
-				if (ice->akm[i].ops.set_rate_val)
-					ice->akm[i].ops.set_rate_val(&ice->akm[i], 0);
-			}
+		unsigned int i;
+		if (ice->gpio.set_pro_rate)
+			ice->gpio.set_pro_rate(ice, 0);
+		for (i = 0; i < ice->akm_codecs; i++) {
+			if (ice->akm[i].ops.set_rate_val)
+				ice->akm[i].ops.set_rate_val(&ice->akm[i], 0);
 		}
 	}
-	return change;
+	return old_rate != new_rate;
 }
 
 static struct snd_kcontrol_new snd_vt1724_pro_internal_clock __devinitdata = {
@@ -2343,6 +2315,19 @@ static int __devinit snd_vt1724_probe(struct pci_dev *pci,
         * was called so in ice1712 driver, and vt1724 driver is derived from
         * ice1712 driver.
         */
+	ice->pro_rate_default = PRO_RATE_DEFAULT;
+	if (!ice->is_spdif_master)
+		ice->is_spdif_master = stdclock_is_spdif_master;
+	if (!ice->get_rate)
+		ice->get_rate = stdclock_get_rate;
+	if (!ice->set_rate)
+		ice->set_rate = stdclock_set_rate;
+	if (!ice->set_mclk)
+		ice->set_mclk = stdclock_set_mclk;
+	if (!ice->set_spdif_clock)
+		ice->set_spdif_clock = stdclock_set_spdif_clock;
+	if (!ice->hw_rates)
+		set_std_hw_rates(ice);
 
 	if ((err = snd_vt1724_pcm_profi(ice, pcm_dev++)) < 0) {
 		snd_card_free(card);
diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c
index 4550609b4d4..b4e0c16852a 100644
--- a/sound/pci/ice1712/juli.c
+++ b/sound/pci/ice1712/juli.c
@@ -4,6 +4,8 @@
  *   Lowlevel functions for ESI Juli@ cards
  *
  *	Copyright (c) 2004 Jaroslav Kysela <perex@perex.cz>
+ *	              2008 Pavel Hofman <dustin@seznam.cz>
+ *
  *
  *   This program is free software; you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -27,11 +29,11 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <sound/core.h>
+#include <sound/tlv.h>
 
 #include "ice1712.h"
 #include "envy24ht.h"
 #include "juli.h"
-
 struct juli_spec {
 	struct ak4114 *ak4114;
 	unsigned int analog: 1;
@@ -43,6 +45,32 @@ struct juli_spec {
 #define AK4114_ADDR		0x20		/* S/PDIF receiver */
 #define AK4358_ADDR		0x22		/* DAC */
 
+/*
+ * Juli does not use the standard ICE1724 clock scheme. Juli's ice1724 chip is
+ * supplied by external clock provided by Xilinx array and MK73-1 PLL frequency
+ * multiplier. Actual frequency is set by ice1724 GPIOs hooked to the Xilinx.
+ *
+ * The clock circuitry is supplied by the two ice1724 crystals. This
+ * arrangement allows to generate independent clock signal for AK4114's input
+ * rate detection circuit. As a result, Juli, unlike most other
+ * ice1724+ak4114-based cards, detects spdif input rate correctly.
+ * This fact is applied in the driver, allowing to modify PCM stream rate
+ * parameter according to the actual input rate.
+ *
+ * Juli uses the remaining three stereo-channels of its DAC to optionally
+ * monitor analog input, digital input, and digital output. The corresponding
+ * I2S signals are routed by Xilinx, controlled by GPIOs.
+ *
+ * The master mute is implemented using output muting transistors (GPIO) in
+ * combination with smuting the DAC.
+ *
+ * The card itself has no HW master volume control, implemented using the
+ * vmaster control.
+ *
+ * TODO:
+ * researching and fixing the input monitors
+ */
+
 /*
  * GPIO pins
  */
@@ -55,17 +83,82 @@ struct juli_spec {
 #define GPIO_MULTI_2X		(1<<2)
 #define GPIO_MULTI_1X		(2<<2)		/* also external */
 #define GPIO_MULTI_HALF		(3<<2)
-#define GPIO_INTERNAL_CLOCK	(1<<4)
+#define GPIO_INTERNAL_CLOCK	(1<<4)		/* 0 = external, 1 = internal */
+#define GPIO_CLOCK_MASK		(1<<4)
 #define GPIO_ANALOG_PRESENT	(1<<5)		/* RO only: 0 = present */
 #define GPIO_RXMCLK_SEL		(1<<7)		/* must be 0 */
 #define GPIO_AK5385A_CKS0	(1<<8)
-#define GPIO_AK5385A_DFS0	(1<<9)		/* swapped with DFS1 according doc? */
-#define GPIO_AK5385A_DFS1	(1<<10)
+#define GPIO_AK5385A_DFS1	(1<<9)
+#define GPIO_AK5385A_DFS0	(1<<10)
 #define GPIO_DIGOUT_MONITOR	(1<<11)		/* 1 = active */
 #define GPIO_DIGIN_MONITOR	(1<<12)		/* 1 = active */
 #define GPIO_ANAIN_MONITOR	(1<<13)		/* 1 = active */
-#define GPIO_AK5385A_MCLK	(1<<14)		/* must be 0 */
-#define GPIO_MUTE_CONTROL	(1<<15)		/* 0 = off, 1 = on */
+#define GPIO_AK5385A_CKS1	(1<<14)		/* must be 0 */
+#define GPIO_MUTE_CONTROL	(1<<15)		/* output mute, 1 = muted */
+
+#define GPIO_RATE_MASK		(GPIO_FREQ_MASK | GPIO_MULTI_MASK | \
+		GPIO_CLOCK_MASK)
+#define GPIO_AK5385A_MASK	(GPIO_AK5385A_CKS0 | GPIO_AK5385A_DFS0 | \
+		GPIO_AK5385A_DFS1 | GPIO_AK5385A_CKS1)
+
+#define JULI_PCM_RATE	(SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \
+		SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
+		SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | \
+		SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | \
+		SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000)
+
+#define GPIO_RATE_16000		(GPIO_FREQ_32KHZ | GPIO_MULTI_HALF | \
+		GPIO_INTERNAL_CLOCK)
+#define GPIO_RATE_22050		(GPIO_FREQ_44KHZ | GPIO_MULTI_HALF | \
+		GPIO_INTERNAL_CLOCK)
+#define GPIO_RATE_24000		(GPIO_FREQ_48KHZ | GPIO_MULTI_HALF | \
+		GPIO_INTERNAL_CLOCK)
+#define GPIO_RATE_32000		(GPIO_FREQ_32KHZ | GPIO_MULTI_1X | \
+		GPIO_INTERNAL_CLOCK)
+#define GPIO_RATE_44100		(GPIO_FREQ_44KHZ | GPIO_MULTI_1X | \
+		GPIO_INTERNAL_CLOCK)
+#define GPIO_RATE_48000		(GPIO_FREQ_48KHZ | GPIO_MULTI_1X | \
+		GPIO_INTERNAL_CLOCK)
+#define GPIO_RATE_64000		(GPIO_FREQ_32KHZ | GPIO_MULTI_2X | \
+		GPIO_INTERNAL_CLOCK)
+#define GPIO_RATE_88200		(GPIO_FREQ_44KHZ | GPIO_MULTI_2X | \
+		GPIO_INTERNAL_CLOCK)
+#define GPIO_RATE_96000		(GPIO_FREQ_48KHZ | GPIO_MULTI_2X | \
+		GPIO_INTERNAL_CLOCK)
+#define GPIO_RATE_176400	(GPIO_FREQ_44KHZ | GPIO_MULTI_4X | \
+		GPIO_INTERNAL_CLOCK)
+#define GPIO_RATE_192000	(GPIO_FREQ_48KHZ | GPIO_MULTI_4X | \
+		GPIO_INTERNAL_CLOCK)
+
+/*
+ * Initial setup of the conversion array GPIO <-> rate
+ */
+static unsigned int juli_rates[] = {
+	16000, 22050, 24000, 32000,
+	44100, 48000, 64000, 88200,
+	96000, 176400, 192000,
+};
+
+static unsigned int gpio_vals[] = {
+	GPIO_RATE_16000, GPIO_RATE_22050, GPIO_RATE_24000, GPIO_RATE_32000,
+	GPIO_RATE_44100, GPIO_RATE_48000, GPIO_RATE_64000, GPIO_RATE_88200,
+	GPIO_RATE_96000, GPIO_RATE_176400, GPIO_RATE_192000,
+};
+
+static struct snd_pcm_hw_constraint_list juli_rates_info = {
+	.count = ARRAY_SIZE(juli_rates),
+	.list = juli_rates,
+	.mask = 0,
+};
+
+static int get_gpio_val(int rate)
+{
+	int i;
+	for (i = 0; i < ARRAY_SIZE(juli_rates); i++)
+		if (juli_rates[i] == rate)
+			return gpio_vals[i];
+	return 0;
+}
 
 static void juli_ak4114_write(void *private_data, unsigned char reg, unsigned char val)
 {
@@ -77,6 +170,10 @@ static unsigned char juli_ak4114_read(void *private_data, unsigned char reg)
 	return snd_vt1724_read_i2c((struct snd_ice1712 *)private_data, AK4114_ADDR, reg);
 }
 
+/*
+ * If SPDIF capture and slaved to SPDIF-IN, setting runtime rate
+ * to the external rate
+ */
 static void juli_spdif_in_open(struct snd_ice1712 *ice,
 			       struct snd_pcm_substream *substream)
 {
@@ -84,7 +181,8 @@ static void juli_spdif_in_open(struct snd_ice1712 *ice,
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	int rate;
 
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ||
+			!ice->is_spdif_master(ice))
 		return;
 	rate = snd_ak4114_external_rate(spec->ak4114);
 	if (rate >= runtime->hw.rate_min && rate <= runtime->hw.rate_max) {
@@ -115,57 +213,285 @@ static void juli_akm_write(struct snd_akm4xxx *ak, int chip,
 }
 
 /*
- * change the rate of envy24HT, AK4358
+ * change the rate of envy24HT, AK4358, AK5385
  */
 static void juli_akm_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate)
 {
-	unsigned char old, tmp, dfs;
+	unsigned char old, tmp, ak4358_dfs;
+	unsigned int ak5385_pins, old_gpio, new_gpio;
+	struct snd_ice1712 *ice = ak->private_data[0];
+	struct juli_spec *spec = ice->spec;
 
-	if (rate == 0)  /* no hint - S/PDIF input is master, simply return */
+	if (rate == 0)  /* no hint - S/PDIF input is master or the new spdif
+			   input rate undetected, simply return */
 		return;
-	
+
 	/* adjust DFS on codecs */
-	if (rate > 96000) 
-		dfs = 2;
-	else if (rate > 48000)
-		dfs = 1;
-	else
-		dfs = 0;
-	
+	if (rate > 96000)  {
+		ak4358_dfs = 2;
+		ak5385_pins = GPIO_AK5385A_DFS1 | GPIO_AK5385A_CKS0;
+	} else if (rate > 48000) {
+		ak4358_dfs = 1;
+		ak5385_pins = GPIO_AK5385A_DFS0;
+	} else {
+		ak4358_dfs = 0;
+		ak5385_pins = 0;
+	}
+	/* AK5385 first, since it requires cold reset affecting both codecs */
+	old_gpio = ice->gpio.get_data(ice);
+	new_gpio =  (old_gpio & ~GPIO_AK5385A_MASK) | ak5385_pins;
+	/* printk(KERN_DEBUG "JULI - ak5385 set_rate_val: new gpio 0x%x\n",
+		new_gpio); */
+	ice->gpio.set_data(ice, new_gpio);
+
+	/* cold reset */
+	old = inb(ICEMT1724(ice, AC97_CMD));
+	outb(old | VT1724_AC97_COLD, ICEMT1724(ice, AC97_CMD));
+	udelay(1);
+	outb(old & ~VT1724_AC97_COLD, ICEMT1724(ice, AC97_CMD));
+
+	/* AK4358 */
+	/* set new value, reset DFS */
 	tmp = snd_akm4xxx_get(ak, 0, 2);
-	old = (tmp >> 4) & 0x03;
-	if (old == dfs)
-		return;
-	/* reset DFS */
 	snd_akm4xxx_reset(ak, 1);
 	tmp = snd_akm4xxx_get(ak, 0, 2);
 	tmp &= ~(0x03 << 4);
-	tmp |= dfs << 4;
+	tmp |= ak4358_dfs << 4;
 	snd_akm4xxx_set(ak, 0, 2, tmp);
 	snd_akm4xxx_reset(ak, 0);
+
+	/* reinit ak4114 */
+	snd_ak4114_reinit(spec->ak4114);
 }
 
+#define AK_DAC(xname, xch)	{ .name = xname, .num_channels = xch }
+#define PCM_VOLUME		"PCM Playback Volume"
+#define MONITOR_AN_IN_VOLUME	"Monitor Analog In Volume"
+#define MONITOR_DIG_IN_VOLUME	"Monitor Digital In Volume"
+#define MONITOR_DIG_OUT_VOLUME	"Monitor Digital Out Volume"
+
+static const struct snd_akm4xxx_dac_channel juli_dac[] = {
+	AK_DAC(PCM_VOLUME, 2),
+	AK_DAC(MONITOR_AN_IN_VOLUME, 2),
+	AK_DAC(MONITOR_DIG_OUT_VOLUME, 2),
+	AK_DAC(MONITOR_DIG_IN_VOLUME, 2),
+};
+
+
 static struct snd_akm4xxx akm_juli_dac __devinitdata = {
 	.type = SND_AK4358,
-	.num_dacs = 2,
+	.num_dacs = 8,	/* DAC1 - analog out
+			   DAC2 - analog in monitor
+			   DAC3 - digital out monitor
+			   DAC4 - digital in monitor
+			 */
 	.ops = {
 		.lock = juli_akm_lock,
 		.unlock = juli_akm_unlock,
 		.write = juli_akm_write,
 		.set_rate_val = juli_akm_set_rate_val
+	},
+	.dac_info = juli_dac,
+};
+
+#define juli_mute_info		snd_ctl_boolean_mono_info
+
+static int juli_mute_get(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+	unsigned int val;
+	val = ice->gpio.get_data(ice) & (unsigned int) kcontrol->private_value;
+	if (kcontrol->private_value == GPIO_MUTE_CONTROL)
+		/* val 0 = signal on */
+		ucontrol->value.integer.value[0] = (val) ? 0 : 1;
+	else
+		/* val 1 = signal on */
+		ucontrol->value.integer.value[0] = (val) ? 1 : 0;
+	return 0;
+}
+
+static int juli_mute_put(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+	unsigned int old_gpio, new_gpio;
+	old_gpio = ice->gpio.get_data(ice);
+	if (ucontrol->value.integer.value[0]) {
+		/* unmute */
+		if (kcontrol->private_value == GPIO_MUTE_CONTROL) {
+			/* 0 = signal on */
+			new_gpio = old_gpio & ~GPIO_MUTE_CONTROL;
+			/* un-smuting DAC */
+			snd_akm4xxx_write(ice->akm, 0, 0x01, 0x01);
+		} else
+			/* 1 = signal on */
+			new_gpio =  old_gpio |
+				(unsigned int) kcontrol->private_value;
+	} else {
+		/* mute */
+		if (kcontrol->private_value == GPIO_MUTE_CONTROL) {
+			/* 1 = signal off */
+			new_gpio = old_gpio | GPIO_MUTE_CONTROL;
+			/* smuting DAC */
+			snd_akm4xxx_write(ice->akm, 0, 0x01, 0x03);
+		} else
+			/* 0 = signal off */
+			new_gpio =  old_gpio &
+				~((unsigned int) kcontrol->private_value);
+	}
+	/* printk("JULI - mute/unmute: control_value: 0x%x, old_gpio: 0x%x, \
+		new_gpio 0x%x\n",
+		(unsigned int)ucontrol->value.integer.value[0], old_gpio,
+		new_gpio); */
+	if (old_gpio != new_gpio) {
+		ice->gpio.set_data(ice, new_gpio);
+		return 1;
+	}
+	/* no change */
+	return 0;
+}
+
+static struct snd_kcontrol_new juli_mute_controls[] __devinitdata = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Master Playback Switch",
+		.info = juli_mute_info,
+		.get = juli_mute_get,
+		.put = juli_mute_put,
+		.private_value = GPIO_MUTE_CONTROL,
+	},
+	/* Although the following functionality respects the succint NDA'd
+	 * documentation from the card manufacturer, and the same way of
+	 * operation is coded in OSS Juli driver, only Digital Out monitor
+	 * seems to work. Surprisingly, Analog input monitor outputs Digital
+	 * output data. The two are independent, as enabling both doubles
+	 * volume of the monitor sound.
+	 *
+	 * Checking traces on the board suggests the functionality described
+	 * by the manufacturer is correct - I2S from ADC and AK4114
+	 * go to ICE as well as to Xilinx, I2S inputs of DAC2,3,4 (the monitor
+	 * inputs) are fed from Xilinx.
+	 *
+	 * I even checked traces on board and coded a support in driver for
+	 * an alternative possiblity - the unused I2S ICE output channels
+	 * switched to HW-IN/SPDIF-IN and providing the monitoring signal to
+	 * the DAC - to no avail. The I2S outputs seem to be unconnected.
+	 *
+	 * The windows driver supports the monitoring correctly.
+	 */
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Monitor Analog In Switch",
+		.info = juli_mute_info,
+		.get = juli_mute_get,
+		.put = juli_mute_put,
+		.private_value = GPIO_ANAIN_MONITOR,
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Monitor Digital Out Switch",
+		.info = juli_mute_info,
+		.get = juli_mute_get,
+		.put = juli_mute_put,
+		.private_value = GPIO_DIGOUT_MONITOR,
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Monitor Digital In Switch",
+		.info = juli_mute_info,
+		.get = juli_mute_get,
+		.put = juli_mute_put,
+		.private_value = GPIO_DIGIN_MONITOR,
+	},
+};
+
+
+static void ak4358_proc_regs_read(struct snd_info_entry *entry,
+		struct snd_info_buffer *buffer)
+{
+	struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data;
+	int reg, val;
+	for (reg = 0; reg <= 0xf; reg++) {
+		val =  snd_akm4xxx_get(ice->akm, 0, reg);
+		snd_iprintf(buffer, "0x%02x = 0x%02x\n", reg, val);
 	}
+}
+
+static void ak4358_proc_init(struct snd_ice1712 *ice)
+{
+	struct snd_info_entry *entry;
+	if (!snd_card_proc_new(ice->card, "ak4358_codec", &entry))
+		snd_info_set_text_ops(entry, ice, ak4358_proc_regs_read);
+}
+
+static char *slave_vols[] __devinitdata = {
+	PCM_VOLUME,
+	MONITOR_AN_IN_VOLUME,
+	MONITOR_DIG_IN_VOLUME,
+	MONITOR_DIG_OUT_VOLUME,
+	NULL
 };
 
+static __devinitdata
+DECLARE_TLV_DB_SCALE(juli_master_db_scale, -6350, 50, 1);
+
+static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card,
+		const char *name)
+{
+	struct snd_ctl_elem_id sid;
+	memset(&sid, 0, sizeof(sid));
+	/* FIXME: strcpy is bad. */
+	strcpy(sid.name, name);
+	sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+	return snd_ctl_find_id(card, &sid);
+}
+
+static void __devinit add_slaves(struct snd_card *card,
+				 struct snd_kcontrol *master, char **list)
+{
+	for (; *list; list++) {
+		struct snd_kcontrol *slave = ctl_find(card, *list);
+		/* printk(KERN_DEBUG "add_slaves - %s\n", *list); */
+		if (slave) {
+			/* printk(KERN_DEBUG "slave %s found\n", *list); */
+			snd_ctl_add_slave(master, slave);
+		}
+	}
+}
+
 static int __devinit juli_add_controls(struct snd_ice1712 *ice)
 {
 	struct juli_spec *spec = ice->spec;
 	int err;
+	unsigned int i;
+	struct snd_kcontrol *vmaster;
+
 	err = snd_ice1712_akm4xxx_build_controls(ice);
 	if (err < 0)
 		return err;
+
+	for (i = 0; i < ARRAY_SIZE(juli_mute_controls); i++) {
+		err = snd_ctl_add(ice->card,
+				snd_ctl_new1(&juli_mute_controls[i], ice));
+		if (err < 0)
+			return err;
+	}
+	/* Create virtual master control */
+	vmaster = snd_ctl_make_virtual_master("Master Playback Volume",
+					      juli_master_db_scale);
+	if (!vmaster)
+		return -ENOMEM;
+	add_slaves(ice->card, vmaster, slave_vols);
+	err = snd_ctl_add(ice->card, vmaster);
+	if (err < 0)
+		return err;
+
 	/* only capture SPDIF over AK4114 */
 	err = snd_ak4114_build(spec->ak4114, NULL,
-			       ice->pcm_pro->streams[SNDRV_PCM_STREAM_CAPTURE].substream);
+			ice->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream);
+
+	ak4358_proc_init(ice);
 	if (err < 0)
 		return err;
 	return 0;
@@ -174,6 +500,74 @@ static int __devinit juli_add_controls(struct snd_ice1712 *ice)
 /*
  * initialize the chip
  */
+
+static inline int juli_is_spdif_master(struct snd_ice1712 *ice)
+{
+	return (ice->gpio.get_data(ice) & GPIO_INTERNAL_CLOCK) ? 0 : 1;
+}
+
+static unsigned int juli_get_rate(struct snd_ice1712 *ice)
+{
+	int i;
+	unsigned char result;
+
+	result =  ice->gpio.get_data(ice) & GPIO_RATE_MASK;
+	for (i = 0; i < ARRAY_SIZE(gpio_vals); i++)
+		if (gpio_vals[i] == result)
+			return juli_rates[i];
+	return 0;
+}
+
+/* setting new rate */
+static void juli_set_rate(struct snd_ice1712 *ice, unsigned int rate)
+{
+	unsigned int old, new;
+	unsigned char val;
+
+	old = ice->gpio.get_data(ice);
+	new =  (old & ~GPIO_RATE_MASK) | get_gpio_val(rate);
+	/* printk(KERN_DEBUG "JULI - set_rate: old %x, new %x\n",
+			old & GPIO_RATE_MASK,
+			new & GPIO_RATE_MASK); */
+
+	ice->gpio.set_data(ice, new);
+	/* switching to external clock - supplied by external circuits */
+	val = inb(ICEMT1724(ice, RATE));
+	outb(val | VT1724_SPDIF_MASTER, ICEMT1724(ice, RATE));
+}
+
+static inline unsigned char juli_set_mclk(struct snd_ice1712 *ice,
+					  unsigned int rate)
+{
+	/* no change in master clock */
+	return 0;
+}
+
+/* setting clock to external - SPDIF */
+static void juli_set_spdif_clock(struct snd_ice1712 *ice)
+{
+	unsigned int old;
+	old = ice->gpio.get_data(ice);
+	/* external clock (= 0), multiply 1x, 48kHz */
+	ice->gpio.set_data(ice, (old & ~GPIO_RATE_MASK) | GPIO_MULTI_1X |
+			GPIO_FREQ_48KHZ);
+}
+
+/* Called when ak4114 detects change in the input SPDIF stream */
+static void juli_ak4114_change(struct ak4114 *ak4114, unsigned char c0,
+			       unsigned char c1)
+{
+	struct snd_ice1712 *ice = ak4114->change_callback_private;
+	int rate;
+	if (ice->is_spdif_master(ice) && c1) {
+		/* only for SPDIF master mode, rate was changed */
+		rate = snd_ak4114_external_rate(ak4114);
+		/* printk(KERN_DEBUG "ak4114 - input rate changed to %d\n",
+				rate); */
+		juli_akm_set_rate_val(ice->akm, rate);
+	}
+}
+
 static int __devinit juli_init(struct snd_ice1712 *ice)
 {
 	static const unsigned char ak4114_init_vals[] = {
@@ -203,6 +597,11 @@ static int __devinit juli_init(struct snd_ice1712 *ice)
 				ice, &spec->ak4114);
 	if (err < 0)
 		return err;
+	/* callback for codecs rate setting */
+	spec->ak4114->change_callback = juli_ak4114_change;
+	spec->ak4114->change_callback_private = ice;
+	/* AK4114 in Juli can detect external rate correctly */
+	spec->ak4114->check_flags = 0;
 
 #if 0
         /* it seems that the analog doughter board detection does not work
@@ -226,6 +625,14 @@ static int __devinit juli_init(struct snd_ice1712 *ice)
 			return err;
 	}
 	
+	/* juli is clocked by Xilinx array */
+	ice->hw_rates = &juli_rates_info;
+	ice->is_spdif_master = juli_is_spdif_master;
+	ice->get_rate = juli_get_rate;
+	ice->set_rate = juli_set_rate;
+	ice->set_mclk = juli_set_mclk;
+	ice->set_spdif_clock = juli_set_spdif_clock;
+
 	ice->spdif.ops.open = juli_spdif_in_open;
 	return 0;
 }
@@ -237,18 +644,20 @@ static int __devinit juli_init(struct snd_ice1712 *ice)
  */
 
 static unsigned char juli_eeprom[] __devinitdata = {
-	[ICE_EEP2_SYSCONF]     = 0x20,	/* clock 512, mpu401, 1xADC, 1xDACs */
+	[ICE_EEP2_SYSCONF]     = 0x2b,	/* clock 512, mpu401, 1xADC, 1xDACs,
+					   SPDIF in */
 	[ICE_EEP2_ACLINK]      = 0x80,	/* I2S */
 	[ICE_EEP2_I2S]         = 0xf8,	/* vol, 96k, 24bit, 192k */
 	[ICE_EEP2_SPDIF]       = 0xc3,	/* out-en, out-int, spdif-in */
-	[ICE_EEP2_GPIO_DIR]    = 0x9f,
+	[ICE_EEP2_GPIO_DIR]    = 0x9f,	/* 5, 6:inputs; 7, 4-0 outputs*/
 	[ICE_EEP2_GPIO_DIR1]   = 0xff,
 	[ICE_EEP2_GPIO_DIR2]   = 0x7f,
-	[ICE_EEP2_GPIO_MASK]   = 0x9f,
-	[ICE_EEP2_GPIO_MASK1]  = 0xff,
+	[ICE_EEP2_GPIO_MASK]   = 0x60,	/* 5, 6: locked; 7, 4-0 writable */
+	[ICE_EEP2_GPIO_MASK1]  = 0x00,  /* 0-7 writable */
 	[ICE_EEP2_GPIO_MASK2]  = 0x7f,
-	[ICE_EEP2_GPIO_STATE]  = 0x16,	/* internal clock, multiple 1x, 48kHz */
-	[ICE_EEP2_GPIO_STATE1] = 0x80,	/* mute */
+	[ICE_EEP2_GPIO_STATE]  = GPIO_FREQ_48KHZ | GPIO_MULTI_1X |
+	       GPIO_INTERNAL_CLOCK,	/* internal clock, multiple 1x, 48kHz*/
+	[ICE_EEP2_GPIO_STATE1] = 0x00,	/* unmuted */
 	[ICE_EEP2_GPIO_STATE2] = 0x00,
 };
 
-- 
cgit v1.2.3-70-g09d2


From 07bcb316cf3510d5048bc251bb23cd6452c16fc2 Mon Sep 17 00:00:00 2001
From: Matthew Ranostay <mranostay@embeddedalley.com>
Date: Thu, 20 Mar 2008 12:10:57 +0100
Subject: [ALSA] hda: 92hd71bxxx DMIC nid

Added missing DMIC verb to dell_4_1_pin_configs[].

Signed-off-by: Matthew Ranostay <mranostay@embeddedalley.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_sigmatel.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 8eff8fe9dcf..69cd3b23f5a 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -1317,7 +1317,7 @@ static unsigned int ref92hd71bxx_pin_configs[10] = {
 
 static unsigned int dell_m4_1_pin_configs[13] = {
 	0x0421101f, 0x04a11221, 0x40f000f0, 0x90170110,
-	0x23a1902e, 0x23014250, 0x40f000f0, 0x4f0000f0,
+	0x23a1902e, 0x23014250, 0x40f000f0, 0x90a000f0,
 	0x40f000f0, 0x4f0000f0,
 };
 
-- 
cgit v1.2.3-70-g09d2


From 0e31daf7d6484c60e96f63a905eb9b959b975da5 Mon Sep 17 00:00:00 2001
From: Jiang zhe <zhe.jiang@intel.com>
Date: Thu, 20 Mar 2008 12:12:39 +0100
Subject: [ALSA] hda-codec - model for alc262 to support Lenovo 3000

This model is to support the Lenovo 3000 y410.
ALSA bug#3856:
	https://bugtrack.alsa-project.org/alsa-bug/view.php?id=3856

Signed-off-by: Jiang zhe <zhe.jiang@intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c | 100 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 100 insertions(+)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index eb40f4820c8..8b819072af3 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -98,6 +98,7 @@ enum {
 	ALC262_SONY_ASSAMD,
 	ALC262_BENQ_T31,
 	ALC262_ULTRA,
+	ALC262_LENOVO_3000,
 	ALC262_AUTO,
 	ALC262_MODEL_LAST /* last tag */
 };
@@ -8728,6 +8729,12 @@ static struct hda_verb alc262_fujitsu_unsol_verbs[] = {
 	{}
 };
 
+static struct hda_verb alc262_lenovo_3000_unsol_verbs[] = {
+	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{}
+};
+
 static struct hda_input_mux alc262_fujitsu_capture_source = {
 	.num_items = 3,
 	.items = {
@@ -8808,6 +8815,46 @@ static struct hda_bind_ctls alc262_fujitsu_bind_master_vol = {
 	},
 };
 
+/* mute/unmute internal speaker according to the hp jack and mute state */
+static void alc262_lenovo_3000_automute(struct hda_codec *codec, int force)
+{
+	struct alc_spec *spec = codec->spec;
+	unsigned int mute;
+
+	if (force || !spec->sense_updated) {
+		unsigned int present_int_hp;
+		/* need to execute and sync at first */
+		snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0);
+		present_int_hp = snd_hda_codec_read(codec, 0x1b, 0,
+					AC_VERB_GET_PIN_SENSE, 0);
+		spec->jack_present = (present_int_hp & 0x80000000) != 0;
+		spec->sense_updated = 1;
+	}
+	if (spec->jack_present) {
+		/* mute internal speaker */
+		snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+					 HDA_AMP_MUTE, HDA_AMP_MUTE);
+		snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
+					 HDA_AMP_MUTE, HDA_AMP_MUTE);
+	} else {
+		/* unmute internal speaker if necessary */
+		mute = snd_hda_codec_amp_read(codec, 0x1b, 0, HDA_OUTPUT, 0);
+		snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+					 HDA_AMP_MUTE, mute);
+		snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
+					 HDA_AMP_MUTE, mute);
+	}
+}
+
+/* unsolicited event for HP jack sensing */
+static void alc262_lenovo_3000_unsol_event(struct hda_codec *codec,
+				       unsigned int res)
+{
+	if ((res >> 26) != ALC_HP_EVENT)
+		return;
+	alc262_lenovo_3000_automute(codec, 1);
+}
+
 /* bind hp and internal speaker mute (with plug check) */
 static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol,
 					 struct snd_ctl_elem_value *ucontrol)
@@ -8849,6 +8896,44 @@ static struct snd_kcontrol_new alc262_fujitsu_mixer[] = {
 	{ } /* end */
 };
 
+/* bind hp and internal speaker mute (with plug check) */
+static int alc262_lenovo_3000_master_sw_put(struct snd_kcontrol *kcontrol,
+					 struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	long *valp = ucontrol->value.integer.value;
+	int change;
+
+	change = snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
+						 HDA_AMP_MUTE,
+						 valp ? 0 : HDA_AMP_MUTE);
+
+	if (change)
+		alc262_lenovo_3000_automute(codec, 0);
+	return change;
+}
+
+static struct snd_kcontrol_new alc262_lenovo_3000_mixer[] = {
+	HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Master Playback Switch",
+		.info = snd_hda_mixer_amp_switch_info,
+		.get = snd_hda_mixer_amp_switch_get,
+		.put = alc262_lenovo_3000_master_sw_put,
+		.private_value = HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
+	},
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	{ } /* end */
+};
+
 /* additional init verbs for Benq laptops */
 static struct hda_verb alc262_EAPD_verbs[] = {
 	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
@@ -9398,6 +9483,7 @@ static const char *alc262_models[ALC262_MODEL_LAST] = {
 	[ALC262_BENQ_T31]	= "benq-t31",
 	[ALC262_SONY_ASSAMD]	= "sony-assamd",
 	[ALC262_ULTRA]		= "ultra",
+	[ALC262_LENOVO_3000]	= "lenovo-3000",
 	[ALC262_AUTO]		= "auto",
 };
 
@@ -9434,6 +9520,7 @@ static struct snd_pci_quirk alc262_cfg_tbl[] = {
 	SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FUJITSU),
 	SND_PCI_QUIRK(0x144d, 0xc032, "Samsung Q1 Ultra", ALC262_ULTRA),
 	SND_PCI_QUIRK(0x144d, 0xc039, "Samsung Q1U EL", ALC262_ULTRA),
+	SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000 y410", ALC262_LENOVO_3000),
 	SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8),
 	SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_BENQ_T31),
 	SND_PCI_QUIRK(0x17ff, 0x058f, "Benq Hippo", ALC262_HIPPO_1),
@@ -9596,6 +9683,19 @@ static struct alc_config_preset alc262_presets[] = {
 		.unsol_event = alc262_ultra_unsol_event,
 		.init_hook = alc262_ultra_automute,
 	},
+	[ALC262_LENOVO_3000] = {
+		.mixers = { alc262_lenovo_3000_mixer },
+		.init_verbs = { alc262_init_verbs, alc262_EAPD_verbs,
+				alc262_lenovo_3000_unsol_verbs },
+		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
+		.dac_nids = alc262_dac_nids,
+		.hp_nid = 0x03,
+		.dig_out_nid = ALC262_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc262_modes),
+		.channel_mode = alc262_modes,
+		.input_mux = &alc262_fujitsu_capture_source,
+		.unsol_event = alc262_lenovo_3000_unsol_event,
+	},
 };
 
 static int patch_alc262(struct hda_codec *codec)
-- 
cgit v1.2.3-70-g09d2


From 5d85f8d02af56da5e3b76805da00a0f7f7427255 Mon Sep 17 00:00:00 2001
From: Herton Ronaldo Krzesinski <herton@mandriva.com>
Date: Thu, 20 Mar 2008 12:13:46 +0100
Subject: [ALSA] hda-codec - Remove now uneeded 6stack-hp model from ALC883

After DAC assignment fix in ALC883, the 6stack-hp model is now the same
as 6stack-dig. So just remove 6stack-hp model and replace its use with
6stack-dig.

Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 Documentation/sound/alsa/ALSA-Configuration.txt |  1 -
 sound/pci/hda/patch_realtek.c                   | 55 +------------------------
 2 files changed, 1 insertion(+), 55 deletions(-)

(limited to 'sound')

diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 42dd8f5855d..0fb62f65938 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -879,7 +879,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
 	  lenovo-nb0763	Lenovo NB0763
 	  lenovo-ms7195-dig Lenovo MS7195
 	  haier-w66	Haier W66
-	  6stack-hp	HP machines with 6stack (Nettle boards)
 	  3stack-hp	HP machines with 3stack (Lucknow, Samba boards)
 	  6stack-dell	Dell machines with 6stack (Inspiron 530)
 	  mitac		Mitac 8252D
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 8b819072af3..15b4704539f 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -198,7 +198,6 @@ enum {
 	ALC883_LENOVO_NB0763,
 	ALC888_LENOVO_MS7195_DIG,
 	ALC883_HAIER_W66,		
-	ALC888_6ST_HP,
 	ALC888_3ST_HP,
 	ALC888_6ST_DELL,
 	ALC883_MITAC,
@@ -6956,46 +6955,6 @@ static struct snd_kcontrol_new alc883_medion_md2_mixer[] = {
 	{ } /* end */
 };	
 
-static struct snd_kcontrol_new alc888_6st_hp_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
-	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
-	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		/* .name = "Capture Source", */
-		.name = "Input Source",
-		.count = 2,
-		.info = alc883_mux_enum_info,
-		.get = alc883_mux_enum_get,
-		.put = alc883_mux_enum_put,
-	},
-	{ } /* end */
-};
-
 static struct snd_kcontrol_new alc888_3st_hp_mixer[] = {
 	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
 	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
@@ -7721,7 +7680,6 @@ static const char *alc883_models[ALC883_MODEL_LAST] = {
 	[ALC883_LENOVO_NB0763]	= "lenovo-nb0763",
 	[ALC888_LENOVO_MS7195_DIG] = "lenovo-ms7195-dig",
 	[ALC883_HAIER_W66] 	= "haier-w66",
-	[ALC888_6ST_HP]		= "6stack-hp",
 	[ALC888_3ST_HP]		= "3stack-hp",
 	[ALC888_6ST_DELL]	= "6stack-dell",
 	[ALC883_MITAC]		= "mitac",
@@ -7740,7 +7698,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
 	SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavillion", ALC883_6ST_DIG),
 	SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP),
 	SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP),
-	SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC888_6ST_HP),
+	SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC883_6ST_DIG),
 	SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG),
 	SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC883_6ST_DIG),
 	SND_PCI_QUIRK(0x1071, 0x8253, "Mitac 8252d", ALC883_MITAC),
@@ -7973,17 +7931,6 @@ static struct alc_config_preset alc883_presets[] = {
 		.unsol_event = alc883_haier_w66_unsol_event,
 		.init_hook = alc883_haier_w66_automute,
 	},	
-	[ALC888_6ST_HP] = {
-		.mixers = { alc888_6st_hp_mixer, alc883_chmode_mixer },
-		.init_verbs = { alc883_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-		.dac_nids = alc883_dac_nids,
-		.dig_out_nid = ALC883_DIGOUT_NID,
-		.dig_in_nid = ALC883_DIGIN_NID,
-		.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
-		.channel_mode = alc883_sixstack_modes,
-		.input_mux = &alc883_capture_source,
-	},
 	[ALC888_3ST_HP] = {
 		.mixers = { alc888_3st_hp_mixer, alc883_chmode_mixer },
 		.init_verbs = { alc883_init_verbs, alc888_3st_hp_verbs },
-- 
cgit v1.2.3-70-g09d2


From f24dbdc61dd7ca6b97c525b40979ab7bd07c0934 Mon Sep 17 00:00:00 2001
From: Herton Ronaldo Krzesinski <herton@mandriva.com>
Date: Thu, 20 Mar 2008 12:14:28 +0100
Subject: [ALSA] hda-codec - Use base ALC883 mixer for 6stack-dell model

After DAC assignment fix in ALC883, alc888_6st_dell_mixer is now the
same as alc883_base_mixer. Avoid duplicated code and use
alc883_base_mixer in 6stack-dell model, removing alc888_6st_dell_mixer
definition.

Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c | 42 +-----------------------------------------
 1 file changed, 1 insertion(+), 41 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 15b4704539f..e1e96698299 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -6993,46 +6993,6 @@ static struct snd_kcontrol_new alc888_3st_hp_mixer[] = {
 	{ } /* end */
 };
 
-static struct snd_kcontrol_new alc888_6st_dell_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
-	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
-	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		/* .name = "Capture Source", */
-		.name = "Input Source",
-		.count = 2,
-		.info = alc883_mux_enum_info,
-		.get = alc883_mux_enum_get,
-		.put = alc883_mux_enum_put,
-	},
-	{ } /* end */
-};
-
 static struct snd_kcontrol_new alc883_acer_aspire_mixer[] = {
 	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
 	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
@@ -7942,7 +7902,7 @@ static struct alc_config_preset alc883_presets[] = {
 		.input_mux = &alc883_capture_source,
 	},
 	[ALC888_6ST_DELL] = {
-		.mixers = { alc888_6st_dell_mixer, alc883_chmode_mixer },
+		.mixers = { alc883_base_mixer, alc883_chmode_mixer },
 		.init_verbs = { alc883_init_verbs, alc888_6st_dell_verbs },
 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
 		.dac_nids = alc883_dac_nids,
-- 
cgit v1.2.3-70-g09d2


From eea6419ea18ed9dfc16f9a262e96cdb832376e88 Mon Sep 17 00:00:00 2001
From: Herton Ronaldo Krzesinski <herton@mandriva.com>
Date: Thu, 20 Mar 2008 12:14:59 +0100
Subject: [ALSA] hda-codec - Use common 3stack-6ch mixer for 3stack-hp model

Forgot one more: 3stack-hp model also have now the same mixer as
3stack-6ch (after DAC assignment fix in ALC883), so use it avoiding
duplicating the same mixer definition.

Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c | 42 ++----------------------------------------
 1 file changed, 2 insertions(+), 40 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index e1e96698299..198facf0178 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -6955,44 +6955,6 @@ static struct snd_kcontrol_new alc883_medion_md2_mixer[] = {
 	{ } /* end */
 };	
 
-static struct snd_kcontrol_new alc888_3st_hp_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
-	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
-	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		/* .name = "Capture Source", */
-		.name = "Input Source",
-		.count = 2,
-		.info = alc883_mux_enum_info,
-		.get = alc883_mux_enum_get,
-		.put = alc883_mux_enum_put,
-	},
-	{ } /* end */
-};
-
 static struct snd_kcontrol_new alc883_acer_aspire_mixer[] = {
 	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
 	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
@@ -7890,9 +7852,9 @@ static struct alc_config_preset alc883_presets[] = {
 		.input_mux = &alc883_capture_source,
 		.unsol_event = alc883_haier_w66_unsol_event,
 		.init_hook = alc883_haier_w66_automute,
-	},	
+	},
 	[ALC888_3ST_HP] = {
-		.mixers = { alc888_3st_hp_mixer, alc883_chmode_mixer },
+		.mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
 		.init_verbs = { alc883_init_verbs, alc888_3st_hp_verbs },
 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
 		.dac_nids = alc883_dac_nids,
-- 
cgit v1.2.3-70-g09d2


From 95866d38028c98ea4d6df6947f6ea3fd77334382 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Sat, 22 Mar 2008 10:11:08 +0100
Subject: [ALSA] ymfpci - Fix race at removal

free_irq() must be called first to avoid races at removal.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/ymfpci/ymfpci_main.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
index 42c1eb7d35f..29b3056c510 100644
--- a/sound/pci/ymfpci/ymfpci_main.c
+++ b/sound/pci/ymfpci/ymfpci_main.c
@@ -2249,6 +2249,8 @@ static int snd_ymfpci_free(struct snd_ymfpci *chip)
 #ifdef CONFIG_PM
 	vfree(chip->saved_regs);
 #endif
+	if (chip->irq >= 0)
+		free_irq(chip->irq, chip);
 	release_and_free_resource(chip->mpu_res);
 	release_and_free_resource(chip->fm_res);
 	snd_ymfpci_free_gameport(chip);
@@ -2257,8 +2259,6 @@ static int snd_ymfpci_free(struct snd_ymfpci *chip)
 	if (chip->work_ptr.area)
 		snd_dma_free_pages(&chip->work_ptr);
 	
-	if (chip->irq >= 0)
-		free_irq(chip->irq, chip);
 	release_and_free_resource(chip->res_reg_area);
 
 	pci_write_config_word(chip->pci, 0x40, chip->old_legacy_ctrl);
-- 
cgit v1.2.3-70-g09d2


From c81d80cbf6dfe4c061719cb146659677c3c36c8e Mon Sep 17 00:00:00 2001
From: Stas Sergeev <stsp@aknet.ru>
Date: Sat, 22 Mar 2008 10:12:37 +0100
Subject: [ALSA] pcsp: remove downsampling

pcsp: remove S16->U8 downsampling as dmix now supports U8 natively.

Signed-off-by: Stas Sergeev <stsp@aknet.ru>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/drivers/pcsp/pcsp_lib.c | 19 +++++--------------
 1 file changed, 5 insertions(+), 14 deletions(-)

(limited to 'sound')

diff --git a/sound/drivers/pcsp/pcsp_lib.c b/sound/drivers/pcsp/pcsp_lib.c
index 54253e9b4b0..ac6238e9351 100644
--- a/sound/drivers/pcsp/pcsp_lib.c
+++ b/sound/drivers/pcsp/pcsp_lib.c
@@ -18,8 +18,6 @@ module_param(nforce_wa, bool, 0444);
 MODULE_PARM_DESC(nforce_wa, "Apply NForce chipset workaround "
 		"(expect bad sound)");
 
-#define DMIX_WANTS_S16	1
-
 static void pcsp_start_timer(unsigned long dummy)
 {
 	hrtimer_start(&pcsp_chip.timer, ktime_set(0, 0), HRTIMER_MODE_REL);
@@ -49,7 +47,7 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle)
 {
 	unsigned long flags;
 	unsigned char timer_cnt, val;
-	int fmt_size, periods_elapsed;
+	int periods_elapsed;
 	u64 ns;
 	size_t period_bytes, buffer_bytes;
 	struct snd_pcm_substream *substream;
@@ -94,11 +92,8 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle)
 		goto exit_nr_unlock2;
 
 	runtime = substream->runtime;
-	fmt_size = snd_pcm_format_physical_width(runtime->format) >> 3;
-	/* assume it is mono! */
-	val = runtime->dma_area[chip->playback_ptr + fmt_size - 1];
-	if (snd_pcm_format_signed(runtime->format))
-		val ^= 0x80;
+	/* assume it is u8 mono */
+	val = runtime->dma_area[chip->playback_ptr];
 	timer_cnt = val * CUR_DIV() / 256;
 
 	if (timer_cnt && chip->enable) {
@@ -116,7 +111,7 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle)
 
 	period_bytes = snd_pcm_lib_period_bytes(substream);
 	buffer_bytes = snd_pcm_lib_buffer_bytes(substream);
-	chip->playback_ptr += PCSP_INDEX_INC() * fmt_size;
+	chip->playback_ptr += PCSP_INDEX_INC();
 	periods_elapsed = chip->playback_ptr - chip->period_ptr;
 	if (periods_elapsed < 0) {
 		printk(KERN_WARNING "PCSP: playback_ptr inconsistent "
@@ -275,11 +270,7 @@ static struct snd_pcm_hardware snd_pcsp_playback = {
 	.info = (SNDRV_PCM_INFO_INTERLEAVED |
 		 SNDRV_PCM_INFO_HALF_DUPLEX |
 		 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),
-	.formats = (SNDRV_PCM_FMTBIT_U8
-#if DMIX_WANTS_S16
-		    | SNDRV_PCM_FMTBIT_S16_LE
-#endif
-	    ),
+	.formats = SNDRV_PCM_FMTBIT_U8,
 	.rates = SNDRV_PCM_RATE_KNOT,
 	.rate_min = PCSP_DEFAULT_SRATE,
 	.rate_max = PCSP_DEFAULT_SRATE,
-- 
cgit v1.2.3-70-g09d2


From 213f0bfe9061e077590f2775cb90c1e6c0c9faa6 Mon Sep 17 00:00:00 2001
From: Herton Ronaldo Krzesinski <herton@mandriva.com>
Date: Sat, 22 Mar 2008 10:25:30 +0100
Subject: [ALSA] hda-codec - Map clevo-m720r ALC883 model for Clevo M720SR

Map clevo-m720r ALC883 model for Clevo M720SR.

Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c | 1 +
 1 file changed, 1 insertion(+)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 198facf0178..e137882d945 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -7650,6 +7650,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
 	SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG),
 	SND_PCI_QUIRK(0x147b, 0x1083, "Abit IP35-PRO", ALC883_6ST_DIG),
 	SND_PCI_QUIRK(0x1558, 0x0721, "Clevo laptop M720R", ALC883_CLEVO_M720R),
+	SND_PCI_QUIRK(0x1558, 0x0722, "Clevo laptop M720SR", ALC883_CLEVO_M720R),
 	SND_PCI_QUIRK(0x1558, 0, "Clevo laptop", ALC883_LAPTOP_EAPD),
 	SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch),
 	SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION),
-- 
cgit v1.2.3-70-g09d2


From 0c4cc4430f40089bb85557e309038faa458247f1 Mon Sep 17 00:00:00 2001
From: Herton Ronaldo Krzesinski <herton@mandriva.com>
Date: Sat, 22 Mar 2008 10:26:05 +0100
Subject: [ALSA] hda-codec - Support mic automute for Clevo M720R/SR

Add support for mic automute in clevo-m720r ALC883 model, and rename it
to more generic clevo-m720. Also change model entry in ALSA-Configuration.txt
accordingly.

Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 Documentation/sound/alsa/ALSA-Configuration.txt |  2 +-
 sound/pci/hda/patch_realtek.c                   | 53 ++++++++++++++++++-------
 2 files changed, 39 insertions(+), 16 deletions(-)

(limited to 'sound')

diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 3eea0675ebb..08256fcb274 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -886,7 +886,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
 	  3stack-hp	HP machines with 3stack (Lucknow, Samba boards)
 	  6stack-dell	Dell machines with 6stack (Inspiron 530)
 	  mitac		Mitac 8252D
-	  clevo-m720r	Clevo laptop M720R
+	  clevo-m720	Clevo M720 laptop series
 	  fujitsu-pi2515 Fujitsu AMILO Pi2515
 	  auto		auto-config reading BIOS (default)
 
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index e137882d945..e5d97c12381 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -201,7 +201,7 @@ enum {
 	ALC888_3ST_HP,
 	ALC888_6ST_DELL,
 	ALC883_MITAC,
-	ALC883_CLEVO_M720R,
+	ALC883_CLEVO_M720,
 	ALC883_FUJITSU_PI2515,
 	ALC883_AUTO,
 	ALC883_MODEL_LAST,
@@ -6661,7 +6661,7 @@ static struct snd_kcontrol_new alc883_mitac_mixer[] = {
 	{ } /* end */
 };
 
-static struct snd_kcontrol_new alc883_clevo_m720r_mixer[] = {
+static struct snd_kcontrol_new alc883_clevo_m720_mixer[] = {
 	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
 	HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
 	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
@@ -7130,7 +7130,7 @@ static struct hda_verb alc883_mitac_verbs[] = {
 	{ } /* end */
 };
 
-static struct hda_verb alc883_clevo_m720r_verbs[] = {
+static struct hda_verb alc883_clevo_m720_verbs[] = {
 	/* HP */
 	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
 	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
@@ -7140,6 +7140,7 @@ static struct hda_verb alc883_clevo_m720r_verbs[] = {
 
 	/* enable unsolicited event */
 	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
+	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
 
 	{ } /* end */
 };
@@ -7330,7 +7331,7 @@ static void alc883_tagra_unsol_event(struct hda_codec *codec, unsigned int res)
 }
 
 /* toggle speaker-output according to the hp-jack state */
-static void alc883_clevo_m720r_automute(struct hda_codec *codec)
+static void alc883_clevo_m720_hp_automute(struct hda_codec *codec)
 {
 	unsigned int present;
 	unsigned char bits;
@@ -7342,11 +7343,33 @@ static void alc883_clevo_m720r_automute(struct hda_codec *codec)
 				 HDA_AMP_MUTE, bits);
 }
 
-static void alc883_clevo_m720r_unsol_event(struct hda_codec *codec,
+static void alc883_clevo_m720_mic_automute(struct hda_codec *codec)
+{
+	unsigned int present;
+
+	present = snd_hda_codec_read(codec, 0x18, 0,
+				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+	snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1,
+				 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+}
+
+static void alc883_clevo_m720_automute(struct hda_codec *codec)
+{
+	alc883_clevo_m720_hp_automute(codec);
+	alc883_clevo_m720_mic_automute(codec);
+}
+
+static void alc883_clevo_m720_unsol_event(struct hda_codec *codec,
 					   unsigned int res)
 {
-	if ((res >> 26) == ALC880_HP_EVENT)
-		alc883_clevo_m720r_automute(codec);
+	switch (res >> 26) {
+	case ALC880_HP_EVENT:
+		alc883_clevo_m720_hp_automute(codec);
+		break;
+	case ALC880_MIC_EVENT:
+		alc883_clevo_m720_mic_automute(codec);
+		break;
+	}
 }
 
 /* toggle speaker-output according to the hp-jack state */
@@ -7605,7 +7628,7 @@ static const char *alc883_models[ALC883_MODEL_LAST] = {
 	[ALC888_3ST_HP]		= "3stack-hp",
 	[ALC888_6ST_DELL]	= "6stack-dell",
 	[ALC883_MITAC]		= "mitac",
-	[ALC883_CLEVO_M720R]	= "clevo-m720r",
+	[ALC883_CLEVO_M720]	= "clevo-m720",
 	[ALC883_FUJITSU_PI2515] = "fujitsu-pi2515",
 	[ALC883_AUTO]		= "auto",
 };
@@ -7649,8 +7672,8 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
 	SND_PCI_QUIRK(0x1462, 0x7327, "MSI", ALC883_6ST_DIG),
 	SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG),
 	SND_PCI_QUIRK(0x147b, 0x1083, "Abit IP35-PRO", ALC883_6ST_DIG),
-	SND_PCI_QUIRK(0x1558, 0x0721, "Clevo laptop M720R", ALC883_CLEVO_M720R),
-	SND_PCI_QUIRK(0x1558, 0x0722, "Clevo laptop M720SR", ALC883_CLEVO_M720R),
+	SND_PCI_QUIRK(0x1558, 0x0721, "Clevo laptop M720R", ALC883_CLEVO_M720),
+	SND_PCI_QUIRK(0x1558, 0x0722, "Clevo laptop M720SR", ALC883_CLEVO_M720),
 	SND_PCI_QUIRK(0x1558, 0, "Clevo laptop", ALC883_LAPTOP_EAPD),
 	SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch),
 	SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION),
@@ -7794,17 +7817,17 @@ static struct alc_config_preset alc883_presets[] = {
 		.channel_mode = alc883_3ST_2ch_modes,
 		.input_mux = &alc883_capture_source,
 	},
-	[ALC883_CLEVO_M720R] = {
-		.mixers = { alc883_clevo_m720r_mixer },
-		.init_verbs = { alc883_init_verbs, alc883_clevo_m720r_verbs },
+	[ALC883_CLEVO_M720] = {
+		.mixers = { alc883_clevo_m720_mixer },
+		.init_verbs = { alc883_init_verbs, alc883_clevo_m720_verbs },
 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
 		.dac_nids = alc883_dac_nids,
 		.dig_out_nid = ALC883_DIGOUT_NID,
 		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
 		.channel_mode = alc883_3ST_2ch_modes,
 		.input_mux = &alc883_capture_source,
-		.unsol_event = alc883_clevo_m720r_unsol_event,
-		.init_hook = alc883_clevo_m720r_automute,
+		.unsol_event = alc883_clevo_m720_unsol_event,
+		.init_hook = alc883_clevo_m720_automute,
 	},
 	[ALC883_LENOVO_101E_2ch] = {
 		.mixers = { alc883_lenovo_101e_2ch_mixer},
-- 
cgit v1.2.3-70-g09d2


From e97f79994ac715e4c8724b201bd3328463ec9314 Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Tue, 1 Apr 2008 10:02:18 +0200
Subject: [ALSA] oxygen: fix line-in recording selection (now for real)

On C-Media cards, the GPIO pin 0 of the CM9780 must be handled exactly
like on Xonar cards, so move the Xonar code to the common mixer code.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/oxygen/oxygen.c       | 33 -------------------------
 sound/pci/oxygen/oxygen.h       |  2 --
 sound/pci/oxygen/oxygen_lib.c   |  2 ++
 sound/pci/oxygen/oxygen_mixer.c | 33 +++++++++++++++++++++----
 sound/pci/oxygen/virtuoso.c     | 53 -----------------------------------------
 5 files changed, 31 insertions(+), 92 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c
index 511ef34a43c..b3b7771b54c 100644
--- a/sound/pci/oxygen/oxygen.c
+++ b/sound/pci/oxygen/oxygen.c
@@ -39,7 +39,6 @@
 #include <sound/tlv.h>
 #include "oxygen.h"
 #include "ak4396.h"
-#include "cm9780.h"
 #include "wm8785.h"
 
 MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
@@ -79,8 +78,6 @@ MODULE_DEVICE_TABLE(pci, oxygen_ids);
 #define GPIO_AK5385_DFS_DOUBLE	0x0001
 #define GPIO_AK5385_DFS_QUAD	0x0002
 
-#define GPIO_LINE_MUTE		CM9780_GPO0
-
 struct generic_data {
 	u8 ak4396_ctl2;
 };
@@ -145,23 +142,16 @@ static void wm8785_init(struct oxygen *chip)
 	snd_component_add(chip->card, "WM8785");
 }
 
-static void cmi9780_init(struct oxygen *chip)
-{
-	oxygen_ac97_clear_bits(chip, 0, CM9780_GPIO_STATUS, GPIO_LINE_MUTE);
-}
-
 static void generic_init(struct oxygen *chip)
 {
 	ak4396_init(chip);
 	wm8785_init(chip);
-	cmi9780_init(chip);
 }
 
 static void meridian_init(struct oxygen *chip)
 {
 	ak4396_init(chip);
 	ak5385_init(chip);
-	cmi9780_init(chip);
 }
 
 static void generic_cleanup(struct oxygen *chip)
@@ -257,27 +247,6 @@ static void set_ak5385_params(struct oxygen *chip,
 			      value, GPIO_AK5385_DFS_MASK);
 }
 
-static void cmi9780_switch_hook(struct oxygen *chip, unsigned int codec,
-				unsigned int reg, int mute)
-{
-	if (codec != 0)
-		return;
-	switch (reg) {
-	case AC97_LINE:
-		oxygen_write_ac97_masked(chip, 0, CM9780_GPIO_STATUS,
-					 mute ? GPIO_LINE_MUTE : 0,
-					 GPIO_LINE_MUTE);
-		break;
-	case AC97_MIC:
-	case AC97_CD:
-	case AC97_AUX:
-		if (!mute)
-			oxygen_ac97_set_bits(chip, 0, CM9780_GPIO_STATUS,
-					     GPIO_LINE_MUTE);
-		break;
-	}
-}
-
 static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0);
 
 static int ak4396_control_filter(struct snd_kcontrol_new *template)
@@ -301,7 +270,6 @@ static const struct oxygen_model model_generic = {
 	.set_adc_params = set_wm8785_params,
 	.update_dac_volume = update_ak4396_volume,
 	.update_dac_mute = update_ak4396_mute,
-	.ac97_switch_hook = cmi9780_switch_hook,
 	.model_data_size = sizeof(struct generic_data),
 	.pcm_dev_cfg = PLAYBACK_0_TO_I2S |
 		       PLAYBACK_1_TO_SPDIF |
@@ -327,7 +295,6 @@ static const struct oxygen_model model_meridian = {
 	.set_adc_params = set_ak5385_params,
 	.update_dac_volume = update_ak4396_volume,
 	.update_dac_mute = update_ak4396_mute,
-	.ac97_switch_hook = cmi9780_switch_hook,
 	.model_data_size = sizeof(struct generic_data),
 	.pcm_dev_cfg = PLAYBACK_0_TO_I2S |
 		       PLAYBACK_1_TO_SPDIF |
diff --git a/sound/pci/oxygen/oxygen.h b/sound/pci/oxygen/oxygen.h
index 5103482f65e..2f25c8dbaf8 100644
--- a/sound/pci/oxygen/oxygen.h
+++ b/sound/pci/oxygen/oxygen.h
@@ -97,8 +97,6 @@ struct oxygen_model {
 			       struct snd_pcm_hw_params *params);
 	void (*update_dac_volume)(struct oxygen *chip);
 	void (*update_dac_mute)(struct oxygen *chip);
-	void (*ac97_switch_hook)(struct oxygen *chip, unsigned int codec,
-				 unsigned int reg, int mute);
 	void (*gpio_changed)(struct oxygen *chip);
 	size_t model_data_size;
 	unsigned int pcm_dev_cfg;
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c
index 858e6d4c919..4f3d9e5fc5d 100644
--- a/sound/pci/oxygen/oxygen_lib.c
+++ b/sound/pci/oxygen/oxygen_lib.c
@@ -360,6 +360,8 @@ static void oxygen_init(struct oxygen *chip)
 		oxygen_write_ac97(chip, 0, AC97_REC_GAIN, 0x8000);
 		oxygen_write_ac97(chip, 0, AC97_CENTER_LFE_MASTER, 0x8080);
 		oxygen_write_ac97(chip, 0, AC97_SURROUND_MASTER, 0x8080);
+		oxygen_ac97_clear_bits(chip, 0, CM9780_GPIO_STATUS,
+				       CM9780_GPO0);
 		/* power down unused ADCs and DACs */
 		oxygen_ac97_set_bits(chip, 0, AC97_POWERDOWN,
 				     AC97_PD_PR0 | AC97_PD_PR1);
diff --git a/sound/pci/oxygen/oxygen_mixer.c b/sound/pci/oxygen/oxygen_mixer.c
index 6b5ff6e0fad..9a7c880eddb 100644
--- a/sound/pci/oxygen/oxygen_mixer.c
+++ b/sound/pci/oxygen/oxygen_mixer.c
@@ -510,6 +510,19 @@ static int ac97_switch_get(struct snd_kcontrol *ctl,
 	return 0;
 }
 
+static void mute_ac97_ctl(struct oxygen *chip, unsigned int control)
+{
+	unsigned int priv_idx = chip->controls[control]->private_value & 0xff;
+	u16 value;
+
+	value = oxygen_read_ac97(chip, 0, priv_idx);
+	if (!(value & 0x8000)) {
+		oxygen_write_ac97(chip, 0, priv_idx, value | 0x8000);
+		snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
+			       &chip->controls[control]->id);
+	}
+}
+
 static int ac97_switch_put(struct snd_kcontrol *ctl,
 			   struct snd_ctl_elem_value *value)
 {
@@ -531,9 +544,22 @@ static int ac97_switch_put(struct snd_kcontrol *ctl,
 	change = newreg != oldreg;
 	if (change) {
 		oxygen_write_ac97(chip, codec, index, newreg);
-		if (bitnr == 15 && chip->model->ac97_switch_hook)
-			chip->model->ac97_switch_hook(chip, codec, index,
-						      newreg & 0x8000);
+		if (index == AC97_LINE) {
+			oxygen_write_ac97_masked(chip, 0, CM9780_GPIO_STATUS,
+						 newreg & 0x8000 ?
+						 CM9780_GPO0 : 0, CM9780_GPO0);
+			if (!(newreg & 0x8000)) {
+				mute_ac97_ctl(chip, CONTROL_MIC_CAPTURE_SWITCH);
+				mute_ac97_ctl(chip, CONTROL_CD_CAPTURE_SWITCH);
+				mute_ac97_ctl(chip, CONTROL_AUX_CAPTURE_SWITCH);
+			}
+		} else if ((index == AC97_MIC || index == AC97_CD ||
+			    index == AC97_VIDEO || index == AC97_AUX) &&
+			   bitnr == 15 && !(newreg & 0x8000)) {
+			mute_ac97_ctl(chip, CONTROL_LINE_CAPTURE_SWITCH);
+			oxygen_write_ac97_masked(chip, 0, CM9780_GPIO_STATUS,
+						 CM9780_GPO0, CM9780_GPO0);
+		}
 	}
 	mutex_unlock(&chip->mutex);
 	return change;
@@ -849,7 +875,6 @@ static const struct snd_kcontrol_new ac97_controls[] = {
 	AC97_VOLUME("Mic Capture Volume", 0, AC97_MIC),
 	AC97_SWITCH("Mic Capture Switch", 0, AC97_MIC, 15, 1),
 	AC97_SWITCH("Mic Boost (+20dB)", 0, AC97_MIC, 6, 0),
-	AC97_VOLUME("Line Capture Volume", 0, AC97_LINE),
 	AC97_SWITCH("Line Capture Switch", 0, AC97_LINE, 15, 1),
 	AC97_VOLUME("CD Capture Volume", 0, AC97_CD),
 	AC97_SWITCH("CD Capture Switch", 0, AC97_CD, 15, 1),
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
index fa79db696e2..2c3daf3ae4c 100644
--- a/sound/pci/oxygen/virtuoso.c
+++ b/sound/pci/oxygen/virtuoso.c
@@ -30,10 +30,6 @@
  * GPIO 5 <- external power present (D2X only)
  * GPIO 7 -> ALT
  * GPIO 8 -> enable output to speakers
- *
- * CM9780:
- *
- * GPIO 0 -> enable AC'97 bypass (line in -> ADC)
  */
 
 #include <linux/pci.h>
@@ -81,8 +77,6 @@ MODULE_DEVICE_TABLE(pci, xonar_ids);
 #define GPIO_ALT		0x0080
 #define GPIO_OUTPUT_ENABLE	0x0100
 
-#define GPIO_LINE_MUTE		CM9780_GPO0
-
 struct xonar_data {
 	u8 is_d2x;
 	u8 has_power;
@@ -134,7 +128,6 @@ static void xonar_init(struct oxygen *chip)
 				     & GPIO_EXT_POWER);
 	}
 	oxygen_ac97_set_bits(chip, 0, CM9780_JACK, CM9780_FMIC2MIC);
-	oxygen_ac97_clear_bits(chip, 0, CM9780_GPIO_STATUS, GPIO_LINE_MUTE);
 	msleep(300);
 	oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_OUTPUT_ENABLE);
 	oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_OUTPUT_ENABLE);
@@ -219,49 +212,6 @@ static void xonar_gpio_changed(struct oxygen *chip)
 	}
 }
 
-static void mute_ac97_ctl(struct oxygen *chip, unsigned int control)
-{
-	unsigned int priv_idx = chip->controls[control]->private_value & 0xff;
-	u16 value;
-
-	value = oxygen_read_ac97(chip, 0, priv_idx);
-	if (!(value & 0x8000)) {
-		oxygen_write_ac97(chip, 0, priv_idx, value | 0x8000);
-		snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
-			       &chip->controls[control]->id);
-	}
-}
-
-static void xonar_ac97_switch_hook(struct oxygen *chip, unsigned int codec,
-				   unsigned int reg, int mute)
-{
-	if (codec != 0)
-		return;
-	/* line-in is exclusive */
-	switch (reg) {
-	case AC97_LINE:
-		oxygen_write_ac97_masked(chip, 0, CM9780_GPIO_STATUS,
-					 mute ? GPIO_LINE_MUTE : 0,
-					 GPIO_LINE_MUTE);
-		if (!mute) {
-			mute_ac97_ctl(chip, CONTROL_MIC_CAPTURE_SWITCH);
-			mute_ac97_ctl(chip, CONTROL_CD_CAPTURE_SWITCH);
-			mute_ac97_ctl(chip, CONTROL_AUX_CAPTURE_SWITCH);
-		}
-		break;
-	case AC97_MIC:
-	case AC97_CD:
-	case AC97_VIDEO:
-	case AC97_AUX:
-		if (!mute) {
-			oxygen_ac97_set_bits(chip, 0, CM9780_GPIO_STATUS,
-					     GPIO_LINE_MUTE);
-			mute_ac97_ctl(chip, CONTROL_LINE_CAPTURE_SWITCH);
-		}
-		break;
-	}
-}
-
 static int pcm1796_volume_info(struct snd_kcontrol *ctl,
 			       struct snd_ctl_elem_info *info)
 {
@@ -321,8 +271,6 @@ static int xonar_control_filter(struct snd_kcontrol_new *template)
 	} else if (!strncmp(template->name, "CD Capture ", 11)) {
 		/* CD in is actually connected to the video in pin */
 		template->private_value ^= AC97_CD ^ AC97_VIDEO;
-	} else if (!strcmp(template->name, "Line Capture Volume")) {
-		return 1; /* line-in bypasses the AC'97 mixer */
 	}
 	return 0;
 }
@@ -345,7 +293,6 @@ static const struct oxygen_model model_xonar = {
 	.set_adc_params = set_cs5381_params,
 	.update_dac_volume = update_pcm1796_volume,
 	.update_dac_mute = update_pcm1796_mute,
-	.ac97_switch_hook = xonar_ac97_switch_hook,
 	.gpio_changed = xonar_gpio_changed,
 	.model_data_size = sizeof(struct xonar_data),
 	.pcm_dev_cfg = PLAYBACK_0_TO_I2S |
-- 
cgit v1.2.3-70-g09d2


From 7a4356747298d1c899a12a25260d5ff1b4feeb5e Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Wed, 2 Apr 2008 10:56:30 +0200
Subject: [ALSA] aw2: remove duplicate MODULE_LICENSE

"GPL 2" does not mean that there have to be two MODULE_LICENSE("GPL")
entries.  ;-)

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/aw2/aw2-alsa.c | 1 -
 1 file changed, 1 deletion(-)

(limited to 'sound')

diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c
index 12d01c9c663..56f87cd33c1 100644
--- a/sound/pci/aw2/aw2-alsa.c
+++ b/sound/pci/aw2/aw2-alsa.c
@@ -36,7 +36,6 @@
 #include "saa7146.h"
 #include "aw2-saa7146.h"
 
-MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Cedric Bregardis <cedric.bregardis@free.fr>, "
 	      "Jean-Christian Hassler <jhassler@free.fr>");
 MODULE_DESCRIPTION("Emagic Audiowerk 2 sound driver");
-- 
cgit v1.2.3-70-g09d2


From 10e6d5f9b6edd4a12d678716d7fdb94278a83227 Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Mon, 7 Apr 2008 10:23:37 +0200
Subject: [ALSA] oxygen: add I2C support

Add a function to write I2C registers.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/oxygen/oxygen.h    |  1 +
 sound/pci/oxygen/oxygen_io.c | 23 +++++++++++++++++++++--
 2 files changed, 22 insertions(+), 2 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/oxygen/oxygen.h b/sound/pci/oxygen/oxygen.h
index 2f25c8dbaf8..d53c18c6fcd 100644
--- a/sound/pci/oxygen/oxygen.h
+++ b/sound/pci/oxygen/oxygen.h
@@ -146,6 +146,7 @@ void oxygen_write_ac97_masked(struct oxygen *chip, unsigned int codec,
 			      unsigned int index, u16 data, u16 mask);
 
 void oxygen_write_spi(struct oxygen *chip, u8 control, unsigned int data);
+void oxygen_write_i2c(struct oxygen *chip, u8 device, u8 map, u8 data);
 
 static inline void oxygen_set_bits8(struct oxygen *chip,
 				    unsigned int reg, u8 value)
diff --git a/sound/pci/oxygen/oxygen_io.c b/sound/pci/oxygen/oxygen_io.c
index 74e23ef9c94..5569606ee87 100644
--- a/sound/pci/oxygen/oxygen_io.c
+++ b/sound/pci/oxygen/oxygen_io.c
@@ -190,12 +190,31 @@ void oxygen_write_spi(struct oxygen *chip, u8 control, unsigned int data)
 		--count;
 	}
 
-	spin_lock_irq(&chip->reg_lock);
 	oxygen_write8(chip, OXYGEN_SPI_DATA1, data);
 	oxygen_write8(chip, OXYGEN_SPI_DATA2, data >> 8);
 	if (control & OXYGEN_SPI_DATA_LENGTH_3)
 		oxygen_write8(chip, OXYGEN_SPI_DATA3, data >> 16);
 	oxygen_write8(chip, OXYGEN_SPI_CONTROL, control);
-	spin_unlock_irq(&chip->reg_lock);
 }
 EXPORT_SYMBOL(oxygen_write_spi);
+
+void oxygen_write_i2c(struct oxygen *chip, u8 device, u8 map, u8 data)
+{
+	unsigned long timeout;
+
+	/* should not need more than about 300 us */
+	timeout = jiffies + msecs_to_jiffies(1);
+	do {
+		if (!(oxygen_read16(chip, OXYGEN_2WIRE_BUS_STATUS)
+		      & OXYGEN_2WIRE_BUSY))
+			break;
+		udelay(1);
+		cond_resched();
+	} while (time_after_eq(timeout, jiffies));
+
+	oxygen_write8(chip, OXYGEN_2WIRE_MAP, map);
+	oxygen_write8(chip, OXYGEN_2WIRE_DATA, data);
+	oxygen_write8(chip, OXYGEN_2WIRE_CONTROL,
+		      device | OXYGEN_2WIRE_DIR_WRITE);
+}
+EXPORT_SYMBOL(oxygen_write_i2c);
-- 
cgit v1.2.3-70-g09d2


From 271ebfca5823875cc4f134515b6c3887d99b8dc2 Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Mon, 7 Apr 2008 10:24:22 +0200
Subject: [ALSA] virtuoso: separate D2/D2X init functions

Use separate model structures for the D2 and D2X so that the init
function does not have to check for the model again.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/oxygen/virtuoso.c | 118 +++++++++++++++++++++++++++-----------------
 1 file changed, 74 insertions(+), 44 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
index 2c3daf3ae4c..b3259fa0a0b 100644
--- a/sound/pci/oxygen/virtuoso.c
+++ b/sound/pci/oxygen/virtuoso.c
@@ -61,9 +61,14 @@ MODULE_PARM_DESC(id, "ID string");
 module_param_array(enable, bool, NULL, 0444);
 MODULE_PARM_DESC(enable, "enable card");
 
+enum {
+	MODEL_D2,
+	MODEL_D2X,
+};
+
 static struct pci_device_id xonar_ids[] __devinitdata = {
-	{ OXYGEN_PCI_SUBID(0x1043, 0x8269) }, /* Asus Xonar D2 */
-	{ OXYGEN_PCI_SUBID(0x1043, 0x82b7) }, /* Asus Xonar D2X */
+	{ OXYGEN_PCI_SUBID(0x1043, 0x8269), .driver_data = MODEL_D2 },
+	{ OXYGEN_PCI_SUBID(0x1043, 0x82b7), .driver_data = MODEL_D2X },
 	{ }
 };
 MODULE_DEVICE_TABLE(pci, xonar_ids);
@@ -78,7 +83,6 @@ MODULE_DEVICE_TABLE(pci, xonar_ids);
 #define GPIO_OUTPUT_ENABLE	0x0100
 
 struct xonar_data {
-	u8 is_d2x;
 	u8 has_power;
 };
 
@@ -97,13 +101,10 @@ static void pcm1796_write(struct oxygen *chip, unsigned int codec,
 			 (reg << 8) | value);
 }
 
-static void xonar_init(struct oxygen *chip)
+static void xonar_d2_init(struct oxygen *chip)
 {
-	struct xonar_data *data = chip->model_data;
 	unsigned int i;
 
-	data->is_d2x = chip->pci->subsystem_device == 0x82b7;
-
 	for (i = 0; i < 4; ++i) {
 		pcm1796_write(chip, i, 18, PCM1796_FMT_24_LJUST | PCM1796_ATLD);
 		pcm1796_write(chip, i, 19, PCM1796_FLT_SHARP | PCM1796_ATS_1);
@@ -118,15 +119,6 @@ static void xonar_init(struct oxygen *chip)
 	oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
 			      GPIO_CS5381_M_SINGLE,
 			      GPIO_CS5381_M_MASK | GPIO_ALT);
-	if (data->is_d2x) {
-		oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL,
-				    GPIO_EXT_POWER);
-		oxygen_set_bits16(chip, OXYGEN_GPIO_INTERRUPT_MASK,
-				  GPIO_EXT_POWER);
-		chip->interrupt_mask |= OXYGEN_INT_GPIO;
-		data->has_power = !!(oxygen_read16(chip, OXYGEN_GPIO_DATA)
-				     & GPIO_EXT_POWER);
-	}
 	oxygen_ac97_set_bits(chip, 0, CM9780_JACK, CM9780_FMIC2MIC);
 	msleep(300);
 	oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_OUTPUT_ENABLE);
@@ -136,6 +128,18 @@ static void xonar_init(struct oxygen *chip)
 	snd_component_add(chip->card, "CS5381");
 }
 
+static void xonar_d2x_init(struct oxygen *chip)
+{
+	struct xonar_data *data = chip->model_data;
+
+	xonar_d2_init(chip);
+	oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_EXT_POWER);
+	oxygen_set_bits16(chip, OXYGEN_GPIO_INTERRUPT_MASK, GPIO_EXT_POWER);
+	chip->interrupt_mask |= OXYGEN_INT_GPIO;
+	data->has_power = !!(oxygen_read16(chip, OXYGEN_GPIO_DATA)
+			     & GPIO_EXT_POWER);
+}
+
 static void xonar_cleanup(struct oxygen *chip)
 {
 	oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_OUTPUT_ENABLE);
@@ -196,8 +200,6 @@ static void xonar_gpio_changed(struct oxygen *chip)
 	struct xonar_data *data = chip->model_data;
 	u8 has_power;
 
-	if (!data->is_d2x)
-		return;
 	has_power = !!(oxygen_read16(chip, OXYGEN_GPIO_DATA)
 		       & GPIO_EXT_POWER);
 	if (has_power != data->has_power) {
@@ -280,31 +282,58 @@ static int xonar_mixer_init(struct oxygen *chip)
 	return snd_ctl_add(chip->card, snd_ctl_new1(&alt_switch, chip));
 }
 
-static const struct oxygen_model model_xonar = {
-	.shortname = "Asus AV200",
-	.longname = "Asus Virtuoso 200",
-	.chip = "AV200",
-	.owner = THIS_MODULE,
-	.init = xonar_init,
-	.control_filter = xonar_control_filter,
-	.mixer_init = xonar_mixer_init,
-	.cleanup = xonar_cleanup,
-	.set_dac_params = set_pcm1796_params,
-	.set_adc_params = set_cs5381_params,
-	.update_dac_volume = update_pcm1796_volume,
-	.update_dac_mute = update_pcm1796_mute,
-	.gpio_changed = xonar_gpio_changed,
-	.model_data_size = sizeof(struct xonar_data),
-	.pcm_dev_cfg = PLAYBACK_0_TO_I2S |
-		       PLAYBACK_1_TO_SPDIF |
-		       CAPTURE_0_FROM_I2S_2 |
-		       CAPTURE_1_FROM_SPDIF,
-	.dac_channels = 8,
-	.misc_flags = OXYGEN_MISC_MIDI,
-	.function_flags = OXYGEN_FUNCTION_SPI |
-			  OXYGEN_FUNCTION_ENABLE_SPI_4_5,
-	.dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
-	.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
+static const struct oxygen_model xonar_models[] = {
+	[MODEL_D2] = {
+		.shortname = "Asus AV200",
+		.longname = "Asus Virtuoso 200",
+		.chip = "AV200",
+		.owner = THIS_MODULE,
+		.init = xonar_d2_init,
+		.control_filter = xonar_control_filter,
+		.mixer_init = xonar_mixer_init,
+		.cleanup = xonar_cleanup,
+		.set_dac_params = set_pcm1796_params,
+		.set_adc_params = set_cs5381_params,
+		.update_dac_volume = update_pcm1796_volume,
+		.update_dac_mute = update_pcm1796_mute,
+		.model_data_size = sizeof(struct xonar_data),
+		.pcm_dev_cfg = PLAYBACK_0_TO_I2S |
+			       PLAYBACK_1_TO_SPDIF |
+			       CAPTURE_0_FROM_I2S_2 |
+			       CAPTURE_1_FROM_SPDIF,
+		.dac_channels = 8,
+		.misc_flags = OXYGEN_MISC_MIDI,
+		.function_flags = OXYGEN_FUNCTION_SPI |
+				  OXYGEN_FUNCTION_ENABLE_SPI_4_5,
+		.dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
+		.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
+	},
+	[MODEL_D2X] = {
+		.shortname = "Asus AV200",
+		.longname = "Asus Virtuoso 200",
+		.chip = "AV200",
+		.owner = THIS_MODULE,
+		.init = xonar_d2x_init,
+		.control_filter = xonar_control_filter,
+		.mixer_init = xonar_mixer_init,
+		.cleanup = xonar_cleanup,
+		.set_dac_params = set_pcm1796_params,
+		.set_adc_params = set_cs5381_params,
+		.update_dac_volume = update_pcm1796_volume,
+		.update_dac_mute = update_pcm1796_mute,
+		.gpio_changed = xonar_gpio_changed,
+		.model_data_size = sizeof(struct xonar_data),
+		.pcm_dev_cfg = PLAYBACK_0_TO_I2S |
+			       PLAYBACK_1_TO_SPDIF |
+			       CAPTURE_0_FROM_I2S_2 |
+			       CAPTURE_1_FROM_SPDIF,
+		.dac_channels = 8,
+		.misc_flags = OXYGEN_MISC_MIDI,
+		.function_flags = OXYGEN_FUNCTION_SPI |
+				  OXYGEN_FUNCTION_ENABLE_SPI_4_5,
+		.dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
+		.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
+	},
 };
 
 static int __devinit xonar_probe(struct pci_dev *pci,
@@ -319,7 +348,8 @@ static int __devinit xonar_probe(struct pci_dev *pci,
 		++dev;
 		return -ENOENT;
 	}
-	err = oxygen_pci_probe(pci, index[dev], id[dev], &model_xonar);
+	err = oxygen_pci_probe(pci, index[dev], id[dev],
+			       &xonar_models[pci_id->driver_data]);
 	if (err >= 0)
 		++dev;
 	return err;
-- 
cgit v1.2.3-70-g09d2


From a694a6a0e4ab4752d1a145b9b32e231d7c9611b5 Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Mon, 7 Apr 2008 10:25:30 +0200
Subject: [ALSA] virtuoso: allow both CS5381 and CS5361

Rename all CS5381 symbols to CS53x1 because they can also be used for
Xonar models with a CS5361.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/oxygen/virtuoso.c | 29 +++++++++++++++--------------
 1 file changed, 15 insertions(+), 14 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
index b3259fa0a0b..1627197f168 100644
--- a/sound/pci/oxygen/virtuoso.c
+++ b/sound/pci/oxygen/virtuoso.c
@@ -74,10 +74,11 @@ static struct pci_device_id xonar_ids[] __devinitdata = {
 MODULE_DEVICE_TABLE(pci, xonar_ids);
 
 
-#define GPIO_CS5381_M_MASK	0x000c
-#define GPIO_CS5381_M_SINGLE	0x0000
-#define GPIO_CS5381_M_DOUBLE	0x0004
-#define GPIO_CS5381_M_QUAD	0x0008
+#define GPIO_CS53x1_M_MASK	0x000c
+#define GPIO_CS53x1_M_SINGLE	0x0000
+#define GPIO_CS53x1_M_DOUBLE	0x0004
+#define GPIO_CS53x1_M_QUAD	0x0008
+
 #define GPIO_EXT_POWER		0x0020
 #define GPIO_ALT		0x0080
 #define GPIO_OUTPUT_ENABLE	0x0100
@@ -115,10 +116,10 @@ static void xonar_d2_init(struct oxygen *chip)
 	}
 
 	oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
-			  GPIO_CS5381_M_MASK | GPIO_ALT);
+			  GPIO_CS53x1_M_MASK | GPIO_ALT);
 	oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
-			      GPIO_CS5381_M_SINGLE,
-			      GPIO_CS5381_M_MASK | GPIO_ALT);
+			      GPIO_CS53x1_M_SINGLE,
+			      GPIO_CS53x1_M_MASK | GPIO_ALT);
 	oxygen_ac97_set_bits(chip, 0, CM9780_JACK, CM9780_FMIC2MIC);
 	msleep(300);
 	oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_OUTPUT_ENABLE);
@@ -180,19 +181,19 @@ static void update_pcm1796_mute(struct oxygen *chip)
 		pcm1796_write(chip, i, 18, value);
 }
 
-static void set_cs5381_params(struct oxygen *chip,
+static void set_cs53x1_params(struct oxygen *chip,
 			      struct snd_pcm_hw_params *params)
 {
 	unsigned int value;
 
 	if (params_rate(params) <= 54000)
-		value = GPIO_CS5381_M_SINGLE;
+		value = GPIO_CS53x1_M_SINGLE;
 	else if (params_rate(params) <= 108000)
-		value = GPIO_CS5381_M_DOUBLE;
+		value = GPIO_CS53x1_M_DOUBLE;
 	else
-		value = GPIO_CS5381_M_QUAD;
+		value = GPIO_CS53x1_M_QUAD;
 	oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
-			      value, GPIO_CS5381_M_MASK);
+			      value, GPIO_CS53x1_M_MASK);
 }
 
 static void xonar_gpio_changed(struct oxygen *chip)
@@ -293,7 +294,7 @@ static const struct oxygen_model xonar_models[] = {
 		.mixer_init = xonar_mixer_init,
 		.cleanup = xonar_cleanup,
 		.set_dac_params = set_pcm1796_params,
-		.set_adc_params = set_cs5381_params,
+		.set_adc_params = set_cs53x1_params,
 		.update_dac_volume = update_pcm1796_volume,
 		.update_dac_mute = update_pcm1796_mute,
 		.model_data_size = sizeof(struct xonar_data),
@@ -318,7 +319,7 @@ static const struct oxygen_model xonar_models[] = {
 		.mixer_init = xonar_mixer_init,
 		.cleanup = xonar_cleanup,
 		.set_dac_params = set_pcm1796_params,
-		.set_adc_params = set_cs5381_params,
+		.set_adc_params = set_cs53x1_params,
 		.update_dac_volume = update_pcm1796_volume,
 		.update_dac_mute = update_pcm1796_mute,
 		.gpio_changed = xonar_gpio_changed,
-- 
cgit v1.2.3-70-g09d2


From af9af1741f5e7959d220fb0d83604ecb5ae26581 Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Mon, 7 Apr 2008 10:26:03 +0200
Subject: [ALSA] virtuoso: move some code to xonar_common_init()

Move the code that is common to all Xonar models to a separate function,
and make it more generic in preparation for another model.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/oxygen/virtuoso.c | 77 ++++++++++++++++++++++++++++++---------------
 1 file changed, 51 insertions(+), 26 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
index 1627197f168..95c229acf85 100644
--- a/sound/pci/oxygen/virtuoso.c
+++ b/sound/pci/oxygen/virtuoso.c
@@ -79,11 +79,16 @@ MODULE_DEVICE_TABLE(pci, xonar_ids);
 #define GPIO_CS53x1_M_DOUBLE	0x0004
 #define GPIO_CS53x1_M_QUAD	0x0008
 
-#define GPIO_EXT_POWER		0x0020
-#define GPIO_ALT		0x0080
-#define GPIO_OUTPUT_ENABLE	0x0100
+#define GPIO_D2X_EXT_POWER	0x0020
+#define GPIO_D2_ALT		0x0080
+#define GPIO_D2_OUTPUT_ENABLE	0x0100
 
 struct xonar_data {
+	unsigned int anti_pop_delay;
+	u16 output_enable_bit;
+	u8 ext_power_reg;
+	u8 ext_power_int_reg;
+	u8 ext_power_bit;
 	u8 has_power;
 };
 
@@ -102,10 +107,34 @@ static void pcm1796_write(struct oxygen *chip, unsigned int codec,
 			 (reg << 8) | value);
 }
 
+static void xonar_common_init(struct oxygen *chip)
+{
+	struct xonar_data *data = chip->model_data;
+
+	if (data->ext_power_reg) {
+		oxygen_set_bits8(chip, data->ext_power_int_reg,
+				 data->ext_power_bit);
+		chip->interrupt_mask |= OXYGEN_INT_GPIO;
+		data->has_power = !!(oxygen_read8(chip, data->ext_power_reg)
+				     & data->ext_power_bit);
+	}
+	oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_CS53x1_M_MASK);
+	oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
+			      GPIO_CS53x1_M_SINGLE, GPIO_CS53x1_M_MASK);
+	oxygen_ac97_set_bits(chip, 0, CM9780_JACK, CM9780_FMIC2MIC);
+	msleep(data->anti_pop_delay);
+	oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, data->output_enable_bit);
+	oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, data->output_enable_bit);
+}
+
 static void xonar_d2_init(struct oxygen *chip)
 {
+	struct xonar_data *data = chip->model_data;
 	unsigned int i;
 
+	data->anti_pop_delay = 300;
+	data->output_enable_bit = GPIO_D2_OUTPUT_ENABLE;
+
 	for (i = 0; i < 4; ++i) {
 		pcm1796_write(chip, i, 18, PCM1796_FMT_24_LJUST | PCM1796_ATLD);
 		pcm1796_write(chip, i, 19, PCM1796_FLT_SHARP | PCM1796_ATS_1);
@@ -115,15 +144,10 @@ static void xonar_d2_init(struct oxygen *chip)
 		pcm1796_write(chip, i, 17, 0xff);
 	}
 
-	oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
-			  GPIO_CS53x1_M_MASK | GPIO_ALT);
-	oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
-			      GPIO_CS53x1_M_SINGLE,
-			      GPIO_CS53x1_M_MASK | GPIO_ALT);
-	oxygen_ac97_set_bits(chip, 0, CM9780_JACK, CM9780_FMIC2MIC);
-	msleep(300);
-	oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_OUTPUT_ENABLE);
-	oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_OUTPUT_ENABLE);
+	oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_D2_ALT);
+	oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_D2_ALT);
+
+	xonar_common_init(chip);
 
 	snd_component_add(chip->card, "PCM1796");
 	snd_component_add(chip->card, "CS5381");
@@ -133,17 +157,18 @@ static void xonar_d2x_init(struct oxygen *chip)
 {
 	struct xonar_data *data = chip->model_data;
 
+	data->ext_power_reg = OXYGEN_GPIO_DATA;
+	data->ext_power_int_reg = OXYGEN_GPIO_INTERRUPT_MASK;
+	data->ext_power_bit = GPIO_D2X_EXT_POWER;
+	oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_D2X_EXT_POWER);
 	xonar_d2_init(chip);
-	oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_EXT_POWER);
-	oxygen_set_bits16(chip, OXYGEN_GPIO_INTERRUPT_MASK, GPIO_EXT_POWER);
-	chip->interrupt_mask |= OXYGEN_INT_GPIO;
-	data->has_power = !!(oxygen_read16(chip, OXYGEN_GPIO_DATA)
-			     & GPIO_EXT_POWER);
 }
 
 static void xonar_cleanup(struct oxygen *chip)
 {
-	oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_OUTPUT_ENABLE);
+	struct xonar_data *data = chip->model_data;
+
+	oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, data->output_enable_bit);
 }
 
 static void set_pcm1796_params(struct oxygen *chip,
@@ -201,8 +226,8 @@ static void xonar_gpio_changed(struct oxygen *chip)
 	struct xonar_data *data = chip->model_data;
 	u8 has_power;
 
-	has_power = !!(oxygen_read16(chip, OXYGEN_GPIO_DATA)
-		       & GPIO_EXT_POWER);
+	has_power = !!(oxygen_read8(chip, data->ext_power_reg)
+		       & data->ext_power_bit);
 	if (has_power != data->has_power) {
 		data->has_power = has_power;
 		if (has_power) {
@@ -231,7 +256,7 @@ static int alt_switch_get(struct snd_kcontrol *ctl,
 	struct oxygen *chip = ctl->private_data;
 
 	value->value.integer.value[0] =
-		!!(oxygen_read16(chip, OXYGEN_GPIO_DATA) & GPIO_ALT);
+		!!(oxygen_read16(chip, OXYGEN_GPIO_DATA) & GPIO_D2_ALT);
 	return 0;
 }
 
@@ -245,9 +270,9 @@ static int alt_switch_put(struct snd_kcontrol *ctl,
 	spin_lock_irq(&chip->reg_lock);
 	old_bits = oxygen_read16(chip, OXYGEN_GPIO_DATA);
 	if (value->value.integer.value[0])
-		new_bits = old_bits | GPIO_ALT;
+		new_bits = old_bits | GPIO_D2_ALT;
 	else
-		new_bits = old_bits & ~GPIO_ALT;
+		new_bits = old_bits & ~GPIO_D2_ALT;
 	changed = new_bits != old_bits;
 	if (changed)
 		oxygen_write16(chip, OXYGEN_GPIO_DATA, new_bits);
@@ -265,7 +290,7 @@ static const struct snd_kcontrol_new alt_switch = {
 
 static const DECLARE_TLV_DB_SCALE(pcm1796_db_scale, -12000, 50, 0);
 
-static int xonar_control_filter(struct snd_kcontrol_new *template)
+static int xonar_d2_control_filter(struct snd_kcontrol_new *template)
 {
 	if (!strcmp(template->name, "Master Playback Volume")) {
 		template->access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
@@ -290,7 +315,7 @@ static const struct oxygen_model xonar_models[] = {
 		.chip = "AV200",
 		.owner = THIS_MODULE,
 		.init = xonar_d2_init,
-		.control_filter = xonar_control_filter,
+		.control_filter = xonar_d2_control_filter,
 		.mixer_init = xonar_mixer_init,
 		.cleanup = xonar_cleanup,
 		.set_dac_params = set_pcm1796_params,
@@ -315,7 +340,7 @@ static const struct oxygen_model xonar_models[] = {
 		.chip = "AV200",
 		.owner = THIS_MODULE,
 		.init = xonar_d2x_init,
-		.control_filter = xonar_control_filter,
+		.control_filter = xonar_d2_control_filter,
 		.mixer_init = xonar_mixer_init,
 		.cleanup = xonar_cleanup,
 		.set_dac_params = set_pcm1796_params,
-- 
cgit v1.2.3-70-g09d2


From d08267a9df99c3cf288ca05e75084d14479fe7cb Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Mon, 7 Apr 2008 10:26:26 +0200
Subject: [ALSA] virtuoso: set PCM1796 oversampling rate

When playing data at 96 kHz or higher, reduce the DAC oversampling rate
to 32.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/oxygen/virtuoso.c | 2 --
 1 file changed, 2 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
index 95c229acf85..c6bd31b9f4b 100644
--- a/sound/pci/oxygen/virtuoso.c
+++ b/sound/pci/oxygen/virtuoso.c
@@ -174,14 +174,12 @@ static void xonar_cleanup(struct oxygen *chip)
 static void set_pcm1796_params(struct oxygen *chip,
 			       struct snd_pcm_hw_params *params)
 {
-#if 0
 	unsigned int i;
 	u8 value;
 
 	value = params_rate(params) >= 96000 ? PCM1796_OS_32 : PCM1796_OS_64;
 	for (i = 0; i < 4; ++i)
 		pcm1796_write(chip, i, 20, value);
-#endif
 }
 
 static void update_pcm1796_volume(struct oxygen *chip)
-- 
cgit v1.2.3-70-g09d2


From aef1a535c4dadff408412833b2b71bc7919e84a6 Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Mon, 7 Apr 2008 10:26:45 +0200
Subject: [ALSA] virtuoso: change card short name

Change the card short name to show to show the card name instead of the
chip name.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/oxygen/virtuoso.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
index c6bd31b9f4b..2d7b96e3f49 100644
--- a/sound/pci/oxygen/virtuoso.c
+++ b/sound/pci/oxygen/virtuoso.c
@@ -308,7 +308,7 @@ static int xonar_mixer_init(struct oxygen *chip)
 
 static const struct oxygen_model xonar_models[] = {
 	[MODEL_D2] = {
-		.shortname = "Asus AV200",
+		.shortname = "Xonar D2",
 		.longname = "Asus Virtuoso 200",
 		.chip = "AV200",
 		.owner = THIS_MODULE,
@@ -333,7 +333,7 @@ static const struct oxygen_model xonar_models[] = {
 		.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
 	},
 	[MODEL_D2X] = {
-		.shortname = "Asus AV200",
+		.shortname = "Xonar D2X",
 		.longname = "Asus Virtuoso 200",
 		.chip = "AV200",
 		.owner = THIS_MODULE,
-- 
cgit v1.2.3-70-g09d2


From 80647ee26e96d6394cab77332c69f60735396e67 Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Mon, 7 Apr 2008 10:27:01 +0200
Subject: [ALSA] virtuoso: fix typo

Fix a (fortunately harmless) typo.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/oxygen/virtuoso.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'sound')

diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
index 2d7b96e3f49..9459ca0a120 100644
--- a/sound/pci/oxygen/virtuoso.c
+++ b/sound/pci/oxygen/virtuoso.c
@@ -292,7 +292,7 @@ static int xonar_d2_control_filter(struct snd_kcontrol_new *template)
 {
 	if (!strcmp(template->name, "Master Playback Volume")) {
 		template->access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
-		template->info = pcm1796_volume_info,
+		template->info = pcm1796_volume_info;
 		template->tlv.p = pcm1796_db_scale;
 	} else if (!strncmp(template->name, "CD Capture ", 11)) {
 		/* CD in is actually connected to the video in pin */
-- 
cgit v1.2.3-70-g09d2


From a9d3cc485e65a56edc9ef78c034146cc8a5b3101 Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Mon, 7 Apr 2008 10:29:44 +0200
Subject: [ALSA] virtuoso: add Xonar DX support

Add support for the Asus Xonar DX.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/Kconfig           |   4 +-
 sound/pci/oxygen/cs4362a.h  |  69 ++++++++++++++
 sound/pci/oxygen/cs4398.h   |  69 ++++++++++++++
 sound/pci/oxygen/virtuoso.c | 227 +++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 365 insertions(+), 4 deletions(-)
 create mode 100644 sound/pci/oxygen/cs4362a.h
 create mode 100644 sound/pci/oxygen/cs4398.h

(limited to 'sound')

diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index b5903eed6ef..581debf37dc 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -914,12 +914,12 @@ config SND_VIA82XX_MODEM
 	  will be called snd-via82xx-modem.
 
 config SND_VIRTUOSO
-	tristate "Asus Virtuoso 200 (Xonar)"
+	tristate "Asus Virtuoso 100/200 (Xonar)"
 	depends on SND
 	select SND_OXYGEN_LIB
 	help
 	  Say Y here to include support for sound cards based on the
-	  Asus AV200 chip, i.e., Xonar D2 and Xonar D2X.
+	  Asus AV100/AV200 chips, i.e., Xonar D2, DX and D2X.
 
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-virtuoso.
diff --git a/sound/pci/oxygen/cs4362a.h b/sound/pci/oxygen/cs4362a.h
new file mode 100644
index 00000000000..6a4fedf5e1e
--- /dev/null
+++ b/sound/pci/oxygen/cs4362a.h
@@ -0,0 +1,69 @@
+/* register 01h */
+#define CS4362A_PDN		0x01
+#define CS4362A_DAC1_DIS	0x02
+#define CS4362A_DAC2_DIS	0x04
+#define CS4362A_DAC3_DIS	0x08
+#define CS4362A_MCLKDIV		0x20
+#define CS4362A_FREEZE		0x40
+#define CS4362A_CPEN		0x80
+/* register 02h */
+#define CS4362A_DIF_MASK	0x70
+#define CS4362A_DIF_LJUST	0x00
+#define CS4362A_DIF_I2S		0x10
+#define CS4362A_DIF_RJUST_16	0x20
+#define CS4362A_DIF_RJUST_24	0x30
+#define CS4362A_DIF_RJUST_20	0x40
+#define CS4362A_DIF_RJUST_18	0x50
+/* register 03h */
+#define CS4362A_MUTEC_MASK	0x03
+#define CS4362A_MUTEC_6		0x00
+#define CS4362A_MUTEC_1		0x01
+#define CS4362A_MUTEC_3		0x03
+#define CS4362A_AMUTE		0x04
+#define CS4362A_MUTEC_POL	0x08
+#define CS4362A_RMP_UP		0x10
+#define CS4362A_SNGLVOL		0x20
+#define CS4362A_ZERO_CROSS	0x40
+#define CS4362A_SOFT_RAMP	0x80
+/* register 04h */
+#define CS4362A_RMP_DN		0x01
+#define CS4362A_DEM_MASK	0x06
+#define CS4362A_DEM_NONE	0x00
+#define CS4362A_DEM_44100	0x02
+#define CS4362A_DEM_48000	0x04
+#define CS4362A_DEM_32000	0x06
+#define CS4362A_FILT_SEL	0x10
+/* register 05h */
+#define CS4362A_INV_A1		0x01
+#define CS4362A_INV_B1		0x02
+#define CS4362A_INV_A2		0x04
+#define CS4362A_INV_B2		0x08
+#define CS4362A_INV_A3		0x10
+#define CS4362A_INV_B3		0x20
+/* register 06h */
+#define CS4362A_FM_MASK		0x03
+#define CS4362A_FM_SINGLE	0x00
+#define CS4362A_FM_DOUBLE	0x01
+#define CS4362A_FM_QUAD		0x02
+#define CS4362A_FM_DSD		0x03
+#define CS4362A_ATAPI_MASK	0x7c
+#define CS4362A_ATAPI_B_MUTE	0x00
+#define CS4362A_ATAPI_B_R	0x04
+#define CS4362A_ATAPI_B_L	0x08
+#define CS4362A_ATAPI_B_LR	0x0c
+#define CS4362A_ATAPI_A_MUTE	0x00
+#define CS4362A_ATAPI_A_R	0x10
+#define CS4362A_ATAPI_A_L	0x20
+#define CS4362A_ATAPI_A_LR	0x30
+#define CS4362A_ATAPI_MIX_LR_VOL 0x40
+#define CS4362A_A_EQ_B		0x80
+/* register 07h */
+#define CS4362A_VOL_MASK		0x7f
+#define CS4362A_MUTE			0x80
+/* register 08h: like 07h */
+/* registers 09h..0Bh: like 06h..08h */
+/* registers 0Ch..0Eh: like 06h..08h */
+/* register 12h */
+#define CS4362A_REV_MASK	0x07
+#define CS4362A_PART_MASK	0xf8
+#define CS4362A_PART_CS4362A	0x50
diff --git a/sound/pci/oxygen/cs4398.h b/sound/pci/oxygen/cs4398.h
new file mode 100644
index 00000000000..5faf5efc882
--- /dev/null
+++ b/sound/pci/oxygen/cs4398.h
@@ -0,0 +1,69 @@
+/* register 1 */
+#define CS4398_REV_MASK		0x07
+#define CS4398_PART_MASK	0xf8
+#define CS4398_PART_CS4398	0x70
+/* register 2 */
+#define CS4398_FM_MASK		0x03
+#define CS4398_FM_SINGLE	0x00
+#define CS4398_FM_DOUBLE	0x01
+#define CS4398_FM_QUAD		0x02
+#define CS4398_FM_DSD		0x03
+#define CS4398_DEM_MASK		0x0c
+#define CS4398_DEM_NONE		0x00
+#define CS4398_DEM_44100	0x04
+#define CS4398_DEM_48000	0x08
+#define CS4398_DEM_32000	0x0c
+#define CS4398_DIF_MASK		0x70
+#define CS4398_DIF_LJUST	0x00
+#define CS4398_DIF_I2S		0x10
+#define CS4398_DIF_RJUST_16	0x20
+#define CS4398_DIF_RJUST_24	0x30
+#define CS4398_DIF_RJUST_20	0x40
+#define CS4398_DIF_RJUST_18	0x50
+#define CS4398_DSD_SRC		0x80
+/* register 3 */
+#define CS4398_ATAPI_MASK	0x1f
+#define CS4398_ATAPI_B_MUTE	0x00
+#define CS4398_ATAPI_B_R	0x01
+#define CS4398_ATAPI_B_L	0x02
+#define CS4398_ATAPI_B_LR	0x03
+#define CS4398_ATAPI_A_MUTE	0x00
+#define CS4398_ATAPI_A_R	0x04
+#define CS4398_ATAPI_A_L	0x08
+#define CS4398_ATAPI_A_LR	0x0c
+#define CS4398_ATAPI_MIX_LR_VOL	0x10
+#define CS4398_INVERT_B		0x20
+#define CS4398_INVERT_A		0x40
+#define CS4398_VOL_B_EQ_A	0x80
+/* register 4 */
+#define CS4398_MUTEP_MASK	0x03
+#define CS4398_MUTEP_AUTO	0x00
+#define CS4398_MUTEP_LOW	0x02
+#define CS4398_MUTEP_HIGH	0x03
+#define CS4398_MUTE_B		0x08
+#define CS4398_MUTE_A		0x10
+#define CS4398_MUTEC_A_EQ_B	0x20
+#define CS4398_DAMUTE		0x40
+#define CS4398_PAMUTE		0x80
+/* register 5 */
+#define CS4398_VOL_A_MASK	0xff
+/* register 6 */
+#define CS4398_VOL_B_MASK	0xff
+/* register 7 */
+#define CS4398_DIR_DSD		0x01
+#define CS4398_FILT_SEL		0x04
+#define CS4398_RMP_DN		0x10
+#define CS4398_RMP_UP		0x20
+#define CS4398_ZERO_CROSS	0x40
+#define CS4398_SOFT_RAMP	0x80
+/* register 8 */
+#define CS4398_MCLKDIV3		0x08
+#define CS4398_MCLKDIV2		0x10
+#define CS4398_FREEZE		0x20
+#define CS4398_CPEN		0x40
+#define CS4398_PDN		0x80
+/* register 9 */
+#define CS4398_DSD_PM_EN	0x01
+#define CS4398_DSD_PM_MODE	0x02
+#define CS4398_INVALID_DSD	0x04
+#define CS4398_STATIC_DSD	0x08
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
index 9459ca0a120..1db4aa5dfad 100644
--- a/sound/pci/oxygen/virtuoso.c
+++ b/sound/pci/oxygen/virtuoso.c
@@ -18,6 +18,9 @@
  */
 
 /*
+ * Xonar D2/D2X
+ * ------------
+ *
  * CMI8788:
  *
  * SPI 0 -> 1st PCM1796 (front)
@@ -32,6 +35,33 @@
  * GPIO 8 -> enable output to speakers
  */
 
+/*
+ * Xonar DX
+ * --------
+ *
+ * CMI8788:
+ *
+ * I²C <-> CS4398 (front)
+ *     <-> CS4362A (surround, center/LFE, back)
+ *
+ * GPI 0 <- external power present
+ *
+ * GPIO 0 -> enable output to speakers
+ * GPIO 1 -> ALT?
+ * GPIO 2 -> M0 of CS5361
+ * GPIO 3 -> M1 of CS5361
+ * GPIO 8 -> line-in/mic-in/digital-out switch?
+ *
+ * CS4398:
+ *
+ * AD0 <- 1
+ * AD1 <- 1
+ *
+ * CS4362A:
+ *
+ * AD0 <- 0
+ */
+
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/mutex.h>
@@ -44,11 +74,13 @@
 #include "oxygen.h"
 #include "cm9780.h"
 #include "pcm1796.h"
+#include "cs4398.h"
+#include "cs4362a.h"
 
 MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
-MODULE_DESCRIPTION("Asus AV200 driver");
+MODULE_DESCRIPTION("Asus AVx00 driver");
 MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("{{Asus,AV200}}");
+MODULE_SUPPORTED_DEVICE("{{Asus,AV100},{Asus,AV200}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
@@ -64,10 +96,12 @@ MODULE_PARM_DESC(enable, "enable card");
 enum {
 	MODEL_D2,
 	MODEL_D2X,
+	MODEL_DX,
 };
 
 static struct pci_device_id xonar_ids[] __devinitdata = {
 	{ OXYGEN_PCI_SUBID(0x1043, 0x8269), .driver_data = MODEL_D2 },
+	{ OXYGEN_PCI_SUBID(0x1043, 0x8275), .driver_data = MODEL_DX },
 	{ OXYGEN_PCI_SUBID(0x1043, 0x82b7), .driver_data = MODEL_D2X },
 	{ }
 };
@@ -83,6 +117,14 @@ MODULE_DEVICE_TABLE(pci, xonar_ids);
 #define GPIO_D2_ALT		0x0080
 #define GPIO_D2_OUTPUT_ENABLE	0x0100
 
+#define GPI_DX_EXT_POWER	0x01
+#define GPIO_DX_OUTPUT_ENABLE	0x0001
+#define GPIO_DX_UNKNOWN1	0x0002
+#define GPIO_DX_UNKNOWN2	0x0100
+
+#define I2C_DEVICE_CS4398	0x9e	/* 10011, AD1=1, AD0=1, /W=0 */
+#define I2C_DEVICE_CS4362A	0x30	/* 001100, AD0=0, /W=0 */
+
 struct xonar_data {
 	unsigned int anti_pop_delay;
 	u16 output_enable_bit;
@@ -107,6 +149,16 @@ static void pcm1796_write(struct oxygen *chip, unsigned int codec,
 			 (reg << 8) | value);
 }
 
+static void cs4398_write(struct oxygen *chip, u8 reg, u8 value)
+{
+	oxygen_write_i2c(chip, I2C_DEVICE_CS4398, reg, value);
+}
+
+static void cs4362a_write(struct oxygen *chip, u8 reg, u8 value)
+{
+	oxygen_write_i2c(chip, I2C_DEVICE_CS4362A, reg, value);
+}
+
 static void xonar_common_init(struct oxygen *chip)
 {
 	struct xonar_data *data = chip->model_data;
@@ -164,6 +216,66 @@ static void xonar_d2x_init(struct oxygen *chip)
 	xonar_d2_init(chip);
 }
 
+static void xonar_dx_init(struct oxygen *chip)
+{
+	struct xonar_data *data = chip->model_data;
+	unsigned int i;
+
+	for (i = 0; i < 8; ++i)
+		chip->dac_volume[i] = 127;
+	data->anti_pop_delay = 800;
+	data->output_enable_bit = GPIO_DX_OUTPUT_ENABLE;
+	data->ext_power_reg = OXYGEN_GPI_DATA;
+	data->ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK;
+	data->ext_power_bit = GPI_DX_EXT_POWER;
+
+	/* XXX the DACs' datasheets say fast mode is not allowed */
+	oxygen_set_bits16(chip, OXYGEN_2WIRE_BUS_STATUS,
+			  OXYGEN_2WIRE_SPEED_FAST);
+
+	/* set CPEN (control port mode) and power down */
+	cs4398_write(chip, 8, CS4398_CPEN | CS4398_PDN);
+	cs4362a_write(chip, 0x01, CS4362A_PDN | CS4362A_CPEN);
+	/* configure */
+	cs4398_write(chip, 2, CS4398_FM_SINGLE |
+		     CS4398_DEM_NONE | CS4398_DIF_LJUST);
+	cs4398_write(chip, 3, CS4398_ATAPI_B_R | CS4398_ATAPI_A_L);
+	cs4398_write(chip, 4, CS4398_MUTEP_LOW | CS4398_PAMUTE);
+	cs4398_write(chip, 5, 0);
+	cs4398_write(chip, 6, 0);
+	cs4398_write(chip, 7, CS4398_RMP_DN | CS4398_RMP_UP |
+		     CS4398_ZERO_CROSS | CS4398_SOFT_RAMP);
+	cs4362a_write(chip, 0x02, CS4362A_DIF_LJUST);
+	cs4362a_write(chip, 0x03, CS4362A_MUTEC_6 | CS4362A_AMUTE |
+		      CS4362A_RMP_UP | CS4362A_ZERO_CROSS | CS4362A_SOFT_RAMP);
+	cs4362a_write(chip, 0x04, CS4362A_RMP_DN | CS4362A_DEM_NONE);
+	cs4362a_write(chip, 0x05, 0);
+	cs4362a_write(chip, 0x06, CS4362A_FM_SINGLE |
+		      CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L);
+	cs4362a_write(chip, 0x09, CS4362A_FM_SINGLE |
+		      CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L);
+	cs4362a_write(chip, 0x0c, CS4362A_FM_SINGLE |
+		      CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L);
+	cs4362a_write(chip, 0x07, 0);
+	cs4362a_write(chip, 0x08, 0);
+	cs4362a_write(chip, 0x0a, 0);
+	cs4362a_write(chip, 0x0b, 0);
+	cs4362a_write(chip, 0x0d, 0);
+	cs4362a_write(chip, 0x0e, 0);
+	/* clear power down */
+	cs4398_write(chip, 8, CS4398_CPEN);
+	cs4362a_write(chip, 0x01, CS4362A_CPEN);
+
+	oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
+			  GPIO_DX_UNKNOWN1 | GPIO_DX_UNKNOWN2);
+
+	xonar_common_init(chip);
+
+	snd_component_add(chip->card, "CS4398");
+	snd_component_add(chip->card, "CS4362A");
+	snd_component_add(chip->card, "CS5361");
+}
+
 static void xonar_cleanup(struct oxygen *chip)
 {
 	struct xonar_data *data = chip->model_data;
@@ -171,6 +283,13 @@ static void xonar_cleanup(struct oxygen *chip)
 	oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, data->output_enable_bit);
 }
 
+static void xonar_dx_cleanup(struct oxygen *chip)
+{
+	xonar_cleanup(chip);
+	cs4362a_write(chip, 0x01, CS4362A_PDN | CS4362A_CPEN);
+	oxygen_clear_bits8(chip, OXYGEN_FUNCTION, OXYGEN_FUNCTION_RESET_CODEC);
+}
+
 static void set_pcm1796_params(struct oxygen *chip,
 			       struct snd_pcm_hw_params *params)
 {
@@ -219,6 +338,60 @@ static void set_cs53x1_params(struct oxygen *chip,
 			      value, GPIO_CS53x1_M_MASK);
 }
 
+static void set_cs43xx_params(struct oxygen *chip,
+			      struct snd_pcm_hw_params *params)
+{
+	u8 fm_cs4398, fm_cs4362a;
+
+	fm_cs4398 = CS4398_DEM_NONE | CS4398_DIF_LJUST;
+	fm_cs4362a = CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L;
+	if (params_rate(params) <= 50000) {
+		fm_cs4398 |= CS4398_FM_SINGLE;
+		fm_cs4362a |= CS4362A_FM_SINGLE;
+	} else if (params_rate(params) <= 100000) {
+		fm_cs4398 |= CS4398_FM_DOUBLE;
+		fm_cs4362a |= CS4362A_FM_DOUBLE;
+	} else {
+		fm_cs4398 |= CS4398_FM_QUAD;
+		fm_cs4362a |= CS4362A_FM_QUAD;
+	}
+	cs4398_write(chip, 2, fm_cs4398);
+	cs4362a_write(chip, 0x06, fm_cs4362a);
+	cs4362a_write(chip, 0x09, fm_cs4362a);
+	cs4362a_write(chip, 0x0c, fm_cs4362a);
+}
+
+static void update_cs4362a_volumes(struct oxygen *chip)
+{
+	u8 mute;
+
+	mute = chip->dac_mute ? CS4362A_MUTE : 0;
+	cs4362a_write(chip, 7, (127 - chip->dac_volume[2]) | mute);
+	cs4362a_write(chip, 8, (127 - chip->dac_volume[3]) | mute);
+	cs4362a_write(chip, 10, (127 - chip->dac_volume[4]) | mute);
+	cs4362a_write(chip, 11, (127 - chip->dac_volume[5]) | mute);
+	cs4362a_write(chip, 13, (127 - chip->dac_volume[6]) | mute);
+	cs4362a_write(chip, 14, (127 - chip->dac_volume[7]) | mute);
+}
+
+static void update_cs43xx_volume(struct oxygen *chip)
+{
+	cs4398_write(chip, 5, (127 - chip->dac_volume[0]) * 2);
+	cs4398_write(chip, 6, (127 - chip->dac_volume[1]) * 2);
+	update_cs4362a_volumes(chip);
+}
+
+static void update_cs43xx_mute(struct oxygen *chip)
+{
+	u8 reg;
+
+	reg = CS4398_MUTEP_LOW | CS4398_PAMUTE;
+	if (chip->dac_mute)
+		reg |= CS4398_MUTE_B | CS4398_MUTE_A;
+	cs4398_write(chip, 4, reg);
+	update_cs4362a_volumes(chip);
+}
+
 static void xonar_gpio_changed(struct oxygen *chip)
 {
 	struct xonar_data *data = chip->model_data;
@@ -248,6 +421,16 @@ static int pcm1796_volume_info(struct snd_kcontrol *ctl,
 	return 0;
 }
 
+static int cs4362a_volume_info(struct snd_kcontrol *ctl,
+			       struct snd_ctl_elem_info *info)
+{
+	info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	info->count = 8;
+	info->value.integer.min = 0;
+	info->value.integer.max = 127;
+	return 0;
+}
+
 static int alt_switch_get(struct snd_kcontrol *ctl,
 			  struct snd_ctl_elem_value *value)
 {
@@ -287,6 +470,7 @@ static const struct snd_kcontrol_new alt_switch = {
 };
 
 static const DECLARE_TLV_DB_SCALE(pcm1796_db_scale, -12000, 50, 0);
+static const DECLARE_TLV_DB_SCALE(cs4362a_db_scale, -12700, 100, 0);
 
 static int xonar_d2_control_filter(struct snd_kcontrol_new *template)
 {
@@ -301,6 +485,23 @@ static int xonar_d2_control_filter(struct snd_kcontrol_new *template)
 	return 0;
 }
 
+static int xonar_dx_control_filter(struct snd_kcontrol_new *template)
+{
+	if (!strcmp(template->name, "Master Playback Volume")) {
+		template->access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
+		template->info = cs4362a_volume_info;
+		template->tlv.p = cs4362a_db_scale;
+	} else if (!strncmp(template->name, "CD Capture ", 11)) {
+		return 1; /* no CD input */
+	} else if (!strcmp(template->name,
+			   SNDRV_CTL_NAME_IEC958("", CAPTURE, MASK)) ||
+		   !strcmp(template->name,
+			   SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT))) {
+		return 1; /* no digital input */
+	}
+	return 0;
+}
+
 static int xonar_mixer_init(struct oxygen *chip)
 {
 	return snd_ctl_add(chip->card, snd_ctl_new1(&alt_switch, chip));
@@ -358,6 +559,28 @@ static const struct oxygen_model xonar_models[] = {
 		.dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
 		.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
 	},
+	[MODEL_DX] = {
+		.shortname = "Xonar DX",
+		.longname = "Asus Virtuoso 100",
+		.chip = "AV200",
+		.owner = THIS_MODULE,
+		.init = xonar_dx_init,
+		.control_filter = xonar_dx_control_filter,
+		.cleanup = xonar_dx_cleanup,
+		.set_dac_params = set_cs43xx_params,
+		.set_adc_params = set_cs53x1_params,
+		.update_dac_volume = update_cs43xx_volume,
+		.update_dac_mute = update_cs43xx_mute,
+		.gpio_changed = xonar_gpio_changed,
+		.model_data_size = sizeof(struct xonar_data),
+		.pcm_dev_cfg = PLAYBACK_0_TO_I2S |
+			       PLAYBACK_1_TO_SPDIF |
+			       CAPTURE_0_FROM_I2S_2,
+		.dac_channels = 8,
+		.function_flags = OXYGEN_FUNCTION_2WIRE,
+		.dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
+		.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
+	},
 };
 
 static int __devinit xonar_probe(struct pci_dev *pci,
-- 
cgit v1.2.3-70-g09d2


From 11864b4b84194b459fc20e0ec47906885bddb12e Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Wed, 9 Apr 2008 09:16:14 +0200
Subject: [ALSA] virtuoso: correctly switch input jack on Xonar DX

When selecting the capture source on the Xonar DX, the input jack must
be routed to either the line input or the microphone input by setting a
GPIO pin.  This requires an additional callback so that the model driver
can hook into the toggling of AC97 switches.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/oxygen/oxygen.h       |  2 ++
 sound/pci/oxygen/oxygen_mixer.c |  4 ++++
 sound/pci/oxygen/virtuoso.c     | 22 ++++++++++++++++++----
 3 files changed, 24 insertions(+), 4 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/oxygen/oxygen.h b/sound/pci/oxygen/oxygen.h
index d53c18c6fcd..7efbf54bc4e 100644
--- a/sound/pci/oxygen/oxygen.h
+++ b/sound/pci/oxygen/oxygen.h
@@ -98,6 +98,8 @@ struct oxygen_model {
 	void (*update_dac_volume)(struct oxygen *chip);
 	void (*update_dac_mute)(struct oxygen *chip);
 	void (*gpio_changed)(struct oxygen *chip);
+	void (*ac97_switch)(struct oxygen *chip,
+			    unsigned int reg, unsigned int mute);
 	size_t model_data_size;
 	unsigned int pcm_dev_cfg;
 	u8 dac_channels;
diff --git a/sound/pci/oxygen/oxygen_mixer.c b/sound/pci/oxygen/oxygen_mixer.c
index 9a7c880eddb..d0bef09a699 100644
--- a/sound/pci/oxygen/oxygen_mixer.c
+++ b/sound/pci/oxygen/oxygen_mixer.c
@@ -518,6 +518,8 @@ static void mute_ac97_ctl(struct oxygen *chip, unsigned int control)
 	value = oxygen_read_ac97(chip, 0, priv_idx);
 	if (!(value & 0x8000)) {
 		oxygen_write_ac97(chip, 0, priv_idx, value | 0x8000);
+		if (chip->model->ac97_switch)
+			chip->model->ac97_switch(chip, priv_idx, 0x8000);
 		snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
 			       &chip->controls[control]->id);
 	}
@@ -544,6 +546,8 @@ static int ac97_switch_put(struct snd_kcontrol *ctl,
 	change = newreg != oldreg;
 	if (change) {
 		oxygen_write_ac97(chip, codec, index, newreg);
+		if (codec == 0 && chip->model->ac97_switch)
+			chip->model->ac97_switch(chip, index, newreg & 0x8000);
 		if (index == AC97_LINE) {
 			oxygen_write_ac97_masked(chip, 0, CM9780_GPIO_STATUS,
 						 newreg & 0x8000 ?
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
index 1db4aa5dfad..b678e2de4ad 100644
--- a/sound/pci/oxygen/virtuoso.c
+++ b/sound/pci/oxygen/virtuoso.c
@@ -47,10 +47,10 @@
  * GPI 0 <- external power present
  *
  * GPIO 0 -> enable output to speakers
- * GPIO 1 -> ALT?
+ * GPIO 1 -> ?
  * GPIO 2 -> M0 of CS5361
  * GPIO 3 -> M1 of CS5361
- * GPIO 8 -> line-in/mic-in/digital-out switch?
+ * GPIO 8 -> route input jack to line-in (0) or mic-in (1)
  *
  * CS4398:
  *
@@ -120,7 +120,7 @@ MODULE_DEVICE_TABLE(pci, xonar_ids);
 #define GPI_DX_EXT_POWER	0x01
 #define GPIO_DX_OUTPUT_ENABLE	0x0001
 #define GPIO_DX_UNKNOWN1	0x0002
-#define GPIO_DX_UNKNOWN2	0x0100
+#define GPIO_DX_INPUT_ROUTE	0x0100
 
 #define I2C_DEVICE_CS4398	0x9e	/* 10011, AD1=1, AD0=1, /W=0 */
 #define I2C_DEVICE_CS4362A	0x30	/* 001100, AD0=0, /W=0 */
@@ -267,7 +267,8 @@ static void xonar_dx_init(struct oxygen *chip)
 	cs4362a_write(chip, 0x01, CS4362A_CPEN);
 
 	oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
-			  GPIO_DX_UNKNOWN1 | GPIO_DX_UNKNOWN2);
+			  GPIO_DX_UNKNOWN1 | GPIO_DX_INPUT_ROUTE);
+	oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_DX_INPUT_ROUTE);
 
 	xonar_common_init(chip);
 
@@ -469,6 +470,18 @@ static const struct snd_kcontrol_new alt_switch = {
 	.put = alt_switch_put,
 };
 
+static void xonar_dx_ac97_switch(struct oxygen *chip,
+				 unsigned int reg, unsigned int mute)
+{
+	if (reg == AC97_LINE) {
+		spin_lock_irq(&chip->reg_lock);
+		oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
+				      mute ? GPIO_DX_INPUT_ROUTE : 0,
+				      GPIO_DX_INPUT_ROUTE);
+		spin_unlock_irq(&chip->reg_lock);
+	}
+}
+
 static const DECLARE_TLV_DB_SCALE(pcm1796_db_scale, -12000, 50, 0);
 static const DECLARE_TLV_DB_SCALE(cs4362a_db_scale, -12700, 100, 0);
 
@@ -572,6 +585,7 @@ static const struct oxygen_model xonar_models[] = {
 		.update_dac_volume = update_cs43xx_volume,
 		.update_dac_mute = update_cs43xx_mute,
 		.gpio_changed = xonar_gpio_changed,
+		.ac97_switch = xonar_dx_ac97_switch,
 		.model_data_size = sizeof(struct xonar_data),
 		.pcm_dev_cfg = PLAYBACK_0_TO_I2S |
 			       PLAYBACK_1_TO_SPDIF |
-- 
cgit v1.2.3-70-g09d2


From 1d98c7d4be6ac521e3391025ddffcfe0400c798c Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Wed, 9 Apr 2008 09:16:33 +0200
Subject: [ALSA] oxygen: use SPDIF input only if present

If the card model does not have a digital input or an AC97 codec,
disable the respective interrupt and mixer controls.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/oxygen/hifier.c       |  5 -----
 sound/pci/oxygen/oxygen_lib.c   | 49 ++++++++++++++++++++++++++---------------
 sound/pci/oxygen/oxygen_mixer.c |  9 ++++++++
 sound/pci/oxygen/virtuoso.c     |  5 -----
 4 files changed, 40 insertions(+), 28 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/oxygen/hifier.c b/sound/pci/oxygen/hifier.c
index 1e54a3cd721..50551ae0b3b 100644
--- a/sound/pci/oxygen/hifier.c
+++ b/sound/pci/oxygen/hifier.c
@@ -132,11 +132,6 @@ static int hifier_control_filter(struct snd_kcontrol_new *template)
 		template->tlv.p = ak4396_db_scale;
 	} else if (!strcmp(template->name, "Stereo Upmixing")) {
 		return 1; /* stereo only - we don't need upmixing */
-	} else if (!strcmp(template->name,
-			   SNDRV_CTL_NAME_IEC958("", CAPTURE, MASK)) ||
-		   !strcmp(template->name,
-			   SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT))) {
-		return 1; /* no digital input */
 	}
 	return 0;
 }
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c
index 4f3d9e5fc5d..39e4b7a5174 100644
--- a/sound/pci/oxygen/oxygen_lib.c
+++ b/sound/pci/oxygen/oxygen_lib.c
@@ -291,20 +291,27 @@ static void oxygen_init(struct oxygen *chip)
 			       OXYGEN_I2S_MASTER | OXYGEN_I2S_MUTE_MCLK);
 	oxygen_write16(chip, OXYGEN_I2S_C_FORMAT,
 		       OXYGEN_I2S_MASTER | OXYGEN_I2S_MUTE_MCLK);
-	oxygen_write32_masked(chip, OXYGEN_SPDIF_CONTROL,
-			      OXYGEN_SPDIF_SENSE_MASK |
-			      OXYGEN_SPDIF_LOCK_MASK |
-			      OXYGEN_SPDIF_RATE_MASK |
-			      OXYGEN_SPDIF_LOCK_PAR |
-			      OXYGEN_SPDIF_IN_CLOCK_96,
-			      OXYGEN_SPDIF_OUT_ENABLE |
-			      OXYGEN_SPDIF_LOOPBACK |
-			      OXYGEN_SPDIF_SENSE_MASK |
-			      OXYGEN_SPDIF_LOCK_MASK |
-			      OXYGEN_SPDIF_RATE_MASK |
-			      OXYGEN_SPDIF_SENSE_PAR |
-			      OXYGEN_SPDIF_LOCK_PAR |
-			      OXYGEN_SPDIF_IN_CLOCK_MASK);
+	oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL,
+			    OXYGEN_SPDIF_OUT_ENABLE |
+			    OXYGEN_SPDIF_LOOPBACK);
+	if (chip->model->pcm_dev_cfg & CAPTURE_1_FROM_SPDIF)
+		oxygen_write32_masked(chip, OXYGEN_SPDIF_CONTROL,
+				      OXYGEN_SPDIF_SENSE_MASK |
+				      OXYGEN_SPDIF_LOCK_MASK |
+				      OXYGEN_SPDIF_RATE_MASK |
+				      OXYGEN_SPDIF_LOCK_PAR |
+				      OXYGEN_SPDIF_IN_CLOCK_96,
+				      OXYGEN_SPDIF_SENSE_MASK |
+				      OXYGEN_SPDIF_LOCK_MASK |
+				      OXYGEN_SPDIF_RATE_MASK |
+				      OXYGEN_SPDIF_SENSE_PAR |
+				      OXYGEN_SPDIF_LOCK_PAR |
+				      OXYGEN_SPDIF_IN_CLOCK_MASK);
+	else
+		oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL,
+				    OXYGEN_SPDIF_SENSE_MASK |
+				    OXYGEN_SPDIF_LOCK_MASK |
+				    OXYGEN_SPDIF_RATE_MASK);
 	oxygen_write32(chip, OXYGEN_SPDIF_OUTPUT_BITS, chip->spdif_bits);
 	oxygen_clear_bits8(chip, OXYGEN_MPU401_CONTROL, OXYGEN_MPU401_LOOPBACK);
 	oxygen_write8(chip, OXYGEN_GPI_INTERRUPT_MASK, 0);
@@ -327,9 +334,12 @@ static void oxygen_init(struct oxygen *chip)
 		      (2 << OXYGEN_A_MONITOR_ROUTE_2_SHIFT) |
 		      (3 << OXYGEN_A_MONITOR_ROUTE_3_SHIFT));
 
-	oxygen_write8(chip, OXYGEN_AC97_INTERRUPT_MASK,
-		      OXYGEN_AC97_INT_READ_DONE |
-		      OXYGEN_AC97_INT_WRITE_DONE);
+	if (chip->has_ac97_0 | chip->has_ac97_1)
+		oxygen_write8(chip, OXYGEN_AC97_INTERRUPT_MASK,
+			      OXYGEN_AC97_INT_READ_DONE |
+			      OXYGEN_AC97_INT_WRITE_DONE);
+	else
+		oxygen_write8(chip, OXYGEN_AC97_INTERRUPT_MASK, 0);
 	oxygen_write32(chip, OXYGEN_AC97_OUT_CONFIG, 0);
 	oxygen_write32(chip, OXYGEN_AC97_IN_CONFIG, 0);
 	if (!(chip->has_ac97_0 | chip->has_ac97_1))
@@ -495,7 +505,10 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
 	oxygen_proc_init(chip);
 
 	spin_lock_irq(&chip->reg_lock);
-	chip->interrupt_mask |= OXYGEN_INT_SPDIF_IN_DETECT | OXYGEN_INT_AC97;
+	if (chip->model->pcm_dev_cfg & CAPTURE_1_FROM_SPDIF)
+		chip->interrupt_mask |= OXYGEN_INT_SPDIF_IN_DETECT;
+	if (chip->has_ac97_0 | chip->has_ac97_1)
+		chip->interrupt_mask |= OXYGEN_INT_AC97;
 	oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, chip->interrupt_mask);
 	spin_unlock_irq(&chip->reg_lock);
 
diff --git a/sound/pci/oxygen/oxygen_mixer.c b/sound/pci/oxygen/oxygen_mixer.c
index d0bef09a699..2cb914498a1 100644
--- a/sound/pci/oxygen/oxygen_mixer.c
+++ b/sound/pci/oxygen/oxygen_mixer.c
@@ -742,6 +742,9 @@ static const struct snd_kcontrol_new controls[] = {
 		.get = spdif_pcm_get,
 		.put = spdif_pcm_put,
 	},
+};
+
+static const struct snd_kcontrol_new spdif_input_controls[] = {
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_PCM,
 		.device = 1,
@@ -961,6 +964,12 @@ int oxygen_mixer_init(struct oxygen *chip)
 	err = add_controls(chip, controls, ARRAY_SIZE(controls));
 	if (err < 0)
 		return err;
+	if (chip->model->pcm_dev_cfg & CAPTURE_1_FROM_SPDIF) {
+		err = add_controls(chip, spdif_input_controls,
+				   ARRAY_SIZE(spdif_input_controls));
+		if (err < 0)
+			return err;
+	}
 	for (i = 0; i < ARRAY_SIZE(monitor_controls); ++i) {
 		if (!(chip->model->pcm_dev_cfg & monitor_controls[i].pcm_dev))
 			continue;
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
index b678e2de4ad..07d7e9b6afb 100644
--- a/sound/pci/oxygen/virtuoso.c
+++ b/sound/pci/oxygen/virtuoso.c
@@ -506,11 +506,6 @@ static int xonar_dx_control_filter(struct snd_kcontrol_new *template)
 		template->tlv.p = cs4362a_db_scale;
 	} else if (!strncmp(template->name, "CD Capture ", 11)) {
 		return 1; /* no CD input */
-	} else if (!strcmp(template->name,
-			   SNDRV_CTL_NAME_IEC958("", CAPTURE, MASK)) ||
-		   !strcmp(template->name,
-			   SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT))) {
-		return 1; /* no digital input */
 	}
 	return 0;
 }
-- 
cgit v1.2.3-70-g09d2


From 387fb6a206749e13377ef8847f77d5341c281e7b Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Fri, 11 Apr 2008 10:24:48 +0200
Subject: [ALSA] virtuoso: add GPIO 1 mixer control

Add a mixer control for switching whatever it is that is connected to
GPIO pin 1 on the Xonar DX.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/oxygen/virtuoso.c | 53 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

(limited to 'sound')

diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
index 07d7e9b6afb..53d7289f21c 100644
--- a/sound/pci/oxygen/virtuoso.c
+++ b/sound/pci/oxygen/virtuoso.c
@@ -470,6 +470,53 @@ static const struct snd_kcontrol_new alt_switch = {
 	.put = alt_switch_put,
 };
 
+static int unknown_info(struct snd_kcontrol *ctl,
+			struct snd_ctl_elem_info *info)
+{
+	info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	info->count = 1;
+	info->value.enumerated.items = 2;
+	if (info->value.enumerated.item > 1)
+		info->value.enumerated.item = 1;
+	sprintf(info->value.enumerated.name, "%u", info->value.enumerated.item);
+	return 0;
+}
+
+static int unknown_get(struct snd_kcontrol *ctl,
+		       struct snd_ctl_elem_value *value)
+{
+	struct oxygen *chip = ctl->private_data;
+
+	value->value.enumerated.item[0] =
+		!!(oxygen_read16(chip, OXYGEN_GPIO_DATA) & GPIO_DX_UNKNOWN1);
+	return 0;
+}
+
+static int unknown_put(struct snd_kcontrol *ctl,
+		       struct snd_ctl_elem_value *value)
+{
+	struct oxygen *chip = ctl->private_data;
+	u16 old_reg, new_reg;
+
+	spin_lock_irq(&chip->reg_lock);
+	old_reg = oxygen_read16(chip, OXYGEN_GPIO_DATA);
+	if (value->value.enumerated.item[0])
+		new_reg = old_reg | GPIO_DX_UNKNOWN1;
+	else
+		new_reg = old_reg & ~GPIO_DX_UNKNOWN1;
+	oxygen_write16(chip, OXYGEN_GPIO_DATA, new_reg);
+	spin_unlock_irq(&chip->reg_lock);
+	return old_reg != new_reg;
+}
+
+static const struct snd_kcontrol_new unknown_switch = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "PanelConfig?",
+	.info = unknown_info,
+	.get = unknown_get,
+	.put = unknown_put,
+};
+
 static void xonar_dx_ac97_switch(struct oxygen *chip,
 				 unsigned int reg, unsigned int mute)
 {
@@ -515,6 +562,11 @@ static int xonar_mixer_init(struct oxygen *chip)
 	return snd_ctl_add(chip->card, snd_ctl_new1(&alt_switch, chip));
 }
 
+static int xonar_dx_mixer_init(struct oxygen *chip)
+{
+	return snd_ctl_add(chip->card, snd_ctl_new1(&unknown_switch, chip));
+}
+
 static const struct oxygen_model xonar_models[] = {
 	[MODEL_D2] = {
 		.shortname = "Xonar D2",
@@ -574,6 +626,7 @@ static const struct oxygen_model xonar_models[] = {
 		.owner = THIS_MODULE,
 		.init = xonar_dx_init,
 		.control_filter = xonar_dx_control_filter,
+		.mixer_init = xonar_dx_mixer_init,
 		.cleanup = xonar_dx_cleanup,
 		.set_dac_params = set_cs43xx_params,
 		.set_adc_params = set_cs53x1_params,
-- 
cgit v1.2.3-70-g09d2


From 80060ecc45bd101f3decafed5b7ff0879a188d28 Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Fri, 11 Apr 2008 10:25:40 +0200
Subject: [ALSA] virtuoso: initialize two-wire control register

On the Xonar DX, initialize all bits of the two-wire control register.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/oxygen/virtuoso.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
index 53d7289f21c..c7080d6b71c 100644
--- a/sound/pci/oxygen/virtuoso.c
+++ b/sound/pci/oxygen/virtuoso.c
@@ -229,9 +229,10 @@ static void xonar_dx_init(struct oxygen *chip)
 	data->ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK;
 	data->ext_power_bit = GPI_DX_EXT_POWER;
 
-	/* XXX the DACs' datasheets say fast mode is not allowed */
-	oxygen_set_bits16(chip, OXYGEN_2WIRE_BUS_STATUS,
-			  OXYGEN_2WIRE_SPEED_FAST);
+	oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS,
+		       OXYGEN_2WIRE_LENGTH_8 |
+		       OXYGEN_2WIRE_INTERRUPT_MASK |
+		       OXYGEN_2WIRE_SPEED_FAST);
 
 	/* set CPEN (control port mode) and power down */
 	cs4398_write(chip, 8, CS4398_CPEN | CS4398_PDN);
-- 
cgit v1.2.3-70-g09d2


From 4383fae0ec5bc269f9eb4383b223731e3ecd2fe3 Mon Sep 17 00:00:00 2001
From: Jiang zhe <zhe.jiang@intel.com>
Date: Mon, 14 Apr 2008 12:58:57 +0200
Subject: [ALSA] hda-codec - PCI quirk for MSI laptop

Please refer to [0003848] on the alsa mantis.
This patch adds the pci quirk and Mic-Int controller.

Signed-off-by: Jiang zhe <zhe.jiang@intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c | 4 ++++
 1 file changed, 4 insertions(+)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index e5d97c12381..0f6de1eb642 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -6864,6 +6864,9 @@ static struct snd_kcontrol_new alc883_tagra_2ch_mixer[] = {
 	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
 	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
 	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
 	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
 	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
 	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
@@ -7653,6 +7656,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
 	SND_PCI_QUIRK(0x1462, 0x0349, "MSI", ALC883_TARGA_2ch_DIG),
 	SND_PCI_QUIRK(0x1462, 0x040d, "MSI", ALC883_TARGA_2ch_DIG),
 	SND_PCI_QUIRK(0x1462, 0x0579, "MSI", ALC883_TARGA_2ch_DIG),
+	SND_PCI_QUIRK(0x1462, 0x2fb3, "MSI", ALC883_TARGA_2ch_DIG),
 	SND_PCI_QUIRK(0x1462, 0x3729, "MSI S420", ALC883_TARGA_DIG),
 	SND_PCI_QUIRK(0x1462, 0x3783, "NEC S970", ALC883_TARGA_DIG),
 	SND_PCI_QUIRK(0x1462, 0x3b7f, "MSI", ALC883_TARGA_2ch_DIG),
-- 
cgit v1.2.3-70-g09d2


From 32f4876e62d5caba712ca76d96b0018dcc0f9601 Mon Sep 17 00:00:00 2001
From: Mark Brown <broonie@opensource.wolfsonmicro.com>
Date: Mon, 14 Apr 2008 12:59:27 +0200
Subject: [ALSA] soc - Include register in DAPM debug output

When logging register changes in DAPM debug output include the register
number.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/soc/soc-dapm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'sound')

diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 4c64560493f..af3326c6350 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -226,7 +226,7 @@ static int dapm_update_bits(struct snd_soc_dapm_widget *widget)
 		snd_soc_write(codec, widget->reg, new);
 		pop_wait(POP_TIME);
 	}
-	dbg("reg old %x new %x change %d\n", old, new, change);
+	dbg("reg %x old %x new %x change %d\n", widget->reg, old, new, change);
 	return change;
 }
 
-- 
cgit v1.2.3-70-g09d2


From 62cef8212ffa9df3e6c5b358ea2382d90489d590 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Mon, 14 Apr 2008 13:04:18 +0200
Subject: [ALSA] sound/pci/rme9652/hdspm.c: stop inlining largish static
 functions

sound/pci/rme9652/hdspm.c has unusually large number of static inline
functions - 22.

I looked through them and some of them seem to be too big to warrant inlining.

This patch removes "inline" from these static functions (regardless of number
of callsites - gcc nowadays auto-inlines statics with one callsite).

Size difference on 32bit x86:
   text    data     bss     dec     hex filename
  20437    2160     516   23113    5a49 linux-2.6-ALLYES/sound/pci/rme9652/hdspm.o
  18036    2160     516   20712    50e8 linux-2.6.inline-ALLYES/sound/pci/rme9652/hdspm.o

[coding fix by Takashi Iwai <tiwai@suse.de>]

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/rme9652/hdspm.c | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index 38c931c480d..ab423bc8234 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -540,7 +540,8 @@ static void hdspm_set_sgbuf(struct hdspm * hdspm, struct snd_sg_buf *sgbuf,
 
 static inline int HDSPM_bit2freq(int n)
 {
-	static int bit2freq_tab[] = { 0, 32000, 44100, 48000, 64000, 88200,
+	static const int bit2freq_tab[] = {
+		0, 32000, 44100, 48000, 64000, 88200,
 		96000, 128000, 176400, 192000 };
 	if (n < 1 || n > 9)
 		return 0;
@@ -582,7 +583,7 @@ static inline int hdspm_read_pb_gain(struct hdspm * hdspm, unsigned int chan,
 	return hdspm->mixer->ch[chan].pb[pb];
 }
 
-static inline int hdspm_write_in_gain(struct hdspm * hdspm, unsigned int chan,
+static int hdspm_write_in_gain(struct hdspm *hdspm, unsigned int chan,
 				      unsigned int in, unsigned short data)
 {
 	if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
@@ -595,7 +596,7 @@ static inline int hdspm_write_in_gain(struct hdspm * hdspm, unsigned int chan,
 	return 0;
 }
 
-static inline int hdspm_write_pb_gain(struct hdspm * hdspm, unsigned int chan,
+static int hdspm_write_pb_gain(struct hdspm *hdspm, unsigned int chan,
 				      unsigned int pb, unsigned short data)
 {
 	if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
@@ -621,7 +622,7 @@ static inline void snd_hdspm_enable_out(struct hdspm * hdspm, int i, int v)
 }
 
 /* check if same process is writing and reading */
-static inline int snd_hdspm_use_is_exclusive(struct hdspm * hdspm)
+static int snd_hdspm_use_is_exclusive(struct hdspm *hdspm)
 {
 	unsigned long flags;
 	int ret = 1;
@@ -636,7 +637,7 @@ static inline int snd_hdspm_use_is_exclusive(struct hdspm * hdspm)
 }
 
 /* check for external sample rate */
-static inline int hdspm_external_sample_rate(struct hdspm * hdspm)
+static int hdspm_external_sample_rate(struct hdspm *hdspm)
 {
 	if (hdspm->is_aes32) {
 		unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
@@ -787,7 +788,7 @@ static inline void hdspm_stop_audio(struct hdspm * s)
 }
 
 /* should I silence all or only opened ones ? doit all for first even is 4MB*/
-static inline void hdspm_silence_playback(struct hdspm * hdspm)
+static void hdspm_silence_playback(struct hdspm *hdspm)
 {
 	int i;
 	int n = hdspm->period_bytes;
@@ -1057,7 +1058,7 @@ static inline int snd_hdspm_midi_output_possible (struct hdspm *hdspm, int id)
 		return 0;
 }
 
-static inline void snd_hdspm_flush_midi_input (struct hdspm *hdspm, int id)
+static void snd_hdspm_flush_midi_input(struct hdspm *hdspm, int id)
 {
 	while (snd_hdspm_midi_input_available (hdspm, id))
 		snd_hdspm_midi_read_byte (hdspm, id);
-- 
cgit v1.2.3-70-g09d2


From f24bfa53dab478e1bde2d7fd39d3c1a69dc518f1 Mon Sep 17 00:00:00 2001
From: Andreas Mueller <andreas@stapelspeicher.org>
Date: Mon, 14 Apr 2008 13:08:05 +0200
Subject: [ALSA] es1968: fix jitter on some maestro cards

This patch suppresses jitter on several Maestro cards in stereo mode (ALSA of
course).

The patch is also incorporated in the *BSD drivers where I "ported" it from.

Without this patch most of the stereo audio gets out of sync and really
distorted (oss-emulation with mplayer at 48000khz worked somehow).

Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/es1968.c | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

(limited to 'sound')

diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index 67f03264f87..f8f3bb662d1 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -1827,6 +1827,23 @@ snd_es1968_pcm(struct es1968 *chip, int device)
 
 	return 0;
 }
+/*
+ * suppress jitter on some maestros when playing stereo
+ */
+static void snd_es1968_suppress_jitter(struct es1968 *chip, struct esschan *es)
+{
+	unsigned int cp1;
+	unsigned int cp2;
+	unsigned int diff;
+
+	cp1 = __apu_get_register(chip, 0, 5);
+	cp2 = __apu_get_register(chip, 1, 5);
+	diff = (cp1 > cp2 ? cp1 - cp2 : cp2 - cp1);
+
+	if (diff > 1) {
+		__maestro_write(chip, IDR0_DATA_PORT, cp1);
+	}
+}
 
 /*
  * update pointer
@@ -1948,8 +1965,11 @@ static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id)
 		struct esschan *es;
 		spin_lock(&chip->substream_lock);
 		list_for_each_entry(es, &chip->substream_list, list) {
-			if (es->running)
+			if (es->running) {
 				snd_es1968_update_pcm(chip, es);
+				if (es->fmt & ESS_FMT_STEREO)
+					snd_es1968_suppress_jitter(chip, es);
+			}
 		}
 		spin_unlock(&chip->substream_lock);
 		if (chip->in_measurement) {
-- 
cgit v1.2.3-70-g09d2


From 66c9aa6043798197e1760eaf4c5f510d6c69b95a Mon Sep 17 00:00:00 2001
From: Andrew Morton <akpm@linux-foundation.org>
Date: Mon, 14 Apr 2008 13:09:33 +0200
Subject: [ALSA] es1968 - fix coding style in the last patch

WARNING: braces {} are not necessary for single statement blocks
#40: FILE: sound/pci/es1968.c:1831:
+       if (diff > 1) {
+               __maestro_write(chip, IDR0_DATA_PORT, cp1);
+       }

total: 0 errors, 1 warnings, 35 lines checked

./patches/es1968-fix-jitter-on-some-maestro-cards.patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

Please run checkpatch prior to sending patches

Cc: Andreas Mueller <andreas@stapelspeicher.org>
Tested-by: Rene Herman <rene.herman@keyaccess.nl>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/es1968.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index f8f3bb662d1..13837989606 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -1840,9 +1840,8 @@ static void snd_es1968_suppress_jitter(struct es1968 *chip, struct esschan *es)
 	cp2 = __apu_get_register(chip, 1, 5);
 	diff = (cp1 > cp2 ? cp1 - cp2 : cp2 - cp1);
 
-	if (diff > 1) {
+	if (diff > 1)
 		__maestro_write(chip, IDR0_DATA_PORT, cp1);
-	}
 }
 
 /*
-- 
cgit v1.2.3-70-g09d2


From eaa9985b4edb5f8008998abdda8b85ddeba05f1f Mon Sep 17 00:00:00 2001
From: Frederik Deweerdt <deweerdt@free.fr>
Date: Mon, 14 Apr 2008 13:11:44 +0200
Subject: [ALSA] hda-codec - Fix unbalanced mutex

On Wed, Apr 02, 2008 at 08:19:29AM -0400, Miles Lane wrote:
> [   48.765906] [ BUG: bad unlock balance detected! ]
> [   48.765912] -------------------------------------
> [   48.765918] pulseaudio/4277 is trying to release lock
> (&codec->spdif_mutex) at:
> [   48.765930] [<c03031b7>] mutex_unlock+0x8/0xa
> [   48.765945] but there are no more locks to release!
> [   48.765950]
> [   48.765952] other info that might help us debug this:
> [   48.765959] 2 locks held by pulseaudio/4277:
> [   48.765965]  #0:  (&pcm->open_mutex){--..}, at: [<f89f134b>]
> snd_pcm_open+0xc1/0x1ba [snd_pcm]
> [   48.766003]  #1:  (&chip->open_mutex){--..}, at: [<f8b4f13d>]
> azx_pcm_open+0x36/0x184 [snd_hda_intel]
> [   48.766057]
> [   48.766059] stack backtrace:
> [   48.766066] Pid: 4277, comm: pulseaudio Not tainted 2.6.25-rc8-mm1 #12
> [   48.766086]  [<c013afc6>] print_unlock_inbalance_bug+0xce/0xd8
> [   48.766107]  [<c0109e1c>] ? save_stack_trace+0x1d/0x3b
> [   48.766130]  [<c012f54e>] ? __kernel_text_address+0x1b/0x27
> [   48.766146]  [<c0104533>] ? dump_trace+0xcd/0xd9
> [   48.766160]  [<c0109d9e>] ? save_stack_address+0x0/0x2c
> [   48.766176]  [<c013b80a>] ? find_usage_backwards+0xa4/0xc3
> [   48.766193]  [<c013cfb5>] lock_release_non_nested+0x84/0x120
> [   48.766209]  [<c03031b7>] ? mutex_unlock+0x8/0xa
> [   48.766222]  [<c013d1bb>] lock_release+0x16a/0x199
> [   48.766238]  [<c0303137>] __mutex_unlock_slowpath+0xa9/0x121
> [   48.766252]  [<c03031b7>] mutex_unlock+0x8/0xa
> [   48.766263]  [<f8b4ffd8>] snd_hda_multi_out_analog_open+0xd3/0xef
> [snd_hda_intel]

The following patch should fix it.

Cc: "Miles Lane" <miles.lane@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/hda_codec.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'sound')

diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 689d177c17b..a6be6e3e871 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -2665,8 +2665,8 @@ int snd_hda_multi_out_analog_open(struct hda_codec *codec,
 			if (mout->spdif_maxbps < hinfo->maxbps)
 				hinfo->maxbps = mout->spdif_maxbps;
 		}
+		mutex_unlock(&codec->spdif_mutex);
 	}
-	mutex_unlock(&codec->spdif_mutex);
 	return snd_pcm_hw_constraint_step(substream->runtime, 0,
 					  SNDRV_PCM_HW_PARAM_CHANNELS, 2);
 }
-- 
cgit v1.2.3-70-g09d2


From b9d43bcd061956c8144bcb453d07d13236b6ab28 Mon Sep 17 00:00:00 2001
From: Pavel Machek <pavel@suse.cz>
Date: Mon, 14 Apr 2008 13:12:47 +0200
Subject: [ALSA] usb audio: Fix another Dallas quirk

Dallas USB speakers are buggy in more than one way. One of configs
they offer does not work at all.

Signed-off-by: Pavel Machek <pavel@suse.cz>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/usbaudio.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

(limited to 'sound')

diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 5c40c031dd5..ff2e09a4613 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -2676,12 +2676,23 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
 	int format;
 	struct audioformat *fp;
 	unsigned char *fmt, *csep;
+	int num;
 
 	dev = chip->dev;
 
 	/* parse the interface's altsettings */
 	iface = usb_ifnum_to_if(dev, iface_no);
-	for (i = 0; i < iface->num_altsetting; i++) {
+
+	num = iface->num_altsetting;
+
+	/*
+	 * Dallas DS4201 workaround: It presents 5 altsettings, but the last
+	 * one misses syncpipe, and does not produce any sound.
+	 */
+	if (chip->usb_id == USB_ID(0x04fa, 0x4201))
+		num = 4;
+
+	for (i = 0; i < num; i++) {
 		alts = &iface->altsetting[i];
 		altsd = get_iface_desc(alts);
 		/* skip invalid one */
-- 
cgit v1.2.3-70-g09d2


From 2a56f51bcc3650ecff806450f7fdab5edf57618f Mon Sep 17 00:00:00 2001
From: Pavel Machek <pavel@suse.cz>
Date: Mon, 14 Apr 2008 13:14:22 +0200
Subject: [ALSA] usb audio: make quirk handling more readable, and fix
 commented-out code

usb audio contains useful  debugging code, protected by #if
0. Unfortunately, it will not compile because variable names changed;
fix it.

Dallas workaround is formatted in a way where it is not quite obvious
what is normal code and what is quirk. Reformat it to make it obvious.

Signed-off-by: Pavel Machek <pavel@suse.cz>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/usbaudio.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

(limited to 'sound')

diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index ff2e09a4613..26fb5769d95 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -1427,8 +1427,8 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
 	subs->cur_audiofmt = fmt;
 
 #if 0
-	printk("setting done: format = %d, rate = %d, channels = %d\n",
-	       fmt->format, fmt->rate, fmt->channels);
+	printk("setting done: format = %d, rate = %d..%d, channels = %d\n",
+	       fmt->format, fmt->rate_min, fmt->rate_max, fmt->channels);
 	printk("  datapipe = 0x%0x, syncpipe = 0x%0x\n",
 	       subs->datapipe, subs->syncpipe);
 #endif
@@ -2468,11 +2468,12 @@ static int parse_audio_format_i_type(struct snd_usb_audio *chip, struct audiofor
 		}
 		break;
 	case USB_AUDIO_FORMAT_PCM8:
-		/* Dallas DS4201 workaround */
+		pcm_format = SNDRV_PCM_FORMAT_U8;
+
+		/* Dallas DS4201 workaround: it advertises U8 format, but really
+		   supports S8. */
 		if (chip->usb_id == USB_ID(0x04fa, 0x4201))
 			pcm_format = SNDRV_PCM_FORMAT_S8;
-		else
-			pcm_format = SNDRV_PCM_FORMAT_U8;
 		break;
 	case USB_AUDIO_FORMAT_IEEE_FLOAT:
 		pcm_format = SNDRV_PCM_FORMAT_FLOAT_LE;
-- 
cgit v1.2.3-70-g09d2


From 07f51a727462696ddea01c7a7750c27796a0e1f3 Mon Sep 17 00:00:00 2001
From: Pavel Machek <pavel@suse.cz>
Date: Mon, 14 Apr 2008 13:15:56 +0200
Subject: [ALSA] sound/usb/usbaudio.c: coding style

Putting space between ! and variable is a strange coding style, fix
that, also make it fit into 80 columns where that is easy.

Signed-off-by: Pavel Machek <pavel@suse.cz>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/usbaudio.c | 63 ++++++++++++++++++++++++++--------------------------
 1 file changed, 32 insertions(+), 31 deletions(-)

(limited to 'sound')

diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 26fb5769d95..7b3bcf1916d 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -64,9 +64,10 @@ MODULE_SUPPORTED_DEVICE("{{Generic,USB Audio}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;	/* Enable this card */
-static int vid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; /* Vendor ID for this card */
-static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; /* Product ID for this card */
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */
+/* Vendor/product IDs for this card */
+static int vid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 };
+static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 };
 static int nrpacks = 8;		/* max. number of packets per urb */
 static int async_unlink = 1;
 static int device_setup[SNDRV_CARDS]; /* device parameter for this card*/
@@ -687,7 +688,7 @@ static void snd_complete_urb(struct urb *urb)
 	int err = 0;
 
 	if ((subs->running && subs->ops.retire(subs, substream->runtime, urb)) ||
-	    ! subs->running || /* can be stopped during retire callback */
+	    !subs->running || /* can be stopped during retire callback */
 	    (err = subs->ops.prepare(subs, substream->runtime, urb)) < 0 ||
 	    (err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
 		clear_bit(ctx->index, &subs->active_mask);
@@ -710,7 +711,7 @@ static void snd_complete_sync_urb(struct urb *urb)
 	int err = 0;
 
 	if ((subs->running && subs->ops.retire_sync(subs, substream->runtime, urb)) ||
-	    ! subs->running || /* can be stopped during retire callback */
+	    !subs->running || /* can be stopped during retire callback */
 	    (err = subs->ops.prepare_sync(subs, substream->runtime, urb)) < 0 ||
 	    (err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
 		clear_bit(ctx->index + 16, &subs->active_mask);
@@ -740,7 +741,7 @@ static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, size_t s
 		vfree(runtime->dma_area);
 	}
 	runtime->dma_area = vmalloc(size);
-	if (! runtime->dma_area)
+	if (!runtime->dma_area)
 		return -ENOMEM;
 	runtime->dma_bytes = size;
 	return 0;
@@ -772,12 +773,12 @@ static int deactivate_urbs(struct snd_usb_substream *subs, int force, int can_sl
 
 	async = !can_sleep && async_unlink;
 
-	if (! async && in_interrupt())
+	if (!async && in_interrupt())
 		return 0;
 
 	for (i = 0; i < subs->nurbs; i++) {
 		if (test_bit(i, &subs->active_mask)) {
-			if (! test_and_set_bit(i, &subs->unlink_mask)) {
+			if (!test_and_set_bit(i, &subs->unlink_mask)) {
 				struct urb *u = subs->dataurb[i].urb;
 				if (async)
 					usb_unlink_urb(u);
@@ -789,7 +790,7 @@ static int deactivate_urbs(struct snd_usb_substream *subs, int force, int can_sl
 	if (subs->syncpipe) {
 		for (i = 0; i < SYNC_URBS; i++) {
 			if (test_bit(i+16, &subs->active_mask)) {
- 				if (! test_and_set_bit(i+16, &subs->unlink_mask)) {
+				if (!test_and_set_bit(i+16, &subs->unlink_mask)) {
 					struct urb *u = subs->syncurb[i].urb;
 					if (async)
 						usb_unlink_urb(u);
@@ -1137,12 +1138,12 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri
 		if (subs->fmt_type == USB_FORMAT_TYPE_II)
 			u->packets++; /* for transfer delimiter */
 		u->urb = usb_alloc_urb(u->packets, GFP_KERNEL);
-		if (! u->urb)
+		if (!u->urb)
 			goto out_of_memory;
 		u->urb->transfer_buffer =
 			usb_buffer_alloc(subs->dev, u->buffer_size, GFP_KERNEL,
 					 &u->urb->transfer_dma);
-		if (! u->urb->transfer_buffer)
+		if (!u->urb->transfer_buffer)
 			goto out_of_memory;
 		u->urb->pipe = subs->datapipe;
 		u->urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
@@ -1155,7 +1156,7 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri
 		/* allocate and initialize sync urbs */
 		subs->syncbuf = usb_buffer_alloc(subs->dev, SYNC_URBS * 4,
 						 GFP_KERNEL, &subs->sync_dma);
-		if (! subs->syncbuf)
+		if (!subs->syncbuf)
 			goto out_of_memory;
 		for (i = 0; i < SYNC_URBS; i++) {
 			struct snd_urb_ctx *u = &subs->syncurb[i];
@@ -1163,7 +1164,7 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri
 			u->subs = subs;
 			u->packets = 1;
 			u->urb = usb_alloc_urb(1, GFP_KERNEL);
-			if (! u->urb)
+			if (!u->urb)
 				goto out_of_memory;
 			u->urb->transfer_buffer = subs->syncbuf + i * 4;
 			u->urb->transfer_dma = subs->sync_dma + i * 4;
@@ -1463,7 +1464,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
 	rate = params_rate(hw_params);
 	channels = params_channels(hw_params);
 	fmt = find_format(subs, format, rate, channels);
-	if (! fmt) {
+	if (!fmt) {
 		snd_printd(KERN_DEBUG "cannot set format: format = 0x%x, rate = %d, channels = %d\n",
 			   format, rate, channels);
 		return -EINVAL;
@@ -1584,7 +1585,7 @@ static int hw_check_valid_format(struct snd_pcm_hw_params *params, struct audiof
 	struct snd_mask *fmts = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
 
 	/* check the format */
-	if (! snd_mask_test(fmts, fp->format)) {
+	if (!snd_mask_test(fmts, fp->format)) {
 		hwc_debug("   > check: no supported format %d\n", fp->format);
 		return 0;
 	}
@@ -1620,7 +1621,7 @@ static int hw_rule_rate(struct snd_pcm_hw_params *params,
 	list_for_each(p, &subs->fmt_list) {
 		struct audioformat *fp;
 		fp = list_entry(p, struct audioformat, list);
-		if (! hw_check_valid_format(params, fp))
+		if (!hw_check_valid_format(params, fp))
 			continue;
 		if (changed++) {
 			if (rmin > fp->rate_min)
@@ -1633,7 +1634,7 @@ static int hw_rule_rate(struct snd_pcm_hw_params *params,
 		}
 	}
 
-	if (! changed) {
+	if (!changed) {
 		hwc_debug("  --> get empty\n");
 		it->empty = 1;
 		return -EINVAL;
@@ -1674,7 +1675,7 @@ static int hw_rule_channels(struct snd_pcm_hw_params *params,
 	list_for_each(p, &subs->fmt_list) {
 		struct audioformat *fp;
 		fp = list_entry(p, struct audioformat, list);
-		if (! hw_check_valid_format(params, fp))
+		if (!hw_check_valid_format(params, fp))
 			continue;
 		if (changed++) {
 			if (rmin > fp->channels)
@@ -1687,7 +1688,7 @@ static int hw_rule_channels(struct snd_pcm_hw_params *params,
 		}
 	}
 
-	if (! changed) {
+	if (!changed) {
 		hwc_debug("  --> get empty\n");
 		it->empty = 1;
 		return -EINVAL;
@@ -1727,7 +1728,7 @@ static int hw_rule_format(struct snd_pcm_hw_params *params,
 	list_for_each(p, &subs->fmt_list) {
 		struct audioformat *fp;
 		fp = list_entry(p, struct audioformat, list);
-		if (! hw_check_valid_format(params, fp))
+		if (!hw_check_valid_format(params, fp))
 			continue;
 		fbits |= (1ULL << fp->format);
 	}
@@ -1736,7 +1737,7 @@ static int hw_rule_format(struct snd_pcm_hw_params *params,
 	oldbits[1] = fmt->bits[1];
 	fmt->bits[0] &= (u32)fbits;
 	fmt->bits[1] &= (u32)(fbits >> 32);
-	if (! fmt->bits[0] && ! fmt->bits[1]) {
+	if (!fmt->bits[0] && !fmt->bits[1]) {
 		hwc_debug("  --> get empty\n");
 		return -EINVAL;
 	}
@@ -2227,7 +2228,7 @@ static void proc_pcm_format_add(struct snd_usb_stream *stream)
 	struct snd_card *card = stream->chip->card;
 
 	sprintf(name, "stream%d", stream->pcm_index);
-	if (! snd_card_proc_new(card, name, &entry))
+	if (!snd_card_proc_new(card, name, &entry))
 		snd_info_set_text_ops(entry, stream, proc_pcm_format_read);
 }
 
@@ -2283,7 +2284,7 @@ static void free_substream(struct snd_usb_substream *subs)
 {
 	struct list_head *p, *n;
 
-	if (! subs->num_formats)
+	if (!subs->num_formats)
 		return; /* not initialized */
 	list_for_each_safe(p, n, &subs->fmt_list) {
 		struct audioformat *fp = list_entry(p, struct audioformat, list);
@@ -2333,7 +2334,7 @@ static int add_audio_endpoint(struct snd_usb_audio *chip, int stream, struct aud
 		if (as->fmt_type != fp->fmt_type)
 			continue;
 		subs = &as->substream[stream];
-		if (! subs->endpoint)
+		if (!subs->endpoint)
 			continue;
 		if (subs->endpoint == fp->endpoint) {
 			list_add_tail(&fp->list, &subs->fmt_list);
@@ -2359,7 +2360,7 @@ static int add_audio_endpoint(struct snd_usb_audio *chip, int stream, struct aud
 
 	/* create a new pcm */
 	as = kzalloc(sizeof(*as), GFP_KERNEL);
-	if (! as)
+	if (!as)
 		return -ENOMEM;
 	as->pcm_index = chip->pcm_devs;
 	as->chip = chip;
@@ -3392,14 +3393,14 @@ static int snd_usb_create_quirk(struct snd_usb_audio *chip,
 static void proc_audio_usbbus_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
 {
 	struct snd_usb_audio *chip = entry->private_data;
-	if (! chip->shutdown)
+	if (!chip->shutdown)
 		snd_iprintf(buffer, "%03d/%03d\n", chip->dev->bus->busnum, chip->dev->devnum);
 }
 
 static void proc_audio_usbid_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
 {
 	struct snd_usb_audio *chip = entry->private_data;
-	if (! chip->shutdown)
+	if (!chip->shutdown)
 		snd_iprintf(buffer, "%04x:%04x\n", 
 			    USB_ID_VENDOR(chip->usb_id),
 			    USB_ID_PRODUCT(chip->usb_id));
@@ -3408,9 +3409,9 @@ static void proc_audio_usbid_read(struct snd_info_entry *entry, struct snd_info_
 static void snd_usb_audio_create_proc(struct snd_usb_audio *chip)
 {
 	struct snd_info_entry *entry;
-	if (! snd_card_proc_new(chip->card, "usbbus", &entry))
+	if (!snd_card_proc_new(chip->card, "usbbus", &entry))
 		snd_info_set_text_ops(entry, chip, proc_audio_usbbus_read);
-	if (! snd_card_proc_new(chip->card, "usbid", &entry))
+	if (!snd_card_proc_new(chip->card, "usbid", &entry))
 		snd_info_set_text_ops(entry, chip, proc_audio_usbid_read);
 }
 
@@ -3617,8 +3618,8 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
 				snd_card_set_dev(chip->card, &intf->dev);
 				break;
 			}
-		if (! chip) {
-			snd_printk(KERN_ERR "no available usb audio device\n");
+		if (!chip) {
+			printk(KERN_ERR "no available usb audio device\n");
 			goto __error;
 		}
 	}
-- 
cgit v1.2.3-70-g09d2


From 64654c2f9e7875a982a9c3b4456ed11ad811ec61 Mon Sep 17 00:00:00 2001
From: Jiang zhe <zhe.jiang@intel.com>
Date: Mon, 14 Apr 2008 13:26:21 +0200
Subject: [ALSA] hda - Should use HDA_OUTPUT instead of HDA_INPUT to mute pin
 15 of ALC880

To mute the output of Pin widget 15 in ALC880, we should use the
HDA_OUTPUT. However, current code looks like :
snd_hda_codec_amp_stereo(codec, 0x15, HDA_INPUT, 0, HDA_AMP_MUTE, bits);
It may be a misspelling.

Signed-off-by: Jiang zhe <zhe.jiang@intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 0f6de1eb642..3aa182a1675 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -1894,7 +1894,7 @@ static void alc880_uniwill_p53_hp_automute(struct hda_codec *codec)
  	present = snd_hda_codec_read(codec, 0x14, 0,
 				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
 	bits = present ? HDA_AMP_MUTE : 0;
-	snd_hda_codec_amp_stereo(codec, 0x15, HDA_INPUT, 0, HDA_AMP_MUTE, bits);
+	snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, HDA_AMP_MUTE, bits);
 }
 
 static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec)
-- 
cgit v1.2.3-70-g09d2


From 5b030389e4ba72cc4e9ad37a5770b32f0353564d Mon Sep 17 00:00:00 2001
From: Jiang zhe <zhe.jiang@intel.com>
Date: Mon, 14 Apr 2008 13:26:53 +0200
Subject: [ALSA] hda - PCI quirk for laptop LG which use CMI9880

Please refer to [0003874] on the alsa mantis.
This patch added the pci quirk.

Signed-off-by: Jiang zhe <zhe.jiang@intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_cmedia.c | 1 +
 1 file changed, 1 insertion(+)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c
index 8d142851aac..c73ce074a6e 100644
--- a/sound/pci/hda/patch_cmedia.c
+++ b/sound/pci/hda/patch_cmedia.c
@@ -611,6 +611,7 @@ static const char *cmi9880_models[CMI_MODELS] = {
 
 static struct snd_pci_quirk cmi9880_cfg_tbl[] = {
 	SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", CMI_FULL_DIG),
+	SND_PCI_QUIRK(0x1854, 0x0032, "LG", CMI_FULL_DIG),
 	{} /* terminator */
 };
 
-- 
cgit v1.2.3-70-g09d2


From 06a9c30cdda43ca82d7f22c8ebeb93e691f85b5f Mon Sep 17 00:00:00 2001
From: Tony Vroon <tony@linx.net>
Date: Mon, 14 Apr 2008 13:31:45 +0200
Subject: [ALSA] hda - Fujitsu Lifebook PC speaker signal

The legacy PC speaker signal was not routed to outputs. The codec is not
prevented from powering down in this patch, although I suppose one could
argue that perhaps it should be. Let me know if anyone feels strongly one
way or the other.

Signed-off-by: Tony Vroon <tony@linx.net>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c | 2 ++
 1 file changed, 2 insertions(+)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 3aa182a1675..830d6626e10 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -8784,6 +8784,8 @@ static struct snd_kcontrol_new alc262_fujitsu_mixer[] = {
 	},
 	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
 	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("PC Speaker Volume", 0x0b, 0x05, HDA_INPUT),
+	HDA_CODEC_MUTE("PC Speaker Switch", 0x0b, 0x05, HDA_INPUT),
 	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
 	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
 	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-- 
cgit v1.2.3-70-g09d2


From 780c8be4ab6c7baf5cdfa1102f56480acb8a2479 Mon Sep 17 00:00:00 2001
From: Matthew Ranostay <mranostay@embeddedalley.com>
Date: Mon, 14 Apr 2008 13:32:27 +0200
Subject: [ALSA] hda: Correct SPDIF out default config

Several laptops have have the SPDIF out defined as 'Digital other out'
when it should be 'SPDIF out' in the default config.

Signed-off-by: Matthew Ranostay <mranostay@embeddedalley.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_sigmatel.c | 7 +++++++
 1 file changed, 7 insertions(+)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 69cd3b23f5a..d79580c2986 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -3778,6 +3778,13 @@ static int patch_stac927x(struct hda_codec *codec)
 		spec->mixer = stac927x_mixer;
 		break;
 	case STAC_DELL_BIOS:
+		switch (codec->subsystem_id) {
+		case 0x10280209:
+		case 0x1028022e:
+			/* correct the device field to SPDIF out */
+			stac92xx_set_config_reg(codec, 0x21, 0x01442070);
+			break;
+		};
 		/* configure the analog microphone on some laptops */
 		stac92xx_set_config_reg(codec, 0x0c, 0x90a79130);
 		/* correct the front output jack as a hp out */
-- 
cgit v1.2.3-70-g09d2


From 0fc9dec46fae19da9899c580a6b870202103f8bb Mon Sep 17 00:00:00 2001
From: Matthew Ranostay <mranostay@embeddedalley.com>
Date: Mon, 14 Apr 2008 13:32:54 +0200
Subject: [ALSA] hda: EAPD power management

Power management support for EAPD enabled laptops, when headphones
are sensed it pulls the EAPD GPIO line low to power it down.

Signed-off-by: Matthew Ranostay <mranostay@embeddedalley.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_sigmatel.c | 25 +++++++++++++++++++------
 1 file changed, 19 insertions(+), 6 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index d79580c2986..e1d07ab5cd1 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -129,6 +129,7 @@ struct sigmatel_spec {
 	unsigned int hp_detect: 1;
 
 	/* gpio lines */
+	unsigned int eapd_mask;
 	unsigned int gpio_mask;
 	unsigned int gpio_dir;
 	unsigned int gpio_data;
@@ -3183,6 +3184,10 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
 		for (i = 0; i < cfg->speaker_outs; i++)
 			stac92xx_reset_pinctl(codec, cfg->speaker_pins[i],
 						AC_PINCTL_OUT_EN);
+		if (spec->eapd_mask)
+			stac_gpio_set(codec, spec->gpio_mask,
+				spec->gpio_dir, spec->gpio_data &
+				~spec->eapd_mask);
 	} else {
 		/* enable lineouts, disable hp */
 		for (i = 0; i < cfg->line_outs; i++)
@@ -3191,6 +3196,10 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
 		for (i = 0; i < cfg->speaker_outs; i++)
 			stac92xx_set_pinctl(codec, cfg->speaker_pins[i],
 						AC_PINCTL_OUT_EN);
+		if (spec->eapd_mask)
+			stac_gpio_set(codec, spec->gpio_mask,
+				spec->gpio_dir, spec->gpio_data |
+				spec->eapd_mask);
 	}
 } 
 
@@ -3478,7 +3487,7 @@ again:
 	spec->num_dmuxes = ARRAY_SIZE(stac92hd73xx_dmux_nids);
 	spec->dinput_mux = &stac92hd73xx_dmux;
 	/* GPIO0 High = Enable EAPD */
-	spec->gpio_mask = spec->gpio_dir = 0x1;
+	spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x1;
 	spec->gpio_data = 0x01;
 
 	switch (spec->board_config) {
@@ -3584,7 +3593,10 @@ again:
 	spec->aloopback_shift = 0;
 
 	/* GPIO0 High = EAPD */
-	spec->gpio_mask = spec->gpio_dir = spec->gpio_data = 0x1;
+	spec->gpio_mask = 0x01;
+	spec->gpio_dir = 0x01;
+	spec->gpio_mask = 0x01;
+	spec->gpio_data = 0x01;
 
 	spec->mux_nids = stac92hd71bxx_mux_nids;
 	spec->adc_nids = stac92hd71bxx_adc_nids;
@@ -3770,7 +3782,7 @@ static int patch_stac927x(struct hda_codec *codec)
 	case STAC_D965_3ST:
 	case STAC_D965_5ST:
 		/* GPIO0 High = Enable EAPD */
-		spec->gpio_mask = spec->gpio_dir = 0x01;
+		spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x01;
 		spec->gpio_data = 0x01;
 		spec->num_dmics = 0;
 
@@ -3794,7 +3806,7 @@ static int patch_stac927x(struct hda_codec *codec)
 		/* fallthru */
 	case STAC_DELL_3ST:
 		/* GPIO2 High = Enable EAPD */
-		spec->gpio_mask = spec->gpio_dir = 0x04;
+		spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x04;
 		spec->gpio_data = 0x04;
 		spec->dmic_nids = stac927x_dmic_nids;
 		spec->num_dmics = STAC927X_NUM_DMICS;
@@ -3806,7 +3818,7 @@ static int patch_stac927x(struct hda_codec *codec)
 		break;
 	default:
 		/* GPIO0 High = Enable EAPD */
-		spec->gpio_mask = spec->gpio_dir = 0x1;
+		spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x1;
 		spec->gpio_data = 0x01;
 		spec->num_dmics = 0;
 
@@ -3910,6 +3922,7 @@ static int patch_stac9205(struct hda_codec *codec)
 					  (AC_USRSP_EN | STAC_HP_EVENT));
 
 		spec->gpio_dir = 0x0b;
+		spec->eapd_mask = 0x01;
 		spec->gpio_mask = 0x1b;
 		spec->gpio_mute = 0x10;
 		/* GPIO0 High = EAPD, GPIO1 Low = Headphone Mute,
@@ -3919,7 +3932,7 @@ static int patch_stac9205(struct hda_codec *codec)
 		break;
 	default:
 		/* GPIO0 High = EAPD */
-		spec->gpio_mask = spec->gpio_dir = 0x1;
+		spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x1;
 		spec->gpio_data = 0x01;
 		break;
 	}
-- 
cgit v1.2.3-70-g09d2


From 8b45a209935c4b79905182608922736ba0e5579e Mon Sep 17 00:00:00 2001
From: Kay Sievers <kay.sievers@vrfy.org>
Date: Mon, 14 Apr 2008 13:33:36 +0200
Subject: [ALSA] sound: fix platform driver hotplug/coldplug

Since 43cc71eed1250755986da4c0f9898f9a635cb3bf, the platform modalias is
prefixed with "platform:".  Add MODULE_ALIAS() to the hotpluggable sound
platform drivers, to re-enable auto loading.

[dbrownell@users.sourceforge.net: more drivers, registration fixes]

Signed-off-by: Kay Sievers <kay.sievers@vrfy.org>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/arm/pxa2xx-ac97.c      | 2 ++
 sound/drivers/ml403-ac97cr.c | 4 ++++
 sound/soc/soc-core.c         | 2 ++
 3 files changed, 8 insertions(+)

(limited to 'sound')

diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c
index 490729799e5..71fbf8d7ee8 100644
--- a/sound/arm/pxa2xx-ac97.c
+++ b/sound/arm/pxa2xx-ac97.c
@@ -424,6 +424,7 @@ static struct platform_driver pxa2xx_ac97_driver = {
 	.resume		= pxa2xx_ac97_resume,
 	.driver		= {
 		.name	= "pxa2xx-ac97",
+		.owner	= THIS_MODULE,
 	},
 };
 
@@ -443,3 +444,4 @@ module_exit(pxa2xx_ac97_exit);
 MODULE_AUTHOR("Nicolas Pitre");
 MODULE_DESCRIPTION("AC97 driver for the Intel PXA2xx chip");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa2xx-ac97");
diff --git a/sound/drivers/ml403-ac97cr.c b/sound/drivers/ml403-ac97cr.c
index b654007331d..ecdbeb6d360 100644
--- a/sound/drivers/ml403-ac97cr.c
+++ b/sound/drivers/ml403-ac97cr.c
@@ -1328,11 +1328,15 @@ static int snd_ml403_ac97cr_remove(struct platform_device *pfdev)
 	return 0;
 }
 
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:" SND_ML403_AC97CR_DRIVER);
+
 static struct platform_driver snd_ml403_ac97cr_driver = {
 	.probe = snd_ml403_ac97cr_probe,
 	.remove = snd_ml403_ac97cr_remove,
 	.driver = {
 		.name = SND_ML403_AC97CR_DRIVER,
+		.owner = THIS_MODULE,
 	},
 };
 
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 9eb5479787c..e148db940cf 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -839,6 +839,7 @@ static int soc_remove(struct platform_device *pdev)
 static struct platform_driver soc_driver = {
 	.driver		= {
 		.name		= "soc-audio",
+		.owner		= THIS_MODULE,
 	},
 	.probe		= soc_probe,
 	.remove		= soc_remove,
@@ -1601,3 +1602,4 @@ module_exit(snd_soc_exit);
 MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
 MODULE_DESCRIPTION("ALSA SoC Core");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:soc-audio");
-- 
cgit v1.2.3-70-g09d2


From eb5a66216658a1c879ab05dcdc65ce7005c4780b Mon Sep 17 00:00:00 2001
From: Herton Ronaldo Krzesinski <herton@mandriva.com>
Date: Mon, 14 Apr 2008 13:46:28 +0200
Subject: [ALSA] hda-intel: Add Quanta IL1 ALC267 model

This adds support for Quanta IL1 mini-notebook to alsa, defining a new model
for it. It comes with an ALC267 codec chip. Some notes about this model:

* In headphone automute, I use AC_VERB_SET_PIN_WIDGET_CONTROL instead of common
  amp mute, to avoid conflict with mixer switch (mixer and automute use the
  same nid).
* The only connected capture sources in the hardware are the internal mic and
  external mic jack. So instead of using an input source selector like on other
  ALC268 models, the mic automute automatically switch between captures.

Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 Documentation/sound/alsa/ALSA-Configuration.txt |  3 +-
 sound/pci/hda/patch_realtek.c                   | 76 +++++++++++++++++++++++++
 2 files changed, 78 insertions(+), 1 deletion(-)

(limited to 'sound')

diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 08256fcb274..3413644dff1 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -829,7 +829,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
 	  basic		fixed pin assignment w/o SPDIF
 	  auto		auto-config reading BIOS (default)
 
-	ALC268
+	ALC267/268
+	  quanta-il1	Quanta IL1 mini-notebook
 	  3stack	3-stack model
 	  toshiba	Toshiba A205
 	  acer		Acer laptops
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 830d6626e10..181db2177a1 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -105,6 +105,7 @@ enum {
 
 /* ALC268 models */
 enum {
+	ALC267_QUANTA_IL1,
 	ALC268_3ST,
 	ALC268_TOSHIBA,
 	ALC268_ACER,
@@ -9902,6 +9903,64 @@ static void alc268_dell_unsol_event(struct hda_codec *codec,
 
 #define alc268_dell_init_hook	alc268_dell_automute
 
+static struct snd_kcontrol_new alc267_quanta_il1_mixer[] = {
+	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x2, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Mic Capture Volume", 0x23, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Mic Capture Switch", 0x23, 2, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Ext Mic Boost", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
+	{ }
+};
+
+static struct hda_verb alc267_quanta_il1_verbs[] = {
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
+	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
+	{ }
+};
+
+static void alc267_quanta_il1_hp_automute(struct hda_codec *codec)
+{
+	unsigned int present;
+
+	present = snd_hda_codec_read(codec, 0x15, 0, AC_VERB_GET_PIN_SENSE, 0)
+		& AC_PINSENSE_PRESENCE;
+	snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+			    present ? 0 : PIN_OUT);
+}
+
+static void alc267_quanta_il1_mic_automute(struct hda_codec *codec)
+{
+	unsigned int present;
+
+	present = snd_hda_codec_read(codec, 0x18, 0,
+				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+	snd_hda_codec_write(codec, 0x23, 0,
+			    AC_VERB_SET_CONNECT_SEL,
+			    present ? 0x00 : 0x01);
+}
+
+static void alc267_quanta_il1_automute(struct hda_codec *codec)
+{
+	alc267_quanta_il1_hp_automute(codec);
+	alc267_quanta_il1_mic_automute(codec);
+}
+
+static void alc267_quanta_il1_unsol_event(struct hda_codec *codec,
+					   unsigned int res)
+{
+	switch (res >> 26) {
+	case ALC880_HP_EVENT:
+		alc267_quanta_il1_hp_automute(codec);
+		break;
+	case ALC880_MIC_EVENT:
+		alc267_quanta_il1_mic_automute(codec);
+		break;
+	}
+}
+
 /*
  * generic initialization of ADC, input mixers and output mixers
  */
@@ -10324,6 +10383,7 @@ static void alc268_auto_init(struct hda_codec *codec)
  * configuration and preset
  */
 static const char *alc268_models[ALC268_MODEL_LAST] = {
+	[ALC267_QUANTA_IL1]	= "quanta-il1",
 	[ALC268_3ST]		= "3stack",
 	[ALC268_TOSHIBA]	= "toshiba",
 	[ALC268_ACER]		= "acer",
@@ -10346,11 +10406,27 @@ static struct snd_pci_quirk alc268_cfg_tbl[] = {
 	SND_PCI_QUIRK(0x1179, 0xff10, "TOSHIBA A205", ALC268_TOSHIBA),
 	SND_PCI_QUIRK(0x1179, 0xff50, "TOSHIBA A305", ALC268_TOSHIBA),
 	SND_PCI_QUIRK(0x152d, 0x0763, "Diverse (CPR2000)", ALC268_ACER),
+	SND_PCI_QUIRK(0x152d, 0x0771, "Quanta IL1", ALC267_QUANTA_IL1),
 	SND_PCI_QUIRK(0x1170, 0x0040, "ZEPTO", ALC268_ZEPTO),
 	{}
 };
 
 static struct alc_config_preset alc268_presets[] = {
+	[ALC267_QUANTA_IL1] = {
+		.mixers = { alc267_quanta_il1_mixer },
+		.init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
+				alc267_quanta_il1_verbs },
+		.num_dacs = ARRAY_SIZE(alc268_dac_nids),
+		.dac_nids = alc268_dac_nids,
+		.num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
+		.adc_nids = alc268_adc_nids_alt,
+		.hp_nid = 0x03,
+		.num_channel_mode = ARRAY_SIZE(alc268_modes),
+		.channel_mode = alc268_modes,
+		.input_mux = &alc268_capture_source,
+		.unsol_event = alc267_quanta_il1_unsol_event,
+		.init_hook = alc267_quanta_il1_automute,
+	},
 	[ALC268_3ST] = {
 		.mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
 			    alc268_beep_mixer },
-- 
cgit v1.2.3-70-g09d2


From a295e09e89d227506ae6c0a58e1cb6359c0cda1c Mon Sep 17 00:00:00 2001
From: Nick Andrew <nick@nick-andrew.net>
Date: Mon, 14 Apr 2008 15:22:11 +0200
Subject: [ALSA] sound: this amplifier only goes up to 7

sound: kernel log levels are 0-7

Kernel log levels are 0-7, not 0-9.

Signed-off-by: Nick Andrew <nick@nick-andrew.net>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/core/misc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'sound')

diff --git a/sound/core/misc.c b/sound/core/misc.c
index 102d1c36cf2..38524f615d9 100644
--- a/sound/core/misc.c
+++ b/sound/core/misc.c
@@ -39,7 +39,7 @@ void snd_verbose_printk(const char *file, int line, const char *format, ...)
 {
 	va_list args;
 	
-	if (format[0] == '<' && format[1] >= '0' && format[1] <= '9' && format[2] == '>') {
+	if (format[0] == '<' && format[1] >= '0' && format[1] <= '7' && format[2] == '>') {
 		char tmp[] = "<0>";
 		tmp[1] = format[1];
 		printk("%sALSA %s:%d: ", tmp, file, line);
@@ -60,7 +60,7 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...)
 {
 	va_list args;
 	
-	if (format[0] == '<' && format[1] >= '0' && format[1] <= '9' && format[2] == '>') {
+	if (format[0] == '<' && format[1] >= '0' && format[1] <= '7' && format[2] == '>') {
 		char tmp[] = "<0>";
 		tmp[1] = format[1];
 		printk("%sALSA %s:%d: ", tmp, file, line);
-- 
cgit v1.2.3-70-g09d2


From 87b57fe2d3fb1ce33671b944db9a4cbe0cd065ea Mon Sep 17 00:00:00 2001
From: Mark Brown <broonie@opensource.wolfsonmicro.com>
Date: Mon, 14 Apr 2008 15:27:30 +0200
Subject: [ALSA] wm9713: Don't control touch screen power on suspend

Leave the power bit for the touch screen alone when suspending the WM9713
so that the touch screen driver can handle it. This allows the touch
screen to be used as a wakeup source when the system is suspended.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/soc/codecs/wm9713.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

(limited to 'sound')

diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index e3174c4d980..1f241161445 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -1132,8 +1132,17 @@ static int wm9713_soc_suspend(struct platform_device *pdev,
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
 	struct snd_soc_codec *codec = socdev->codec;
+	u16 reg;
+
+	/* Disable everything except touchpanel - that will be handled
+	 * by the touch driver and left disabled if touch is not in
+	 * use. */
+	reg = ac97_read(codec, AC97_EXTENDED_MID);
+	ac97_write(codec, AC97_EXTENDED_MID, reg | 0x7fff);
+	ac97_write(codec, AC97_EXTENDED_MSTATUS, 0xffff);
+	ac97_write(codec, AC97_POWERDOWN, 0x6f00);
+	ac97_write(codec, AC97_POWERDOWN, 0xffff);
 
-	wm9713_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
 	return 0;
 }
 
-- 
cgit v1.2.3-70-g09d2


From f57ab97e767d293132a29a43ca3ecb0f73f1d5bb Mon Sep 17 00:00:00 2001
From: Jarkko Nikula <jarkko.nikula@nokia.com>
Date: Mon, 14 Apr 2008 15:28:19 +0200
Subject: [ALSA] ASoC: Add support for 19.2 MHz MCLK in TLV320AIC3X

Signed-off-by: Jarkko Nikula <jarkko.nikula@nokia.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/soc/codecs/tlv320aic3x.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

(limited to 'sound')

diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index e6a730b0dd2..630684f4a0b 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -661,42 +661,52 @@ struct aic3x_rate_divs {
 static const struct aic3x_rate_divs aic3x_divs[] = {
 	/* 8k */
 	{12000000, 8000, 48000, 0xa, 16, 3840},
+	{19200000, 8000, 48000, 0xa, 10, 2400},
 	{22579200, 8000, 48000, 0xa, 8, 7075},
 	{33868800, 8000, 48000, 0xa, 5, 8049},
 	/* 11.025k */
 	{12000000, 11025, 44100, 0x6, 15, 528},
+	{19200000, 11025, 44100, 0x6, 9, 4080},
 	{22579200, 11025, 44100, 0x6, 8, 0},
 	{33868800, 11025, 44100, 0x6, 5, 3333},
 	/* 16k */
 	{12000000, 16000, 48000, 0x4, 16, 3840},
+	{19200000, 16000, 48000, 0x4, 10, 2400},
 	{22579200, 16000, 48000, 0x4, 8, 7075},
 	{33868800, 16000, 48000, 0x4, 5, 8049},
 	/* 22.05k */
 	{12000000, 22050, 44100, 0x2, 15, 528},
+	{19200000, 22050, 44100, 0x2, 9, 4080},
 	{22579200, 22050, 44100, 0x2, 8, 0},
 	{33868800, 22050, 44100, 0x2, 5, 3333},
 	/* 32k */
 	{12000000, 32000, 48000, 0x1, 16, 3840},
+	{19200000, 32000, 48000, 0x1, 10, 2400},
 	{22579200, 32000, 48000, 0x1, 8, 7075},
 	{33868800, 32000, 48000, 0x1, 5, 8049},
 	/* 44.1k */
 	{12000000, 44100, 44100, 0x0, 15, 528},
+	{19200000, 44100, 44100, 0x0, 9, 4080},
 	{22579200, 44100, 44100, 0x0, 8, 0},
 	{33868800, 44100, 44100, 0x0, 5, 3333},
 	/* 48k */
 	{12000000, 48000, 48000, 0x0, 16, 3840},
+	{19200000, 48000, 48000, 0x0, 10, 2400},
 	{22579200, 48000, 48000, 0x0, 8, 7075},
 	{33868800, 48000, 48000, 0x0, 5, 8049},
 	/* 64k */
 	{12000000, 64000, 96000, 0x1, 16, 3840},
+	{19200000, 64000, 96000, 0x1, 10, 2400},
 	{22579200, 64000, 96000, 0x1, 8, 7075},
 	{33868800, 64000, 96000, 0x1, 5, 8049},
 	/* 88.2k */
 	{12000000, 88200, 88200, 0x0, 15, 528},
+	{19200000, 88200, 88200, 0x0, 9, 4080},
 	{22579200, 88200, 88200, 0x0, 8, 0},
 	{33868800, 88200, 88200, 0x0, 5, 3333},
 	/* 96k */
 	{12000000, 96000, 96000, 0x0, 16, 3840},
+	{19200000, 96000, 96000, 0x0, 10, 2400},
 	{22579200, 96000, 96000, 0x0, 8, 7075},
 	{33868800, 96000, 96000, 0x0, 5, 8049},
 };
@@ -818,6 +828,7 @@ static int aic3x_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai,
 
 	switch (freq) {
 	case 12000000:
+	case 19200000:
 	case 22579200:
 	case 33868800:
 		aic3x->sysclk = freq;
-- 
cgit v1.2.3-70-g09d2


From 8d048841e822f745187246a036d03f2793739b7f Mon Sep 17 00:00:00 2001
From: Daniel Mack <daniel@caiaq.de>
Date: Mon, 14 Apr 2008 15:39:14 +0200
Subject: [ALSA] snd_usb_caiaq: fix potential lockups locking

This patch fixes potential lockups in snd_usb_caiaq by refining the
locking mechanims and by using usb_kill_urb() in favor to
usb_unlink_urb().

Signed-off-by: Daniel Mack <daniel@caiaq.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/caiaq/caiaq-audio.c  | 71 +++++++++++++++++-------------------------
 sound/usb/caiaq/caiaq-device.c |  4 +--
 2 files changed, 31 insertions(+), 44 deletions(-)

(limited to 'sound')

diff --git a/sound/usb/caiaq/caiaq-audio.c b/sound/usb/caiaq/caiaq-audio.c
index 9cc4cd8283f..1aa927942cc 100644
--- a/sound/usb/caiaq/caiaq-audio.c
+++ b/sound/usb/caiaq/caiaq-audio.c
@@ -1,5 +1,5 @@
 /*
- *   Copyright (c) 2006,2007 Daniel Mack, Karsten Wiese
+ *   Copyright (c) 2006-2008 Daniel Mack, Karsten Wiese
  *
  *   This program is free software; you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -77,10 +77,15 @@ static void
 deactivate_substream(struct snd_usb_caiaqdev *dev,
 		     struct snd_pcm_substream *sub)
 {
+	unsigned long flags;
+	spin_lock_irqsave(&dev->spinlock, flags);
+
 	if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK)
 		dev->sub_playback[sub->number] = NULL;
 	else
 		dev->sub_capture[sub->number] = NULL;
+
+	spin_unlock_irqrestore(&dev->spinlock, flags);
 }
 
 static int
@@ -97,13 +102,13 @@ static int stream_start(struct snd_usb_caiaqdev *dev)
 {
 	int i, ret;
 
-	debug("stream_start(%p)\n", dev);
-	spin_lock_irq(&dev->spinlock);
-	if (dev->streaming) {
-		spin_unlock_irq(&dev->spinlock);
+	debug("%s(%p)\n", __func__, dev);
+
+	if (dev->streaming)
 		return -EINVAL;
-	}
 
+	memset(dev->sub_playback, 0, sizeof(dev->sub_playback));
+	memset(dev->sub_capture, 0, sizeof(dev->sub_capture));
 	dev->input_panic = 0;
 	dev->output_panic = 0;
 	dev->first_packet = 1;
@@ -112,37 +117,35 @@ static int stream_start(struct snd_usb_caiaqdev *dev)
 	for (i = 0; i < N_URBS; i++) {
 		ret = usb_submit_urb(dev->data_urbs_in[i], GFP_ATOMIC);
 		if (ret) {
-			log("unable to trigger initial read #%d! (ret = %d)\n",
-				i, ret);
+			log("unable to trigger read #%d! (ret %d)\n", i, ret);
 			dev->streaming = 0;
-			spin_unlock_irq(&dev->spinlock);
 			return -EPIPE;
 		}
 	}
 	
-	spin_unlock_irq(&dev->spinlock);
 	return 0;
 }
 
 static void stream_stop(struct snd_usb_caiaqdev *dev)
 {
 	int i;
-	
-	debug("stream_stop(%p)\n", dev);
+
+	debug("%s(%p)\n", __func__, dev);
 	if (!dev->streaming)
 		return;
 	
 	dev->streaming = 0;
+
 	for (i = 0; i < N_URBS; i++) {
-		usb_unlink_urb(dev->data_urbs_in[i]);
-		usb_unlink_urb(dev->data_urbs_out[i]);
+		usb_kill_urb(dev->data_urbs_in[i]);
+		usb_kill_urb(dev->data_urbs_out[i]);
 	}
 }
 
 static int snd_usb_caiaq_substream_open(struct snd_pcm_substream *substream)
 {
 	struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream);
-	debug("snd_usb_caiaq_substream_open(%p)\n", substream);
+	debug("%s(%p)\n", __func__, substream);
 	substream->runtime->hw = dev->pcm_info;
 	snd_pcm_limit_hw_rates(substream->runtime);
 	return 0;
@@ -152,7 +155,7 @@ static int snd_usb_caiaq_substream_close(struct snd_pcm_substream *substream)
 {
 	struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream);
 
-	debug("snd_usb_caiaq_substream_close(%p)\n", substream);
+	debug("%s(%p)\n", __func__, substream);
 	if (all_substreams_zero(dev->sub_playback) &&
 	    all_substreams_zero(dev->sub_capture)) {
 		/* when the last client has stopped streaming, 
@@ -160,24 +163,22 @@ static int snd_usb_caiaq_substream_close(struct snd_pcm_substream *substream)
 		stream_stop(dev);
 		dev->pcm_info.rates = dev->samplerates;
 	}
-	
+
 	return 0;
 }
 
 static int snd_usb_caiaq_pcm_hw_params(struct snd_pcm_substream *sub,
 			     		struct snd_pcm_hw_params *hw_params)
 {
-	debug("snd_usb_caiaq_pcm_hw_params(%p)\n", sub);
+	debug("%s(%p)\n", __func__, sub);
 	return snd_pcm_lib_malloc_pages(sub, params_buffer_bytes(hw_params));
 }
 
 static int snd_usb_caiaq_pcm_hw_free(struct snd_pcm_substream *sub)
 {
 	struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(sub);
-	debug("snd_usb_caiaq_pcm_hw_free(%p)\n", sub);
-	spin_lock_irq(&dev->spinlock);
+	debug("%s(%p)\n", __func__, sub);
 	deactivate_substream(dev, sub);
-	spin_unlock_irq(&dev->spinlock);
 	return snd_pcm_lib_free_pages(sub);
 }
 
@@ -196,7 +197,7 @@ static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream)
 	struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream);
 	struct snd_pcm_runtime *runtime = substream->runtime;
 
-	debug("snd_usb_caiaq_pcm_prepare(%p)\n", substream);
+	debug("%s(%p)\n", __func__, substream);
 	
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 		dev->audio_out_buf_pos[index] = BYTES_PER_SAMPLE + 1;
@@ -247,15 +248,11 @@ static int snd_usb_caiaq_pcm_trigger(struct snd_pcm_substream *sub, int cmd)
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		spin_lock(&dev->spinlock);
 		activate_substream(dev, sub);
-		spin_unlock(&dev->spinlock);
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		spin_lock(&dev->spinlock);
 		deactivate_substream(dev, sub);
-		spin_unlock(&dev->spinlock);
 		break;
 	default:
 		return -EINVAL;
@@ -328,8 +325,6 @@ static void read_in_urb_mode0(struct snd_usb_caiaqdev *dev,
 	if (all_substreams_zero(dev->sub_capture))
 		return;
 
-	spin_lock(&dev->spinlock);
-	
 	for (i = 0; i < iso->actual_length;) {
 		for (stream = 0; stream < dev->n_streams; stream++, i++) {
 			sub = dev->sub_capture[stream];
@@ -345,8 +340,6 @@ static void read_in_urb_mode0(struct snd_usb_caiaqdev *dev,
 			}
 		}
 	}
-	
-	spin_unlock(&dev->spinlock);
 }
 
 static void read_in_urb_mode2(struct snd_usb_caiaqdev *dev,
@@ -358,8 +351,6 @@ static void read_in_urb_mode2(struct snd_usb_caiaqdev *dev,
 	struct snd_pcm_substream *sub;
 	int stream, i;
 
-	spin_lock(&dev->spinlock);
-	
 	for (i = 0; i < iso->actual_length;) {
 		if (i % (dev->n_streams * BYTES_PER_SAMPLE_USB) == 0) {
 			for (stream = 0; 
@@ -393,8 +384,6 @@ static void read_in_urb_mode2(struct snd_usb_caiaqdev *dev,
 			}
 		}
 	}
-
-	spin_unlock(&dev->spinlock);
 }
 
 static void read_in_urb(struct snd_usb_caiaqdev *dev,
@@ -418,8 +407,6 @@ static void read_in_urb(struct snd_usb_caiaqdev *dev,
 				dev->input_panic ? "(input)" : "",
 				dev->output_panic ? "(output)" : "");
 	}
-
-	check_for_elapsed_periods(dev, dev->sub_capture);
 }
 
 static void fill_out_urb(struct snd_usb_caiaqdev *dev, 
@@ -429,8 +416,6 @@ static void fill_out_urb(struct snd_usb_caiaqdev *dev,
 	unsigned char *usb_buf = urb->transfer_buffer + iso->offset;
 	struct snd_pcm_substream *sub;
 	int stream, i;
-
-	spin_lock(&dev->spinlock);
 	
 	for (i = 0; i < iso->length;) {
 		for (stream = 0; stream < dev->n_streams; stream++, i++) {
@@ -456,9 +441,6 @@ static void fill_out_urb(struct snd_usb_caiaqdev *dev,
 		    for (stream = 0; stream < dev->n_streams; stream++, i++)
 		    	usb_buf[i] = MAKE_CHECKBYTE(dev, stream, i);
 	}
-
-	spin_unlock(&dev->spinlock);
-	check_for_elapsed_periods(dev, dev->sub_playback);
 }
 
 static void read_completed(struct urb *urb)
@@ -472,6 +454,7 @@ static void read_completed(struct urb *urb)
 		return;
 
 	dev = info->dev;
+
 	if (!dev->streaming)
 		return;
 
@@ -489,8 +472,12 @@ static void read_completed(struct urb *urb)
 		out->iso_frame_desc[outframe].offset = BYTES_PER_FRAME * frame;
 		
 		if (len > 0) {
+			spin_lock(&dev->spinlock);
 			fill_out_urb(dev, out, &out->iso_frame_desc[outframe]);
 			read_in_urb(dev, urb, &urb->iso_frame_desc[frame]);
+			spin_unlock(&dev->spinlock);
+			check_for_elapsed_periods(dev, dev->sub_playback);
+			check_for_elapsed_periods(dev, dev->sub_capture);
 			send_it = 1;
 		}
 
@@ -696,7 +683,7 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev)
 
 void snd_usb_caiaq_audio_free(struct snd_usb_caiaqdev *dev)
 {
-	debug("snd_usb_caiaq_audio_free (%p)\n", dev);
+	debug("%s(%p)\n", __func__, dev);
 	stream_stop(dev);
 	free_urbs(dev->data_urbs_in);
 	free_urbs(dev->data_urbs_out);
diff --git a/sound/usb/caiaq/caiaq-device.c b/sound/usb/caiaq/caiaq-device.c
index 7c44a2c7f96..73c08b40cc5 100644
--- a/sound/usb/caiaq/caiaq-device.c
+++ b/sound/usb/caiaq/caiaq-device.c
@@ -42,7 +42,7 @@
 #endif
 
 MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
-MODULE_DESCRIPTION("caiaq USB audio, version 1.3.2");
+MODULE_DESCRIPTION("caiaq USB audio, version 1.3.4");
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2},"
 			 "{Native Instruments, RigKontrol3},"
@@ -456,7 +456,7 @@ static void snd_disconnect(struct usb_interface *intf)
 	struct snd_usb_caiaqdev *dev;
 	struct snd_card *card = dev_get_drvdata(&intf->dev);
 
-	debug("snd_disconnect(%p)\n", intf);
+	debug("%s(%p)\n", __func__, intf);
 
 	if (!card)
 		return;
-- 
cgit v1.2.3-70-g09d2


From 6849d49c48718def95cf1b74154b9b0aee617c7e Mon Sep 17 00:00:00 2001
From: Daniel Mack <daniel@caiaq.de>
Date: Mon, 14 Apr 2008 15:39:47 +0200
Subject: [ALSA] snd_usb_caiaq: correct input channel order

This patch corrects the input channel order of hardware supported by
snd_usb_caiaq.

Signed-off-by: Daniel Mack <daniel@caiaq.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/caiaq/caiaq-audio.c  | 2 +-
 sound/usb/caiaq/caiaq-device.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

(limited to 'sound')

diff --git a/sound/usb/caiaq/caiaq-audio.c b/sound/usb/caiaq/caiaq-audio.c
index 1aa927942cc..ebf32818a16 100644
--- a/sound/usb/caiaq/caiaq-audio.c
+++ b/sound/usb/caiaq/caiaq-audio.c
@@ -202,7 +202,7 @@ static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream)
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 		dev->audio_out_buf_pos[index] = BYTES_PER_SAMPLE + 1;
 	else
-		dev->audio_in_buf_pos[index] = 0;
+		dev->audio_in_buf_pos[index] = BYTES_PER_SAMPLE;
 	
 	if (dev->streaming)
 		return 0;
diff --git a/sound/usb/caiaq/caiaq-device.c b/sound/usb/caiaq/caiaq-device.c
index 73c08b40cc5..379e6082756 100644
--- a/sound/usb/caiaq/caiaq-device.c
+++ b/sound/usb/caiaq/caiaq-device.c
@@ -42,7 +42,7 @@
 #endif
 
 MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
-MODULE_DESCRIPTION("caiaq USB audio, version 1.3.4");
+MODULE_DESCRIPTION("caiaq USB audio, version 1.3.5");
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2},"
 			 "{Native Instruments, RigKontrol3},"
-- 
cgit v1.2.3-70-g09d2


From 6e9fc6bd5db34a6580e1917bd0fea4b0754c7de8 Mon Sep 17 00:00:00 2001
From: Daniel Mack <daniel@caiaq.de>
Date: Mon, 14 Apr 2008 15:40:31 +0200
Subject: [ALSA] snd_usb_caiaq: make high sample rates work with A8DJ

This patch for snd_usb_caiaq makes sample rates higher dann 48KHz work
with devices which have more than 2 stereo input/output pairs.

Signed-off-by: Daniel Mack <daniel@caiaq.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/caiaq/caiaq-audio.c  | 8 ++++++--
 sound/usb/caiaq/caiaq-device.c | 2 +-
 2 files changed, 7 insertions(+), 3 deletions(-)

(limited to 'sound')

diff --git a/sound/usb/caiaq/caiaq-audio.c b/sound/usb/caiaq/caiaq-audio.c
index ebf32818a16..24970a5c888 100644
--- a/sound/usb/caiaq/caiaq-audio.c
+++ b/sound/usb/caiaq/caiaq-audio.c
@@ -39,7 +39,8 @@
 #define BYTES_PER_SAMPLE	3
 #define BYTES_PER_SAMPLE_USB	4
 #define MAX_BUFFER_SIZE		(128*1024)
-				 
+#define MAX_ENDPOINT_SIZE	512
+
 #define ENDPOINT_CAPTURE	2
 #define ENDPOINT_PLAYBACK	6
 
@@ -221,7 +222,10 @@ static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream)
 	
 	bpp = ((runtime->rate / 8000) + CLOCK_DRIFT_TOLERANCE)
 		* bytes_per_sample * CHANNELS_PER_STREAM * dev->n_streams;
-	
+
+	if (bpp > MAX_ENDPOINT_SIZE)
+		bpp = MAX_ENDPOINT_SIZE;
+
 	ret = snd_usb_caiaq_set_audio_params(dev, runtime->rate,
 					     runtime->sample_bits, bpp);
 	if (ret)
diff --git a/sound/usb/caiaq/caiaq-device.c b/sound/usb/caiaq/caiaq-device.c
index 379e6082756..e97d8b2ac16 100644
--- a/sound/usb/caiaq/caiaq-device.c
+++ b/sound/usb/caiaq/caiaq-device.c
@@ -42,7 +42,7 @@
 #endif
 
 MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
-MODULE_DESCRIPTION("caiaq USB audio, version 1.3.5");
+MODULE_DESCRIPTION("caiaq USB audio, version 1.3.6");
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2},"
 			 "{Native Instruments, RigKontrol3},"
-- 
cgit v1.2.3-70-g09d2


From a8bb1bad9b16ab91de6568ac9356b8f705f7272b Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Tue, 15 Apr 2008 08:57:31 +0200
Subject: [ALSA] virtuoso: fix DX front panel I/O

Fix the GPIO 1 mixer control to enable I/O through the front panel
connector of the Xonar DX.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/oxygen/virtuoso.c | 51 ++++++++++++++++++---------------------------
 1 file changed, 20 insertions(+), 31 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
index c7080d6b71c..6f5c2531abd 100644
--- a/sound/pci/oxygen/virtuoso.c
+++ b/sound/pci/oxygen/virtuoso.c
@@ -47,7 +47,7 @@
  * GPI 0 <- external power present
  *
  * GPIO 0 -> enable output to speakers
- * GPIO 1 -> ?
+ * GPIO 1 -> enable front panel I/O
  * GPIO 2 -> M0 of CS5361
  * GPIO 3 -> M1 of CS5361
  * GPIO 8 -> route input jack to line-in (0) or mic-in (1)
@@ -119,7 +119,7 @@ MODULE_DEVICE_TABLE(pci, xonar_ids);
 
 #define GPI_DX_EXT_POWER	0x01
 #define GPIO_DX_OUTPUT_ENABLE	0x0001
-#define GPIO_DX_UNKNOWN1	0x0002
+#define GPIO_DX_FRONT_PANEL	0x0002
 #define GPIO_DX_INPUT_ROUTE	0x0100
 
 #define I2C_DEVICE_CS4398	0x9e	/* 10011, AD1=1, AD0=1, /W=0 */
@@ -268,8 +268,9 @@ static void xonar_dx_init(struct oxygen *chip)
 	cs4362a_write(chip, 0x01, CS4362A_CPEN);
 
 	oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
-			  GPIO_DX_UNKNOWN1 | GPIO_DX_INPUT_ROUTE);
-	oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_DX_INPUT_ROUTE);
+			  GPIO_DX_FRONT_PANEL | GPIO_DX_INPUT_ROUTE);
+	oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA,
+			    GPIO_DX_FRONT_PANEL | GPIO_DX_INPUT_ROUTE);
 
 	xonar_common_init(chip);
 
@@ -471,51 +472,39 @@ static const struct snd_kcontrol_new alt_switch = {
 	.put = alt_switch_put,
 };
 
-static int unknown_info(struct snd_kcontrol *ctl,
-			struct snd_ctl_elem_info *info)
-{
-	info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-	info->count = 1;
-	info->value.enumerated.items = 2;
-	if (info->value.enumerated.item > 1)
-		info->value.enumerated.item = 1;
-	sprintf(info->value.enumerated.name, "%u", info->value.enumerated.item);
-	return 0;
-}
-
-static int unknown_get(struct snd_kcontrol *ctl,
-		       struct snd_ctl_elem_value *value)
+static int front_panel_get(struct snd_kcontrol *ctl,
+			   struct snd_ctl_elem_value *value)
 {
 	struct oxygen *chip = ctl->private_data;
 
-	value->value.enumerated.item[0] =
-		!!(oxygen_read16(chip, OXYGEN_GPIO_DATA) & GPIO_DX_UNKNOWN1);
+	value->value.integer.value[0] =
+		!!(oxygen_read16(chip, OXYGEN_GPIO_DATA) & GPIO_DX_FRONT_PANEL);
 	return 0;
 }
 
-static int unknown_put(struct snd_kcontrol *ctl,
-		       struct snd_ctl_elem_value *value)
+static int front_panel_put(struct snd_kcontrol *ctl,
+			   struct snd_ctl_elem_value *value)
 {
 	struct oxygen *chip = ctl->private_data;
 	u16 old_reg, new_reg;
 
 	spin_lock_irq(&chip->reg_lock);
 	old_reg = oxygen_read16(chip, OXYGEN_GPIO_DATA);
-	if (value->value.enumerated.item[0])
-		new_reg = old_reg | GPIO_DX_UNKNOWN1;
+	if (value->value.integer.value[0])
+		new_reg = old_reg | GPIO_DX_FRONT_PANEL;
 	else
-		new_reg = old_reg & ~GPIO_DX_UNKNOWN1;
+		new_reg = old_reg & ~GPIO_DX_FRONT_PANEL;
 	oxygen_write16(chip, OXYGEN_GPIO_DATA, new_reg);
 	spin_unlock_irq(&chip->reg_lock);
 	return old_reg != new_reg;
 }
 
-static const struct snd_kcontrol_new unknown_switch = {
+static const struct snd_kcontrol_new front_panel_switch = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-	.name = "PanelConfig?",
-	.info = unknown_info,
-	.get = unknown_get,
-	.put = unknown_put,
+	.name = "Front Panel Switch",
+	.info = snd_ctl_boolean_mono_info,
+	.get = front_panel_get,
+	.put = front_panel_put,
 };
 
 static void xonar_dx_ac97_switch(struct oxygen *chip,
@@ -565,7 +554,7 @@ static int xonar_mixer_init(struct oxygen *chip)
 
 static int xonar_dx_mixer_init(struct oxygen *chip)
 {
-	return snd_ctl_add(chip->card, snd_ctl_new1(&unknown_switch, chip));
+	return snd_ctl_add(chip->card, snd_ctl_new1(&front_panel_switch, chip));
 }
 
 static const struct oxygen_model xonar_models[] = {
-- 
cgit v1.2.3-70-g09d2


From 3adb8abc70aaf5c071f27576069c8b01783cca83 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Tue, 15 Apr 2008 18:46:42 +0200
Subject: [ALSA] hda - Add support of AD1989A/AD1989B

Added the support of AD1989A and AD1989B codecs.
These codecs can have multiple SPDIF devices, but currently we handle
only one SPDIF.  If any real devices with two SPDIF interfaces (likely
one for SPDIF and one for HDMI), we'll fix this rightly.

Otherwise, these codecs are pretty similar with AD1988.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 Documentation/sound/alsa/ALSA-Configuration.txt |  2 +-
 sound/pci/hda/patch_analog.c                    | 28 ++++++++++++++++++++++---
 2 files changed, 26 insertions(+), 4 deletions(-)

(limited to 'sound')

diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 3413644dff1..fd4c32a031c 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -956,7 +956,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
 	  laptop-automute 2-channel with EAPD and HP-automute (Lenovo N100)
 	  ultra		2-channel with EAPD (Samsung Ultra tablet PC)
 
-	AD1988
+	AD1988/AD1988B/AD1989A/AD1989B
 	  6stack	6-jack
 	  6stack-dig	ditto with SPDIF
 	  3stack	3-jack
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 2befeebd909..f486eb16a38 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -2142,6 +2142,10 @@ static struct snd_kcontrol_new ad1988_spdif_in_mixers[] = {
 	{ } /* end */
 };
 
+static struct snd_kcontrol_new ad1989_spdif_out_mixers[] = {
+	HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
+	{ } /* end */
+};
 
 /*
  * initialization verbs
@@ -2242,6 +2246,13 @@ static struct hda_verb ad1988_spdif_init_verbs[] = {
 	{ }
 };
 
+/* AD1989 has no ADC -> SPDIF route */
+static struct hda_verb ad1989_spdif_init_verbs[] = {
+	/* SPDIF out pin */
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
+	{ }
+};
+
 /*
  * verbs for 3stack (+dig)
  */
@@ -2949,10 +2960,19 @@ static int patch_ad1988(struct hda_codec *codec)
 	spec->mixers[spec->num_mixers++] = ad1988_capture_mixers;
 	spec->init_verbs[spec->num_init_verbs++] = ad1988_capture_init_verbs;
 	if (spec->multiout.dig_out_nid) {
-		spec->mixers[spec->num_mixers++] = ad1988_spdif_out_mixers;
-		spec->init_verbs[spec->num_init_verbs++] = ad1988_spdif_init_verbs;
+		if (codec->vendor_id >= 0x11d4989a) {
+			spec->mixers[spec->num_mixers++] =
+				ad1989_spdif_out_mixers;
+			spec->init_verbs[spec->num_init_verbs++] =
+				ad1989_spdif_init_verbs;
+		} else {
+			spec->mixers[spec->num_mixers++] =
+				ad1988_spdif_out_mixers;
+			spec->init_verbs[spec->num_init_verbs++] =
+				ad1988_spdif_init_verbs;
+		}
 	}
-	if (spec->dig_in_nid)
+	if (spec->dig_in_nid && codec->vendor_id < 0x11d4989a)
 		spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers;
 
 	codec->patch_ops = ad198x_patch_ops;
@@ -4184,5 +4204,7 @@ struct hda_codec_preset snd_hda_preset_analog[] = {
 	{ .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
 	{ .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 },
 	{ .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 },
+	{ .id = 0x11d4989a, .name = "AD1989A", .patch = patch_ad1988 },
+	{ .id = 0x11d4989b, .name = "AD1989B", .patch = patch_ad1988 },
 	{} /* terminator */
 };
-- 
cgit v1.2.3-70-g09d2


From 0c0e6daf14183fb1cd0dea054ecf81165abbdc83 Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Wed, 16 Apr 2008 09:12:27 +0200
Subject: [ALSA] hifier: remove empty hifier_mixer_init()

The empty hifier_mixer_init() function is useless; remove it.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/oxygen/hifier.c | 6 ------
 1 file changed, 6 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/oxygen/hifier.c b/sound/pci/oxygen/hifier.c
index 50551ae0b3b..b67888f6745 100644
--- a/sound/pci/oxygen/hifier.c
+++ b/sound/pci/oxygen/hifier.c
@@ -136,11 +136,6 @@ static int hifier_control_filter(struct snd_kcontrol_new *template)
 	return 0;
 }
 
-static int hifier_mixer_init(struct oxygen *chip)
-{
-	return 0;
-}
-
 static const struct oxygen_model model_hifier = {
 	.shortname = "C-Media CMI8787",
 	.longname = "C-Media Oxygen HD Audio",
@@ -148,7 +143,6 @@ static const struct oxygen_model model_hifier = {
 	.owner = THIS_MODULE,
 	.init = hifier_init,
 	.control_filter = hifier_control_filter,
-	.mixer_init = hifier_mixer_init,
 	.cleanup = hifier_cleanup,
 	.set_dac_params = set_ak4396_params,
 	.set_adc_params = set_cs5340_params,
-- 
cgit v1.2.3-70-g09d2


From 193e813814775b1b1574515fc6f11e61b29a54f7 Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Wed, 16 Apr 2008 09:13:36 +0200
Subject: [ALSA] oxygen: generalize handling of DAC volume limits

Add fields for the DAC volume limits to the module structure so that
model drivers do not need to install their own control info handlers.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/oxygen/hifier.c       |  2 ++
 sound/pci/oxygen/oxygen.c       |  4 ++++
 sound/pci/oxygen/oxygen.h       |  2 ++
 sound/pci/oxygen/oxygen_lib.c   |  2 +-
 sound/pci/oxygen/oxygen_mixer.c |  4 ++--
 sound/pci/oxygen/virtuoso.c     | 31 ++++++-------------------------
 6 files changed, 17 insertions(+), 28 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/oxygen/hifier.c b/sound/pci/oxygen/hifier.c
index b67888f6745..bf39c72a130 100644
--- a/sound/pci/oxygen/hifier.c
+++ b/sound/pci/oxygen/hifier.c
@@ -153,6 +153,8 @@ static const struct oxygen_model model_hifier = {
 		       PLAYBACK_1_TO_SPDIF |
 		       CAPTURE_0_FROM_I2S_1,
 	.dac_channels = 2,
+	.dac_volume_min = 0,
+	.dac_volume_max = 255,
 	.function_flags = OXYGEN_FUNCTION_SPI,
 	.dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
 	.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c
index b3b7771b54c..718169792c3 100644
--- a/sound/pci/oxygen/oxygen.c
+++ b/sound/pci/oxygen/oxygen.c
@@ -278,6 +278,8 @@ static const struct oxygen_model model_generic = {
 		       CAPTURE_1_FROM_SPDIF |
 		       CAPTURE_2_FROM_AC97_1,
 	.dac_channels = 8,
+	.dac_volume_min = 0,
+	.dac_volume_max = 255,
 	.function_flags = OXYGEN_FUNCTION_SPI |
 			  OXYGEN_FUNCTION_ENABLE_SPI_4_5,
 	.dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
@@ -303,6 +305,8 @@ static const struct oxygen_model model_meridian = {
 		       CAPTURE_1_FROM_SPDIF |
 		       CAPTURE_2_FROM_AC97_1,
 	.dac_channels = 8,
+	.dac_volume_min = 0,
+	.dac_volume_max = 255,
 	.misc_flags = OXYGEN_MISC_MIDI,
 	.function_flags = OXYGEN_FUNCTION_SPI |
 			  OXYGEN_FUNCTION_ENABLE_SPI_4_5,
diff --git a/sound/pci/oxygen/oxygen.h b/sound/pci/oxygen/oxygen.h
index 7efbf54bc4e..36f2f81fefc 100644
--- a/sound/pci/oxygen/oxygen.h
+++ b/sound/pci/oxygen/oxygen.h
@@ -103,6 +103,8 @@ struct oxygen_model {
 	size_t model_data_size;
 	unsigned int pcm_dev_cfg;
 	u8 dac_channels;
+	u8 dac_volume_min;
+	u8 dac_volume_max;
 	u8 misc_flags;
 	u8 function_flags;
 	u16 dac_i2s_format;
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c
index 39e4b7a5174..b7aa9fcb6b8 100644
--- a/sound/pci/oxygen/oxygen_lib.c
+++ b/sound/pci/oxygen/oxygen_lib.c
@@ -221,7 +221,7 @@ static void oxygen_init(struct oxygen *chip)
 
 	chip->dac_routing = 1;
 	for (i = 0; i < 8; ++i)
-		chip->dac_volume[i] = 0xff;
+		chip->dac_volume[i] = chip->model->dac_volume_max;
 	chip->spdif_playback_enable = 1;
 	chip->spdif_bits = OXYGEN_SPDIF_C | OXYGEN_SPDIF_ORIGINAL |
 		(IEC958_AES1_CON_PCM_CODER << OXYGEN_SPDIF_CATEGORY_SHIFT);
diff --git a/sound/pci/oxygen/oxygen_mixer.c b/sound/pci/oxygen/oxygen_mixer.c
index 2cb914498a1..056581ecd91 100644
--- a/sound/pci/oxygen/oxygen_mixer.c
+++ b/sound/pci/oxygen/oxygen_mixer.c
@@ -32,8 +32,8 @@ static int dac_volume_info(struct snd_kcontrol *ctl,
 
 	info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 	info->count = chip->model->dac_channels;
-	info->value.integer.min = 0;
-	info->value.integer.max = 0xff;
+	info->value.integer.min = chip->model->dac_volume_min;
+	info->value.integer.max = chip->model->dac_volume_max;
 	return 0;
 }
 
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
index 6f5c2531abd..37f53a8c588 100644
--- a/sound/pci/oxygen/virtuoso.c
+++ b/sound/pci/oxygen/virtuoso.c
@@ -219,10 +219,7 @@ static void xonar_d2x_init(struct oxygen *chip)
 static void xonar_dx_init(struct oxygen *chip)
 {
 	struct xonar_data *data = chip->model_data;
-	unsigned int i;
 
-	for (i = 0; i < 8; ++i)
-		chip->dac_volume[i] = 127;
 	data->anti_pop_delay = 800;
 	data->output_enable_bit = GPIO_DX_OUTPUT_ENABLE;
 	data->ext_power_reg = OXYGEN_GPI_DATA;
@@ -414,26 +411,6 @@ static void xonar_gpio_changed(struct oxygen *chip)
 	}
 }
 
-static int pcm1796_volume_info(struct snd_kcontrol *ctl,
-			       struct snd_ctl_elem_info *info)
-{
-	info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-	info->count = 8;
-	info->value.integer.min = 0x0f;
-	info->value.integer.max = 0xff;
-	return 0;
-}
-
-static int cs4362a_volume_info(struct snd_kcontrol *ctl,
-			       struct snd_ctl_elem_info *info)
-{
-	info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-	info->count = 8;
-	info->value.integer.min = 0;
-	info->value.integer.max = 127;
-	return 0;
-}
-
 static int alt_switch_get(struct snd_kcontrol *ctl,
 			  struct snd_ctl_elem_value *value)
 {
@@ -526,7 +503,6 @@ static int xonar_d2_control_filter(struct snd_kcontrol_new *template)
 {
 	if (!strcmp(template->name, "Master Playback Volume")) {
 		template->access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
-		template->info = pcm1796_volume_info;
 		template->tlv.p = pcm1796_db_scale;
 	} else if (!strncmp(template->name, "CD Capture ", 11)) {
 		/* CD in is actually connected to the video in pin */
@@ -539,7 +515,6 @@ static int xonar_dx_control_filter(struct snd_kcontrol_new *template)
 {
 	if (!strcmp(template->name, "Master Playback Volume")) {
 		template->access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
-		template->info = cs4362a_volume_info;
 		template->tlv.p = cs4362a_db_scale;
 	} else if (!strncmp(template->name, "CD Capture ", 11)) {
 		return 1; /* no CD input */
@@ -577,6 +552,8 @@ static const struct oxygen_model xonar_models[] = {
 			       CAPTURE_0_FROM_I2S_2 |
 			       CAPTURE_1_FROM_SPDIF,
 		.dac_channels = 8,
+		.dac_volume_min = 0x0f,
+		.dac_volume_max = 0xff,
 		.misc_flags = OXYGEN_MISC_MIDI,
 		.function_flags = OXYGEN_FUNCTION_SPI |
 				  OXYGEN_FUNCTION_ENABLE_SPI_4_5,
@@ -603,6 +580,8 @@ static const struct oxygen_model xonar_models[] = {
 			       CAPTURE_0_FROM_I2S_2 |
 			       CAPTURE_1_FROM_SPDIF,
 		.dac_channels = 8,
+		.dac_volume_min = 0x0f,
+		.dac_volume_max = 0xff,
 		.misc_flags = OXYGEN_MISC_MIDI,
 		.function_flags = OXYGEN_FUNCTION_SPI |
 				  OXYGEN_FUNCTION_ENABLE_SPI_4_5,
@@ -629,6 +608,8 @@ static const struct oxygen_model xonar_models[] = {
 			       PLAYBACK_1_TO_SPDIF |
 			       CAPTURE_0_FROM_I2S_2,
 		.dac_channels = 8,
+		.dac_volume_min = 0,
+		.dac_volume_max = 127,
 		.function_flags = OXYGEN_FUNCTION_2WIRE,
 		.dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
 		.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
-- 
cgit v1.2.3-70-g09d2


From e983532e446ac7fabe829d9e3aeff8e26b0a277d Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Wed, 16 Apr 2008 09:14:30 +0200
Subject: [ALSA] oxygen: mute by default

Initialize the playback volume controls as being muted and having
minimal volume.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/oxygen/hifier.c     |  6 +++---
 sound/pci/oxygen/oxygen.c     |  6 +++---
 sound/pci/oxygen/oxygen_lib.c |  3 ++-
 sound/pci/oxygen/virtuoso.c   | 23 ++++++++++++-----------
 4 files changed, 20 insertions(+), 18 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/oxygen/hifier.c b/sound/pci/oxygen/hifier.c
index bf39c72a130..dec9073d6ed 100644
--- a/sound/pci/oxygen/hifier.c
+++ b/sound/pci/oxygen/hifier.c
@@ -66,12 +66,12 @@ static void hifier_init(struct oxygen *chip)
 {
 	struct hifier_data *data = chip->model_data;
 
-	data->ak4396_ctl2 = AK4396_DEM_OFF | AK4396_DFS_NORMAL;
+	data->ak4396_ctl2 = AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL;
 	ak4396_write(chip, AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_RSTN);
 	ak4396_write(chip, AK4396_CONTROL_2, data->ak4396_ctl2);
 	ak4396_write(chip, AK4396_CONTROL_3, AK4396_PCM);
-	ak4396_write(chip, AK4396_LCH_ATT, 0xff);
-	ak4396_write(chip, AK4396_RCH_ATT, 0xff);
+	ak4396_write(chip, AK4396_LCH_ATT, 0);
+	ak4396_write(chip, AK4396_RCH_ATT, 0);
 
 	snd_component_add(chip->card, "AK4396");
 	snd_component_add(chip->card, "CS5340");
diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c
index 718169792c3..636315612c3 100644
--- a/sound/pci/oxygen/oxygen.c
+++ b/sound/pci/oxygen/oxygen.c
@@ -112,7 +112,7 @@ static void ak4396_init(struct oxygen *chip)
 	struct generic_data *data = chip->model_data;
 	unsigned int i;
 
-	data->ak4396_ctl2 = AK4396_DEM_OFF | AK4396_DFS_NORMAL;
+	data->ak4396_ctl2 = AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL;
 	for (i = 0; i < 4; ++i) {
 		ak4396_write(chip, i,
 			     AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_RSTN);
@@ -120,8 +120,8 @@ static void ak4396_init(struct oxygen *chip)
 			     AK4396_CONTROL_2, data->ak4396_ctl2);
 		ak4396_write(chip, i,
 			     AK4396_CONTROL_3, AK4396_PCM);
-		ak4396_write(chip, i, AK4396_LCH_ATT, 0xff);
-		ak4396_write(chip, i, AK4396_RCH_ATT, 0xff);
+		ak4396_write(chip, i, AK4396_LCH_ATT, 0);
+		ak4396_write(chip, i, AK4396_RCH_ATT, 0);
 	}
 	snd_component_add(chip->card, "AK4396");
 }
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c
index b7aa9fcb6b8..f84f6a128ee 100644
--- a/sound/pci/oxygen/oxygen_lib.c
+++ b/sound/pci/oxygen/oxygen_lib.c
@@ -221,7 +221,8 @@ static void oxygen_init(struct oxygen *chip)
 
 	chip->dac_routing = 1;
 	for (i = 0; i < 8; ++i)
-		chip->dac_volume[i] = chip->model->dac_volume_max;
+		chip->dac_volume[i] = chip->model->dac_volume_min;
+	chip->dac_mute = 1;
 	chip->spdif_playback_enable = 1;
 	chip->spdif_bits = OXYGEN_SPDIF_C | OXYGEN_SPDIF_ORIGINAL |
 		(IEC958_AES1_CON_PCM_CODER << OXYGEN_SPDIF_CATEGORY_SHIFT);
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
index 37f53a8c588..fe4e289840b 100644
--- a/sound/pci/oxygen/virtuoso.c
+++ b/sound/pci/oxygen/virtuoso.c
@@ -188,12 +188,13 @@ static void xonar_d2_init(struct oxygen *chip)
 	data->output_enable_bit = GPIO_D2_OUTPUT_ENABLE;
 
 	for (i = 0; i < 4; ++i) {
-		pcm1796_write(chip, i, 18, PCM1796_FMT_24_LJUST | PCM1796_ATLD);
+		pcm1796_write(chip, i, 18, PCM1796_MUTE | PCM1796_DMF_DISABLED |
+			      PCM1796_FMT_24_LJUST | PCM1796_ATLD);
 		pcm1796_write(chip, i, 19, PCM1796_FLT_SHARP | PCM1796_ATS_1);
 		pcm1796_write(chip, i, 20, PCM1796_OS_64);
 		pcm1796_write(chip, i, 21, 0);
-		pcm1796_write(chip, i, 16, 0xff); /* set ATL/ATR after ATLD */
-		pcm1796_write(chip, i, 17, 0xff);
+		pcm1796_write(chip, i, 16, 0x0f); /* set ATL/ATR after ATLD */
+		pcm1796_write(chip, i, 17, 0x0f);
 	}
 
 	oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_D2_ALT);
@@ -239,8 +240,8 @@ static void xonar_dx_init(struct oxygen *chip)
 		     CS4398_DEM_NONE | CS4398_DIF_LJUST);
 	cs4398_write(chip, 3, CS4398_ATAPI_B_R | CS4398_ATAPI_A_L);
 	cs4398_write(chip, 4, CS4398_MUTEP_LOW | CS4398_PAMUTE);
-	cs4398_write(chip, 5, 0);
-	cs4398_write(chip, 6, 0);
+	cs4398_write(chip, 5, 0xfe);
+	cs4398_write(chip, 6, 0xfe);
 	cs4398_write(chip, 7, CS4398_RMP_DN | CS4398_RMP_UP |
 		     CS4398_ZERO_CROSS | CS4398_SOFT_RAMP);
 	cs4362a_write(chip, 0x02, CS4362A_DIF_LJUST);
@@ -250,16 +251,16 @@ static void xonar_dx_init(struct oxygen *chip)
 	cs4362a_write(chip, 0x05, 0);
 	cs4362a_write(chip, 0x06, CS4362A_FM_SINGLE |
 		      CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L);
+	cs4362a_write(chip, 0x07, 0x7f | CS4362A_MUTE);
+	cs4362a_write(chip, 0x08, 0x7f | CS4362A_MUTE);
 	cs4362a_write(chip, 0x09, CS4362A_FM_SINGLE |
 		      CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L);
+	cs4362a_write(chip, 0x0a, 0x7f | CS4362A_MUTE);
+	cs4362a_write(chip, 0x0b, 0x7f | CS4362A_MUTE);
 	cs4362a_write(chip, 0x0c, CS4362A_FM_SINGLE |
 		      CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L);
-	cs4362a_write(chip, 0x07, 0);
-	cs4362a_write(chip, 0x08, 0);
-	cs4362a_write(chip, 0x0a, 0);
-	cs4362a_write(chip, 0x0b, 0);
-	cs4362a_write(chip, 0x0d, 0);
-	cs4362a_write(chip, 0x0e, 0);
+	cs4362a_write(chip, 0x0d, 0x7f | CS4362A_MUTE);
+	cs4362a_write(chip, 0x0e, 0x7f | CS4362A_MUTE);
 	/* clear power down */
 	cs4398_write(chip, 8, CS4398_CPEN);
 	cs4362a_write(chip, 0x01, CS4362A_CPEN);
-- 
cgit v1.2.3-70-g09d2


From 4972a177fed34036498aee555335f84a70219bc1 Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Wed, 16 Apr 2008 09:15:45 +0200
Subject: [ALSA] oxygen: generalize DAC volume TLV handling

Add a pointer for DAC volume TLV data to the model structure so that the
model driver do not need to manually assign it in their control filter.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/oxygen/hifier.c       |  7 ++-----
 sound/pci/oxygen/oxygen.c       | 13 ++-----------
 sound/pci/oxygen/oxygen.h       |  1 +
 sound/pci/oxygen/oxygen_mixer.c |  5 +++++
 sound/pci/oxygen/virtuoso.c     | 15 +++++----------
 5 files changed, 15 insertions(+), 26 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/oxygen/hifier.c b/sound/pci/oxygen/hifier.c
index dec9073d6ed..090dd4354a2 100644
--- a/sound/pci/oxygen/hifier.c
+++ b/sound/pci/oxygen/hifier.c
@@ -127,12 +127,8 @@ static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0);
 
 static int hifier_control_filter(struct snd_kcontrol_new *template)
 {
-	if (!strcmp(template->name, "Master Playback Volume")) {
-		template->access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
-		template->tlv.p = ak4396_db_scale;
-	} else if (!strcmp(template->name, "Stereo Upmixing")) {
+	if (!strcmp(template->name, "Stereo Upmixing"))
 		return 1; /* stereo only - we don't need upmixing */
-	}
 	return 0;
 }
 
@@ -148,6 +144,7 @@ static const struct oxygen_model model_hifier = {
 	.set_adc_params = set_cs5340_params,
 	.update_dac_volume = update_ak4396_volume,
 	.update_dac_mute = update_ak4396_mute,
+	.dac_tlv = ak4396_db_scale,
 	.model_data_size = sizeof(struct hifier_data),
 	.pcm_dev_cfg = PLAYBACK_0_TO_I2S |
 		       PLAYBACK_1_TO_SPDIF |
diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c
index 636315612c3..63f185c1ed1 100644
--- a/sound/pci/oxygen/oxygen.c
+++ b/sound/pci/oxygen/oxygen.c
@@ -249,27 +249,18 @@ static void set_ak5385_params(struct oxygen *chip,
 
 static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0);
 
-static int ak4396_control_filter(struct snd_kcontrol_new *template)
-{
-	if (!strcmp(template->name, "Master Playback Volume")) {
-		template->access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
-		template->tlv.p = ak4396_db_scale;
-	}
-	return 0;
-}
-
 static const struct oxygen_model model_generic = {
 	.shortname = "C-Media CMI8788",
 	.longname = "C-Media Oxygen HD Audio",
 	.chip = "CMI8788",
 	.owner = THIS_MODULE,
 	.init = generic_init,
-	.control_filter = ak4396_control_filter,
 	.cleanup = generic_cleanup,
 	.set_dac_params = set_ak4396_params,
 	.set_adc_params = set_wm8785_params,
 	.update_dac_volume = update_ak4396_volume,
 	.update_dac_mute = update_ak4396_mute,
+	.dac_tlv = ak4396_db_scale,
 	.model_data_size = sizeof(struct generic_data),
 	.pcm_dev_cfg = PLAYBACK_0_TO_I2S |
 		       PLAYBACK_1_TO_SPDIF |
@@ -291,12 +282,12 @@ static const struct oxygen_model model_meridian = {
 	.chip = "CMI8788",
 	.owner = THIS_MODULE,
 	.init = meridian_init,
-	.control_filter = ak4396_control_filter,
 	.cleanup = generic_cleanup,
 	.set_dac_params = set_ak4396_params,
 	.set_adc_params = set_ak5385_params,
 	.update_dac_volume = update_ak4396_volume,
 	.update_dac_mute = update_ak4396_mute,
+	.dac_tlv = ak4396_db_scale,
 	.model_data_size = sizeof(struct generic_data),
 	.pcm_dev_cfg = PLAYBACK_0_TO_I2S |
 		       PLAYBACK_1_TO_SPDIF |
diff --git a/sound/pci/oxygen/oxygen.h b/sound/pci/oxygen/oxygen.h
index 36f2f81fefc..a71c6e05926 100644
--- a/sound/pci/oxygen/oxygen.h
+++ b/sound/pci/oxygen/oxygen.h
@@ -100,6 +100,7 @@ struct oxygen_model {
 	void (*gpio_changed)(struct oxygen *chip);
 	void (*ac97_switch)(struct oxygen *chip,
 			    unsigned int reg, unsigned int mute);
+	const unsigned int *dac_tlv;
 	size_t model_data_size;
 	unsigned int pcm_dev_cfg;
 	u8 dac_channels;
diff --git a/sound/pci/oxygen/oxygen_mixer.c b/sound/pci/oxygen/oxygen_mixer.c
index 056581ecd91..cc0cddadd58 100644
--- a/sound/pci/oxygen/oxygen_mixer.c
+++ b/sound/pci/oxygen/oxygen_mixer.c
@@ -941,6 +941,11 @@ static int add_controls(struct oxygen *chip,
 			return err;
 		if (err == 1)
 			continue;
+		if (!strcmp(template.name, "Master Playback Volume") &&
+		    chip->model->dac_tlv) {
+			template.tlv.p = chip->model->dac_tlv;
+			template.access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
+		}
 		ctl = snd_ctl_new1(&template, chip);
 		if (!ctl)
 			return -ENOMEM;
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
index fe4e289840b..7f84fa5deca 100644
--- a/sound/pci/oxygen/virtuoso.c
+++ b/sound/pci/oxygen/virtuoso.c
@@ -502,24 +502,16 @@ static const DECLARE_TLV_DB_SCALE(cs4362a_db_scale, -12700, 100, 0);
 
 static int xonar_d2_control_filter(struct snd_kcontrol_new *template)
 {
-	if (!strcmp(template->name, "Master Playback Volume")) {
-		template->access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
-		template->tlv.p = pcm1796_db_scale;
-	} else if (!strncmp(template->name, "CD Capture ", 11)) {
+	if (!strncmp(template->name, "CD Capture ", 11))
 		/* CD in is actually connected to the video in pin */
 		template->private_value ^= AC97_CD ^ AC97_VIDEO;
-	}
 	return 0;
 }
 
 static int xonar_dx_control_filter(struct snd_kcontrol_new *template)
 {
-	if (!strcmp(template->name, "Master Playback Volume")) {
-		template->access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
-		template->tlv.p = cs4362a_db_scale;
-	} else if (!strncmp(template->name, "CD Capture ", 11)) {
+	if (!strncmp(template->name, "CD Capture ", 11))
 		return 1; /* no CD input */
-	}
 	return 0;
 }
 
@@ -547,6 +539,7 @@ static const struct oxygen_model xonar_models[] = {
 		.set_adc_params = set_cs53x1_params,
 		.update_dac_volume = update_pcm1796_volume,
 		.update_dac_mute = update_pcm1796_mute,
+		.dac_tlv = pcm1796_db_scale,
 		.model_data_size = sizeof(struct xonar_data),
 		.pcm_dev_cfg = PLAYBACK_0_TO_I2S |
 			       PLAYBACK_1_TO_SPDIF |
@@ -575,6 +568,7 @@ static const struct oxygen_model xonar_models[] = {
 		.update_dac_volume = update_pcm1796_volume,
 		.update_dac_mute = update_pcm1796_mute,
 		.gpio_changed = xonar_gpio_changed,
+		.dac_tlv = pcm1796_db_scale,
 		.model_data_size = sizeof(struct xonar_data),
 		.pcm_dev_cfg = PLAYBACK_0_TO_I2S |
 			       PLAYBACK_1_TO_SPDIF |
@@ -604,6 +598,7 @@ static const struct oxygen_model xonar_models[] = {
 		.update_dac_mute = update_cs43xx_mute,
 		.gpio_changed = xonar_gpio_changed,
 		.ac97_switch = xonar_dx_ac97_switch,
+		.dac_tlv = cs4362a_db_scale,
 		.model_data_size = sizeof(struct xonar_data),
 		.pcm_dev_cfg = PLAYBACK_0_TO_I2S |
 			       PLAYBACK_1_TO_SPDIF |
-- 
cgit v1.2.3-70-g09d2


From 0a08478c0f7548211b492b578a67dacca5aea1a8 Mon Sep 17 00:00:00 2001
From: Mark Brown <broonie@opensource.wolfsonmicro.com>
Date: Wed, 16 Apr 2008 12:59:55 +0200
Subject: [ALSA] soc - wm9712: Remove unneeded AC97_EXTENDED_MID updates

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/soc/codecs/wm9712.c | 8 --------
 1 file changed, 8 deletions(-)

(limited to 'sound')

diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
index 524f7450804..d2d79e182a4 100644
--- a/sound/soc/codecs/wm9712.c
+++ b/sound/soc/codecs/wm9712.c
@@ -581,22 +581,14 @@ static int wm9712_dapm_event(struct snd_soc_codec *codec, int event)
 
 	switch (event) {
 	case SNDRV_CTL_POWER_D0: /* full On */
-		/* liam - maybe enable thermal shutdown */
-		reg = ac97_read(codec, AC97_EXTENDED_MID) & 0xdfff;
-		ac97_write(codec, AC97_EXTENDED_MID, reg);
-		break;
 	case SNDRV_CTL_POWER_D1: /* partial On */
 	case SNDRV_CTL_POWER_D2: /* partial On */
 		break;
 	case SNDRV_CTL_POWER_D3hot: /* Off, with power */
-		/* enable master bias and vmid */
-		reg = ac97_read(codec, AC97_EXTENDED_MID) & 0xbbff;
-		ac97_write(codec, AC97_EXTENDED_MID, reg);
 		ac97_write(codec, AC97_POWERDOWN, 0x0000);
 		break;
 	case SNDRV_CTL_POWER_D3cold: /* Off, without power */
 		/* disable everything including AC link */
-		ac97_write(codec, AC97_EXTENDED_MID, 0xffff);
 		ac97_write(codec, AC97_EXTENDED_MSTATUS, 0xffff);
 		ac97_write(codec, AC97_POWERDOWN, 0xffff);
 		break;
-- 
cgit v1.2.3-70-g09d2


From 7c2ba97b8a99c857758fd03513350b39a8b242d6 Mon Sep 17 00:00:00 2001
From: Matthew Ranostay <mranostay@embeddedalley.com>
Date: Wed, 16 Apr 2008 13:13:59 +0200
Subject: [ALSA] hda: Add 5.1 support for second headphone jack

Several 92hd7xxx and STAC9228 laptops have multiple headphone jacks,
the second headphone jack should be used for the 5.1 surround sound.
Add support for 'Headphone as Line Out' switch, which allows it be used
in 5.1 surround sound.

Signed-off-by: Matthew Ranostay <mranostay@embeddedalley.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_sigmatel.c | 60 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 59 insertions(+), 1 deletion(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index e1d07ab5cd1..b3a15d61687 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -181,6 +181,7 @@ struct sigmatel_spec {
 	/* i/o switches */
 	unsigned int io_switch[2];
 	unsigned int clfe_swap;
+	unsigned int hp_switch;
 	unsigned int aloopback;
 
 	struct hda_pcm pcm_rec[2];	/* PCM information */
@@ -1274,7 +1275,7 @@ static unsigned int ref92hd73xx_pin_configs[13] = {
 
 static unsigned int dell_m6_pin_configs[13] = {
 	0x0321101f, 0x4f00000f, 0x4f0000f0, 0x90170110,
-	0x03a11020, 0x03011050, 0x4f0000f0, 0x4f0000f0,
+	0x03a11020, 0x0321101f, 0x4f0000f0, 0x4f0000f0,
 	0x4f0000f0, 0x90a60160, 0x4f0000f0, 0x4f0000f0,
 	0x4f0000f0,
 };
@@ -2052,6 +2053,34 @@ static void stac92xx_auto_set_pinctl(struct hda_codec *codec, hda_nid_t nid, int
 				  AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
 }
 
+#define stac92xx_hp_switch_info		snd_ctl_boolean_mono_info
+
+static int stac92xx_hp_switch_get(struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct sigmatel_spec *spec = codec->spec;
+
+	ucontrol->value.integer.value[0] = spec->hp_switch;
+	return 0;
+}
+
+static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct sigmatel_spec *spec = codec->spec;
+
+	spec->hp_switch = ucontrol->value.integer.value[0];
+
+	/* check to be sure that the ports are upto date with
+	 * switch changes
+	 */
+	codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26);
+
+	return 1;
+}
+
 #define stac92xx_io_switch_info		snd_ctl_boolean_mono_info
 
 static int stac92xx_io_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
@@ -2123,6 +2152,15 @@ static int stac92xx_clfe_switch_put(struct snd_kcontrol *kcontrol,
 	return 1;
 }
 
+#define STAC_CODEC_HP_SWITCH(xname) \
+	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+	  .name = xname, \
+	  .index = 0, \
+	  .info = stac92xx_hp_switch_info, \
+	  .get = stac92xx_hp_switch_get, \
+	  .put = stac92xx_hp_switch_put, \
+	}
+
 #define STAC_CODEC_IO_SWITCH(xname, xpval) \
 	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
 	  .name = xname, \
@@ -2147,6 +2185,7 @@ enum {
 	STAC_CTL_WIDGET_VOL,
 	STAC_CTL_WIDGET_MUTE,
 	STAC_CTL_WIDGET_MONO_MUX,
+	STAC_CTL_WIDGET_HP_SWITCH,
 	STAC_CTL_WIDGET_IO_SWITCH,
 	STAC_CTL_WIDGET_CLFE_SWITCH
 };
@@ -2155,6 +2194,7 @@ static struct snd_kcontrol_new stac92xx_control_templates[] = {
 	HDA_CODEC_VOLUME(NULL, 0, 0, 0),
 	HDA_CODEC_MUTE(NULL, 0, 0, 0),
 	STAC_MONO_MUX,
+	STAC_CODEC_HP_SWITCH(NULL),
 	STAC_CODEC_IO_SWITCH(NULL, 0),
 	STAC_CODEC_CLFE_SWITCH(NULL, 0),
 };
@@ -2419,6 +2459,14 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
 		}
 	}
 
+	if (cfg->hp_outs > 1) {
+		err = stac92xx_add_control(spec,
+			STAC_CTL_WIDGET_HP_SWITCH,
+			"Headphone as Line Out Switch", 0);
+		if (err < 0)
+			return err;
+	}
+
 	if (spec->line_switch) {
 		nid = cfg->input_pins[AUTO_PIN_LINE];
 		pincap = snd_hda_param_read(codec, nid,
@@ -3163,6 +3211,7 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
 {
 	struct sigmatel_spec *spec = codec->spec;
 	struct auto_pin_cfg *cfg = &spec->autocfg;
+	int nid = cfg->hp_pins[cfg->hp_outs - 1];
 	int i, presence;
 
 	presence = 0;
@@ -3173,11 +3222,15 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
 	for (i = 0; i < cfg->hp_outs; i++) {
 		if (presence)
 			break;
+		if (spec->hp_switch && cfg->hp_pins[i] == nid)
+			break;
 		presence = get_hp_pin_presence(codec, cfg->hp_pins[i]);
 	}
 
 	if (presence) {
 		/* disable lineouts, enable hp */
+		if (spec->hp_switch)
+			stac92xx_reset_pinctl(codec, nid, AC_PINCTL_OUT_EN);
 		for (i = 0; i < cfg->line_outs; i++)
 			stac92xx_reset_pinctl(codec, cfg->line_out_pins[i],
 						AC_PINCTL_OUT_EN);
@@ -3190,6 +3243,8 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
 				~spec->eapd_mask);
 	} else {
 		/* enable lineouts, disable hp */
+		if (spec->hp_switch)
+			stac92xx_set_pinctl(codec, nid, AC_PINCTL_OUT_EN);
 		for (i = 0; i < cfg->line_outs; i++)
 			stac92xx_set_pinctl(codec, cfg->line_out_pins[i],
 						AC_PINCTL_OUT_EN);
@@ -3201,6 +3256,8 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
 				spec->gpio_dir, spec->gpio_data |
 				spec->eapd_mask);
 	}
+	if (!spec->hp_switch && cfg->hp_outs > 1 && presence)
+		stac92xx_set_pinctl(codec, nid, AC_PINCTL_OUT_EN);
 } 
 
 static void stac92xx_pin_sense(struct hda_codec *codec, int idx)
@@ -3459,6 +3516,7 @@ again:
 
 	switch (spec->multiout.num_dacs) {
 	case 0x3: /* 6 Channel */
+		spec->multiout.hp_nid = 0x17;
 		spec->mixer = stac92hd73xx_6ch_mixer;
 		spec->init = stac92hd73xx_6ch_core_init;
 		break;
-- 
cgit v1.2.3-70-g09d2


From cb308f97aee2c816834240c8d5f7c98dd8aff157 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Wed, 16 Apr 2008 14:13:29 +0200
Subject: [ALSA] hda - Fix ALC889A codec support

ALC889A is recognized ALC885/ALC882 but it's actually closer to
ALC888/ALC883.

Cc: Kasper Sandberg <lkml@metanurb.dk>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c | 2 ++
 1 file changed, 2 insertions(+)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 181db2177a1..fb09e4429b2 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -14042,6 +14042,8 @@ struct hda_codec_preset snd_hda_preset_realtek[] = {
 	{ .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
 	{ .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
 	{ .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc883 },
+	{ .id = 0x10ec0885, .rev = 0x100103, .name = "ALC889A",
+	  .patch = patch_alc883 },
 	{ .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
 	{ .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc883 },
 	{ .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc883 },
-- 
cgit v1.2.3-70-g09d2


From 7943a8aba93ab439bdfbd9b92221720a4a4d8153 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Wed, 16 Apr 2008 17:29:09 +0200
Subject: [ALSA] hda - Avoid unexpected breakage with ALC889A hack

The last ALC889A hack may break on some devices with certain model presets
since patch_alc*() have different model tables.  So, now it's handled in
the original patch_alc882() but fly to patch_alc883() in model=auto
appropriately.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index fb09e4429b2..732515dcc99 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -2579,6 +2579,7 @@ static void alc_free(struct hda_codec *codec)
 		kfree(spec->kctl_alloc);
 	}
 	kfree(spec);
+	codec->spec = NULL; /* to be sure */
 }
 
 /*
@@ -6336,6 +6337,8 @@ static void alc882_auto_init(struct hda_codec *codec)
 		alc_sku_automute(codec);
 }
 
+static int patch_alc883(struct hda_codec *codec); /* called in patch_alc882() */
+
 static int patch_alc882(struct hda_codec *codec)
 {
 	struct alc_spec *spec;
@@ -6365,6 +6368,11 @@ static int patch_alc882(struct hda_codec *codec)
 			board_config = ALC885_MBP3;
 			break;
 		default:
+			/* ALC889A is handled better as ALC888-compatible */
+			if (codec->revision_id == 0x100103) {
+				alc_free(codec);
+				return patch_alc883(codec);
+			}
 			printk(KERN_INFO "hda_codec: Unknown model for ALC882, "
 		       			 "trying auto-probe from BIOS...\n");
 			board_config = ALC882_AUTO;
@@ -14043,7 +14051,7 @@ struct hda_codec_preset snd_hda_preset_realtek[] = {
 	{ .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
 	{ .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc883 },
 	{ .id = 0x10ec0885, .rev = 0x100103, .name = "ALC889A",
-	  .patch = patch_alc883 },
+	  .patch = patch_alc882 }, /* should be patch_alc883() in future */
 	{ .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
 	{ .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc883 },
 	{ .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc883 },
-- 
cgit v1.2.3-70-g09d2


From 369b240d6391aef41d376c9e8769fd939c7c6c4d Mon Sep 17 00:00:00 2001
From: Roel Kluin <12o3l@tiscali.nl>
Date: Wed, 16 Apr 2008 19:30:30 +0200
Subject: [ALSA] sound/drivers/dummy.c: fix negative snd_pcm_format_width()
 check

bps is unsigned, a negative snd_pcm_format_width() return value is not noticed

Signed-off-by: Roel Kluin <12o3l@tiscali.nl>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/drivers/dummy.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

(limited to 'sound')

diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index 83ac4980c5f..4e4c69e6cb4 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -230,13 +230,14 @@ static int snd_card_dummy_pcm_prepare(struct snd_pcm_substream *substream)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct snd_dummy_pcm *dpcm = runtime->private_data;
-	unsigned int bps;
+	int bps;
+
+	bps = snd_pcm_format_width(runtime->format) * runtime->rate *
+		runtime->channels / 8;
 
-	bps = runtime->rate * runtime->channels;
-	bps *= snd_pcm_format_width(runtime->format);
-	bps /= 8;
 	if (bps <= 0)
 		return -EINVAL;
+
 	dpcm->pcm_bps = bps;
 	dpcm->pcm_hz = HZ;
 	dpcm->pcm_buffer_size = snd_pcm_lib_buffer_bytes(substream);
-- 
cgit v1.2.3-70-g09d2


From 9a4f20fcbd9cd89d8e4cfcaece81802c19d467ae Mon Sep 17 00:00:00 2001
From: Risto Suominen <Risto.Suominen@gmail.com>
Date: Wed, 16 Apr 2008 13:15:38 +0200
Subject: [ALSA] snd-powermac: enable headphone detection

Enable port change interrupt while initialising AWACS, Screamer, and
Burgundy chipsets.

Signed-off-by: Risto Suominen <Risto.Suominen@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/ppc/pmac.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'sound')

diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c
index 613a565e04d..6f68ac9982e 100644
--- a/sound/ppc/pmac.c
+++ b/sound/ppc/pmac.c
@@ -1300,9 +1300,9 @@ int __init snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return)
 
 	snd_pmac_sound_feature(chip, 1);
 
-	/* reset */
-	if (chip->model == PMAC_AWACS)
-		out_le32(&chip->awacs->control, 0x11);
+	/* reset & enable interrupts */
+	if (chip->model <= PMAC_BURGUNDY)
+		out_le32(&chip->awacs->control, chip->control_mask);
 
 	/* Powerbooks have odd ways of enabling inputs such as
 	   an expansion-bay CD or sound from an internal modem
-- 
cgit v1.2.3-70-g09d2


From 946cda7d64b81053beac5d31148996f3e379e89e Mon Sep 17 00:00:00 2001
From: Risto Suominen <Risto.Suominen@gmail.com>
Date: Wed, 16 Apr 2008 13:16:05 +0200
Subject: [ALSA] snd-powermac: style pmac.c

Coding style corrections for pmac.c.

Signed-off-by: Risto Suominen <Risto.Suominen@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/ppc/pmac.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'sound')

diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c
index 6f68ac9982e..a38c0c790d2 100644
--- a/sound/ppc/pmac.c
+++ b/sound/ppc/pmac.c
@@ -214,7 +214,7 @@ static int snd_pmac_pcm_prepare(struct snd_pmac *chip, struct pmac_stream *rec,
 	int rate_index;
 	long offset;
 	struct pmac_stream *astr;
-	
+
 	rec->dma_size = snd_pcm_lib_buffer_bytes(subs);
 	rec->period_size = snd_pcm_lib_period_bytes(subs);
 	rec->nperiods = rec->dma_size / rec->period_size;
@@ -643,7 +643,7 @@ static int snd_pmac_pcm_close(struct snd_pmac *chip, struct pmac_stream *rec,
 	/* reset constraints */
 	astr->cur_freqs = chip->freqs_ok;
 	astr->cur_formats = chip->formats_ok;
-	
+
 	return 0;
 }
 
-- 
cgit v1.2.3-70-g09d2


From a8c2a6bf464d983c642c8b8b001a57aabbf76673 Mon Sep 17 00:00:00 2001
From: Risto Suominen <Risto.Suominen@gmail.com>
Date: Thu, 17 Apr 2008 17:55:30 +0200
Subject: [ALSA] snd-powermac: AWACS and Screamer mixers for PM7500, Beige, and
 iMac SL

Add mixer controls and correct headphone detection bits for PowerMacs
7300/7500 (AWACS) and G3 Beige (Screamer), and iMac G3 Slot-loading
(Screamer).

Signed-off-by: Risto Suominen <Risto.Suominen@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/ppc/awacs.c | 171 +++++++++++++++++++++++++++++++++++++++++++-----------
 sound/ppc/awacs.h |  16 ++++-
 2 files changed, 151 insertions(+), 36 deletions(-)

(limited to 'sound')

diff --git a/sound/ppc/awacs.c b/sound/ppc/awacs.c
index 8441e780df0..db4e35d2824 100644
--- a/sound/ppc/awacs.c
+++ b/sound/ppc/awacs.c
@@ -544,7 +544,7 @@ static int snd_pmac_screamer_mic_boost_info(struct snd_kcontrol *kcontrol,
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 	uinfo->count = 1;
 	uinfo->value.integer.min = 0;
-	uinfo->value.integer.max = 2;
+	uinfo->value.integer.max = 3;
 	return 0;
 }
 
@@ -552,16 +552,14 @@ static int snd_pmac_screamer_mic_boost_get(struct snd_kcontrol *kcontrol,
 					   struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
-	int val;
+	int val = 0;
 	unsigned long flags;
 
 	spin_lock_irqsave(&chip->reg_lock, flags);
 	if (chip->awacs_reg[6] & MASK_MIC_BOOST)
-		val = 2;
-	else if (chip->awacs_reg[0] & MASK_GAINLINE)
-		val = 1;
-	else
-		val = 0;
+		val |= 2;
+	if (chip->awacs_reg[0] & MASK_GAINLINE)
+		val |= 1;
 	spin_unlock_irqrestore(&chip->reg_lock, flags);
 	ucontrol->value.integer.value[0] = val;
 	return 0;
@@ -578,11 +576,10 @@ static int snd_pmac_screamer_mic_boost_put(struct snd_kcontrol *kcontrol,
 	spin_lock_irqsave(&chip->reg_lock, flags);
 	val0 = chip->awacs_reg[0] & ~MASK_GAINLINE;
 	val6 = chip->awacs_reg[6] & ~MASK_MIC_BOOST;
-	if (ucontrol->value.integer.value[0] > 0) {
+	if (ucontrol->value.integer.value[0] & 1)
 		val0 |= MASK_GAINLINE;
-		if (ucontrol->value.integer.value[0] > 1)
-			val6 |= MASK_MIC_BOOST;
-	}
+	if (ucontrol->value.integer.value[0] & 2)
+		val6 |= MASK_MIC_BOOST;
 	if (val0 != chip->awacs_reg[0]) {
 		snd_pmac_awacs_write_reg(chip, 0, val0);
 		changed = 1;
@@ -599,9 +596,32 @@ static int snd_pmac_screamer_mic_boost_put(struct snd_kcontrol *kcontrol,
  * lists of mixer elements
  */
 static struct snd_kcontrol_new snd_pmac_awacs_mixers[] __initdata = {
-	AWACS_VOLUME("Master Playback Volume", 2, 6, 1),
 	AWACS_SWITCH("Master Capture Switch", 1, SHIFT_LOOPTHRU, 0),
-	AWACS_VOLUME("Capture Volume", 0, 4, 0),
+	AWACS_VOLUME("Master Capture Volume", 0, 4, 0),
+/*	AWACS_SWITCH("Unknown Playback Switch", 6, SHIFT_PAROUT0, 0), */
+};
+
+static struct snd_kcontrol_new snd_pmac_screamer_mixers_beige[] __initdata = {
+	AWACS_VOLUME("Master Playback Volume", 2, 6, 1),
+	AWACS_VOLUME("Play-through Playback Volume", 5, 6, 1),
+	AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
+	AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_LINE, 0),
+};
+
+static struct snd_kcontrol_new snd_pmac_screamer_mixers_imac[] __initdata = {
+	AWACS_VOLUME("Line out Playback Volume", 2, 6, 1),
+	AWACS_VOLUME("Master Playback Volume", 5, 6, 1),
+	AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
+};
+
+static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac7500[] __initdata = {
+	AWACS_VOLUME("Line out Playback Volume", 2, 6, 1),
+	AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
+	AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
+};
+
+static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac[] __initdata = {
+	AWACS_VOLUME("Master Playback Volume", 2, 6, 1),
 	AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
 };
 
@@ -621,25 +641,49 @@ static struct snd_kcontrol_new snd_pmac_screamer_mixers2[] __initdata = {
 static struct snd_kcontrol_new snd_pmac_awacs_master_sw __initdata =
 AWACS_SWITCH("Master Playback Switch", 1, SHIFT_HDMUTE, 1);
 
+static struct snd_kcontrol_new snd_pmac_awacs_master_sw_imac __initdata =
+AWACS_SWITCH("Line out Playback Switch", 1, SHIFT_HDMUTE, 1);
+
 static struct snd_kcontrol_new snd_pmac_awacs_mic_boost[] __initdata = {
-	AWACS_SWITCH("Mic Boost", 0, SHIFT_GAINLINE, 0),
+	AWACS_SWITCH("Mic Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
 };
 
 static struct snd_kcontrol_new snd_pmac_screamer_mic_boost[] __initdata = {
 	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-	  .name = "Mic Boost",
+	  .name = "Mic Boost Capture Volume",
 	  .info = snd_pmac_screamer_mic_boost_info,
 	  .get = snd_pmac_screamer_mic_boost_get,
 	  .put = snd_pmac_screamer_mic_boost_put,
 	},
 };
 
+static struct snd_kcontrol_new snd_pmac_awacs_mic_boost_pmac7500[] __initdata =
+{
+	AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
+};
+
+static struct snd_kcontrol_new snd_pmac_screamer_mic_boost_beige[] __initdata =
+{
+	AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
+	AWACS_SWITCH("CD Boost Capture Switch", 6, SHIFT_MIC_BOOST, 0),
+};
+
+static struct snd_kcontrol_new snd_pmac_screamer_mic_boost_imac[] __initdata =
+{
+	AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
+	AWACS_SWITCH("Mic Boost Capture Switch", 6, SHIFT_MIC_BOOST, 0),
+};
+
 static struct snd_kcontrol_new snd_pmac_awacs_speaker_vol[] __initdata = {
 	AWACS_VOLUME("PC Speaker Playback Volume", 4, 6, 1),
 };
+
 static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw __initdata =
 AWACS_SWITCH("PC Speaker Playback Switch", 1, SHIFT_SPKMUTE, 1);
 
+static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac __initdata =
+AWACS_SWITCH("PC Speaker Playback Switch", 1, SHIFT_PAROUT1, 0);
+
 
 /*
  * add new mixer elements to the card
@@ -708,6 +752,14 @@ static void snd_pmac_awacs_resume(struct snd_pmac *chip)
 }
 #endif /* CONFIG_PM */
 
+#define IS_PM7500 (machine_is_compatible("AAPL,7500"))
+#define IS_BEIGE (machine_is_compatible("AAPL,Gossamer"))
+#define IS_IMAC (machine_is_compatible("PowerMac2,1") \
+		|| machine_is_compatible("PowerMac2,2") \
+		|| machine_is_compatible("PowerMac4,1"))
+
+static int imac;
+
 #ifdef PMAC_SUPPORT_AUTOMUTE
 /*
  * auto-mute stuffs
@@ -750,9 +802,16 @@ static void snd_pmac_awacs_update_automute(struct snd_pmac *chip, int do_notify)
 		} else
 #endif
 		{
-			int reg = chip->awacs_reg[1] | (MASK_HDMUTE|MASK_SPKMUTE);
+			int reg = chip->awacs_reg[1]
+				| (MASK_HDMUTE | MASK_SPKMUTE);
+			if (imac) {
+				reg &= ~MASK_SPKMUTE;
+				reg &= ~MASK_PAROUT1;
+			}
 			if (snd_pmac_awacs_detect_headphone(chip))
 				reg &= ~MASK_HDMUTE;
+			else if (imac)
+				reg |= MASK_PAROUT1;
 			else
 				reg &= ~MASK_SPKMUTE;
 			if (do_notify && reg == chip->awacs_reg[1])
@@ -778,8 +837,11 @@ static void snd_pmac_awacs_update_automute(struct snd_pmac *chip, int do_notify)
 int __init
 snd_pmac_awacs_init(struct snd_pmac *chip)
 {
+	int pm7500 = IS_PM7500;
+	int beige = IS_BEIGE;
 	int err, vol;
 
+	imac = IS_IMAC;
 	/* looks like MASK_GAINLINE triggers something, so we set here
 	 * as start-up
 	 */
@@ -826,20 +888,25 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
 		/* set headphone-jack detection bit */
 		switch (chip->model) {
 		case PMAC_AWACS:
-			chip->hp_stat_mask = 0x04;
+			chip->hp_stat_mask = pm7500 ? MASK_HDPCONN
+				: MASK_LOCONN;
 			break;
 		case PMAC_SCREAMER:
 			switch (chip->device_id) {
 			case 0x08:
-				/* 1 = side jack, 2 = front jack */
-				chip->hp_stat_mask = 0x03;
+			case 0x0B:
+				chip->hp_stat_mask = imac
+					? MASK_LOCONN_IMAC |
+					MASK_HDPLCONN_IMAC |
+					MASK_HDPRCONN_IMAC
+					: MASK_HDPCONN;
 				break;
 			case 0x00:
 			case 0x05:
-				chip->hp_stat_mask = 0x04;
+				chip->hp_stat_mask = MASK_LOCONN;
 				break;
 			default:
-				chip->hp_stat_mask = 0x08;
+				chip->hp_stat_mask = MASK_HDPCONN;
 				break;
 			}
 			break;
@@ -857,15 +924,37 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
 	if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mixers),
 				snd_pmac_awacs_mixers)) < 0)
 		return err;
-	if (chip->model == PMAC_SCREAMER)
+	if (beige)
+		;
+	else if (chip->model == PMAC_SCREAMER)
 		err = build_mixers(chip, ARRAY_SIZE(snd_pmac_screamer_mixers2),
 				   snd_pmac_screamer_mixers2);
-	else
+	else if (!pm7500)
 		err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mixers2),
 				   snd_pmac_awacs_mixers2);
 	if (err < 0)
 		return err;
-	chip->master_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_master_sw, chip);
+	if (pm7500)
+		err = build_mixers(chip,
+				   ARRAY_SIZE(snd_pmac_awacs_mixers_pmac7500),
+				   snd_pmac_awacs_mixers_pmac7500);
+	else if (beige)
+		err = build_mixers(chip,
+				   ARRAY_SIZE(snd_pmac_screamer_mixers_beige),
+				   snd_pmac_screamer_mixers_beige);
+	else if (imac)
+		err = build_mixers(chip,
+				   ARRAY_SIZE(snd_pmac_screamer_mixers_imac),
+				   snd_pmac_screamer_mixers_imac);
+	else
+		err = build_mixers(chip,
+				   ARRAY_SIZE(snd_pmac_awacs_mixers_pmac),
+				   snd_pmac_awacs_mixers_pmac);
+	if (err < 0)
+		return err;
+	chip->master_sw_ctl = snd_ctl_new1((pm7500 || imac)
+			? &snd_pmac_awacs_master_sw_imac
+			: &snd_pmac_awacs_master_sw, chip);
 	if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0)
 		return err;
 #ifdef PMAC_AMP_AVAIL
@@ -893,20 +982,34 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
 		if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_speaker_vol),
 					snd_pmac_awacs_speaker_vol)) < 0)
 			return err;
-		chip->speaker_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_speaker_sw, chip);
+		chip->speaker_sw_ctl = snd_ctl_new1(imac
+				? &snd_pmac_awacs_speaker_sw_imac
+				: &snd_pmac_awacs_speaker_sw, chip);
 		if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0)
 			return err;
 	}
 
-	if (chip->model == PMAC_SCREAMER) {
-		if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_screamer_mic_boost),
-					snd_pmac_screamer_mic_boost)) < 0)
-			return err;
-	} else {
-		if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mic_boost),
-					snd_pmac_awacs_mic_boost)) < 0)
-			return err;
-	}
+	if (beige)
+		err = build_mixers(chip,
+				ARRAY_SIZE(snd_pmac_screamer_mic_boost_beige),
+				snd_pmac_screamer_mic_boost_beige);
+	else if (imac)
+		err = build_mixers(chip,
+				ARRAY_SIZE(snd_pmac_screamer_mic_boost_imac),
+				snd_pmac_screamer_mic_boost_imac);
+	else if (chip->model == PMAC_SCREAMER)
+		err = build_mixers(chip,
+				ARRAY_SIZE(snd_pmac_screamer_mic_boost),
+				snd_pmac_screamer_mic_boost);
+	else if (pm7500)
+		err = build_mixers(chip,
+				ARRAY_SIZE(snd_pmac_awacs_mic_boost_pmac7500),
+				snd_pmac_awacs_mic_boost_pmac7500);
+	else
+		err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mic_boost),
+				snd_pmac_awacs_mic_boost);
+	if (err < 0)
+		return err;
 
 	/*
 	 * set lowlevel callbacks
diff --git a/sound/ppc/awacs.h b/sound/ppc/awacs.h
index 1b2cc44eda5..684bfa7cfff 100644
--- a/sound/ppc/awacs.h
+++ b/sound/ppc/awacs.h
@@ -116,6 +116,11 @@ struct awacs_regs {
 #define MASK_HDMUTE	MASK_AMUTE
 #define SHIFT_HDMUTE	9
 #define MASK_PAROUT	(0x3 << 10)	/* Parallel Out (???) */
+#define MASK_PAROUT0	(0x1 << 10)	/* Parallel Out (???) */
+#define MASK_PAROUT1	(0x1 << 11)	/* Parallel Out (enable speaker) */
+#define SHIFT_PAROUT	10
+#define SHIFT_PAROUT0	10
+#define SHIFT_PAROUT1	11
 
 #define SAMPLERATE_48000	(0x0 << 3)	/* 48 or 44.1 kHz */
 #define SAMPLERATE_32000	(0x1 << 3)	/* 32 or 29.4 kHz */
@@ -152,8 +157,15 @@ struct awacs_regs {
 #define MASK_REVISION	(0xf << 12)	/* Revision Number */
 #define MASK_MFGID	(0xf << 8)	/* Mfg. ID */
 #define MASK_CODSTATRES	(0xf << 4)	/* bits 4 - 7 reserved */
-#define MASK_INPPORT	(0xf)		/* Input Port */
-#define MASK_HDPCONN	8		/* headphone plugged in */
+#define MASK_INSENSE	(0xf)		/* port sense bits: */
+#define MASK_HDPCONN		8	/* headphone plugged in */
+#define MASK_LOCONN		4	/* line-out plugged in */
+#define MASK_LICONN		2	/* line-in plugged in */
+#define MASK_MICCONN		1	/* microphone plugged in */
+#define MASK_LICONN_IMAC	8	/* line-in plugged in */
+#define MASK_HDPRCONN_IMAC	4	/* headphone right plugged in */
+#define MASK_HDPLCONN_IMAC	2	/* headphone left plugged in */
+#define MASK_LOCONN_IMAC	1	/* line-out plugged in */
 
 /* Clipping Count Reg Bit Masks */
 /* -------- ----- --- --- ----- */
-- 
cgit v1.2.3-70-g09d2


From 7ae44cfa7ab29b277691327e8de790d7b880722f Mon Sep 17 00:00:00 2001
From: Risto Suominen <Risto.Suominen@gmail.com>
Date: Wed, 16 Apr 2008 19:39:27 +0200
Subject: [ALSA] snd-powermac: style awacs.s and awacs.h

Coding style corrections for awacs.c and awacs.h.

Signed-off-by: Risto Suominen <Risto.Suominen@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/ppc/awacs.c | 94 ++++++++++++++++++++++++++++++++++---------------------
 sound/ppc/awacs.h |  5 +--
 2 files changed, 62 insertions(+), 37 deletions(-)

(limited to 'sound')

diff --git a/sound/ppc/awacs.c b/sound/ppc/awacs.c
index db4e35d2824..566a6d0daf4 100644
--- a/sound/ppc/awacs.c
+++ b/sound/ppc/awacs.c
@@ -141,7 +141,7 @@ static int snd_pmac_awacs_info_volume(struct snd_kcontrol *kcontrol,
 	uinfo->value.integer.max = 15;
 	return 0;
 }
- 
+
 static int snd_pmac_awacs_get_volume(struct snd_kcontrol *kcontrol,
 				     struct snd_ctl_elem_value *ucontrol)
 {
@@ -267,7 +267,8 @@ static int snd_pmac_awacs_put_switch(struct snd_kcontrol *kcontrol,
 static void awacs_set_cuda(int reg, int val)
 {
 	struct adb_request req;
-	cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC, 0x8a, reg, val);
+	cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC, 0x8a,
+			reg, val);
 	while (! req.complete)
 		cuda_poll();
 }
@@ -289,11 +290,11 @@ static void awacs_amp_set_tone(struct awacs_amp *amp, int bass, int treble)
 /*
  * vol = 0 - 31 (attenuation), 32 = mute bit, stereo
  */
-static int awacs_amp_set_vol(struct awacs_amp *amp, int index, int lvol, int rvol,
-			     int do_check)
+static int awacs_amp_set_vol(struct awacs_amp *amp, int index,
+			     int lvol, int rvol, int do_check)
 {
 	if (do_check && amp->amp_vol[index][0] == lvol &&
-	    amp->amp_vol[index][1] == rvol)
+			amp->amp_vol[index][1] == rvol)
 		return 0;
 	awacs_set_cuda(3 + index, lvol);
 	awacs_set_cuda(5 + index, rvol);
@@ -337,7 +338,7 @@ static int snd_pmac_awacs_info_volume_amp(struct snd_kcontrol *kcontrol,
 	uinfo->value.integer.max = 31;
 	return 0;
 }
- 
+
 static int snd_pmac_awacs_get_volume_amp(struct snd_kcontrol *kcontrol,
 					 struct snd_ctl_elem_value *ucontrol)
 {
@@ -361,8 +362,10 @@ static int snd_pmac_awacs_put_volume_amp(struct snd_kcontrol *kcontrol,
 	snd_assert(amp, return -EINVAL);
 	snd_assert(index >= 0 && index <= 1, return -EINVAL);
 
-	vol[0] = (31 - (ucontrol->value.integer.value[0] & 31)) | (amp->amp_vol[index][0] & 32);
-	vol[1] = (31 - (ucontrol->value.integer.value[1] & 31)) | (amp->amp_vol[index][1] & 32);
+	vol[0] = (31 - (ucontrol->value.integer.value[0] & 31))
+		| (amp->amp_vol[index][0] & 32);
+	vol[1] = (31 - (ucontrol->value.integer.value[1] & 31))
+		| (amp->amp_vol[index][1] & 32);
 	return awacs_amp_set_vol(amp, index, vol[0], vol[1], 1);
 }
 
@@ -374,8 +377,10 @@ static int snd_pmac_awacs_get_switch_amp(struct snd_kcontrol *kcontrol,
 	struct awacs_amp *amp = chip->mixer_data;
 	snd_assert(amp, return -EINVAL);
 	snd_assert(index >= 0 && index <= 1, return -EINVAL);
-	ucontrol->value.integer.value[0] = (amp->amp_vol[index][0] & 32) ? 0 : 1;
-	ucontrol->value.integer.value[1] = (amp->amp_vol[index][1] & 32) ? 0 : 1;
+	ucontrol->value.integer.value[0] = (amp->amp_vol[index][0] & 32)
+					? 0 : 1;
+	ucontrol->value.integer.value[1] = (amp->amp_vol[index][1] & 32)
+					? 0 : 1;
 	return 0;
 }
 
@@ -389,8 +394,10 @@ static int snd_pmac_awacs_put_switch_amp(struct snd_kcontrol *kcontrol,
 	snd_assert(amp, return -EINVAL);
 	snd_assert(index >= 0 && index <= 1, return -EINVAL);
 
-	vol[0] = (ucontrol->value.integer.value[0] ? 0 : 32) | (amp->amp_vol[index][0] & 31);
-	vol[1] = (ucontrol->value.integer.value[1] ? 0 : 32) | (amp->amp_vol[index][1] & 31);
+	vol[0] = (ucontrol->value.integer.value[0] ? 0 : 32)
+		| (amp->amp_vol[index][0] & 31);
+	vol[1] = (ucontrol->value.integer.value[1] ? 0 : 32)
+		| (amp->amp_vol[index][1] & 31);
 	return awacs_amp_set_vol(amp, index, vol[0], vol[1], 1);
 }
 
@@ -403,7 +410,7 @@ static int snd_pmac_awacs_info_tone_amp(struct snd_kcontrol *kcontrol,
 	uinfo->value.integer.max = 14;
 	return 0;
 }
- 
+
 static int snd_pmac_awacs_get_tone_amp(struct snd_kcontrol *kcontrol,
 				       struct snd_ctl_elem_value *ucontrol)
 {
@@ -445,7 +452,7 @@ static int snd_pmac_awacs_info_master_amp(struct snd_kcontrol *kcontrol,
 	uinfo->value.integer.max = 99;
 	return 0;
 }
- 
+
 static int snd_pmac_awacs_get_master_amp(struct snd_kcontrol *kcontrol,
 					 struct snd_ctl_elem_value *ucontrol)
 {
@@ -688,12 +695,14 @@ AWACS_SWITCH("PC Speaker Playback Switch", 1, SHIFT_PAROUT1, 0);
 /*
  * add new mixer elements to the card
  */
-static int build_mixers(struct snd_pmac *chip, int nums, struct snd_kcontrol_new *mixers)
+static int build_mixers(struct snd_pmac *chip, int nums,
+			struct snd_kcontrol_new *mixers)
 {
 	int i, err;
 
 	for (i = 0; i < nums; i++) {
-		if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&mixers[i], chip))) < 0)
+		err = snd_ctl_add(chip->card, snd_ctl_new1(&mixers[i], chip));
+		if (err < 0)
 			return err;
 	}
 	return 0;
@@ -743,8 +752,10 @@ static void snd_pmac_awacs_resume(struct snd_pmac *chip)
 #ifdef PMAC_AMP_AVAIL
 	if (chip->mixer_data) {
 		struct awacs_amp *amp = chip->mixer_data;
-		awacs_amp_set_vol(amp, 0, amp->amp_vol[0][0], amp->amp_vol[0][1], 0);
-		awacs_amp_set_vol(amp, 1, amp->amp_vol[1][0], amp->amp_vol[1][1], 0);
+		awacs_amp_set_vol(amp, 0,
+				  amp->amp_vol[0][0], amp->amp_vol[0][1], 0);
+		awacs_amp_set_vol(amp, 1,
+				  amp->amp_vol[1][0], amp->amp_vol[1][1], 0);
 		awacs_amp_set_tone(amp, amp->amp_tone[0], amp->amp_tone[1]);
 		awacs_amp_set_master(amp, amp->amp_master);
 	}
@@ -849,7 +860,7 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
 	chip->awacs_reg[1] = MASK_CMUTE | MASK_AMUTE;
 	/* FIXME: Only machines with external SRS module need MASK_PAROUT */
 	if (chip->has_iic || chip->device_id == 0x5 ||
-	    /*chip->_device_id == 0x8 || */
+	    /* chip->_device_id == 0x8 || */
 	    chip->device_id == 0xb)
 		chip->awacs_reg[1] |= MASK_PAROUT;
 	/* get default volume from nvram */
@@ -860,8 +871,10 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
 	chip->awacs_reg[2] = vol;
 	chip->awacs_reg[4] = vol;
 	if (chip->model == PMAC_SCREAMER) {
-		chip->awacs_reg[5] = vol; /* FIXME: screamer has loopthru vol control */
-		chip->awacs_reg[6] = MASK_MIC_BOOST; /* FIXME: maybe should be vol << 3 for PCMCIA speaker */
+		/* FIXME: screamer has loopthru vol control */
+		chip->awacs_reg[5] = vol;
+		/* FIXME: maybe should be vol << 3 for PCMCIA speaker */
+		chip->awacs_reg[6] = MASK_MIC_BOOST;
 		chip->awacs_reg[7] = 0;
 	}
 
@@ -877,7 +890,8 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
 			return -ENOMEM;
 		chip->mixer_data = amp;
 		chip->mixer_free = awacs_amp_free;
-		awacs_amp_set_vol(amp, 0, 63, 63, 0); /* mute and zero vol */
+		/* mute and zero vol */
+		awacs_amp_set_vol(amp, 0, 63, 63, 0);
 		awacs_amp_set_vol(amp, 1, 63, 63, 0);
 		awacs_amp_set_tone(amp, 7, 7); /* 0 dB */
 		awacs_amp_set_master(amp, 79); /* 0 dB */
@@ -921,8 +935,9 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
 	 */
 	strcpy(chip->card->mixername, "PowerMac AWACS");
 
-	if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mixers),
-				snd_pmac_awacs_mixers)) < 0)
+	err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mixers),
+				snd_pmac_awacs_mixers);
+	if (err < 0)
 		return err;
 	if (beige)
 		;
@@ -955,7 +970,8 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
 	chip->master_sw_ctl = snd_ctl_new1((pm7500 || imac)
 			? &snd_pmac_awacs_master_sw_imac
 			: &snd_pmac_awacs_master_sw, chip);
-	if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0)
+	err = snd_ctl_add(chip->card, chip->master_sw_ctl);
+	if (err < 0)
 		return err;
 #ifdef PMAC_AMP_AVAIL
 	if (chip->mixer_data) {
@@ -965,27 +981,34 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
 		 * screamer registers.
 		 * in this case, it seems the route C is not used.
 		 */
-		if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_amp_vol),
-					snd_pmac_awacs_amp_vol)) < 0)
+		err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_amp_vol),
+					snd_pmac_awacs_amp_vol);
+		if (err < 0)
 			return err;
 		/* overwrite */
-		chip->master_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_amp_hp_sw, chip);
-		if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0)
+		chip->master_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_amp_hp_sw,
+							chip);
+		err = snd_ctl_add(chip->card, chip->master_sw_ctl);
+		if (err < 0)
 			return err;
-		chip->speaker_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_amp_spk_sw, chip);
-		if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0)
+		chip->speaker_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_amp_spk_sw,
+							chip);
+		err = snd_ctl_add(chip->card, chip->speaker_sw_ctl);
+		if (err < 0)
 			return err;
 	} else
 #endif /* PMAC_AMP_AVAIL */
 	{
 		/* route A = headphone, route C = speaker */
-		if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_speaker_vol),
-					snd_pmac_awacs_speaker_vol)) < 0)
+		err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_speaker_vol),
+					snd_pmac_awacs_speaker_vol);
+		if (err < 0)
 			return err;
 		chip->speaker_sw_ctl = snd_ctl_new1(imac
 				? &snd_pmac_awacs_speaker_sw_imac
 				: &snd_pmac_awacs_speaker_sw, chip);
-		if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0)
+		err = snd_ctl_add(chip->card, chip->speaker_sw_ctl);
+		if (err < 0)
 			return err;
 	}
 
@@ -1020,7 +1043,8 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
 	chip->resume = snd_pmac_awacs_resume;
 #endif
 #ifdef PMAC_SUPPORT_AUTOMUTE
-	if ((err = snd_pmac_add_automute(chip)) < 0)
+	err = snd_pmac_add_automute(chip);
+	if (err < 0)
 		return err;
 	chip->detect_headphone = snd_pmac_awacs_detect_headphone;
 	chip->update_automute = snd_pmac_awacs_update_automute;
diff --git a/sound/ppc/awacs.h b/sound/ppc/awacs.h
index 684bfa7cfff..c33e6a531cf 100644
--- a/sound/ppc/awacs.h
+++ b/sound/ppc/awacs.h
@@ -144,7 +144,7 @@ struct awacs_regs {
 #define VOLLEFT(x)	(((~(x)) << 6) & MASK_OUTVOLLEFT)
 
 /* address 6 */
-#define MASK_MIC_BOOST  (0x4)           /* screamer mic boost */
+#define MASK_MIC_BOOST  (0x4)		/* screamer mic boost */
 #define SHIFT_MIC_BOOST	2
 
 /* Audio Codec Status Reg Bit Masks */
@@ -175,7 +175,8 @@ struct awacs_regs {
 /* DBDMA ChannelStatus Bit Masks */
 /* ----- ------------- --- ----- */
 #define MASK_CSERR	(0x1 << 7)	/* Error */
-#define MASK_EOI	(0x1 << 6)	/* End of Input -- only for Input Channel */
+#define MASK_EOI	(0x1 << 6)	/* End of Input --
+					   only for Input Channel */
 #define MASK_CSUNUSED	(0x1f << 1)	/* bits 1-5 not used */
 #define MASK_WAIT	(0x1)		/* Wait */
 
-- 
cgit v1.2.3-70-g09d2


From 44deee129c9af3759d3e5e772b82012742dc57a0 Mon Sep 17 00:00:00 2001
From: Risto Suominen <Risto.Suominen@gmail.com>
Date: Wed, 16 Apr 2008 19:45:31 +0200
Subject: [ALSA] snd-powermac: Burgundy mixers for B&W and iMac

Add mixer controls and correct headphone detection bits for PowerMac
G3 B&W and iMac G3 Tray-loading, both having Burgundy chipset.

Signed-off-by: Risto Suominen <Risto.Suominen@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/ppc/burgundy.c | 433 ++++++++++++++++++++++++++++++++++++++++++---------
 sound/ppc/burgundy.h |  31 +++-
 2 files changed, 381 insertions(+), 83 deletions(-)

(limited to 'sound')

diff --git a/sound/ppc/burgundy.c b/sound/ppc/burgundy.c
index 1a545ac0de0..f0c12a97fdb 100644
--- a/sound/ppc/burgundy.c
+++ b/sound/ppc/burgundy.c
@@ -211,17 +211,156 @@ static int snd_pmac_burgundy_put_volume(struct snd_kcontrol *kcontrol,
 		nvoices[1] != ucontrol->value.integer.value[1]);
 }
 
-#define BURGUNDY_VOLUME(xname, xindex, addr, shift) \
+#define BURGUNDY_VOLUME_W(xname, xindex, addr, shift) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
   .info = snd_pmac_burgundy_info_volume,\
   .get = snd_pmac_burgundy_get_volume,\
   .put = snd_pmac_burgundy_put_volume,\
   .private_value = ((ADDR2BASE(addr) & 0xff) | ((shift) << 8)) }
 
-/* lineout/speaker */
+/*
+ * Burgundy volume: 0 - 100, stereo, 2-byte reg
+ */
+static void
+snd_pmac_burgundy_write_volume_2b(struct snd_pmac *chip, unsigned int address,
+				  long *volume, int off)
+{
+	int lvolume, rvolume;
+
+	off |= off << 2;
+	lvolume = volume[0] ? volume[0] + BURGUNDY_VOLUME_OFFSET : 0;
+	rvolume = volume[1] ? volume[1] + BURGUNDY_VOLUME_OFFSET : 0;
+
+	snd_pmac_burgundy_wcb(chip, address + off, lvolume);
+	snd_pmac_burgundy_wcb(chip, address + off + 0x500, rvolume);
+}
+
+static void
+snd_pmac_burgundy_read_volume_2b(struct snd_pmac *chip, unsigned int address,
+				 long *volume, int off)
+{
+	volume[0] = snd_pmac_burgundy_rcb(chip, address + off);
+	if (volume[0] >= BURGUNDY_VOLUME_OFFSET)
+		volume[0] -= BURGUNDY_VOLUME_OFFSET;
+	else
+		volume[0] = 0;
+	volume[1] = snd_pmac_burgundy_rcb(chip, address + off + 0x100);
+	if (volume[1] >= BURGUNDY_VOLUME_OFFSET)
+		volume[1] -= BURGUNDY_VOLUME_OFFSET;
+	else
+		volume[1] = 0;
+}
+
+static int snd_pmac_burgundy_info_volume_2b(struct snd_kcontrol *kcontrol,
+					    struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 2;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 100;
+	return 0;
+}
+
+static int snd_pmac_burgundy_get_volume_2b(struct snd_kcontrol *kcontrol,
+					   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+	unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
+	int off = kcontrol->private_value & 0x300;
+	snd_pmac_burgundy_read_volume_2b(chip, addr,
+			ucontrol->value.integer.value, off);
+	return 0;
+}
+
+static int snd_pmac_burgundy_put_volume_2b(struct snd_kcontrol *kcontrol,
+					   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+	unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
+	int off = kcontrol->private_value & 0x300;
+	long nvoices[2];
+
+	snd_pmac_burgundy_write_volume_2b(chip, addr,
+			ucontrol->value.integer.value, off);
+	snd_pmac_burgundy_read_volume_2b(chip, addr, nvoices, off);
+	return (nvoices[0] != ucontrol->value.integer.value[0] ||
+		nvoices[1] != ucontrol->value.integer.value[1]);
+}
+
+#define BURGUNDY_VOLUME_2B(xname, xindex, addr, off) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
+  .info = snd_pmac_burgundy_info_volume_2b,\
+  .get = snd_pmac_burgundy_get_volume_2b,\
+  .put = snd_pmac_burgundy_put_volume_2b,\
+  .private_value = ((ADDR2BASE(addr) & 0xff) | ((off) << 8)) }
+
+/*
+ * Burgundy gain/attenuation: 0 - 15, mono/stereo, byte reg
+ */
+static int snd_pmac_burgundy_info_gain(struct snd_kcontrol *kcontrol,
+				       struct snd_ctl_elem_info *uinfo)
+{
+	int stereo = (kcontrol->private_value >> 24) & 1;
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = stereo + 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 15;
+	return 0;
+}
 
-static int snd_pmac_burgundy_info_switch_out(struct snd_kcontrol *kcontrol,
-					     struct snd_ctl_elem_info *uinfo)
+static int snd_pmac_burgundy_get_gain(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+	unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
+	int stereo = (kcontrol->private_value >> 24) & 1;
+	int atten = (kcontrol->private_value >> 25) & 1;
+	int oval;
+
+	oval = snd_pmac_burgundy_rcb(chip, addr);
+	if (atten)
+		oval = ~oval & 0xff;
+	ucontrol->value.integer.value[0] = oval & 0xf;
+	if (stereo)
+		ucontrol->value.integer.value[1] = (oval >> 4) & 0xf;
+	return 0;
+}
+
+static int snd_pmac_burgundy_put_gain(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+	unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
+	int stereo = (kcontrol->private_value >> 24) & 1;
+	int atten = (kcontrol->private_value >> 25) & 1;
+	int oval, val;
+
+	oval = snd_pmac_burgundy_rcb(chip, addr);
+	if (atten)
+		oval = ~oval & 0xff;
+	val = ucontrol->value.integer.value[0];
+	if (stereo)
+		val |= ucontrol->value.integer.value[1] << 4;
+	else
+		val |= ucontrol->value.integer.value[0] << 4;
+	if (atten)
+		val = ~val & 0xff;
+	snd_pmac_burgundy_wcb(chip, addr, val);
+	return val != oval;
+}
+
+#define BURGUNDY_VOLUME_B(xname, xindex, addr, stereo, atten) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
+  .info = snd_pmac_burgundy_info_gain,\
+  .get = snd_pmac_burgundy_get_gain,\
+  .put = snd_pmac_burgundy_put_gain,\
+  .private_value = (ADDR2BASE(addr) | ((stereo) << 24) | ((atten) << 25)) }
+
+/*
+ * Burgundy switch: 0/1, mono/stereo, word reg
+ */
+static int snd_pmac_burgundy_info_switch_w(struct snd_kcontrol *kcontrol,
+					   struct snd_ctl_elem_info *uinfo)
 {
 	int stereo = (kcontrol->private_value >> 24) & 1;
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
@@ -231,111 +370,207 @@ static int snd_pmac_burgundy_info_switch_out(struct snd_kcontrol *kcontrol,
 	return 0;
 }
 
-static int snd_pmac_burgundy_get_switch_out(struct snd_kcontrol *kcontrol,
-					    struct snd_ctl_elem_value *ucontrol)
+static int snd_pmac_burgundy_get_switch_w(struct snd_kcontrol *kcontrol,
+					  struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
-	int lmask = kcontrol->private_value & 0xff;
-	int rmask = (kcontrol->private_value >> 8) & 0xff;
+	unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff);
+	int lmask = 1 << (kcontrol->private_value & 0xff);
+	int rmask = 1 << ((kcontrol->private_value >> 8) & 0xff);
 	int stereo = (kcontrol->private_value >> 24) & 1;
-	int val = snd_pmac_burgundy_rcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES);
+	int val = snd_pmac_burgundy_rcw(chip, addr);
 	ucontrol->value.integer.value[0] = (val & lmask) ? 1 : 0;
 	if (stereo)
 		ucontrol->value.integer.value[1] = (val & rmask) ? 1 : 0;
 	return 0;
 }
 
-static int snd_pmac_burgundy_put_switch_out(struct snd_kcontrol *kcontrol,
-					    struct snd_ctl_elem_value *ucontrol)
+static int snd_pmac_burgundy_put_switch_w(struct snd_kcontrol *kcontrol,
+					  struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
-	int lmask = kcontrol->private_value & 0xff;
-	int rmask = (kcontrol->private_value >> 8) & 0xff;
+	unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff);
+	int lmask = 1 << (kcontrol->private_value & 0xff);
+	int rmask = 1 << ((kcontrol->private_value >> 8) & 0xff);
 	int stereo = (kcontrol->private_value >> 24) & 1;
 	int val, oval;
-	oval = snd_pmac_burgundy_rcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES);
-	val = oval & ~(lmask | rmask);
+	oval = snd_pmac_burgundy_rcw(chip, addr);
+	val = oval & ~(lmask | (stereo ? rmask : 0));
 	if (ucontrol->value.integer.value[0])
 		val |= lmask;
 	if (stereo && ucontrol->value.integer.value[1])
 		val |= rmask;
-	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, val);
+	snd_pmac_burgundy_wcw(chip, addr, val);
 	return val != oval;
 }
 
-#define BURGUNDY_OUTPUT_SWITCH(xname, xindex, lmask, rmask, stereo) \
+#define BURGUNDY_SWITCH_W(xname, xindex, addr, lbit, rbit, stereo) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
-  .info = snd_pmac_burgundy_info_switch_out,\
-  .get = snd_pmac_burgundy_get_switch_out,\
-  .put = snd_pmac_burgundy_put_switch_out,\
-  .private_value = ((lmask) | ((rmask) << 8) | ((stereo) << 24)) }
-
-/* line/speaker output volume */
-static int snd_pmac_burgundy_info_volume_out(struct snd_kcontrol *kcontrol,
-					     struct snd_ctl_elem_info *uinfo)
+  .info = snd_pmac_burgundy_info_switch_w,\
+  .get = snd_pmac_burgundy_get_switch_w,\
+  .put = snd_pmac_burgundy_put_switch_w,\
+  .private_value = ((lbit) | ((rbit) << 8)\
+		| (ADDR2BASE(addr) << 16) | ((stereo) << 24)) }
+
+/*
+ * Burgundy switch: 0/1, mono/stereo, byte reg, bit mask
+ */
+static int snd_pmac_burgundy_info_switch_b(struct snd_kcontrol *kcontrol,
+					   struct snd_ctl_elem_info *uinfo)
 {
 	int stereo = (kcontrol->private_value >> 24) & 1;
-	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
 	uinfo->count = stereo + 1;
 	uinfo->value.integer.min = 0;
-	uinfo->value.integer.max = 15;
+	uinfo->value.integer.max = 1;
 	return 0;
 }
 
-static int snd_pmac_burgundy_get_volume_out(struct snd_kcontrol *kcontrol,
-					    struct snd_ctl_elem_value *ucontrol)
+static int snd_pmac_burgundy_get_switch_b(struct snd_kcontrol *kcontrol,
+					  struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
-	unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
+	unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff);
+	int lmask = kcontrol->private_value & 0xff;
+	int rmask = (kcontrol->private_value >> 8) & 0xff;
 	int stereo = (kcontrol->private_value >> 24) & 1;
-	int oval;
-
-	oval = ~snd_pmac_burgundy_rcb(chip, addr) & 0xff;
-	ucontrol->value.integer.value[0] = oval & 0xf;
+	int val = snd_pmac_burgundy_rcb(chip, addr);
+	ucontrol->value.integer.value[0] = (val & lmask) ? 1 : 0;
 	if (stereo)
-		ucontrol->value.integer.value[1] = (oval >> 4) & 0xf;
+		ucontrol->value.integer.value[1] = (val & rmask) ? 1 : 0;
 	return 0;
 }
 
-static int snd_pmac_burgundy_put_volume_out(struct snd_kcontrol *kcontrol,
-					    struct snd_ctl_elem_value *ucontrol)
+static int snd_pmac_burgundy_put_switch_b(struct snd_kcontrol *kcontrol,
+					  struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
-	unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
+	unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff);
+	int lmask = kcontrol->private_value & 0xff;
+	int rmask = (kcontrol->private_value >> 8) & 0xff;
 	int stereo = (kcontrol->private_value >> 24) & 1;
-	unsigned int oval, val;
-
-	oval = ~snd_pmac_burgundy_rcb(chip, addr) & 0xff;
-	val = ucontrol->value.integer.value[0] & 15;
-	if (stereo)
-		val |= (ucontrol->value.integer.value[1] & 15) << 4;
-	else
-		val |= val << 4;
-	val = ~val & 0xff;
+	int val, oval;
+	oval = snd_pmac_burgundy_rcb(chip, addr);
+	val = oval & ~(lmask | rmask);
+	if (ucontrol->value.integer.value[0])
+		val |= lmask;
+	if (stereo && ucontrol->value.integer.value[1])
+		val |= rmask;
 	snd_pmac_burgundy_wcb(chip, addr, val);
 	return val != oval;
 }
 
-#define BURGUNDY_OUTPUT_VOLUME(xname, xindex, addr, stereo) \
+#define BURGUNDY_SWITCH_B(xname, xindex, addr, lmask, rmask, stereo) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
-  .info = snd_pmac_burgundy_info_volume_out,\
-  .get = snd_pmac_burgundy_get_volume_out,\
-  .put = snd_pmac_burgundy_put_volume_out,\
-  .private_value = (ADDR2BASE(addr) | ((stereo) << 24)) }
+  .info = snd_pmac_burgundy_info_switch_b,\
+  .get = snd_pmac_burgundy_get_switch_b,\
+  .put = snd_pmac_burgundy_put_switch_b,\
+  .private_value = ((lmask) | ((rmask) << 8)\
+		| (ADDR2BASE(addr) << 16) | ((stereo) << 24)) }
 
+/*
+ * Burgundy mixers
+ */
 static struct snd_kcontrol_new snd_pmac_burgundy_mixers[] __initdata = {
-	BURGUNDY_VOLUME("Master Playback Volume", 0, MASK_ADDR_BURGUNDY_MASTER_VOLUME, 8),
-	BURGUNDY_VOLUME("Line Playback Volume", 0, MASK_ADDR_BURGUNDY_VOLLINE, 16),
-	BURGUNDY_VOLUME("CD Playback Volume", 0, MASK_ADDR_BURGUNDY_VOLCD, 16),
-	BURGUNDY_VOLUME("Mic Playback Volume", 0, MASK_ADDR_BURGUNDY_VOLMIC, 16),
-	BURGUNDY_OUTPUT_VOLUME("PC Speaker Playback Volume", 0, MASK_ADDR_BURGUNDY_ATTENHP, 0),
-	/*BURGUNDY_OUTPUT_VOLUME("PCM Playback Volume", 0, MASK_ADDR_BURGUNDY_ATTENLINEOUT, 1),*/
-	BURGUNDY_OUTPUT_VOLUME("Headphone Playback Volume", 0, MASK_ADDR_BURGUNDY_ATTENSPEAKER, 1),
-};	
-static struct snd_kcontrol_new snd_pmac_burgundy_master_sw __initdata = 
-BURGUNDY_OUTPUT_SWITCH("Headphone Playback Switch", 0, BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
-static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw __initdata = 
-BURGUNDY_OUTPUT_SWITCH("PC Speaker Playback Switch", 0, BURGUNDY_OUTPUT_INTERN, 0, 0);
+	BURGUNDY_VOLUME_W("Master Playback Volume", 0,
+			MASK_ADDR_BURGUNDY_MASTER_VOLUME, 8),
+	BURGUNDY_VOLUME_W("CD Capture Volume", 0,
+			MASK_ADDR_BURGUNDY_VOLCD, 16),
+	BURGUNDY_VOLUME_2B("Input Capture Volume", 0,
+			MASK_ADDR_BURGUNDY_VOLMIX01, 2),
+	BURGUNDY_VOLUME_2B("Mixer Playback Volume", 0,
+			MASK_ADDR_BURGUNDY_VOLMIX23, 0),
+	BURGUNDY_VOLUME_B("CD Gain Capture Volume", 0,
+			MASK_ADDR_BURGUNDY_GAINCD, 1, 0),
+	BURGUNDY_SWITCH_W("Master Capture Switch", 0,
+			MASK_ADDR_BURGUNDY_OUTPUTENABLES, 24, 0, 0),
+	BURGUNDY_SWITCH_W("CD Capture Switch", 0,
+			MASK_ADDR_BURGUNDY_CAPTURESELECTS, 0, 16, 1),
+	BURGUNDY_SWITCH_W("CD Playback Switch", 0,
+			MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 0, 16, 1),
+/*	BURGUNDY_SWITCH_W("Loop Capture Switch", 0,
+ *		MASK_ADDR_BURGUNDY_CAPTURESELECTS, 8, 24, 1),
+ *	BURGUNDY_SWITCH_B("Mixer out Capture Switch", 0,
+ *		MASK_ADDR_BURGUNDY_HOSTIFAD, 0x02, 0, 0),
+ *	BURGUNDY_SWITCH_B("Mixer Capture Switch", 0,
+ *		MASK_ADDR_BURGUNDY_HOSTIFAD, 0x01, 0, 0),
+ *	BURGUNDY_SWITCH_B("PCM out Capture Switch", 0,
+ *		MASK_ADDR_BURGUNDY_HOSTIFEH, 0x02, 0, 0),
+ */	BURGUNDY_SWITCH_B("PCM Capture Switch", 0,
+			MASK_ADDR_BURGUNDY_HOSTIFEH, 0x01, 0, 0)
+};
+static struct snd_kcontrol_new snd_pmac_burgundy_mixers_imac[] __initdata = {
+	BURGUNDY_VOLUME_W("Line in Capture Volume", 0,
+			MASK_ADDR_BURGUNDY_VOLLINE, 16),
+	BURGUNDY_VOLUME_W("Mic Capture Volume", 0,
+			MASK_ADDR_BURGUNDY_VOLMIC, 16),
+	BURGUNDY_VOLUME_B("Line in Gain Capture Volume", 0,
+			MASK_ADDR_BURGUNDY_GAINLINE, 1, 0),
+	BURGUNDY_VOLUME_B("Mic Gain Capture Volume", 0,
+			MASK_ADDR_BURGUNDY_GAINMIC, 1, 0),
+	BURGUNDY_VOLUME_B("PC Speaker Playback Volume", 0,
+			MASK_ADDR_BURGUNDY_ATTENSPEAKER, 1, 1),
+	BURGUNDY_VOLUME_B("Line out Playback Volume", 0,
+			MASK_ADDR_BURGUNDY_ATTENLINEOUT, 1, 1),
+	BURGUNDY_VOLUME_B("Headphone Playback Volume", 0,
+			MASK_ADDR_BURGUNDY_ATTENHP, 1, 1),
+	BURGUNDY_SWITCH_W("Line in Capture Switch", 0,
+			MASK_ADDR_BURGUNDY_CAPTURESELECTS, 1, 17, 1),
+	BURGUNDY_SWITCH_W("Mic Capture Switch", 0,
+			MASK_ADDR_BURGUNDY_CAPTURESELECTS, 2, 18, 1),
+	BURGUNDY_SWITCH_W("Line in Playback Switch", 0,
+			MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 1, 17, 1),
+	BURGUNDY_SWITCH_W("Mic Playback Switch", 0,
+			MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 2, 18, 1),
+	BURGUNDY_SWITCH_B("Mic Boost Capture Switch", 0,
+			MASK_ADDR_BURGUNDY_INPBOOST, 0x40, 0x80, 1)
+};
+static struct snd_kcontrol_new snd_pmac_burgundy_mixers_pmac[] __initdata = {
+	BURGUNDY_VOLUME_W("Line in Capture Volume", 0,
+			MASK_ADDR_BURGUNDY_VOLMIC, 16),
+	BURGUNDY_VOLUME_B("Line in Gain Capture Volume", 0,
+			MASK_ADDR_BURGUNDY_GAINMIC, 1, 0),
+	BURGUNDY_VOLUME_B("PC Speaker Playback Volume", 0,
+			MASK_ADDR_BURGUNDY_ATTENMONO, 0, 1),
+	BURGUNDY_VOLUME_B("Line out Playback Volume", 0,
+			MASK_ADDR_BURGUNDY_ATTENSPEAKER, 1, 1),
+	BURGUNDY_SWITCH_W("Line in Capture Switch", 0,
+			MASK_ADDR_BURGUNDY_CAPTURESELECTS, 2, 18, 1),
+	BURGUNDY_SWITCH_W("Line in Playback Switch", 0,
+			MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 2, 18, 1),
+/*	BURGUNDY_SWITCH_B("Line in Boost Capture Switch", 0,
+ *		MASK_ADDR_BURGUNDY_INPBOOST, 0x40, 0x80, 1) */
+};
+static struct snd_kcontrol_new snd_pmac_burgundy_master_sw_imac __initdata =
+BURGUNDY_SWITCH_B("Master Playback Switch", 0,
+	MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+	BURGUNDY_OUTPUT_LEFT | BURGUNDY_LINEOUT_LEFT | BURGUNDY_HP_LEFT,
+	BURGUNDY_OUTPUT_RIGHT | BURGUNDY_LINEOUT_RIGHT | BURGUNDY_HP_RIGHT, 1);
+static struct snd_kcontrol_new snd_pmac_burgundy_master_sw_pmac __initdata =
+BURGUNDY_SWITCH_B("Master Playback Switch", 0,
+	MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+	BURGUNDY_OUTPUT_INTERN
+	| BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
+static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_imac __initdata =
+BURGUNDY_SWITCH_B("PC Speaker Playback Switch", 0,
+	MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+	BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
+static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_pmac __initdata =
+BURGUNDY_SWITCH_B("PC Speaker Playback Switch", 0,
+	MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+	BURGUNDY_OUTPUT_INTERN, 0, 0);
+static struct snd_kcontrol_new snd_pmac_burgundy_line_sw_imac __initdata =
+BURGUNDY_SWITCH_B("Line out Playback Switch", 0,
+	MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+	BURGUNDY_LINEOUT_LEFT, BURGUNDY_LINEOUT_RIGHT, 1);
+static struct snd_kcontrol_new snd_pmac_burgundy_line_sw_pmac __initdata =
+BURGUNDY_SWITCH_B("Line out Playback Switch", 0,
+	MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+	BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
+static struct snd_kcontrol_new snd_pmac_burgundy_hp_sw_imac __initdata =
+BURGUNDY_SWITCH_B("Headphone Playback Switch", 0,
+	MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+	BURGUNDY_HP_LEFT, BURGUNDY_HP_RIGHT, 1);
 
 
 #ifdef PMAC_SUPPORT_AUTOMUTE
@@ -350,16 +585,26 @@ static int snd_pmac_burgundy_detect_headphone(struct snd_pmac *chip)
 static void snd_pmac_burgundy_update_automute(struct snd_pmac *chip, int do_notify)
 {
 	if (chip->auto_mute) {
+		int imac = machine_is_compatible("iMac");
 		int reg, oreg;
-		reg = oreg = snd_pmac_burgundy_rcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES);
-		reg &= ~(BURGUNDY_OUTPUT_LEFT | BURGUNDY_OUTPUT_RIGHT | BURGUNDY_OUTPUT_INTERN);
+		reg = oreg = snd_pmac_burgundy_rcb(chip,
+				MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES);
+		reg &= imac ? ~(BURGUNDY_OUTPUT_LEFT | BURGUNDY_OUTPUT_RIGHT
+				| BURGUNDY_HP_LEFT | BURGUNDY_HP_RIGHT)
+			: ~(BURGUNDY_OUTPUT_LEFT | BURGUNDY_OUTPUT_RIGHT
+				| BURGUNDY_OUTPUT_INTERN);
 		if (snd_pmac_burgundy_detect_headphone(chip))
-			reg |= BURGUNDY_OUTPUT_LEFT | BURGUNDY_OUTPUT_RIGHT;
+			reg |= imac ? (BURGUNDY_HP_LEFT | BURGUNDY_HP_RIGHT)
+				: (BURGUNDY_OUTPUT_LEFT
+					| BURGUNDY_OUTPUT_RIGHT);
 		else
-			reg |= BURGUNDY_OUTPUT_INTERN;
+			reg |= imac ? (BURGUNDY_OUTPUT_LEFT
+					| BURGUNDY_OUTPUT_RIGHT)
+				: (BURGUNDY_OUTPUT_INTERN);
 		if (do_notify && reg == oreg)
 			return;
-		snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, reg);
+		snd_pmac_burgundy_wcb(chip,
+				MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, reg);
 		if (do_notify) {
 			snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
 				       &chip->master_sw_ctl->id);
@@ -378,6 +623,7 @@ static void snd_pmac_burgundy_update_automute(struct snd_pmac *chip, int do_noti
  */
 int __init snd_pmac_burgundy_init(struct snd_pmac *chip)
 {
+	int imac = machine_is_compatible("iMac");
 	int i, err;
 
 	/* Checks to see the chip is alive and kicking */
@@ -386,7 +632,7 @@ int __init snd_pmac_burgundy_init(struct snd_pmac *chip)
 		return 1;
 	}
 
-	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_OUTPUTENABLES,
+	snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_OUTPUTENABLES,
 			   DEF_BURGUNDY_OUTPUTENABLES);
 	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
 			   DEF_BURGUNDY_MORE_OUTPUTENABLES);
@@ -396,7 +642,8 @@ int __init snd_pmac_burgundy_init(struct snd_pmac *chip)
 	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_INPSEL21,
 			   DEF_BURGUNDY_INPSEL21);
 	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_INPSEL3,
-			   DEF_BURGUNDY_INPSEL3);
+			   imac ? DEF_BURGUNDY_INPSEL3_IMAC
+			   : DEF_BURGUNDY_INPSEL3_PMAC);
 	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_GAINCD,
 			   DEF_BURGUNDY_GAINCD);
 	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_GAINLINE,
@@ -422,23 +669,55 @@ int __init snd_pmac_burgundy_init(struct snd_pmac *chip)
 	snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_VOLMIC,
 			   DEF_BURGUNDY_VOLMIC);
 
-	if (chip->hp_stat_mask == 0)
+	if (chip->hp_stat_mask == 0) {
 		/* set headphone-jack detection bit */
-		chip->hp_stat_mask = 0x04;
-
+		if (imac)
+			chip->hp_stat_mask = BURGUNDY_HPDETECT_IMAC_UPPER
+				| BURGUNDY_HPDETECT_IMAC_LOWER
+				| BURGUNDY_HPDETECT_IMAC_SIDE;
+		else
+			chip->hp_stat_mask = BURGUNDY_HPDETECT_PMAC_BACK;
+	}
 	/*
 	 * build burgundy mixers
 	 */
 	strcpy(chip->card->mixername, "PowerMac Burgundy");
 
 	for (i = 0; i < ARRAY_SIZE(snd_pmac_burgundy_mixers); i++) {
-		if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_pmac_burgundy_mixers[i], chip))) < 0)
+		err = snd_ctl_add(chip->card,
+		    snd_ctl_new1(&snd_pmac_burgundy_mixers[i], chip));
+		if (err < 0)
+			return err;
+	}
+	for (i = 0; i < (imac ? ARRAY_SIZE(snd_pmac_burgundy_mixers_imac)
+			: ARRAY_SIZE(snd_pmac_burgundy_mixers_pmac)); i++) {
+		err = snd_ctl_add(chip->card,
+		    snd_ctl_new1(imac ? &snd_pmac_burgundy_mixers_imac[i]
+		    : &snd_pmac_burgundy_mixers_pmac[i], chip));
+		if (err < 0)
 			return err;
 	}
-	chip->master_sw_ctl = snd_ctl_new1(&snd_pmac_burgundy_master_sw, chip);
+	chip->master_sw_ctl = snd_ctl_new1(imac
+			? &snd_pmac_burgundy_master_sw_imac
+			: &snd_pmac_burgundy_master_sw_pmac, chip);
 	if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0)
 		return err;
-	chip->speaker_sw_ctl = snd_ctl_new1(&snd_pmac_burgundy_speaker_sw, chip);
+	chip->master_sw_ctl = snd_ctl_new1(imac
+			? &snd_pmac_burgundy_line_sw_imac
+			: &snd_pmac_burgundy_line_sw_pmac, chip);
+	err = snd_ctl_add(chip->card, chip->master_sw_ctl);
+	if (err < 0)
+		return err;
+	if (imac) {
+		chip->master_sw_ctl = snd_ctl_new1(
+				&snd_pmac_burgundy_hp_sw_imac, chip);
+		err = snd_ctl_add(chip->card, chip->master_sw_ctl);
+		if (err < 0)
+			return err;
+	}
+	chip->speaker_sw_ctl = snd_ctl_new1(imac
+			? &snd_pmac_burgundy_speaker_sw_imac
+			: &snd_pmac_burgundy_speaker_sw_pmac, chip);
 	if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0)
 		return err;
 #ifdef PMAC_SUPPORT_AUTOMUTE
diff --git a/sound/ppc/burgundy.h b/sound/ppc/burgundy.h
index ebb457a8342..7a7f9cf3d29 100644
--- a/sound/ppc/burgundy.h
+++ b/sound/ppc/burgundy.h
@@ -22,6 +22,7 @@
 #ifndef __BURGUNDY_H
 #define __BURGUNDY_H
 
+#define MASK_ADDR_BURGUNDY_INPBOOST (0x10 << 12)
 #define MASK_ADDR_BURGUNDY_INPSEL21 (0x11 << 12)
 #define MASK_ADDR_BURGUNDY_INPSEL3 (0x12 << 12)
 
@@ -35,7 +36,10 @@
 #define MASK_ADDR_BURGUNDY_VOLCH3 (0x22 << 12)
 #define MASK_ADDR_BURGUNDY_VOLCH4 (0x23 << 12)
 
+#define MASK_ADDR_BURGUNDY_CAPTURESELECTS (0x2A << 12)
 #define MASK_ADDR_BURGUNDY_OUTPUTSELECTS (0x2B << 12)
+#define MASK_ADDR_BURGUNDY_VOLMIX01 (0x2D << 12)
+#define MASK_ADDR_BURGUNDY_VOLMIX23 (0x2E << 12)
 #define MASK_ADDR_BURGUNDY_OUTPUTENABLES (0x2F << 12)
 
 #define MASK_ADDR_BURGUNDY_MASTER_VOLUME (0x30 << 12)
@@ -45,6 +49,10 @@
 #define MASK_ADDR_BURGUNDY_ATTENSPEAKER (0x62 << 12)
 #define MASK_ADDR_BURGUNDY_ATTENLINEOUT (0x63 << 12)
 #define MASK_ADDR_BURGUNDY_ATTENHP (0x64 << 12)
+#define MASK_ADDR_BURGUNDY_ATTENMONO (0x65 << 12)
+
+#define MASK_ADDR_BURGUNDY_HOSTIFAD (0x78 << 12)
+#define MASK_ADDR_BURGUNDY_HOSTIFEH (0x79 << 12)
 
 #define MASK_ADDR_BURGUNDY_VOLCD (MASK_ADDR_BURGUNDY_VOLCH1)
 #define MASK_ADDR_BURGUNDY_VOLLINE (MASK_ADDR_BURGUNDY_VOLCH2)
@@ -59,21 +67,22 @@
 
 /* These are all default values for the burgundy */
 #define DEF_BURGUNDY_INPSEL21 (0xAA)
-#define DEF_BURGUNDY_INPSEL3 (0x0A)
+#define DEF_BURGUNDY_INPSEL3_IMAC (0x0A)
+#define DEF_BURGUNDY_INPSEL3_PMAC (0x05)
 
 #define DEF_BURGUNDY_GAINCD (0x33)
 #define DEF_BURGUNDY_GAINLINE (0x44)
 #define DEF_BURGUNDY_GAINMIC (0x44)
 #define DEF_BURGUNDY_GAINMODEM (0x06)
 
-/* Remember: lowest volume here is 0x9b */
+/* Remember: lowest volume here is 0x9B (155) */
 #define DEF_BURGUNDY_VOLCD (0xCCCCCCCC)
 #define DEF_BURGUNDY_VOLLINE (0x00000000)
 #define DEF_BURGUNDY_VOLMIC (0x00000000)
 #define DEF_BURGUNDY_VOLMODEM (0xCCCCCCCC)
 
-#define DEF_BURGUNDY_OUTPUTSELECTS (0x010f010f)
-#define DEF_BURGUNDY_OUTPUTENABLES (0x0A)
+#define DEF_BURGUNDY_OUTPUTSELECTS (0x010F010F)
+#define DEF_BURGUNDY_OUTPUTENABLES (0x0100000A)
 
 /* #define DEF_BURGUNDY_MASTER_VOLUME (0xFFFFFFFF) */ /* too loud */
 #define DEF_BURGUNDY_MASTER_VOLUME (0xDDDDDDDD)
@@ -84,12 +93,22 @@
 #define DEF_BURGUNDY_ATTENLINEOUT (0xCC)
 #define DEF_BURGUNDY_ATTENHP (0xCC)
 
-/* OUTPUTENABLES bits */
+/* MORE_OUTPUTENABLES bits */
 #define BURGUNDY_OUTPUT_LEFT	0x02
 #define BURGUNDY_OUTPUT_RIGHT	0x04
+#define BURGUNDY_LINEOUT_LEFT	0x08
+#define BURGUNDY_LINEOUT_RIGHT	0x10
+#define BURGUNDY_HP_LEFT	0x20
+#define BURGUNDY_HP_RIGHT	0x40
 #define BURGUNDY_OUTPUT_INTERN	0x80
 
-/* volume offset */
+/* Headphone detection bits */
+#define BURGUNDY_HPDETECT_PMAC_BACK	0x04
+#define BURGUNDY_HPDETECT_IMAC_SIDE	0x04
+#define BURGUNDY_HPDETECT_IMAC_UPPER	0x08
+#define BURGUNDY_HPDETECT_IMAC_LOWER	0x01
+
+/* Volume offset */
 #define BURGUNDY_VOLUME_OFFSET	155
 
 #endif /* __BURGUNDY_H */
-- 
cgit v1.2.3-70-g09d2


From 20861fa7b20a40ca045393df634d4d51e61efa58 Mon Sep 17 00:00:00 2001
From: Risto Suominen <Risto.Suominen@gmail.com>
Date: Wed, 16 Apr 2008 19:45:51 +0200
Subject: [ALSA] snd-powermac: style burgundy.c

Coding style corrections for burgundy.c.

Signed-off-by: Risto Suominen <Risto.Suominen@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/ppc/burgundy.c | 32 ++++++++++++++++----------------
 1 file changed, 16 insertions(+), 16 deletions(-)

(limited to 'sound')

diff --git a/sound/ppc/burgundy.c b/sound/ppc/burgundy.c
index f0c12a97fdb..f860d39af36 100644
--- a/sound/ppc/burgundy.c
+++ b/sound/ppc/burgundy.c
@@ -102,7 +102,8 @@ snd_pmac_burgundy_rcw(struct snd_pmac *chip, unsigned addr)
 }
 
 static void
-snd_pmac_burgundy_wcb(struct snd_pmac *chip, unsigned int addr, unsigned int val)
+snd_pmac_burgundy_wcb(struct snd_pmac *chip, unsigned int addr,
+		      unsigned int val)
 {
 	out_le32(&chip->awacs->codec_ctrl, addr + 0x300000 + (val & 0xff));
 	snd_pmac_burgundy_busy_wait(chip);
@@ -126,8 +127,11 @@ snd_pmac_burgundy_rcb(struct snd_pmac *chip, unsigned int addr)
 	return val;
 }
 
+#define BASE2ADDR(base)	((base) << 12)
+#define ADDR2BASE(addr)	((addr) >> 12)
+
 /*
- * Burgundy volume: 0 - 100, stereo
+ * Burgundy volume: 0 - 100, stereo, word reg
  */
 static void
 snd_pmac_burgundy_write_volume(struct snd_pmac *chip, unsigned int address,
@@ -168,13 +172,6 @@ snd_pmac_burgundy_read_volume(struct snd_pmac *chip, unsigned int address,
 		volume[1] = 0;
 }
 
-
-/*
- */
-
-#define BASE2ADDR(base)	((base) << 12)
-#define ADDR2BASE(addr)	((addr) >> 12)
-
 static int snd_pmac_burgundy_info_volume(struct snd_kcontrol *kcontrol,
 					 struct snd_ctl_elem_info *uinfo)
 {
@@ -191,8 +188,8 @@ static int snd_pmac_burgundy_get_volume(struct snd_kcontrol *kcontrol,
 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
 	unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
 	int shift = (kcontrol->private_value >> 8) & 0xff;
-	snd_pmac_burgundy_read_volume(chip, addr, ucontrol->value.integer.value,
-				      shift);
+	snd_pmac_burgundy_read_volume(chip, addr,
+				      ucontrol->value.integer.value, shift);
 	return 0;
 }
 
@@ -204,8 +201,8 @@ static int snd_pmac_burgundy_put_volume(struct snd_kcontrol *kcontrol,
 	int shift = (kcontrol->private_value >> 8) & 0xff;
 	long nvoices[2];
 
-	snd_pmac_burgundy_write_volume(chip, addr, ucontrol->value.integer.value,
-				       shift);
+	snd_pmac_burgundy_write_volume(chip, addr,
+				       ucontrol->value.integer.value, shift);
 	snd_pmac_burgundy_read_volume(chip, addr, nvoices, shift);
 	return (nvoices[0] != ucontrol->value.integer.value[0] ||
 		nvoices[1] != ucontrol->value.integer.value[1]);
@@ -700,7 +697,8 @@ int __init snd_pmac_burgundy_init(struct snd_pmac *chip)
 	chip->master_sw_ctl = snd_ctl_new1(imac
 			? &snd_pmac_burgundy_master_sw_imac
 			: &snd_pmac_burgundy_master_sw_pmac, chip);
-	if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0)
+	err = snd_ctl_add(chip->card, chip->master_sw_ctl);
+	if (err < 0)
 		return err;
 	chip->master_sw_ctl = snd_ctl_new1(imac
 			? &snd_pmac_burgundy_line_sw_imac
@@ -718,10 +716,12 @@ int __init snd_pmac_burgundy_init(struct snd_pmac *chip)
 	chip->speaker_sw_ctl = snd_ctl_new1(imac
 			? &snd_pmac_burgundy_speaker_sw_imac
 			: &snd_pmac_burgundy_speaker_sw_pmac, chip);
-	if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0)
+	err = snd_ctl_add(chip->card, chip->speaker_sw_ctl);
+	if (err < 0)
 		return err;
 #ifdef PMAC_SUPPORT_AUTOMUTE
-	if ((err = snd_pmac_add_automute(chip)) < 0)
+	err = snd_pmac_add_automute(chip);
+	if (err < 0)
 		return err;
 
 	chip->detect_headphone = snd_pmac_burgundy_detect_headphone;
-- 
cgit v1.2.3-70-g09d2


From 73d38b13ffb105ab633bd91969c8d218b2de38d4 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Thu, 17 Apr 2008 12:50:47 +0200
Subject: [ALSA] Fix the race of card instance unregistration

Move the call of device_unregister() for the card instance in
snd_card_disconnect() to avoid the race of sysfs card entry, which
can be typically found on usb-audio reconnection.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/core/init.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

(limited to 'sound')

diff --git a/sound/core/init.c b/sound/core/init.c
index f045f7db3ab..07acac77ea4 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -360,6 +360,12 @@ int snd_card_disconnect(struct snd_card *card)
 		snd_printk(KERN_ERR "not all devices for card %i can be disconnected\n", card->number);
 
 	snd_info_card_disconnect(card);
+#ifndef CONFIG_SYSFS_DEPRECATED
+	if (card->card_dev) {
+		device_unregister(card->card_dev);
+		card->card_dev = NULL;
+	}
+#endif
 	return 0;	
 }
 
@@ -401,10 +407,6 @@ static int snd_card_do_free(struct snd_card *card)
 		snd_printk(KERN_WARNING "unable to free card info\n");
 		/* Not fatal error */
 	}
-#ifndef CONFIG_SYSFS_DEPRECATED
-	if (card->card_dev)
-		device_unregister(card->card_dev);
-#endif
 	kfree(card);
 	return 0;
 }
-- 
cgit v1.2.3-70-g09d2


From f18638dcf0c481eca2430206ebcdc7295aec8623 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Thu, 17 Apr 2008 12:52:02 +0200
Subject: [ALSA] Clean up snd_card_free*()

A little clean up of snd_card_free*().
Removed snd_card_free_prepare() since it's actually almost identical
with snd_card_disconnect().

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/core/init.c | 26 +++++++++-----------------
 1 file changed, 9 insertions(+), 17 deletions(-)

(limited to 'sound')

diff --git a/sound/core/init.c b/sound/core/init.c
index 07acac77ea4..ac057341613 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -311,6 +311,9 @@ int snd_card_disconnect(struct snd_card *card)
 	struct file *file;
 	int err;
 
+	if (!card)
+		return -EINVAL;
+
 	spin_lock(&card->files_lock);
 	if (card->shutdown) {
 		spin_unlock(&card->files_lock);
@@ -322,6 +325,7 @@ int snd_card_disconnect(struct snd_card *card)
 	/* phase 1: disable fops (user space) operations for ALSA API */
 	mutex_lock(&snd_card_mutex);
 	snd_cards[card->number] = NULL;
+	snd_cards_lock &= ~(1 << card->number);
 	mutex_unlock(&snd_card_mutex);
 	
 	/* phase 2: replace file->f_op with special dummy operations */
@@ -365,6 +369,9 @@ int snd_card_disconnect(struct snd_card *card)
 		device_unregister(card->card_dev);
 		card->card_dev = NULL;
 	}
+#endif
+#ifdef CONFIG_PM
+	wake_up(&card->power_sleep);
 #endif
 	return 0;	
 }
@@ -411,25 +418,10 @@ static int snd_card_do_free(struct snd_card *card)
 	return 0;
 }
 
-static int snd_card_free_prepare(struct snd_card *card)
-{
-	if (card == NULL)
-		return -EINVAL;
-	(void) snd_card_disconnect(card);
-	mutex_lock(&snd_card_mutex);
-	snd_cards[card->number] = NULL;
-	snd_cards_lock &= ~(1 << card->number);
-	mutex_unlock(&snd_card_mutex);
-#ifdef CONFIG_PM
-	wake_up(&card->power_sleep);
-#endif
-	return 0;
-}
-
 int snd_card_free_when_closed(struct snd_card *card)
 {
 	int free_now = 0;
-	int ret = snd_card_free_prepare(card);
+	int ret = snd_card_disconnect(card);
 	if (ret)
 		return ret;
 
@@ -449,7 +441,7 @@ EXPORT_SYMBOL(snd_card_free_when_closed);
 
 int snd_card_free(struct snd_card *card)
 {
-	int ret = snd_card_free_prepare(card);
+	int ret = snd_card_disconnect(card);
 	if (ret)
 		return ret;
 
-- 
cgit v1.2.3-70-g09d2


From 9eb70e68f38bbc5996a2193e7b7dc0b5487a08cb Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Thu, 17 Apr 2008 12:53:26 +0200
Subject: [ALSA] usb-audio - Fix race in reconnection

Fix the race at reconnection of the device.
The disconnected usb_chip[] must be cleared before the next probe
call properly.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/usbaudio.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'sound')

diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 7b3bcf1916d..410be4aff1b 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -3424,7 +3424,6 @@ static void snd_usb_audio_create_proc(struct snd_usb_audio *chip)
 
 static int snd_usb_audio_free(struct snd_usb_audio *chip)
 {
-	usb_chip[chip->index] = NULL;
 	kfree(chip);
 	return 0;
 }
@@ -3689,6 +3688,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, void *ptr)
 		list_for_each(p, &chip->mixer_list) {
 			snd_usb_mixer_disconnect(p);
 		}
+		usb_chip[chip->index] = NULL;
 		mutex_unlock(&register_mutex);
 		snd_card_free_when_closed(card);
 	} else {
-- 
cgit v1.2.3-70-g09d2


From e34ba212225a27cdf5f974be22cc539ae7ee7ca5 Mon Sep 17 00:00:00 2001
From: Roel Kluin <12o3l@tiscali.nl>
Date: Thu, 17 Apr 2008 18:58:34 +0200
Subject: [ALSA] SOC: fix tests in cs4270_hw_params()

cs4270_hw_params does several times:

ret = snd_soc_write()
if (ret < 0)
	...

This only works when ret is signed.

Signed-off-by: Roel Kluin <12o3l@tiscali.nl>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/soc/codecs/cs4270.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'sound')

diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index bf2ab72d49b..e73fcfd9f5c 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -372,7 +372,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream,
 	struct snd_soc_device *socdev = rtd->socdev;
 	struct snd_soc_codec *codec = socdev->codec;
 	struct cs4270_private *cs4270 = codec->private_data;
-	unsigned int ret = 0;
+	int ret;
 	unsigned int i;
 	unsigned int rate;
 	unsigned int ratio;
-- 
cgit v1.2.3-70-g09d2


From 0d52cea487c0213d6d7bca9c951210081e7b653b Mon Sep 17 00:00:00 2001
From: Roel Kluin <12o3l@tiscali.nl>
Date: Fri, 18 Apr 2008 12:25:41 +0200
Subject: OSS: dmabuf: fix negative DMAbuf_get_buffer_pointer() check

Since unsigned active_offs < 0 is even true when DMAbuf_get_buffer_pointer()
returns negative

Signed-off-by: Roel Kluin <12o3l@tiscali.nl>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/oss/dmabuf.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'sound')

diff --git a/sound/oss/dmabuf.c b/sound/oss/dmabuf.c
index eaf69971bf9..1e90d769b62 100644
--- a/sound/oss/dmabuf.c
+++ b/sound/oss/dmabuf.c
@@ -795,9 +795,9 @@ static int find_output_space(int dev, char **buf, int *size)
 #ifdef BE_CONSERVATIVE
 	active_offs = dmap->byte_counter + dmap->qhead * dmap->fragment_size;
 #else
-	active_offs = DMAbuf_get_buffer_pointer(dev, dmap, DMODE_OUTPUT);
+	active_offs = max(DMAbuf_get_buffer_pointer(dev, dmap, DMODE_OUTPUT), 0);
 	/* Check for pointer wrapping situation */
-	if (active_offs < 0 || active_offs >= dmap->bytes_in_use)
+	if (active_offs >= dmap->bytes_in_use)
 		active_offs = 0;
 	active_offs += dmap->byte_counter;
 #endif
-- 
cgit v1.2.3-70-g09d2


From 988f0664779674c7c06252a6d549eee8debd5d76 Mon Sep 17 00:00:00 2001
From: Karsten Wiese <fzu@wemgehoertderstaat.de>
Date: Tue, 22 Apr 2008 12:52:15 +0200
Subject: [ALSA] ice1724.c: toggle "chip reset" and "eeprom based setup"
 sequence

Let "chip reset" become first. Increasement of the "chip reset" related timeout
leads to correctly read eeprom's contents here.

Signed-off-by: Karsten Wiese <fzu@wemgehoertderstaat.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/ice1712/ice1724.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index ceac8705626..6b15e1cbfe4 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -2045,12 +2045,16 @@ static int __devinit snd_vt1724_read_eeprom(struct snd_ice1712 *ice,
 
 
 
-static int __devinit snd_vt1724_chip_init(struct snd_ice1712 *ice)
+static void __devinit snd_vt1724_chip_reset(struct snd_ice1712 *ice)
 {
 	outb(VT1724_RESET , ICEREG1724(ice, CONTROL));
-	udelay(200);
+	msleep(10);
 	outb(0, ICEREG1724(ice, CONTROL));
-	udelay(200);
+	msleep(10);
+}
+
+static int __devinit snd_vt1724_chip_init(struct snd_ice1712 *ice)
+{
 	outb(ice->eeprom.data[ICE_EEP2_SYSCONF], ICEREG1724(ice, SYS_CFG));
 	outb(ice->eeprom.data[ICE_EEP2_ACLINK], ICEREG1724(ice, AC97_CFG));
 	outb(ice->eeprom.data[ICE_EEP2_I2S], ICEREG1724(ice, I2S_FEATURES));
@@ -2223,6 +2227,7 @@ static int __devinit snd_vt1724_create(struct snd_card *card,
 
 	ice->irq = pci->irq;
 
+	snd_vt1724_chip_reset(ice);
 	if (snd_vt1724_read_eeprom(ice, modelname) < 0) {
 		snd_vt1724_free(ice);
 		return -EIO;
-- 
cgit v1.2.3-70-g09d2


From 775c199e6af5e4212bfa7ebeadee09563c14694b Mon Sep 17 00:00:00 2001
From: Karsten Wiese <fzu@wemgehoertderstaat.de>
Date: Tue, 22 Apr 2008 12:52:45 +0200
Subject: [ALSA] Don't set gpio mask register in snd_ice1712_gpio_write_bits()

Some calls to snd_ice1712_gpio_write() go wrong, if
snd_ice1712_gpio_write_bits() ran before and changed the gpio mask register.
Read the actual gpio value and combine it with the to be set bits in the cpu
instead.

Signed-off-by: Karsten Wiese <fzu@wemgehoertderstaat.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/ice1712/ice1712.h | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h
index a3bea2247c7..3208901c740 100644
--- a/sound/pci/ice1712/ice1712.h
+++ b/sound/pci/ice1712/ice1712.h
@@ -438,10 +438,14 @@ int snd_ice1712_gpio_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu
 static inline void snd_ice1712_gpio_write_bits(struct snd_ice1712 *ice,
 					       unsigned int mask, unsigned int bits)
 {
+	unsigned val;
+
 	ice->gpio.direction |= mask;
 	snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);
-	snd_ice1712_gpio_set_mask(ice, ~mask);
-	snd_ice1712_gpio_write(ice, mask & bits);
+	val = snd_ice1712_gpio_read(ice);
+	val &= ~mask;
+	val |= mask & bits;
+	snd_ice1712_gpio_write(ice, val);
 }
 
 static inline int snd_ice1712_gpio_read_bits(struct snd_ice1712 *ice,
-- 
cgit v1.2.3-70-g09d2


From 8a87c9cf999542db846c3ab93c1065d446427f37 Mon Sep 17 00:00:00 2001
From: Karsten Wiese <fzu@wemgehoertderstaat.de>
Date: Tue, 22 Apr 2008 12:53:12 +0200
Subject: [ALSA] Audiophile 192: Fix ad converter initialization

Correct some arguments in calls to snd_ice1712_gpio_write_bits() from
ap192_set_rate_val().

Signed-off-by: Karsten Wiese <fzu@wemgehoertderstaat.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/ice1712/revo.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/ice1712/revo.c b/sound/pci/ice1712/revo.c
index dba93d8efbe..4d2631434dc 100644
--- a/sound/pci/ice1712/revo.c
+++ b/sound/pci/ice1712/revo.c
@@ -327,7 +327,7 @@ static void ap192_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate)
 	revo_set_rate_val(ak, rate);
 
 	/* reset CKS */
-	snd_ice1712_gpio_write_bits(ice, 1 << 8, rate > 96000 ? 1 : 0);
+	snd_ice1712_gpio_write_bits(ice, 1 << 8, rate > 96000 ? 1 << 8 : 0);
 	/* reset DFS pins of AK5385A for ADC, too */
 	if (rate > 96000)
 		dfs = 2;
@@ -338,7 +338,7 @@ static void ap192_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate)
 	snd_ice1712_gpio_write_bits(ice, 3 << 9, dfs << 9);
 	/* reset ADC */
 	snd_ice1712_gpio_write_bits(ice, 1 << 11, 0);
-	snd_ice1712_gpio_write_bits(ice, 1 << 11, 1);
+	snd_ice1712_gpio_write_bits(ice, 1 << 11, 1 << 11);
 }
 
 static const struct snd_akm4xxx_dac_channel ap192_dac[] = {
-- 
cgit v1.2.3-70-g09d2


From f000fd80937c0d94c67f9f3e7026f1fbc8ef8873 Mon Sep 17 00:00:00 2001
From: Jeff Garzik <jgarzik@redhat.com>
Date: Tue, 22 Apr 2008 13:50:34 +0200
Subject: [ALSA] Fix synchronize_irq() bugs, redundancies

free_irq() calls synchronize_irq() for you, so there is no need for
drivers to manually do the same thing (again).  Thus, calls where
sync-irq immediately precedes free-irq can be simplified.

However, during this audit several bugs were noticed, where free-irq is
preceded by a "irq >= 0" check... but the sync-irq call is not covered
by the same check.

So, where sync-irq could not be eliminated completely, the missing check
was added.

Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 drivers/media/video/cx88/cx88-alsa.c       | 4 +---
 drivers/media/video/saa7134/saa7134-alsa.c | 4 +---
 sound/pci/ad1889.c                         | 2 --
 sound/pci/ali5451/ali5451.c                | 4 +---
 sound/pci/atiixp.c                         | 2 +-
 sound/pci/atiixp_modem.c                   | 2 +-
 sound/pci/au88x0/au88x0.c                  | 2 --
 sound/pci/azt3328.c                        | 3 ++-
 sound/pci/cmipci.c                         | 2 --
 sound/pci/ens1370.c                        | 3 ++-
 sound/pci/es1938.c                         | 5 +----
 sound/pci/es1968.c                         | 3 ++-
 sound/pci/hda/hda_intel.c                  | 5 +----
 sound/pci/ice1712/ice1712.c                | 5 ++---
 sound/pci/ice1712/ice1724.c                | 4 +---
 sound/pci/intel8x0.c                       | 3 +--
 sound/pci/intel8x0m.c                      | 3 ++-
 sound/pci/maestro3.c                       | 4 +---
 sound/pci/oxygen/oxygen_lib.c              | 4 +---
 sound/pci/sis7019.c                        | 1 -
 sound/pci/via82xx.c                        | 2 +-
 sound/pci/via82xx_modem.c                  | 2 +-
 22 files changed, 23 insertions(+), 46 deletions(-)

(limited to 'sound')

diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c
index 316b106c351..03feb5b49e1 100644
--- a/drivers/media/video/cx88/cx88-alsa.c
+++ b/drivers/media/video/cx88/cx88-alsa.c
@@ -690,10 +690,8 @@ MODULE_DEVICE_TABLE(pci, cx88_audio_pci_tbl);
 static int snd_cx88_free(snd_cx88_card_t *chip)
 {
 
-	if (chip->irq >= 0){
-		synchronize_irq(chip->irq);
+	if (chip->irq >= 0)
 		free_irq(chip->irq, chip);
-	}
 
 	cx88_core_put(chip->core,chip->pci);
 
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c
index 047add8f301..ec6bdb9680a 100644
--- a/drivers/media/video/saa7134/saa7134-alsa.c
+++ b/drivers/media/video/saa7134/saa7134-alsa.c
@@ -954,10 +954,8 @@ static void snd_saa7134_free(struct snd_card * card)
 	if (chip->dev->dmasound.priv_data == NULL)
 		return;
 
-	if (chip->irq >= 0) {
-		synchronize_irq(chip->irq);
+	if (chip->irq >= 0)
 		free_irq(chip->irq, &chip->dev->dmasound);
-	}
 
 	chip->dev->dmasound.priv_data = NULL;
 
diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c
index 1edb6448946..39ec55b57b1 100644
--- a/sound/pci/ad1889.c
+++ b/sound/pci/ad1889.c
@@ -854,8 +854,6 @@ snd_ad1889_free(struct snd_ad1889 *chip)
 
 	spin_unlock_irq(&chip->lock);
 
-	synchronize_irq(chip->irq);
-	
 	if (chip->irq >= 0)
 		free_irq(chip->irq, chip);
 
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index fc04d3da1af..1a0fd65ec28 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -2047,10 +2047,8 @@ static int snd_ali_free(struct snd_ali * codec)
 {
 	if (codec->hw_initialized)
 		snd_ali_disable_address_interrupt(codec);
-	if (codec->irq >= 0) {
-		synchronize_irq(codec->irq);
+	if (codec->irq >= 0)
 		free_irq(codec->irq, codec);
-	}
 	if (codec->port)
 		pci_release_regions(codec->pci);
 	pci_disable_device(codec->pci);
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index 4594186b83e..457228fb22a 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -1553,7 +1553,7 @@ static int snd_atiixp_free(struct atiixp *chip)
 	if (chip->irq < 0)
 		goto __hw_end;
 	snd_atiixp_chip_stop(chip);
-	synchronize_irq(chip->irq);
+
       __hw_end:
 	if (chip->irq >= 0)
 		free_irq(chip->irq, chip);
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
index a67a869180d..d457a32a793 100644
--- a/sound/pci/atiixp_modem.c
+++ b/sound/pci/atiixp_modem.c
@@ -1197,7 +1197,7 @@ static int snd_atiixp_free(struct atiixp_modem *chip)
 	if (chip->irq < 0)
 		goto __hw_end;
 	snd_atiixp_chip_stop(chip);
-	synchronize_irq(chip->irq);
+
       __hw_end:
 	if (chip->irq >= 0)
 		free_irq(chip->irq, chip);
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c
index 26819e2f576..68368e49007 100644
--- a/sound/pci/au88x0/au88x0.c
+++ b/sound/pci/au88x0/au88x0.c
@@ -126,7 +126,6 @@ static int snd_vortex_dev_free(struct snd_device *device)
 	vortex_gameport_unregister(vortex);
 	vortex_core_shutdown(vortex);
 	// Take down PCI interface.
-	synchronize_irq(vortex->irq);
 	free_irq(vortex->irq, vortex);
 	iounmap(vortex->mmio);
 	pci_release_regions(vortex->pci_dev);
@@ -220,7 +219,6 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip)
 	return 0;
 
       alloc_out:
-	synchronize_irq(chip->irq);
 	free_irq(chip->irq, chip);
       irq_out:
 	vortex_core_shutdown(chip);
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index be87d3113ee..5f63af6b88a 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -1514,7 +1514,8 @@ snd_azf3328_free(struct snd_azf3328 *chip)
 	/* well, at least we know how to disable the timer IRQ */
 	snd_azf3328_codec_outb(chip, IDX_IO_TIMER_VALUE + 3, 0x00);
 
-        synchronize_irq(chip->irq);
+	if (chip->irq >= 0)
+        	synchronize_irq(chip->irq);
 __end_hw:
 	snd_azf3328_free_joystick(chip);
         if (chip->irq >= 0)
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
index 4074584a7d9..9971b5b7735 100644
--- a/sound/pci/cmipci.c
+++ b/sound/pci/cmipci.c
@@ -2933,8 +2933,6 @@ static int snd_cmipci_free(struct cmipci *cm)
 		/* reset mixer */
 		snd_cmipci_mixer_write(cm, 0, 0);
 
-		synchronize_irq(cm->irq);
-
 		free_irq(cm->irq, cm);
 	}
 
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index 52fae4a7cfd..fbf1124f7c7 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -1910,7 +1910,8 @@ static int snd_ensoniq_free(struct ensoniq *ensoniq)
 	outl(0, ES_REG(ensoniq, CONTROL));	/* switch everything off */
 	outl(0, ES_REG(ensoniq, SERIAL));	/* clear serial interface */
 #endif
-	synchronize_irq(ensoniq->irq);
+	if (ensoniq->irq >= 0)
+		synchronize_irq(ensoniq->irq);
 	pci_set_power_state(ensoniq->pci, 3);
       __hw_end:
 #ifdef CHIP1370
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
index 1a314fa99c4..84fac1fbf10 100644
--- a/sound/pci/es1938.c
+++ b/sound/pci/es1938.c
@@ -1488,7 +1488,6 @@ static int es1938_suspend(struct pci_dev *pci, pm_message_t state)
 
 	outb(0x00, SLIO_REG(chip, IRQCONTROL)); /* disable irqs */
 	if (chip->irq >= 0) {
-		synchronize_irq(chip->irq);
 		free_irq(chip->irq, chip);
 		chip->irq = -1;
 	}
@@ -1578,10 +1577,8 @@ static int snd_es1938_free(struct es1938 *chip)
 
 	snd_es1938_free_gameport(chip);
 
-	if (chip->irq >= 0) {
-		synchronize_irq(chip->irq);
+	if (chip->irq >= 0)
 		free_irq(chip->irq, chip);
-	}
 	pci_release_regions(chip->pci);
 	pci_disable_device(chip->pci);
 	kfree(chip);
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index 13837989606..1bf298d214b 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -2475,7 +2475,8 @@ static inline void snd_es1968_free_gameport(struct es1968 *chip) { }
 static int snd_es1968_free(struct es1968 *chip)
 {
 	if (chip->io_port) {
-		synchronize_irq(chip->irq);
+		if (chip->irq >= 0)
+			synchronize_irq(chip->irq);
 		outw(1, chip->io_port + 0x04); /* clear WP interrupts */
 		outw(0, chip->io_port + ESM_PORT_HOST_IRQ); /* disable IRQ */
 	}
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index bc3867e1945..b3a618eb42c 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -1682,7 +1682,6 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state)
 		snd_hda_suspend(chip->bus, state);
 	azx_stop_chip(chip);
 	if (chip->irq >= 0) {
-		synchronize_irq(chip->irq);
 		free_irq(chip->irq, chip);
 		chip->irq = -1;
 	}
@@ -1738,10 +1737,8 @@ static int azx_free(struct azx *chip)
 		azx_stop_chip(chip);
 	}
 
-	if (chip->irq >= 0) {
-		synchronize_irq(chip->irq);
+	if (chip->irq >= 0)
 		free_irq(chip->irq, (void*)chip);
-	}
 	if (chip->msi)
 		pci_disable_msi(chip->pci);
 	if (chip->remap_addr)
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
index 38e93ca12e2..29d449d73c9 100644
--- a/sound/pci/ice1712/ice1712.c
+++ b/sound/pci/ice1712/ice1712.c
@@ -2490,10 +2490,9 @@ static int snd_ice1712_free(struct snd_ice1712 *ice)
 	outb(0xff, ICEREG(ice, IRQMASK));
 	/* --- */
       __hw_end:
-	if (ice->irq >= 0) {
-		synchronize_irq(ice->irq);
+	if (ice->irq >= 0)
 		free_irq(ice->irq, ice);
-	}
+
 	if (ice->port)
 		pci_release_regions(ice->pci);
 	snd_ice1712_akm4xxx_free(ice);
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index 6b15e1cbfe4..13ea94f317c 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -2153,10 +2153,8 @@ static int snd_vt1724_free(struct snd_ice1712 *ice)
 	outb(0xff, ICEREG1724(ice, IRQMASK));
 	/* --- */
       __hw_end:
-	if (ice->irq >= 0) {
-		synchronize_irq(ice->irq);
+	if (ice->irq >= 0)
 		free_irq(ice->irq, ice);
-	}
 	pci_release_regions(ice->pci);
 	snd_ice1712_akm4xxx_free(ice);
 	pci_disable_device(ice->pci);
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index 47485afcab5..048d99e25ab 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -2468,7 +2468,7 @@ static int snd_intel8x0_free(struct intel8x0 *chip)
 		pci_write_config_dword(chip->pci, 0x4c, val);
 	}
 	/* --- */
-	synchronize_irq(chip->irq);
+
       __hw_end:
 	if (chip->irq >= 0)
 		free_irq(chip->irq, chip);
@@ -2517,7 +2517,6 @@ static int intel8x0_suspend(struct pci_dev *pci, pm_message_t state)
 		chip->sdm_saved = igetbyte(chip, ICHREG(SDM));
 
 	if (chip->irq >= 0) {
-		synchronize_irq(chip->irq);
 		free_irq(chip->irq, chip);
 		chip->irq = -1;
 	}
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
index cadda8d6b70..15db810d589 100644
--- a/sound/pci/intel8x0m.c
+++ b/sound/pci/intel8x0m.c
@@ -986,7 +986,8 @@ static int snd_intel8x0_free(struct intel8x0m *chip)
 	for (i = 0; i < chip->bdbars_count; i++)
 		iputbyte(chip, ICH_REG_OFF_CR + chip->ichd[i].reg_offset, ICH_RESETREGS);
 	/* --- */
-	synchronize_irq(chip->irq);
+	if (chip->irq >= 0)
+		synchronize_irq(chip->irq);
       __hw_end:
 	if (chip->bdbars.area)
 		snd_dma_free_pages(&chip->bdbars);
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index a753dae65ab..a536c59fbea 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -2542,10 +2542,8 @@ static int snd_m3_free(struct snd_m3 *chip)
 	vfree(chip->suspend_mem);
 #endif
 
-	if (chip->irq >= 0) {
-		synchronize_irq(chip->irq);
+	if (chip->irq >= 0)
 		free_irq(chip->irq, chip);
-	}
 
 	if (chip->iobase)
 		pci_release_regions(chip->pci);
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c
index f84f6a128ee..897697d4350 100644
--- a/sound/pci/oxygen/oxygen_lib.c
+++ b/sound/pci/oxygen/oxygen_lib.c
@@ -410,10 +410,8 @@ static void oxygen_card_free(struct snd_card *card)
 	oxygen_write16(chip, OXYGEN_DMA_STATUS, 0);
 	oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0);
 	spin_unlock_irq(&chip->reg_lock);
-	if (chip->irq >= 0) {
+	if (chip->irq >= 0)
 		free_irq(chip->irq, chip);
-		synchronize_irq(chip->irq);
-	}
 	flush_scheduled_work();
 	chip->model->cleanup(chip);
 	mutex_destroy(&chip->mutex);
diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c
index 742f1180c39..df2007e3be7 100644
--- a/sound/pci/sis7019.c
+++ b/sound/pci/sis7019.c
@@ -1194,7 +1194,6 @@ static int sis_suspend(struct pci_dev *pci, pm_message_t state)
 	/* snd_pcm_suspend_all() stopped all channels, so we're quiescent.
 	 */
 	if (sis->irq >= 0) {
-		synchronize_irq(sis->irq);
 		free_irq(sis->irq, sis);
 		sis->irq = -1;
 	}
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index a756be661f9..b585cc3e4c4 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -2236,7 +2236,7 @@ static int snd_via82xx_free(struct via82xx *chip)
 	/* disable interrupts */
 	for (i = 0; i < chip->num_devs; i++)
 		snd_via82xx_channel_reset(chip, &chip->devs[i]);
-	synchronize_irq(chip->irq);
+
 	if (chip->irq >= 0)
 		free_irq(chip->irq, chip);
  __end_hw:
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c
index f5df1c79bee..31f64ee3988 100644
--- a/sound/pci/via82xx_modem.c
+++ b/sound/pci/via82xx_modem.c
@@ -1075,7 +1075,7 @@ static int snd_via82xx_free(struct via82xx_modem *chip)
 	/* disable interrupts */
 	for (i = 0; i < chip->num_devs; i++)
 		snd_via82xx_channel_reset(chip, &chip->devs[i]);
-	synchronize_irq(chip->irq);
+
       __end_hw:
 	if (chip->irq >= 0)
 		free_irq(chip->irq, chip);
-- 
cgit v1.2.3-70-g09d2


From d80fd0935e2c177ae58d85cb736684ff6c00314d Mon Sep 17 00:00:00 2001
From: Peter Lienig <lienig@rheinmetall-de.com>
Date: Tue, 22 Apr 2008 17:05:07 +0200
Subject: [ALSA] ice1712 - Add Terrasoniq TS88 support

Added the support of Terrasonq TS88.

Signed-off-by: Peter Lienig <lienig@rheinmetall-de.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/ice1712/ews.c | 15 +++++++++++++++
 sound/pci/ice1712/ews.h |  4 +++-
 2 files changed, 18 insertions(+), 1 deletion(-)

(limited to 'sound')

diff --git a/sound/pci/ice1712/ews.c b/sound/pci/ice1712/ews.c
index 064760d2a02..013fc4f0482 100644
--- a/sound/pci/ice1712/ews.c
+++ b/sound/pci/ice1712/ews.c
@@ -238,6 +238,7 @@ static void snd_ice1712_ews_cs8404_spdif_write(struct snd_ice1712 *ice, unsigned
 	case ICE1712_SUBDEVICE_EWS88MT:
 	case ICE1712_SUBDEVICE_EWS88MT_NEW:
 	case ICE1712_SUBDEVICE_PHASE88:
+	case ICE1712_SUBDEVICE_TS88:
 		if (snd_i2c_sendbytes(spec->i2cdevs[EWS_I2C_CS8404], &bits, 1)
 		    != 1)
 			goto _error;
@@ -433,6 +434,7 @@ static int __devinit snd_ice1712_ews_init(struct snd_ice1712 *ice)
 	case ICE1712_SUBDEVICE_EWS88MT:
 	case ICE1712_SUBDEVICE_EWS88MT_NEW:
 	case ICE1712_SUBDEVICE_PHASE88:
+	case ICE1712_SUBDEVICE_TS88:
 		ice->num_total_dacs = 8;
 		ice->num_total_adcs = 8;
 		break;
@@ -475,6 +477,8 @@ static int __devinit snd_ice1712_ews_init(struct snd_ice1712 *ice)
 	case ICE1712_SUBDEVICE_EWS88MT:
 	case ICE1712_SUBDEVICE_EWS88MT_NEW:
 	case ICE1712_SUBDEVICE_PHASE88:
+	case ICE1712_SUBDEVICE_TS88:
+
 		err = snd_i2c_device_create(ice->i2c, "CS8404",
 					    ICE1712_EWS88MT_CS8404_ADDR,
 					    &spec->i2cdevs[EWS_I2C_CS8404]);
@@ -518,6 +522,7 @@ static int __devinit snd_ice1712_ews_init(struct snd_ice1712 *ice)
 	case ICE1712_SUBDEVICE_EWS88MT:
 	case ICE1712_SUBDEVICE_EWS88MT_NEW:
 	case ICE1712_SUBDEVICE_PHASE88:
+	case ICE1712_SUBDEVICE_TS88:
 	case ICE1712_SUBDEVICE_EWS88D:
 		/* set up CS8404 */
 		ice->spdif.ops.open = ews88_open_spdif;
@@ -547,6 +552,7 @@ static int __devinit snd_ice1712_ews_init(struct snd_ice1712 *ice)
 	case ICE1712_SUBDEVICE_EWS88MT:
 	case ICE1712_SUBDEVICE_EWS88MT_NEW:
 	case ICE1712_SUBDEVICE_PHASE88:
+	case ICE1712_SUBDEVICE_TS88:
 		err = snd_ice1712_akm4xxx_init(ak, &akm_ews88mt, &akm_ews88mt_priv, ice);
 		break;
 	case ICE1712_SUBDEVICE_EWX2496:
@@ -973,6 +979,7 @@ static int __devinit snd_ice1712_ews_add_controls(struct snd_ice1712 *ice)
 	case ICE1712_SUBDEVICE_EWS88MT:
 	case ICE1712_SUBDEVICE_EWS88MT_NEW:
 	case ICE1712_SUBDEVICE_PHASE88:
+	case ICE1712_SUBDEVICE_TS88:
 	case ICE1712_SUBDEVICE_DMX6FIRE:
 		err = snd_ice1712_akm4xxx_build_controls(ice);
 		if (err < 0)
@@ -992,6 +999,7 @@ static int __devinit snd_ice1712_ews_add_controls(struct snd_ice1712 *ice)
 	case ICE1712_SUBDEVICE_EWS88MT:
 	case ICE1712_SUBDEVICE_EWS88MT_NEW:
 	case ICE1712_SUBDEVICE_PHASE88:
+	case ICE1712_SUBDEVICE_TS88:
 		err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_ews88mt_input_sense, ice));
 		if (err < 0)
 			return err;
@@ -1048,6 +1056,13 @@ struct snd_ice1712_card_info snd_ice1712_ews_cards[] __devinitdata = {
 		.chip_init = snd_ice1712_ews_init,
 		.build_controls = snd_ice1712_ews_add_controls,
 	},
+	{
+		.subvendor = ICE1712_SUBDEVICE_TS88,
+		.name = "terrasoniq TS88",
+		.model = "phase88",
+		.chip_init = snd_ice1712_ews_init,
+		.build_controls = snd_ice1712_ews_add_controls,
+	},
 	{
 		.subvendor = ICE1712_SUBDEVICE_EWS88D,
 		.name = "TerraTec EWS88D",
diff --git a/sound/pci/ice1712/ews.h b/sound/pci/ice1712/ews.h
index e4ed1b475b0..1c443718af0 100644
--- a/sound/pci/ice1712/ews.h
+++ b/sound/pci/ice1712/ews.h
@@ -30,7 +30,8 @@
 		"{TerraTec,EWS 88MT},"\
 		"{TerraTec,EWS 88D},"\
 		"{TerraTec,DMX 6Fire},"\
-		"{TerraTec,Phase 88},"
+		"{TerraTec,Phase 88}," \
+		"{terrasoniq,TS 88},"
 
 #define ICE1712_SUBDEVICE_EWX2496	0x3b153011
 #define ICE1712_SUBDEVICE_EWS88MT	0x3b151511
@@ -38,6 +39,7 @@
 #define ICE1712_SUBDEVICE_EWS88D	0x3b152b11
 #define ICE1712_SUBDEVICE_DMX6FIRE	0x3b153811
 #define ICE1712_SUBDEVICE_PHASE88	0x3b155111
+#define ICE1712_SUBDEVICE_TS88   	0x3b157c11
 
 /* entry point */
 extern struct snd_ice1712_card_info snd_ice1712_ews_cards[];
-- 
cgit v1.2.3-70-g09d2


From 7a22323b231fe5d47804f98f31a70eb34c6104a9 Mon Sep 17 00:00:00 2001
From: Mark Brown <broonie@opensource.wolfsonmicro.com>
Date: Tue, 22 Apr 2008 17:08:52 +0200
Subject: [ALSA] soc - Support PXA3xx AC97

The PXA3xx does not support the use of interrupts during reset and access
to the GPIO status requires similar handling to that for PXA27x.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/soc/pxa/pxa2xx-ac97.c | 29 +++++++++++++++++++++++++++--
 1 file changed, 27 insertions(+), 2 deletions(-)

(limited to 'sound')

diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
index 1092d58e852..97ec2d90547 100644
--- a/sound/soc/pxa/pxa2xx-ac97.c
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -61,7 +61,7 @@ static unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97,
 	mutex_lock(&car_mutex);
 
 	/* set up primary or secondary codec/modem space */
-#ifdef CONFIG_PXA27x
+#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
 	reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
 #else
 	if (reg == AC97_GPIO_STATUS)
@@ -111,7 +111,7 @@ static void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
 	mutex_lock(&car_mutex);
 
 	/* set up primary or secondary codec/modem space */
-#ifdef CONFIG_PXA27x
+#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
 	reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
 #else
 	if (reg == AC97_GPIO_STATUS)
@@ -134,6 +134,9 @@ static void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
 
 static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97)
 {
+#ifdef CONFIG_PXA3xx
+	int timeout = 100;
+#endif
 	gsr_bits = 0;
 
 #ifdef CONFIG_PXA27x
@@ -144,6 +147,11 @@ static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97)
 	GCR |= GCR_WARM_RST;
 	pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
 	udelay(500);
+#elif defined(CONFIG_PXA3xx)
+	/* Can't use interrupts */
+	GCR |= GCR_WARM_RST;
+	while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--)
+		mdelay(1);
 #else
 	GCR |= GCR_WARM_RST | GCR_PRIRDY_IEN | GCR_SECRDY_IEN;
 	wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1);
@@ -159,6 +167,16 @@ static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97)
 
 static void pxa2xx_ac97_cold_reset(struct snd_ac97 *ac97)
 {
+#ifdef CONFIG_PXA3xx
+	int timeout = 1000;
+
+	/* Hold CLKBPB for 100us */
+	GCR = 0;
+	GCR = GCR_CLKBPB;
+	udelay(100);
+	GCR = 0;
+#endif
+
 	GCR &=  GCR_COLD_RST;  /* clear everything but nCRST */
 	GCR &= ~GCR_COLD_RST;  /* then assert nCRST */
 
@@ -170,6 +188,13 @@ static void pxa2xx_ac97_cold_reset(struct snd_ac97 *ac97)
 	clk_disable(ac97conf_clk);
 	GCR = GCR_COLD_RST;
 	udelay(50);
+#elif defined(CONFIG_PXA3xx)
+	/* Can't use interrupts on PXA3xx */
+	GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
+
+	GCR = GCR_WARM_RST | GCR_COLD_RST;
+	while (!(GSR & (GSR_PCR | GSR_SCR)) && timeout--)
+		mdelay(10);
 #else
 	GCR = GCR_COLD_RST;
 	GCR |= GCR_CDONE_IE|GCR_SDONE_IE;
-- 
cgit v1.2.3-70-g09d2


From 815c1be320fd51e5981c007f737aca410707baf8 Mon Sep 17 00:00:00 2001
From: Mark Brown <broonie@opensource.wolfsonmicro.com>
Date: Tue, 22 Apr 2008 17:09:49 +0200
Subject: [ALSA] pxa2xx-ac97: Support PXA3xx AC97

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/arm/pxa2xx-ac97.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

(limited to 'sound')

diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c
index 71fbf8d7ee8..5b3274b465e 100644
--- a/sound/arm/pxa2xx-ac97.c
+++ b/sound/arm/pxa2xx-ac97.c
@@ -112,6 +112,16 @@ static void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigne
 static void pxa2xx_ac97_reset(struct snd_ac97 *ac97)
 {
 	/* First, try cold reset */
+#ifdef CONFIG_PXA3xx
+	int timeout;
+
+	/* Hold CLKBPB for 100us */
+	GCR = 0;
+	GCR = GCR_CLKBPB;
+	udelay(100);
+	GCR = 0;
+#endif
+
 	GCR &=  GCR_COLD_RST;  /* clear everything but nCRST */
 	GCR &= ~GCR_COLD_RST;  /* then assert nCRST */
 
@@ -123,6 +133,14 @@ static void pxa2xx_ac97_reset(struct snd_ac97 *ac97)
 	clk_disable(ac97conf_clk);
 	GCR = GCR_COLD_RST;
 	udelay(50);
+#elif defined(CONFIG_PXA3xx)
+	timeout = 1000;
+	/* Can't use interrupts on PXA3xx */
+	GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
+
+	GCR = GCR_WARM_RST | GCR_COLD_RST;
+	while (!(GSR & (GSR_PCR | GSR_SCR)) && timeout--)
+		mdelay(10);
 #else
 	GCR = GCR_COLD_RST;
 	GCR |= GCR_CDONE_IE|GCR_SDONE_IE;
@@ -143,6 +161,12 @@ static void pxa2xx_ac97_reset(struct snd_ac97 *ac97)
 		GCR |= GCR_WARM_RST;
 		pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
 		udelay(500);
+#elif defined(CONFIG_PXA3xx)
+		timeout = 100;
+		/* Can't use interrupts */
+		GCR |= GCR_WARM_RST;
+		while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--)
+			mdelay(1);
 #else
 		GCR |= GCR_WARM_RST|GCR_PRIRDY_IEN|GCR_SECRDY_IEN;
 		wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1);
-- 
cgit v1.2.3-70-g09d2


From 6b9a9b329640b7e8143df7b2782884ea758650f7 Mon Sep 17 00:00:00 2001
From: Tim Niemeyer <reddog@mastersword.de>
Date: Tue, 22 Apr 2008 17:10:23 +0200
Subject: [ALSA] soc - neo1973_wm8753 - Fix module unload

Signed-off-by: Tim Niemeyer <reddog@mastersword.de>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/soc/s3c24xx/neo1973_wm8753.c | 1 +
 1 file changed, 1 insertion(+)

(limited to 'sound')

diff --git a/sound/soc/s3c24xx/neo1973_wm8753.c b/sound/soc/s3c24xx/neo1973_wm8753.c
index 6ee115ceb01..962cc20b1af 100644
--- a/sound/soc/s3c24xx/neo1973_wm8753.c
+++ b/sound/soc/s3c24xx/neo1973_wm8753.c
@@ -659,6 +659,7 @@ static int __init neo1973_init(void)
 
 static void __exit neo1973_exit(void)
 {
+	i2c_del_driver(&lm4857_i2c_driver);
 	platform_device_unregister(neo1973_snd_device);
 }
 
-- 
cgit v1.2.3-70-g09d2


From ebf029da38829ede6b53ac8a5ad45b149064ea16 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Tue, 22 Apr 2008 17:28:11 +0200
Subject: [ALSA] Fix possible races at free_irq in PCI drivers

The irq handler of PCI drivers must be released before releasing other
resources since the handler for a shared irq can be still called and
may access the freed resource again.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/ca0106/ca0106_main.c   |  5 ++---
 sound/pci/cs46xx/cs46xx_lib.c    |  6 +++---
 sound/pci/echoaudio/echoaudio.c  |  7 ++++---
 sound/pci/emu10k1/emu10k1_main.c | 15 ++++++++-------
 sound/pci/emu10k1/emu10k1x.c     |  8 ++++----
 sound/pci/intel8x0m.c            |  8 ++------
 sound/pci/korg1212/korg1212.c    |  1 -
 sound/pci/nm256/nm256.c          |  4 +---
 sound/pci/trident/trident_main.c |  4 ++--
 9 files changed, 26 insertions(+), 32 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index 3818249fcc8..ecbe79b67e4 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -1114,6 +1114,8 @@ static int snd_ca0106_free(struct snd_ca0106 *chip)
 		 * So we can fix: snd-malloc: Memory leak?  pages not freed = 8
 		 */
 	}
+	if (chip->irq >= 0)
+		free_irq(chip->irq, chip);
 	// release the data
 #if 1
 	if (chip->buffer.area)
@@ -1123,9 +1125,6 @@ static int snd_ca0106_free(struct snd_ca0106 *chip)
 	// release the i/o port
 	release_and_free_resource(chip->res_port);
 
-	// release the irq
-	if (chip->irq >= 0)
-		free_irq(chip->irq, chip);
 	pci_disable_device(chip->pci);
 	kfree(chip);
 	return 0;
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
index 87ddffcd9d8..e214e567dec 100644
--- a/sound/pci/cs46xx/cs46xx_lib.c
+++ b/sound/pci/cs46xx/cs46xx_lib.c
@@ -2772,6 +2772,9 @@ static int snd_cs46xx_free(struct snd_cs46xx *chip)
 	if (chip->irq >= 0)
 		free_irq(chip->irq, chip);
 
+	if (chip->active_ctrl)
+		chip->active_ctrl(chip, -chip->amplifier);
+
 	for (idx = 0; idx < 5; idx++) {
 		struct snd_cs46xx_region *region = &chip->region.idx[idx];
 		if (region->remap_addr)
@@ -2779,9 +2782,6 @@ static int snd_cs46xx_free(struct snd_cs46xx *chip)
 		release_and_free_resource(region->resource);
 	}
 
-	if (chip->active_ctrl)
-		chip->active_ctrl(chip, -chip->amplifier);
-	
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
 	if (chip->dsp_spos_instance) {
 		cs46xx_dsp_spos_destroy(chip);
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c
index 90ec090792b..e16dc92e82f 100644
--- a/sound/pci/echoaudio/echoaudio.c
+++ b/sound/pci/echoaudio/echoaudio.c
@@ -1852,15 +1852,16 @@ static irqreturn_t snd_echo_interrupt(int irq, void *dev_id)
 static int snd_echo_free(struct echoaudio *chip)
 {
 	DE_INIT(("Stop DSP...\n"));
-	if (chip->comm_page) {
+	if (chip->comm_page)
 		rest_in_peace(chip);
-		snd_dma_free_pages(&chip->commpage_dma_buf);
-	}
 	DE_INIT(("Stopped.\n"));
 
 	if (chip->irq >= 0)
 		free_irq(chip->irq, chip);
 
+	if (chip->comm_page)
+		snd_dma_free_pages(&chip->commpage_dma_buf);
+
 	if (chip->dsp_registers)
 		iounmap(chip->dsp_registers);
 
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index 9a9b977d3cf..abde5b90188 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -1249,11 +1249,6 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu)
 	if (emu->port) {	/* avoid access to already used hardware */
 	       	snd_emu10k1_fx8010_tram_setup(emu, 0);
 		snd_emu10k1_done(emu);
-		/* remove reserved page */
-		if (emu->reserved_page) {
-			snd_emu10k1_synth_free(emu, (struct snd_util_memblk *)emu->reserved_page);
-			emu->reserved_page = NULL;
-		}
 		snd_emu10k1_free_efx(emu);
        	}
 	if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1010) {
@@ -1262,6 +1257,14 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu)
 	}
 	if (emu->emu1010.firmware_thread)
 		kthread_stop(emu->emu1010.firmware_thread);
+	if (emu->irq >= 0)
+		free_irq(emu->irq, emu);
+	/* remove reserved page */
+	if (emu->reserved_page) {
+		snd_emu10k1_synth_free(emu,
+			(struct snd_util_memblk *)emu->reserved_page);
+		emu->reserved_page = NULL;
+	}
 	if (emu->memhdr)
 		snd_util_memhdr_free(emu->memhdr);
 	if (emu->silent_page.area)
@@ -1273,8 +1276,6 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu)
 #ifdef CONFIG_PM
 	free_pm_buffer(emu);
 #endif
-	if (emu->irq >= 0)
-		free_irq(emu->irq, emu);
 	if (emu->port)
 		pci_release_regions(emu->pci);
 	if (emu->card_capabilities->ca0151_chip) /* P16V */	
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
index 341f34e19f3..491a4a50f86 100644
--- a/sound/pci/emu10k1/emu10k1x.c
+++ b/sound/pci/emu10k1/emu10k1x.c
@@ -754,13 +754,13 @@ static int snd_emu10k1x_free(struct emu10k1x *chip)
 	// disable audio
 	outl(HCFG_LOCKSOUNDCACHE, chip->port + HCFG);
 
-	// release the i/o port
-	release_and_free_resource(chip->res_port);
-
-	// release the irq
+	/* release the irq */
 	if (chip->irq >= 0)
 		free_irq(chip->irq, chip);
 
+	// release the i/o port
+	release_and_free_resource(chip->res_port);
+
 	// release the DMA
 	if (chip->dma_buffer.area) {
 		snd_dma_free_pages(&chip->dma_buffer);
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
index 15db810d589..faf674e671a 100644
--- a/sound/pci/intel8x0m.c
+++ b/sound/pci/intel8x0m.c
@@ -985,18 +985,15 @@ static int snd_intel8x0_free(struct intel8x0m *chip)
 	/* reset channels */
 	for (i = 0; i < chip->bdbars_count; i++)
 		iputbyte(chip, ICH_REG_OFF_CR + chip->ichd[i].reg_offset, ICH_RESETREGS);
-	/* --- */
+ __hw_end:
 	if (chip->irq >= 0)
-		synchronize_irq(chip->irq);
-      __hw_end:
+		free_irq(chip->irq, chip);
 	if (chip->bdbars.area)
 		snd_dma_free_pages(&chip->bdbars);
 	if (chip->addr)
 		pci_iounmap(chip->pci, chip->addr);
 	if (chip->bmaddr)
 		pci_iounmap(chip->pci, chip->bmaddr);
-	if (chip->irq >= 0)
-		free_irq(chip->irq, chip);
 	pci_release_regions(chip->pci);
 	pci_disable_device(chip->pci);
 	kfree(chip);
@@ -1018,7 +1015,6 @@ static int intel8x0m_suspend(struct pci_dev *pci, pm_message_t state)
 		snd_pcm_suspend_all(chip->pcm[i]);
 	snd_ac97_suspend(chip->ac97);
 	if (chip->irq >= 0) {
-		synchronize_irq(chip->irq);
 		free_irq(chip->irq, chip);
 		chip->irq = -1;
 	}
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
index 10c713d9ac4..f4c85b52bde 100644
--- a/sound/pci/korg1212/korg1212.c
+++ b/sound/pci/korg1212/korg1212.c
@@ -2102,7 +2102,6 @@ snd_korg1212_free(struct snd_korg1212 *korg1212)
         snd_korg1212_TurnOffIdleMonitor(korg1212);
 
         if (korg1212->irq >= 0) {
-                synchronize_irq(korg1212->irq);                
                 snd_korg1212_DisableCardInterrupts(korg1212);
                 free_irq(korg1212->irq, korg1212);
                 korg1212->irq = -1;
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
index 7ac654e381d..7efb838d18a 100644
--- a/sound/pci/nm256/nm256.c
+++ b/sound/pci/nm256/nm256.c
@@ -1439,7 +1439,7 @@ static int snd_nm256_free(struct nm256 *chip)
 		snd_nm256_capture_stop(chip);
 
 	if (chip->irq >= 0)
-		synchronize_irq(chip->irq);
+		free_irq(chip->irq, chip);
 
 	if (chip->cport)
 		iounmap(chip->cport);
@@ -1447,8 +1447,6 @@ static int snd_nm256_free(struct nm256 *chip)
 		iounmap(chip->buffer);
 	release_and_free_resource(chip->res_cport);
 	release_and_free_resource(chip->res_buffer);
-	if (chip->irq >= 0)
-		free_irq(chip->irq, chip);
 
 	pci_disable_device(chip->pci);
 	kfree(chip->ac97_regs);
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
index 71138ff9b31..bbcee2c09ae 100644
--- a/sound/pci/trident/trident_main.c
+++ b/sound/pci/trident/trident_main.c
@@ -3676,6 +3676,8 @@ static int snd_trident_free(struct snd_trident *trident)
 	else if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
 		outl(0, TRID_REG(trident, SI_SERIAL_INTF_CTRL));
 	}
+	if (trident->irq >= 0)
+		free_irq(trident->irq, trident);
 	if (trident->tlb.buffer.area) {
 		outl(0, TRID_REG(trident, NX_TLBC));
 		if (trident->tlb.memhdr)
@@ -3685,8 +3687,6 @@ static int snd_trident_free(struct snd_trident *trident)
 		vfree(trident->tlb.shadow_entries);
 		snd_dma_free_pages(&trident->tlb.buffer);
 	}
-	if (trident->irq >= 0)
-		free_irq(trident->irq, trident);
 	pci_release_regions(trident->pci);
 	pci_disable_device(trident->pci);
 	kfree(trident);
-- 
cgit v1.2.3-70-g09d2


From 409203074e9f3c423cdc7c38f984ce24ae261556 Mon Sep 17 00:00:00 2001
From: Tim Niemeyer <reddog@mastersword.de>
Date: Tue, 22 Apr 2008 18:26:59 +0200
Subject: [ALSA] soc - s3c24xx - Improve diagnostic output

Add some debug messages for suspend/resume and to add a clear prefix to
s3c24xx-i2s and s3c24xx-pcm.

Signed-off-by: Tim Niemeyer <reddog@mastersword.de>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/soc/s3c24xx/s3c24xx-i2s.c | 5 ++++-
 sound/soc/s3c24xx/s3c24xx-pcm.c | 2 +-
 2 files changed, 5 insertions(+), 2 deletions(-)

(limited to 'sound')

diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.c b/sound/soc/s3c24xx/s3c24xx-i2s.c
index 301002cd3fc..cb68b9ced60 100644
--- a/sound/soc/s3c24xx/s3c24xx-i2s.c
+++ b/sound/soc/s3c24xx/s3c24xx-i2s.c
@@ -46,7 +46,7 @@
 
 #define S3C24XX_I2S_DEBUG 0
 #if S3C24XX_I2S_DEBUG
-#define DBG(x...) printk(KERN_DEBUG x)
+#define DBG(x...) printk(KERN_DEBUG "s3c24xx-i2s: " x)
 #else
 #define DBG(x...)
 #endif
@@ -414,6 +414,8 @@ static int s3c24xx_i2s_probe(struct platform_device *pdev)
 int s3c24xx_i2s_suspend(struct platform_device *pdev,
 		struct snd_soc_cpu_dai *cpu_dai)
 {
+	DBG("Entered %s\n", __func__);
+
 	s3c24xx_i2s.iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON);
 	s3c24xx_i2s.iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
 	s3c24xx_i2s.iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON);
@@ -427,6 +429,7 @@ int s3c24xx_i2s_suspend(struct platform_device *pdev,
 int s3c24xx_i2s_resume(struct platform_device *pdev,
 		struct snd_soc_cpu_dai *cpu_dai)
 {
+	DBG("Entered %s\n", __func__);
 	clk_enable(s3c24xx_i2s.iis_clk);
 
 	writel(s3c24xx_i2s.iiscon, s3c24xx_i2s.regs + S3C2410_IISCON);
diff --git a/sound/soc/s3c24xx/s3c24xx-pcm.c b/sound/soc/s3c24xx/s3c24xx-pcm.c
index 40112e2b1ec..49580fb481d 100644
--- a/sound/soc/s3c24xx/s3c24xx-pcm.c
+++ b/sound/soc/s3c24xx/s3c24xx-pcm.c
@@ -39,7 +39,7 @@
 
 #define S3C24XX_PCM_DEBUG 0
 #if S3C24XX_PCM_DEBUG
-#define DBG(x...) printk(KERN_DEBUG x)
+#define DBG(x...) printk(KERN_DEBUG "s3c24xx-pcm: " x)
 #else
 #define DBG(x...)
 #endif
-- 
cgit v1.2.3-70-g09d2


From d8ed061a9fb2ab1f4bd90b5c30f4dc98b9c2085b Mon Sep 17 00:00:00 2001
From: Mark Brown <broonie@opensource.wolfsonmicro.com>
Date: Tue, 22 Apr 2008 18:27:22 +0200
Subject: [ALSA] soc - s3c24xx - Declare suspend and resume static

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/soc/s3c24xx/s3c24xx-i2s.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'sound')

diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.c b/sound/soc/s3c24xx/s3c24xx-i2s.c
index cb68b9ced60..ce935a71099 100644
--- a/sound/soc/s3c24xx/s3c24xx-i2s.c
+++ b/sound/soc/s3c24xx/s3c24xx-i2s.c
@@ -411,7 +411,7 @@ static int s3c24xx_i2s_probe(struct platform_device *pdev)
 }
 
 #ifdef CONFIG_PM
-int s3c24xx_i2s_suspend(struct platform_device *pdev,
+static int s3c24xx_i2s_suspend(struct platform_device *pdev,
 		struct snd_soc_cpu_dai *cpu_dai)
 {
 	DBG("Entered %s\n", __func__);
@@ -426,7 +426,7 @@ int s3c24xx_i2s_suspend(struct platform_device *pdev,
 	return 0;
 }
 
-int s3c24xx_i2s_resume(struct platform_device *pdev,
+static int s3c24xx_i2s_resume(struct platform_device *pdev,
 		struct snd_soc_cpu_dai *cpu_dai)
 {
 	DBG("Entered %s\n", __func__);
-- 
cgit v1.2.3-70-g09d2


From a0b8f7d89b8de0cc79999b9fdd3a303912f3b2a3 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Tue, 22 Apr 2008 19:39:49 +0200
Subject: [ALSA] hda - Fix model for Acer Aspire 5720z

Set the proper model=acer for Acer Aspire 5720z with ALC268 codec.
ALSA bug#3550:
	https://bugtrack.alsa-project.org/alsa-bug/view.php?id=3550

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c | 1 +
 1 file changed, 1 insertion(+)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 732515dcc99..cdda64b02f4 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -10404,6 +10404,7 @@ static const char *alc268_models[ALC268_MODEL_LAST] = {
 };
 
 static struct snd_pci_quirk alc268_cfg_tbl[] = {
+	SND_PCI_QUIRK(0x1025, 0x011e, "Acer Aspire 5720z", ALC268_ACER),
 	SND_PCI_QUIRK(0x1025, 0x0126, "Acer", ALC268_ACER),
 	SND_PCI_QUIRK(0x1025, 0x012e, "Acer Aspire 5310", ALC268_ACER),
 	SND_PCI_QUIRK(0x1025, 0x0130, "Acer Extensa 5210", ALC268_ACER),
-- 
cgit v1.2.3-70-g09d2


From 05808ecc45802c1b533f42ed701a132d4c949034 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Wed, 23 Apr 2008 13:50:08 +0200
Subject: [ALSA] hda - Fix Thinkpad X300 digital mic

TP X300 digital mic requires additional init verbs with magic COEFs.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_analog.c | 3 +++
 1 file changed, 3 insertions(+)

(limited to 'sound')

diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index f486eb16a38..e0a605adde4 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -3740,6 +3740,9 @@ static struct hda_verb ad1984a_thinkpad_verbs[] = {
 	{0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
 	/* internal mic - dmic */
 	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	/* set magic COEFs for dmic */
+	{0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
+	{0x01, AC_VERB_SET_PROC_COEF, 0x08},
 	{ } /* end */
 };
 
-- 
cgit v1.2.3-70-g09d2


From 40efc15fc637cff22cf9c4f02c63f3f398320f83 Mon Sep 17 00:00:00 2001
From: Mark Brown <broonie@opensource.wolfsonmicro.com>
Date: Wed, 23 Apr 2008 15:09:31 +0200
Subject: [ALSA] soc - s3c24xx-i2s - Use linux/io.h

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/soc/s3c24xx/s3c24xx-i2s.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'sound')

diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.c b/sound/soc/s3c24xx/s3c24xx-i2s.c
index ce935a71099..340f36e6979 100644
--- a/sound/soc/s3c24xx/s3c24xx-i2s.c
+++ b/sound/soc/s3c24xx/s3c24xx-i2s.c
@@ -25,6 +25,7 @@
 #include <linux/delay.h>
 #include <linux/clk.h>
 #include <linux/jiffies.h>
+#include <linux/io.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -32,7 +33,6 @@
 #include <sound/soc.h>
 
 #include <asm/hardware.h>
-#include <asm/io.h>
 #include <asm/arch/regs-gpio.h>
 #include <asm/arch/regs-clock.h>
 #include <asm/arch/audio.h>
-- 
cgit v1.2.3-70-g09d2


From 0015e7d1e2b09443ac76573a2fb886854aa1ca15 Mon Sep 17 00:00:00 2001
From: Mark Brown <broonie@opensource.wolfsonmicro.com>
Date: Wed, 23 Apr 2008 15:09:57 +0200
Subject: [ALSA] soc - s3c24xx-i2s - Fix tab/space breakage

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/soc/s3c24xx/s3c24xx-i2s.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

(limited to 'sound')

diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.c b/sound/soc/s3c24xx/s3c24xx-i2s.c
index 340f36e6979..50e06f0777f 100644
--- a/sound/soc/s3c24xx/s3c24xx-i2s.c
+++ b/sound/soc/s3c24xx/s3c24xx-i2s.c
@@ -159,10 +159,10 @@ static void s3c24xx_snd_rxctrl(int on)
 		 * DMA engine will simply freeze randomly.
 		 */
 
-        iisfcon &= ~S3C2410_IISFCON_RXENABLE;
-        iisfcon &= ~S3C2410_IISFCON_RXDMA;
-        iiscon  |= S3C2410_IISCON_RXIDLE;
-        iiscon  &= ~S3C2410_IISCON_RXDMAEN;
+		iisfcon &= ~S3C2410_IISFCON_RXENABLE;
+		iisfcon &= ~S3C2410_IISFCON_RXDMA;
+		iiscon  |= S3C2410_IISCON_RXIDLE;
+		iiscon  &= ~S3C2410_IISCON_RXDMAEN;
 		iismod  &= ~S3C2410_IISMOD_RXMODE;
 
 		writel(iisfcon, s3c24xx_i2s.regs + S3C2410_IISFCON);
-- 
cgit v1.2.3-70-g09d2


From 0fe564a564922465ec3c483cee0e3dc6b368d879 Mon Sep 17 00:00:00 2001
From: Mark Brown <broonie@opensource.wolfsonmicro.com>
Date: Wed, 23 Apr 2008 15:10:28 +0200
Subject: [ALSA] soc - s3c24xx-i2s - Add missing spaces

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/soc/s3c24xx/s3c24xx-i2s.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'sound')

diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.c b/sound/soc/s3c24xx/s3c24xx-i2s.c
index 50e06f0777f..4ebcd6a8bf2 100644
--- a/sound/soc/s3c24xx/s3c24xx-i2s.c
+++ b/sound/soc/s3c24xx/s3c24xx-i2s.c
@@ -387,7 +387,7 @@ static int s3c24xx_i2s_probe(struct platform_device *pdev)
 	if (s3c24xx_i2s.regs == NULL)
 		return -ENXIO;
 
-	s3c24xx_i2s.iis_clk=clk_get(&pdev->dev, "iis");
+	s3c24xx_i2s.iis_clk = clk_get(&pdev->dev, "iis");
 	if (s3c24xx_i2s.iis_clk == NULL) {
 		DBG("failed to get iis_clock\n");
 		iounmap(s3c24xx_i2s.regs);
-- 
cgit v1.2.3-70-g09d2


From 1bfcd361461f25be7d6d180a8da30d02bc124046 Mon Sep 17 00:00:00 2001
From: Mark Brown <broonie@opensource.wolfsonmicro.com>
Date: Wed, 23 Apr 2008 15:12:19 +0200
Subject: [ALSA] soc - corgi - Fix checkpatch warnings

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/soc/pxa/corgi.c | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

(limited to 'sound')

diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c
index 1a70a6ac98c..7f32a116757 100644
--- a/sound/soc/pxa/corgi.c
+++ b/sound/soc/pxa/corgi.c
@@ -297,21 +297,19 @@ static int corgi_wm8731_init(struct snd_soc_codec *codec)
 	/* Add corgi specific controls */
 	for (i = 0; i < ARRAY_SIZE(wm8731_corgi_controls); i++) {
 		err = snd_ctl_add(codec->card,
-			snd_soc_cnew(&wm8731_corgi_controls[i],codec, NULL));
+			snd_soc_cnew(&wm8731_corgi_controls[i], codec, NULL));
 		if (err < 0)
 			return err;
 	}
 
 	/* Add corgi specific widgets */
-	for(i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++) {
+	for (i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++)
 		snd_soc_dapm_new_control(codec, &wm8731_dapm_widgets[i]);
-	}
 
 	/* Set up corgi specific audio path audio_map */
-	for(i = 0; audio_map[i][0] != NULL; i++) {
+	for (i = 0; audio_map[i][0] != NULL; i++)
 		snd_soc_dapm_connect_input(codec, audio_map[i][0],
 			audio_map[i][1], audio_map[i][2]);
-	}
 
 	snd_soc_dapm_sync_endpoints(codec);
 	return 0;
@@ -353,7 +351,8 @@ static int __init corgi_init(void)
 {
 	int ret;
 
-	if (!(machine_is_corgi() || machine_is_shepherd() || machine_is_husky()))
+	if (!(machine_is_corgi() || machine_is_shepherd() ||
+	      machine_is_husky()))
 		return -ENODEV;
 
 	corgi_snd_device = platform_device_alloc("soc-audio", -1);
-- 
cgit v1.2.3-70-g09d2


From 29e36e49bdb7f24ca7cc0fb980fab2c407a8a2c9 Mon Sep 17 00:00:00 2001
From: Mark Brown <broonie@opensource.wolfsonmicro.com>
Date: Wed, 23 Apr 2008 15:13:04 +0200
Subject: [ALSA] soc - poodle - Fix checkpatch warnings

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/soc/pxa/poodle.c | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

(limited to 'sound')

diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c
index 4fbf8bba962..7e830b21894 100644
--- a/sound/soc/pxa/poodle.c
+++ b/sound/soc/pxa/poodle.c
@@ -257,21 +257,19 @@ static int poodle_wm8731_init(struct snd_soc_codec *codec)
 	/* Add poodle specific controls */
 	for (i = 0; i < ARRAY_SIZE(wm8731_poodle_controls); i++) {
 		err = snd_ctl_add(codec->card,
-			snd_soc_cnew(&wm8731_poodle_controls[i],codec, NULL));
+			snd_soc_cnew(&wm8731_poodle_controls[i], codec, NULL));
 		if (err < 0)
 			return err;
 	}
 
 	/* Add poodle specific widgets */
-	for (i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++) {
+	for (i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++)
 		snd_soc_dapm_new_control(codec, &wm8731_dapm_widgets[i]);
-	}
 
 	/* Set up poodle specific audio path audio_map */
-	for (i = 0; audio_map[i][0] != NULL; i++) {
+	for (i = 0; audio_map[i][0] != NULL; i++)
 		snd_soc_dapm_connect_input(codec, audio_map[i][0],
 			audio_map[i][1], audio_map[i][2]);
-	}
 
 	snd_soc_dapm_sync_endpoints(codec);
 	return 0;
-- 
cgit v1.2.3-70-g09d2


From 22cd630285b6a12a50f02dfb23c531f151be5499 Mon Sep 17 00:00:00 2001
From: Mark Brown <broonie@opensource.wolfsonmicro.com>
Date: Wed, 23 Apr 2008 15:13:33 +0200
Subject: [ALSA] soc - spitz - Fix checkpatch warnings

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/soc/pxa/spitz.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

(limited to 'sound')

diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c
index ecca39033fc..d8b8372db00 100644
--- a/sound/soc/pxa/spitz.c
+++ b/sound/soc/pxa/spitz.c
@@ -313,15 +313,13 @@ static int spitz_wm8750_init(struct snd_soc_codec *codec)
 	}
 
 	/* Add spitz specific widgets */
-	for (i = 0; i < ARRAY_SIZE(wm8750_dapm_widgets); i++) {
+	for (i = 0; i < ARRAY_SIZE(wm8750_dapm_widgets); i++)
 		snd_soc_dapm_new_control(codec, &wm8750_dapm_widgets[i]);
-	}
 
 	/* Set up spitz specific audio path audio_map */
-	for (i = 0; audio_map[i][0] != NULL; i++) {
+	for (i = 0; audio_map[i][0] != NULL; i++)
 		snd_soc_dapm_connect_input(codec, audio_map[i][0],
 			audio_map[i][1], audio_map[i][2]);
-	}
 
 	snd_soc_dapm_sync_endpoints(codec);
 	return 0;
-- 
cgit v1.2.3-70-g09d2


From b32432e3f2d386d9563669c8cfdeaa473bfd8572 Mon Sep 17 00:00:00 2001
From: Mark Brown <broonie@opensource.wolfsonmicro.com>
Date: Wed, 23 Apr 2008 15:14:18 +0200
Subject: [ALSA] soc - pxa2xx-pcm - Fix checkpatch warnings

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/soc/pxa/pxa2xx-pcm.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

(limited to 'sound')

diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c
index daeaa4c8b87..01ad7bf716b 100644
--- a/sound/soc/pxa/pxa2xx-pcm.c
+++ b/sound/soc/pxa/pxa2xx-pcm.c
@@ -64,8 +64,8 @@ static void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id)
 	if (dcsr & DCSR_ENDINTR) {
 		snd_pcm_period_elapsed(substream);
 	} else {
-		printk( KERN_ERR "%s: DMA error on channel %d (DCSR=%#x)\n",
-			prtd->params->name, dma_ch, dcsr );
+		printk(KERN_ERR "%s: DMA error on channel %d (DCSR=%#x)\n",
+			prtd->params->name, dma_ch, dcsr);
 	}
 }
 
@@ -84,8 +84,8 @@ static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
 
 	/* return if this is a bufferless transfer e.g.
 	 * codec <--> BT codec or GSM modem -- lg FIXME */
-	 if (!dma)
-	 	return 0;
+	if (!dma)
+		return 0;
 
 	/* this may get called several times by oss emulation
 	 * with different params */
@@ -363,7 +363,6 @@ struct snd_soc_platform pxa2xx_soc_platform = {
 	.pcm_new	= pxa2xx_pcm_new,
 	.pcm_free	= pxa2xx_pcm_free_dma_buffers,
 };
-
 EXPORT_SYMBOL_GPL(pxa2xx_soc_platform);
 
 MODULE_AUTHOR("Nicolas Pitre");
-- 
cgit v1.2.3-70-g09d2


From d454aee9be72472ee18b5397fda2c673f40a1e69 Mon Sep 17 00:00:00 2001
From: Mark Brown <broonie@opensource.wolfsonmicro.com>
Date: Wed, 23 Apr 2008 15:16:46 +0200
Subject: [ALSA] soc - wm8731 - Clean up checkpatch warnings

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/soc/codecs/wm8731.c | 23 +++++++++++------------
 1 file changed, 11 insertions(+), 12 deletions(-)

(limited to 'sound')

diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index 9c33fe87492..0cf9265fca8 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -110,7 +110,7 @@ static int wm8731_write(struct snd_soc_codec *codec, unsigned int reg,
 	data[0] = (reg << 1) | ((value >> 8) & 0x0001);
 	data[1] = value & 0x00ff;
 
-	wm8731_write_reg_cache (codec, reg, value);
+	wm8731_write_reg_cache(codec, reg, value);
 	if (codec->hw_write(codec->control_data, data, 2) == 2)
 		return 0;
 	else
@@ -154,8 +154,10 @@ static int wm8731_add_controls(struct snd_soc_codec *codec)
 	int err, i;
 
 	for (i = 0; i < ARRAY_SIZE(wm8731_snd_controls); i++) {
-		if ((err = snd_ctl_add(codec->card,
-				snd_soc_cnew(&wm8731_snd_controls[i],codec, NULL))) < 0)
+		err = snd_ctl_add(codec->card,
+				  snd_soc_cnew(&wm8731_snd_controls[i],
+						codec, NULL));
+		if (err < 0)
 			return err;
 	}
 
@@ -221,15 +223,13 @@ static int wm8731_add_widgets(struct snd_soc_codec *codec)
 {
 	int i;
 
-	for(i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++) {
+	for (i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++)
 		snd_soc_dapm_new_control(codec, &wm8731_dapm_widgets[i]);
-	}
 
 	/* set up audio path interconnects */
-	for(i = 0; intercon[i][0] != NULL; i++) {
+	for (i = 0; intercon[i][0] != NULL; i++)
 		snd_soc_dapm_connect_input(codec, intercon[i][0],
 			intercon[i][1], intercon[i][2]);
-	}
 
 	snd_soc_dapm_new_widgets(codec);
 	return 0;
@@ -589,7 +589,7 @@ pcm_err:
 
 static struct snd_soc_device *wm8731_socdev;
 
-#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 
 /*
  * WM8731 2 wire address is determined by GPIO5
@@ -651,7 +651,7 @@ err:
 
 static int wm8731_i2c_detach(struct i2c_client *client)
 {
-	struct snd_soc_codec* codec = i2c_get_clientdata(client);
+	struct snd_soc_codec *codec = i2c_get_clientdata(client);
 	i2c_detach_client(client);
 	kfree(codec->reg_cache);
 	kfree(client);
@@ -709,7 +709,7 @@ static int wm8731_probe(struct platform_device *pdev)
 	INIT_LIST_HEAD(&codec->dapm_paths);
 
 	wm8731_socdev = socdev;
-#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 	if (setup->i2c_address) {
 		normal_i2c[0] = setup->i2c_address;
 		codec->hw_write = (hw_write_t)i2c_master_send;
@@ -734,7 +734,7 @@ static int wm8731_remove(struct platform_device *pdev)
 
 	snd_soc_free_pcms(socdev);
 	snd_soc_dapm_free(socdev);
-#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 	i2c_del_driver(&wm8731_i2c_driver);
 #endif
 	kfree(codec->private_data);
@@ -749,7 +749,6 @@ struct snd_soc_codec_device soc_codec_dev_wm8731 = {
 	.suspend = 	wm8731_suspend,
 	.resume =	wm8731_resume,
 };
-
 EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731);
 
 MODULE_DESCRIPTION("ASoC WM8731 driver");
-- 
cgit v1.2.3-70-g09d2


From 42f3030f0cac474fc3232c8028b97f54b985718c Mon Sep 17 00:00:00 2001
From: Mark Brown <broonie@opensource.wolfsonmicro.com>
Date: Wed, 23 Apr 2008 15:17:12 +0200
Subject: [ALSA] soc - wm8750 - Clean up checkpatch warnings

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/soc/codecs/wm8750.c | 27 +++++++++++++--------------
 1 file changed, 13 insertions(+), 14 deletions(-)

(limited to 'sound')

diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
index 77a857b997a..16cd5d4d5ad 100644
--- a/sound/soc/codecs/wm8750.c
+++ b/sound/soc/codecs/wm8750.c
@@ -110,7 +110,7 @@ static int wm8750_write(struct snd_soc_codec *codec, unsigned int reg,
 	data[0] = (reg << 1) | ((value >> 8) & 0x0001);
 	data[1] = value & 0x00ff;
 
-	wm8750_write_reg_cache (codec, reg, value);
+	wm8750_write_reg_cache(codec, reg, value);
 	if (codec->hw_write(codec->control_data, data, 2) == 2)
 		return 0;
 	else
@@ -257,7 +257,8 @@ static int wm8750_add_controls(struct snd_soc_codec *codec)
 
 	for (i = 0; i < ARRAY_SIZE(wm8750_snd_controls); i++) {
 		err = snd_ctl_add(codec->card,
-				snd_soc_cnew(&wm8750_snd_controls[i],codec, NULL));
+				snd_soc_cnew(&wm8750_snd_controls[i],
+						codec, NULL));
 		if (err < 0)
 			return err;
 	}
@@ -478,15 +479,13 @@ static int wm8750_add_widgets(struct snd_soc_codec *codec)
 {
 	int i;
 
-	for(i = 0; i < ARRAY_SIZE(wm8750_dapm_widgets); i++) {
+	for (i = 0; i < ARRAY_SIZE(wm8750_dapm_widgets); i++)
 		snd_soc_dapm_new_control(codec, &wm8750_dapm_widgets[i]);
-	}
 
 	/* set up audio path audio_mapnects */
-	for(i = 0; audio_map[i][0] != NULL; i++) {
+	for (i = 0; audio_map[i][0] != NULL; i++)
 		snd_soc_dapm_connect_input(codec, audio_map[i][0],
 			audio_map[i][1], audio_map[i][2]);
-	}
 
 	snd_soc_dapm_new_widgets(codec);
 	return 0;
@@ -714,8 +713,8 @@ static int wm8750_dapm_event(struct snd_soc_codec *codec, int event)
 }
 
 #define WM8750_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
-		SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
-		SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
+	SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
+	SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
 
 #define WM8750_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
 	SNDRV_PCM_FMTBIT_S24_LE)
@@ -784,7 +783,8 @@ static int wm8750_resume(struct platform_device *pdev)
 	if (codec->suspend_dapm_state == SNDRV_CTL_POWER_D0) {
 		wm8750_dapm_event(codec, SNDRV_CTL_POWER_D2);
 		codec->dapm_state = SNDRV_CTL_POWER_D0;
-		schedule_delayed_work(&codec->delayed_work, msecs_to_jiffies(1000));
+		schedule_delayed_work(&codec->delayed_work,
+					msecs_to_jiffies(1000));
 	}
 
 	return 0;
@@ -864,7 +864,7 @@ pcm_err:
    around */
 static struct snd_soc_device *wm8750_socdev;
 
-#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 
 /*
  * WM8731 2 wire address is determined by GPIO5
@@ -979,8 +979,8 @@ static int wm8750_probe(struct platform_device *pdev)
 	INIT_LIST_HEAD(&codec->dapm_paths);
 	wm8750_socdev = socdev;
 	INIT_DELAYED_WORK(&codec->delayed_work, wm8750_work);
-	
-#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 	if (setup->i2c_address) {
 		normal_i2c[0] = setup->i2c_address;
 		codec->hw_write = (hw_write_t)i2c_master_send;
@@ -1025,7 +1025,7 @@ static int wm8750_remove(struct platform_device *pdev)
 	run_delayed_work(&codec->delayed_work);
 	snd_soc_free_pcms(socdev);
 	snd_soc_dapm_free(socdev);
-#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 	i2c_del_driver(&wm8750_i2c_driver);
 #endif
 	kfree(codec->private_data);
@@ -1040,7 +1040,6 @@ struct snd_soc_codec_device soc_codec_dev_wm8750 = {
 	.suspend = 	wm8750_suspend,
 	.resume =	wm8750_resume,
 };
-
 EXPORT_SYMBOL_GPL(soc_codec_dev_wm8750);
 
 MODULE_DESCRIPTION("ASoC WM8750 driver");
-- 
cgit v1.2.3-70-g09d2


From 24c053e755f2f77d9c9d9a9250ca1132eae280e7 Mon Sep 17 00:00:00 2001
From: Mark Brown <broonie@opensource.wolfsonmicro.com>
Date: Wed, 23 Apr 2008 15:26:45 +0200
Subject: [ALSA] soc - ac97 - Clean up checkpatch warnings

Also change some if (x == NULL) to if (!x).

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/soc/codecs/ac97.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

(limited to 'sound')

diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c
index 242130cf1ab..2a1ffe39690 100644
--- a/sound/soc/codecs/ac97.c
+++ b/sound/soc/codecs/ac97.c
@@ -40,7 +40,8 @@ static int ac97_prepare(struct snd_pcm_substream *substream)
 }
 
 #define STD_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
-		SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
+		SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 |\
+		SNDRV_PCM_RATE_48000)
 
 struct snd_soc_codec_dai ac97_dai = {
 	.name = "AC97 HiFi",
@@ -86,7 +87,7 @@ static int ac97_soc_probe(struct platform_device *pdev)
 	printk(KERN_INFO "AC97 SoC Audio Codec %s\n", AC97_VERSION);
 
 	socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
-	if (socdev->codec == NULL)
+	if (!socdev->codec)
 		return -ENOMEM;
 	codec = socdev->codec;
 	mutex_init(&codec->mutex);
@@ -102,17 +103,17 @@ static int ac97_soc_probe(struct platform_device *pdev)
 
 	/* register pcms */
 	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
-	if(ret < 0)
+	if (ret < 0)
 		goto err;
 
 	/* add codec as bus device for standard ac97 */
 	ret = snd_ac97_bus(codec->card, 0, &soc_ac97_ops, NULL, &ac97_bus);
-	if(ret < 0)
+	if (ret < 0)
 		goto bus_err;
 
 	memset(&ac97_template, 0, sizeof(struct snd_ac97_template));
 	ret = snd_ac97_mixer(ac97_bus, &ac97_template, &codec->ac97);
-	if(ret < 0)
+	if (ret < 0)
 		goto bus_err;
 
 	ret = snd_soc_register_card(socdev);
@@ -135,7 +136,7 @@ static int ac97_soc_remove(struct platform_device *pdev)
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
 	struct snd_soc_codec *codec = socdev->codec;
 
-	if(codec == NULL)
+	if (!codec)
 		return 0;
 
 	snd_soc_free_pcms(socdev);
@@ -145,11 +146,10 @@ static int ac97_soc_remove(struct platform_device *pdev)
 	return 0;
 }
 
-struct snd_soc_codec_device soc_codec_dev_ac97= {
+struct snd_soc_codec_device soc_codec_dev_ac97 = {
 	.probe = 	ac97_soc_probe,
 	.remove = 	ac97_soc_remove,
 };
-
 EXPORT_SYMBOL_GPL(soc_codec_dev_ac97);
 
 MODULE_DESCRIPTION("Soc Generic AC97 driver");
-- 
cgit v1.2.3-70-g09d2


From 73bdd2ad7aac70456494c4a1d93f99fe88184dba Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Wed, 23 Apr 2008 17:08:58 +0200
Subject: [ALSA] pcsp - Fix dependency in Kconfig

Added the proper dependency to Kconfig for snd-pcsp driver.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/drivers/Kconfig | 1 +
 1 file changed, 1 insertion(+)

(limited to 'sound')

diff --git a/sound/drivers/Kconfig b/sound/drivers/Kconfig
index 78648c4e9e7..fe85af1c569 100644
--- a/sound/drivers/Kconfig
+++ b/sound/drivers/Kconfig
@@ -7,6 +7,7 @@ menu "Generic devices"
 config SND_PCSP
 	tristate "Internal PC speaker support"
 	depends on X86_PC && HIGH_RES_TIMERS
+	depends on INPUT
 	help
 	  If you don't have a sound card in your computer, you can include a
 	  driver for the PC speaker which allows it to act like a primitive
-- 
cgit v1.2.3-70-g09d2


From efd89d9dcf75ab0a31b200db0ae4ae19cad25e48 Mon Sep 17 00:00:00 2001
From: Stas Sergeev <stsp@aknet.ru>
Date: Wed, 23 Apr 2008 17:16:38 +0200
Subject: [ALSA] pcsp: fix wording in DEBUG_PAGEALLOC warning

Signed-off-by: Stas Sergeev <stsp@aknet.ru>
(fixed invalid KERN_WARNING by tiwai)
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/drivers/pcsp/pcsp.c | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

(limited to 'sound')

diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c
index d8f96219fd3..59203511e77 100644
--- a/sound/drivers/pcsp/pcsp.c
+++ b/sound/drivers/pcsp/pcsp.c
@@ -147,12 +147,8 @@ static int __devinit alsa_card_pcsp_init(struct device *dev)
 
 #ifdef CONFIG_DEBUG_PAGEALLOC
 	/* Well, CONFIG_DEBUG_PAGEALLOC makes the sound horrible. Lets alert */
-	printk(KERN_WARNING
-	       "PCSP: Warning, CONFIG_DEBUG_PAGEALLOC is enabled!\n"
-	       "You have to disable it if you want to use the PC-Speaker "
-	       "driver.\n"
-	       "Unless it is disabled, enjoy the horrible, distorted "
-	       "and crackling noise.\n");
+	printk(KERN_WARNING "PCSP: CONFIG_DEBUG_PAGEALLOC is enabled, "
+	       "which may make the sound noisy.\n");
 #endif
 
 	return 0;
-- 
cgit v1.2.3-70-g09d2


From b415ed45f4db9f8365daac84cf2518642a174dc0 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Wed, 23 Apr 2008 17:47:28 +0200
Subject: [ALSA] Define MPU401 registers in sound/mpu401_uart.h

Define some MPU401 registers in sound/mpu401_uart.h so that other
drivers can refer to them.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 include/sound/mpu401.h             | 15 +++++++++++++++
 sound/drivers/mpu401/mpu401_uart.c | 10 ++++------
 2 files changed, 19 insertions(+), 6 deletions(-)

(limited to 'sound')

diff --git a/include/sound/mpu401.h b/include/sound/mpu401.h
index d45218b44df..68b634b7506 100644
--- a/include/sound/mpu401.h
+++ b/include/sound/mpu401.h
@@ -102,6 +102,21 @@ struct snd_mpu401 {
 #define MPU401C(mpu) (mpu)->cport
 #define MPU401D(mpu) (mpu)->port
 
+/*
+ * control register bits
+ */
+/* read MPU401C() */
+#define MPU401_RX_EMPTY		0x80
+#define MPU401_TX_FULL		0x40
+
+/* write MPU401C() */
+#define MPU401_RESET		0xff
+#define MPU401_ENTER_UART	0x3f
+
+/* read MPU401D() */
+#define MPU401_ACK		0xfe
+
+
 /*
 
  */
diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c
index dd6ec426673..18cca2457d4 100644
--- a/sound/drivers/mpu401/mpu401_uart.c
+++ b/sound/drivers/mpu401/mpu401_uart.c
@@ -49,12 +49,10 @@ static void snd_mpu401_uart_output_write(struct snd_mpu401 * mpu);
 
  */
 
-#define snd_mpu401_input_avail(mpu)	(!(mpu->read(mpu, MPU401C(mpu)) & 0x80))
-#define snd_mpu401_output_ready(mpu)	(!(mpu->read(mpu, MPU401C(mpu)) & 0x40))
-
-#define MPU401_RESET		0xff
-#define MPU401_ENTER_UART	0x3f
-#define MPU401_ACK		0xfe
+#define snd_mpu401_input_avail(mpu) \
+	(!(mpu->read(mpu, MPU401C(mpu)) & MPU401_RX_EMPTY))
+#define snd_mpu401_output_ready(mpu) \
+	(!(mpu->read(mpu, MPU401C(mpu)) & MPU401_TX_FULL))
 
 /* Build in lowlevel io */
 static void mpu401_write_port(struct snd_mpu401 *mpu, unsigned char data,
-- 
cgit v1.2.3-70-g09d2


From 3a841d519f91463361bbbe7addc24a0c1b2e9f99 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Wed, 23 Apr 2008 17:47:28 +0200
Subject: [ALSA] ice1724 - Fix IRQ lock-up with MPU access

The sound boards with VT1724 and compatible chips may lock up when
MPU401 is accessed together with the PCM streaming.
This patch fixes the problem.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/ice1712/ice1724.c    | 95 +++++++++++++++++++++++++++++++++++-------
 sound/pci/ice1712/prodigy192.c |  4 --
 2 files changed, 81 insertions(+), 18 deletions(-)

(limited to 'sound')

diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index 13ea94f317c..4490422fb93 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -222,6 +222,32 @@ static unsigned int snd_vt1724_get_gpio_data(struct snd_ice1712 *ice)
 	return data;
 }
 
+/*
+ * MPU401 accessor
+ */
+static unsigned char snd_vt1724_mpu401_read(struct snd_mpu401 *mpu,
+					    unsigned long addr)
+{
+	/* fix status bits to the standard position */
+	/* only RX_EMPTY and TX_FULL are checked */
+	if (addr == MPU401C(mpu))
+		return (inb(addr) & 0x0c) << 4;
+	else
+		return inb(addr);
+}
+
+static void snd_vt1724_mpu401_write(struct snd_mpu401 *mpu,
+				    unsigned char data, unsigned long addr)
+{
+	if (addr == MPU401C(mpu)) {
+		if (data == MPU401_ENTER_UART)
+			outb(0x01, addr);
+		/* what else? */
+	} else
+		outb(data, addr);
+}
+
+
 /*
  *  Interrupt handler
  */
@@ -230,24 +256,53 @@ static irqreturn_t snd_vt1724_interrupt(int irq, void *dev_id)
 {
 	struct snd_ice1712 *ice = dev_id;
 	unsigned char status;
+	unsigned char status_mask =
+		VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX | VT1724_IRQ_MTPCM;
 	int handled = 0;
+#ifdef CONFIG_SND_DEBUG
+	int timeout = 0;
+#endif
 
 	while (1) {
 		status = inb(ICEREG1724(ice, IRQSTAT));
+		status &= status_mask;
 		if (status == 0)
 			break;
-
+#ifdef CONFIG_SND_DEBUG
+		if (++timeout > 10) {
+			printk(KERN_ERR
+			       "ice1724: Too long irq loop, status = 0x%x\n",
+			       status);
+			break;
+		}
+#endif
 		handled = 1;		
-		/* these should probably be separated at some point, 
-		 * but as we don't currently have MPU support on the board
-		 * I will leave it
-		 */
-		if ((status & VT1724_IRQ_MPU_RX)||(status & VT1724_IRQ_MPU_TX)) {
+		if (status & VT1724_IRQ_MPU_TX) {
 			if (ice->rmidi[0])
-				snd_mpu401_uart_interrupt(irq, ice->rmidi[0]->private_data);
-			outb(status & (VT1724_IRQ_MPU_RX|VT1724_IRQ_MPU_TX), ICEREG1724(ice, IRQSTAT));
-			status &= ~(VT1724_IRQ_MPU_RX|VT1724_IRQ_MPU_TX);
+				snd_mpu401_uart_interrupt_tx(irq,
+					ice->rmidi[0]->private_data);
+			else /* disable TX to be sure */
+				outb(inb(ICEREG1724(ice, IRQMASK)) |
+				     VT1724_IRQ_MPU_TX,
+				     ICEREG1724(ice, IRQMASK));
+			/* Due to mysterical reasons, MPU_TX is always
+			 * generated (and can't be cleared) when a PCM
+			 * playback is going.  So let's ignore at the
+			 * next loop.
+			 */
+			status_mask &= ~VT1724_IRQ_MPU_TX;
+		}
+		if (status & VT1724_IRQ_MPU_RX) {
+			if (ice->rmidi[0])
+				snd_mpu401_uart_interrupt(irq,
+					ice->rmidi[0]->private_data);
+			else /* disable RX to be sure */
+				outb(inb(ICEREG1724(ice, IRQMASK)) |
+				     VT1724_IRQ_MPU_RX,
+				     ICEREG1724(ice, IRQMASK));
 		}
+		/* ack MPU irq */
+		outb(status, ICEREG1724(ice, IRQSTAT));
 		if (status & VT1724_IRQ_MTPCM) {
 			/*
 			 * Multi-track PCM
@@ -2236,10 +2291,7 @@ static int __devinit snd_vt1724_create(struct snd_card *card,
 	}
 
 	/* unmask used interrupts */
-	if (! (ice->eeprom.data[ICE_EEP2_SYSCONF] & VT1724_CFG_MPU401))
-		mask = VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX;
-	else
-		mask = 0;
+	mask = VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX;
 	outb(mask, ICEREG1724(ice, IRQMASK));
 	/* don't handle FIFO overrun/underruns (just yet),
 	 * since they cause machine lockups
@@ -2373,14 +2425,29 @@ static int __devinit snd_vt1724_probe(struct pci_dev *pci,
 
 	if (! c->no_mpu401) {
 		if (ice->eeprom.data[ICE_EEP2_SYSCONF] & VT1724_CFG_MPU401) {
+			struct snd_mpu401 *mpu;
 			if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_ICE1712,
 						       ICEREG1724(ice, MPU_CTRL),
-						       MPU401_INFO_INTEGRATED,
+						       (MPU401_INFO_INTEGRATED |
+							MPU401_INFO_TX_IRQ),
 						       ice->irq, 0,
 						       &ice->rmidi[0])) < 0) {
 				snd_card_free(card);
 				return err;
 			}
+			mpu = ice->rmidi[0]->private_data;
+			mpu->read = snd_vt1724_mpu401_read;
+			mpu->write = snd_vt1724_mpu401_write;
+			/* unmask MPU RX/TX irqs */
+			outb(inb(ICEREG1724(ice, IRQMASK)) &
+			     ~(VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX),
+			     ICEREG1724(ice, IRQMASK));
+#if 0 /* for testing */
+			/* set watermarks */
+			outb(VT1724_MPU_RX_FIFO | 0x1,
+			     ICEREG1724(ice, MPU_FIFO_WM));
+			outb(0x1, ICEREG1724(ice, MPU_FIFO_WM));
+#endif
 		}
 	}
 
diff --git a/sound/pci/ice1712/prodigy192.c b/sound/pci/ice1712/prodigy192.c
index 25ceb67a9c1..48d3679292a 100644
--- a/sound/pci/ice1712/prodigy192.c
+++ b/sound/pci/ice1712/prodigy192.c
@@ -812,10 +812,6 @@ struct snd_ice1712_card_info snd_vt1724_prodigy192_cards[] __devinitdata = {
 		.build_controls = prodigy192_add_controls,
 		.eeprom_size = sizeof(prodigy71_eeprom),
 		.eeprom_data = prodigy71_eeprom,
-		/* the current MPU401 code loops infinitely
-		 * when opening midi device
-		 */
-		.no_mpu401 = 1,
 	},
 	{ } /* terminator */
 };
-- 
cgit v1.2.3-70-g09d2