summaryrefslogtreecommitdiffstats
path: root/sound/pci/hda
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda')
-rw-r--r--sound/pci/hda/hda_beep.c11
-rw-r--r--sound/pci/hda/hda_codec.c22
-rw-r--r--sound/pci/hda/hda_codec.h2
-rw-r--r--sound/pci/hda/hda_eld.c4
-rw-r--r--sound/pci/hda/hda_intel.c132
-rw-r--r--sound/pci/hda/patch_analog.c156
-rw-r--r--sound/pci/hda/patch_ca0110.c2
-rw-r--r--sound/pci/hda/patch_realtek.c129
-rw-r--r--sound/pci/hda/patch_sigmatel.c24
-rw-r--r--sound/pci/hda/patch_via.c89
10 files changed, 368 insertions, 203 deletions
diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c
index 29272f2..b0275a0 100644
--- a/sound/pci/hda/hda_beep.c
+++ b/sound/pci/hda/hda_beep.c
@@ -50,19 +50,22 @@ static void snd_hda_generate_beep(struct work_struct *work)
* The tone frequency of beep generator on IDT/STAC codecs is
* defined from the 8bit tone parameter, in Hz,
* freq = 48000 * (257 - tone) / 1024
- * that is from 12kHz to 93.75kHz in step of 46.875 hz
+ * that is from 12kHz to 93.75Hz in steps of 46.875 Hz
*/
static int beep_linear_tone(struct hda_beep *beep, int hz)
{
+ if (hz <= 0)
+ return 0;
hz *= 1000; /* fixed point */
- hz = hz - DIGBEEP_HZ_MIN;
+ hz = hz - DIGBEEP_HZ_MIN
+ + DIGBEEP_HZ_STEP / 2; /* round to nearest step */
if (hz < 0)
hz = 0; /* turn off PC beep*/
else if (hz >= (DIGBEEP_HZ_MAX - DIGBEEP_HZ_MIN))
- hz = 0xff;
+ hz = 1; /* max frequency */
else {
hz /= DIGBEEP_HZ_STEP;
- hz++;
+ hz = 255 - hz;
}
return hz;
}
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 462e2ce..c7df01b 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) {
@@ -332,6 +332,12 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
AC_VERB_GET_CONNECT_LIST, i);
range_val = !!(parm & (1 << (shift-1))); /* ranges */
val = parm & mask;
+ if (val == 0) {
+ snd_printk(KERN_WARNING "hda_codec: "
+ "invalid CONNECT_LIST verb %x[%i]:%x\n",
+ nid, i, parm);
+ return 0;
+ }
parm >>= shift;
if (range_val) {
/* ranges between the previous and this one */
@@ -3470,10 +3476,16 @@ int snd_hda_multi_out_analog_open(struct hda_codec *codec,
}
mutex_lock(&codec->spdif_mutex);
if (mout->share_spdif) {
- runtime->hw.rates &= mout->spdif_rates;
- runtime->hw.formats &= mout->spdif_formats;
- if (mout->spdif_maxbps < hinfo->maxbps)
- hinfo->maxbps = mout->spdif_maxbps;
+ if ((runtime->hw.rates & mout->spdif_rates) &&
+ (runtime->hw.formats & mout->spdif_formats)) {
+ runtime->hw.rates &= mout->spdif_rates;
+ runtime->hw.formats &= mout->spdif_formats;
+ if (mout->spdif_maxbps < hinfo->maxbps)
+ hinfo->maxbps = mout->spdif_maxbps;
+ } else {
+ mout->share_spdif = 0;
+ /* FIXME: need notify? */
+ }
}
mutex_unlock(&codec->spdif_mutex);
}
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index cad79ef..1b75f28 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_eld.c b/sound/pci/hda/hda_eld.c
index fcad5ec..9446a5a 100644
--- a/sound/pci/hda/hda_eld.c
+++ b/sound/pci/hda/hda_eld.c
@@ -508,7 +508,7 @@ static void hdmi_write_eld_info(struct snd_info_entry *entry,
char name[64];
char *sname;
long long val;
- int n;
+ unsigned int n;
while (!snd_info_get_line(buffer, line, sizeof(line))) {
if (sscanf(line, "%s %llx", name, &val) != 2)
@@ -539,7 +539,7 @@ static void hdmi_write_eld_info(struct snd_info_entry *entry,
sname++;
n = 10 * n + name[4] - '0';
}
- if (n < 0 || n > 31) /* double the CEA limit */
+ if (n >= ELD_MAX_SAD)
continue;
if (!strcmp(sname, "_coding_type"))
e->sad[n].format = val;
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 4e9ea70..175f07a 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 {
@@ -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;
@@ -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;
@@ -531,7 +532,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));
@@ -543,30 +545,60 @@ 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)
+{
+ 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;
+ 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++;
+ 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;
@@ -578,13 +610,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 +625,24 @@ 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]--;
+ } else
+ snd_printk(KERN_ERR SFX "spurious response %#x:%#x, "
+ "last cmd=%#08x\n",
+ res, res_ex,
+ chip->last_cmd[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 +655,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;
@@ -633,7 +672,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);
@@ -648,7 +688,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;
}
@@ -672,7 +712,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 */
@@ -692,7 +732,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 +740,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 +748,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 +756,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 +769,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 +780,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];
}
/*
@@ -757,7 +799,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
@@ -765,13 +807,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
@@ -1243,10 +1286,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);
+ 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);
@@ -1454,6 +1499,18 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
mutex_unlock(&chip->open_mutex);
return err;
}
+ snd_pcm_limit_hw_rates(runtime);
+ /* sanity check */
+ if (snd_BUG_ON(!runtime->hw.channels_min) ||
+ snd_BUG_ON(!runtime->hw.channels_max) ||
+ snd_BUG_ON(!runtime->hw.formats) ||
+ snd_BUG_ON(!runtime->hw.rates)) {
+ azx_release_device(azx_dev);
+ hinfo->ops.close(hinfo, apcm->codec, substream);
+ snd_hda_power_down(apcm->codec);
+ mutex_unlock(&chip->open_mutex);
+ return -EINVAL;
+ }
spin_lock_irqsave(&chip->reg_lock, flags);
azx_dev->substream = substream;
azx_dev->running = 0;
@@ -1462,7 +1519,6 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
runtime->private_data = azx_dev;
snd_pcm_set_sync(substream);
mutex_unlock(&chip->open_mutex);
-
return 0;
}
@@ -2322,9 +2378,19 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
gcap = azx_readw(chip, GCAP);
snd_printdd(SFX "chipset global capabilities = 0x%x\n", gcap);
- /* ATI chips seems buggy about 64bit DMA addresses */
- if (chip->driver_type == AZX_DRIVER_ATI)
- gcap &= ~ICH6_GCAP_64OK;
+ /* disable SB600 64bit support for safety */
+ if ((chip->driver_type == AZX_DRIVER_ATI) ||
+ (chip->driver_type == AZX_DRIVER_ATIHDMI)) {
+ struct pci_dev *p_smbus;
+ p_smbus = pci_get_device(PCI_VENDOR_ID_ATI,
+ PCI_DEVICE_ID_ATI_SBX00_SMBUS,
+ NULL);
+ if (p_smbus) {
+ if (p_smbus->revision < 0x30)
+ gcap &= ~ICH6_GCAP_64OK;
+ pci_dev_put(p_smbus);
+ }
+ }
/* allow 64bit DMA address if supported by H/W */
if ((gcap & ICH6_GCAP_64OK) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64)))
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 84cc49c..3da85ca 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -72,6 +72,7 @@ struct ad198x_spec {
hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
unsigned int jack_present :1;
+ unsigned int inv_jack_detect:1;
#ifdef CONFIG_SND_HDA_POWER_SAVE
struct hda_loopback_check loopback;
@@ -669,39 +670,13 @@ static struct hda_input_mux ad1986a_automic_capture_source = {
},
};
-static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {
+static struct snd_kcontrol_new ad1986a_laptop_master_mixers[] = {
HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
- HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Capture Source",
- .info = ad198x_mux_enum_info,
- .get = ad198x_mux_enum_get,
- .put = ad198x_mux_enum_put,
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "External Amplifier",
- .info = ad198x_eapd_info,
- .get = ad198x_eapd_get,
- .put = ad198x_eapd_put,
- .private_value = 0x1b | (1 << 8), /* port-D, inversed */
- },
{ } /* end */
};
-static struct snd_kcontrol_new ad1986a_samsung_mixers[] = {
- HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
- HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
+static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {
HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
@@ -727,6 +702,12 @@ static struct snd_kcontrol_new ad1986a_samsung_mixers[] = {
{ } /* end */
};
+static struct snd_kcontrol_new ad1986a_laptop_intmic_mixers[] = {
+ HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0, HDA_OUTPUT),
+ { } /* end */
+};
+
/* re-connect the mic boost input according to the jack sensing */
static void ad1986a_automic(struct hda_codec *codec)
{
@@ -776,8 +757,9 @@ static void ad1986a_hp_automute(struct hda_codec *codec)
unsigned int present;
present = snd_hda_codec_read(codec, 0x1a, 0, AC_VERB_GET_PIN_SENSE, 0);
- /* Lenovo N100 seems to report the reversed bit for HP jack-sensing */
- spec->jack_present = !(present & 0x80000000);
+ spec->jack_present = !!(present & 0x80000000);
+ if (spec->inv_jack_detect)
+ spec->jack_present = !spec->jack_present;
ad1986a_update_hp(codec);
}
@@ -816,7 +798,7 @@ static int ad1986a_hp_master_sw_put(struct snd_kcontrol *kcontrol,
return change;
}
-static struct snd_kcontrol_new ad1986a_laptop_automute_mixers[] = {
+static struct snd_kcontrol_new ad1986a_automute_master_mixers[] = {
HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -826,33 +808,10 @@ static struct snd_kcontrol_new ad1986a_laptop_automute_mixers[] = {
.put = ad1986a_hp_master_sw_put,
.private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
},
- HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Capture Source",
- .info = ad198x_mux_enum_info,
- .get = ad198x_mux_enum_get,
- .put = ad198x_mux_enum_put,
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "External Amplifier",
- .info = ad198x_eapd_info,
- .get = ad198x_eapd_get,
- .put = ad198x_eapd_put,
- .private_value = 0x1b | (1 << 8), /* port-D, inversed */
- },
{ } /* end */
};
+
/*
* initialization verbs
*/
@@ -981,6 +940,27 @@ static struct hda_verb ad1986a_hp_init_verbs[] = {
{}
};
+static void ad1986a_samsung_p50_unsol_event(struct hda_codec *codec,
+ unsigned int res)
+{
+ switch (res >> 26) {
+ case AD1986A_HP_EVENT:
+ ad1986a_hp_automute(codec);
+ break;
+ case AD1986A_MIC_EVENT:
+ ad1986a_automic(codec);
+ break;
+ }
+}
+
+static int ad1986a_samsung_p50_init(struct hda_codec *codec)
+{
+ ad198x_init(codec);
+ ad1986a_hp_automute(codec);
+ ad1986a_automic(codec);
+ return 0;
+}
+
/* models */
enum {
@@ -991,6 +971,7 @@ enum {
AD1986A_LAPTOP_AUTOMUTE,
AD1986A_ULTRA,
AD1986A_SAMSUNG,
+ AD1986A_SAMSUNG_P50,
AD1986A_MODELS
};
@@ -1002,6 +983,7 @@ static const char *ad1986a_models[AD1986A_MODELS] = {
[AD1986A_LAPTOP_AUTOMUTE] = "laptop-automute",
[AD1986A_ULTRA] = "ultra",
[AD1986A_SAMSUNG] = "samsung",
+ [AD1986A_SAMSUNG_P50] = "samsung-p50",
};
static struct snd_pci_quirk ad1986a_cfg_tbl[] = {
@@ -1024,6 +1006,7 @@ static struct snd_pci_quirk ad1986a_cfg_tbl[] = {
SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba", AD1986A_LAPTOP_EAPD),
SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK),
SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP),
+ SND_PCI_QUIRK(0x144d, 0xc024, "Samsung P50", AD1986A_SAMSUNG_P50),
SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA),
SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc000, "Samsung", AD1986A_SAMSUNG),
SND_PCI_QUIRK(0x144d, 0xc504, "Samsung Q35", AD1986A_3STACK),
@@ -1111,7 +1094,10 @@ static int patch_ad1986a(struct hda_codec *codec)
spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
break;
case AD1986A_LAPTOP_EAPD:
- spec->mixers[0] = ad1986a_laptop_eapd_mixers;
+ spec->num_mixers = 3;
+ spec->mixers[0] = ad1986a_laptop_master_mixers;
+ spec->mixers[1] = ad1986a_laptop_eapd_mixers;
+ spec->mixers[2] = ad1986a_laptop_intmic_mixers;
spec->num_init_verbs = 2;
spec->init_verbs[1] = ad1986a_eapd_init_verbs;
spec->multiout.max_channels = 2;
@@ -1122,7 +1108,9 @@ static int patch_ad1986a(struct hda_codec *codec)
spec->input_mux = &ad1986a_laptop_eapd_capture_source;
break;
case AD1986A_SAMSUNG:
- spec->mixers[0] = ad1986a_samsung_mixers;
+ spec->num_mixers = 2;
+ spec->mixers[0] = ad1986a_laptop_master_mixers;
+ spec->mixers[1] = ad1986a_laptop_eapd_mixers;
spec->num_init_verbs = 3;
spec->init_verbs[1] = ad1986a_eapd_init_verbs;
spec->init_verbs[2] = ad1986a_automic_verbs;
@@ -1135,8 +1123,28 @@ static int patch_ad1986a(struct hda_codec *codec)
codec->patch_ops.unsol_event = ad1986a_automic_unsol_event;
codec->patch_ops.init = ad1986a_automic_init;
break;
+ case AD1986A_SAMSUNG_P50:
+ spec->num_mixers = 2;
+ spec->mixers[0] = ad1986a_automute_master_mixers;
+ spec->mixers[1] = ad1986a_laptop_eapd_mixers;
+ spec->num_init_verbs = 4;
+ spec->init_verbs[1] = ad1986a_eapd_init_verbs;
+ spec->init_verbs[2] = ad1986a_automic_verbs;
+ spec->init_verbs[3] = ad1986a_hp_init_verbs;
+ spec->multiout.max_channels = 2;
+ spec->multiout.num_dacs = 1;
+ spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
+ if (!is_jack_available(codec, 0x25))
+ spec->multiout.dig_out_nid = 0;
+ spec->input_mux = &ad1986a_automic_capture_source;
+ codec->patch_ops.unsol_event = ad1986a_samsung_p50_unsol_event;
+ codec->patch_ops.init = ad1986a_samsung_p50_init;
+ break;
case AD1986A_LAPTOP_AUTOMUTE:
- spec->mixers[0] = ad1986a_laptop_automute_mixers;
+ spec->num_mixers = 3;
+ spec->mixers[0] = ad1986a_automute_master_mixers;
+ spec->mixers[1] = ad1986a_laptop_eapd_mixers;
+ spec->mixers[2] = ad1986a_laptop_intmic_mixers;
spec->num_init_verbs = 3;
spec->init_verbs[1] = ad1986a_eapd_init_verbs;
spec->init_verbs[2] = ad1986a_hp_init_verbs;
@@ -1148,6 +1156,10 @@ static int patch_ad1986a(struct hda_codec *codec)
spec->input_mux = &ad1986a_laptop_eapd_capture_source;
codec->patch_ops.unsol_event = ad1986a_hp_unsol_event;
codec->patch_ops.init = ad1986a_hp_init;
+ /* Lenovo N100 seems to report the reversed bit
+ * for HP jack-sensing
+ */
+ spec->inv_jack_detect = 1;
break;
case AD1986A_ULTRA:
spec->mixers[0] = ad1986a_laptop_eapd_mixers;
@@ -3734,9 +3746,30 @@ static struct snd_kcontrol_new ad1884a_laptop_mixers[] = {
{ } /* end */
};
+static int ad1884a_mobile_master_sw_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ int ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
+ int mute = (!ucontrol->value.integer.value[0] &&
+ !ucontrol->value.integer.value[1]);
+ /* toggle GPIO1 according to the mute state */
+ snd_hda_codec_write_cache(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
+ mute ? 0x02 : 0x0);
+ return ret;
+}
+
static struct snd_kcontrol_new ad1884a_mobile_mixers[] = {
HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
+ /*HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Master Playback Switch",
+ .info = snd_hda_mixer_amp_switch_info,
+ .get = snd_hda_mixer_amp_switch_get,
+ .put = ad1884a_mobile_master_sw_put,
+ .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
+ },
HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Capture Volume", 0x14, 0x0, HDA_INPUT),
@@ -3857,6 +3890,10 @@ static struct hda_verb ad1884a_mobile_verbs[] = {
/* unsolicited event for pin-sense */
{0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
+ /* allow to touch GPIO1 (for mute control) */
+ {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
+ {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
+ {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
{ } /* end */
};
@@ -3966,6 +4003,7 @@ static struct snd_pci_quirk ad1884a_cfg_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP),
SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE),
SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x3070, "HP", AD1884A_MOBILE),
+ SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30d0, "HP laptop", AD1884A_LAPTOP),
SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30e0, "HP laptop", AD1884A_LAPTOP),
SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3600, "HP laptop", AD1884A_LAPTOP),
SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD),
diff --git a/sound/pci/hda/patch_ca0110.c b/sound/pci/hda/patch_ca0110.c
index 392d108..019ca7c 100644
--- a/sound/pci/hda/patch_ca0110.c
+++ b/sound/pci/hda/patch_ca0110.c
@@ -510,7 +510,7 @@ static int ca0110_parse_auto_config(struct hda_codec *codec)
}
-int patch_ca0110(struct hda_codec *codec)
+static int patch_ca0110(struct hda_codec *codec)
{
struct ca0110_spec *spec;
int err;
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 3345331..51c44fd 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -275,13 +275,13 @@ struct alc_spec {
*/
unsigned int num_init_verbs;
- char stream_name_analog[16]; /* analog PCM stream */
+ char stream_name_analog[32]; /* analog PCM stream */
struct hda_pcm_stream *stream_analog_playback;
struct hda_pcm_stream *stream_analog_capture;
struct hda_pcm_stream *stream_analog_alt_playback;
struct hda_pcm_stream *stream_analog_alt_capture;
- char stream_name_digital[16]; /* digital PCM stream */
+ char stream_name_digital[32]; /* digital PCM stream */
struct hda_pcm_stream *stream_digital_playback;
struct hda_pcm_stream *stream_digital_capture;
@@ -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;
@@ -945,12 +945,13 @@ static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid,
static void alc_automute_pin(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- unsigned int present;
+ unsigned int present, pincap;
unsigned int nid = spec->autocfg.hp_pins[0];
int i;
- /* need to execute and sync at first */
- snd_hda_codec_read(codec, nid, 0, AC_VERB_SET_PIN_SENSE, 0);
+ 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);
present = snd_hda_codec_read(codec, nid, 0,
AC_VERB_GET_PIN_SENSE, 0);
spec->jack_present = (present & AC_PINSENSE_PRESENCE) != 0;
@@ -1392,7 +1393,7 @@ static struct hda_verb alc888_fujitsu_xa3530_verbs[] = {
static void alc_automute_amp(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- unsigned int val, mute;
+ unsigned int val, mute, pincap;
hda_nid_t nid;
int i;
@@ -1401,6 +1402,10 @@ static void alc_automute_amp(struct hda_codec *codec)
nid = spec->autocfg.hp_pins[i];
if (!nid)
break;
+ 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);
val = snd_hda_codec_read(codec, nid, 0,
AC_VERB_GET_PIN_SENSE, 0);
if (val & AC_PINSENSE_PRESENCE) {
@@ -1471,6 +1476,10 @@ static struct hda_verb alc888_acer_aspire_4930g_verbs[] = {
static struct hda_verb alc888_acer_aspire_6530g_verbs[] = {
/* Bias voltage on for external mic port */
{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN | PIN_VREF80},
+/* Front Mic: set to PIN_IN (empty by default) */
+ {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+/* Unselect Front Mic by default in input mixer 3 */
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0xb)},
/* Enable unsolicited event for HP jack */
{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
/* Enable speaker output */
@@ -1560,18 +1569,22 @@ static struct hda_input_mux alc888_2_capture_sources[2] = {
static struct hda_input_mux alc888_acer_aspire_6530_sources[2] = {
/* Interal mic only available on one ADC */
{
- .num_items = 3,
+ .num_items = 5,
.items = {
{ "Ext Mic", 0x0 },
+ { "Line In", 0x2 },
{ "CD", 0x4 },
+ { "Input Mix", 0xa },
{ "Int Mic", 0xb },
},
},
{
- .num_items = 2,
+ .num_items = 4,
.items = {
{ "Ext Mic", 0x0 },
+ { "Line In", 0x2 },
{ "CD", 0x4 },
+ { "Input Mix", 0xa },
},
}
};
@@ -1639,6 +1652,17 @@ static void alc888_acer_aspire_4930g_init_hook(struct hda_codec *codec)
alc_automute_amp(codec);
}
+static void alc888_acer_aspire_6530g_init_hook(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+
+ spec->autocfg.hp_pins[0] = 0x15;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ spec->autocfg.speaker_pins[1] = 0x16;
+ spec->autocfg.speaker_pins[2] = 0x17;
+ alc_automute_amp(codec);
+}
+
static void alc889_acer_aspire_8930g_init_hook(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
@@ -4481,6 +4505,12 @@ static int alc880_parse_auto_config(struct hda_codec *codec)
&dig_nid, 1);
if (err < 0)
continue;
+ if (dig_nid > 0x7f) {
+ printk(KERN_ERR "alc880_auto: invalid dig_nid "
+ "connection 0x%x for NID 0x%x\n", dig_nid,
+ spec->autocfg.dig_out_pins[i]);
+ continue;
+ }
if (!i)
spec->multiout.dig_out_nid = dig_nid;
else {
@@ -6895,9 +6925,6 @@ static struct hda_verb alc882_targa_verbs[] = {
{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
- {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
- {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03},
- {0x01, AC_VERB_SET_GPIO_DATA, 0x03},
{ } /* end */
};
@@ -7217,7 +7244,8 @@ static struct alc_config_preset alc882_presets[] = {
},
[ALC882_TARGA] = {
.mixers = { alc882_targa_mixer, alc882_chmode_mixer },
- .init_verbs = { alc882_init_verbs, alc882_targa_verbs},
+ .init_verbs = { alc882_init_verbs, alc880_gpio3_init_verbs,
+ alc882_targa_verbs},
.num_dacs = ARRAY_SIZE(alc882_dac_nids),
.dac_nids = alc882_dac_nids,
.dig_out_nid = ALC882_DIGOUT_NID,
@@ -8189,6 +8217,8 @@ static struct snd_kcontrol_new alc888_acer_aspire_6530_mixer[] = {
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("LFE Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("LFE Playback Switch", 0x0f, 2, HDA_INPUT),
+ HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+ HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
@@ -9064,7 +9094,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
SND_PCI_QUIRK(0x1025, 0x0157, "Acer X3200", ALC883_AUTO),
SND_PCI_QUIRK(0x1025, 0x0158, "Acer AX1700-U3700A", ALC883_AUTO),
SND_PCI_QUIRK(0x1025, 0x015e, "Acer Aspire 6930G",
- ALC888_ACER_ASPIRE_4930G),
+ ALC888_ACER_ASPIRE_6530G),
SND_PCI_QUIRK(0x1025, 0x0166, "Acer Aspire 6530G",
ALC888_ACER_ASPIRE_6530G),
/* default Acer -- disabled as it causes more problems.
@@ -9212,7 +9242,8 @@ static struct alc_config_preset alc883_presets[] = {
},
[ALC883_TARGA_DIG] = {
.mixers = { alc883_targa_mixer, alc883_chmode_mixer },
- .init_verbs = { alc883_init_verbs, alc883_targa_verbs},
+ .init_verbs = { alc883_init_verbs, alc880_gpio3_init_verbs,
+ alc883_targa_verbs},
.num_dacs = ARRAY_SIZE(alc883_dac_nids),
.dac_nids = alc883_dac_nids,
.dig_out_nid = ALC883_DIGOUT_NID,
@@ -9225,7 +9256,8 @@ static struct alc_config_preset alc883_presets[] = {
},
[ALC883_TARGA_2ch_DIG] = {
.mixers = { alc883_targa_2ch_mixer},
- .init_verbs = { alc883_init_verbs, alc883_targa_verbs},
+ .init_verbs = { alc883_init_verbs, alc880_gpio3_init_verbs,
+ alc883_targa_verbs},
.num_dacs = ARRAY_SIZE(alc883_dac_nids),
.dac_nids = alc883_dac_nids,
.adc_nids = alc883_adc_nids_alt,
@@ -9317,7 +9349,7 @@ static struct alc_config_preset alc883_presets[] = {
ARRAY_SIZE(alc888_2_capture_sources),
.input_mux = alc888_acer_aspire_6530_sources,
.unsol_event = alc_automute_amp_unsol_event,
- .init_hook = alc888_acer_aspire_4930g_init_hook,
+ .init_hook = alc888_acer_aspire_6530g_init_hook,
},
[ALC888_ACER_ASPIRE_8930G] = {
.mixers = { alc888_base_mixer,
@@ -10599,6 +10631,18 @@ static void alc262_lenovo_3000_unsol_event(struct hda_codec *codec,
alc262_lenovo_3000_automute(codec, 1);
}
+static int amp_stereo_mute_update(struct hda_codec *codec, hda_nid_t nid,
+ int dir, int idx, long *valp)
+{
+ int i, change = 0;
+
+ for (i = 0; i < 2; i++, valp++)
+ change |= snd_hda_codec_amp_update(codec, nid, i, dir, idx,
+ HDA_AMP_MUTE,
+ *valp ? 0 : HDA_AMP_MUTE);
+ return change;
+}
+
/* bind hp and internal speaker mute (with plug check) */
static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -10607,13 +10651,8 @@ static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol,
long *valp = ucontrol->value.integer.value;
int change;
- change = snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
- HDA_AMP_MUTE,
- valp ? 0 : HDA_AMP_MUTE);
- change |= snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
- HDA_AMP_MUTE,
- valp ? 0 : HDA_AMP_MUTE);
-
+ change = amp_stereo_mute_update(codec, 0x14, HDA_OUTPUT, 0, valp);
+ change |= amp_stereo_mute_update(codec, 0x1b, HDA_OUTPUT, 0, valp);
if (change)
alc262_fujitsu_automute(codec, 0);
return change;
@@ -10648,10 +10687,7 @@ static int alc262_lenovo_3000_master_sw_put(struct snd_kcontrol *kcontrol,
long *valp = ucontrol->value.integer.value;
int change;
- change = snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
- HDA_AMP_MUTE,
- valp ? 0 : HDA_AMP_MUTE);
-
+ change = amp_stereo_mute_update(codec, 0x1b, HDA_OUTPUT, 0, valp);
if (change)
alc262_lenovo_3000_automute(codec, 0);
return change;
@@ -11822,12 +11858,7 @@ static int alc268_acer_master_sw_put(struct snd_kcontrol *kcontrol,
long *valp = ucontrol->value.integer.value;
int change;
- change = snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
- HDA_AMP_MUTE,
- valp[0] ? 0 : HDA_AMP_MUTE);
- change |= snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
- HDA_AMP_MUTE,
- valp[1] ? 0 : HDA_AMP_MUTE);
+ change = amp_stereo_mute_update(codec, 0x14, HDA_OUTPUT, 0, valp);
if (change)
alc268_acer_automute(codec, 0);
return change;
@@ -12437,6 +12468,8 @@ static int alc268_parse_auto_config(struct hda_codec *codec)
if (err < 0)
return err;
+ alc_ssid_check(codec, 0x15, 0x1b, 0x14);
+
return 1;
}
@@ -12848,20 +12881,11 @@ static struct snd_kcontrol_new alc269_lifebook_mixer[] = {
{ }
};
-/* bind volumes of both NID 0x0c and 0x0d */
-static struct hda_bind_ctls alc269_epc_bind_vol = {
- .ops = &snd_hda_bind_vol,
- .values = {
- HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
- HDA_COMPOSE_AMP_VAL(0x03, 3, 0, HDA_OUTPUT),
- 0
- },
-};
-
static struct snd_kcontrol_new alc269_eeepc_mixer[] = {
- HDA_CODEC_MUTE("iSpeaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
- HDA_BIND_VOL("LineOut Playback Volume", &alc269_epc_bind_vol),
- HDA_CODEC_MUTE("LineOut Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
{ } /* end */
};
@@ -12874,12 +12898,7 @@ static struct snd_kcontrol_new alc269_epc_capture_mixer[] = {
};
/* FSC amilo */
-static struct snd_kcontrol_new alc269_fujitsu_mixer[] = {
- HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
- HDA_BIND_VOL("PCM Playback Volume", &alc269_epc_bind_vol),
- { } /* end */
-};
+#define alc269_fujitsu_mixer alc269_eeepc_mixer
static struct hda_verb alc269_quanta_fl1_verbs[] = {
{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
@@ -13345,6 +13364,8 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
if (!spec->cap_mixer && !spec->no_analog)
set_capture_mixer(spec);
+ alc_ssid_check(codec, 0x15, 0x1b, 0x14);
+
return 1;
}
@@ -15136,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),
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 14f3c3e..456ef6a 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -1590,8 +1590,6 @@ static struct snd_pci_quirk stac9200_cfg_tbl[] = {
/* SigmaTel reference board */
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
"DFI LanParty", STAC_REF),
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0xfb30,
- "SigmaTel",STAC_9205_REF),
SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101,
"DFI LanParty", STAC_REF),
/* Dell laptops have BIOS problem */
@@ -1811,6 +1809,8 @@ static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = {
"Dell Studio 1537", STAC_DELL_M6_DMIC),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02a0,
"Dell Studio 17", STAC_DELL_M6_DMIC),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02be,
+ "Dell Studio 1555", STAC_DELL_M6_DMIC),
{} /* terminator */
};
@@ -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),
@@ -2344,6 +2344,8 @@ static struct snd_pci_quirk stac9205_cfg_tbl[] = {
/* SigmaTel reference board */
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
"DFI LanParty", STAC_9205_REF),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0xfb30,
+ "SigmaTel", STAC_9205_REF),
SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101,
"DFI LanParty", STAC_9205_REF),
/* Dell */
@@ -2378,6 +2380,7 @@ static struct snd_pci_quirk stac9205_cfg_tbl[] = {
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0228,
"Dell Vostro 1500", STAC_9205_DELL_M42),
/* Gateway */
+ SND_PCI_QUIRK(0x107b, 0x0560, "Gateway T6834c", STAC_9205_EAPD),
SND_PCI_QUIRK(0x107b, 0x0565, "Gateway T1616", STAC_9205_EAPD),
{} /* terminator */
};
@@ -4065,7 +4068,7 @@ static int stac92xx_add_jack(struct hda_codec *codec,
jack->nid = nid;
jack->type = type;
- sprintf(name, "%s at %s %s Jack",
+ snprintf(name, sizeof(name), "%s at %s %s Jack",
snd_hda_get_jack_type(def_conf),
snd_hda_get_jack_connectivity(def_conf),
snd_hda_get_jack_location(def_conf));
@@ -5642,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;
@@ -5854,6 +5864,8 @@ static unsigned int *stac9872_brd_tbl[STAC_9872_MODELS] = {
};
static struct snd_pci_quirk stac9872_cfg_tbl[] = {
+ SND_PCI_QUIRK_MASK(0x104d, 0xfff0, 0x81e0,
+ "Sony VAIO F/S", STAC_9872_VAIO),
{} /* terminator */
};
@@ -5866,6 +5878,8 @@ static int patch_stac9872(struct hda_codec *codec)
if (spec == NULL)
return -ENOMEM;
codec->spec = spec;
+ spec->num_pins = ARRAY_SIZE(stac9872_pin_nids);
+ spec->pin_nids = stac9872_pin_nids;
spec->board_config = snd_hda_check_board_config(codec, STAC_9872_MODELS,
stac9872_models,
@@ -5877,8 +5891,6 @@ static int patch_stac9872(struct hda_codec *codec)
stac92xx_set_config_regs(codec,
stac9872_brd_tbl[spec->board_config]);
- spec->num_pins = ARRAY_SIZE(stac9872_pin_nids);
- spec->pin_nids = stac9872_pin_nids;
spec->multiout.dac_nids = spec->dac_nids;
spec->num_adcs = ARRAY_SIZE(stac9872_adc_nids);
spec->adc_nids = stac9872_adc_nids;
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index 8e004fb..9008b4b 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -210,7 +210,9 @@ struct via_spec {
/* capture */
unsigned int num_adc_nids;
hda_nid_t *adc_nids;
+ hda_nid_t mux_nids[3];
hda_nid_t dig_in_nid;
+ hda_nid_t dig_in_pin;
/* capture source */
const struct hda_input_mux *input_mux;
@@ -319,6 +321,9 @@ static void via_auto_set_output_and_unmute(struct hda_codec *codec,
pin_type);
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
AMP_OUT_UNMUTE);
+ if (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)
+ snd_hda_codec_write(codec, nid, 0,
+ AC_VERB_SET_EAPD_BTLENABLE, 0x02);
}
@@ -387,27 +392,12 @@ static int via_mux_enum_put(struct snd_kcontrol *kcontrol,
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct via_spec *spec = codec->spec;
unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
- unsigned int vendor_id = codec->vendor_id;
-
- /* AIW0 lydia 060801 add for correct sw0 input select */
- if (IS_VT1708_VENDORID(vendor_id) && (adc_idx == 0))
- return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
- 0x18, &spec->cur_mux[adc_idx]);
- else if ((IS_VT1709_10CH_VENDORID(vendor_id) ||
- IS_VT1709_6CH_VENDORID(vendor_id)) && (adc_idx == 0))
- return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
- 0x19, &spec->cur_mux[adc_idx]);
- else if ((IS_VT1708B_8CH_VENDORID(vendor_id) ||
- IS_VT1708B_4CH_VENDORID(vendor_id)) && (adc_idx == 0))
- return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
- 0x17, &spec->cur_mux[adc_idx]);
- else if (IS_VT1702_VENDORID(vendor_id) && (adc_idx == 0))
- return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
- 0x13, &spec->cur_mux[adc_idx]);
- else
- return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
- spec->adc_nids[adc_idx],
- &spec->cur_mux[adc_idx]);
+
+ if (!spec->mux_nids[adc_idx])
+ return -EINVAL;
+ return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
+ spec->mux_nids[adc_idx],
+ &spec->cur_mux[adc_idx]);
}
static int via_independent_hp_info(struct snd_kcontrol *kcontrol,
@@ -998,25 +988,11 @@ static int via_init(struct hda_codec *codec)
/* Lydia Add for EAPD enable */
if (!spec->dig_in_nid) { /* No Digital In connection */
- if (IS_VT1708_VENDORID(codec->vendor_id)) {
- snd_hda_codec_write(codec, VT1708_DIGIN_PIN, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- PIN_OUT);
- snd_hda_codec_write(codec, VT1708_DIGIN_PIN, 0,
- AC_VERB_SET_EAPD_BTLENABLE, 0x02);
- } else if (IS_VT1709_10CH_VENDORID(codec->vendor_id) ||
- IS_VT1709_6CH_VENDORID(codec->vendor_id)) {
- snd_hda_codec_write(codec, VT1709_DIGIN_PIN, 0,
+ if (spec->dig_in_pin) {
+ snd_hda_codec_write(codec, spec->dig_in_pin, 0,
AC_VERB_SET_PIN_WIDGET_CONTROL,
PIN_OUT);
- snd_hda_codec_write(codec, VT1709_DIGIN_PIN, 0,
- AC_VERB_SET_EAPD_BTLENABLE, 0x02);
- } else if (IS_VT1708B_8CH_VENDORID(codec->vendor_id) ||
- IS_VT1708B_4CH_VENDORID(codec->vendor_id)) {
- snd_hda_codec_write(codec, VT1708B_DIGIN_PIN, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- PIN_OUT);
- snd_hda_codec_write(codec, VT1708B_DIGIN_PIN, 0,
+ snd_hda_codec_write(codec, spec->dig_in_pin, 0,
AC_VERB_SET_EAPD_BTLENABLE, 0x02);
}
} else /* enable SPDIF-input pin */
@@ -1326,6 +1302,7 @@ static int vt1708_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_outs)
spec->multiout.dig_out_nid = VT1708_DIGOUT_NID;
+ spec->dig_in_pin = VT1708_DIGIN_PIN;
if (spec->autocfg.dig_in_pin)
spec->dig_in_nid = VT1708_DIGIN_NID;
@@ -1352,6 +1329,34 @@ static int via_auto_init(struct hda_codec *codec)
return 0;
}
+static int get_mux_nids(struct hda_codec *codec)
+{
+ struct via_spec *spec = codec->spec;
+ hda_nid_t nid, conn[8];
+ unsigned int type;
+ int i, n;
+
+ for (i = 0; i < spec->num_adc_nids; i++) {
+ nid = spec->adc_nids[i];
+ while (nid) {
+ type = (get_wcaps(codec, nid) & AC_WCAP_TYPE)
+ >> AC_WCAP_TYPE_SHIFT;
+ if (type == AC_WID_PIN)
+ break;
+ n = snd_hda_get_connections(codec, nid, conn,
+ ARRAY_SIZE(conn));
+ if (n <= 0)
+ break;
+ if (n > 1) {
+ spec->mux_nids[i] = nid;
+ break;
+ }
+ nid = conn[0];
+ }
+ }
+ return 0;
+}
+
static int patch_vt1708(struct hda_codec *codec)
{
struct via_spec *spec;
@@ -1799,6 +1804,7 @@ static int vt1709_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_outs)
spec->multiout.dig_out_nid = VT1709_DIGOUT_NID;
+ spec->dig_in_pin = VT1709_DIGIN_PIN;
if (spec->autocfg.dig_in_pin)
spec->dig_in_nid = VT1709_DIGIN_NID;
@@ -1859,6 +1865,7 @@ static int patch_vt1709_10ch(struct hda_codec *codec)
if (!spec->adc_nids && spec->input_mux) {
spec->adc_nids = vt1709_adc_nids;
spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids);
+ get_mux_nids(codec);
spec->mixers[spec->num_mixers] = vt1709_capture_mixer;
spec->num_mixers++;
}
@@ -1952,6 +1959,7 @@ static int patch_vt1709_6ch(struct hda_codec *codec)
if (!spec->adc_nids && spec->input_mux) {
spec->adc_nids = vt1709_adc_nids;
spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids);
+ get_mux_nids(codec);
spec->mixers[spec->num_mixers] = vt1709_capture_mixer;
spec->num_mixers++;
}
@@ -2344,6 +2352,7 @@ static int vt1708B_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_outs)
spec->multiout.dig_out_nid = VT1708B_DIGOUT_NID;
+ spec->dig_in_pin = VT1708B_DIGIN_PIN;
if (spec->autocfg.dig_in_pin)
spec->dig_in_nid = VT1708B_DIGIN_NID;
@@ -2404,6 +2413,7 @@ static int patch_vt1708B_8ch(struct hda_codec *codec)
if (!spec->adc_nids && spec->input_mux) {
spec->adc_nids = vt1708B_adc_nids;
spec->num_adc_nids = ARRAY_SIZE(vt1708B_adc_nids);
+ get_mux_nids(codec);
spec->mixers[spec->num_mixers] = vt1708B_capture_mixer;
spec->num_mixers++;
}
@@ -2455,6 +2465,7 @@ static int patch_vt1708B_4ch(struct hda_codec *codec)
if (!spec->adc_nids && spec->input_mux) {
spec->adc_nids = vt1708B_adc_nids;
spec->num_adc_nids = ARRAY_SIZE(vt1708B_adc_nids);
+ get_mux_nids(codec);
spec->mixers[spec->num_mixers] = vt1708B_capture_mixer;
spec->num_mixers++;
}
@@ -2889,6 +2900,7 @@ static int patch_vt1708S(struct hda_codec *codec)
if (!spec->adc_nids && spec->input_mux) {
spec->adc_nids = vt1708S_adc_nids;
spec->num_adc_nids = ARRAY_SIZE(vt1708S_adc_nids);
+ get_mux_nids(codec);
spec->mixers[spec->num_mixers] = vt1708S_capture_mixer;
spec->num_mixers++;
}
@@ -3206,6 +3218,7 @@ static int patch_vt1702(struct hda_codec *codec)
if (!spec->adc_nids && spec->input_mux) {
spec->adc_nids = vt1702_adc_nids;
spec->num_adc_nids = ARRAY_SIZE(vt1702_adc_nids);
+ get_mux_nids(codec);
spec->mixers[spec->num_mixers] = vt1702_capture_mixer;
spec->num_mixers++;
}
OpenPOWER on IntegriCloud