From ce577e8cf5ddb4216553c9d563a9835d6de70ffa Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 3 Aug 2009 08:23:52 +0200 Subject: ALSA: hda - Fix quirk for Toshiba Satellite A135-S4527 Use model=lenovo instead of model=dallas for Toshiba Satellite A135-S4527 with ALC861-VD codec. Reference: Novell bnc#526325 https://bugzilla.novell.com/show_bug.cgi?id=526325 Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index b95df5d5dcc2..f6b4cbf1ead0 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -15157,7 +15157,7 @@ static struct snd_pci_quirk alc861vd_cfg_tbl[] = { SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST), SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba A135", ALC861VD_LENOVO), /*SND_PCI_QUIRK(0x1179, 0xff00, "DALLAS", ALC861VD_DALLAS),*/ /*lenovo*/ - SND_PCI_QUIRK(0x1179, 0xff01, "DALLAS", ALC861VD_DALLAS), + SND_PCI_QUIRK(0x1179, 0xff01, "Toshiba A135", ALC861VD_LENOVO), SND_PCI_QUIRK(0x1179, 0xff03, "Toshiba P205", ALC861VD_LENOVO), SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba L30-149", ALC861VD_DALLAS), SND_PCI_QUIRK(0x1565, 0x820d, "Biostar NF61S SE", ALC861VD_6ST_DIG), -- cgit v1.2.2 From deadff1665491afce124a8ff83f00f784161f660 Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Sat, 1 Aug 2009 18:45:16 +0800 Subject: ALSA: hda: track CIRB/CORB command/response states for each codec Recently we hit a bug in our dev board, whose HDMI codec#3 may emit redundant/spurious responses, which were then taken as responses to command for another onboard Realtek codec#2, and mess up both codecs. Extend the azx_rb.cmds and azx_rb.res to array and track each codec's commands/responses separately. This helps keep good codec safe from broken ones. Signed-off-by: Wu Fengguang Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 2 +- sound/pci/hda/hda_codec.h | 2 +- sound/pci/hda/hda_intel.c | 76 +++++++++++++++++++++++++++++++++-------------- 3 files changed, 56 insertions(+), 24 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 88480c0c58a0..c7df01b72cac 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -174,7 +174,7 @@ static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd, mutex_lock(&bus->cmd_mutex); err = bus->ops.command(bus, cmd); if (!err && res) - *res = bus->ops.get_response(bus); + *res = bus->ops.get_response(bus, codec->addr); mutex_unlock(&bus->cmd_mutex); snd_hda_power_down(codec); if (res && *res == -1 && bus->rirb_error) { diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index cad79efaabc9..1b75f28ed092 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -568,7 +568,7 @@ struct hda_bus_ops { /* send a single command */ int (*command)(struct hda_bus *bus, unsigned int cmd); /* get a response from the last command */ - unsigned int (*get_response)(struct hda_bus *bus); + unsigned int (*get_response)(struct hda_bus *bus, unsigned int addr); /* free the private data */ void (*private_free)(struct hda_bus *); /* attach a PCM stream */ diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 77c1b840ca8b..19e67a1b6026 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -253,7 +253,7 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; /* STATESTS int mask: S3,SD2,SD1,SD0 */ #define AZX_MAX_CODECS 4 -#define STATESTS_INT_MASK 0x0f +#define STATESTS_INT_MASK ((1 << AZX_MAX_CODECS) - 1) /* SD_CTL bits */ #define SD_CTL_STREAM_RESET 0x01 /* stream reset bit */ @@ -361,8 +361,8 @@ struct azx_rb { dma_addr_t addr; /* physical address of CORB/RIRB buffer */ /* for RIRB */ unsigned short rp, wp; /* read/write pointers */ - int cmds; /* number of pending requests */ - u32 res; /* last read value */ + int cmds[AZX_MAX_CODECS]; /* number of pending requests */ + u32 res[AZX_MAX_CODECS]; /* last read value */ }; struct azx { @@ -531,7 +531,8 @@ static void azx_init_cmd_io(struct azx *chip) /* RIRB set up */ chip->rirb.addr = chip->rb.addr + 2048; chip->rirb.buf = (u32 *)(chip->rb.area + 2048); - chip->rirb.wp = chip->rirb.rp = chip->rirb.cmds = 0; + chip->rirb.wp = chip->rirb.rp = 0; + memset(chip->rirb.cmds, 0, sizeof(chip->rirb.cmds)); azx_writel(chip, RIRBLBASE, (u32)chip->rirb.addr); azx_writel(chip, RIRBUBASE, upper_32_bits(chip->rirb.addr)); @@ -552,10 +553,35 @@ static void azx_free_cmd_io(struct azx *chip) azx_writeb(chip, CORBCTL, 0); } +static unsigned int azx_command_addr(u32 cmd) +{ + unsigned int addr = cmd >> 28; + + if (addr >= AZX_MAX_CODECS) { + snd_BUG(); + addr = 0; + } + + return addr; +} + +static unsigned int azx_response_addr(u32 res) +{ + unsigned int addr = res & 0xf; + + if (addr >= AZX_MAX_CODECS) { + snd_BUG(); + addr = 0; + } + + return addr; +} + /* send a command */ static int azx_corb_send_cmd(struct hda_bus *bus, u32 val) { struct azx *chip = bus->private_data; + unsigned int addr = azx_command_addr(val); unsigned int wp; /* add command to corb */ @@ -564,7 +590,7 @@ static int azx_corb_send_cmd(struct hda_bus *bus, u32 val) wp %= ICH6_MAX_CORB_ENTRIES; spin_lock_irq(&chip->reg_lock); - chip->rirb.cmds++; + chip->rirb.cmds[addr]++; chip->corb.buf[wp] = cpu_to_le32(val); azx_writel(chip, CORBWP, wp); spin_unlock_irq(&chip->reg_lock); @@ -578,13 +604,14 @@ static int azx_corb_send_cmd(struct hda_bus *bus, u32 val) static void azx_update_rirb(struct azx *chip) { unsigned int rp, wp; + unsigned int addr; u32 res, res_ex; wp = azx_readb(chip, RIRBWP); if (wp == chip->rirb.wp) return; chip->rirb.wp = wp; - + while (chip->rirb.rp != wp) { chip->rirb.rp++; chip->rirb.rp %= ICH6_MAX_RIRB_ENTRIES; @@ -592,18 +619,20 @@ static void azx_update_rirb(struct azx *chip) rp = chip->rirb.rp << 1; /* an RIRB entry is 8-bytes */ res_ex = le32_to_cpu(chip->rirb.buf[rp + 1]); res = le32_to_cpu(chip->rirb.buf[rp]); + addr = azx_response_addr(res_ex); if (res_ex & ICH6_RIRB_EX_UNSOL_EV) snd_hda_queue_unsol_event(chip->bus, res, res_ex); - else if (chip->rirb.cmds) { - chip->rirb.res = res; + else if (chip->rirb.cmds[addr]) { + chip->rirb.res[addr] = res; smp_wmb(); - chip->rirb.cmds--; + chip->rirb.cmds[addr]--; } } } /* receive a response */ -static unsigned int azx_rirb_get_response(struct hda_bus *bus) +static unsigned int azx_rirb_get_response(struct hda_bus *bus, + unsigned int addr) { struct azx *chip = bus->private_data; unsigned long timeout; @@ -616,10 +645,10 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus) azx_update_rirb(chip); spin_unlock_irq(&chip->reg_lock); } - if (!chip->rirb.cmds) { + if (!chip->rirb.cmds[addr]) { smp_rmb(); bus->rirb_error = 0; - return chip->rirb.res; /* the last value */ + return chip->rirb.res[addr]; /* the last value */ } if (time_after(jiffies, timeout)) break; @@ -692,7 +721,7 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus) */ /* receive a response */ -static int azx_single_wait_for_response(struct azx *chip) +static int azx_single_wait_for_response(struct azx *chip, unsigned int addr) { int timeout = 50; @@ -700,7 +729,7 @@ static int azx_single_wait_for_response(struct azx *chip) /* check IRV busy bit */ if (azx_readw(chip, IRS) & ICH6_IRS_VALID) { /* reuse rirb.res as the response return value */ - chip->rirb.res = azx_readl(chip, IR); + chip->rirb.res[addr] = azx_readl(chip, IR); return 0; } udelay(1); @@ -708,7 +737,7 @@ static int azx_single_wait_for_response(struct azx *chip) if (printk_ratelimit()) snd_printd(SFX "get_response timeout: IRS=0x%x\n", azx_readw(chip, IRS)); - chip->rirb.res = -1; + chip->rirb.res[addr] = -1; return -EIO; } @@ -716,6 +745,7 @@ static int azx_single_wait_for_response(struct azx *chip) static int azx_single_send_cmd(struct hda_bus *bus, u32 val) { struct azx *chip = bus->private_data; + unsigned int addr = azx_command_addr(val); int timeout = 50; bus->rirb_error = 0; @@ -728,7 +758,7 @@ static int azx_single_send_cmd(struct hda_bus *bus, u32 val) azx_writel(chip, IC, val); azx_writew(chip, IRS, azx_readw(chip, IRS) | ICH6_IRS_BUSY); - return azx_single_wait_for_response(chip); + return azx_single_wait_for_response(chip, addr); } udelay(1); } @@ -739,10 +769,11 @@ static int azx_single_send_cmd(struct hda_bus *bus, u32 val) } /* receive a response */ -static unsigned int azx_single_get_response(struct hda_bus *bus) +static unsigned int azx_single_get_response(struct hda_bus *bus, + unsigned int addr) { struct azx *chip = bus->private_data; - return chip->rirb.res; + return chip->rirb.res[addr]; } /* @@ -765,13 +796,14 @@ static int azx_send_cmd(struct hda_bus *bus, unsigned int val) } /* get a response */ -static unsigned int azx_get_response(struct hda_bus *bus) +static unsigned int azx_get_response(struct hda_bus *bus, + unsigned int addr) { struct azx *chip = bus->private_data; if (chip->single_cmd) - return azx_single_get_response(bus); + return azx_single_get_response(bus, addr); else - return azx_rirb_get_response(bus); + return azx_rirb_get_response(bus, addr); } #ifdef CONFIG_SND_HDA_POWER_SAVE @@ -1245,7 +1277,7 @@ static int probe_codec(struct azx *chip, int addr) chip->probing = 1; azx_send_cmd(chip->bus, cmd); - res = azx_get_response(chip->bus); + res = azx_get_response(chip->bus, addr); chip->probing = 0; if (res == -1) return -EIO; -- cgit v1.2.2 From a678cdee25a387c8fc3b2754974695412baf1d85 Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Sat, 1 Aug 2009 18:46:46 +0800 Subject: ALSA: hda: take cmd_mutex in probe_codec() Now that each codec will have its own module, it is possible for the user to load one codec while another one is running. So cmd_mutex would be a safe addition to probe_codec(). Signed-off-by: Wu Fengguang Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sound') diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 19e67a1b6026..ddabc827ac44 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1275,10 +1275,12 @@ static int probe_codec(struct azx *chip, int addr) (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID; unsigned int res; + mutex_lock(&chip->bus->cmd_mutex); chip->probing = 1; azx_send_cmd(chip->bus, cmd); res = azx_get_response(chip->bus, addr); chip->probing = 0; + mutex_unlock(&chip->bus->cmd_mutex); if (res == -1) return -EIO; snd_printdd(SFX "codec #%d probed OK\n", addr); -- cgit v1.2.2 From cdb1fbf23181c133fb24f12ad14ccea7dc399599 Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Sat, 1 Aug 2009 18:47:41 +0800 Subject: ALSA: hda: take reg_lock in azx_init_cmd_io/azx_free_cmd_io Just for safety. azx_init_cmd_io() and azx_free_cmd_io() may be called when switching to single command mode. Signed-off-by: Wu Fengguang Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'sound') diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index ddabc827ac44..b6e6314d0069 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -513,6 +513,7 @@ static int azx_alloc_cmd_io(struct azx *chip) static void azx_init_cmd_io(struct azx *chip) { + spin_lock_irq(&chip->reg_lock); /* CORB set up */ chip->corb.addr = chip->rb.addr; chip->corb.buf = (u32 *)chip->rb.area; @@ -544,13 +545,16 @@ static void azx_init_cmd_io(struct azx *chip) azx_writew(chip, RINTCNT, 1); /* enable rirb dma and response irq */ azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN | ICH6_RBCTL_IRQ_EN); + spin_unlock_irq(&chip->reg_lock); } static void azx_free_cmd_io(struct azx *chip) { + spin_lock_irq(&chip->reg_lock); /* disable ringbuffer DMAs */ azx_writeb(chip, RIRBCTL, 0); azx_writeb(chip, CORBCTL, 0); + spin_unlock_irq(&chip->reg_lock); } static unsigned int azx_command_addr(u32 cmd) -- cgit v1.2.2 From c32649feb4573b31f0a2bfdf35cbe1351256c764 Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Sat, 1 Aug 2009 18:48:12 +0800 Subject: ALSA: hda: read CORBWP inside reg_lock This converts the last CORBWP access outside of reg_lock. Signed-off-by: Wu Fengguang Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index b6e6314d0069..df6d9820efad 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -588,15 +588,17 @@ static int azx_corb_send_cmd(struct hda_bus *bus, u32 val) unsigned int addr = azx_command_addr(val); unsigned int wp; + spin_lock_irq(&chip->reg_lock); + /* add command to corb */ wp = azx_readb(chip, CORBWP); wp++; wp %= ICH6_MAX_CORB_ENTRIES; - spin_lock_irq(&chip->reg_lock); chip->rirb.cmds[addr]++; chip->corb.buf[wp] = cpu_to_le32(val); azx_writel(chip, CORBWP, wp); + spin_unlock_irq(&chip->reg_lock); return 0; -- cgit v1.2.2 From feb273404f15d86098cb0e81e46330d5c1e22b1b Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Sat, 1 Aug 2009 19:17:14 +0800 Subject: ALSA: hda: remember last command for each codec Signed-off-by: Wu Fengguang Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index df6d9820efad..7c43f92de2fa 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -418,7 +418,7 @@ struct azx { unsigned int probing :1; /* codec probing phase */ /* for debugging */ - unsigned int last_cmd; /* last issued command (to sync) */ + unsigned int last_cmd[AZX_MAX_CODECS]; /* for pending irqs */ struct work_struct irq_pending_work; @@ -668,7 +668,8 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus, if (chip->msi) { snd_printk(KERN_WARNING SFX "No response from codec, " - "disabling MSI: last cmd=0x%08x\n", chip->last_cmd); + "disabling MSI: last cmd=0x%08x\n", + chip->last_cmd[addr]); free_irq(chip->irq, chip); chip->irq = -1; pci_disable_msi(chip->pci); @@ -683,7 +684,7 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus, if (!chip->polling_mode) { snd_printk(KERN_WARNING SFX "azx_get_response timeout, " "switching to polling mode: last cmd=0x%08x\n", - chip->last_cmd); + chip->last_cmd[addr]); chip->polling_mode = 1; goto again; } @@ -707,7 +708,7 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus, snd_printk(KERN_ERR "hda_intel: azx_get_response timeout, " "switching to single_cmd mode: last cmd=0x%08x\n", - chip->last_cmd); + chip->last_cmd[addr]); chip->single_cmd = 1; bus->response_reset = 0; /* re-initialize CORB/RIRB */ @@ -794,7 +795,7 @@ static int azx_send_cmd(struct hda_bus *bus, unsigned int val) { struct azx *chip = bus->private_data; - chip->last_cmd = val; + chip->last_cmd[azx_command_addr(val)] = val; if (chip->single_cmd) return azx_single_send_cmd(bus, val); else -- cgit v1.2.2 From e310bb0646e57a4f9182865115c5780931456c65 Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Sat, 1 Aug 2009 19:18:45 +0800 Subject: ALSA: hda: warn on spurious response To help disclose hardware bugs. Signed-off-by: Wu Fengguang Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 7c43f92de2fa..175f07a381ba 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -632,7 +632,11 @@ static void azx_update_rirb(struct azx *chip) chip->rirb.res[addr] = res; smp_wmb(); chip->rirb.cmds[addr]--; - } + } else + snd_printk(KERN_ERR SFX "spurious response %#x:%#x, " + "last cmd=%#08x\n", + res, res_ex, + chip->last_cmd[addr]); } } -- cgit v1.2.2 From 84d3dc200fc8b878acf7c1840b238e6a0450e4d0 Mon Sep 17 00:00:00 2001 From: Chengu Wang Date: Thu, 30 Jul 2009 19:43:55 +0800 Subject: ALSA: hda: Correct EAPD for Dell Inspiron 1525 The commit 24918b61b55c21e09a3e07cd82e1b3a8154782dc statically changes the model from dell-bios to dell-3stack to solve the sound decreasing regression (http://lkml.org/lkml/2008/9/12/203), however it leads to another problem that the 2nd headphone jack doesn't work (https://bugtrack.alsa-project.org/alsa-bug/view.php?id=3987). So I think the commit 249**2dc is just a workaround. I would like to give a true solution here. The datasheet for STAC9228 says, GPIO2 is the same pin as VOL DOWN, and the EAPD pin is GPIO0. This is why the sound decreases if we set EAPD as GPIO2. This patch changes EAPD to GPIO0 to solve the problem. Signed-off-by: Chengu Wang Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 5383d8cff88b..456ef6ac12e4 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -2266,7 +2266,7 @@ static struct snd_pci_quirk stac927x_cfg_tbl[] = { SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f3, "Dell Inspiron 1420", STAC_DELL_BIOS), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0227, "Dell Vostro 1400 ", STAC_DELL_BIOS), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x022e, "Dell ", STAC_DELL_BIOS), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x022f, "Dell Inspiron 1525", STAC_DELL_3ST), + SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x022f, "Dell Inspiron 1525", STAC_DELL_BIOS), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0242, "Dell ", STAC_DELL_BIOS), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0243, "Dell ", STAC_DELL_BIOS), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ff, "Dell ", STAC_DELL_BIOS), @@ -5645,6 +5645,13 @@ static int patch_stac927x(struct hda_codec *codec) /* GPIO2 High = Enable EAPD */ spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x04; spec->gpio_data = 0x04; + switch (codec->subsystem_id) { + case 0x1028022f: + /* correct EAPD to be GPIO0 */ + spec->eapd_mask = spec->gpio_mask = 0x01; + spec->gpio_dir = spec->gpio_data = 0x01; + break; + }; spec->dmic_nids = stac927x_dmic_nids; spec->num_dmics = STAC927X_NUM_DMICS; -- cgit v1.2.2 From 4b35d2ca2307d40ccb6b3b6f9cc25ac9178b2a6c Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Sun, 2 Aug 2009 13:30:45 +0200 Subject: ALSA: hda - Read buffer overflow Check whether index is within bounds before testing the element. Signed-off-by: Roel Kluin Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index f6b4cbf1ead0..51c44fdbc0f0 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -559,7 +559,7 @@ static int alc_pin_mode_get(struct snd_kcontrol *kcontrol, /* Find enumerated value for current pinctl setting */ i = alc_pin_mode_min(dir); - while (alc_pin_mode_values[i] != pinctl && i <= alc_pin_mode_max(dir)) + while (i <= alc_pin_mode_max(dir) && alc_pin_mode_values[i] != pinctl) i++; *valp = i <= alc_pin_mode_max(dir) ? i: alc_pin_mode_min(dir); return 0; -- cgit v1.2.2 From afc5e65245255a268ab22a20477ed2c9f2cdfcd3 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 7 Aug 2009 16:33:53 +0200 Subject: ASoC: Add missing DRV_NAME definitions for fsl/* drivers Module builds are broken due to missing DRV_NAME for efika-audio-fabric and pcm030-audio-fabric. Signed-off-by: Takashi Iwai --- sound/soc/fsl/efika-audio-fabric.c | 2 ++ sound/soc/fsl/pcm030-audio-fabric.c | 2 ++ 2 files changed, 4 insertions(+) (limited to 'sound') diff --git a/sound/soc/fsl/efika-audio-fabric.c b/sound/soc/fsl/efika-audio-fabric.c index 85b0e7569504..3326e2a1e863 100644 --- a/sound/soc/fsl/efika-audio-fabric.c +++ b/sound/soc/fsl/efika-audio-fabric.c @@ -30,6 +30,8 @@ #include "mpc5200_psc_ac97.h" #include "../codecs/stac9766.h" +#define DRV_NAME "efika-audio-fabric" + static struct snd_soc_device device; static struct snd_soc_card card; diff --git a/sound/soc/fsl/pcm030-audio-fabric.c b/sound/soc/fsl/pcm030-audio-fabric.c index 8766f7a3893d..b928ef7d28eb 100644 --- a/sound/soc/fsl/pcm030-audio-fabric.c +++ b/sound/soc/fsl/pcm030-audio-fabric.c @@ -30,6 +30,8 @@ #include "mpc5200_psc_ac97.h" #include "../codecs/wm9712.h" +#define DRV_NAME "pcm030-audio-fabric" + static struct snd_soc_device device; static struct snd_soc_card card; -- cgit v1.2.2 From 100d5eb36ba20dc0b99a17ea2b9800c567bfc3d1 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 10 Aug 2009 11:55:51 +0200 Subject: ALSA: hda - Add missing vmaster initialization for ALC269 Without the initialization of vmaster NID, the dB information got confused for ALC269 codec. Reference: Novell bnc#527361 https://bugzilla.novell.com/show_bug.cgi?id=527361 Signed-off-by: Takashi Iwai Cc: --- sound/pci/hda/patch_realtek.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 51c44fdbc0f0..5cc927f47837 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -13563,6 +13563,8 @@ static int patch_alc269(struct hda_codec *codec) set_capture_mixer(spec); set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); + spec->vmaster_nid = 0x02; + codec->patch_ops = alc_patch_ops; if (board_config == ALC269_AUTO) spec->init_hook = alc269_auto_init; -- cgit v1.2.2 From dd704698f56c1451fc9c5daadcd6e3a089de2c40 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 11 Aug 2009 08:45:11 +0200 Subject: ALSA: hda - Don't override ADC definitions for ALC codecs ALC269 and ALC861-VD parsers override the ADC definitions unconditionally without checking the spec definition. This causes the problem when any inconsistent ADC is set up in the device quirk (like ALC272 with digital-mic). This patch avoids the overriding by adding the proper checks. Reference: Novell bnc#529467 https://bugzilla.novell.com/show_bug.cgi?id=529467 Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 5cc927f47837..fea976793ae5 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -15579,9 +15579,12 @@ static int patch_alc861vd(struct hda_codec *codec) spec->stream_digital_playback = &alc861vd_pcm_digital_playback; spec->stream_digital_capture = &alc861vd_pcm_digital_capture; - spec->adc_nids = alc861vd_adc_nids; - spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids); - spec->capsrc_nids = alc861vd_capsrc_nids; + if (!spec->adc_nids) { + spec->adc_nids = alc861vd_adc_nids; + spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids); + } + if (!spec->capsrc_nids) + spec->capsrc_nids = alc861vd_capsrc_nids; set_capture_mixer(spec); set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); @@ -17498,9 +17501,12 @@ static int patch_alc662(struct hda_codec *codec) spec->stream_digital_playback = &alc662_pcm_digital_playback; spec->stream_digital_capture = &alc662_pcm_digital_capture; - spec->adc_nids = alc662_adc_nids; - spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids); - spec->capsrc_nids = alc662_capsrc_nids; + if (!spec->adc_nids) { + spec->adc_nids = alc662_adc_nids; + spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids); + } + if (!spec->capsrc_nids) + spec->capsrc_nids = alc662_capsrc_nids; if (!spec->cap_mixer) set_capture_mixer(spec); -- cgit v1.2.2 From 150fe14c1a1f08cb430d8382bf5554c2a168b79b Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Wed, 19 Aug 2009 16:58:59 +0800 Subject: ALSA: hda: enable speaker output for Compaq 6530s/6531s HP Compaq 6530s and 6531s internal speaker is silence or becomes silence within 1 minute after fresh boot. It is found that pin 0x1c must be set to PIN_OUT mode to make the speaker work. This is weird - line-in pin 0x1c and speaker pin 0x16 seem to be unrelated. The codec differences before/after patch are: @@ Node 0x17 [Pin Complex] wcaps 0x40020b: Pin Default 0x41a6e130: [N/A] Mic at Ext Rear Conn = Digital, Color = White DefAssociation = 0x3, Sequence = 0x0 Misc = NO_PRESENCE - Pin-ctls: 0x24: IN + Pin-ctls: 0x40: OUT @@ Node 0x1c [Pin Complex] wcaps 0x40018d: Pin Default 0x41813021: [N/A] Line In at Ext Rear Conn = 1/8, Color = Blue DefAssociation = 0x2, Sequence = 0x1 - Pin-ctls: 0x24: IN VREF_80 + Pin-ctls: 0x40: OUT VREF_HIZ Unsolicited: tag=00, enabled=0 Connection: 1 0x24 Tests show that it won't impact (external) Mic recording. Reported-by: "Lin, Ming M" Signed-off-by: Wu Fengguang Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_analog.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index e8e6a43865c2..f2bb48034170 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -3823,9 +3823,11 @@ static struct hda_verb ad1884a_laptop_verbs[] = { /* Port-F (int speaker) mixer - route only from analog mixer */ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - /* Port-F pin */ - {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, + /* Port-F (int speaker) pin */ + {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + /* required for compaq 6530s/6531s speaker output */ + {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* Port-C pin - internal mic-in */ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */ -- cgit v1.2.2 From ae709440edb2d36f51f5ea51cfab931f45c03e02 Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Wed, 19 Aug 2009 17:05:11 +0800 Subject: ALSA: hda: add model for Intel DG45ID/DG45FC boards The BIOS pin configs are in fact correct and shall not be overwritten. Signed-off-by: Wu Fengguang Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 456ef6ac12e4..6990cfcb6a38 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -76,6 +76,7 @@ enum { STAC_92HD73XX_AUTO, STAC_92HD73XX_NO_JD, /* no jack-detection */ STAC_92HD73XX_REF, + STAC_92HD73XX_INTEL, STAC_DELL_M6_AMIC, STAC_DELL_M6_DMIC, STAC_DELL_M6_BOTH, @@ -1777,6 +1778,7 @@ static const char *stac92hd73xx_models[STAC_92HD73XX_MODELS] = { [STAC_92HD73XX_AUTO] = "auto", [STAC_92HD73XX_NO_JD] = "no-jd", [STAC_92HD73XX_REF] = "ref", + [STAC_92HD73XX_INTEL] = "intel", [STAC_DELL_M6_AMIC] = "dell-m6-amic", [STAC_DELL_M6_DMIC] = "dell-m6-dmic", [STAC_DELL_M6_BOTH] = "dell-m6", @@ -1789,6 +1791,10 @@ static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = { "DFI LanParty", STAC_92HD73XX_REF), SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, "DFI LanParty", STAC_92HD73XX_REF), + SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5002, + "Intel DG45ID", STAC_92HD73XX_INTEL), + SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5003, + "Intel DG45FC", STAC_92HD73XX_INTEL), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0254, "Dell Studio 1535", STAC_DELL_M6_DMIC), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0255, -- cgit v1.2.2 From 3abf2f3639959e4f53f209f93cd4d93fe9356de1 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 19 Aug 2009 20:05:02 +0200 Subject: ALSA: hda - Fix probe of Toshiba laptops with ALC268 codec There are many variants of Toshiba laptops with ALC268 codec, and it seems that a few of them don't work with model=toshiba preset since they have the secondary ALC268 codec just for HDMI output. This is a regression due to the previous clean-up work to merge all Toshiba quirk entries into a single check. This patch adds the identification of such laptops to apply the standard BIOS-probing method. Unfortunately, Toshiba laptops have all the same PCI SSID, so we need to check the codec SSID to identify each device. Tested-by: Alexey Dobriyan Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index fea976793ae5..6f683e451f2b 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -12521,8 +12521,6 @@ static struct snd_pci_quirk alc268_cfg_tbl[] = { ALC268_TOSHIBA), SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC268_3ST), SND_PCI_QUIRK(0x1170, 0x0040, "ZEPTO", ALC268_ZEPTO), - SND_PCI_QUIRK_MASK(0x1179, 0xff00, 0xff00, "TOSHIBA A/Lx05", - ALC268_TOSHIBA), SND_PCI_QUIRK(0x14c0, 0x0025, "COMPAL IFL90/JFL-92", ALC268_TOSHIBA), SND_PCI_QUIRK(0x152d, 0x0763, "Diverse (CPR2000)", ALC268_ACER), SND_PCI_QUIRK(0x152d, 0x0771, "Quanta IL1", ALC267_QUANTA_IL1), @@ -12530,6 +12528,15 @@ static struct snd_pci_quirk alc268_cfg_tbl[] = { {} }; +/* Toshiba laptops have no unique PCI SSID but only codec SSID */ +static struct snd_pci_quirk alc268_ssid_cfg_tbl[] = { + SND_PCI_QUIRK(0x1179, 0xff0a, "TOSHIBA X-200", ALC268_AUTO), + SND_PCI_QUIRK(0x1179, 0xff0e, "TOSHIBA X-200 HDMI", ALC268_AUTO), + SND_PCI_QUIRK_MASK(0x1179, 0xff00, 0xff00, "TOSHIBA A/Lx05", + ALC268_TOSHIBA), + {} +}; + static struct alc_config_preset alc268_presets[] = { [ALC267_QUANTA_IL1] = { .mixers = { alc267_quanta_il1_mixer, alc268_beep_mixer }, @@ -12696,6 +12703,10 @@ static int patch_alc268(struct hda_codec *codec) alc268_models, alc268_cfg_tbl); + 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); + if (board_config < 0 || board_config >= ALC268_MODEL_LAST) { printk(KERN_INFO "hda_codec: Unknown model for %s, " "trying auto-probe from BIOS...\n", codec->chip_name); -- cgit v1.2.2 From 70bdbd3d1ae9c4ca3e84a43df34262face26575d Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Sun, 23 Aug 2009 15:27:25 +0200 Subject: ALSA: ali5451: fix timeout handling in snd_ali_{codecs,timer}_ready() Modify loops in such way that the register value is checked also after the timeout condition, just in case the heavy interrupt load etc. caused the thread to sleep for the time period exceeding the timeout value. While at it remove an extra ALI_STIMER read from snd_ali_stimer_ready(). Reported-by: Jack Byer Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Takashi Iwai --- sound/pci/ali5451/ali5451.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'sound') diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index c551006e2920..76d76c08339b 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c @@ -310,12 +310,16 @@ static int snd_ali_codec_ready(struct snd_ali *codec, unsigned int res; end_time = jiffies + msecs_to_jiffies(250); - do { + + for (;;) { res = snd_ali_5451_peek(codec,port); if (!(res & 0x8000)) return 0; + if (!time_after_eq(end_time, jiffies)) + break; schedule_timeout_uninterruptible(1); - } while (time_after_eq(end_time, jiffies)); + } + snd_ali_5451_poke(codec, port, res & ~0x8000); snd_printdd("ali_codec_ready: codec is not ready.\n "); return -EIO; @@ -327,15 +331,17 @@ static int snd_ali_stimer_ready(struct snd_ali *codec) unsigned long dwChk1,dwChk2; dwChk1 = snd_ali_5451_peek(codec, ALI_STIMER); - dwChk2 = snd_ali_5451_peek(codec, ALI_STIMER); - end_time = jiffies + msecs_to_jiffies(250); - do { + + for (;;) { dwChk2 = snd_ali_5451_peek(codec, ALI_STIMER); if (dwChk2 != dwChk1) return 0; + if (!time_after_eq(end_time, jiffies)) + break; schedule_timeout_uninterruptible(1); - } while (time_after_eq(end_time, jiffies)); + } + snd_printk(KERN_ERR "ali_stimer_read: stimer is not ready.\n"); return -EIO; } -- cgit v1.2.2 From edd1365e90eb32625041d09de427d7b03461bc5c Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 24 Aug 2009 09:11:58 +0200 Subject: sound: vx222: fix input level control range check Fix a logic error in the range check of the input level control that would prevent setting any volume less than the maximum. Signed-off-by: Clemens Ladisch Signed-off-by: Takashi Iwai --- sound/pci/vx222/vx222_ops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/pci/vx222/vx222_ops.c b/sound/pci/vx222/vx222_ops.c index 6416d3f0c7be..a69e774d0b13 100644 --- a/sound/pci/vx222/vx222_ops.c +++ b/sound/pci/vx222/vx222_ops.c @@ -885,10 +885,10 @@ static int vx_input_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem struct vx_core *_chip = snd_kcontrol_chip(kcontrol); struct snd_vx222 *chip = (struct snd_vx222 *)_chip; if (ucontrol->value.integer.value[0] < 0 || - ucontrol->value.integer.value[0] < MIC_LEVEL_MAX) + ucontrol->value.integer.value[0] > MIC_LEVEL_MAX) return -EINVAL; if (ucontrol->value.integer.value[1] < 0 || - ucontrol->value.integer.value[1] < MIC_LEVEL_MAX) + ucontrol->value.integer.value[1] > MIC_LEVEL_MAX) return -EINVAL; mutex_lock(&_chip->mixer_mutex); if (chip->input_level[0] != ucontrol->value.integer.value[0] || -- cgit v1.2.2 From b1ddaf681e362ed453182ddee1699d7487069a16 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Tue, 25 Aug 2009 08:15:41 +0200 Subject: sound: pcm_lib: fix unsorted list constraint handling snd_interval_list() expected a sorted list but did not document this, so there are drivers that give it an unsorted list. To fix this, change the algorithm to work with any list. This fixes the "Slave PCM not usable" error with USB devices that have multiple alternate settings with sample rates in decreasing order, such as the Philips Askey VC010 WebCam. http://bugzilla.kernel.org/show_bug.cgi?id=14028 Reported-and-tested-by: Andrzej Signed-off-by: Clemens Ladisch Cc: Signed-off-by: Takashi Iwai --- sound/core/pcm_lib.c | 39 ++++++++------------------------------- 1 file changed, 8 insertions(+), 31 deletions(-) (limited to 'sound') diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 333e4dd29450..d8a7bb28cd83 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -909,47 +909,24 @@ static int snd_interval_ratden(struct snd_interval *i, int snd_interval_list(struct snd_interval *i, unsigned int count, unsigned int *list, unsigned int mask) { unsigned int k; - int changed = 0; + struct snd_interval list_range; if (!count) { i->empty = 1; return -EINVAL; } + snd_interval_any(&list_range); + list_range.min = UINT_MAX; + list_range.max = 0; for (k = 0; k < count; k++) { if (mask && !(mask & (1 << k))) continue; - if (i->min == list[k] && !i->openmin) - goto _l1; - if (i->min < list[k]) { - i->min = list[k]; - i->openmin = 0; - changed = 1; - goto _l1; - } - } - i->empty = 1; - return -EINVAL; - _l1: - for (k = count; k-- > 0;) { - if (mask && !(mask & (1 << k))) + if (!snd_interval_test(i, list[k])) continue; - if (i->max == list[k] && !i->openmax) - goto _l2; - if (i->max > list[k]) { - i->max = list[k]; - i->openmax = 0; - changed = 1; - goto _l2; - } + list_range.min = min(list_range.min, list[k]); + list_range.max = max(list_range.max, list[k]); } - i->empty = 1; - return -EINVAL; - _l2: - if (snd_interval_checkempty(i)) { - i->empty = 1; - return -EINVAL; - } - return changed; + return snd_interval_refine(i, &list_range); } EXPORT_SYMBOL(snd_interval_list); -- cgit v1.2.2 From 0f67a611629f84dd0afacd23d422b4b9c2558285 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 31 Aug 2009 08:12:29 +0200 Subject: ALSA: hda - Add missing mux check for VT1708 In patch_vt1708(), the check of MUX nids is missing and this results in the -EINVAL error in accessing Input Source mixer element. Simpliy adding the call of get_mux_nids() fixes the problem. Reference: Novell bnc#534904 https://bugzilla.novell.com/show_bug.cgi?id=534904 Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_via.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 9008b4b013aa..e8f10b10cceb 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -1395,6 +1395,7 @@ static int patch_vt1708(struct hda_codec *codec) if (!spec->adc_nids && spec->input_mux) { spec->adc_nids = vt1708_adc_nids; spec->num_adc_nids = ARRAY_SIZE(vt1708_adc_nids); + get_mux_nids(codec); spec->mixers[spec->num_mixers] = vt1708_capture_mixer; spec->num_mixers++; } -- cgit v1.2.2 From a3f730af7e33cea10ea66f05b2565fde1f9512df Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 31 Aug 2009 08:15:26 +0200 Subject: ALSA: hda - Fix MacBookPro 3,1/4,1 quirk with ALC889A This patch fixes the wrong headphone output routing for MacBookPro 3,1/4,1 quirk with ALC889A codec, which caused the silent headphone output. Also, this gives the individual Headphone and Speaker volume controls. Reference: kernel bug#14078 http://bugzilla.kernel.org/show_bug.cgi?id=14078 Signed-off-by: Takashi Iwai Cc: --- sound/pci/hda/patch_realtek.c | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 6f683e451f2b..30eeb304351c 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6423,9 +6423,9 @@ static struct hda_verb alc885_mbp_ch2_init[] = { }; /* - * 6ch mode + * 4ch mode */ -static struct hda_verb alc885_mbp_ch6_init[] = { +static struct hda_verb alc885_mbp_ch4_init[] = { { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 }, @@ -6434,9 +6434,9 @@ static struct hda_verb alc885_mbp_ch6_init[] = { { } /* end */ }; -static struct hda_channel_mode alc885_mbp_6ch_modes[2] = { +static struct hda_channel_mode alc885_mbp_4ch_modes[2] = { { 2, alc885_mbp_ch2_init }, - { 6, alc885_mbp_ch6_init }, + { 4, alc885_mbp_ch4_init }, }; /* @@ -6497,10 +6497,11 @@ static struct snd_kcontrol_new alc882_base_mixer[] = { }; static struct snd_kcontrol_new alc885_mbp3_mixer[] = { - HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT), - HDA_BIND_MUTE ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT), - HDA_CODEC_MUTE ("Speaker Playback Switch", 0x14, 0x00, HDA_OUTPUT), - HDA_CODEC_VOLUME("Line-Out Playback Volume", 0x0d, 0x00, HDA_OUTPUT), + HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT), + HDA_BIND_MUTE ("Speaker Playback Switch", 0x0c, 0x02, HDA_INPUT), + HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0e, 0x00, HDA_OUTPUT), + HDA_BIND_MUTE ("Headphone Playback Switch", 0x0e, 0x02, HDA_INPUT), + HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT), HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT), @@ -6814,14 +6815,18 @@ static struct hda_verb alc885_mbp3_init_verbs[] = { {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, + /* HP mixer */ + {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, + {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, + {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* Front Pin: output 0 (0x0c) */ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, - /* HP Pin: output 0 (0x0d) */ + /* HP Pin: output 0 (0x0e) */ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, + {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + {0x15, AC_VERB_SET_CONNECT_SEL, 0x02}, {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, /* Mic (rear) pin: input vref at 80% */ {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, @@ -7195,10 +7200,11 @@ static struct alc_config_preset alc882_presets[] = { .mixers = { alc885_mbp3_mixer, alc882_chmode_mixer }, .init_verbs = { alc885_mbp3_init_verbs, alc880_gpio1_init_verbs }, - .num_dacs = ARRAY_SIZE(alc882_dac_nids), + .num_dacs = 2, .dac_nids = alc882_dac_nids, - .channel_mode = alc885_mbp_6ch_modes, - .num_channel_mode = ARRAY_SIZE(alc885_mbp_6ch_modes), + .hp_nid = 0x04, + .channel_mode = alc885_mbp_4ch_modes, + .num_channel_mode = ARRAY_SIZE(alc885_mbp_4ch_modes), .input_mux = &alc882_capture_source, .dig_out_nid = ALC882_DIGOUT_NID, .dig_in_nid = ALC882_DIGIN_NID, -- cgit v1.2.2