aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2010-04-02 20:02:55 +0200
committerIngo Molnar <mingo@elte.hu>2010-04-02 20:03:08 +0200
commitc9494727cf293ae2ec66af57547a3e79c724fec2 (patch)
tree44ae197b64fa7530ee695a90ad31326dda06f1e1 /sound
parent6427462bfa50f50dc6c088c07037264fcc73eca1 (diff)
parent42be79e37e264557f12860fa4cc84b4de3685954 (diff)
downloadkernel_samsung_tuna-c9494727cf293ae2ec66af57547a3e79c724fec2.zip
kernel_samsung_tuna-c9494727cf293ae2ec66af57547a3e79c724fec2.tar.gz
kernel_samsung_tuna-c9494727cf293ae2ec66af57547a3e79c724fec2.tar.bz2
Merge branch 'linus' into sched/core
Merge reason: update to latest upstream Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'sound')
-rw-r--r--sound/arm/pxa2xx-ac97-lib.c68
-rw-r--r--sound/arm/pxa2xx-pcm-lib.c1
-rw-r--r--sound/core/pcm_lib.c6
-rw-r--r--sound/core/timer.c2
-rw-r--r--sound/isa/opti9xx/miro.c2
-rw-r--r--sound/isa/opti9xx/opti92x-ad1848.c121
-rw-r--r--sound/isa/sb/jazz16.c1
-rw-r--r--sound/oss/coproc.h2
-rw-r--r--sound/oss/sequencer.c2
-rw-r--r--sound/oss/v_midi.h5
-rw-r--r--sound/oss/vidc.c4
-rw-r--r--sound/pci/ac97/ac97_patch.c2
-rw-r--r--sound/pci/cmipci.c14
-rw-r--r--sound/pci/hda/Kconfig2
-rw-r--r--sound/pci/hda/Makefile4
-rw-r--r--sound/pci/hda/hda_codec.c73
-rw-r--r--sound/pci/hda/hda_eld.c6
-rw-r--r--sound/pci/hda/hda_intel.c20
-rw-r--r--sound/pci/hda/patch_conexant.c15
-rw-r--r--sound/pci/hda/patch_hdmi.c849
-rw-r--r--sound/pci/hda/patch_intelhdmi.c821
-rw-r--r--sound/pci/hda/patch_nvhdmi.c278
-rw-r--r--sound/pci/hda/patch_realtek.c34
-rw-r--r--sound/pci/hda/patch_sigmatel.c2
-rw-r--r--sound/pci/oxygen/xonar_wm87x6.c2
-rw-r--r--sound/pci/riptide/riptide.c6
-rw-r--r--sound/pci/rme9652/hdspm.c2
-rw-r--r--sound/soc/codecs/ak4104.c6
-rw-r--r--sound/soc/codecs/tlv320dac33.c10
-rw-r--r--sound/soc/codecs/uda1380.c2
-rw-r--r--sound/soc/codecs/wm8350.c8
-rw-r--r--sound/soc/codecs/wm8990.c2
-rw-r--r--sound/soc/codecs/wm_hubs.c2
-rw-r--r--sound/soc/imx/Kconfig2
-rw-r--r--sound/soc/omap/omap-mcbsp.c144
-rw-r--r--sound/soc/omap/omap-mcbsp.h4
-rw-r--r--sound/soc/pxa/pxa-ssp.c93
-rw-r--r--sound/soc/s3c24xx/s3c64xx-i2s.c4
-rw-r--r--sound/soc/sh/Kconfig1
-rw-r--r--sound/soc/sh/siu.h2
-rw-r--r--sound/soc/sh/siu_pcm.c2
-rw-r--r--sound/soc/soc-core.c14
-rw-r--r--sound/usb/Kconfig6
-rw-r--r--sound/usb/caiaq/midi.h2
-rw-r--r--sound/usb/ua101.c100
-rw-r--r--sound/usb/usbaudio.c57
-rw-r--r--sound/usb/usbaudio.h3
-rw-r--r--sound/usb/usbquirks.h30
48 files changed, 1583 insertions, 1255 deletions
diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c
index 6fdca97..88eec38 100644
--- a/sound/arm/pxa2xx-ac97-lib.c
+++ b/sound/arm/pxa2xx-ac97-lib.c
@@ -22,7 +22,6 @@
#include <asm/irq.h>
#include <mach/regs-ac97.h>
-#include <mach/pxa2xx-gpio.h>
#include <mach/audio.h>
static DEFINE_MUTEX(car_mutex);
@@ -32,6 +31,8 @@ static struct clk *ac97_clk;
static struct clk *ac97conf_clk;
static int reset_gpio;
+extern void pxa27x_assert_ac97reset(int reset_gpio, int on);
+
/*
* Beware PXA27x bugs:
*
@@ -42,45 +43,6 @@ static int reset_gpio;
* 1 jiffy timeout if interrupt never comes).
*/
-enum {
- RESETGPIO_FORCE_HIGH,
- RESETGPIO_FORCE_LOW,
- RESETGPIO_NORMAL_ALTFUNC
-};
-
-/**
- * set_resetgpio_mode - computes and sets the AC97_RESET gpio mode on PXA
- * @mode: chosen action
- *
- * As the PXA27x CPUs suffer from a AC97 bug, a manual control of the reset line
- * must be done to insure proper work of AC97 reset line. This function
- * computes the correct gpio_mode for further use by reset functions, and
- * applied the change through pxa_gpio_mode.
- */
-static void set_resetgpio_mode(int resetgpio_action)
-{
- int mode = 0;
-
- if (reset_gpio)
- switch (resetgpio_action) {
- case RESETGPIO_NORMAL_ALTFUNC:
- if (reset_gpio == 113)
- mode = 113 | GPIO_ALT_FN_2_OUT;
- if (reset_gpio == 95)
- mode = 95 | GPIO_ALT_FN_1_OUT;
- break;
- case RESETGPIO_FORCE_LOW:
- mode = reset_gpio | GPIO_OUT | GPIO_DFLT_LOW;
- break;
- case RESETGPIO_FORCE_HIGH:
- mode = reset_gpio | GPIO_OUT | GPIO_DFLT_HIGH;
- break;
- };
-
- if (mode)
- pxa_gpio_mode(mode);
-}
-
unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
{
unsigned short val = -1;
@@ -174,12 +136,11 @@ static inline void pxa_ac97_warm_pxa27x(void)
{
gsr_bits = 0;
- /* warm reset broken on Bulverde,
- so manually keep AC97 reset high */
- set_resetgpio_mode(RESETGPIO_FORCE_HIGH);
+ /* warm reset broken on Bulverde, so manually keep AC97 reset high */
+ pxa27x_assert_ac97reset(reset_gpio, 1);
udelay(10);
GCR |= GCR_WARM_RST;
- set_resetgpio_mode(RESETGPIO_NORMAL_ALTFUNC);
+ pxa27x_assert_ac97reset(reset_gpio, 0);
udelay(500);
}
@@ -345,16 +306,6 @@ EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_suspend);
int pxa2xx_ac97_hw_resume(void)
{
- if (cpu_is_pxa25x() || cpu_is_pxa27x()) {
- pxa_gpio_mode(GPIO31_SYNC_AC97_MD);
- pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD);
- pxa_gpio_mode(GPIO28_BITCLK_AC97_MD);
- pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD);
- }
- if (cpu_is_pxa27x()) {
- /* Use GPIO 113 or 95 as AC97 Reset on Bulverde */
- set_resetgpio_mode(RESETGPIO_NORMAL_ALTFUNC);
- }
clk_enable(ac97_clk);
return 0;
}
@@ -386,16 +337,9 @@ int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev)
reset_gpio = 113;
}
- if (cpu_is_pxa25x() || cpu_is_pxa27x()) {
- pxa_gpio_mode(GPIO31_SYNC_AC97_MD);
- pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD);
- pxa_gpio_mode(GPIO28_BITCLK_AC97_MD);
- pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD);
- }
-
if (cpu_is_pxa27x()) {
/* Use GPIO 113 as AC97 Reset on Bulverde */
- set_resetgpio_mode(RESETGPIO_NORMAL_ALTFUNC);
+ pxa27x_assert_ac97reset(reset_gpio, 0);
ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK");
if (IS_ERR(ac97conf_clk)) {
ret = PTR_ERR(ac97conf_clk);
diff --git a/sound/arm/pxa2xx-pcm-lib.c b/sound/arm/pxa2xx-pcm-lib.c
index 743ac6a..fd51fa8 100644
--- a/sound/arm/pxa2xx-pcm-lib.c
+++ b/sound/arm/pxa2xx-pcm-lib.c
@@ -205,6 +205,7 @@ int __pxa2xx_pcm_open(struct snd_pcm_substream *substream)
if (!rtd->dma_desc_array)
goto err1;
+ rtd->dma_ch = -1;
runtime->private_data = rtd;
return 0;
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index b546ac2..a2ff861 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -148,6 +148,9 @@ static void pcm_debug_name(struct snd_pcm_substream *substream,
#define xrun_debug(substream, mask) \
((substream)->pstr->xrun_debug & (mask))
+#else
+#define xrun_debug(substream, mask) 0
+#endif
#define dump_stack_on_xrun(substream) do { \
if (xrun_debug(substream, XRUN_DEBUG_STACK)) \
@@ -169,6 +172,7 @@ static void xrun(struct snd_pcm_substream *substream)
}
}
+#ifdef CONFIG_SND_PCM_XRUN_DEBUG
#define hw_ptr_error(substream, fmt, args...) \
do { \
if (xrun_debug(substream, XRUN_DEBUG_BASIC)) { \
@@ -255,8 +259,6 @@ static void xrun_log_show(struct snd_pcm_substream *substream)
#else /* ! CONFIG_SND_PCM_XRUN_DEBUG */
-#define xrun_debug(substream, mask) 0
-#define xrun(substream) do { } while (0)
#define hw_ptr_error(substream, fmt, args...) do { } while (0)
#define xrun_log(substream, pos) do { } while (0)
#define xrun_log_show(substream) do { } while (0)
diff --git a/sound/core/timer.c b/sound/core/timer.c
index 8f8b17a..7394365 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -393,7 +393,7 @@ static void snd_timer_notify1(struct snd_timer_instance *ti, int event)
event == SNDRV_TIMER_EVENT_CONTINUE)
resolution = snd_timer_resolution(ti);
if (ti->ccallback)
- ti->ccallback(ti, SNDRV_TIMER_EVENT_START, &tstamp, resolution);
+ ti->ccallback(ti, event, &tstamp, resolution);
if (ti->flags & SNDRV_TIMER_IFLG_SLAVE)
return;
timer = ti->timer;
diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c
index b865e45..5913717 100644
--- a/sound/isa/opti9xx/miro.c
+++ b/sound/isa/opti9xx/miro.c
@@ -1558,7 +1558,7 @@ static int __devinit snd_card_miro_pnp(struct snd_miro *chip,
err = pnp_activate_dev(devmc);
if (err < 0) {
- snd_printk(KERN_ERR "OPL syntg pnp configure failure: %d\n",
+ snd_printk(KERN_ERR "MC pnp configure failure: %d\n",
err);
return err;
}
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c
index a4af53b..4d2d040 100644
--- a/sound/isa/opti9xx/opti92x-ad1848.c
+++ b/sound/isa/opti9xx/opti92x-ad1848.c
@@ -144,12 +144,8 @@ struct snd_opti9xx {
spinlock_t lock;
+ long wss_base;
int irq;
-
-#ifdef CONFIG_PNP
- struct pnp_dev *dev;
- struct pnp_dev *devmpu;
-#endif /* CONFIG_PNP */
};
static int snd_opti9xx_pnp_is_probed;
@@ -159,12 +155,17 @@ static int snd_opti9xx_pnp_is_probed;
static struct pnp_card_device_id snd_opti9xx_pnpids[] = {
#ifndef OPTi93X
/* OPTi 82C924 */
- { .id = "OPT0924", .devs = { { "OPT0000" }, { "OPT0002" } }, .driver_data = 0x0924 },
+ { .id = "OPT0924",
+ .devs = { { "OPT0000" }, { "OPT0002" }, { "OPT0005" } },
+ .driver_data = 0x0924 },
/* OPTi 82C925 */
- { .id = "OPT0925", .devs = { { "OPT9250" }, { "OPT0002" } }, .driver_data = 0x0925 },
+ { .id = "OPT0925",
+ .devs = { { "OPT9250" }, { "OPT0002" }, { "OPT0005" } },
+ .driver_data = 0x0925 },
#else
/* OPTi 82C931/3 */
- { .id = "OPT0931", .devs = { { "OPT9310" }, { "OPT0002" } }, .driver_data = 0x0931 },
+ { .id = "OPT0931", .devs = { { "OPT9310" }, { "OPT0002" } },
+ .driver_data = 0x0931 },
#endif /* OPTi93X */
{ .id = "" }
};
@@ -207,24 +208,35 @@ static int __devinit snd_opti9xx_init(struct snd_opti9xx *chip,
chip->hardware = hardware;
strcpy(chip->name, snd_opti9xx_names[hardware]);
- chip->mc_base_size = opti9xx_mc_size[hardware];
-
spin_lock_init(&chip->lock);
chip->irq = -1;
+#ifndef OPTi93X
+#ifdef CONFIG_PNP
+ if (isapnp && chip->mc_base)
+ /* PnP resource gives the least 10 bits */
+ chip->mc_base |= 0xc00;
+ else
+#endif /* CONFIG_PNP */
+ {
+ chip->mc_base = 0xf8c;
+ chip->mc_base_size = opti9xx_mc_size[hardware];
+ }
+#else
+ chip->mc_base_size = opti9xx_mc_size[hardware];
+#endif
+
switch (hardware) {
#ifndef OPTi93X
case OPTi9XX_HW_82C928:
case OPTi9XX_HW_82C929:
- chip->mc_base = 0xf8c;
chip->password = (hardware == OPTi9XX_HW_82C928) ? 0xe2 : 0xe3;
chip->pwd_reg = 3;
break;
case OPTi9XX_HW_82C924:
case OPTi9XX_HW_82C925:
- chip->mc_base = 0xf8c;
chip->password = 0xe5;
chip->pwd_reg = 3;
break;
@@ -292,7 +304,7 @@ static unsigned char snd_opti9xx_read(struct snd_opti9xx *chip,
spin_unlock_irqrestore(&chip->lock, flags);
return retval;
}
-
+
static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg,
unsigned char value)
{
@@ -341,7 +353,7 @@ static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg,
static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip,
- long wss_base,
+ long port,
int irq, int dma1, int dma2,
long mpu_port, int mpu_irq)
{
@@ -354,16 +366,23 @@ static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip,
switch (chip->hardware) {
#ifndef OPTi93X
case OPTi9XX_HW_82C924:
+ /* opti 929 mode (?), OPL3 clock output, audio enable */
snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(4), 0xf0, 0xfc);
+ /* enable wave audio */
snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x02);
case OPTi9XX_HW_82C925:
+ /* enable WSS mode */
snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80);
+ /* OPL3 FM synthesis */
snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2), 0x00, 0x20);
+ /* disable Sound Blaster IRQ and DMA */
snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(3), 0xf0, 0xff);
#ifdef CS4231
+ /* cs4231/4248 fix enabled */
snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02);
#else
+ /* cs4231/4248 fix disabled */
snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x00, 0x02);
#endif /* CS4231 */
break;
@@ -411,21 +430,26 @@ static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip,
return -EINVAL;
}
- switch (wss_base) {
- case 0x530:
+ /* PnP resource says it decodes only 10 bits of address */
+ switch (port & 0x3ff) {
+ case 0x130:
+ chip->wss_base = 0x530;
wss_base_bits = 0x00;
break;
- case 0x604:
+ case 0x204:
+ chip->wss_base = 0x604;
wss_base_bits = 0x03;
break;
- case 0xe80:
+ case 0x280:
+ chip->wss_base = 0xe80;
wss_base_bits = 0x01;
break;
- case 0xf40:
+ case 0x340:
+ chip->wss_base = 0xf40;
wss_base_bits = 0x02;
break;
default:
- snd_printk(KERN_WARNING "WSS port 0x%lx not valid\n", wss_base);
+ snd_printk(KERN_WARNING "WSS port 0x%lx not valid\n", port);
goto __skip_base;
}
snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), wss_base_bits << 4, 0x30);
@@ -487,7 +511,7 @@ __skip_base:
#endif /* CS4231 || OPTi93X */
#ifndef OPTi93X
- outb(irq_bits << 3 | dma_bits, wss_base);
+ outb(irq_bits << 3 | dma_bits, chip->wss_base);
#else /* OPTi93X */
snd_opti9xx_write(chip, OPTi9XX_MC_REG(3), (irq_bits << 3 | dma_bits));
#endif /* OPTi93X */
@@ -729,15 +753,15 @@ static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip,
{
struct pnp_dev *pdev;
int err;
+ struct pnp_dev *devmpu;
+#ifndef OPTi93X
+ struct pnp_dev *devmc;
+#endif
- chip->dev = pnp_request_card_device(card, pid->devs[0].id, NULL);
- if (chip->dev == NULL)
+ pdev = pnp_request_card_device(card, pid->devs[0].id, NULL);
+ if (pdev == NULL)
return -EBUSY;
- chip->devmpu = pnp_request_card_device(card, pid->devs[1].id, NULL);
-
- pdev = chip->dev;
-
err = pnp_activate_dev(pdev);
if (err < 0) {
snd_printk(KERN_ERR "AUDIO pnp configure failure: %d\n", err);
@@ -750,9 +774,24 @@ static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip,
chip->mc_indir_index = pnp_port_start(pdev, 3) + 2;
chip->mc_indir_size = pnp_port_len(pdev, 3) - 2;
#else
- if (pid->driver_data != 0x0924)
- port = pnp_port_start(pdev, 1);
+ devmc = pnp_request_card_device(card, pid->devs[2].id, NULL);
+ if (devmc == NULL)
+ return -EBUSY;
+
+ err = pnp_activate_dev(devmc);
+ if (err < 0) {
+ snd_printk(KERN_ERR "MC pnp configure failure: %d\n", err);
+ return err;
+ }
+
+ port = pnp_port_start(pdev, 1);
fm_port = pnp_port_start(pdev, 2) + 8;
+ /*
+ * The MC(0) is never accessed and card does not
+ * include it in the PnP resource range. OPTI93x include it.
+ */
+ chip->mc_base = pnp_port_start(devmc, 0) - 1;
+ chip->mc_base_size = pnp_port_len(devmc, 0) + 1;
#endif /* OPTi93X */
irq = pnp_irq(pdev, 0);
dma1 = pnp_dma(pdev, 0);
@@ -760,16 +799,16 @@ static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip,
dma2 = pnp_dma(pdev, 1);
#endif /* CS4231 || OPTi93X */
- pdev = chip->devmpu;
- if (pdev && mpu_port > 0) {
- err = pnp_activate_dev(pdev);
+ devmpu = pnp_request_card_device(card, pid->devs[1].id, NULL);
+
+ if (devmpu && mpu_port > 0) {
+ err = pnp_activate_dev(devmpu);
if (err < 0) {
- snd_printk(KERN_ERR "AUDIO pnp configure failure\n");
+ snd_printk(KERN_ERR "MPU401 pnp configure failure\n");
mpu_port = -1;
- chip->devmpu = NULL;
} else {
- mpu_port = pnp_port_start(pdev, 0);
- mpu_irq = pnp_irq(pdev, 0);
+ mpu_port = pnp_port_start(devmpu, 0);
+ mpu_irq = pnp_irq(devmpu, 0);
}
}
return pid->driver_data;
@@ -824,7 +863,7 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card)
if (error)
return error;
- error = snd_wss_create(card, port + 4, -1, irq, dma1, xdma2,
+ error = snd_wss_create(card, chip->wss_base + 4, -1, irq, dma1, xdma2,
#ifdef OPTi93X
WSS_HW_OPTI93X, WSS_HWSHARE_IRQ,
#else
@@ -865,10 +904,11 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card)
sprintf(card->shortname, "OPTi %s", card->driver);
#if defined(CS4231) || defined(OPTi93X)
sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d&%d",
- card->shortname, pcm->name, port + 4, irq, dma1, xdma2);
+ card->shortname, pcm->name,
+ chip->wss_base + 4, irq, dma1, xdma2);
#else
sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d",
- card->shortname, pcm->name, port + 4, irq, dma1);
+ card->shortname, pcm->name, chip->wss_base + 4, irq, dma1);
#endif /* CS4231 || OPTi93X */
if (mpu_port <= 0 || mpu_port == SNDRV_AUTO_PORT)
@@ -1062,9 +1102,6 @@ static int __devinit snd_opti9xx_pnp_probe(struct pnp_card_link *pcard,
snd_card_free(card);
return error;
}
- if (hw <= OPTi9XX_HW_82C930)
- chip->mc_base -= 0x80;
-
error = snd_opti9xx_read_check(chip);
if (error) {
snd_printk(KERN_ERR "OPTI chip not found\n");
diff --git a/sound/isa/sb/jazz16.c b/sound/isa/sb/jazz16.c
index 8d21a3f..8ccbcdd 100644
--- a/sound/isa/sb/jazz16.c
+++ b/sound/isa/sb/jazz16.c
@@ -14,6 +14,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/io.h>
+#include <linux/delay.h>
#include <asm/dma.h>
#include <linux/isa.h>
#include <sound/core.h>
diff --git a/sound/oss/coproc.h b/sound/oss/coproc.h
index 7306346..7bec21b 100644
--- a/sound/oss/coproc.h
+++ b/sound/oss/coproc.h
@@ -4,7 +4,7 @@
*/
/*
- * Coprocessor access types
+ * Coprocessor access types
*/
#define COPR_CUSTOM 0x0001 /* Custom applications */
#define COPR_MIDI 0x0002 /* MIDI (MPU-401) emulation */
diff --git a/sound/oss/sequencer.c b/sound/oss/sequencer.c
index c798746..e85789e 100644
--- a/sound/oss/sequencer.c
+++ b/sound/oss/sequencer.c
@@ -1631,8 +1631,6 @@ unsigned long compute_finetune(unsigned long base_freq, int bend, int range,
}
semitones = bend / 100;
- if (semitones > 99)
- semitones = 99;
cents = bend % 100;
amount = (int) (semitone_tuning[semitones] * multiplier * cent_tuning[cents]) / 10000;
diff --git a/sound/oss/v_midi.h b/sound/oss/v_midi.h
index 1b86cb4..08e2185 100644
--- a/sound/oss/v_midi.h
+++ b/sound/oss/v_midi.h
@@ -2,9 +2,9 @@ typedef struct vmidi_devc {
int dev;
/* State variables */
- int opened;
+ int opened;
spinlock_t lock;
-
+
/* MIDI fields */
int my_mididev;
int pair_mididev;
@@ -12,4 +12,3 @@ typedef struct vmidi_devc {
int intr_active;
void (*midi_input_intr) (int dev, unsigned char data);
} vmidi_devc;
-
diff --git a/sound/oss/vidc.c b/sound/oss/vidc.c
index 725fef0..a4127ba 100644
--- a/sound/oss/vidc.c
+++ b/sound/oss/vidc.c
@@ -363,13 +363,13 @@ static void vidc_audio_trigger(int dev, int enable_bits)
struct audio_operations *adev = audio_devs[dev];
if (enable_bits & PCM_ENABLE_OUTPUT) {
- if (!(adev->flags & DMA_ACTIVE)) {
+ if (!(adev->dmap_out->flags & DMA_ACTIVE)) {
unsigned long flags;
local_irq_save(flags);
/* prevent recusion */
- adev->flags |= DMA_ACTIVE;
+ adev->dmap_out->flags |= DMA_ACTIVE;
dma_interrupt = vidc_audio_dma_interrupt;
vidc_sound_dma_irq(0, NULL);
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
index 1caf5e3..e68c98e 100644
--- a/sound/pci/ac97/ac97_patch.c
+++ b/sound/pci/ac97/ac97_patch.c
@@ -1852,12 +1852,14 @@ static unsigned int ad1981_jacks_blacklist[] = {
0x10140523, /* Thinkpad R40 */
0x10140534, /* Thinkpad X31 */
0x10140537, /* Thinkpad T41p */
+ 0x1014053e, /* Thinkpad R40e */
0x10140554, /* Thinkpad T42p/R50p */
0x10140567, /* Thinkpad T43p 2668-G7U */
0x10140581, /* Thinkpad X41-2527 */
0x10280160, /* Dell Dimension 2400 */
0x104380b0, /* Asus A7V8X-MX */
0x11790241, /* Toshiba Satellite A-15 S127 */
+ 0x1179ff10, /* Toshiba P500 */
0x144dc01a, /* Samsung NP-X20C004/SEG */
0 /* end */
};
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
index 1ded64e..329968e 100644
--- a/sound/pci/cmipci.c
+++ b/sound/pci/cmipci.c
@@ -941,13 +941,21 @@ static snd_pcm_uframes_t snd_cmipci_pcm_pointer(struct cmipci *cm, struct cmipci
struct snd_pcm_substream *substream)
{
size_t ptr;
- unsigned int reg;
+ unsigned int reg, rem, tries;
+
if (!rec->running)
return 0;
#if 1 // this seems better..
reg = rec->ch ? CM_REG_CH1_FRAME2 : CM_REG_CH0_FRAME2;
- ptr = rec->dma_size - (snd_cmipci_read_w(cm, reg) + 1);
- ptr >>= rec->shift;
+ for (tries = 0; tries < 3; tries++) {
+ rem = snd_cmipci_read_w(cm, reg);
+ if (rem < rec->dma_size)
+ goto ok;
+ }
+ printk(KERN_ERR "cmipci: invalid PCM pointer: %#x\n", rem);
+ return SNDRV_PCM_POS_XRUN;
+ok:
+ ptr = (rec->dma_size - (rem + 1)) >> rec->shift;
#else
reg = rec->ch ? CM_REG_CH1_FRAME1 : CM_REG_CH0_FRAME1;
ptr = snd_cmipci_read(cm, reg) - rec->offset;
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig
index 556cff9..567348b 100644
--- a/sound/pci/hda/Kconfig
+++ b/sound/pci/hda/Kconfig
@@ -157,7 +157,7 @@ config SND_HDA_CODEC_INTELHDMI
config SND_HDA_ELD
def_bool y
- depends on SND_HDA_CODEC_INTELHDMI
+ depends on SND_HDA_CODEC_INTELHDMI || SND_HDA_CODEC_NVHDMI
config SND_HDA_CODEC_CIRRUS
bool "Build Cirrus Logic codec support"
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
index 315a1c4..24bc195 100644
--- a/sound/pci/hda/Makefile
+++ b/sound/pci/hda/Makefile
@@ -3,7 +3,7 @@ snd-hda-intel-objs := hda_intel.o
snd-hda-codec-y := hda_codec.o
snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o
snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o
-# snd-hda-codec-$(CONFIG_SND_HDA_ELD) += hda_eld.o
+snd-hda-codec-$(CONFIG_SND_HDA_ELD) += hda_eld.o
snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o
snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o
@@ -18,7 +18,7 @@ snd-hda-codec-ca0110-objs := patch_ca0110.o
snd-hda-codec-conexant-objs := patch_conexant.o
snd-hda-codec-via-objs := patch_via.o
snd-hda-codec-nvhdmi-objs := patch_nvhdmi.o
-snd-hda-codec-intelhdmi-objs := patch_intelhdmi.o hda_eld.o
+snd-hda-codec-intelhdmi-objs := patch_intelhdmi.o
# common driver
obj-$(CONFIG_SND_HDA_INTEL) := snd-hda-codec.o
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 76d3c4c..0e76ac2 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -978,8 +978,9 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
*
* Returns 0 if successful, or a negative error code.
*/
-int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
- struct hda_codec **codecp)
+int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus,
+ unsigned int codec_addr,
+ struct hda_codec **codecp)
{
struct hda_codec *codec;
char component[31];
@@ -1186,7 +1187,7 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream);
*/
/* FIXME: more better hash key? */
-#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24))
+#define HDA_HASH_KEY(nid, dir, idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24))
#define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24))
#define HDA_HASH_PARPCM_KEY(nid) (u32)((nid) + (0x03 << 24))
#define HDA_HASH_PARSTR_KEY(nid) (u32)((nid) + (0x04 << 24))
@@ -1356,7 +1357,8 @@ u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid)
if (!codec->no_trigger_sense) {
pincap = snd_hda_query_pin_caps(codec, nid);
if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */
- snd_hda_codec_read(codec, nid, 0, AC_VERB_SET_PIN_SENSE, 0);
+ snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_SET_PIN_SENSE, 0);
}
return snd_hda_codec_read(codec, nid, 0,
AC_VERB_GET_PIN_SENSE, 0);
@@ -1372,8 +1374,8 @@ EXPORT_SYMBOL_HDA(snd_hda_pin_sense);
*/
int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid)
{
- u32 sense = snd_hda_pin_sense(codec, nid);
- return !!(sense & AC_PINSENSE_PRESENCE);
+ u32 sense = snd_hda_pin_sense(codec, nid);
+ return !!(sense & AC_PINSENSE_PRESENCE);
}
EXPORT_SYMBOL_HDA(snd_hda_jack_detect);
@@ -1804,6 +1806,8 @@ int snd_hda_add_nid(struct hda_codec *codec, struct snd_kcontrol *kctl,
item->nid = nid;
return 0;
}
+ printk(KERN_ERR "hda-codec: no NID for mapping control %s:%d:%d\n",
+ kctl->id.name, kctl->id.index, index);
return -EINVAL;
}
EXPORT_SYMBOL_HDA(snd_hda_add_nid);
@@ -1952,7 +1956,7 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
err = snd_hda_ctl_add(codec, 0, kctl);
if (err < 0)
return err;
-
+
for (s = slaves; *s; s++) {
struct snd_kcontrol *sctl;
int i = 0;
@@ -2439,27 +2443,27 @@ static struct snd_kcontrol_new dig_mixes[] = {
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
+ .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, CON_MASK),
.info = snd_hda_spdif_mask_info,
.get = snd_hda_spdif_cmask_get,
},
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
+ .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PRO_MASK),
.info = snd_hda_spdif_mask_info,
.get = snd_hda_spdif_pmask_get,
},
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
+ .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
.info = snd_hda_spdif_mask_info,
.get = snd_hda_spdif_default_get,
.put = snd_hda_spdif_default_put,
},
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),
+ .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH),
.info = snd_hda_spdif_out_switch_info,
.get = snd_hda_spdif_out_switch_get,
.put = snd_hda_spdif_out_switch_put,
@@ -2610,7 +2614,7 @@ static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol,
static struct snd_kcontrol_new dig_in_ctls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
+ .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, SWITCH),
.info = snd_hda_spdif_in_switch_info,
.get = snd_hda_spdif_in_switch_get,
.put = snd_hda_spdif_in_switch_put,
@@ -2618,7 +2622,7 @@ static struct snd_kcontrol_new dig_in_ctls[] = {
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
+ .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT),
.info = snd_hda_spdif_mask_info,
.get = snd_hda_spdif_in_status_get,
},
@@ -2882,8 +2886,8 @@ int /*__devinit*/ snd_hda_build_controls(struct hda_bus *bus)
list_for_each_entry(codec, &bus->codec_list, list) {
int err = snd_hda_codec_build_controls(codec);
if (err < 0) {
- printk(KERN_ERR "hda_codec: cannot build controls"
- "for #%d (error %d)\n", codec->addr, err);
+ printk(KERN_ERR "hda_codec: cannot build controls "
+ "for #%d (error %d)\n", codec->addr, err);
err = snd_hda_codec_reset(codec);
if (err < 0) {
printk(KERN_ERR
@@ -2979,8 +2983,12 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
val |= channels - 1;
switch (snd_pcm_format_width(format)) {
- case 8: val |= 0x00; break;
- case 16: val |= 0x10; break;
+ case 8:
+ val |= 0x00;
+ break;
+ case 16:
+ val |= 0x10;
+ break;
case 20:
case 24:
case 32:
@@ -3298,7 +3306,8 @@ static int get_empty_pcm_device(struct hda_bus *bus, int type)
if (!test_and_set_bit(audio_idx[type][i], bus->pcm_dev_bits))
return audio_idx[type][i];
- snd_printk(KERN_WARNING "Too many %s devices\n", snd_hda_pcm_type_name[type]);
+ snd_printk(KERN_WARNING "Too many %s devices\n",
+ snd_hda_pcm_type_name[type]);
return -EAGAIN;
}
@@ -3336,7 +3345,7 @@ int snd_hda_codec_build_pcms(struct hda_codec *codec)
err = codec->patch_ops.build_pcms(codec);
if (err < 0) {
printk(KERN_ERR "hda_codec: cannot build PCMs"
- "for #%d (error %d)\n", codec->addr, err);
+ "for #%d (error %d)\n", codec->addr, err);
err = snd_hda_codec_reset(codec);
if (err < 0) {
printk(KERN_ERR
@@ -3466,8 +3475,8 @@ EXPORT_SYMBOL_HDA(snd_hda_check_board_config);
/**
* snd_hda_check_board_codec_sid_config - compare the current codec
- subsystem ID with the
- config table
+ subsystem ID with the
+ config table
This is important for Gateway notebooks with SB450 HDA Audio
where the vendor ID of the PCI device is:
@@ -3607,7 +3616,7 @@ void snd_hda_update_power_acct(struct hda_codec *codec)
*
* Increment the power-up counter and power up the hardware really when
* not turned on yet.
- */
+ */
void snd_hda_power_up(struct hda_codec *codec)
{
struct hda_bus *bus = codec->bus;
@@ -3636,7 +3645,7 @@ EXPORT_SYMBOL_HDA(snd_hda_power_up);
*
* Decrement the power-up counter and schedules the power-off work if
* the counter rearches to zero.
- */
+ */
void snd_hda_power_down(struct hda_codec *codec)
{
--codec->power_count;
@@ -3662,7 +3671,7 @@ EXPORT_SYMBOL_HDA(snd_hda_power_down);
*
* This function is supposed to be set or called from the check_power_status
* patch ops.
- */
+ */
int snd_hda_check_amp_list_power(struct hda_codec *codec,
struct hda_loopback_check *check,
hda_nid_t nid)
@@ -3830,7 +3839,7 @@ static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid,
{
/* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
- set_dig_out_convert(codec, nid,
+ set_dig_out_convert(codec, nid,
codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff,
-1);
snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
@@ -4089,13 +4098,13 @@ static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list)
/*
* Sort an associated group of pins according to their sequence numbers.
*/
-static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences,
+static void sort_pins_by_sequence(hda_nid_t *pins, short *sequences,
int num_pins)
{
int i, j;
short seq;
hda_nid_t nid;
-
+
for (i = 0; i < num_pins; i++) {
for (j = i + 1; j < num_pins; j++) {
if (sequences[i] > sequences[j]) {
@@ -4123,7 +4132,7 @@ static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences,
* is detected, one of speaker of HP pins is assigned as the primary
* output, i.e. to line_out_pins[0]. So, line_outs is always positive
* if any analog output exists.
- *
+ *
* The analog input pins are assigned to input_pins array.
* The digital input/output pins are assigned to dig_in_pin and dig_out_pin,
* respectively.
@@ -4186,9 +4195,9 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
case AC_JACK_SPEAKER:
seq = get_defcfg_sequence(def_conf);
assoc = get_defcfg_association(def_conf);
- if (! assoc)
+ if (!assoc)
continue;
- if (! assoc_speaker)
+ if (!assoc_speaker)
assoc_speaker = assoc;
else if (assoc_speaker != assoc)
continue;
@@ -4286,7 +4295,7 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
cfg->speaker_outs);
sort_pins_by_sequence(cfg->hp_pins, sequences_hp,
cfg->hp_outs);
-
+
/* if we have only one mic, make it AUTO_PIN_MIC */
if (!cfg->input_pins[AUTO_PIN_MIC] &&
cfg->input_pins[AUTO_PIN_FRONT_MIC]) {
@@ -4436,7 +4445,7 @@ EXPORT_SYMBOL_HDA(snd_hda_resume);
/**
* snd_array_new - get a new element from the given array
* @array: the array object
- *
+ *
* Get a new element from the given array. If it exceeds the
* pre-allocated array size, re-allocate the array.
*
diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c
index 4228f2f..dcd2244 100644
--- a/sound/pci/hda/hda_eld.c
+++ b/sound/pci/hda/hda_eld.c
@@ -331,6 +331,7 @@ int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid)
return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE,
AC_DIPSIZE_ELD_BUF);
}
+EXPORT_SYMBOL_HDA(snd_hdmi_get_eld_size);
int snd_hdmi_get_eld(struct hdmi_eld *eld,
struct hda_codec *codec, hda_nid_t nid)
@@ -366,6 +367,7 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld,
kfree(buf);
return ret;
}
+EXPORT_SYMBOL_HDA(snd_hdmi_get_eld);
static void hdmi_show_short_audio_desc(struct cea_sad *a)
{
@@ -404,6 +406,7 @@ void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen)
}
buf[j] = '\0'; /* necessary when j == 0 */
}
+EXPORT_SYMBOL_HDA(snd_print_channel_allocation);
void snd_hdmi_show_eld(struct hdmi_eld *e)
{
@@ -422,6 +425,7 @@ void snd_hdmi_show_eld(struct hdmi_eld *e)
for (i = 0; i < e->sad_count; i++)
hdmi_show_short_audio_desc(e->sad + i);
}
+EXPORT_SYMBOL_HDA(snd_hdmi_show_eld);
#ifdef CONFIG_PROC_FS
@@ -580,6 +584,7 @@ int snd_hda_eld_proc_new(struct hda_codec *codec, struct hdmi_eld *eld,
return 0;
}
+EXPORT_SYMBOL_HDA(snd_hda_eld_proc_new);
void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld)
{
@@ -588,5 +593,6 @@ void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld)
eld->proc_entry = NULL;
}
}
+EXPORT_SYMBOL_HDA(snd_hda_eld_proc_free);
#endif /* CONFIG_PROC_FS */
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index d5c93ad..4bb9067 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -267,7 +267,8 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
#define RIRB_INT_MASK 0x05
/* STATESTS int mask: S3,SD2,SD1,SD0 */
-#define AZX_MAX_CODECS 4
+#define AZX_MAX_CODECS 8
+#define AZX_DEFAULT_CODECS 4
#define STATESTS_INT_MASK ((1 << AZX_MAX_CODECS) - 1)
/* SD_CTL bits */
@@ -1367,6 +1368,7 @@ static void azx_bus_reset(struct hda_bus *bus)
/* number of codec slots for each chipset: 0 = default slots (i.e. 4) */
static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] __devinitdata = {
+ [AZX_DRIVER_NVIDIA] = 8,
[AZX_DRIVER_TERA] = 1,
};
@@ -1399,7 +1401,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model)
codecs = 0;
max_slots = azx_max_codecs[chip->driver_type];
if (!max_slots)
- max_slots = AZX_MAX_CODECS;
+ max_slots = AZX_DEFAULT_CODECS;
/* First try to probe all given codec slots */
for (c = 0; c < max_slots; c++) {
@@ -2263,10 +2265,14 @@ 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_LPIB),
SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB),
+ SND_PCI_QUIRK(0x1028, 0x01f6, "Dell Latitude 131L", POS_FIX_LPIB),
SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1106, 0x3288, "ASUS M2V-MX SE", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB),
+ SND_PCI_QUIRK(0x1458, 0xa022, "ga-ma770-ud3", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB),
+ SND_PCI_QUIRK(0x1565, 0x820f, "Biostar Microtech", POS_FIX_LPIB),
+ SND_PCI_QUIRK(0x8086, 0xd601, "eMachines T5212", POS_FIX_LPIB),
{}
};
@@ -2354,6 +2360,8 @@ static void __devinit check_probe_mask(struct azx *chip, int dev)
static struct snd_pci_quirk msi_black_list[] __devinitdata = {
SND_PCI_QUIRK(0x1043, 0x81f2, "ASUS", 0), /* Athlon64 X2 + nvidia */
SND_PCI_QUIRK(0x1043, 0x81f6, "ASUS", 0), /* nvidia */
+ SND_PCI_QUIRK(0x1043, 0x822d, "ASUS", 0), /* Athlon64 X2 + nvidia MCP55 */
+ SND_PCI_QUIRK(0x1849, 0x0888, "ASRock", 0), /* Athlon64 X2 + nvidia */
{}
};
@@ -2372,6 +2380,13 @@ static void __devinit check_msi(struct azx *chip)
"hda_intel: msi for device %04x:%04x set to %d\n",
q->subvendor, q->subdevice, q->value);
chip->msi = q->value;
+ return;
+ }
+
+ /* NVidia chipsets seem to cause troubles with MSI */
+ if (chip->driver_type == AZX_DRIVER_NVIDIA) {
+ printk(KERN_INFO "hda_intel: Disable MSI for Nvidia chipset\n");
+ chip->msi = 0;
}
}
@@ -2700,6 +2715,7 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
{ PCI_DEVICE(0x8086, 0x3a6e), .driver_data = AZX_DRIVER_ICH },
/* PCH */
{ PCI_DEVICE(0x8086, 0x3b56), .driver_data = AZX_DRIVER_ICH },
+ { PCI_DEVICE(0x8086, 0x3b57), .driver_data = AZX_DRIVER_ICH },
/* CPT */
{ PCI_DEVICE(0x8086, 0x1c20), .driver_data = AZX_DRIVER_PCH },
/* SCH */
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 194a28c..61682e1 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -1591,6 +1591,21 @@ static int patch_cxt5047(struct hda_codec *codec)
#endif
}
spec->vmaster_nid = 0x13;
+
+ switch (codec->subsystem_id >> 16) {
+ case 0x103c:
+ /* HP laptops have really bad sound over 0 dB on NID 0x10.
+ * Fix max PCM level to 0 dB (originally it has 0x1e steps
+ * with 0 dB offset 0x17)
+ */
+ snd_hda_override_amp_caps(codec, 0x10, HDA_INPUT,
+ (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
+ (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
+ (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
+ (1 << AC_AMPCAP_MUTE_SHIFT));
+ break;
+ }
+
return 0;
}
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
new file mode 100644
index 0000000..2c2bafb
--- /dev/null
+++ b/sound/pci/hda/patch_hdmi.c
@@ -0,0 +1,849 @@
+/*
+ *
+ * patch_hdmi.c - routines for HDMI/DisplayPort codecs
+ *
+ * Copyright(c) 2008-2010 Intel Corporation. All rights reserved.
+ *
+ * Authors:
+ * Wu Fengguang <wfg@linux.intel.com>
+ *
+ * Maintained by:
+ * Wu Fengguang <wfg@linux.intel.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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+struct hdmi_spec {
+ int num_cvts;
+ int num_pins;
+ hda_nid_t cvt[MAX_HDMI_CVTS+1]; /* audio sources */
+ hda_nid_t pin[MAX_HDMI_PINS+1]; /* audio sinks */
+
+ /*
+ * source connection for each pin
+ */
+ hda_nid_t pin_cvt[MAX_HDMI_PINS+1];
+
+ /*
+ * HDMI sink attached to each pin
+ */
+ struct hdmi_eld sink_eld[MAX_HDMI_PINS];
+
+ /*
+ * export one pcm per pipe
+ */
+ struct hda_pcm pcm_rec[MAX_HDMI_CVTS];
+
+ /*
+ * nvhdmi specific
+ */
+ struct hda_multi_out multiout;
+ unsigned int codec_type;
+};
+
+
+struct hdmi_audio_infoframe {
+ u8 type; /* 0x84 */
+ u8 ver; /* 0x01 */
+ u8 len; /* 0x0a */
+
+ u8 checksum; /* PB0 */
+ u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */
+ u8 SS01_SF24;
+ u8 CXT04;
+ u8 CA;
+ u8 LFEPBL01_LSV36_DM_INH7;
+ u8 reserved[5]; /* PB6 - PB10 */
+};
+
+/*
+ * CEA speaker placement:
+ *
+ * FLH FCH FRH
+ * FLW FL FLC FC FRC FR FRW
+ *
+ * LFE
+ * TC
+ *
+ * RL RLC RC RRC RR
+ *
+ * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to
+ * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC.
+ */
+enum cea_speaker_placement {
+ FL = (1 << 0), /* Front Left */
+ FC = (1 << 1), /* Front Center */
+ FR = (1 << 2), /* Front Right */
+ FLC = (1 << 3), /* Front Left Center */
+ FRC = (1 << 4), /* Front Right Center */
+ RL = (1 << 5), /* Rear Left */
+ RC = (1 << 6), /* Rear Center */
+ RR = (1 << 7), /* Rear Right */
+ RLC = (1 << 8), /* Rear Left Center */
+ RRC = (1 << 9), /* Rear Right Center */
+ LFE = (1 << 10), /* Low Frequency Effect */
+ FLW = (1 << 11), /* Front Left Wide */
+ FRW = (1 << 12), /* Front Right Wide */
+ FLH = (1 << 13), /* Front Left High */
+ FCH = (1 << 14), /* Front Center High */
+ FRH = (1 << 15), /* Front Right High */
+ TC = (1 << 16), /* Top Center */
+};
+
+/*
+ * ELD SA bits in the CEA Speaker Allocation data block
+ */
+static int eld_speaker_allocation_bits[] = {
+ [0] = FL | FR,
+ [1] = LFE,
+ [2] = FC,
+ [3] = RL | RR,
+ [4] = RC,
+ [5] = FLC | FRC,
+ [6] = RLC | RRC,
+ /* the following are not defined in ELD yet */
+ [7] = FLW | FRW,
+ [8] = FLH | FRH,
+ [9] = TC,
+ [10] = FCH,
+};
+
+struct cea_channel_speaker_allocation {
+ int ca_index;
+ int speakers[8];
+
+ /* derived values, just for convenience */
+ int channels;
+ int spk_mask;
+};
+
+/*
+ * ALSA sequence is:
+ *
+ * surround40 surround41 surround50 surround51 surround71
+ * ch0 front left = = = =
+ * ch1 front right = = = =
+ * ch2 rear left = = = =
+ * ch3 rear right = = = =
+ * ch4 LFE center center center
+ * ch5 LFE LFE
+ * ch6 side left
+ * ch7 side right
+ *
+ * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR}
+ */
+static int hdmi_channel_mapping[0x32][8] = {
+ /* stereo */
+ [0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
+ /* 2.1 */
+ [0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
+ /* Dolby Surround */
+ [0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 },
+ /* surround40 */
+ [0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 },
+ /* 4ch */
+ [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 },
+ /* surround41 */
+ [0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 },
+ /* surround50 */
+ [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 },
+ /* surround51 */
+ [0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 },
+ /* 7.1 */
+ [0x13] = { 0x00, 0x11, 0x26, 0x37, 0x43, 0x52, 0x64, 0x75 },
+};
+
+/*
+ * This is an ordered list!
+ *
+ * The preceding ones have better chances to be selected by
+ * hdmi_setup_channel_allocation().
+ */
+static struct cea_channel_speaker_allocation channel_allocations[] = {
+/* channel: 7 6 5 4 3 2 1 0 */
+{ .ca_index = 0x00, .speakers = { 0, 0, 0, 0, 0, 0, FR, FL } },
+ /* 2.1 */
+{ .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL } },
+ /* Dolby Surround */
+{ .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL } },
+ /* surround40 */
+{ .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } },
+ /* surround41 */
+{ .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } },
+ /* surround50 */
+{ .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } },
+ /* surround51 */
+{ .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } },
+ /* 6.1 */
+{ .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } },
+ /* surround71 */
+{ .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } },
+
+{ .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL } },
+{ .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL } },
+{ .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL } },
+{ .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL } },
+{ .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL } },
+{ .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL } },
+{ .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL } },
+{ .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL } },
+{ .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL } },
+{ .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL } },
+{ .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL } },
+{ .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL } },
+{ .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL } },
+{ .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL } },
+{ .ca_index = 0x17, .speakers = { FRC, FLC, 0, 0, FC, LFE, FR, FL } },
+{ .ca_index = 0x18, .speakers = { FRC, FLC, 0, RC, 0, 0, FR, FL } },
+{ .ca_index = 0x19, .speakers = { FRC, FLC, 0, RC, 0, LFE, FR, FL } },
+{ .ca_index = 0x1a, .speakers = { FRC, FLC, 0, RC, FC, 0, FR, FL } },
+{ .ca_index = 0x1b, .speakers = { FRC, FLC, 0, RC, FC, LFE, FR, FL } },
+{ .ca_index = 0x1c, .speakers = { FRC, FLC, RR, RL, 0, 0, FR, FL } },
+{ .ca_index = 0x1d, .speakers = { FRC, FLC, RR, RL, 0, LFE, FR, FL } },
+{ .ca_index = 0x1e, .speakers = { FRC, FLC, RR, RL, FC, 0, FR, FL } },
+{ .ca_index = 0x1f, .speakers = { FRC, FLC, RR, RL, FC, LFE, FR, FL } },
+{ .ca_index = 0x20, .speakers = { 0, FCH, RR, RL, FC, 0, FR, FL } },
+{ .ca_index = 0x21, .speakers = { 0, FCH, RR, RL, FC, LFE, FR, FL } },
+{ .ca_index = 0x22, .speakers = { TC, 0, RR, RL, FC, 0, FR, FL } },
+{ .ca_index = 0x23, .speakers = { TC, 0, RR, RL, FC, LFE, FR, FL } },
+{ .ca_index = 0x24, .speakers = { FRH, FLH, RR, RL, 0, 0, FR, FL } },
+{ .ca_index = 0x25, .speakers = { FRH, FLH, RR, RL, 0, LFE, FR, FL } },
+{ .ca_index = 0x26, .speakers = { FRW, FLW, RR, RL, 0, 0, FR, FL } },
+{ .ca_index = 0x27, .speakers = { FRW, FLW, RR, RL, 0, LFE, FR, FL } },
+{ .ca_index = 0x28, .speakers = { TC, RC, RR, RL, FC, 0, FR, FL } },
+{ .ca_index = 0x29, .speakers = { TC, RC, RR, RL, FC, LFE, FR, FL } },
+{ .ca_index = 0x2a, .speakers = { FCH, RC, RR, RL, FC, 0, FR, FL } },
+{ .ca_index = 0x2b, .speakers = { FCH, RC, RR, RL, FC, LFE, FR, FL } },
+{ .ca_index = 0x2c, .speakers = { TC, FCH, RR, RL, FC, 0, FR, FL } },
+{ .ca_index = 0x2d, .speakers = { TC, FCH, RR, RL, FC, LFE, FR, FL } },
+{ .ca_index = 0x2e, .speakers = { FRH, FLH, RR, RL, FC, 0, FR, FL } },
+{ .ca_index = 0x2f, .speakers = { FRH, FLH, RR, RL, FC, LFE, FR, FL } },
+{ .ca_index = 0x30, .speakers = { FRW, FLW, RR, RL, FC, 0, FR, FL } },
+{ .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } },
+};
+
+
+/*
+ * HDMI routines
+ */
+
+static int hda_node_index(hda_nid_t *nids, hda_nid_t nid)
+{
+ int i;
+
+ for (i = 0; nids[i]; i++)
+ if (nids[i] == nid)
+ return i;
+
+ snd_printk(KERN_WARNING "HDMI: nid %d not registered\n", nid);
+ return -EINVAL;
+}
+
+static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid,
+ struct hdmi_eld *eld)
+{
+ if (!snd_hdmi_get_eld(eld, codec, pin_nid))
+ snd_hdmi_show_eld(eld);
+}
+
+#ifdef BE_PARANOID
+static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
+ int *packet_index, int *byte_index)
+{
+ int val;
+
+ val = snd_hda_codec_read(codec, pin_nid, 0,
+ AC_VERB_GET_HDMI_DIP_INDEX, 0);
+
+ *packet_index = val >> 5;
+ *byte_index = val & 0x1f;
+}
+#endif
+
+static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
+ int packet_index, int byte_index)
+{
+ int val;
+
+ val = (packet_index << 5) | (byte_index & 0x1f);
+
+ snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val);
+}
+
+static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid,
+ unsigned char val)
+{
+ snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val);
+}
+
+static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+ /* Unmute */
+ if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP)
+ snd_hda_codec_write(codec, pin_nid, 0,
+ AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
+ /* Enable pin out */
+ snd_hda_codec_write(codec, pin_nid, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
+}
+
+static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid)
+{
+ return 1 + snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_CVT_CHAN_COUNT, 0);
+}
+
+static void hdmi_set_channel_count(struct hda_codec *codec,
+ hda_nid_t nid, int chs)
+{
+ if (chs != hdmi_get_channel_count(codec, nid))
+ snd_hda_codec_write(codec, nid, 0,
+ AC_VERB_SET_CVT_CHAN_COUNT, chs - 1);
+}
+
+
+/*
+ * Channel mapping routines
+ */
+
+/*
+ * Compute derived values in channel_allocations[].
+ */
+static void init_channel_allocations(void)
+{
+ int i, j;
+ struct cea_channel_speaker_allocation *p;
+
+ for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
+ p = channel_allocations + i;
+ p->channels = 0;
+ p->spk_mask = 0;
+ for (j = 0; j < ARRAY_SIZE(p->speakers); j++)
+ if (p->speakers[j]) {
+ p->channels++;
+ p->spk_mask |= p->speakers[j];
+ }
+ }
+}
+
+/*
+ * The transformation takes two steps:
+ *
+ * eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask
+ * spk_mask => (channel_allocations[]) => ai->CA
+ *
+ * TODO: it could select the wrong CA from multiple candidates.
+*/
+static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid,
+ struct hdmi_audio_infoframe *ai)
+{
+ struct hdmi_spec *spec = codec->spec;
+ struct hdmi_eld *eld;
+ int i;
+ int spk_mask = 0;
+ int channels = 1 + (ai->CC02_CT47 & 0x7);
+ char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
+
+ /*
+ * CA defaults to 0 for basic stereo audio
+ */
+ if (channels <= 2)
+ return 0;
+
+ i = hda_node_index(spec->pin_cvt, nid);
+ if (i < 0)
+ return 0;
+ eld = &spec->sink_eld[i];
+
+ /*
+ * HDMI sink's ELD info cannot always be retrieved for now, e.g.
+ * in console or for audio devices. Assume the highest speakers
+ * configuration, to _not_ prohibit multi-channel audio playback.
+ */
+ if (!eld->spk_alloc)
+ eld->spk_alloc = 0xffff;
+
+ /*
+ * expand ELD's speaker allocation mask
+ *
+ * ELD tells the speaker mask in a compact(paired) form,
+ * expand ELD's notions to match the ones used by Audio InfoFrame.
+ */
+ for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
+ if (eld->spk_alloc & (1 << i))
+ spk_mask |= eld_speaker_allocation_bits[i];
+ }
+
+ /* search for the first working match in the CA table */
+ for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
+ if (channels == channel_allocations[i].channels &&
+ (spk_mask & channel_allocations[i].spk_mask) ==
+ channel_allocations[i].spk_mask) {
+ ai->CA = channel_allocations[i].ca_index;
+ break;
+ }
+ }
+
+ snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf));
+ snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n",
+ ai->CA, channels, buf);
+
+ return ai->CA;
+}
+
+static void hdmi_debug_channel_mapping(struct hda_codec *codec,
+ hda_nid_t pin_nid)
+{
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+ int i;
+ int slot;
+
+ for (i = 0; i < 8; i++) {
+ slot = snd_hda_codec_read(codec, pin_nid, 0,
+ AC_VERB_GET_HDMI_CHAN_SLOT, i);
+ printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n",
+ slot >> 4, slot & 0xf);
+ }
+#endif
+}
+
+
+static void hdmi_setup_channel_mapping(struct hda_codec *codec,
+ hda_nid_t pin_nid,
+ struct hdmi_audio_infoframe *ai)
+{
+ int i;
+ int ca = ai->CA;
+ int err;
+
+ if (hdmi_channel_mapping[ca][1] == 0) {
+ for (i = 0; i < channel_allocations[ca].channels; i++)
+ hdmi_channel_mapping[ca][i] = i | (i << 4);
+ for (; i < 8; i++)
+ hdmi_channel_mapping[ca][i] = 0xf | (i << 4);
+ }
+
+ for (i = 0; i < 8; i++) {
+ err = snd_hda_codec_write(codec, pin_nid, 0,
+ AC_VERB_SET_HDMI_CHAN_SLOT,
+ hdmi_channel_mapping[ca][i]);
+ if (err) {
+ snd_printdd(KERN_NOTICE
+ "HDMI: channel mapping failed\n");
+ break;
+ }
+ }
+
+ hdmi_debug_channel_mapping(codec, pin_nid);
+}
+
+
+/*
+ * Audio InfoFrame routines
+ */
+
+/*
+ * Enable Audio InfoFrame Transmission
+ */
+static void hdmi_start_infoframe_trans(struct hda_codec *codec,
+ hda_nid_t pin_nid)
+{
+ hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
+ snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
+ AC_DIPXMIT_BEST);
+}
+
+/*
+ * Disable Audio InfoFrame Transmission
+ */
+static void hdmi_stop_infoframe_trans(struct hda_codec *codec,
+ hda_nid_t pin_nid)
+{
+ hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
+ snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
+ AC_DIPXMIT_DISABLE);
+}
+
+static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+ int i;
+ int size;
+
+ size = snd_hdmi_get_eld_size(codec, pin_nid);
+ printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size);
+
+ for (i = 0; i < 8; i++) {
+ size = snd_hda_codec_read(codec, pin_nid, 0,
+ AC_VERB_GET_HDMI_DIP_SIZE, i);
+ printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size);
+ }
+#endif
+}
+
+static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+#ifdef BE_PARANOID
+ int i, j;
+ int size;
+ int pi, bi;
+ for (i = 0; i < 8; i++) {
+ size = snd_hda_codec_read(codec, pin_nid, 0,
+ AC_VERB_GET_HDMI_DIP_SIZE, i);
+ if (size == 0)
+ continue;
+
+ hdmi_set_dip_index(codec, pin_nid, i, 0x0);
+ for (j = 1; j < 1000; j++) {
+ hdmi_write_dip_byte(codec, pin_nid, 0x0);
+ hdmi_get_dip_index(codec, pin_nid, &pi, &bi);
+ if (pi != i)
+ snd_printd(KERN_INFO "dip index %d: %d != %d\n",
+ bi, pi, i);
+ if (bi == 0) /* byte index wrapped around */
+ break;
+ }
+ snd_printd(KERN_INFO
+ "HDMI: DIP GP[%d] buf reported size=%d, written=%d\n",
+ i, size, j);
+ }
+#endif
+}
+
+static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai)
+{
+ u8 *bytes = (u8 *)ai;
+ u8 sum = 0;
+ int i;
+
+ ai->checksum = 0;
+
+ for (i = 0; i < sizeof(*ai); i++)
+ sum += bytes[i];
+
+ ai->checksum = -sum;
+}
+
+static void hdmi_fill_audio_infoframe(struct hda_codec *codec,
+ hda_nid_t pin_nid,
+ struct hdmi_audio_infoframe *ai)
+{
+ u8 *bytes = (u8 *)ai;
+ int i;
+
+ hdmi_debug_dip_size(codec, pin_nid);
+ hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */
+
+ hdmi_checksum_audio_infoframe(ai);
+
+ hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
+ for (i = 0; i < sizeof(*ai); i++)
+ hdmi_write_dip_byte(codec, pin_nid, bytes[i]);
+}
+
+static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid,
+ struct hdmi_audio_infoframe *ai)
+{
+ u8 *bytes = (u8 *)ai;
+ u8 val;
+ int i;
+
+ if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0)
+ != AC_DIPXMIT_BEST)
+ return false;
+
+ hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
+ for (i = 0; i < sizeof(*ai); i++) {
+ val = snd_hda_codec_read(codec, pin_nid, 0,
+ AC_VERB_GET_HDMI_DIP_DATA, 0);
+ if (val != bytes[i])
+ return false;
+ }
+
+ return true;
+}
+
+static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
+ struct snd_pcm_substream *substream)
+{
+ struct hdmi_spec *spec = codec->spec;
+ hda_nid_t pin_nid;
+ int i;
+ struct hdmi_audio_infoframe ai = {
+ .type = 0x84,
+ .ver = 0x01,
+ .len = 0x0a,
+ .CC02_CT47 = substream->runtime->channels - 1,
+ };
+
+ hdmi_setup_channel_allocation(codec, nid, &ai);
+
+ for (i = 0; i < spec->num_pins; i++) {
+ if (spec->pin_cvt[i] != nid)
+ continue;
+ if (!spec->sink_eld[i].monitor_present)
+ continue;
+
+ pin_nid = spec->pin[i];
+ if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) {
+ snd_printdd("hdmi_setup_audio_infoframe: "
+ "cvt=%d pin=%d channels=%d\n",
+ nid, pin_nid,
+ substream->runtime->channels);
+ hdmi_setup_channel_mapping(codec, pin_nid, &ai);
+ hdmi_stop_infoframe_trans(codec, pin_nid);
+ hdmi_fill_audio_infoframe(codec, pin_nid, &ai);
+ hdmi_start_infoframe_trans(codec, pin_nid);
+ }
+ }
+}
+
+
+/*
+ * Unsolicited events
+ */
+
+static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
+{
+ struct hdmi_spec *spec = codec->spec;
+ int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
+ int pind = !!(res & AC_UNSOL_RES_PD);
+ int eldv = !!(res & AC_UNSOL_RES_ELDV);
+ int index;
+
+ printk(KERN_INFO
+ "HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
+ tag, pind, eldv);
+
+ index = hda_node_index(spec->pin, tag);
+ if (index < 0)
+ return;
+
+ spec->sink_eld[index].monitor_present = pind;
+ spec->sink_eld[index].eld_valid = eldv;
+
+ if (pind && eldv) {
+ hdmi_get_show_eld(codec, spec->pin[index],
+ &spec->sink_eld[index]);
+ /* TODO: do real things about ELD */
+ }
+}
+
+static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
+{
+ int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
+ int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
+ int cp_state = !!(res & AC_UNSOL_RES_CP_STATE);
+ int cp_ready = !!(res & AC_UNSOL_RES_CP_READY);
+
+ printk(KERN_INFO
+ "HDMI CP event: PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n",
+ tag,
+ subtag,
+ cp_state,
+ cp_ready);
+
+ /* TODO */
+ if (cp_state)
+ ;
+ if (cp_ready)
+ ;
+}
+
+
+static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+ struct hdmi_spec *spec = codec->spec;
+ int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
+ int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
+
+ if (hda_node_index(spec->pin, tag) < 0) {
+ snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag);
+ return;
+ }
+
+ if (subtag == 0)
+ hdmi_intrinsic_event(codec, res);
+ else
+ hdmi_non_intrinsic_event(codec, res);
+}
+
+/*
+ * Callbacks
+ */
+
+static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid,
+ u32 stream_tag, int format)
+{
+ int tag;
+ int fmt;
+
+ tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4;
+ fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0);
+
+ snd_printdd("hdmi_setup_stream: "
+ "NID=0x%x, %sstream=0x%x, %sformat=0x%x\n",
+ nid,
+ tag == stream_tag ? "" : "new-",
+ stream_tag,
+ fmt == format ? "" : "new-",
+ format);
+
+ if (tag != stream_tag)
+ snd_hda_codec_write(codec, nid, 0,
+ AC_VERB_SET_CHANNEL_STREAMID,
+ stream_tag << 4);
+ if (fmt != format)
+ snd_hda_codec_write(codec, nid, 0,
+ AC_VERB_SET_STREAM_FORMAT, format);
+}
+
+/*
+ * HDA/HDMI auto parsing
+ */
+
+static int hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+ struct hdmi_spec *spec = codec->spec;
+ hda_nid_t conn_list[HDA_MAX_CONNECTIONS];
+ int conn_len, curr;
+ int index;
+
+ if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) {
+ snd_printk(KERN_WARNING
+ "HDMI: pin %d wcaps %#x "
+ "does not support connection list\n",
+ pin_nid, get_wcaps(codec, pin_nid));
+ return -EINVAL;
+ }
+
+ conn_len = snd_hda_get_connections(codec, pin_nid, conn_list,
+ HDA_MAX_CONNECTIONS);
+ if (conn_len > 1)
+ curr = snd_hda_codec_read(codec, pin_nid, 0,
+ AC_VERB_GET_CONNECT_SEL, 0);
+ else
+ curr = 0;
+
+ index = hda_node_index(spec->pin, pin_nid);
+ if (index < 0)
+ return -EINVAL;
+
+ spec->pin_cvt[index] = conn_list[curr];
+
+ return 0;
+}
+
+static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
+ struct hdmi_eld *eld)
+{
+ int present = snd_hda_pin_sense(codec, pin_nid);
+
+ eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE);
+ eld->eld_valid = !!(present & AC_PINSENSE_ELDV);
+
+ if (present & AC_PINSENSE_ELDV)
+ hdmi_get_show_eld(codec, pin_nid, eld);
+}
+
+static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+ struct hdmi_spec *spec = codec->spec;
+
+ if (spec->num_pins >= MAX_HDMI_PINS) {
+ snd_printk(KERN_WARNING
+ "HDMI: no space for pin %d\n", pin_nid);
+ return -EINVAL;
+ }
+
+ hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]);
+
+ spec->pin[spec->num_pins] = pin_nid;
+ spec->num_pins++;
+
+ /*
+ * It is assumed that converter nodes come first in the node list and
+ * hence have been registered and usable now.
+ */
+ return hdmi_read_pin_conn(codec, pin_nid);
+}
+
+static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid)
+{
+ struct hdmi_spec *spec = codec->spec;
+
+ if (spec->num_cvts >= MAX_HDMI_CVTS) {
+ snd_printk(KERN_WARNING
+ "HDMI: no space for converter %d\n", nid);
+ return -EINVAL;
+ }
+
+ spec->cvt[spec->num_cvts] = nid;
+ spec->num_cvts++;
+
+ return 0;
+}
+
+static int hdmi_parse_codec(struct hda_codec *codec)
+{
+ hda_nid_t nid;
+ int i, nodes;
+
+ nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
+ if (!nid || nodes < 0) {
+ snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < nodes; i++, nid++) {
+ unsigned int caps;
+ unsigned int type;
+
+ caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
+ type = get_wcaps_type(caps);
+
+ if (!(caps & AC_WCAP_DIGITAL))
+ continue;
+
+ switch (type) {
+ case AC_WID_AUD_OUT:
+ if (hdmi_add_cvt(codec, nid) < 0)
+ return -EINVAL;
+ break;
+ case AC_WID_PIN:
+ caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
+ if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP)))
+ continue;
+ if (hdmi_add_pin(codec, nid) < 0)
+ return -EINVAL;
+ break;
+ }
+ }
+
+ /*
+ * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event
+ * can be lost and presence sense verb will become inaccurate if the
+ * HDA link is powered off at hot plug or hw initialization time.
+ */
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) &
+ AC_PWRST_EPSS))
+ codec->bus->power_keep_link_on = 1;
+#endif
+
+ return 0;
+}
+
diff --git a/sound/pci/hda/patch_intelhdmi.c b/sound/pci/hda/patch_intelhdmi.c
index 918f403..88d0351 100644
--- a/sound/pci/hda/patch_intelhdmi.c
+++ b/sound/pci/hda/patch_intelhdmi.c
@@ -40,815 +40,20 @@
*
* The HDA correspondence of pipes/ports are converter/pin nodes.
*/
-#define INTEL_HDMI_CVTS 2
-#define INTEL_HDMI_PINS 3
+#define MAX_HDMI_CVTS 2
+#define MAX_HDMI_PINS 3
-static char *intel_hdmi_pcm_names[INTEL_HDMI_CVTS] = {
+#include "patch_hdmi.c"
+
+static char *intel_hdmi_pcm_names[MAX_HDMI_CVTS] = {
"INTEL HDMI 0",
"INTEL HDMI 1",
};
-struct intel_hdmi_spec {
- int num_cvts;
- int num_pins;
- hda_nid_t cvt[INTEL_HDMI_CVTS+1]; /* audio sources */
- hda_nid_t pin[INTEL_HDMI_PINS+1]; /* audio sinks */
-
- /*
- * source connection for each pin
- */
- hda_nid_t pin_cvt[INTEL_HDMI_PINS+1];
-
- /*
- * HDMI sink attached to each pin
- */
- struct hdmi_eld sink_eld[INTEL_HDMI_PINS];
-
- /*
- * export one pcm per pipe
- */
- struct hda_pcm pcm_rec[INTEL_HDMI_CVTS];
-};
-
-struct hdmi_audio_infoframe {
- u8 type; /* 0x84 */
- u8 ver; /* 0x01 */
- u8 len; /* 0x0a */
-
- u8 checksum; /* PB0 */
- u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */
- u8 SS01_SF24;
- u8 CXT04;
- u8 CA;
- u8 LFEPBL01_LSV36_DM_INH7;
- u8 reserved[5]; /* PB6 - PB10 */
-};
-
-/*
- * CEA speaker placement:
- *
- * FLH FCH FRH
- * FLW FL FLC FC FRC FR FRW
- *
- * LFE
- * TC
- *
- * RL RLC RC RRC RR
- *
- * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to
- * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC.
- */
-enum cea_speaker_placement {
- FL = (1 << 0), /* Front Left */
- FC = (1 << 1), /* Front Center */
- FR = (1 << 2), /* Front Right */
- FLC = (1 << 3), /* Front Left Center */
- FRC = (1 << 4), /* Front Right Center */
- RL = (1 << 5), /* Rear Left */
- RC = (1 << 6), /* Rear Center */
- RR = (1 << 7), /* Rear Right */
- RLC = (1 << 8), /* Rear Left Center */
- RRC = (1 << 9), /* Rear Right Center */
- LFE = (1 << 10), /* Low Frequency Effect */
- FLW = (1 << 11), /* Front Left Wide */
- FRW = (1 << 12), /* Front Right Wide */
- FLH = (1 << 13), /* Front Left High */
- FCH = (1 << 14), /* Front Center High */
- FRH = (1 << 15), /* Front Right High */
- TC = (1 << 16), /* Top Center */
-};
-
-/*
- * ELD SA bits in the CEA Speaker Allocation data block
- */
-static int eld_speaker_allocation_bits[] = {
- [0] = FL | FR,
- [1] = LFE,
- [2] = FC,
- [3] = RL | RR,
- [4] = RC,
- [5] = FLC | FRC,
- [6] = RLC | RRC,
- /* the following are not defined in ELD yet */
- [7] = FLW | FRW,
- [8] = FLH | FRH,
- [9] = TC,
- [10] = FCH,
-};
-
-struct cea_channel_speaker_allocation {
- int ca_index;
- int speakers[8];
-
- /* derived values, just for convenience */
- int channels;
- int spk_mask;
-};
-
-/*
- * ALSA sequence is:
- *
- * surround40 surround41 surround50 surround51 surround71
- * ch0 front left = = = =
- * ch1 front right = = = =
- * ch2 rear left = = = =
- * ch3 rear right = = = =
- * ch4 LFE center center center
- * ch5 LFE LFE
- * ch6 side left
- * ch7 side right
- *
- * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR}
- */
-static int hdmi_channel_mapping[0x32][8] = {
- /* stereo */
- [0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
- /* 2.1 */
- [0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
- /* Dolby Surround */
- [0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 },
- /* surround40 */
- [0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 },
- /* 4ch */
- [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 },
- /* surround41 */
- [0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 },
- /* surround50 */
- [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 },
- /* surround51 */
- [0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 },
- /* 7.1 */
- [0x13] = { 0x00, 0x11, 0x26, 0x37, 0x43, 0x52, 0x64, 0x75 },
-};
-
-/*
- * This is an ordered list!
- *
- * The preceding ones have better chances to be selected by
- * hdmi_setup_channel_allocation().
- */
-static struct cea_channel_speaker_allocation channel_allocations[] = {
-/* channel: 7 6 5 4 3 2 1 0 */
-{ .ca_index = 0x00, .speakers = { 0, 0, 0, 0, 0, 0, FR, FL } },
- /* 2.1 */
-{ .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL } },
- /* Dolby Surround */
-{ .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL } },
- /* surround40 */
-{ .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } },
- /* surround41 */
-{ .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } },
- /* surround50 */
-{ .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } },
- /* surround51 */
-{ .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } },
- /* 6.1 */
-{ .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } },
- /* surround71 */
-{ .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } },
-
-{ .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL } },
-{ .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL } },
-{ .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL } },
-{ .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL } },
-{ .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL } },
-{ .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL } },
-{ .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL } },
-{ .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL } },
-{ .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL } },
-{ .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL } },
-{ .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL } },
-{ .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL } },
-{ .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL } },
-{ .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL } },
-{ .ca_index = 0x17, .speakers = { FRC, FLC, 0, 0, FC, LFE, FR, FL } },
-{ .ca_index = 0x18, .speakers = { FRC, FLC, 0, RC, 0, 0, FR, FL } },
-{ .ca_index = 0x19, .speakers = { FRC, FLC, 0, RC, 0, LFE, FR, FL } },
-{ .ca_index = 0x1a, .speakers = { FRC, FLC, 0, RC, FC, 0, FR, FL } },
-{ .ca_index = 0x1b, .speakers = { FRC, FLC, 0, RC, FC, LFE, FR, FL } },
-{ .ca_index = 0x1c, .speakers = { FRC, FLC, RR, RL, 0, 0, FR, FL } },
-{ .ca_index = 0x1d, .speakers = { FRC, FLC, RR, RL, 0, LFE, FR, FL } },
-{ .ca_index = 0x1e, .speakers = { FRC, FLC, RR, RL, FC, 0, FR, FL } },
-{ .ca_index = 0x1f, .speakers = { FRC, FLC, RR, RL, FC, LFE, FR, FL } },
-{ .ca_index = 0x20, .speakers = { 0, FCH, RR, RL, FC, 0, FR, FL } },
-{ .ca_index = 0x21, .speakers = { 0, FCH, RR, RL, FC, LFE, FR, FL } },
-{ .ca_index = 0x22, .speakers = { TC, 0, RR, RL, FC, 0, FR, FL } },
-{ .ca_index = 0x23, .speakers = { TC, 0, RR, RL, FC, LFE, FR, FL } },
-{ .ca_index = 0x24, .speakers = { FRH, FLH, RR, RL, 0, 0, FR, FL } },
-{ .ca_index = 0x25, .speakers = { FRH, FLH, RR, RL, 0, LFE, FR, FL } },
-{ .ca_index = 0x26, .speakers = { FRW, FLW, RR, RL, 0, 0, FR, FL } },
-{ .ca_index = 0x27, .speakers = { FRW, FLW, RR, RL, 0, LFE, FR, FL } },
-{ .ca_index = 0x28, .speakers = { TC, RC, RR, RL, FC, 0, FR, FL } },
-{ .ca_index = 0x29, .speakers = { TC, RC, RR, RL, FC, LFE, FR, FL } },
-{ .ca_index = 0x2a, .speakers = { FCH, RC, RR, RL, FC, 0, FR, FL } },
-{ .ca_index = 0x2b, .speakers = { FCH, RC, RR, RL, FC, LFE, FR, FL } },
-{ .ca_index = 0x2c, .speakers = { TC, FCH, RR, RL, FC, 0, FR, FL } },
-{ .ca_index = 0x2d, .speakers = { TC, FCH, RR, RL, FC, LFE, FR, FL } },
-{ .ca_index = 0x2e, .speakers = { FRH, FLH, RR, RL, FC, 0, FR, FL } },
-{ .ca_index = 0x2f, .speakers = { FRH, FLH, RR, RL, FC, LFE, FR, FL } },
-{ .ca_index = 0x30, .speakers = { FRW, FLW, RR, RL, FC, 0, FR, FL } },
-{ .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } },
-};
-
-/*
- * HDA/HDMI auto parsing
- */
-
-static int hda_node_index(hda_nid_t *nids, hda_nid_t nid)
-{
- int i;
-
- for (i = 0; nids[i]; i++)
- if (nids[i] == nid)
- return i;
-
- snd_printk(KERN_WARNING "HDMI: nid %d not registered\n", nid);
- return -EINVAL;
-}
-
-static int intel_hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid)
-{
- struct intel_hdmi_spec *spec = codec->spec;
- hda_nid_t conn_list[HDA_MAX_CONNECTIONS];
- int conn_len, curr;
- int index;
-
- if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) {
- snd_printk(KERN_WARNING
- "HDMI: pin %d wcaps %#x "
- "does not support connection list\n",
- pin_nid, get_wcaps(codec, pin_nid));
- return -EINVAL;
- }
-
- conn_len = snd_hda_get_connections(codec, pin_nid, conn_list,
- HDA_MAX_CONNECTIONS);
- if (conn_len > 1)
- curr = snd_hda_codec_read(codec, pin_nid, 0,
- AC_VERB_GET_CONNECT_SEL, 0);
- else
- curr = 0;
-
- index = hda_node_index(spec->pin, pin_nid);
- if (index < 0)
- return -EINVAL;
-
- spec->pin_cvt[index] = conn_list[curr];
-
- return 0;
-}
-
-static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid,
- struct hdmi_eld *eld)
-{
- if (!snd_hdmi_get_eld(eld, codec, pin_nid))
- snd_hdmi_show_eld(eld);
-}
-
-static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
- struct hdmi_eld *eld)
-{
- int present = snd_hda_pin_sense(codec, pin_nid);
-
- eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE);
- eld->eld_valid = !!(present & AC_PINSENSE_ELDV);
-
- if (present & AC_PINSENSE_ELDV)
- hdmi_get_show_eld(codec, pin_nid, eld);
-}
-
-static int intel_hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
-{
- struct intel_hdmi_spec *spec = codec->spec;
-
- if (spec->num_pins >= INTEL_HDMI_PINS) {
- snd_printk(KERN_WARNING
- "HDMI: no space for pin %d \n", pin_nid);
- return -EINVAL;
- }
-
- hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]);
-
- spec->pin[spec->num_pins] = pin_nid;
- spec->num_pins++;
-
- /*
- * It is assumed that converter nodes come first in the node list and
- * hence have been registered and usable now.
- */
- return intel_hdmi_read_pin_conn(codec, pin_nid);
-}
-
-static int intel_hdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid)
-{
- struct intel_hdmi_spec *spec = codec->spec;
-
- if (spec->num_cvts >= INTEL_HDMI_CVTS) {
- snd_printk(KERN_WARNING
- "HDMI: no space for converter %d \n", nid);
- return -EINVAL;
- }
-
- spec->cvt[spec->num_cvts] = nid;
- spec->num_cvts++;
-
- return 0;
-}
-
-static int intel_hdmi_parse_codec(struct hda_codec *codec)
-{
- hda_nid_t nid;
- int i, nodes;
-
- nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
- if (!nid || nodes < 0) {
- snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n");
- return -EINVAL;
- }
-
- for (i = 0; i < nodes; i++, nid++) {
- unsigned int caps;
- unsigned int type;
-
- caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
- type = get_wcaps_type(caps);
-
- if (!(caps & AC_WCAP_DIGITAL))
- continue;
-
- switch (type) {
- case AC_WID_AUD_OUT:
- if (intel_hdmi_add_cvt(codec, nid) < 0)
- return -EINVAL;
- break;
- case AC_WID_PIN:
- caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
- if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP)))
- continue;
- if (intel_hdmi_add_pin(codec, nid) < 0)
- return -EINVAL;
- break;
- }
- }
-
- /*
- * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event
- * can be lost and presence sense verb will become inaccurate if the
- * HDA link is powered off at hot plug or hw initialization time.
- */
-#ifdef CONFIG_SND_HDA_POWER_SAVE
- if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) &
- AC_PWRST_EPSS))
- codec->bus->power_keep_link_on = 1;
-#endif
-
- return 0;
-}
-
-/*
- * HDMI routines
- */
-
-#ifdef BE_PARANOID
-static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
- int *packet_index, int *byte_index)
-{
- int val;
-
- val = snd_hda_codec_read(codec, pin_nid, 0,
- AC_VERB_GET_HDMI_DIP_INDEX, 0);
-
- *packet_index = val >> 5;
- *byte_index = val & 0x1f;
-}
-#endif
-
-static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
- int packet_index, int byte_index)
-{
- int val;
-
- val = (packet_index << 5) | (byte_index & 0x1f);
-
- snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val);
-}
-
-static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid,
- unsigned char val)
-{
- snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val);
-}
-
-static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid)
-{
- /* Unmute */
- if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP)
- snd_hda_codec_write(codec, pin_nid, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
- /* Enable pin out */
- snd_hda_codec_write(codec, pin_nid, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
-}
-
-/*
- * Enable Audio InfoFrame Transmission
- */
-static void hdmi_start_infoframe_trans(struct hda_codec *codec,
- hda_nid_t pin_nid)
-{
- hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
- snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
- AC_DIPXMIT_BEST);
-}
-
-/*
- * Disable Audio InfoFrame Transmission
- */
-static void hdmi_stop_infoframe_trans(struct hda_codec *codec,
- hda_nid_t pin_nid)
-{
- hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
- snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
- AC_DIPXMIT_DISABLE);
-}
-
-static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid)
-{
- return 1 + snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_CVT_CHAN_COUNT, 0);
-}
-
-static void hdmi_set_channel_count(struct hda_codec *codec,
- hda_nid_t nid, int chs)
-{
- if (chs != hdmi_get_channel_count(codec, nid))
- snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_CVT_CHAN_COUNT, chs - 1);
-}
-
-static void hdmi_debug_channel_mapping(struct hda_codec *codec,
- hda_nid_t pin_nid)
-{
-#ifdef CONFIG_SND_DEBUG_VERBOSE
- int i;
- int slot;
-
- for (i = 0; i < 8; i++) {
- slot = snd_hda_codec_read(codec, pin_nid, 0,
- AC_VERB_GET_HDMI_CHAN_SLOT, i);
- printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n",
- slot >> 4, slot & 0xf);
- }
-#endif
-}
-
-
-/*
- * Audio InfoFrame routines
- */
-
-static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-#ifdef CONFIG_SND_DEBUG_VERBOSE
- int i;
- int size;
-
- size = snd_hdmi_get_eld_size(codec, pin_nid);
- printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size);
-
- for (i = 0; i < 8; i++) {
- size = snd_hda_codec_read(codec, pin_nid, 0,
- AC_VERB_GET_HDMI_DIP_SIZE, i);
- printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size);
- }
-#endif
-}
-
-static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-#ifdef BE_PARANOID
- int i, j;
- int size;
- int pi, bi;
- for (i = 0; i < 8; i++) {
- size = snd_hda_codec_read(codec, pin_nid, 0,
- AC_VERB_GET_HDMI_DIP_SIZE, i);
- if (size == 0)
- continue;
-
- hdmi_set_dip_index(codec, pin_nid, i, 0x0);
- for (j = 1; j < 1000; j++) {
- hdmi_write_dip_byte(codec, pin_nid, 0x0);
- hdmi_get_dip_index(codec, pin_nid, &pi, &bi);
- if (pi != i)
- snd_printd(KERN_INFO "dip index %d: %d != %d\n",
- bi, pi, i);
- if (bi == 0) /* byte index wrapped around */
- break;
- }
- snd_printd(KERN_INFO
- "HDMI: DIP GP[%d] buf reported size=%d, written=%d\n",
- i, size, j);
- }
-#endif
-}
-
-static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai)
-{
- u8 *bytes = (u8 *)ai;
- u8 sum = 0;
- int i;
-
- ai->checksum = 0;
-
- for (i = 0; i < sizeof(*ai); i++)
- sum += bytes[i];
-
- ai->checksum = - sum;
-}
-
-static void hdmi_fill_audio_infoframe(struct hda_codec *codec,
- hda_nid_t pin_nid,
- struct hdmi_audio_infoframe *ai)
-{
- u8 *bytes = (u8 *)ai;
- int i;
-
- hdmi_debug_dip_size(codec, pin_nid);
- hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */
-
- hdmi_checksum_audio_infoframe(ai);
-
- hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
- for (i = 0; i < sizeof(*ai); i++)
- hdmi_write_dip_byte(codec, pin_nid, bytes[i]);
-}
-
-/*
- * Compute derived values in channel_allocations[].
- */
-static void init_channel_allocations(void)
-{
- int i, j;
- struct cea_channel_speaker_allocation *p;
-
- for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
- p = channel_allocations + i;
- p->channels = 0;
- p->spk_mask = 0;
- for (j = 0; j < ARRAY_SIZE(p->speakers); j++)
- if (p->speakers[j]) {
- p->channels++;
- p->spk_mask |= p->speakers[j];
- }
- }
-}
-
-/*
- * The transformation takes two steps:
- *
- * eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask
- * spk_mask => (channel_allocations[]) => ai->CA
- *
- * TODO: it could select the wrong CA from multiple candidates.
-*/
-static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid,
- struct hdmi_audio_infoframe *ai)
-{
- struct intel_hdmi_spec *spec = codec->spec;
- struct hdmi_eld *eld;
- int i;
- int spk_mask = 0;
- int channels = 1 + (ai->CC02_CT47 & 0x7);
- char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
-
- /*
- * CA defaults to 0 for basic stereo audio
- */
- if (channels <= 2)
- return 0;
-
- i = hda_node_index(spec->pin_cvt, nid);
- if (i < 0)
- return 0;
- eld = &spec->sink_eld[i];
-
- /*
- * HDMI sink's ELD info cannot always be retrieved for now, e.g.
- * in console or for audio devices. Assume the highest speakers
- * configuration, to _not_ prohibit multi-channel audio playback.
- */
- if (!eld->spk_alloc)
- eld->spk_alloc = 0xffff;
-
- /*
- * expand ELD's speaker allocation mask
- *
- * ELD tells the speaker mask in a compact(paired) form,
- * expand ELD's notions to match the ones used by Audio InfoFrame.
- */
- for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
- if (eld->spk_alloc & (1 << i))
- spk_mask |= eld_speaker_allocation_bits[i];
- }
-
- /* search for the first working match in the CA table */
- for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
- if (channels == channel_allocations[i].channels &&
- (spk_mask & channel_allocations[i].spk_mask) ==
- channel_allocations[i].spk_mask) {
- ai->CA = channel_allocations[i].ca_index;
- break;
- }
- }
-
- snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf));
- snd_printdd(KERN_INFO
- "HDMI: select CA 0x%x for %d-channel allocation: %s\n",
- ai->CA, channels, buf);
-
- return ai->CA;
-}
-
-static void hdmi_setup_channel_mapping(struct hda_codec *codec,
- hda_nid_t pin_nid,
- struct hdmi_audio_infoframe *ai)
-{
- int i;
- int ca = ai->CA;
- int err;
-
- if (hdmi_channel_mapping[ca][1] == 0) {
- for (i = 0; i < channel_allocations[ca].channels; i++)
- hdmi_channel_mapping[ca][i] = i | (i << 4);
- for (; i < 8; i++)
- hdmi_channel_mapping[ca][i] = 0xf | (i << 4);
- }
-
- for (i = 0; i < 8; i++) {
- err = snd_hda_codec_write(codec, pin_nid, 0,
- AC_VERB_SET_HDMI_CHAN_SLOT,
- hdmi_channel_mapping[ca][i]);
- if (err) {
- snd_printdd(KERN_INFO "HDMI: channel mapping failed\n");
- break;
- }
- }
-
- hdmi_debug_channel_mapping(codec, pin_nid);
-}
-
-static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid,
- struct hdmi_audio_infoframe *ai)
-{
- u8 *bytes = (u8 *)ai;
- u8 val;
- int i;
-
- if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0)
- != AC_DIPXMIT_BEST)
- return false;
-
- hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
- for (i = 0; i < sizeof(*ai); i++) {
- val = snd_hda_codec_read(codec, pin_nid, 0,
- AC_VERB_GET_HDMI_DIP_DATA, 0);
- if (val != bytes[i])
- return false;
- }
-
- return true;
-}
-
-static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
- struct snd_pcm_substream *substream)
-{
- struct intel_hdmi_spec *spec = codec->spec;
- hda_nid_t pin_nid;
- int i;
- struct hdmi_audio_infoframe ai = {
- .type = 0x84,
- .ver = 0x01,
- .len = 0x0a,
- .CC02_CT47 = substream->runtime->channels - 1,
- };
-
- hdmi_setup_channel_allocation(codec, nid, &ai);
-
- for (i = 0; i < spec->num_pins; i++) {
- if (spec->pin_cvt[i] != nid)
- continue;
- if (!spec->sink_eld[i].monitor_present)
- continue;
-
- pin_nid = spec->pin[i];
- if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) {
- hdmi_setup_channel_mapping(codec, pin_nid, &ai);
- hdmi_stop_infoframe_trans(codec, pin_nid);
- hdmi_fill_audio_infoframe(codec, pin_nid, &ai);
- hdmi_start_infoframe_trans(codec, pin_nid);
- }
- }
-}
-
-
/*
- * Unsolicited events
+ * HDMI callbacks
*/
-static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
-{
- struct intel_hdmi_spec *spec = codec->spec;
- int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
- int pind = !!(res & AC_UNSOL_RES_PD);
- int eldv = !!(res & AC_UNSOL_RES_ELDV);
- int index;
-
- printk(KERN_INFO
- "HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
- tag, pind, eldv);
-
- index = hda_node_index(spec->pin, tag);
- if (index < 0)
- return;
-
- spec->sink_eld[index].monitor_present = pind;
- spec->sink_eld[index].eld_valid = eldv;
-
- if (pind && eldv) {
- hdmi_get_show_eld(codec, spec->pin[index], &spec->sink_eld[index]);
- /* TODO: do real things about ELD */
- }
-}
-
-static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
-{
- int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
- int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
- int cp_state = !!(res & AC_UNSOL_RES_CP_STATE);
- int cp_ready = !!(res & AC_UNSOL_RES_CP_READY);
-
- printk(KERN_INFO
- "HDMI CP event: PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n",
- tag,
- subtag,
- cp_state,
- cp_ready);
-
- /* TODO */
- if (cp_state)
- ;
- if (cp_ready)
- ;
-}
-
-
-static void intel_hdmi_unsol_event(struct hda_codec *codec, unsigned int res)
-{
- struct intel_hdmi_spec *spec = codec->spec;
- int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
- int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
-
- if (hda_node_index(spec->pin, tag) < 0) {
- snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag);
- return;
- }
-
- if (subtag == 0)
- hdmi_intrinsic_event(codec, res);
- else
- hdmi_non_intrinsic_event(codec, res);
-}
-
-/*
- * Callbacks
- */
-
-static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid,
- u32 stream_tag, int format)
-{
- int tag;
- int fmt;
-
- tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4;
- fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0);
-
- snd_printdd("hdmi_setup_stream: "
- "NID=0x%x, %sstream=0x%x, %sformat=0x%x\n",
- nid,
- tag == stream_tag ? "" : "new-",
- stream_tag,
- fmt == format ? "" : "new-",
- format);
-
- if (tag != stream_tag)
- snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_CHANNEL_STREAMID, stream_tag << 4);
- if (fmt != format)
- snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_STREAM_FORMAT, format);
-}
-
static int intel_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
unsigned int stream_tag,
@@ -882,7 +87,7 @@ static struct hda_pcm_stream intel_hdmi_pcm_playback = {
static int intel_hdmi_build_pcms(struct hda_codec *codec)
{
- struct intel_hdmi_spec *spec = codec->spec;
+ struct hdmi_spec *spec = codec->spec;
struct hda_pcm *info = spec->pcm_rec;
int i;
@@ -908,7 +113,7 @@ static int intel_hdmi_build_pcms(struct hda_codec *codec)
static int intel_hdmi_build_controls(struct hda_codec *codec)
{
- struct intel_hdmi_spec *spec = codec->spec;
+ struct hdmi_spec *spec = codec->spec;
int err;
int i;
@@ -923,7 +128,7 @@ static int intel_hdmi_build_controls(struct hda_codec *codec)
static int intel_hdmi_init(struct hda_codec *codec)
{
- struct intel_hdmi_spec *spec = codec->spec;
+ struct hdmi_spec *spec = codec->spec;
int i;
for (i = 0; spec->pin[i]; i++) {
@@ -937,7 +142,7 @@ static int intel_hdmi_init(struct hda_codec *codec)
static void intel_hdmi_free(struct hda_codec *codec)
{
- struct intel_hdmi_spec *spec = codec->spec;
+ struct hdmi_spec *spec = codec->spec;
int i;
for (i = 0; i < spec->num_pins; i++)
@@ -951,12 +156,12 @@ static struct hda_codec_ops intel_hdmi_patch_ops = {
.free = intel_hdmi_free,
.build_pcms = intel_hdmi_build_pcms,
.build_controls = intel_hdmi_build_controls,
- .unsol_event = intel_hdmi_unsol_event,
+ .unsol_event = hdmi_unsol_event,
};
static int patch_intel_hdmi(struct hda_codec *codec)
{
- struct intel_hdmi_spec *spec;
+ struct hdmi_spec *spec;
int i;
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
@@ -964,7 +169,7 @@ static int patch_intel_hdmi(struct hda_codec *codec)
return -ENOMEM;
codec->spec = spec;
- if (intel_hdmi_parse_codec(codec) < 0) {
+ if (hdmi_parse_codec(codec) < 0) {
codec->spec = NULL;
kfree(spec);
return -EINVAL;
diff --git a/sound/pci/hda/patch_nvhdmi.c b/sound/pci/hda/patch_nvhdmi.c
index 6afdab0..3c10c0b 100644
--- a/sound/pci/hda/patch_nvhdmi.c
+++ b/sound/pci/hda/patch_nvhdmi.c
@@ -29,13 +29,23 @@
#include "hda_codec.h"
#include "hda_local.h"
+#define MAX_HDMI_CVTS 1
+#define MAX_HDMI_PINS 1
+
+#include "patch_hdmi.c"
+
+static char *nvhdmi_pcm_names[MAX_HDMI_CVTS] = {
+ "NVIDIA HDMI",
+};
+
/* define below to restrict the supported rates and formats */
/* #define LIMITED_RATE_FMT_SUPPORT */
-struct nvhdmi_spec {
- struct hda_multi_out multiout;
-
- struct hda_pcm pcm_rec;
+enum HDACodec {
+ HDA_CODEC_NVIDIA_MCP7X,
+ HDA_CODEC_NVIDIA_MCP89,
+ HDA_CODEC_NVIDIA_GT21X,
+ HDA_CODEC_INVALID
};
#define Nv_VERB_SET_Channel_Allocation 0xF79
@@ -43,15 +53,18 @@ struct nvhdmi_spec {
#define Nv_VERB_SET_Audio_Protection_On 0xF98
#define Nv_VERB_SET_Audio_Protection_Off 0xF99
-#define Nv_Master_Convert_nid 0x04
-#define Nv_Master_Pin_nid 0x05
+#define nvhdmi_master_con_nid_7x 0x04
+#define nvhdmi_master_pin_nid_7x 0x05
-static hda_nid_t nvhdmi_convert_nids[4] = {
+#define nvhdmi_master_con_nid_89 0x04
+#define nvhdmi_master_pin_nid_89 0x05
+
+static hda_nid_t nvhdmi_con_nids_7x[4] = {
/*front, rear, clfe, rear_surr */
0x6, 0x8, 0xa, 0xc,
};
-static struct hda_verb nvhdmi_basic_init[] = {
+static struct hda_verb nvhdmi_basic_init_7x[] = {
/* set audio protect on */
{ 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1},
/* enable digital output on pin widget */
@@ -84,22 +97,60 @@ static struct hda_verb nvhdmi_basic_init[] = {
*/
static int nvhdmi_build_controls(struct hda_codec *codec)
{
- struct nvhdmi_spec *spec = codec->spec;
+ struct hdmi_spec *spec = codec->spec;
int err;
+ int i;
- err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
- if (err < 0)
- return err;
+ if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89)
+ || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) {
+ for (i = 0; i < codec->num_pcms; i++) {
+ err = snd_hda_create_spdif_out_ctls(codec,
+ spec->cvt[i]);
+ if (err < 0)
+ return err;
+ }
+ } else {
+ err = snd_hda_create_spdif_out_ctls(codec,
+ spec->multiout.dig_out_nid);
+ if (err < 0)
+ return err;
+ }
return 0;
}
static int nvhdmi_init(struct hda_codec *codec)
{
- snd_hda_sequence_write(codec, nvhdmi_basic_init);
+ struct hdmi_spec *spec = codec->spec;
+ int i;
+ if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89)
+ || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) {
+ for (i = 0; spec->pin[i]; i++) {
+ hdmi_enable_output(codec, spec->pin[i]);
+ snd_hda_codec_write(codec, spec->pin[i], 0,
+ AC_VERB_SET_UNSOLICITED_ENABLE,
+ AC_USRSP_EN | spec->pin[i]);
+ }
+ } else {
+ snd_hda_sequence_write(codec, nvhdmi_basic_init_7x);
+ }
return 0;
}
+static void nvhdmi_free(struct hda_codec *codec)
+{
+ struct hdmi_spec *spec = codec->spec;
+ int i;
+
+ if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89)
+ || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) {
+ for (i = 0; i < spec->num_pins; i++)
+ snd_hda_eld_proc_free(codec, &spec->sink_eld[i]);
+ }
+
+ kfree(spec);
+}
+
/*
* Digital out
*/
@@ -107,25 +158,25 @@ static int nvhdmi_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
struct snd_pcm_substream *substream)
{
- struct nvhdmi_spec *spec = codec->spec;
+ struct hdmi_spec *spec = codec->spec;
return snd_hda_multi_out_dig_open(codec, &spec->multiout);
}
-static int nvhdmi_dig_playback_pcm_close_8ch(struct hda_pcm_stream *hinfo,
+static int nvhdmi_dig_playback_pcm_close_8ch_7x(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
struct snd_pcm_substream *substream)
{
- struct nvhdmi_spec *spec = codec->spec;
+ struct hdmi_spec *spec = codec->spec;
int i;
- snd_hda_codec_write(codec, Nv_Master_Convert_nid,
+ snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x,
0, AC_VERB_SET_CHANNEL_STREAMID, 0);
for (i = 0; i < 4; i++) {
/* set the stream id */
- snd_hda_codec_write(codec, nvhdmi_convert_nids[i], 0,
+ snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0,
AC_VERB_SET_CHANNEL_STREAMID, 0);
/* set the stream format */
- snd_hda_codec_write(codec, nvhdmi_convert_nids[i], 0,
+ snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0,
AC_VERB_SET_STREAM_FORMAT, 0);
}
@@ -136,10 +187,25 @@ static int nvhdmi_dig_playback_pcm_close_2ch(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
struct snd_pcm_substream *substream)
{
- struct nvhdmi_spec *spec = codec->spec;
+ struct hdmi_spec *spec = codec->spec;
return snd_hda_multi_out_dig_close(codec, &spec->multiout);
}
+static int nvhdmi_dig_playback_pcm_prepare_8ch_89(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ unsigned int stream_tag,
+ unsigned int format,
+ struct snd_pcm_substream *substream)
+{
+ hdmi_set_channel_count(codec, hinfo->nid,
+ substream->runtime->channels);
+
+ hdmi_setup_audio_infoframe(codec, hinfo->nid, substream);
+
+ hdmi_setup_stream(codec, hinfo->nid, stream_tag, format);
+ return 0;
+}
+
static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
unsigned int stream_tag,
@@ -181,29 +247,29 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
/* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
snd_hda_codec_write(codec,
- Nv_Master_Convert_nid,
+ nvhdmi_master_con_nid_7x,
0,
AC_VERB_SET_DIGI_CONVERT_1,
codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
/* set the stream id */
- snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0,
+ snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0,
AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0);
/* set the stream format */
- snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0,
+ snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0,
AC_VERB_SET_STREAM_FORMAT, format);
/* turn on again (if needed) */
/* enable and set the channel status audio/data flag */
if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) {
snd_hda_codec_write(codec,
- Nv_Master_Convert_nid,
+ nvhdmi_master_con_nid_7x,
0,
AC_VERB_SET_DIGI_CONVERT_1,
codec->spdif_ctls & 0xff);
snd_hda_codec_write(codec,
- Nv_Master_Convert_nid,
+ nvhdmi_master_con_nid_7x,
0,
AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
}
@@ -220,19 +286,19 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
if (codec->spdif_status_reset &&
(codec->spdif_ctls & AC_DIG1_ENABLE))
snd_hda_codec_write(codec,
- nvhdmi_convert_nids[i],
+ nvhdmi_con_nids_7x[i],
0,
AC_VERB_SET_DIGI_CONVERT_1,
codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
/* set the stream id */
snd_hda_codec_write(codec,
- nvhdmi_convert_nids[i],
+ nvhdmi_con_nids_7x[i],
0,
AC_VERB_SET_CHANNEL_STREAMID,
(stream_tag << 4) | channel_id);
/* set the stream format */
snd_hda_codec_write(codec,
- nvhdmi_convert_nids[i],
+ nvhdmi_con_nids_7x[i],
0,
AC_VERB_SET_STREAM_FORMAT,
format);
@@ -241,12 +307,12 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
if (codec->spdif_status_reset &&
(codec->spdif_ctls & AC_DIG1_ENABLE)) {
snd_hda_codec_write(codec,
- nvhdmi_convert_nids[i],
+ nvhdmi_con_nids_7x[i],
0,
AC_VERB_SET_DIGI_CONVERT_1,
codec->spdif_ctls & 0xff);
snd_hda_codec_write(codec,
- nvhdmi_convert_nids[i],
+ nvhdmi_con_nids_7x[i],
0,
AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
}
@@ -261,28 +327,47 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
return 0;
}
+static int nvhdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ struct snd_pcm_substream *substream)
+{
+ return 0;
+}
+
static int nvhdmi_dig_playback_pcm_prepare_2ch(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
unsigned int stream_tag,
unsigned int format,
struct snd_pcm_substream *substream)
{
- struct nvhdmi_spec *spec = codec->spec;
+ struct hdmi_spec *spec = codec->spec;
return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
format, substream);
}
-static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch = {
+static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_89 = {
+ .substreams = 1,
+ .channels_min = 2,
+ .rates = SUPPORTED_RATES,
+ .maxbps = SUPPORTED_MAXBPS,
+ .formats = SUPPORTED_FORMATS,
+ .ops = {
+ .prepare = nvhdmi_dig_playback_pcm_prepare_8ch_89,
+ .cleanup = nvhdmi_playback_pcm_cleanup,
+ },
+};
+
+static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_7x = {
.substreams = 1,
.channels_min = 2,
.channels_max = 8,
- .nid = Nv_Master_Convert_nid,
+ .nid = nvhdmi_master_con_nid_7x,
.rates = SUPPORTED_RATES,
.maxbps = SUPPORTED_MAXBPS,
.formats = SUPPORTED_FORMATS,
.ops = {
.open = nvhdmi_dig_playback_pcm_open,
- .close = nvhdmi_dig_playback_pcm_close_8ch,
+ .close = nvhdmi_dig_playback_pcm_close_8ch_7x,
.prepare = nvhdmi_dig_playback_pcm_prepare_8ch
},
};
@@ -291,7 +376,7 @@ static struct hda_pcm_stream nvhdmi_pcm_digital_playback_2ch = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
- .nid = Nv_Master_Convert_nid,
+ .nid = nvhdmi_master_con_nid_7x,
.rates = SUPPORTED_RATES,
.maxbps = SUPPORTED_MAXBPS,
.formats = SUPPORTED_FORMATS,
@@ -302,10 +387,36 @@ static struct hda_pcm_stream nvhdmi_pcm_digital_playback_2ch = {
},
};
-static int nvhdmi_build_pcms_8ch(struct hda_codec *codec)
+static int nvhdmi_build_pcms_8ch_89(struct hda_codec *codec)
+{
+ struct hdmi_spec *spec = codec->spec;
+ struct hda_pcm *info = spec->pcm_rec;
+ int i;
+
+ codec->num_pcms = spec->num_cvts;
+ codec->pcm_info = info;
+
+ for (i = 0; i < codec->num_pcms; i++, info++) {
+ unsigned int chans;
+
+ chans = get_wcaps(codec, spec->cvt[i]);
+ chans = get_wcaps_channels(chans);
+
+ info->name = nvhdmi_pcm_names[i];
+ info->pcm_type = HDA_PCM_TYPE_HDMI;
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK]
+ = nvhdmi_pcm_digital_playback_8ch_89;
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->cvt[i];
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = chans;
+ }
+
+ return 0;
+}
+
+static int nvhdmi_build_pcms_8ch_7x(struct hda_codec *codec)
{
- struct nvhdmi_spec *spec = codec->spec;
- struct hda_pcm *info = &spec->pcm_rec;
+ struct hdmi_spec *spec = codec->spec;
+ struct hda_pcm *info = spec->pcm_rec;
codec->num_pcms = 1;
codec->pcm_info = info;
@@ -313,15 +424,15 @@ static int nvhdmi_build_pcms_8ch(struct hda_codec *codec)
info->name = "NVIDIA HDMI";
info->pcm_type = HDA_PCM_TYPE_HDMI;
info->stream[SNDRV_PCM_STREAM_PLAYBACK]
- = nvhdmi_pcm_digital_playback_8ch;
+ = nvhdmi_pcm_digital_playback_8ch_7x;
return 0;
}
static int nvhdmi_build_pcms_2ch(struct hda_codec *codec)
{
- struct nvhdmi_spec *spec = codec->spec;
- struct hda_pcm *info = &spec->pcm_rec;
+ struct hdmi_spec *spec = codec->spec;
+ struct hda_pcm *info = spec->pcm_rec;
codec->num_pcms = 1;
codec->pcm_info = info;
@@ -334,14 +445,17 @@ static int nvhdmi_build_pcms_2ch(struct hda_codec *codec)
return 0;
}
-static void nvhdmi_free(struct hda_codec *codec)
-{
- kfree(codec->spec);
-}
+static struct hda_codec_ops nvhdmi_patch_ops_8ch_89 = {
+ .build_controls = nvhdmi_build_controls,
+ .build_pcms = nvhdmi_build_pcms_8ch_89,
+ .init = nvhdmi_init,
+ .free = nvhdmi_free,
+ .unsol_event = hdmi_unsol_event,
+};
-static struct hda_codec_ops nvhdmi_patch_ops_8ch = {
+static struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = {
.build_controls = nvhdmi_build_controls,
- .build_pcms = nvhdmi_build_pcms_8ch,
+ .build_pcms = nvhdmi_build_pcms_8ch_7x,
.init = nvhdmi_init,
.free = nvhdmi_free,
};
@@ -353,9 +467,36 @@ static struct hda_codec_ops nvhdmi_patch_ops_2ch = {
.free = nvhdmi_free,
};
-static int patch_nvhdmi_8ch(struct hda_codec *codec)
+static int patch_nvhdmi_8ch_89(struct hda_codec *codec)
+{
+ struct hdmi_spec *spec;
+ int i;
+
+ spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+ if (spec == NULL)
+ return -ENOMEM;
+
+ codec->spec = spec;
+ spec->codec_type = HDA_CODEC_NVIDIA_MCP89;
+
+ if (hdmi_parse_codec(codec) < 0) {
+ codec->spec = NULL;
+ kfree(spec);
+ return -EINVAL;
+ }
+ codec->patch_ops = nvhdmi_patch_ops_8ch_89;
+
+ for (i = 0; i < spec->num_pins; i++)
+ snd_hda_eld_proc_new(codec, &spec->sink_eld[i], i);
+
+ init_channel_allocations();
+
+ return 0;
+}
+
+static int patch_nvhdmi_8ch_7x(struct hda_codec *codec)
{
- struct nvhdmi_spec *spec;
+ struct hdmi_spec *spec;
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
@@ -365,16 +506,17 @@ static int patch_nvhdmi_8ch(struct hda_codec *codec)
spec->multiout.num_dacs = 0; /* no analog */
spec->multiout.max_channels = 8;
- spec->multiout.dig_out_nid = Nv_Master_Convert_nid;
+ spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x;
+ spec->codec_type = HDA_CODEC_NVIDIA_MCP7X;
- codec->patch_ops = nvhdmi_patch_ops_8ch;
+ codec->patch_ops = nvhdmi_patch_ops_8ch_7x;
return 0;
}
static int patch_nvhdmi_2ch(struct hda_codec *codec)
{
- struct nvhdmi_spec *spec;
+ struct hdmi_spec *spec;
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
@@ -384,7 +526,8 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec)
spec->multiout.num_dacs = 0; /* no analog */
spec->multiout.max_channels = 2;
- spec->multiout.dig_out_nid = Nv_Master_Convert_nid;
+ spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x;
+ spec->codec_type = HDA_CODEC_NVIDIA_MCP7X;
codec->patch_ops = nvhdmi_patch_ops_2ch;
@@ -395,11 +538,24 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec)
* patch entries
*/
static struct hda_codec_preset snd_hda_preset_nvhdmi[] = {
- { .id = 0x10de0002, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch },
- { .id = 0x10de0003, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch },
- { .id = 0x10de0005, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch },
- { .id = 0x10de0006, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch },
- { .id = 0x10de0007, .name = "MCP7A HDMI", .patch = patch_nvhdmi_8ch },
+ { .id = 0x10de0002, .name = "MCP77/78 HDMI",
+ .patch = patch_nvhdmi_8ch_7x },
+ { .id = 0x10de0003, .name = "MCP77/78 HDMI",
+ .patch = patch_nvhdmi_8ch_7x },
+ { .id = 0x10de0005, .name = "MCP77/78 HDMI",
+ .patch = patch_nvhdmi_8ch_7x },
+ { .id = 0x10de0006, .name = "MCP77/78 HDMI",
+ .patch = patch_nvhdmi_8ch_7x },
+ { .id = 0x10de0007, .name = "MCP79/7A HDMI",
+ .patch = patch_nvhdmi_8ch_7x },
+ { .id = 0x10de000a, .name = "GT220 HDMI",
+ .patch = patch_nvhdmi_8ch_89 },
+ { .id = 0x10de000b, .name = "GT21x HDMI",
+ .patch = patch_nvhdmi_8ch_89 },
+ { .id = 0x10de000c, .name = "MCP89 HDMI",
+ .patch = patch_nvhdmi_8ch_89 },
+ { .id = 0x10de000d, .name = "GT240 HDMI",
+ .patch = patch_nvhdmi_8ch_89 },
{ .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch },
{ .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch },
{} /* terminator */
@@ -410,11 +566,15 @@ MODULE_ALIAS("snd-hda-codec-id:10de0003");
MODULE_ALIAS("snd-hda-codec-id:10de0005");
MODULE_ALIAS("snd-hda-codec-id:10de0006");
MODULE_ALIAS("snd-hda-codec-id:10de0007");
+MODULE_ALIAS("snd-hda-codec-id:10de000a");
+MODULE_ALIAS("snd-hda-codec-id:10de000b");
+MODULE_ALIAS("snd-hda-codec-id:10de000c");
+MODULE_ALIAS("snd-hda-codec-id:10de000d");
MODULE_ALIAS("snd-hda-codec-id:10de0067");
MODULE_ALIAS("snd-hda-codec-id:10de8001");
MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Nvidia HDMI HD-audio codec");
+MODULE_DESCRIPTION("NVIDIA HDMI HD-audio codec");
static struct hda_codec_preset_list nvhdmi_list = {
.preset = snd_hda_preset_nvhdmi,
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index e8cbe21..9a23444 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -411,6 +411,8 @@ static int alc_mux_enum_info(struct snd_kcontrol *kcontrol,
unsigned int mux_idx = snd_ctl_get_ioffidx(kcontrol, &uinfo->id);
if (mux_idx >= spec->num_mux_defs)
mux_idx = 0;
+ if (!spec->input_mux[mux_idx].num_items && mux_idx > 0)
+ mux_idx = 0;
return snd_hda_input_mux_info(&spec->input_mux[mux_idx], uinfo);
}
@@ -439,6 +441,8 @@ static int alc_mux_enum_put(struct snd_kcontrol *kcontrol,
mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
imux = &spec->input_mux[mux_idx];
+ if (!imux->num_items && mux_idx > 0)
+ imux = &spec->input_mux[0];
type = get_wcaps_type(get_wcaps(codec, nid));
if (type == AC_WID_AUD_MIX) {
@@ -2528,8 +2532,6 @@ static int alc_build_controls(struct hda_codec *codec)
return err;
}
- alc_free_kctls(codec); /* no longer needed */
-
/* assign Capture Source enums to NID */
kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
if (!kctl)
@@ -2598,6 +2600,9 @@ static int alc_build_controls(struct hda_codec *codec)
}
}
}
+
+ alc_free_kctls(codec); /* no longer needed */
+
return 0;
}
@@ -4915,7 +4920,7 @@ static void fixup_automic_adc(struct hda_codec *codec)
static void fixup_single_adc(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- hda_nid_t pin;
+ hda_nid_t pin = 0;
int i;
/* search for the input pin; there must be only one */
@@ -6473,7 +6478,7 @@ static struct alc_config_preset alc260_presets[] = {
.num_dacs = ARRAY_SIZE(alc260_dac_nids),
.dac_nids = alc260_dac_nids,
.num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
- .adc_nids = alc260_adc_nids,
+ .adc_nids = alc260_dual_adc_nids,
.num_channel_mode = ARRAY_SIZE(alc260_modes),
.channel_mode = alc260_modes,
.input_mux = &alc260_capture_source,
@@ -9191,6 +9196,7 @@ static struct snd_pci_quirk alc882_cfg_tbl[] = {
SND_PCI_QUIRK(0x1462, 0x4314, "MSI", ALC883_TARGA_DIG),
SND_PCI_QUIRK(0x1462, 0x4319, "MSI", ALC883_TARGA_DIG),
SND_PCI_QUIRK(0x1462, 0x4324, "MSI", ALC883_TARGA_DIG),
+ SND_PCI_QUIRK(0x1462, 0x4570, "MSI Wind Top AE2220", ALC883_TARGA_DIG),
SND_PCI_QUIRK(0x1462, 0x6510, "MSI GX620", ALC883_TARGA_8ch_DIG),
SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC883_6ST_DIG),
SND_PCI_QUIRK(0x1462, 0x7187, "MSI", ALC883_6ST_DIG),
@@ -9200,6 +9206,7 @@ static struct snd_pci_quirk alc882_cfg_tbl[] = {
SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG),
SND_PCI_QUIRK(0x1462, 0x7327, "MSI", ALC883_6ST_DIG),
SND_PCI_QUIRK(0x1462, 0x7350, "MSI", ALC883_6ST_DIG),
+ SND_PCI_QUIRK(0x1462, 0x7437, "MSI NetOn AP1900", ALC883_TARGA_DIG),
SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG),
SND_PCI_QUIRK(0x1462, 0xaa08, "MSI", ALC883_TARGA_2ch_DIG),
@@ -9231,7 +9238,7 @@ static struct snd_pci_quirk alc882_cfg_tbl[] = {
SND_PCI_QUIRK(0x8086, 0x0022, "DX58SO", ALC889_INTEL),
SND_PCI_QUIRK(0x8086, 0x0021, "Intel IbexPeak", ALC889A_INTEL),
SND_PCI_QUIRK(0x8086, 0x3b56, "Intel IbexPeak", ALC889A_INTEL),
- SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC883_3ST_6ch),
+ SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC882_6ST_DIG),
{}
};
@@ -10036,8 +10043,11 @@ static void alc882_auto_set_output_and_unmute(struct hda_codec *codec,
alc_set_pin_output(codec, nid, pin_type);
if (spec->multiout.dac_nids[dac_idx] == 0x25)
idx = 4;
- else
+ else {
+ if (spec->multiout.num_dacs >= dac_idx)
+ return;
idx = spec->multiout.dac_nids[dac_idx] - 2;
+ }
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
}
@@ -10105,6 +10115,8 @@ static void alc882_auto_init_input_src(struct hda_codec *codec)
continue;
mux_idx = c >= spec->num_mux_defs ? 0 : c;
imux = &spec->input_mux[mux_idx];
+ if (!imux->num_items && mux_idx > 0)
+ imux = &spec->input_mux[0];
for (idx = 0; idx < conns; idx++) {
/* if the current connection is the selected one,
* unmute it as default - otherwise mute it
@@ -13201,7 +13213,7 @@ static int patch_alc268(struct hda_codec *codec)
if (board_config < 0 || board_config >= ALC268_MODEL_LAST)
board_config = snd_hda_check_board_codec_sid_config(codec,
- ALC882_MODEL_LAST, alc268_models, alc268_ssid_cfg_tbl);
+ ALC268_MODEL_LAST, alc268_models, alc268_ssid_cfg_tbl);
if (board_config < 0 || board_config >= ALC268_MODEL_LAST) {
printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
@@ -13561,6 +13573,8 @@ static void alc269_lifebook_unsol_event(struct hda_codec *codec,
static void alc269_quanta_fl1_setup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
+ spec->autocfg.hp_pins[0] = 0x15;
+ spec->autocfg.speaker_pins[0] = 0x14;
spec->ext_mic.pin = 0x18;
spec->ext_mic.mux_idx = 0;
spec->int_mic.pin = 0x19;
@@ -13656,6 +13670,8 @@ static void alc269_laptop_unsol_event(struct hda_codec *codec,
static void alc269_laptop_dmic_setup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
+ spec->autocfg.hp_pins[0] = 0x15;
+ spec->autocfg.speaker_pins[0] = 0x14;
spec->ext_mic.pin = 0x18;
spec->ext_mic.mux_idx = 0;
spec->int_mic.pin = 0x12;
@@ -13666,6 +13682,8 @@ static void alc269_laptop_dmic_setup(struct hda_codec *codec)
static void alc269vb_laptop_dmic_setup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
+ spec->autocfg.hp_pins[0] = 0x15;
+ spec->autocfg.speaker_pins[0] = 0x14;
spec->ext_mic.pin = 0x18;
spec->ext_mic.mux_idx = 0;
spec->int_mic.pin = 0x12;
@@ -13676,6 +13694,8 @@ static void alc269vb_laptop_dmic_setup(struct hda_codec *codec)
static void alc269_laptop_amic_setup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
+ spec->autocfg.hp_pins[0] = 0x15;
+ spec->autocfg.speaker_pins[0] = 0x14;
spec->ext_mic.pin = 0x18;
spec->ext_mic.mux_idx = 0;
spec->int_mic.pin = 0x19;
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 8c416bb..c4be3fa 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -1730,6 +1730,8 @@ static struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = {
"HP HDX", STAC_HP_HDX), /* HDX16 */
SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3620,
"HP dv6", STAC_HP_DV5),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3061,
+ "HP dv6", STAC_HP_DV5), /* HP dv6-1110ax */
SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x7010,
"HP", STAC_HP_DV5),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0233,
diff --git a/sound/pci/oxygen/xonar_wm87x6.c b/sound/pci/oxygen/xonar_wm87x6.c
index 7754db1..dbc4b89 100644
--- a/sound/pci/oxygen/xonar_wm87x6.c
+++ b/sound/pci/oxygen/xonar_wm87x6.c
@@ -68,7 +68,7 @@ static void wm8776_write(struct oxygen *chip,
OXYGEN_SPI_CEN_LATCH_CLOCK_LO,
(reg << 9) | value);
if (reg < ARRAY_SIZE(data->wm8776_regs)) {
- if (reg >= WM8776_HPLVOL || reg <= WM8776_DACMASTER)
+ if (reg >= WM8776_HPLVOL && reg <= WM8776_DACMASTER)
value &= ~WM8776_UPDATE;
data->wm8776_regs[reg] = value;
}
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c
index 960a227..ad44626 100644
--- a/sound/pci/riptide/riptide.c
+++ b/sound/pci/riptide/riptide.c
@@ -1974,9 +1974,9 @@ snd_riptide_proc_read(struct snd_info_entry *entry,
}
snd_iprintf(buffer, "Paths:\n");
i = getpaths(cif, p);
- while (i--) {
- snd_iprintf(buffer, "%x->%x ", p[i - 1], p[i]);
- i--;
+ while (i >= 2) {
+ i -= 2;
+ snd_iprintf(buffer, "%x->%x ", p[i], p[i + 1]);
}
snd_iprintf(buffer, "\n");
}
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index 3d72c1e..547b713 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -2479,7 +2479,7 @@ static int snd_hdspm_put_qs_wire(struct snd_kcontrol *kcontrol,
on MADICARD
- playback mixer matrix: [channelout+64] [output] [value]
- input(thru) mixer matrix: [channelin] [output] [value]
- (better do 2 kontrols for seperation ?)
+ (better do 2 kontrols for separation ?)
*/
#define HDSPM_MIXER(xname, xindex) \
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c
index b9ef7e4..b68d99f 100644
--- a/sound/soc/codecs/ak4104.c
+++ b/sound/soc/codecs/ak4104.c
@@ -90,12 +90,10 @@ static int ak4104_spi_write(struct snd_soc_codec *codec, unsigned int reg,
if (reg >= codec->reg_cache_size)
return -EINVAL;
- reg &= AK4104_REG_MASK;
- reg |= AK4104_WRITE;
-
/* only write to the hardware if value has changed */
if (cache[reg] != value) {
- u8 tmp[2] = { reg, value };
+ u8 tmp[2] = { (reg & AK4104_REG_MASK) | AK4104_WRITE, value };
+
if (spi_write(spi, tmp, sizeof(tmp))) {
dev_err(&spi->dev, "SPI write failed\n");
return -EIO;
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c
index f9f367d..d50f169 100644
--- a/sound/soc/codecs/tlv320dac33.c
+++ b/sound/soc/codecs/tlv320dac33.c
@@ -778,7 +778,7 @@ static int dac33_prepare_chip(struct snd_pcm_substream *substream)
if (dac33->fifo_mode) {
/* Generic for all FIFO modes */
/* 50-51 : ASRC Control registers */
- dac33_write(codec, DAC33_ASRC_CTRL_A, (1 << 4)); /* div=2 */
+ dac33_write(codec, DAC33_ASRC_CTRL_A, DAC33_SRCLKDIV(1));
dac33_write(codec, DAC33_ASRC_CTRL_B, 1); /* ??? */
/* Write registers 0x34 and 0x35 (MSB, LSB) */
@@ -1038,11 +1038,7 @@ static int dac33_set_dai_fmt(struct snd_soc_dai *codec_dai,
case SND_SOC_DAIFMT_DSP_A:
aictrl_a |= DAC33_AFMT_DSP;
aictrl_b &= ~DAC33_DATA_DELAY_MASK;
- aictrl_b |= DAC33_DATA_DELAY(1); /* 1 bit delay */
- break;
- case SND_SOC_DAIFMT_DSP_B:
- aictrl_a |= DAC33_AFMT_DSP;
- aictrl_b &= ~DAC33_DATA_DELAY_MASK; /* No delay */
+ aictrl_b |= DAC33_DATA_DELAY(0);
break;
case SND_SOC_DAIFMT_RIGHT_J:
aictrl_a |= DAC33_AFMT_RIGHT_J;
@@ -1066,7 +1062,7 @@ static void dac33_init_chip(struct snd_soc_codec *codec)
{
/* 44-46: DAC Control Registers */
/* A : DAC sample rate Fsref/1.5 */
- dac33_write(codec, DAC33_DAC_CTRL_A, DAC33_DACRATE(1));
+ dac33_write(codec, DAC33_DAC_CTRL_A, DAC33_DACRATE(0));
/* B : DAC src=normal, not muted */
dac33_write(codec, DAC33_DAC_CTRL_B, DAC33_DACSRCR_RIGHT |
DAC33_DACSRCL_LEFT);
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c
index a2763c2..9cd0a66 100644
--- a/sound/soc/codecs/uda1380.c
+++ b/sound/soc/codecs/uda1380.c
@@ -137,7 +137,7 @@ static void uda1380_flush_work(struct work_struct *work)
{
int bit, reg;
- for_each_bit(bit, &uda1380_cache_dirty, UDA1380_CACHEREGNUM - 0x10) {
+ for_each_set_bit(bit, &uda1380_cache_dirty, UDA1380_CACHEREGNUM - 0x10) {
reg = 0x10 + bit;
pr_debug("uda1380: flush reg %x val %x:\n", reg,
uda1380_read_reg_cache(uda1380_codec, reg));
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c
index 718ef91..df2c6d9 100644
--- a/sound/soc/codecs/wm8350.c
+++ b/sound/soc/codecs/wm8350.c
@@ -1349,7 +1349,7 @@ static irqreturn_t wm8350_hp_jack_handler(int irq, void *data)
int mask;
struct wm8350_jack_data *jack = NULL;
- switch (irq) {
+ switch (irq - wm8350->irq_base) {
case WM8350_IRQ_CODEC_JCK_DET_L:
jack = &priv->hpl;
mask = WM8350_JACK_L_LVL;
@@ -1424,7 +1424,7 @@ int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which,
wm8350_set_bits(wm8350, WM8350_JACK_DETECT, ena);
/* Sync status */
- wm8350_hp_jack_handler(irq, priv);
+ wm8350_hp_jack_handler(irq + wm8350->irq_base, priv);
return 0;
}
@@ -1521,8 +1521,8 @@ static int wm8350_remove(struct platform_device *pdev)
WM8350_JDL_ENA | WM8350_JDR_ENA);
wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA);
- wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L);
- wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R);
+ wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L, priv);
+ wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R, priv);
priv->hpl.jack = NULL;
priv->hpr.jack = NULL;
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
index a54dc77..056b787 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -990,7 +990,7 @@ static int wm8990_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
reg = snd_soc_read(codec, WM8990_CLOCKING_2);
snd_soc_write(codec, WM8990_CLOCKING_2, reg | WM8990_SYSCLK_SRC);
- /* set up N , fractional mode and pre-divisor if neccessary */
+ /* set up N , fractional mode and pre-divisor if necessary */
snd_soc_write(codec, WM8990_PLL1, pll_div.n | WM8990_SDM |
(pll_div.div2?WM8990_PRESCALE:0));
snd_soc_write(codec, WM8990_PLL2, (u8)(pll_div.k>>8));
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c
index 0ad9f5d..486bdd2 100644
--- a/sound/soc/codecs/wm_hubs.c
+++ b/sound/soc/codecs/wm_hubs.c
@@ -74,7 +74,7 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec)
msleep(1);
reg = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_0);
dev_dbg(codec->dev, "DC servo: %x\n", reg);
- } while (reg & WM8993_DCS_DATAPATH_BUSY);
+ } while (reg & WM8993_DCS_DATAPATH_BUSY && count < 400);
if (reg & WM8993_DCS_DATAPATH_BUSY)
dev_err(codec->dev, "Timed out waiting for DC Servo\n");
diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig
index c7d0fd9..7174b4c 100644
--- a/sound/soc/imx/Kconfig
+++ b/sound/soc/imx/Kconfig
@@ -1,6 +1,6 @@
config SND_IMX_SOC
tristate "SoC Audio for Freescale i.MX CPUs"
- depends on ARCH_MXC && BROKEN
+ depends on ARCH_MXC
select SND_PCM
select FIQ
select SND_SOC_AC97_BUS
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index d297256..e814a95 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -39,6 +39,14 @@
#define OMAP_MCBSP_RATES (SNDRV_PCM_RATE_8000_96000)
+#define OMAP_MCBSP_SOC_SINGLE_S16_EXT(xname, xmin, xmax, \
+ xhandler_get, xhandler_put) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+ .info = omap_mcbsp_st_info_volsw, \
+ .get = xhandler_get, .put = xhandler_put, \
+ .private_value = (unsigned long) &(struct soc_mixer_control) \
+ {.min = xmin, .max = xmax} }
+
struct omap_mcbsp_data {
unsigned int bus_id;
struct omap_mcbsp_reg_cfg regs;
@@ -82,11 +90,11 @@ static const int omap1_dma_reqs[][2] = {};
static const unsigned long omap1_mcbsp_port[][2] = {};
#endif
-#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
static const int omap24xx_dma_reqs[][2] = {
{ OMAP24XX_DMA_MCBSP1_TX, OMAP24XX_DMA_MCBSP1_RX },
{ OMAP24XX_DMA_MCBSP2_TX, OMAP24XX_DMA_MCBSP2_RX },
-#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP34XX)
+#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3)
{ OMAP24XX_DMA_MCBSP3_TX, OMAP24XX_DMA_MCBSP3_RX },
{ OMAP24XX_DMA_MCBSP4_TX, OMAP24XX_DMA_MCBSP4_RX },
{ OMAP24XX_DMA_MCBSP5_TX, OMAP24XX_DMA_MCBSP5_RX },
@@ -124,7 +132,7 @@ static const unsigned long omap2430_mcbsp_port[][2] = {
static const unsigned long omap2430_mcbsp_port[][2] = {};
#endif
-#if defined(CONFIG_ARCH_OMAP34XX)
+#if defined(CONFIG_ARCH_OMAP3)
static const unsigned long omap34xx_mcbsp_port[][2] = {
{ OMAP34XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR,
OMAP34XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR },
@@ -639,6 +647,136 @@ struct snd_soc_dai omap_mcbsp_dai[] = {
EXPORT_SYMBOL_GPL(omap_mcbsp_dai);
+int omap_mcbsp_st_info_volsw(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ int max = mc->max;
+ int min = mc->min;
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ uinfo->value.integer.min = min;
+ uinfo->value.integer.max = max;
+ return 0;
+}
+
+#define OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(id, channel) \
+static int \
+omap_mcbsp##id##_set_st_ch##channel##_volume(struct snd_kcontrol *kc, \
+ struct snd_ctl_elem_value *uc) \
+{ \
+ struct soc_mixer_control *mc = \
+ (struct soc_mixer_control *)kc->private_value; \
+ int max = mc->max; \
+ int min = mc->min; \
+ int val = uc->value.integer.value[0]; \
+ \
+ if (val < min || val > max) \
+ return -EINVAL; \
+ \
+ /* OMAP McBSP implementation uses index values 0..4 */ \
+ return omap_st_set_chgain((id)-1, channel, val); \
+}
+
+#define OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(id, channel) \
+static int \
+omap_mcbsp##id##_get_st_ch##channel##_volume(struct snd_kcontrol *kc, \
+ struct snd_ctl_elem_value *uc) \
+{ \
+ s16 chgain; \
+ \
+ if (omap_st_get_chgain((id)-1, channel, &chgain)) \
+ return -EAGAIN; \
+ \
+ uc->value.integer.value[0] = chgain; \
+ return 0; \
+}
+
+OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(2, 0)
+OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(2, 1)
+OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(3, 0)
+OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(3, 1)
+OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(2, 0)
+OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(2, 1)
+OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(3, 0)
+OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(3, 1)
+
+static int omap_mcbsp_st_put_mode(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ u8 value = ucontrol->value.integer.value[0];
+
+ if (value == omap_st_is_enabled(mc->reg))
+ return 0;
+
+ if (value)
+ omap_st_enable(mc->reg);
+ else
+ omap_st_disable(mc->reg);
+
+ return 1;
+}
+
+static int omap_mcbsp_st_get_mode(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+
+ ucontrol->value.integer.value[0] = omap_st_is_enabled(mc->reg);
+ return 0;
+}
+
+static const struct snd_kcontrol_new omap_mcbsp2_st_controls[] = {
+ SOC_SINGLE_EXT("McBSP2 Sidetone Switch", 1, 0, 1, 0,
+ omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode),
+ OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 0 Volume",
+ -32768, 32767,
+ omap_mcbsp2_get_st_ch0_volume,
+ omap_mcbsp2_set_st_ch0_volume),
+ OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 1 Volume",
+ -32768, 32767,
+ omap_mcbsp2_get_st_ch1_volume,
+ omap_mcbsp2_set_st_ch1_volume),
+};
+
+static const struct snd_kcontrol_new omap_mcbsp3_st_controls[] = {
+ SOC_SINGLE_EXT("McBSP3 Sidetone Switch", 2, 0, 1, 0,
+ omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode),
+ OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 0 Volume",
+ -32768, 32767,
+ omap_mcbsp3_get_st_ch0_volume,
+ omap_mcbsp3_set_st_ch0_volume),
+ OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 1 Volume",
+ -32768, 32767,
+ omap_mcbsp3_get_st_ch1_volume,
+ omap_mcbsp3_set_st_ch1_volume),
+};
+
+int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id)
+{
+ if (!cpu_is_omap34xx())
+ return -ENODEV;
+
+ switch (mcbsp_id) {
+ case 1: /* McBSP 2 */
+ return snd_soc_add_controls(codec, omap_mcbsp2_st_controls,
+ ARRAY_SIZE(omap_mcbsp2_st_controls));
+ case 2: /* McBSP 3 */
+ return snd_soc_add_controls(codec, omap_mcbsp3_st_controls,
+ ARRAY_SIZE(omap_mcbsp3_st_controls));
+ default:
+ break;
+ }
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(omap_mcbsp_st_add_controls);
+
static int __init snd_omap_mcbsp_init(void)
{
return snd_soc_register_dais(omap_mcbsp_dai,
diff --git a/sound/soc/omap/omap-mcbsp.h b/sound/soc/omap/omap-mcbsp.h
index 647d2f9..6c363e5 100644
--- a/sound/soc/omap/omap-mcbsp.h
+++ b/sound/soc/omap/omap-mcbsp.h
@@ -50,11 +50,13 @@ enum omap_mcbsp_div {
#undef NUM_LINKS
#define NUM_LINKS 3
#endif
-#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP34XX)
+#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3)
#undef NUM_LINKS
#define NUM_LINKS 5
#endif
extern struct snd_soc_dai omap_mcbsp_dai[NUM_LINKS];
+int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id);
+
#endif
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index e69397f..9e95e51 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -42,11 +42,14 @@
* SSP audio private data
*/
struct ssp_priv {
- struct ssp_dev dev;
+ struct ssp_device *ssp;
unsigned int sysclk;
int dai_fmt;
#ifdef CONFIG_PM
- struct ssp_state state;
+ uint32_t cr0;
+ uint32_t cr1;
+ uint32_t to;
+ uint32_t psp;
#endif
};
@@ -61,6 +64,22 @@ static void dump_registers(struct ssp_device *ssp)
ssp_read_reg(ssp, SSACD));
}
+static void ssp_enable(struct ssp_device *ssp)
+{
+ uint32_t sscr0;
+
+ sscr0 = __raw_readl(ssp->mmio_base + SSCR0) | SSCR0_SSE;
+ __raw_writel(sscr0, ssp->mmio_base + SSCR0);
+}
+
+static void ssp_disable(struct ssp_device *ssp)
+{
+ uint32_t sscr0;
+
+ sscr0 = __raw_readl(ssp->mmio_base + SSCR0) & ~SSCR0_SSE;
+ __raw_writel(sscr0, ssp->mmio_base + SSCR0);
+}
+
struct pxa2xx_pcm_dma_data {
struct pxa2xx_pcm_dma_params params;
char name[20];
@@ -94,13 +113,12 @@ static int pxa_ssp_startup(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
struct ssp_priv *priv = cpu_dai->private_data;
+ struct ssp_device *ssp = priv->ssp;
int ret = 0;
if (!cpu_dai->active) {
- priv->dev.port = cpu_dai->id + 1;
- priv->dev.irq = NO_IRQ;
- clk_enable(priv->dev.ssp->clk);
- ssp_disable(&priv->dev);
+ clk_enable(ssp->clk);
+ ssp_disable(ssp);
}
if (cpu_dai->dma_data) {
@@ -116,10 +134,11 @@ static void pxa_ssp_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
struct ssp_priv *priv = cpu_dai->private_data;
+ struct ssp_device *ssp = priv->ssp;
if (!cpu_dai->active) {
- ssp_disable(&priv->dev);
- clk_disable(priv->dev.ssp->clk);
+ ssp_disable(ssp);
+ clk_disable(ssp->clk);
}
if (cpu_dai->dma_data) {
@@ -133,27 +152,39 @@ static void pxa_ssp_shutdown(struct snd_pcm_substream *substream,
static int pxa_ssp_suspend(struct snd_soc_dai *cpu_dai)
{
struct ssp_priv *priv = cpu_dai->private_data;
+ struct ssp_device *ssp = priv->ssp;
if (!cpu_dai->active)
- clk_enable(priv->dev.ssp->clk);
+ clk_enable(ssp->clk);
- ssp_save_state(&priv->dev, &priv->state);
- clk_disable(priv->dev.ssp->clk);
+ priv->cr0 = __raw_readl(ssp->mmio_base + SSCR0);
+ priv->cr1 = __raw_readl(ssp->mmio_base + SSCR1);
+ priv->to = __raw_readl(ssp->mmio_base + SSTO);
+ priv->psp = __raw_readl(ssp->mmio_base + SSPSP);
+ ssp_disable(ssp);
+ clk_disable(ssp->clk);
return 0;
}
static int pxa_ssp_resume(struct snd_soc_dai *cpu_dai)
{
struct ssp_priv *priv = cpu_dai->private_data;
+ struct ssp_device *ssp = priv->ssp;
+ uint32_t sssr = SSSR_ROR | SSSR_TUR | SSSR_BCE;
+
+ clk_enable(ssp->clk);
- clk_enable(priv->dev.ssp->clk);
- ssp_restore_state(&priv->dev, &priv->state);
+ __raw_writel(sssr, ssp->mmio_base + SSSR);
+ __raw_writel(priv->cr0 & ~SSCR0_SSE, ssp->mmio_base + SSCR0);
+ __raw_writel(priv->cr1, ssp->mmio_base + SSCR1);
+ __raw_writel(priv->to, ssp->mmio_base + SSTO);
+ __raw_writel(priv->psp, ssp->mmio_base + SSPSP);
if (cpu_dai->active)
- ssp_enable(&priv->dev);
+ ssp_enable(ssp);
else
- clk_disable(priv->dev.ssp->clk);
+ clk_disable(ssp->clk);
return 0;
}
@@ -203,7 +234,7 @@ static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
int clk_id, unsigned int freq, int dir)
{
struct ssp_priv *priv = cpu_dai->private_data;
- struct ssp_device *ssp = priv->dev.ssp;
+ struct ssp_device *ssp = priv->ssp;
int val;
u32 sscr0 = ssp_read_reg(ssp, SSCR0) &
@@ -244,11 +275,11 @@ static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
/* The SSP clock must be disabled when changing SSP clock mode
* on PXA2xx. On PXA3xx it must be enabled when doing so. */
if (!cpu_is_pxa3xx())
- clk_disable(priv->dev.ssp->clk);
+ clk_disable(ssp->clk);
val = ssp_read_reg(ssp, SSCR0) | sscr0;
ssp_write_reg(ssp, SSCR0, val);
if (!cpu_is_pxa3xx())
- clk_enable(priv->dev.ssp->clk);
+ clk_enable(ssp->clk);
return 0;
}
@@ -260,7 +291,7 @@ static int pxa_ssp_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
int div_id, int div)
{
struct ssp_priv *priv = cpu_dai->private_data;
- struct ssp_device *ssp = priv->dev.ssp;
+ struct ssp_device *ssp = priv->ssp;
int val;
switch (div_id) {
@@ -311,7 +342,7 @@ static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai, int pll_id,
int source, unsigned int freq_in, unsigned int freq_out)
{
struct ssp_priv *priv = cpu_dai->private_data;
- struct ssp_device *ssp = priv->dev.ssp;
+ struct ssp_device *ssp = priv->ssp;
u32 ssacd = ssp_read_reg(ssp, SSACD) & ~0x70;
#if defined(CONFIG_PXA3xx)
@@ -380,7 +411,7 @@ static int pxa_ssp_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai,
unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)
{
struct ssp_priv *priv = cpu_dai->private_data;
- struct ssp_device *ssp = priv->dev.ssp;
+ struct ssp_device *ssp = priv->ssp;
u32 sscr0;
sscr0 = ssp_read_reg(ssp, SSCR0);
@@ -415,7 +446,7 @@ static int pxa_ssp_set_dai_tristate(struct snd_soc_dai *cpu_dai,
int tristate)
{
struct ssp_priv *priv = cpu_dai->private_data;
- struct ssp_device *ssp = priv->dev.ssp;
+ struct ssp_device *ssp = priv->ssp;
u32 sscr1;
sscr1 = ssp_read_reg(ssp, SSCR1);
@@ -437,7 +468,7 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
unsigned int fmt)
{
struct ssp_priv *priv = cpu_dai->private_data;
- struct ssp_device *ssp = priv->dev.ssp;
+ struct ssp_device *ssp = priv->ssp;
u32 sscr0;
u32 sscr1;
u32 sspsp;
@@ -532,7 +563,7 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
struct ssp_priv *priv = cpu_dai->private_data;
- struct ssp_device *ssp = priv->dev.ssp;
+ struct ssp_device *ssp = priv->ssp;
int chn = params_channels(params);
u32 sscr0;
u32 sspsp;
@@ -642,12 +673,12 @@ static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
int ret = 0;
struct ssp_priv *priv = cpu_dai->private_data;
- struct ssp_device *ssp = priv->dev.ssp;
+ struct ssp_device *ssp = priv->ssp;
int val;
switch (cmd) {
case SNDRV_PCM_TRIGGER_RESUME:
- ssp_enable(&priv->dev);
+ ssp_enable(ssp);
break;
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
val = ssp_read_reg(ssp, SSCR1);
@@ -666,7 +697,7 @@ static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd,
else
val |= SSCR1_RSRE;
ssp_write_reg(ssp, SSCR1, val);
- ssp_enable(&priv->dev);
+ ssp_enable(ssp);
break;
case SNDRV_PCM_TRIGGER_STOP:
val = ssp_read_reg(ssp, SSCR1);
@@ -677,7 +708,7 @@ static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd,
ssp_write_reg(ssp, SSCR1, val);
break;
case SNDRV_PCM_TRIGGER_SUSPEND:
- ssp_disable(&priv->dev);
+ ssp_disable(ssp);
break;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
val = ssp_read_reg(ssp, SSCR1);
@@ -707,8 +738,8 @@ static int pxa_ssp_probe(struct platform_device *pdev,
if (!priv)
return -ENOMEM;
- priv->dev.ssp = ssp_request(dai->id + 1, "SoC audio");
- if (priv->dev.ssp == NULL) {
+ priv->ssp = ssp_request(dai->id + 1, "SoC audio");
+ if (priv->ssp == NULL) {
ret = -ENODEV;
goto err_priv;
}
@@ -727,7 +758,7 @@ static void pxa_ssp_remove(struct platform_device *pdev,
struct snd_soc_dai *dai)
{
struct ssp_priv *priv = dai->private_data;
- ssp_free(priv->dev.ssp);
+ ssp_free(priv->ssp);
}
#define PXA_SSP_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.c b/sound/soc/s3c24xx/s3c64xx-i2s.c
index 93ed3aa..a72c251 100644
--- a/sound/soc/s3c24xx/s3c64xx-i2s.c
+++ b/sound/soc/s3c24xx/s3c64xx-i2s.c
@@ -22,8 +22,8 @@
#include <sound/soc.h>
#include <plat/regs-s3c2412-iis.h>
-#include <plat/gpio-bank-d.h>
-#include <plat/gpio-bank-e.h>
+#include <mach/gpio-bank-d.h>
+#include <mach/gpio-bank-e.h>
#include <plat/gpio-cfg.h>
#include <mach/map.h>
diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig
index 1066749..f07f6d8 100644
--- a/sound/soc/sh/Kconfig
+++ b/sound/soc/sh/Kconfig
@@ -32,6 +32,7 @@ config SND_SOC_SH4_SIU
select DMA_ENGINE
select DMADEVICES
select SH_DMAE
+ select FW_LOADER
##
## Boards
diff --git a/sound/soc/sh/siu.h b/sound/soc/sh/siu.h
index 9cc04ab..c0bfab8 100644
--- a/sound/soc/sh/siu.h
+++ b/sound/soc/sh/siu.h
@@ -72,7 +72,7 @@ struct siu_firmware {
#include <linux/interrupt.h>
#include <linux/io.h>
-#include <asm/dma-sh.h>
+#include <asm/dmaengine.h>
#include <sound/core.h>
#include <sound/pcm.h>
diff --git a/sound/soc/sh/siu_pcm.c b/sound/soc/sh/siu_pcm.c
index c5efc30..ba7f8d0 100644
--- a/sound/soc/sh/siu_pcm.c
+++ b/sound/soc/sh/siu_pcm.c
@@ -32,7 +32,7 @@
#include <sound/pcm_params.h>
#include <sound/soc-dai.h>
-#include <asm/dma-sh.h>
+#include <asm/dmaengine.h>
#include <asm/siu.h>
#include "siu.h"
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index a03bac9..c8b0556 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -427,24 +427,24 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
if (!runtime->hw.rates) {
printk(KERN_ERR "asoc: %s <-> %s No matching rates\n",
codec_dai->name, cpu_dai->name);
- goto machine_err;
+ goto config_err;
}
if (!runtime->hw.formats) {
printk(KERN_ERR "asoc: %s <-> %s No matching formats\n",
codec_dai->name, cpu_dai->name);
- goto machine_err;
+ goto config_err;
}
if (!runtime->hw.channels_min || !runtime->hw.channels_max) {
printk(KERN_ERR "asoc: %s <-> %s No matching channels\n",
codec_dai->name, cpu_dai->name);
- goto machine_err;
+ goto config_err;
}
/* Symmetry only applies if we've already got an active stream. */
if (cpu_dai->active || codec_dai->active) {
ret = soc_pcm_apply_symmetry(substream);
if (ret != 0)
- goto machine_err;
+ goto config_err;
}
pr_debug("asoc: %s <-> %s info:\n", codec_dai->name, cpu_dai->name);
@@ -464,10 +464,14 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
mutex_unlock(&pcm_mutex);
return 0;
-machine_err:
+config_err:
if (machine->ops && machine->ops->shutdown)
machine->ops->shutdown(substream);
+machine_err:
+ if (codec_dai->ops->shutdown)
+ codec_dai->ops->shutdown(substream, codec_dai);
+
codec_dai_err:
if (platform->pcm_ops->close)
platform->pcm_ops->close(substream);
diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig
index 8c29258..c570ae3 100644
--- a/sound/usb/Kconfig
+++ b/sound/usb/Kconfig
@@ -22,13 +22,13 @@ config SND_USB_AUDIO
will be called snd-usb-audio.
config SND_USB_UA101
- tristate "Edirol UA-101 driver (EXPERIMENTAL)"
+ tristate "Edirol UA-101/UA-1000 driver (EXPERIMENTAL)"
depends on EXPERIMENTAL
select SND_PCM
select SND_RAWMIDI
help
- Say Y here to include support for the Edirol UA-101 audio/MIDI
- interface.
+ Say Y here to include support for the Edirol UA-101 and UA-1000
+ audio/MIDI interfaces.
To compile this driver as a module, choose M here: the module
will be called snd-ua101.
diff --git a/sound/usb/caiaq/midi.h b/sound/usb/caiaq/midi.h
index 9d16db0..380f984 100644
--- a/sound/usb/caiaq/midi.h
+++ b/sound/usb/caiaq/midi.h
@@ -3,6 +3,6 @@
int snd_usb_caiaq_midi_init(struct snd_usb_caiaqdev *dev);
void snd_usb_caiaq_midi_handle_input(struct snd_usb_caiaqdev *dev, int port, const char *buf, int len);
-void snd_usb_caiaq_midi_output_done(struct urb* urb);
+void snd_usb_caiaq_midi_output_done(struct urb *urb);
#endif /* CAIAQ_MIDI_H */
diff --git a/sound/usb/ua101.c b/sound/usb/ua101.c
index 4f4ccdf..3d458d3 100644
--- a/sound/usb/ua101.c
+++ b/sound/usb/ua101.c
@@ -1,5 +1,5 @@
/*
- * Edirol UA-101 driver
+ * Edirol UA-101/UA-1000 driver
* Copyright (c) Clemens Ladisch <clemens@ladisch.de>
*
* This driver is free software: you can redistribute it and/or modify
@@ -25,13 +25,10 @@
#include <sound/pcm_params.h>
#include "usbaudio.h"
-MODULE_DESCRIPTION("Edirol UA-101 driver");
+MODULE_DESCRIPTION("Edirol UA-101/1000 driver");
MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
MODULE_LICENSE("GPL v2");
-MODULE_SUPPORTED_DEVICE("{{Edirol,UA-101}}");
-
-/* I use my UA-1A for testing because I don't have a UA-101 ... */
-#define UA1A_HACK
+MODULE_SUPPORTED_DEVICE("{{Edirol,UA-101},{Edirol,UA-1000}}");
/*
* Should not be lower than the minimum scheduling delay of the host
@@ -132,9 +129,6 @@ struct ua101 {
dma_addr_t dma;
} buffers[MAX_MEMORY_BUFFERS];
} capture, playback;
-
- unsigned int fps[10];
- unsigned int frame_counter;
};
static DEFINE_MUTEX(devices_mutex);
@@ -424,16 +418,6 @@ static void capture_urb_complete(struct urb *urb)
if (do_period_elapsed)
snd_pcm_period_elapsed(stream->substream);
- /* for debugging: measure the sample rate relative to the USB clock */
- ua->fps[ua->frame_counter++ / ua->packets_per_second] += frames;
- if (ua->frame_counter >= ARRAY_SIZE(ua->fps) * ua->packets_per_second) {
- printk(KERN_DEBUG "capture rate:");
- for (frames = 0; frames < ARRAY_SIZE(ua->fps); ++frames)
- printk(KERN_CONT " %u", ua->fps[frames]);
- printk(KERN_CONT "\n");
- memset(ua->fps, 0, sizeof(ua->fps));
- ua->frame_counter = 0;
- }
return;
stream_stopped:
@@ -1200,13 +1184,30 @@ static int ua101_probe(struct usb_interface *interface,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
.data = &midi_ep
};
+ static const int intf_numbers[2][3] = {
+ { /* UA-101 */
+ [INTF_PLAYBACK] = 0,
+ [INTF_CAPTURE] = 1,
+ [INTF_MIDI] = 2,
+ },
+ { /* UA-1000 */
+ [INTF_CAPTURE] = 1,
+ [INTF_PLAYBACK] = 2,
+ [INTF_MIDI] = 3,
+ },
+ };
struct snd_card *card;
struct ua101 *ua;
unsigned int card_index, i;
+ int is_ua1000;
+ const char *name;
char usb_path[32];
int err;
- if (interface->altsetting->desc.bInterfaceNumber != 0)
+ is_ua1000 = usb_id->idProduct == 0x0044;
+
+ if (interface->altsetting->desc.bInterfaceNumber !=
+ intf_numbers[is_ua1000][0])
return -ENODEV;
mutex_lock(&devices_mutex);
@@ -1239,20 +1240,13 @@ static int ua101_probe(struct usb_interface *interface,
init_waitqueue_head(&ua->rate_feedback_wait);
init_waitqueue_head(&ua->alsa_playback_wait);
-#ifdef UA1A_HACK
- if (ua->dev->descriptor.idProduct == cpu_to_le16(0x0018)) {
- ua->intf[2] = interface;
- ua->intf[0] = usb_ifnum_to_if(ua->dev, 1);
- ua->intf[1] = usb_ifnum_to_if(ua->dev, 2);
- usb_driver_claim_interface(&ua101_driver, ua->intf[0], ua);
- usb_driver_claim_interface(&ua101_driver, ua->intf[1], ua);
- } else {
-#endif
ua->intf[0] = interface;
for (i = 1; i < ARRAY_SIZE(ua->intf); ++i) {
- ua->intf[i] = usb_ifnum_to_if(ua->dev, i);
+ ua->intf[i] = usb_ifnum_to_if(ua->dev,
+ intf_numbers[is_ua1000][i]);
if (!ua->intf[i]) {
- dev_err(&ua->dev->dev, "interface %u not found\n", i);
+ dev_err(&ua->dev->dev, "interface %u not found\n",
+ intf_numbers[is_ua1000][i]);
err = -ENXIO;
goto probe_error;
}
@@ -1264,39 +1258,19 @@ static int ua101_probe(struct usb_interface *interface,
goto probe_error;
}
}
-#ifdef UA1A_HACK
- }
-#endif
snd_card_set_dev(card, &interface->dev);
-#ifdef UA1A_HACK
- if (ua->dev->descriptor.idProduct == cpu_to_le16(0x0018)) {
- ua->format_bit = SNDRV_PCM_FMTBIT_S16_LE;
- ua->rate = 44100;
- ua->packets_per_second = 1000;
- ua->capture.channels = 2;
- ua->playback.channels = 2;
- ua->capture.frame_bytes = 4;
- ua->playback.frame_bytes = 4;
- ua->capture.usb_pipe = usb_rcvisocpipe(ua->dev, 2);
- ua->playback.usb_pipe = usb_sndisocpipe(ua->dev, 1);
- ua->capture.max_packet_bytes = 192;
- ua->playback.max_packet_bytes = 192;
- } else {
-#endif
err = detect_usb_format(ua);
if (err < 0)
goto probe_error;
-#ifdef UA1A_HACK
- }
-#endif
+ name = usb_id->idProduct == 0x0044 ? "UA-1000" : "UA-101";
strcpy(card->driver, "UA-101");
- strcpy(card->shortname, "UA-101");
+ strcpy(card->shortname, name);
usb_make_path(ua->dev, usb_path, sizeof(usb_path));
snprintf(ua->card->longname, sizeof(ua->card->longname),
- "EDIROL UA-101 (serial %s), %u Hz at %s, %s speed",
+ "EDIROL %s (serial %s), %u Hz at %s, %s speed", name,
ua->dev->serial ? ua->dev->serial : "?", ua->rate, usb_path,
ua->dev->speed == USB_SPEED_HIGH ? "high" : "full");
@@ -1314,24 +1288,18 @@ static int ua101_probe(struct usb_interface *interface,
if (err < 0)
goto probe_error;
- err = snd_pcm_new(card, "UA-101", 0, 1, 1, &ua->pcm);
+ err = snd_pcm_new(card, name, 0, 1, 1, &ua->pcm);
if (err < 0)
goto probe_error;
ua->pcm->private_data = ua;
- strcpy(ua->pcm->name, "UA-101");
+ strcpy(ua->pcm->name, name);
snd_pcm_set_ops(ua->pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_pcm_ops);
snd_pcm_set_ops(ua->pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_pcm_ops);
-#ifdef UA1A_HACK
- if (ua->dev->descriptor.idProduct != cpu_to_le16(0x0018)) {
-#endif
err = snd_usbmidi_create(card, ua->intf[INTF_MIDI],
&ua->midi_list, &midi_quirk);
if (err < 0)
goto probe_error;
-#ifdef UA1A_HACK
- }
-#endif
err = snd_card_register(card);
if (err < 0)
@@ -1386,11 +1354,9 @@ static void ua101_disconnect(struct usb_interface *interface)
}
static struct usb_device_id ua101_ids[] = {
-#ifdef UA1A_HACK
- { USB_DEVICE(0x0582, 0x0018) },
-#endif
- { USB_DEVICE(0x0582, 0x007d) },
- { USB_DEVICE(0x0582, 0x008d) },
+ { USB_DEVICE(0x0582, 0x0044) }, /* UA-1000 high speed */
+ { USB_DEVICE(0x0582, 0x007d) }, /* UA-101 high speed */
+ { USB_DEVICE(0x0582, 0x008d) }, /* UA-101 full speed */
{ }
};
MODULE_DEVICE_TABLE(usb, ua101_ids);
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index c539f7f..11b0826 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -2483,7 +2483,6 @@ static int parse_audio_format_i_type(struct snd_usb_audio *chip,
sample_width, sample_bytes);
}
/* check the format byte size */
- printk(" XXXXX SAMPLE BYTES %d\n", sample_bytes);
switch (sample_bytes) {
case 1:
pcm_format = SNDRV_PCM_FORMAT_S8;
@@ -2581,6 +2580,9 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof
chip->usb_id == USB_ID(0x0d8c, 0x0102)) &&
fp->altsetting == 5 && fp->maxpacksize == 392)
rate = 96000;
+ /* Creative VF0470 Live Cam reports 16 kHz instead of 8kHz */
+ if (rate == 16000 && chip->usb_id == USB_ID(0x041e, 0x4068))
+ rate = 8000;
fp->rate_table[fp->nr_rates] = rate;
if (!fp->rate_min || rate < fp->rate_min)
fp->rate_min = rate;
@@ -3386,58 +3388,6 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip,
return 0;
}
-/*
- * Create a stream for an Edirol UA-1000 interface.
- */
-static int create_ua1000_quirk(struct snd_usb_audio *chip,
- struct usb_interface *iface,
- const struct snd_usb_audio_quirk *quirk)
-{
- static const struct audioformat ua1000_format = {
- .format = SNDRV_PCM_FORMAT_S32_LE,
- .fmt_type = UAC_FORMAT_TYPE_I,
- .altsetting = 1,
- .altset_idx = 1,
- .attributes = 0,
- .rates = SNDRV_PCM_RATE_CONTINUOUS,
- };
- struct usb_host_interface *alts;
- struct usb_interface_descriptor *altsd;
- struct audioformat *fp;
- int stream, err;
-
- if (iface->num_altsetting != 2)
- return -ENXIO;
- alts = &iface->altsetting[1];
- altsd = get_iface_desc(alts);
- if (alts->extralen != 11 || alts->extra[1] != USB_DT_CS_INTERFACE ||
- altsd->bNumEndpoints != 1)
- return -ENXIO;
-
- fp = kmemdup(&ua1000_format, sizeof(*fp), GFP_KERNEL);
- if (!fp)
- return -ENOMEM;
-
- fp->channels = alts->extra[4];
- fp->iface = altsd->bInterfaceNumber;
- fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
- fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
- fp->datainterval = parse_datainterval(chip, alts);
- fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
- fp->rate_max = fp->rate_min = combine_triple(&alts->extra[8]);
-
- stream = (fp->endpoint & USB_DIR_IN)
- ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
- err = add_audio_endpoint(chip, stream, fp);
- if (err < 0) {
- kfree(fp);
- return err;
- }
- /* FIXME: playback must be synchronized to capture */
- usb_set_interface(chip->dev, fp->iface, 0);
- return 0;
-}
-
static int snd_usb_create_quirk(struct snd_usb_audio *chip,
struct usb_interface *iface,
const struct snd_usb_audio_quirk *quirk);
@@ -3686,7 +3636,6 @@ static int snd_usb_create_quirk(struct snd_usb_audio *chip,
[QUIRK_MIDI_CME] = create_any_midi_quirk,
[QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk,
[QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk,
- [QUIRK_AUDIO_EDIROL_UA1000] = create_ua1000_quirk,
[QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk,
[QUIRK_AUDIO_ALIGN_TRANSFER] = create_align_transfer_quirk
};
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 6b016d4..42c299c 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -75,7 +75,6 @@ enum quirk_type {
QUIRK_MIDI_US122L,
QUIRK_AUDIO_STANDARD_INTERFACE,
QUIRK_AUDIO_FIXED_ENDPOINT,
- QUIRK_AUDIO_EDIROL_UA1000,
QUIRK_AUDIO_EDIROL_UAXX,
QUIRK_AUDIO_ALIGN_TRANSFER,
@@ -112,7 +111,7 @@ struct snd_usb_midi_endpoint_info {
/* for QUIRK_AUDIO/MIDI_STANDARD_INTERFACE, data is NULL */
-/* for QUIRK_AUDIO_EDIROL_UA700_UA25/UA1000, data is NULL */
+/* for QUIRK_AUDIO_EDIROL_UAXX, data is NULL */
/* for QUIRK_IGNORE_INTERFACE, data is NULL */
diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h
index f06faf7..2b426c1 100644
--- a/sound/usb/usbquirks.h
+++ b/sound/usb/usbquirks.h
@@ -1016,36 +1016,6 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
{
- USB_DEVICE(0x0582, 0x0044),
- .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
- .vendor_name = "Roland",
- .product_name = "UA-1000",
- .ifnum = QUIRK_ANY_INTERFACE,
- .type = QUIRK_COMPOSITE,
- .data = (const struct snd_usb_audio_quirk[]) {
- {
- .ifnum = 1,
- .type = QUIRK_AUDIO_EDIROL_UA1000
- },
- {
- .ifnum = 2,
- .type = QUIRK_AUDIO_EDIROL_UA1000
- },
- {
- .ifnum = 3,
- .type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const struct snd_usb_midi_endpoint_info) {
- .out_cables = 0x0003,
- .in_cables = 0x0003
- }
- },
- {
- .ifnum = -1
- }
- }
- }
-},
-{
/* has ID 0x0049 when not in "Advanced Driver" mode */
USB_DEVICE(0x0582, 0x0047),
.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {