diff options
author | Jiri Kosina <jkosina@suse.cz> | 2012-04-08 15:48:52 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2012-04-08 15:48:52 -0400 |
commit | e75d660672ddd11704b7f0fdb8ff21968587b266 (patch) | |
tree | ccb9c107744c10b553c0373e450bee3971d16c00 /sound/pci | |
parent | 61282f37927143e45b03153f3e7b48d6b702147a (diff) | |
parent | 0034102808e0dbbf3a2394b82b1bb40b5778de9e (diff) |
Merge branch 'master' into for-next
Merge with latest Linus' tree, as I have incoming patches
that fix code that is newer than current HEAD of for-next.
Conflicts:
drivers/net/ethernet/realtek/r8169.c
Diffstat (limited to 'sound/pci')
35 files changed, 2075 insertions, 4947 deletions
diff --git a/sound/pci/asihpi/hpi_internal.h b/sound/pci/asihpi/hpi_internal.h index 4cc315daeda0..8c63200cf339 100644 --- a/sound/pci/asihpi/hpi_internal.h +++ b/sound/pci/asihpi/hpi_internal.h | |||
@@ -42,7 +42,7 @@ On error *pLockedMemHandle marked invalid, non-zero returned. | |||
42 | If this function succeeds, then HpiOs_LockedMem_GetVirtAddr() and | 42 | If this function succeeds, then HpiOs_LockedMem_GetVirtAddr() and |
43 | HpiOs_LockedMem_GetPyhsAddr() will always succed on the returned handle. | 43 | HpiOs_LockedMem_GetPyhsAddr() will always succed on the returned handle. |
44 | */ | 44 | */ |
45 | u16 hpios_locked_mem_alloc(struct consistent_dma_area *p_locked_mem_handle, | 45 | int hpios_locked_mem_alloc(struct consistent_dma_area *p_locked_mem_handle, |
46 | /**< memory handle */ | 46 | /**< memory handle */ |
47 | u32 size, /**< Size in bytes to allocate */ | 47 | u32 size, /**< Size in bytes to allocate */ |
48 | struct pci_dev *p_os_reference | 48 | struct pci_dev *p_os_reference |
diff --git a/sound/pci/asihpi/hpios.c b/sound/pci/asihpi/hpios.c index 2d7d1c2e1d0d..87f4385fe8c7 100644 --- a/sound/pci/asihpi/hpios.c +++ b/sound/pci/asihpi/hpios.c | |||
@@ -43,7 +43,7 @@ void hpios_delay_micro_seconds(u32 num_micro_sec) | |||
43 | 43 | ||
44 | On error, return -ENOMEM, and *pMemArea.size = 0 | 44 | On error, return -ENOMEM, and *pMemArea.size = 0 |
45 | */ | 45 | */ |
46 | u16 hpios_locked_mem_alloc(struct consistent_dma_area *p_mem_area, u32 size, | 46 | int hpios_locked_mem_alloc(struct consistent_dma_area *p_mem_area, u32 size, |
47 | struct pci_dev *pdev) | 47 | struct pci_dev *pdev) |
48 | { | 48 | { |
49 | /*?? any benefit in using managed dmam_alloc_coherent? */ | 49 | /*?? any benefit in using managed dmam_alloc_coherent? */ |
diff --git a/sound/pci/asihpi/hpios.h b/sound/pci/asihpi/hpios.h index c5cef113c209..d3fbd0d76c37 100644 --- a/sound/pci/asihpi/hpios.h +++ b/sound/pci/asihpi/hpios.h | |||
@@ -30,7 +30,6 @@ HPI Operating System Specific macros for Linux Kernel driver | |||
30 | #define HPI_BUILD_KERNEL_MODE | 30 | #define HPI_BUILD_KERNEL_MODE |
31 | 31 | ||
32 | #include <linux/io.h> | 32 | #include <linux/io.h> |
33 | #include <asm/system.h> | ||
34 | #include <linux/ioctl.h> | 33 | #include <linux/ioctl.h> |
35 | #include <linux/kernel.h> | 34 | #include <linux/kernel.h> |
36 | #include <linux/string.h> | 35 | #include <linux/string.h> |
diff --git a/sound/pci/au88x0/au88x0.h b/sound/pci/au88x0/au88x0.h index bb938153a964..466a5c8e8354 100644 --- a/sound/pci/au88x0/au88x0.h +++ b/sound/pci/au88x0/au88x0.h | |||
@@ -26,7 +26,7 @@ | |||
26 | #include <sound/mpu401.h> | 26 | #include <sound/mpu401.h> |
27 | #include <sound/hwdep.h> | 27 | #include <sound/hwdep.h> |
28 | #include <sound/ac97_codec.h> | 28 | #include <sound/ac97_codec.h> |
29 | 29 | #include <sound/tlv.h> | |
30 | #endif | 30 | #endif |
31 | 31 | ||
32 | #ifndef CHIP_AU8820 | 32 | #ifndef CHIP_AU8820 |
@@ -107,6 +107,14 @@ | |||
107 | #define NR_WTPB 0x20 /* WT channels per each bank. */ | 107 | #define NR_WTPB 0x20 /* WT channels per each bank. */ |
108 | #define NR_PCM 0x10 | 108 | #define NR_PCM 0x10 |
109 | 109 | ||
110 | struct pcm_vol { | ||
111 | struct snd_kcontrol *kctl; | ||
112 | int active; | ||
113 | int dma; | ||
114 | int mixin[4]; | ||
115 | int vol[4]; | ||
116 | }; | ||
117 | |||
110 | /* Structs */ | 118 | /* Structs */ |
111 | typedef struct { | 119 | typedef struct { |
112 | //int this_08; /* Still unknown */ | 120 | //int this_08; /* Still unknown */ |
@@ -168,6 +176,7 @@ struct snd_vortex { | |||
168 | /* Xtalk canceler */ | 176 | /* Xtalk canceler */ |
169 | int xt_mode; /* 1: speakers, 0:headphones. */ | 177 | int xt_mode; /* 1: speakers, 0:headphones. */ |
170 | #endif | 178 | #endif |
179 | struct pcm_vol pcm_vol[NR_PCM]; | ||
171 | 180 | ||
172 | int isquad; /* cache of extended ID codec flag. */ | 181 | int isquad; /* cache of extended ID codec flag. */ |
173 | 182 | ||
@@ -239,7 +248,7 @@ static int vortex_alsafmt_aspfmt(int alsafmt); | |||
239 | /* Connection stuff. */ | 248 | /* Connection stuff. */ |
240 | static void vortex_connect_default(vortex_t * vortex, int en); | 249 | static void vortex_connect_default(vortex_t * vortex, int en); |
241 | static int vortex_adb_allocroute(vortex_t * vortex, int dma, int nr_ch, | 250 | static int vortex_adb_allocroute(vortex_t * vortex, int dma, int nr_ch, |
242 | int dir, int type); | 251 | int dir, int type, int subdev); |
243 | static char vortex_adb_checkinout(vortex_t * vortex, int resmap[], int out, | 252 | static char vortex_adb_checkinout(vortex_t * vortex, int resmap[], int out, |
244 | int restype); | 253 | int restype); |
245 | #ifndef CHIP_AU8810 | 254 | #ifndef CHIP_AU8810 |
diff --git a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c index 6933a27a5d76..525f881f0409 100644 --- a/sound/pci/au88x0/au88x0_core.c +++ b/sound/pci/au88x0/au88x0_core.c | |||
@@ -2050,8 +2050,6 @@ vortex_adb_checkinout(vortex_t * vortex, int resmap[], int out, int restype) | |||
2050 | } | 2050 | } |
2051 | 2051 | ||
2052 | /* Default Connections */ | 2052 | /* Default Connections */ |
2053 | static int | ||
2054 | vortex_adb_allocroute(vortex_t * vortex, int dma, int nr_ch, int dir, int type); | ||
2055 | 2053 | ||
2056 | static void vortex_connect_default(vortex_t * vortex, int en) | 2054 | static void vortex_connect_default(vortex_t * vortex, int en) |
2057 | { | 2055 | { |
@@ -2111,15 +2109,13 @@ static void vortex_connect_default(vortex_t * vortex, int en) | |||
2111 | Return: Return allocated DMA or same DMA passed as "dma" when dma >= 0. | 2109 | Return: Return allocated DMA or same DMA passed as "dma" when dma >= 0. |
2112 | */ | 2110 | */ |
2113 | static int | 2111 | static int |
2114 | vortex_adb_allocroute(vortex_t * vortex, int dma, int nr_ch, int dir, int type) | 2112 | vortex_adb_allocroute(vortex_t *vortex, int dma, int nr_ch, int dir, |
2113 | int type, int subdev) | ||
2115 | { | 2114 | { |
2116 | stream_t *stream; | 2115 | stream_t *stream; |
2117 | int i, en; | 2116 | int i, en; |
2117 | struct pcm_vol *p; | ||
2118 | 2118 | ||
2119 | if ((nr_ch == 3) | ||
2120 | || ((dir == SNDRV_PCM_STREAM_CAPTURE) && (nr_ch > 2))) | ||
2121 | return -EBUSY; | ||
2122 | |||
2123 | if (dma >= 0) { | 2119 | if (dma >= 0) { |
2124 | en = 0; | 2120 | en = 0; |
2125 | vortex_adb_checkinout(vortex, | 2121 | vortex_adb_checkinout(vortex, |
@@ -2250,6 +2246,14 @@ vortex_adb_allocroute(vortex_t * vortex, int dma, int nr_ch, int dir, int type) | |||
2250 | MIX_DEFIGAIN); | 2246 | MIX_DEFIGAIN); |
2251 | #endif | 2247 | #endif |
2252 | } | 2248 | } |
2249 | if (stream->type == VORTEX_PCM_ADB && en) { | ||
2250 | p = &vortex->pcm_vol[subdev]; | ||
2251 | p->dma = dma; | ||
2252 | for (i = 0; i < nr_ch; i++) | ||
2253 | p->mixin[i] = mix[i]; | ||
2254 | for (i = 0; i < ch_top; i++) | ||
2255 | p->vol[i] = 0; | ||
2256 | } | ||
2253 | } | 2257 | } |
2254 | #ifndef CHIP_AU8820 | 2258 | #ifndef CHIP_AU8820 |
2255 | else { | 2259 | else { |
@@ -2473,7 +2477,7 @@ static irqreturn_t vortex_interrupt(int irq, void *dev_id) | |||
2473 | hwread(vortex->mmio, VORTEX_IRQ_STAT); | 2477 | hwread(vortex->mmio, VORTEX_IRQ_STAT); |
2474 | handled = 1; | 2478 | handled = 1; |
2475 | } | 2479 | } |
2476 | if (source & IRQ_MIDI) { | 2480 | if ((source & IRQ_MIDI) && vortex->rmidi) { |
2477 | snd_mpu401_uart_interrupt(vortex->irq, | 2481 | snd_mpu401_uart_interrupt(vortex->irq, |
2478 | vortex->rmidi->private_data); | 2482 | vortex->rmidi->private_data); |
2479 | handled = 1; | 2483 | handled = 1; |
diff --git a/sound/pci/au88x0/au88x0_pcm.c b/sound/pci/au88x0/au88x0_pcm.c index 0ef2f9712208..e59f120742a4 100644 --- a/sound/pci/au88x0/au88x0_pcm.c +++ b/sound/pci/au88x0/au88x0_pcm.c | |||
@@ -122,6 +122,18 @@ static struct snd_pcm_hw_constraint_list hw_constraints_au8830_channels = { | |||
122 | .mask = 0, | 122 | .mask = 0, |
123 | }; | 123 | }; |
124 | #endif | 124 | #endif |
125 | |||
126 | static void vortex_notify_pcm_vol_change(struct snd_card *card, | ||
127 | struct snd_kcontrol *kctl, int activate) | ||
128 | { | ||
129 | if (activate) | ||
130 | kctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; | ||
131 | else | ||
132 | kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; | ||
133 | snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE | | ||
134 | SNDRV_CTL_EVENT_MASK_INFO, &(kctl->id)); | ||
135 | } | ||
136 | |||
125 | /* open callback */ | 137 | /* open callback */ |
126 | static int snd_vortex_pcm_open(struct snd_pcm_substream *substream) | 138 | static int snd_vortex_pcm_open(struct snd_pcm_substream *substream) |
127 | { | 139 | { |
@@ -230,12 +242,14 @@ snd_vortex_pcm_hw_params(struct snd_pcm_substream *substream, | |||
230 | if (stream != NULL) | 242 | if (stream != NULL) |
231 | vortex_adb_allocroute(chip, stream->dma, | 243 | vortex_adb_allocroute(chip, stream->dma, |
232 | stream->nr_ch, stream->dir, | 244 | stream->nr_ch, stream->dir, |
233 | stream->type); | 245 | stream->type, |
246 | substream->number); | ||
234 | /* Alloc routes. */ | 247 | /* Alloc routes. */ |
235 | dma = | 248 | dma = |
236 | vortex_adb_allocroute(chip, -1, | 249 | vortex_adb_allocroute(chip, -1, |
237 | params_channels(hw_params), | 250 | params_channels(hw_params), |
238 | substream->stream, type); | 251 | substream->stream, type, |
252 | substream->number); | ||
239 | if (dma < 0) { | 253 | if (dma < 0) { |
240 | spin_unlock_irq(&chip->lock); | 254 | spin_unlock_irq(&chip->lock); |
241 | return dma; | 255 | return dma; |
@@ -246,6 +260,11 @@ snd_vortex_pcm_hw_params(struct snd_pcm_substream *substream, | |||
246 | vortex_adbdma_setbuffers(chip, dma, | 260 | vortex_adbdma_setbuffers(chip, dma, |
247 | params_period_bytes(hw_params), | 261 | params_period_bytes(hw_params), |
248 | params_periods(hw_params)); | 262 | params_periods(hw_params)); |
263 | if (VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_ADB) { | ||
264 | chip->pcm_vol[substream->number].active = 1; | ||
265 | vortex_notify_pcm_vol_change(chip->card, | ||
266 | chip->pcm_vol[substream->number].kctl, 1); | ||
267 | } | ||
249 | } | 268 | } |
250 | #ifndef CHIP_AU8810 | 269 | #ifndef CHIP_AU8810 |
251 | else { | 270 | else { |
@@ -275,10 +294,18 @@ static int snd_vortex_pcm_hw_free(struct snd_pcm_substream *substream) | |||
275 | spin_lock_irq(&chip->lock); | 294 | spin_lock_irq(&chip->lock); |
276 | // Delete audio routes. | 295 | // Delete audio routes. |
277 | if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) { | 296 | if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) { |
278 | if (stream != NULL) | 297 | if (stream != NULL) { |
298 | if (VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_ADB) { | ||
299 | chip->pcm_vol[substream->number].active = 0; | ||
300 | vortex_notify_pcm_vol_change(chip->card, | ||
301 | chip->pcm_vol[substream->number].kctl, | ||
302 | 0); | ||
303 | } | ||
279 | vortex_adb_allocroute(chip, stream->dma, | 304 | vortex_adb_allocroute(chip, stream->dma, |
280 | stream->nr_ch, stream->dir, | 305 | stream->nr_ch, stream->dir, |
281 | stream->type); | 306 | stream->type, |
307 | substream->number); | ||
308 | } | ||
282 | } | 309 | } |
283 | #ifndef CHIP_AU8810 | 310 | #ifndef CHIP_AU8810 |
284 | else { | 311 | else { |
@@ -506,6 +533,83 @@ static struct snd_kcontrol_new snd_vortex_mixer_spdif[] __devinitdata = { | |||
506 | }, | 533 | }, |
507 | }; | 534 | }; |
508 | 535 | ||
536 | /* subdevice PCM Volume control */ | ||
537 | |||
538 | static int snd_vortex_pcm_vol_info(struct snd_kcontrol *kcontrol, | ||
539 | struct snd_ctl_elem_info *uinfo) | ||
540 | { | ||
541 | vortex_t *vortex = snd_kcontrol_chip(kcontrol); | ||
542 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
543 | uinfo->count = (VORTEX_IS_QUAD(vortex) ? 4 : 2); | ||
544 | uinfo->value.integer.min = -128; | ||
545 | uinfo->value.integer.max = 32; | ||
546 | return 0; | ||
547 | } | ||
548 | |||
549 | static int snd_vortex_pcm_vol_get(struct snd_kcontrol *kcontrol, | ||
550 | struct snd_ctl_elem_value *ucontrol) | ||
551 | { | ||
552 | int i; | ||
553 | vortex_t *vortex = snd_kcontrol_chip(kcontrol); | ||
554 | int subdev = kcontrol->id.subdevice; | ||
555 | struct pcm_vol *p = &vortex->pcm_vol[subdev]; | ||
556 | int max_chn = (VORTEX_IS_QUAD(vortex) ? 4 : 2); | ||
557 | for (i = 0; i < max_chn; i++) | ||
558 | ucontrol->value.integer.value[i] = p->vol[i]; | ||
559 | return 0; | ||
560 | } | ||
561 | |||
562 | static int snd_vortex_pcm_vol_put(struct snd_kcontrol *kcontrol, | ||
563 | struct snd_ctl_elem_value *ucontrol) | ||
564 | { | ||
565 | int i; | ||
566 | int changed = 0; | ||
567 | int mixin; | ||
568 | unsigned char vol; | ||
569 | vortex_t *vortex = snd_kcontrol_chip(kcontrol); | ||
570 | int subdev = kcontrol->id.subdevice; | ||
571 | struct pcm_vol *p = &vortex->pcm_vol[subdev]; | ||
572 | int max_chn = (VORTEX_IS_QUAD(vortex) ? 4 : 2); | ||
573 | for (i = 0; i < max_chn; i++) { | ||
574 | if (p->vol[i] != ucontrol->value.integer.value[i]) { | ||
575 | p->vol[i] = ucontrol->value.integer.value[i]; | ||
576 | if (p->active) { | ||
577 | switch (vortex->dma_adb[p->dma].nr_ch) { | ||
578 | case 1: | ||
579 | mixin = p->mixin[0]; | ||
580 | break; | ||
581 | case 2: | ||
582 | default: | ||
583 | mixin = p->mixin[(i < 2) ? i : (i - 2)]; | ||
584 | break; | ||
585 | case 4: | ||
586 | mixin = p->mixin[i]; | ||
587 | break; | ||
588 | }; | ||
589 | vol = p->vol[i]; | ||
590 | vortex_mix_setinputvolumebyte(vortex, | ||
591 | vortex->mixplayb[i], mixin, vol); | ||
592 | } | ||
593 | changed = 1; | ||
594 | } | ||
595 | } | ||
596 | return changed; | ||
597 | } | ||
598 | |||
599 | static const DECLARE_TLV_DB_MINMAX(vortex_pcm_vol_db_scale, -9600, 2400); | ||
600 | |||
601 | static struct snd_kcontrol_new snd_vortex_pcm_vol __devinitdata = { | ||
602 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
603 | .name = "PCM Playback Volume", | ||
604 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
605 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | | ||
606 | SNDRV_CTL_ELEM_ACCESS_INACTIVE, | ||
607 | .info = snd_vortex_pcm_vol_info, | ||
608 | .get = snd_vortex_pcm_vol_get, | ||
609 | .put = snd_vortex_pcm_vol_put, | ||
610 | .tlv = { .p = vortex_pcm_vol_db_scale }, | ||
611 | }; | ||
612 | |||
509 | /* create a pcm device */ | 613 | /* create a pcm device */ |
510 | static int __devinit snd_vortex_new_pcm(vortex_t *chip, int idx, int nr) | 614 | static int __devinit snd_vortex_new_pcm(vortex_t *chip, int idx, int nr) |
511 | { | 615 | { |
@@ -555,5 +659,20 @@ static int __devinit snd_vortex_new_pcm(vortex_t *chip, int idx, int nr) | |||
555 | return err; | 659 | return err; |
556 | } | 660 | } |
557 | } | 661 | } |
662 | if (VORTEX_PCM_TYPE(pcm) == VORTEX_PCM_ADB) { | ||
663 | for (i = 0; i < NR_PCM; i++) { | ||
664 | chip->pcm_vol[i].active = 0; | ||
665 | chip->pcm_vol[i].dma = -1; | ||
666 | kctl = snd_ctl_new1(&snd_vortex_pcm_vol, chip); | ||
667 | if (!kctl) | ||
668 | return -ENOMEM; | ||
669 | chip->pcm_vol[i].kctl = kctl; | ||
670 | kctl->id.device = 0; | ||
671 | kctl->id.subdevice = i; | ||
672 | err = snd_ctl_add(chip->card, kctl); | ||
673 | if (err < 0) | ||
674 | return err; | ||
675 | } | ||
676 | } | ||
558 | return 0; | 677 | return 0; |
559 | } | 678 | } |
diff --git a/sound/pci/aw2/aw2-saa7146.c b/sound/pci/aw2/aw2-saa7146.c index 8afd8b5d1ac7..4439636971eb 100644 --- a/sound/pci/aw2/aw2-saa7146.c +++ b/sound/pci/aw2/aw2-saa7146.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include <linux/pci.h> | 27 | #include <linux/pci.h> |
28 | #include <linux/interrupt.h> | 28 | #include <linux/interrupt.h> |
29 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
30 | #include <asm/system.h> | ||
31 | #include <asm/io.h> | 30 | #include <asm/io.h> |
32 | #include <sound/core.h> | 31 | #include <sound/core.h> |
33 | #include <sound/initval.h> | 32 | #include <sound/initval.h> |
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index 95ffa6a9db6e..496f14c1a731 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c | |||
@@ -2684,10 +2684,9 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) | |||
2684 | err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); | 2684 | err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); |
2685 | if (err < 0) | 2685 | if (err < 0) |
2686 | goto out_err; | 2686 | goto out_err; |
2687 | opl3->private_data = chip; | ||
2687 | } | 2688 | } |
2688 | 2689 | ||
2689 | opl3->private_data = chip; | ||
2690 | |||
2691 | sprintf(card->longname, "%s at 0x%lx, irq %i", | 2690 | sprintf(card->longname, "%s at 0x%lx, irq %i", |
2692 | card->shortname, chip->ctrl_io, chip->irq); | 2691 | card->shortname, chip->ctrl_io, chip->irq); |
2693 | 2692 | ||
diff --git a/sound/pci/ctxfi/ctvmem.c b/sound/pci/ctxfi/ctvmem.c index b78f3fc3c33c..6109490b83e8 100644 --- a/sound/pci/ctxfi/ctvmem.c +++ b/sound/pci/ctxfi/ctvmem.c | |||
@@ -36,7 +36,7 @@ get_vm_block(struct ct_vm *vm, unsigned int size) | |||
36 | 36 | ||
37 | size = CT_PAGE_ALIGN(size); | 37 | size = CT_PAGE_ALIGN(size); |
38 | if (size > vm->size) { | 38 | if (size > vm->size) { |
39 | printk(KERN_ERR "ctxfi: Fail! No sufficient device virtural " | 39 | printk(KERN_ERR "ctxfi: Fail! No sufficient device virtual " |
40 | "memory space available!\n"); | 40 | "memory space available!\n"); |
41 | return NULL; | 41 | return NULL; |
42 | } | 42 | } |
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index cb557c603a80..a8faae1c85e4 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c | |||
@@ -142,6 +142,7 @@ static int enable_mpu[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; | |||
142 | #ifdef SUPPORT_JOYSTICK | 142 | #ifdef SUPPORT_JOYSTICK |
143 | static bool joystick[SNDRV_CARDS]; | 143 | static bool joystick[SNDRV_CARDS]; |
144 | #endif | 144 | #endif |
145 | static int radio_nr[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -1}; | ||
145 | 146 | ||
146 | module_param_array(index, int, NULL, 0444); | 147 | module_param_array(index, int, NULL, 0444); |
147 | MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard."); | 148 | MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard."); |
@@ -165,6 +166,9 @@ MODULE_PARM_DESC(enable_mpu, "Enable MPU401. (0 = off, 1 = on, 2 = auto)"); | |||
165 | module_param_array(joystick, bool, NULL, 0444); | 166 | module_param_array(joystick, bool, NULL, 0444); |
166 | MODULE_PARM_DESC(joystick, "Enable joystick."); | 167 | MODULE_PARM_DESC(joystick, "Enable joystick."); |
167 | #endif | 168 | #endif |
169 | module_param_array(radio_nr, int, NULL, 0444); | ||
170 | MODULE_PARM_DESC(radio_nr, "Radio device numbers"); | ||
171 | |||
168 | 172 | ||
169 | 173 | ||
170 | #define NR_APUS 64 | 174 | #define NR_APUS 64 |
@@ -558,6 +562,7 @@ struct es1968 { | |||
558 | struct work_struct hwvol_work; | 562 | struct work_struct hwvol_work; |
559 | 563 | ||
560 | #ifdef CONFIG_SND_ES1968_RADIO | 564 | #ifdef CONFIG_SND_ES1968_RADIO |
565 | struct v4l2_device v4l2_dev; | ||
561 | struct snd_tea575x tea; | 566 | struct snd_tea575x tea; |
562 | #endif | 567 | #endif |
563 | }; | 568 | }; |
@@ -2613,6 +2618,7 @@ static int snd_es1968_free(struct es1968 *chip) | |||
2613 | 2618 | ||
2614 | #ifdef CONFIG_SND_ES1968_RADIO | 2619 | #ifdef CONFIG_SND_ES1968_RADIO |
2615 | snd_tea575x_exit(&chip->tea); | 2620 | snd_tea575x_exit(&chip->tea); |
2621 | v4l2_device_unregister(&chip->v4l2_dev); | ||
2616 | #endif | 2622 | #endif |
2617 | 2623 | ||
2618 | if (chip->irq >= 0) | 2624 | if (chip->irq >= 0) |
@@ -2655,6 +2661,7 @@ static int __devinit snd_es1968_create(struct snd_card *card, | |||
2655 | int capt_streams, | 2661 | int capt_streams, |
2656 | int chip_type, | 2662 | int chip_type, |
2657 | int do_pm, | 2663 | int do_pm, |
2664 | int radio_nr, | ||
2658 | struct es1968 **chip_ret) | 2665 | struct es1968 **chip_ret) |
2659 | { | 2666 | { |
2660 | static struct snd_device_ops ops = { | 2667 | static struct snd_device_ops ops = { |
@@ -2751,7 +2758,14 @@ static int __devinit snd_es1968_create(struct snd_card *card, | |||
2751 | snd_card_set_dev(card, &pci->dev); | 2758 | snd_card_set_dev(card, &pci->dev); |
2752 | 2759 | ||
2753 | #ifdef CONFIG_SND_ES1968_RADIO | 2760 | #ifdef CONFIG_SND_ES1968_RADIO |
2761 | err = v4l2_device_register(&pci->dev, &chip->v4l2_dev); | ||
2762 | if (err < 0) { | ||
2763 | snd_es1968_free(chip); | ||
2764 | return err; | ||
2765 | } | ||
2766 | chip->tea.v4l2_dev = &chip->v4l2_dev; | ||
2754 | chip->tea.private_data = chip; | 2767 | chip->tea.private_data = chip; |
2768 | chip->tea.radio_nr = radio_nr; | ||
2755 | chip->tea.ops = &snd_es1968_tea_ops; | 2769 | chip->tea.ops = &snd_es1968_tea_ops; |
2756 | strlcpy(chip->tea.card, "SF64-PCE2", sizeof(chip->tea.card)); | 2770 | strlcpy(chip->tea.card, "SF64-PCE2", sizeof(chip->tea.card)); |
2757 | sprintf(chip->tea.bus_info, "PCI:%s", pci_name(pci)); | 2771 | sprintf(chip->tea.bus_info, "PCI:%s", pci_name(pci)); |
@@ -2797,6 +2811,7 @@ static int __devinit snd_es1968_probe(struct pci_dev *pci, | |||
2797 | pcm_substreams_c[dev], | 2811 | pcm_substreams_c[dev], |
2798 | pci_id->driver_data, | 2812 | pci_id->driver_data, |
2799 | use_pm[dev], | 2813 | use_pm[dev], |
2814 | radio_nr[dev], | ||
2800 | &chip)) < 0) { | 2815 | &chip)) < 0) { |
2801 | snd_card_free(card); | 2816 | snd_card_free(card); |
2802 | return err; | 2817 | return err; |
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index 9597ef1eccca..a416ea8af3e9 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c | |||
@@ -58,6 +58,7 @@ static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card | |||
58 | * High 16-bits are video (radio) device number + 1 | 58 | * High 16-bits are video (radio) device number + 1 |
59 | */ | 59 | */ |
60 | static int tea575x_tuner[SNDRV_CARDS]; | 60 | static int tea575x_tuner[SNDRV_CARDS]; |
61 | static int radio_nr[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -1}; | ||
61 | 62 | ||
62 | module_param_array(index, int, NULL, 0444); | 63 | module_param_array(index, int, NULL, 0444); |
63 | MODULE_PARM_DESC(index, "Index value for the FM801 soundcard."); | 64 | MODULE_PARM_DESC(index, "Index value for the FM801 soundcard."); |
@@ -67,6 +68,9 @@ module_param_array(enable, bool, NULL, 0444); | |||
67 | MODULE_PARM_DESC(enable, "Enable FM801 soundcard."); | 68 | MODULE_PARM_DESC(enable, "Enable FM801 soundcard."); |
68 | module_param_array(tea575x_tuner, int, NULL, 0444); | 69 | module_param_array(tea575x_tuner, int, NULL, 0444); |
69 | MODULE_PARM_DESC(tea575x_tuner, "TEA575x tuner access method (0 = auto, 1 = SF256-PCS, 2=SF256-PCP, 3=SF64-PCR, 8=disable, +16=tuner-only)."); | 70 | MODULE_PARM_DESC(tea575x_tuner, "TEA575x tuner access method (0 = auto, 1 = SF256-PCS, 2=SF256-PCP, 3=SF64-PCR, 8=disable, +16=tuner-only)."); |
71 | module_param_array(radio_nr, int, NULL, 0444); | ||
72 | MODULE_PARM_DESC(radio_nr, "Radio device numbers"); | ||
73 | |||
70 | 74 | ||
71 | #define TUNER_DISABLED (1<<3) | 75 | #define TUNER_DISABLED (1<<3) |
72 | #define TUNER_ONLY (1<<4) | 76 | #define TUNER_ONLY (1<<4) |
@@ -197,6 +201,7 @@ struct fm801 { | |||
197 | struct snd_info_entry *proc_entry; | 201 | struct snd_info_entry *proc_entry; |
198 | 202 | ||
199 | #ifdef CONFIG_SND_FM801_TEA575X_BOOL | 203 | #ifdef CONFIG_SND_FM801_TEA575X_BOOL |
204 | struct v4l2_device v4l2_dev; | ||
200 | struct snd_tea575x tea; | 205 | struct snd_tea575x tea; |
201 | #endif | 206 | #endif |
202 | 207 | ||
@@ -1154,8 +1159,10 @@ static int snd_fm801_free(struct fm801 *chip) | |||
1154 | 1159 | ||
1155 | __end_hw: | 1160 | __end_hw: |
1156 | #ifdef CONFIG_SND_FM801_TEA575X_BOOL | 1161 | #ifdef CONFIG_SND_FM801_TEA575X_BOOL |
1157 | if (!(chip->tea575x_tuner & TUNER_DISABLED)) | 1162 | if (!(chip->tea575x_tuner & TUNER_DISABLED)) { |
1158 | snd_tea575x_exit(&chip->tea); | 1163 | snd_tea575x_exit(&chip->tea); |
1164 | v4l2_device_unregister(&chip->v4l2_dev); | ||
1165 | } | ||
1159 | #endif | 1166 | #endif |
1160 | if (chip->irq >= 0) | 1167 | if (chip->irq >= 0) |
1161 | free_irq(chip->irq, chip); | 1168 | free_irq(chip->irq, chip); |
@@ -1175,6 +1182,7 @@ static int snd_fm801_dev_free(struct snd_device *device) | |||
1175 | static int __devinit snd_fm801_create(struct snd_card *card, | 1182 | static int __devinit snd_fm801_create(struct snd_card *card, |
1176 | struct pci_dev * pci, | 1183 | struct pci_dev * pci, |
1177 | int tea575x_tuner, | 1184 | int tea575x_tuner, |
1185 | int radio_nr, | ||
1178 | struct fm801 ** rchip) | 1186 | struct fm801 ** rchip) |
1179 | { | 1187 | { |
1180 | struct fm801 *chip; | 1188 | struct fm801 *chip; |
@@ -1234,6 +1242,13 @@ static int __devinit snd_fm801_create(struct snd_card *card, | |||
1234 | snd_card_set_dev(card, &pci->dev); | 1242 | snd_card_set_dev(card, &pci->dev); |
1235 | 1243 | ||
1236 | #ifdef CONFIG_SND_FM801_TEA575X_BOOL | 1244 | #ifdef CONFIG_SND_FM801_TEA575X_BOOL |
1245 | err = v4l2_device_register(&pci->dev, &chip->v4l2_dev); | ||
1246 | if (err < 0) { | ||
1247 | snd_fm801_free(chip); | ||
1248 | return err; | ||
1249 | } | ||
1250 | chip->tea.v4l2_dev = &chip->v4l2_dev; | ||
1251 | chip->tea.radio_nr = radio_nr; | ||
1237 | chip->tea.private_data = chip; | 1252 | chip->tea.private_data = chip; |
1238 | chip->tea.ops = &snd_fm801_tea_ops; | 1253 | chip->tea.ops = &snd_fm801_tea_ops; |
1239 | sprintf(chip->tea.bus_info, "PCI:%s", pci_name(pci)); | 1254 | sprintf(chip->tea.bus_info, "PCI:%s", pci_name(pci)); |
@@ -1241,6 +1256,7 @@ static int __devinit snd_fm801_create(struct snd_card *card, | |||
1241 | (tea575x_tuner & TUNER_TYPE_MASK) < 4) { | 1256 | (tea575x_tuner & TUNER_TYPE_MASK) < 4) { |
1242 | if (snd_tea575x_init(&chip->tea)) { | 1257 | if (snd_tea575x_init(&chip->tea)) { |
1243 | snd_printk(KERN_ERR "TEA575x radio not found\n"); | 1258 | snd_printk(KERN_ERR "TEA575x radio not found\n"); |
1259 | snd_fm801_free(chip); | ||
1244 | return -ENODEV; | 1260 | return -ENODEV; |
1245 | } | 1261 | } |
1246 | } else if ((tea575x_tuner & TUNER_TYPE_MASK) == 0) { | 1262 | } else if ((tea575x_tuner & TUNER_TYPE_MASK) == 0) { |
@@ -1287,7 +1303,7 @@ static int __devinit snd_card_fm801_probe(struct pci_dev *pci, | |||
1287 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); | 1303 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); |
1288 | if (err < 0) | 1304 | if (err < 0) |
1289 | return err; | 1305 | return err; |
1290 | if ((err = snd_fm801_create(card, pci, tea575x_tuner[dev], &chip)) < 0) { | 1306 | if ((err = snd_fm801_create(card, pci, tea575x_tuner[dev], radio_nr[dev], &chip)) < 0) { |
1291 | snd_card_free(card); | 1307 | snd_card_free(card); |
1292 | return err; | 1308 | return err; |
1293 | } | 1309 | } |
diff --git a/sound/pci/hda/alc260_quirks.c b/sound/pci/hda/alc260_quirks.c deleted file mode 100644 index 3b5170b9700f..000000000000 --- a/sound/pci/hda/alc260_quirks.c +++ /dev/null | |||
@@ -1,968 +0,0 @@ | |||
1 | /* | ||
2 | * ALC260 quirk models | ||
3 | * included by patch_realtek.c | ||
4 | */ | ||
5 | |||
6 | /* ALC260 models */ | ||
7 | enum { | ||
8 | ALC260_AUTO, | ||
9 | ALC260_BASIC, | ||
10 | ALC260_FUJITSU_S702X, | ||
11 | ALC260_ACER, | ||
12 | ALC260_WILL, | ||
13 | ALC260_REPLACER_672V, | ||
14 | ALC260_FAVORIT100, | ||
15 | #ifdef CONFIG_SND_DEBUG | ||
16 | ALC260_TEST, | ||
17 | #endif | ||
18 | ALC260_MODEL_LAST /* last tag */ | ||
19 | }; | ||
20 | |||
21 | static const hda_nid_t alc260_dac_nids[1] = { | ||
22 | /* front */ | ||
23 | 0x02, | ||
24 | }; | ||
25 | |||
26 | static const hda_nid_t alc260_adc_nids[1] = { | ||
27 | /* ADC0 */ | ||
28 | 0x04, | ||
29 | }; | ||
30 | |||
31 | static const hda_nid_t alc260_adc_nids_alt[1] = { | ||
32 | /* ADC1 */ | ||
33 | 0x05, | ||
34 | }; | ||
35 | |||
36 | /* NIDs used when simultaneous access to both ADCs makes sense. Note that | ||
37 | * alc260_capture_mixer assumes ADC0 (nid 0x04) is the first ADC. | ||
38 | */ | ||
39 | static const hda_nid_t alc260_dual_adc_nids[2] = { | ||
40 | /* ADC0, ADC1 */ | ||
41 | 0x04, 0x05 | ||
42 | }; | ||
43 | |||
44 | #define ALC260_DIGOUT_NID 0x03 | ||
45 | #define ALC260_DIGIN_NID 0x06 | ||
46 | |||
47 | static const struct hda_input_mux alc260_capture_source = { | ||
48 | .num_items = 4, | ||
49 | .items = { | ||
50 | { "Mic", 0x0 }, | ||
51 | { "Front Mic", 0x1 }, | ||
52 | { "Line", 0x2 }, | ||
53 | { "CD", 0x4 }, | ||
54 | }, | ||
55 | }; | ||
56 | |||
57 | /* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack, | ||
58 | * headphone jack and the internal CD lines since these are the only pins at | ||
59 | * which audio can appear. For flexibility, also allow the option of | ||
60 | * recording the mixer output on the second ADC (ADC0 doesn't have a | ||
61 | * connection to the mixer output). | ||
62 | */ | ||
63 | static const struct hda_input_mux alc260_fujitsu_capture_sources[2] = { | ||
64 | { | ||
65 | .num_items = 3, | ||
66 | .items = { | ||
67 | { "Mic/Line", 0x0 }, | ||
68 | { "CD", 0x4 }, | ||
69 | { "Headphone", 0x2 }, | ||
70 | }, | ||
71 | }, | ||
72 | { | ||
73 | .num_items = 4, | ||
74 | .items = { | ||
75 | { "Mic/Line", 0x0 }, | ||
76 | { "CD", 0x4 }, | ||
77 | { "Headphone", 0x2 }, | ||
78 | { "Mixer", 0x5 }, | ||
79 | }, | ||
80 | }, | ||
81 | |||
82 | }; | ||
83 | |||
84 | /* Acer TravelMate(/Extensa/Aspire) notebooks have similar configuration to | ||
85 | * the Fujitsu S702x, but jacks are marked differently. | ||
86 | */ | ||
87 | static const struct hda_input_mux alc260_acer_capture_sources[2] = { | ||
88 | { | ||
89 | .num_items = 4, | ||
90 | .items = { | ||
91 | { "Mic", 0x0 }, | ||
92 | { "Line", 0x2 }, | ||
93 | { "CD", 0x4 }, | ||
94 | { "Headphone", 0x5 }, | ||
95 | }, | ||
96 | }, | ||
97 | { | ||
98 | .num_items = 5, | ||
99 | .items = { | ||
100 | { "Mic", 0x0 }, | ||
101 | { "Line", 0x2 }, | ||
102 | { "CD", 0x4 }, | ||
103 | { "Headphone", 0x6 }, | ||
104 | { "Mixer", 0x5 }, | ||
105 | }, | ||
106 | }, | ||
107 | }; | ||
108 | |||
109 | /* Maxdata Favorit 100XS */ | ||
110 | static const struct hda_input_mux alc260_favorit100_capture_sources[2] = { | ||
111 | { | ||
112 | .num_items = 2, | ||
113 | .items = { | ||
114 | { "Line/Mic", 0x0 }, | ||
115 | { "CD", 0x4 }, | ||
116 | }, | ||
117 | }, | ||
118 | { | ||
119 | .num_items = 3, | ||
120 | .items = { | ||
121 | { "Line/Mic", 0x0 }, | ||
122 | { "CD", 0x4 }, | ||
123 | { "Mixer", 0x5 }, | ||
124 | }, | ||
125 | }, | ||
126 | }; | ||
127 | |||
128 | /* | ||
129 | * This is just place-holder, so there's something for alc_build_pcms to look | ||
130 | * at when it calculates the maximum number of channels. ALC260 has no mixer | ||
131 | * element which allows changing the channel mode, so the verb list is | ||
132 | * never used. | ||
133 | */ | ||
134 | static const struct hda_channel_mode alc260_modes[1] = { | ||
135 | { 2, NULL }, | ||
136 | }; | ||
137 | |||
138 | |||
139 | /* Mixer combinations | ||
140 | * | ||
141 | * basic: base_output + input + pc_beep + capture | ||
142 | * fujitsu: fujitsu + capture | ||
143 | * acer: acer + capture | ||
144 | */ | ||
145 | |||
146 | static const struct snd_kcontrol_new alc260_base_output_mixer[] = { | ||
147 | HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT), | ||
148 | HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT), | ||
149 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT), | ||
150 | HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT), | ||
151 | HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), | ||
152 | HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT), | ||
153 | { } /* end */ | ||
154 | }; | ||
155 | |||
156 | static const struct snd_kcontrol_new alc260_input_mixer[] = { | ||
157 | HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), | ||
158 | HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), | ||
159 | HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), | ||
160 | HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT), | ||
161 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT), | ||
162 | HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT), | ||
163 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT), | ||
164 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT), | ||
165 | { } /* end */ | ||
166 | }; | ||
167 | |||
168 | /* Fujitsu S702x series laptops. ALC260 pin usage: Mic/Line jack = 0x12, | ||
169 | * HP jack = 0x14, CD audio = 0x16, internal speaker = 0x10. | ||
170 | */ | ||
171 | static const struct snd_kcontrol_new alc260_fujitsu_mixer[] = { | ||
172 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT), | ||
173 | HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT), | ||
174 | ALC_PIN_MODE("Headphone Jack Mode", 0x14, ALC_PIN_DIR_INOUT), | ||
175 | HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), | ||
176 | HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), | ||
177 | HDA_CODEC_VOLUME("Mic/Line Playback Volume", 0x07, 0x0, HDA_INPUT), | ||
178 | HDA_CODEC_MUTE("Mic/Line Playback Switch", 0x07, 0x0, HDA_INPUT), | ||
179 | ALC_PIN_MODE("Mic/Line Jack Mode", 0x12, ALC_PIN_DIR_IN), | ||
180 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT), | ||
181 | HDA_BIND_MUTE("Speaker Playback Switch", 0x09, 2, HDA_INPUT), | ||
182 | { } /* end */ | ||
183 | }; | ||
184 | |||
185 | /* Mixer for Acer TravelMate(/Extensa/Aspire) notebooks. Note that current | ||
186 | * versions of the ALC260 don't act on requests to enable mic bias from NID | ||
187 | * 0x0f (used to drive the headphone jack in these laptops). The ALC260 | ||
188 | * datasheet doesn't mention this restriction. At this stage it's not clear | ||
189 | * whether this behaviour is intentional or is a hardware bug in chip | ||
190 | * revisions available in early 2006. Therefore for now allow the | ||
191 | * "Headphone Jack Mode" control to span all choices, but if it turns out | ||
192 | * that the lack of mic bias for this NID is intentional we could change the | ||
193 | * mode from ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS. | ||
194 | * | ||
195 | * In addition, Acer TravelMate(/Extensa/Aspire) notebooks in early 2006 | ||
196 | * don't appear to make the mic bias available from the "line" jack, even | ||
197 | * though the NID used for this jack (0x14) can supply it. The theory is | ||
198 | * that perhaps Acer have included blocking capacitors between the ALC260 | ||
199 | * and the output jack. If this turns out to be the case for all such | ||
200 | * models the "Line Jack Mode" mode could be changed from ALC_PIN_DIR_INOUT | ||
201 | * to ALC_PIN_DIR_INOUT_NOMICBIAS. | ||
202 | * | ||
203 | * The C20x Tablet series have a mono internal speaker which is controlled | ||
204 | * via the chip's Mono sum widget and pin complex, so include the necessary | ||
205 | * controls for such models. On models without a "mono speaker" the control | ||
206 | * won't do anything. | ||
207 | */ | ||
208 | static const struct snd_kcontrol_new alc260_acer_mixer[] = { | ||
209 | HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT), | ||
210 | HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT), | ||
211 | ALC_PIN_MODE("Headphone Jack Mode", 0x0f, ALC_PIN_DIR_INOUT), | ||
212 | HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0a, 1, 0x0, | ||
213 | HDA_OUTPUT), | ||
214 | HDA_BIND_MUTE_MONO("Speaker Playback Switch", 0x0a, 1, 2, | ||
215 | HDA_INPUT), | ||
216 | HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), | ||
217 | HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), | ||
218 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT), | ||
219 | HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT), | ||
220 | ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN), | ||
221 | HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), | ||
222 | HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT), | ||
223 | ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT), | ||
224 | { } /* end */ | ||
225 | }; | ||
226 | |||
227 | /* Maxdata Favorit 100XS: one output and one input (0x12) jack | ||
228 | */ | ||
229 | static const struct snd_kcontrol_new alc260_favorit100_mixer[] = { | ||
230 | HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT), | ||
231 | HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT), | ||
232 | ALC_PIN_MODE("Output Jack Mode", 0x0f, ALC_PIN_DIR_INOUT), | ||
233 | HDA_CODEC_VOLUME("Line/Mic Playback Volume", 0x07, 0x0, HDA_INPUT), | ||
234 | HDA_CODEC_MUTE("Line/Mic Playback Switch", 0x07, 0x0, HDA_INPUT), | ||
235 | ALC_PIN_MODE("Line/Mic Jack Mode", 0x12, ALC_PIN_DIR_IN), | ||
236 | { } /* end */ | ||
237 | }; | ||
238 | |||
239 | /* Packard bell V7900 ALC260 pin usage: HP = 0x0f, Mic jack = 0x12, | ||
240 | * Line In jack = 0x14, CD audio = 0x16, pc beep = 0x17. | ||
241 | */ | ||
242 | static const struct snd_kcontrol_new alc260_will_mixer[] = { | ||
243 | HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT), | ||
244 | HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT), | ||
245 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT), | ||
246 | HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT), | ||
247 | ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN), | ||
248 | HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), | ||
249 | HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT), | ||
250 | ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT), | ||
251 | HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), | ||
252 | HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), | ||
253 | { } /* end */ | ||
254 | }; | ||
255 | |||
256 | /* Replacer 672V ALC260 pin usage: Mic jack = 0x12, | ||
257 | * Line In jack = 0x14, ATAPI Mic = 0x13, speaker = 0x0f. | ||
258 | */ | ||
259 | static const struct snd_kcontrol_new alc260_replacer_672v_mixer[] = { | ||
260 | HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT), | ||
261 | HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT), | ||
262 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT), | ||
263 | HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT), | ||
264 | ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN), | ||
265 | HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x07, 0x1, HDA_INPUT), | ||
266 | HDA_CODEC_MUTE("ATATI Mic Playback Switch", 0x07, 0x1, HDA_INPUT), | ||
267 | HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), | ||
268 | HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT), | ||
269 | ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT), | ||
270 | { } /* end */ | ||
271 | }; | ||
272 | |||
273 | /* | ||
274 | * initialization verbs | ||
275 | */ | ||
276 | static const struct hda_verb alc260_init_verbs[] = { | ||
277 | /* Line In pin widget for input */ | ||
278 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
279 | /* CD pin widget for input */ | ||
280 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
281 | /* Mic1 (rear panel) pin widget for input and vref at 80% */ | ||
282 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
283 | /* Mic2 (front panel) pin widget for input and vref at 80% */ | ||
284 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
285 | /* LINE-2 is used for line-out in rear */ | ||
286 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
287 | /* select line-out */ | ||
288 | {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
289 | /* LINE-OUT pin */ | ||
290 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
291 | /* enable HP */ | ||
292 | {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
293 | /* enable Mono */ | ||
294 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
295 | /* mute capture amp left and right */ | ||
296 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
297 | /* set connection select to line in (default select for this ADC) */ | ||
298 | {0x04, AC_VERB_SET_CONNECT_SEL, 0x02}, | ||
299 | /* mute capture amp left and right */ | ||
300 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
301 | /* set connection select to line in (default select for this ADC) */ | ||
302 | {0x05, AC_VERB_SET_CONNECT_SEL, 0x02}, | ||
303 | /* set vol=0 Line-Out mixer amp left and right */ | ||
304 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
305 | /* unmute pin widget amp left and right (no gain on this amp) */ | ||
306 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
307 | /* set vol=0 HP mixer amp left and right */ | ||
308 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
309 | /* unmute pin widget amp left and right (no gain on this amp) */ | ||
310 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
311 | /* set vol=0 Mono mixer amp left and right */ | ||
312 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
313 | /* unmute pin widget amp left and right (no gain on this amp) */ | ||
314 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
315 | /* unmute LINE-2 out pin */ | ||
316 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
317 | /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & | ||
318 | * Line In 2 = 0x03 | ||
319 | */ | ||
320 | /* mute analog inputs */ | ||
321 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
322 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
323 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
324 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
325 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
326 | /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ | ||
327 | /* mute Front out path */ | ||
328 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
329 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
330 | /* mute Headphone out path */ | ||
331 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
332 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
333 | /* mute Mono out path */ | ||
334 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
335 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
336 | { } | ||
337 | }; | ||
338 | |||
339 | /* Initialisation sequence for ALC260 as configured in Fujitsu S702x | ||
340 | * laptops. ALC260 pin usage: Mic/Line jack = 0x12, HP jack = 0x14, CD | ||
341 | * audio = 0x16, internal speaker = 0x10. | ||
342 | */ | ||
343 | static const struct hda_verb alc260_fujitsu_init_verbs[] = { | ||
344 | /* Disable all GPIOs */ | ||
345 | {0x01, AC_VERB_SET_GPIO_MASK, 0}, | ||
346 | /* Internal speaker is connected to headphone pin */ | ||
347 | {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
348 | /* Headphone/Line-out jack connects to Line1 pin; make it an output */ | ||
349 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
350 | /* Mic/Line-in jack is connected to mic1 pin, so make it an input */ | ||
351 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
352 | /* Ensure all other unused pins are disabled and muted. */ | ||
353 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
354 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
355 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
356 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
357 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
358 | {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
359 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
360 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
361 | |||
362 | /* Disable digital (SPDIF) pins */ | ||
363 | {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0}, | ||
364 | {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0}, | ||
365 | |||
366 | /* Ensure Line1 pin widget takes its input from the OUT1 sum bus | ||
367 | * when acting as an output. | ||
368 | */ | ||
369 | {0x0d, AC_VERB_SET_CONNECT_SEL, 0}, | ||
370 | |||
371 | /* Start with output sum widgets muted and their output gains at min */ | ||
372 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
373 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
374 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
375 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
376 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
377 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
378 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
379 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
380 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
381 | |||
382 | /* Unmute HP pin widget amp left and right (no equiv mixer ctrl) */ | ||
383 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
384 | /* Unmute Line1 pin widget output buffer since it starts as an output. | ||
385 | * If the pin mode is changed by the user the pin mode control will | ||
386 | * take care of enabling the pin's input/output buffers as needed. | ||
387 | * Therefore there's no need to enable the input buffer at this | ||
388 | * stage. | ||
389 | */ | ||
390 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
391 | /* Unmute input buffer of pin widget used for Line-in (no equiv | ||
392 | * mixer ctrl) | ||
393 | */ | ||
394 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
395 | |||
396 | /* Mute capture amp left and right */ | ||
397 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
398 | /* Set ADC connection select to match default mixer setting - line | ||
399 | * in (on mic1 pin) | ||
400 | */ | ||
401 | {0x04, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
402 | |||
403 | /* Do the same for the second ADC: mute capture input amp and | ||
404 | * set ADC connection to line in (on mic1 pin) | ||
405 | */ | ||
406 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
407 | {0x05, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
408 | |||
409 | /* Mute all inputs to mixer widget (even unconnected ones) */ | ||
410 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */ | ||
411 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */ | ||
412 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */ | ||
413 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */ | ||
414 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */ | ||
415 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */ | ||
416 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */ | ||
417 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */ | ||
418 | |||
419 | { } | ||
420 | }; | ||
421 | |||
422 | /* Initialisation sequence for ALC260 as configured in Acer TravelMate and | ||
423 | * similar laptops (adapted from Fujitsu init verbs). | ||
424 | */ | ||
425 | static const struct hda_verb alc260_acer_init_verbs[] = { | ||
426 | /* On TravelMate laptops, GPIO 0 enables the internal speaker and | ||
427 | * the headphone jack. Turn this on and rely on the standard mute | ||
428 | * methods whenever the user wants to turn these outputs off. | ||
429 | */ | ||
430 | {0x01, AC_VERB_SET_GPIO_MASK, 0x01}, | ||
431 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, | ||
432 | {0x01, AC_VERB_SET_GPIO_DATA, 0x01}, | ||
433 | /* Internal speaker/Headphone jack is connected to Line-out pin */ | ||
434 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
435 | /* Internal microphone/Mic jack is connected to Mic1 pin */ | ||
436 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50}, | ||
437 | /* Line In jack is connected to Line1 pin */ | ||
438 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
439 | /* Some Acers (eg: C20x Tablets) use Mono pin for internal speaker */ | ||
440 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
441 | /* Ensure all other unused pins are disabled and muted. */ | ||
442 | {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
443 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
444 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
445 | {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
446 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
447 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
448 | /* Disable digital (SPDIF) pins */ | ||
449 | {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0}, | ||
450 | {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0}, | ||
451 | |||
452 | /* Ensure Mic1 and Line1 pin widgets take input from the OUT1 sum | ||
453 | * bus when acting as outputs. | ||
454 | */ | ||
455 | {0x0b, AC_VERB_SET_CONNECT_SEL, 0}, | ||
456 | {0x0d, AC_VERB_SET_CONNECT_SEL, 0}, | ||
457 | |||
458 | /* Start with output sum widgets muted and their output gains at min */ | ||
459 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
460 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
461 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
462 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
463 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
464 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
465 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
466 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
467 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
468 | |||
469 | /* Unmute Line-out pin widget amp left and right | ||
470 | * (no equiv mixer ctrl) | ||
471 | */ | ||
472 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
473 | /* Unmute mono pin widget amp output (no equiv mixer ctrl) */ | ||
474 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
475 | /* Unmute Mic1 and Line1 pin widget input buffers since they start as | ||
476 | * inputs. If the pin mode is changed by the user the pin mode control | ||
477 | * will take care of enabling the pin's input/output buffers as needed. | ||
478 | * Therefore there's no need to enable the input buffer at this | ||
479 | * stage. | ||
480 | */ | ||
481 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
482 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
483 | |||
484 | /* Mute capture amp left and right */ | ||
485 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
486 | /* Set ADC connection select to match default mixer setting - mic | ||
487 | * (on mic1 pin) | ||
488 | */ | ||
489 | {0x04, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
490 | |||
491 | /* Do similar with the second ADC: mute capture input amp and | ||
492 | * set ADC connection to mic to match ALSA's default state. | ||
493 | */ | ||
494 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
495 | {0x05, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
496 | |||
497 | /* Mute all inputs to mixer widget (even unconnected ones) */ | ||
498 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */ | ||
499 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */ | ||
500 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */ | ||
501 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */ | ||
502 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */ | ||
503 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */ | ||
504 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */ | ||
505 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */ | ||
506 | |||
507 | { } | ||
508 | }; | ||
509 | |||
510 | /* Initialisation sequence for Maxdata Favorit 100XS | ||
511 | * (adapted from Acer init verbs). | ||
512 | */ | ||
513 | static const struct hda_verb alc260_favorit100_init_verbs[] = { | ||
514 | /* GPIO 0 enables the output jack. | ||
515 | * Turn this on and rely on the standard mute | ||
516 | * methods whenever the user wants to turn these outputs off. | ||
517 | */ | ||
518 | {0x01, AC_VERB_SET_GPIO_MASK, 0x01}, | ||
519 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, | ||
520 | {0x01, AC_VERB_SET_GPIO_DATA, 0x01}, | ||
521 | /* Line/Mic input jack is connected to Mic1 pin */ | ||
522 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50}, | ||
523 | /* Ensure all other unused pins are disabled and muted. */ | ||
524 | {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
525 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
526 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
527 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
528 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
529 | {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
530 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
531 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
532 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
533 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
534 | /* Disable digital (SPDIF) pins */ | ||
535 | {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0}, | ||
536 | {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0}, | ||
537 | |||
538 | /* Ensure Mic1 and Line1 pin widgets take input from the OUT1 sum | ||
539 | * bus when acting as outputs. | ||
540 | */ | ||
541 | {0x0b, AC_VERB_SET_CONNECT_SEL, 0}, | ||
542 | {0x0d, AC_VERB_SET_CONNECT_SEL, 0}, | ||
543 | |||
544 | /* Start with output sum widgets muted and their output gains at min */ | ||
545 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
546 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
547 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
548 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
549 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
550 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
551 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
552 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
553 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
554 | |||
555 | /* Unmute Line-out pin widget amp left and right | ||
556 | * (no equiv mixer ctrl) | ||
557 | */ | ||
558 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
559 | /* Unmute Mic1 and Line1 pin widget input buffers since they start as | ||
560 | * inputs. If the pin mode is changed by the user the pin mode control | ||
561 | * will take care of enabling the pin's input/output buffers as needed. | ||
562 | * Therefore there's no need to enable the input buffer at this | ||
563 | * stage. | ||
564 | */ | ||
565 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
566 | |||
567 | /* Mute capture amp left and right */ | ||
568 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
569 | /* Set ADC connection select to match default mixer setting - mic | ||
570 | * (on mic1 pin) | ||
571 | */ | ||
572 | {0x04, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
573 | |||
574 | /* Do similar with the second ADC: mute capture input amp and | ||
575 | * set ADC connection to mic to match ALSA's default state. | ||
576 | */ | ||
577 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
578 | {0x05, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
579 | |||
580 | /* Mute all inputs to mixer widget (even unconnected ones) */ | ||
581 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */ | ||
582 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */ | ||
583 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */ | ||
584 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */ | ||
585 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */ | ||
586 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */ | ||
587 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */ | ||
588 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */ | ||
589 | |||
590 | { } | ||
591 | }; | ||
592 | |||
593 | static const struct hda_verb alc260_will_verbs[] = { | ||
594 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
595 | {0x0b, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
596 | {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
597 | {0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, | ||
598 | {0x1a, AC_VERB_SET_COEF_INDEX, 0x07}, | ||
599 | {0x1a, AC_VERB_SET_PROC_COEF, 0x3040}, | ||
600 | {} | ||
601 | }; | ||
602 | |||
603 | static const struct hda_verb alc260_replacer_672v_verbs[] = { | ||
604 | {0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, | ||
605 | {0x1a, AC_VERB_SET_COEF_INDEX, 0x07}, | ||
606 | {0x1a, AC_VERB_SET_PROC_COEF, 0x3050}, | ||
607 | |||
608 | {0x01, AC_VERB_SET_GPIO_MASK, 0x01}, | ||
609 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, | ||
610 | {0x01, AC_VERB_SET_GPIO_DATA, 0x00}, | ||
611 | |||
612 | {0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT}, | ||
613 | {} | ||
614 | }; | ||
615 | |||
616 | /* toggle speaker-output according to the hp-jack state */ | ||
617 | static void alc260_replacer_672v_automute(struct hda_codec *codec) | ||
618 | { | ||
619 | unsigned int present; | ||
620 | |||
621 | /* speaker --> GPIO Data 0, hp or spdif --> GPIO data 1 */ | ||
622 | present = snd_hda_jack_detect(codec, 0x0f); | ||
623 | if (present) { | ||
624 | snd_hda_codec_write_cache(codec, 0x01, 0, | ||
625 | AC_VERB_SET_GPIO_DATA, 1); | ||
626 | snd_hda_codec_write_cache(codec, 0x0f, 0, | ||
627 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
628 | PIN_HP); | ||
629 | } else { | ||
630 | snd_hda_codec_write_cache(codec, 0x01, 0, | ||
631 | AC_VERB_SET_GPIO_DATA, 0); | ||
632 | snd_hda_codec_write_cache(codec, 0x0f, 0, | ||
633 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
634 | PIN_OUT); | ||
635 | } | ||
636 | } | ||
637 | |||
638 | static void alc260_replacer_672v_unsol_event(struct hda_codec *codec, | ||
639 | unsigned int res) | ||
640 | { | ||
641 | if ((res >> 26) == ALC_HP_EVENT) | ||
642 | alc260_replacer_672v_automute(codec); | ||
643 | } | ||
644 | |||
645 | static const struct hda_verb alc260_hp_dc7600_verbs[] = { | ||
646 | {0x05, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
647 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
648 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
649 | {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
650 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
651 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
652 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
653 | {0x10, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT}, | ||
654 | {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT}, | ||
655 | {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT}, | ||
656 | {} | ||
657 | }; | ||
658 | |||
659 | /* Test configuration for debugging, modelled after the ALC880 test | ||
660 | * configuration. | ||
661 | */ | ||
662 | #ifdef CONFIG_SND_DEBUG | ||
663 | static const hda_nid_t alc260_test_dac_nids[1] = { | ||
664 | 0x02, | ||
665 | }; | ||
666 | static const hda_nid_t alc260_test_adc_nids[2] = { | ||
667 | 0x04, 0x05, | ||
668 | }; | ||
669 | /* For testing the ALC260, each input MUX needs its own definition since | ||
670 | * the signal assignments are different. This assumes that the first ADC | ||
671 | * is NID 0x04. | ||
672 | */ | ||
673 | static const struct hda_input_mux alc260_test_capture_sources[2] = { | ||
674 | { | ||
675 | .num_items = 7, | ||
676 | .items = { | ||
677 | { "MIC1 pin", 0x0 }, | ||
678 | { "MIC2 pin", 0x1 }, | ||
679 | { "LINE1 pin", 0x2 }, | ||
680 | { "LINE2 pin", 0x3 }, | ||
681 | { "CD pin", 0x4 }, | ||
682 | { "LINE-OUT pin", 0x5 }, | ||
683 | { "HP-OUT pin", 0x6 }, | ||
684 | }, | ||
685 | }, | ||
686 | { | ||
687 | .num_items = 8, | ||
688 | .items = { | ||
689 | { "MIC1 pin", 0x0 }, | ||
690 | { "MIC2 pin", 0x1 }, | ||
691 | { "LINE1 pin", 0x2 }, | ||
692 | { "LINE2 pin", 0x3 }, | ||
693 | { "CD pin", 0x4 }, | ||
694 | { "Mixer", 0x5 }, | ||
695 | { "LINE-OUT pin", 0x6 }, | ||
696 | { "HP-OUT pin", 0x7 }, | ||
697 | }, | ||
698 | }, | ||
699 | }; | ||
700 | static const struct snd_kcontrol_new alc260_test_mixer[] = { | ||
701 | /* Output driver widgets */ | ||
702 | HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), | ||
703 | HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT), | ||
704 | HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x09, 0x0, HDA_OUTPUT), | ||
705 | HDA_BIND_MUTE("LOUT2 Playback Switch", 0x09, 2, HDA_INPUT), | ||
706 | HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x08, 0x0, HDA_OUTPUT), | ||
707 | HDA_BIND_MUTE("LOUT1 Playback Switch", 0x08, 2, HDA_INPUT), | ||
708 | |||
709 | /* Modes for retasking pin widgets | ||
710 | * Note: the ALC260 doesn't seem to act on requests to enable mic | ||
711 | * bias from NIDs 0x0f and 0x10. The ALC260 datasheet doesn't | ||
712 | * mention this restriction. At this stage it's not clear whether | ||
713 | * this behaviour is intentional or is a hardware bug in chip | ||
714 | * revisions available at least up until early 2006. Therefore for | ||
715 | * now allow the "HP-OUT" and "LINE-OUT" Mode controls to span all | ||
716 | * choices, but if it turns out that the lack of mic bias for these | ||
717 | * NIDs is intentional we could change their modes from | ||
718 | * ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS. | ||
719 | */ | ||
720 | ALC_PIN_MODE("HP-OUT pin mode", 0x10, ALC_PIN_DIR_INOUT), | ||
721 | ALC_PIN_MODE("LINE-OUT pin mode", 0x0f, ALC_PIN_DIR_INOUT), | ||
722 | ALC_PIN_MODE("LINE2 pin mode", 0x15, ALC_PIN_DIR_INOUT), | ||
723 | ALC_PIN_MODE("LINE1 pin mode", 0x14, ALC_PIN_DIR_INOUT), | ||
724 | ALC_PIN_MODE("MIC2 pin mode", 0x13, ALC_PIN_DIR_INOUT), | ||
725 | ALC_PIN_MODE("MIC1 pin mode", 0x12, ALC_PIN_DIR_INOUT), | ||
726 | |||
727 | /* Loopback mixer controls */ | ||
728 | HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x07, 0x00, HDA_INPUT), | ||
729 | HDA_CODEC_MUTE("MIC1 Playback Switch", 0x07, 0x00, HDA_INPUT), | ||
730 | HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x07, 0x01, HDA_INPUT), | ||
731 | HDA_CODEC_MUTE("MIC2 Playback Switch", 0x07, 0x01, HDA_INPUT), | ||
732 | HDA_CODEC_VOLUME("LINE1 Playback Volume", 0x07, 0x02, HDA_INPUT), | ||
733 | HDA_CODEC_MUTE("LINE1 Playback Switch", 0x07, 0x02, HDA_INPUT), | ||
734 | HDA_CODEC_VOLUME("LINE2 Playback Volume", 0x07, 0x03, HDA_INPUT), | ||
735 | HDA_CODEC_MUTE("LINE2 Playback Switch", 0x07, 0x03, HDA_INPUT), | ||
736 | HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), | ||
737 | HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), | ||
738 | HDA_CODEC_VOLUME("LINE-OUT loopback Playback Volume", 0x07, 0x06, HDA_INPUT), | ||
739 | HDA_CODEC_MUTE("LINE-OUT loopback Playback Switch", 0x07, 0x06, HDA_INPUT), | ||
740 | HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x07, 0x7, HDA_INPUT), | ||
741 | HDA_CODEC_MUTE("HP-OUT loopback Playback Switch", 0x07, 0x7, HDA_INPUT), | ||
742 | |||
743 | /* Controls for GPIO pins, assuming they are configured as outputs */ | ||
744 | ALC_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01), | ||
745 | ALC_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02), | ||
746 | ALC_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04), | ||
747 | ALC_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08), | ||
748 | |||
749 | /* Switches to allow the digital IO pins to be enabled. The datasheet | ||
750 | * is ambigious as to which NID is which; testing on laptops which | ||
751 | * make this output available should provide clarification. | ||
752 | */ | ||
753 | ALC_SPDIF_CTRL_SWITCH("SPDIF Playback Switch", 0x03, 0x01), | ||
754 | ALC_SPDIF_CTRL_SWITCH("SPDIF Capture Switch", 0x06, 0x01), | ||
755 | |||
756 | /* A switch allowing EAPD to be enabled. Some laptops seem to use | ||
757 | * this output to turn on an external amplifier. | ||
758 | */ | ||
759 | ALC_EAPD_CTRL_SWITCH("LINE-OUT EAPD Enable Switch", 0x0f, 0x02), | ||
760 | ALC_EAPD_CTRL_SWITCH("HP-OUT EAPD Enable Switch", 0x10, 0x02), | ||
761 | |||
762 | { } /* end */ | ||
763 | }; | ||
764 | static const struct hda_verb alc260_test_init_verbs[] = { | ||
765 | /* Enable all GPIOs as outputs with an initial value of 0 */ | ||
766 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x0f}, | ||
767 | {0x01, AC_VERB_SET_GPIO_DATA, 0x00}, | ||
768 | {0x01, AC_VERB_SET_GPIO_MASK, 0x0f}, | ||
769 | |||
770 | /* Enable retasking pins as output, initially without power amp */ | ||
771 | {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
772 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
773 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
774 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
775 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
776 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
777 | |||
778 | /* Disable digital (SPDIF) pins initially, but users can enable | ||
779 | * them via a mixer switch. In the case of SPDIF-out, this initverb | ||
780 | * payload also sets the generation to 0, output to be in "consumer" | ||
781 | * PCM format, copyright asserted, no pre-emphasis and no validity | ||
782 | * control. | ||
783 | */ | ||
784 | {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0}, | ||
785 | {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0}, | ||
786 | |||
787 | /* Ensure mic1, mic2, line1 and line2 pin widgets take input from the | ||
788 | * OUT1 sum bus when acting as an output. | ||
789 | */ | ||
790 | {0x0b, AC_VERB_SET_CONNECT_SEL, 0}, | ||
791 | {0x0c, AC_VERB_SET_CONNECT_SEL, 0}, | ||
792 | {0x0d, AC_VERB_SET_CONNECT_SEL, 0}, | ||
793 | {0x0e, AC_VERB_SET_CONNECT_SEL, 0}, | ||
794 | |||
795 | /* Start with output sum widgets muted and their output gains at min */ | ||
796 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
797 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
798 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
799 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
800 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
801 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
802 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
803 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
804 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
805 | |||
806 | /* Unmute retasking pin widget output buffers since the default | ||
807 | * state appears to be output. As the pin mode is changed by the | ||
808 | * user the pin mode control will take care of enabling the pin's | ||
809 | * input/output buffers as needed. | ||
810 | */ | ||
811 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
812 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
813 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
814 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
815 | {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
816 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
817 | /* Also unmute the mono-out pin widget */ | ||
818 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
819 | |||
820 | /* Mute capture amp left and right */ | ||
821 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
822 | /* Set ADC connection select to match default mixer setting (mic1 | ||
823 | * pin) | ||
824 | */ | ||
825 | {0x04, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
826 | |||
827 | /* Do the same for the second ADC: mute capture input amp and | ||
828 | * set ADC connection to mic1 pin | ||
829 | */ | ||
830 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
831 | {0x05, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
832 | |||
833 | /* Mute all inputs to mixer widget (even unconnected ones) */ | ||
834 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */ | ||
835 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */ | ||
836 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */ | ||
837 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */ | ||
838 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */ | ||
839 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */ | ||
840 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */ | ||
841 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */ | ||
842 | |||
843 | { } | ||
844 | }; | ||
845 | #endif | ||
846 | |||
847 | /* | ||
848 | * ALC260 configurations | ||
849 | */ | ||
850 | static const char * const alc260_models[ALC260_MODEL_LAST] = { | ||
851 | [ALC260_BASIC] = "basic", | ||
852 | [ALC260_FUJITSU_S702X] = "fujitsu", | ||
853 | [ALC260_ACER] = "acer", | ||
854 | [ALC260_WILL] = "will", | ||
855 | [ALC260_REPLACER_672V] = "replacer", | ||
856 | [ALC260_FAVORIT100] = "favorit100", | ||
857 | #ifdef CONFIG_SND_DEBUG | ||
858 | [ALC260_TEST] = "test", | ||
859 | #endif | ||
860 | [ALC260_AUTO] = "auto", | ||
861 | }; | ||
862 | |||
863 | static const struct snd_pci_quirk alc260_cfg_tbl[] = { | ||
864 | SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_ACER), | ||
865 | SND_PCI_QUIRK(0x1025, 0x007f, "Acer", ALC260_WILL), | ||
866 | SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_ACER), | ||
867 | SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FAVORIT100), | ||
868 | SND_PCI_QUIRK(0x104d, 0x81bb, "Sony VAIO", ALC260_BASIC), | ||
869 | SND_PCI_QUIRK(0x104d, 0x81cc, "Sony VAIO", ALC260_BASIC), | ||
870 | SND_PCI_QUIRK(0x104d, 0x81cd, "Sony VAIO", ALC260_BASIC), | ||
871 | SND_PCI_QUIRK(0x10cf, 0x1326, "Fujitsu S702X", ALC260_FUJITSU_S702X), | ||
872 | SND_PCI_QUIRK(0x152d, 0x0729, "CTL U553W", ALC260_BASIC), | ||
873 | SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_REPLACER_672V), | ||
874 | SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_WILL), | ||
875 | {} | ||
876 | }; | ||
877 | |||
878 | static const struct alc_config_preset alc260_presets[] = { | ||
879 | [ALC260_BASIC] = { | ||
880 | .mixers = { alc260_base_output_mixer, | ||
881 | alc260_input_mixer }, | ||
882 | .init_verbs = { alc260_init_verbs }, | ||
883 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), | ||
884 | .dac_nids = alc260_dac_nids, | ||
885 | .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids), | ||
886 | .adc_nids = alc260_dual_adc_nids, | ||
887 | .num_channel_mode = ARRAY_SIZE(alc260_modes), | ||
888 | .channel_mode = alc260_modes, | ||
889 | .input_mux = &alc260_capture_source, | ||
890 | }, | ||
891 | [ALC260_FUJITSU_S702X] = { | ||
892 | .mixers = { alc260_fujitsu_mixer }, | ||
893 | .init_verbs = { alc260_fujitsu_init_verbs }, | ||
894 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), | ||
895 | .dac_nids = alc260_dac_nids, | ||
896 | .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids), | ||
897 | .adc_nids = alc260_dual_adc_nids, | ||
898 | .num_channel_mode = ARRAY_SIZE(alc260_modes), | ||
899 | .channel_mode = alc260_modes, | ||
900 | .num_mux_defs = ARRAY_SIZE(alc260_fujitsu_capture_sources), | ||
901 | .input_mux = alc260_fujitsu_capture_sources, | ||
902 | }, | ||
903 | [ALC260_ACER] = { | ||
904 | .mixers = { alc260_acer_mixer }, | ||
905 | .init_verbs = { alc260_acer_init_verbs }, | ||
906 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), | ||
907 | .dac_nids = alc260_dac_nids, | ||
908 | .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids), | ||
909 | .adc_nids = alc260_dual_adc_nids, | ||
910 | .num_channel_mode = ARRAY_SIZE(alc260_modes), | ||
911 | .channel_mode = alc260_modes, | ||
912 | .num_mux_defs = ARRAY_SIZE(alc260_acer_capture_sources), | ||
913 | .input_mux = alc260_acer_capture_sources, | ||
914 | }, | ||
915 | [ALC260_FAVORIT100] = { | ||
916 | .mixers = { alc260_favorit100_mixer }, | ||
917 | .init_verbs = { alc260_favorit100_init_verbs }, | ||
918 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), | ||
919 | .dac_nids = alc260_dac_nids, | ||
920 | .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids), | ||
921 | .adc_nids = alc260_dual_adc_nids, | ||
922 | .num_channel_mode = ARRAY_SIZE(alc260_modes), | ||
923 | .channel_mode = alc260_modes, | ||
924 | .num_mux_defs = ARRAY_SIZE(alc260_favorit100_capture_sources), | ||
925 | .input_mux = alc260_favorit100_capture_sources, | ||
926 | }, | ||
927 | [ALC260_WILL] = { | ||
928 | .mixers = { alc260_will_mixer }, | ||
929 | .init_verbs = { alc260_init_verbs, alc260_will_verbs }, | ||
930 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), | ||
931 | .dac_nids = alc260_dac_nids, | ||
932 | .num_adc_nids = ARRAY_SIZE(alc260_adc_nids), | ||
933 | .adc_nids = alc260_adc_nids, | ||
934 | .dig_out_nid = ALC260_DIGOUT_NID, | ||
935 | .num_channel_mode = ARRAY_SIZE(alc260_modes), | ||
936 | .channel_mode = alc260_modes, | ||
937 | .input_mux = &alc260_capture_source, | ||
938 | }, | ||
939 | [ALC260_REPLACER_672V] = { | ||
940 | .mixers = { alc260_replacer_672v_mixer }, | ||
941 | .init_verbs = { alc260_init_verbs, alc260_replacer_672v_verbs }, | ||
942 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), | ||
943 | .dac_nids = alc260_dac_nids, | ||
944 | .num_adc_nids = ARRAY_SIZE(alc260_adc_nids), | ||
945 | .adc_nids = alc260_adc_nids, | ||
946 | .dig_out_nid = ALC260_DIGOUT_NID, | ||
947 | .num_channel_mode = ARRAY_SIZE(alc260_modes), | ||
948 | .channel_mode = alc260_modes, | ||
949 | .input_mux = &alc260_capture_source, | ||
950 | .unsol_event = alc260_replacer_672v_unsol_event, | ||
951 | .init_hook = alc260_replacer_672v_automute, | ||
952 | }, | ||
953 | #ifdef CONFIG_SND_DEBUG | ||
954 | [ALC260_TEST] = { | ||
955 | .mixers = { alc260_test_mixer }, | ||
956 | .init_verbs = { alc260_test_init_verbs }, | ||
957 | .num_dacs = ARRAY_SIZE(alc260_test_dac_nids), | ||
958 | .dac_nids = alc260_test_dac_nids, | ||
959 | .num_adc_nids = ARRAY_SIZE(alc260_test_adc_nids), | ||
960 | .adc_nids = alc260_test_adc_nids, | ||
961 | .num_channel_mode = ARRAY_SIZE(alc260_modes), | ||
962 | .channel_mode = alc260_modes, | ||
963 | .num_mux_defs = ARRAY_SIZE(alc260_test_capture_sources), | ||
964 | .input_mux = alc260_test_capture_sources, | ||
965 | }, | ||
966 | #endif | ||
967 | }; | ||
968 | |||
diff --git a/sound/pci/hda/alc880_quirks.c b/sound/pci/hda/alc880_quirks.c deleted file mode 100644 index 501501ef36a9..000000000000 --- a/sound/pci/hda/alc880_quirks.c +++ /dev/null | |||
@@ -1,1707 +0,0 @@ | |||
1 | /* | ||
2 | * ALC880 quirk models | ||
3 | * included by patch_realtek.c | ||
4 | */ | ||
5 | |||
6 | /* ALC880 board config type */ | ||
7 | enum { | ||
8 | ALC880_AUTO, | ||
9 | ALC880_3ST, | ||
10 | ALC880_3ST_DIG, | ||
11 | ALC880_5ST, | ||
12 | ALC880_5ST_DIG, | ||
13 | ALC880_W810, | ||
14 | ALC880_Z71V, | ||
15 | ALC880_6ST, | ||
16 | ALC880_6ST_DIG, | ||
17 | ALC880_F1734, | ||
18 | ALC880_ASUS, | ||
19 | ALC880_ASUS_DIG, | ||
20 | ALC880_ASUS_W1V, | ||
21 | ALC880_ASUS_DIG2, | ||
22 | ALC880_FUJITSU, | ||
23 | ALC880_UNIWILL_DIG, | ||
24 | ALC880_UNIWILL, | ||
25 | ALC880_UNIWILL_P53, | ||
26 | ALC880_CLEVO, | ||
27 | ALC880_TCL_S700, | ||
28 | ALC880_LG, | ||
29 | #ifdef CONFIG_SND_DEBUG | ||
30 | ALC880_TEST, | ||
31 | #endif | ||
32 | ALC880_MODEL_LAST /* last tag */ | ||
33 | }; | ||
34 | |||
35 | /* | ||
36 | * ALC880 3-stack model | ||
37 | * | ||
38 | * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e) | ||
39 | * Pin assignment: Front = 0x14, Line-In/Surr = 0x1a, Mic/CLFE = 0x18, | ||
40 | * F-Mic = 0x1b, HP = 0x19 | ||
41 | */ | ||
42 | |||
43 | static const hda_nid_t alc880_dac_nids[4] = { | ||
44 | /* front, rear, clfe, rear_surr */ | ||
45 | 0x02, 0x05, 0x04, 0x03 | ||
46 | }; | ||
47 | |||
48 | static const hda_nid_t alc880_adc_nids[3] = { | ||
49 | /* ADC0-2 */ | ||
50 | 0x07, 0x08, 0x09, | ||
51 | }; | ||
52 | |||
53 | /* The datasheet says the node 0x07 is connected from inputs, | ||
54 | * but it shows zero connection in the real implementation on some devices. | ||
55 | * Note: this is a 915GAV bug, fixed on 915GLV | ||
56 | */ | ||
57 | static const hda_nid_t alc880_adc_nids_alt[2] = { | ||
58 | /* ADC1-2 */ | ||
59 | 0x08, 0x09, | ||
60 | }; | ||
61 | |||
62 | #define ALC880_DIGOUT_NID 0x06 | ||
63 | #define ALC880_DIGIN_NID 0x0a | ||
64 | #define ALC880_PIN_CD_NID 0x1c | ||
65 | |||
66 | static const struct hda_input_mux alc880_capture_source = { | ||
67 | .num_items = 4, | ||
68 | .items = { | ||
69 | { "Mic", 0x0 }, | ||
70 | { "Front Mic", 0x3 }, | ||
71 | { "Line", 0x2 }, | ||
72 | { "CD", 0x4 }, | ||
73 | }, | ||
74 | }; | ||
75 | |||
76 | /* channel source setting (2/6 channel selection for 3-stack) */ | ||
77 | /* 2ch mode */ | ||
78 | static const struct hda_verb alc880_threestack_ch2_init[] = { | ||
79 | /* set line-in to input, mute it */ | ||
80 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | ||
81 | { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, | ||
82 | /* set mic-in to input vref 80%, mute it */ | ||
83 | { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, | ||
84 | { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, | ||
85 | { } /* end */ | ||
86 | }; | ||
87 | |||
88 | /* 6ch mode */ | ||
89 | static const struct hda_verb alc880_threestack_ch6_init[] = { | ||
90 | /* set line-in to output, unmute it */ | ||
91 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
92 | { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, | ||
93 | /* set mic-in to output, unmute it */ | ||
94 | { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
95 | { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, | ||
96 | { } /* end */ | ||
97 | }; | ||
98 | |||
99 | static const struct hda_channel_mode alc880_threestack_modes[2] = { | ||
100 | { 2, alc880_threestack_ch2_init }, | ||
101 | { 6, alc880_threestack_ch6_init }, | ||
102 | }; | ||
103 | |||
104 | static const struct snd_kcontrol_new alc880_three_stack_mixer[] = { | ||
105 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
106 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | ||
107 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT), | ||
108 | HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT), | ||
109 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), | ||
110 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), | ||
111 | HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), | ||
112 | HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), | ||
113 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
114 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
115 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | ||
116 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | ||
117 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
118 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
119 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT), | ||
120 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT), | ||
121 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT), | ||
122 | { | ||
123 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
124 | .name = "Channel Mode", | ||
125 | .info = alc_ch_mode_info, | ||
126 | .get = alc_ch_mode_get, | ||
127 | .put = alc_ch_mode_put, | ||
128 | }, | ||
129 | { } /* end */ | ||
130 | }; | ||
131 | |||
132 | /* | ||
133 | * ALC880 5-stack model | ||
134 | * | ||
135 | * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0d), | ||
136 | * Side = 0x02 (0xd) | ||
137 | * Pin assignment: Front = 0x14, Surr = 0x17, CLFE = 0x16 | ||
138 | * Line-In/Side = 0x1a, Mic = 0x18, F-Mic = 0x1b, HP = 0x19 | ||
139 | */ | ||
140 | |||
141 | /* additional mixers to alc880_three_stack_mixer */ | ||
142 | static const struct snd_kcontrol_new alc880_five_stack_mixer[] = { | ||
143 | HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
144 | HDA_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT), | ||
145 | { } /* end */ | ||
146 | }; | ||
147 | |||
148 | /* channel source setting (6/8 channel selection for 5-stack) */ | ||
149 | /* 6ch mode */ | ||
150 | static const struct hda_verb alc880_fivestack_ch6_init[] = { | ||
151 | /* set line-in to input, mute it */ | ||
152 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | ||
153 | { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, | ||
154 | { } /* end */ | ||
155 | }; | ||
156 | |||
157 | /* 8ch mode */ | ||
158 | static const struct hda_verb alc880_fivestack_ch8_init[] = { | ||
159 | /* set line-in to output, unmute it */ | ||
160 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
161 | { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, | ||
162 | { } /* end */ | ||
163 | }; | ||
164 | |||
165 | static const struct hda_channel_mode alc880_fivestack_modes[2] = { | ||
166 | { 6, alc880_fivestack_ch6_init }, | ||
167 | { 8, alc880_fivestack_ch8_init }, | ||
168 | }; | ||
169 | |||
170 | |||
171 | /* | ||
172 | * ALC880 6-stack model | ||
173 | * | ||
174 | * DAC: Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e), | ||
175 | * Side = 0x05 (0x0f) | ||
176 | * Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, Side = 0x17, | ||
177 | * Mic = 0x18, F-Mic = 0x19, Line = 0x1a, HP = 0x1b | ||
178 | */ | ||
179 | |||
180 | static const hda_nid_t alc880_6st_dac_nids[4] = { | ||
181 | /* front, rear, clfe, rear_surr */ | ||
182 | 0x02, 0x03, 0x04, 0x05 | ||
183 | }; | ||
184 | |||
185 | static const struct hda_input_mux alc880_6stack_capture_source = { | ||
186 | .num_items = 4, | ||
187 | .items = { | ||
188 | { "Mic", 0x0 }, | ||
189 | { "Front Mic", 0x1 }, | ||
190 | { "Line", 0x2 }, | ||
191 | { "CD", 0x4 }, | ||
192 | }, | ||
193 | }; | ||
194 | |||
195 | /* fixed 8-channels */ | ||
196 | static const struct hda_channel_mode alc880_sixstack_modes[1] = { | ||
197 | { 8, NULL }, | ||
198 | }; | ||
199 | |||
200 | static const struct snd_kcontrol_new alc880_six_stack_mixer[] = { | ||
201 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
202 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | ||
203 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
204 | HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), | ||
205 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), | ||
206 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), | ||
207 | HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), | ||
208 | HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), | ||
209 | HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), | ||
210 | HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), | ||
211 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
212 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
213 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | ||
214 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | ||
215 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
216 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
217 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | ||
218 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | ||
219 | { | ||
220 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
221 | .name = "Channel Mode", | ||
222 | .info = alc_ch_mode_info, | ||
223 | .get = alc_ch_mode_get, | ||
224 | .put = alc_ch_mode_put, | ||
225 | }, | ||
226 | { } /* end */ | ||
227 | }; | ||
228 | |||
229 | |||
230 | /* | ||
231 | * ALC880 W810 model | ||
232 | * | ||
233 | * W810 has rear IO for: | ||
234 | * Front (DAC 02) | ||
235 | * Surround (DAC 03) | ||
236 | * Center/LFE (DAC 04) | ||
237 | * Digital out (06) | ||
238 | * | ||
239 | * The system also has a pair of internal speakers, and a headphone jack. | ||
240 | * These are both connected to Line2 on the codec, hence to DAC 02. | ||
241 | * | ||
242 | * There is a variable resistor to control the speaker or headphone | ||
243 | * volume. This is a hardware-only device without a software API. | ||
244 | * | ||
245 | * Plugging headphones in will disable the internal speakers. This is | ||
246 | * implemented in hardware, not via the driver using jack sense. In | ||
247 | * a similar fashion, plugging into the rear socket marked "front" will | ||
248 | * disable both the speakers and headphones. | ||
249 | * | ||
250 | * For input, there's a microphone jack, and an "audio in" jack. | ||
251 | * These may not do anything useful with this driver yet, because I | ||
252 | * haven't setup any initialization verbs for these yet... | ||
253 | */ | ||
254 | |||
255 | static const hda_nid_t alc880_w810_dac_nids[3] = { | ||
256 | /* front, rear/surround, clfe */ | ||
257 | 0x02, 0x03, 0x04 | ||
258 | }; | ||
259 | |||
260 | /* fixed 6 channels */ | ||
261 | static const struct hda_channel_mode alc880_w810_modes[1] = { | ||
262 | { 6, NULL } | ||
263 | }; | ||
264 | |||
265 | /* Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, HP = 0x1b */ | ||
266 | static const struct snd_kcontrol_new alc880_w810_base_mixer[] = { | ||
267 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
268 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | ||
269 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
270 | HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), | ||
271 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), | ||
272 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), | ||
273 | HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), | ||
274 | HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), | ||
275 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | ||
276 | { } /* end */ | ||
277 | }; | ||
278 | |||
279 | |||
280 | /* | ||
281 | * Z710V model | ||
282 | * | ||
283 | * DAC: Front = 0x02 (0x0c), HP = 0x03 (0x0d) | ||
284 | * Pin assignment: Front = 0x14, HP = 0x15, Mic = 0x18, Mic2 = 0x19(?), | ||
285 | * Line = 0x1a | ||
286 | */ | ||
287 | |||
288 | static const hda_nid_t alc880_z71v_dac_nids[1] = { | ||
289 | 0x02 | ||
290 | }; | ||
291 | #define ALC880_Z71V_HP_DAC 0x03 | ||
292 | |||
293 | /* fixed 2 channels */ | ||
294 | static const struct hda_channel_mode alc880_2_jack_modes[1] = { | ||
295 | { 2, NULL } | ||
296 | }; | ||
297 | |||
298 | static const struct snd_kcontrol_new alc880_z71v_mixer[] = { | ||
299 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
300 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | ||
301 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
302 | HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT), | ||
303 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
304 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
305 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
306 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
307 | { } /* end */ | ||
308 | }; | ||
309 | |||
310 | |||
311 | /* | ||
312 | * ALC880 F1734 model | ||
313 | * | ||
314 | * DAC: HP = 0x02 (0x0c), Front = 0x03 (0x0d) | ||
315 | * Pin assignment: HP = 0x14, Front = 0x15, Mic = 0x18 | ||
316 | */ | ||
317 | |||
318 | static const hda_nid_t alc880_f1734_dac_nids[1] = { | ||
319 | 0x03 | ||
320 | }; | ||
321 | #define ALC880_F1734_HP_DAC 0x02 | ||
322 | |||
323 | static const struct snd_kcontrol_new alc880_f1734_mixer[] = { | ||
324 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
325 | HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT), | ||
326 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
327 | HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT), | ||
328 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
329 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
330 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | ||
331 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | ||
332 | { } /* end */ | ||
333 | }; | ||
334 | |||
335 | static const struct hda_input_mux alc880_f1734_capture_source = { | ||
336 | .num_items = 2, | ||
337 | .items = { | ||
338 | { "Mic", 0x1 }, | ||
339 | { "CD", 0x4 }, | ||
340 | }, | ||
341 | }; | ||
342 | |||
343 | |||
344 | /* | ||
345 | * ALC880 ASUS model | ||
346 | * | ||
347 | * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e) | ||
348 | * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16, | ||
349 | * Mic = 0x18, Line = 0x1a | ||
350 | */ | ||
351 | |||
352 | #define alc880_asus_dac_nids alc880_w810_dac_nids /* identical with w810 */ | ||
353 | #define alc880_asus_modes alc880_threestack_modes /* 2/6 channel mode */ | ||
354 | |||
355 | static const struct snd_kcontrol_new alc880_asus_mixer[] = { | ||
356 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
357 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | ||
358 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
359 | HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), | ||
360 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), | ||
361 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), | ||
362 | HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), | ||
363 | HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), | ||
364 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
365 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
366 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | ||
367 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | ||
368 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
369 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
370 | { | ||
371 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
372 | .name = "Channel Mode", | ||
373 | .info = alc_ch_mode_info, | ||
374 | .get = alc_ch_mode_get, | ||
375 | .put = alc_ch_mode_put, | ||
376 | }, | ||
377 | { } /* end */ | ||
378 | }; | ||
379 | |||
380 | /* | ||
381 | * ALC880 ASUS W1V model | ||
382 | * | ||
383 | * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e) | ||
384 | * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16, | ||
385 | * Mic = 0x18, Line = 0x1a, Line2 = 0x1b | ||
386 | */ | ||
387 | |||
388 | /* additional mixers to alc880_asus_mixer */ | ||
389 | static const struct snd_kcontrol_new alc880_asus_w1v_mixer[] = { | ||
390 | HDA_CODEC_VOLUME("Line2 Playback Volume", 0x0b, 0x03, HDA_INPUT), | ||
391 | HDA_CODEC_MUTE("Line2 Playback Switch", 0x0b, 0x03, HDA_INPUT), | ||
392 | { } /* end */ | ||
393 | }; | ||
394 | |||
395 | /* TCL S700 */ | ||
396 | static const struct snd_kcontrol_new alc880_tcl_s700_mixer[] = { | ||
397 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
398 | HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | ||
399 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT), | ||
400 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0B, 0x04, HDA_INPUT), | ||
401 | HDA_CODEC_MUTE("CD Playback Switch", 0x0B, 0x04, HDA_INPUT), | ||
402 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0B, 0x0, HDA_INPUT), | ||
403 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0B, 0x0, HDA_INPUT), | ||
404 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
405 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
406 | { } /* end */ | ||
407 | }; | ||
408 | |||
409 | /* Uniwill */ | ||
410 | static const struct snd_kcontrol_new alc880_uniwill_mixer[] = { | ||
411 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
412 | HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT), | ||
413 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
414 | HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT), | ||
415 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), | ||
416 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), | ||
417 | HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), | ||
418 | HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), | ||
419 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
420 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
421 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | ||
422 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | ||
423 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
424 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
425 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | ||
426 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | ||
427 | { | ||
428 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
429 | .name = "Channel Mode", | ||
430 | .info = alc_ch_mode_info, | ||
431 | .get = alc_ch_mode_get, | ||
432 | .put = alc_ch_mode_put, | ||
433 | }, | ||
434 | { } /* end */ | ||
435 | }; | ||
436 | |||
437 | static const struct snd_kcontrol_new alc880_fujitsu_mixer[] = { | ||
438 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
439 | HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT), | ||
440 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
441 | HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT), | ||
442 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
443 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
444 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
445 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
446 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | ||
447 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | ||
448 | { } /* end */ | ||
449 | }; | ||
450 | |||
451 | static const struct snd_kcontrol_new alc880_uniwill_p53_mixer[] = { | ||
452 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
453 | HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT), | ||
454 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
455 | HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT), | ||
456 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
457 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
458 | { } /* end */ | ||
459 | }; | ||
460 | |||
461 | /* | ||
462 | * initialize the codec volumes, etc | ||
463 | */ | ||
464 | |||
465 | /* | ||
466 | * generic initialization of ADC, input mixers and output mixers | ||
467 | */ | ||
468 | static const struct hda_verb alc880_volume_init_verbs[] = { | ||
469 | /* | ||
470 | * Unmute ADC0-2 and set the default input to mic-in | ||
471 | */ | ||
472 | {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
473 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
474 | {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
475 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
476 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
477 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
478 | |||
479 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | ||
480 | * mixer widget | ||
481 | * Note: PASD motherboards uses the Line In 2 as the input for front | ||
482 | * panel mic (mic 2) | ||
483 | */ | ||
484 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | ||
485 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
486 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
487 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
488 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
489 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
490 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, | ||
491 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, | ||
492 | |||
493 | /* | ||
494 | * Set up output mixers (0x0c - 0x0f) | ||
495 | */ | ||
496 | /* set vol=0 to output mixers */ | ||
497 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
498 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
499 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
500 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
501 | /* set up input amps for analog loopback */ | ||
502 | /* Amp Indices: DAC = 0, mixer = 1 */ | ||
503 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
504 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
505 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
506 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
507 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
508 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
509 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
510 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
511 | |||
512 | { } | ||
513 | }; | ||
514 | |||
515 | /* | ||
516 | * 3-stack pin configuration: | ||
517 | * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b | ||
518 | */ | ||
519 | static const struct hda_verb alc880_pin_3stack_init_verbs[] = { | ||
520 | /* | ||
521 | * preset connection lists of input pins | ||
522 | * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround | ||
523 | */ | ||
524 | {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */ | ||
525 | {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ | ||
526 | {0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */ | ||
527 | |||
528 | /* | ||
529 | * Set pin mode and muting | ||
530 | */ | ||
531 | /* set front pin widgets 0x14 for output */ | ||
532 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
533 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
534 | /* Mic1 (rear panel) pin widget for input and vref at 80% */ | ||
535 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
536 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
537 | /* Mic2 (as headphone out) for HP output */ | ||
538 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
539 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
540 | /* Line In pin widget for input */ | ||
541 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
542 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
543 | /* Line2 (as front mic) pin widget for input and vref at 80% */ | ||
544 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
545 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
546 | /* CD pin widget for input */ | ||
547 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
548 | |||
549 | { } | ||
550 | }; | ||
551 | |||
552 | /* | ||
553 | * 5-stack pin configuration: | ||
554 | * front = 0x14, surround = 0x17, clfe = 0x16, mic = 0x18, HP = 0x19, | ||
555 | * line-in/side = 0x1a, f-mic = 0x1b | ||
556 | */ | ||
557 | static const struct hda_verb alc880_pin_5stack_init_verbs[] = { | ||
558 | /* | ||
559 | * preset connection lists of input pins | ||
560 | * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround | ||
561 | */ | ||
562 | {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ | ||
563 | {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/side */ | ||
564 | |||
565 | /* | ||
566 | * Set pin mode and muting | ||
567 | */ | ||
568 | /* set pin widgets 0x14-0x17 for output */ | ||
569 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
570 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
571 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
572 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
573 | /* unmute pins for output (no gain on this amp) */ | ||
574 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
575 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
576 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
577 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
578 | |||
579 | /* Mic1 (rear panel) pin widget for input and vref at 80% */ | ||
580 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
581 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
582 | /* Mic2 (as headphone out) for HP output */ | ||
583 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
584 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
585 | /* Line In pin widget for input */ | ||
586 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
587 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
588 | /* Line2 (as front mic) pin widget for input and vref at 80% */ | ||
589 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
590 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
591 | /* CD pin widget for input */ | ||
592 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
593 | |||
594 | { } | ||
595 | }; | ||
596 | |||
597 | /* | ||
598 | * W810 pin configuration: | ||
599 | * front = 0x14, surround = 0x15, clfe = 0x16, HP = 0x1b | ||
600 | */ | ||
601 | static const struct hda_verb alc880_pin_w810_init_verbs[] = { | ||
602 | /* hphone/speaker input selector: front DAC */ | ||
603 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
604 | |||
605 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
606 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
607 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
608 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
609 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
610 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
611 | |||
612 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
613 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
614 | |||
615 | { } | ||
616 | }; | ||
617 | |||
618 | /* | ||
619 | * Z71V pin configuration: | ||
620 | * Speaker-out = 0x14, HP = 0x15, Mic = 0x18, Line-in = 0x1a, Mic2 = 0x1b (?) | ||
621 | */ | ||
622 | static const struct hda_verb alc880_pin_z71v_init_verbs[] = { | ||
623 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
624 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
625 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
626 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
627 | |||
628 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
629 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
630 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
631 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
632 | |||
633 | { } | ||
634 | }; | ||
635 | |||
636 | /* | ||
637 | * 6-stack pin configuration: | ||
638 | * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18, | ||
639 | * f-mic = 0x19, line = 0x1a, HP = 0x1b | ||
640 | */ | ||
641 | static const struct hda_verb alc880_pin_6stack_init_verbs[] = { | ||
642 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ | ||
643 | |||
644 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
645 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
646 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
647 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
648 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
649 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
650 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
651 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
652 | |||
653 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
654 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
655 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
656 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
657 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
658 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
659 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
660 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
661 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
662 | |||
663 | { } | ||
664 | }; | ||
665 | |||
666 | /* | ||
667 | * Uniwill pin configuration: | ||
668 | * HP = 0x14, InternalSpeaker = 0x15, mic = 0x18, internal mic = 0x19, | ||
669 | * line = 0x1a | ||
670 | */ | ||
671 | static const struct hda_verb alc880_uniwill_init_verbs[] = { | ||
672 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ | ||
673 | |||
674 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
675 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
676 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
677 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
678 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
679 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
680 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
681 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
682 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | ||
683 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | ||
684 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | ||
685 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | ||
686 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | ||
687 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | ||
688 | |||
689 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
690 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
691 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
692 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
693 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
694 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
695 | /* {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, */ | ||
696 | /* {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, */ | ||
697 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
698 | |||
699 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT}, | ||
700 | {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT}, | ||
701 | |||
702 | { } | ||
703 | }; | ||
704 | |||
705 | /* | ||
706 | * Uniwill P53 | ||
707 | * HP = 0x14, InternalSpeaker = 0x15, mic = 0x19, | ||
708 | */ | ||
709 | static const struct hda_verb alc880_uniwill_p53_init_verbs[] = { | ||
710 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ | ||
711 | |||
712 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
713 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
714 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
715 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
716 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
717 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
718 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | ||
719 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | ||
720 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | ||
721 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | ||
722 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | ||
723 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | ||
724 | |||
725 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
726 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
727 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
728 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
729 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
730 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
731 | |||
732 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT}, | ||
733 | {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_DCVOL_EVENT}, | ||
734 | |||
735 | { } | ||
736 | }; | ||
737 | |||
738 | static const struct hda_verb alc880_beep_init_verbs[] = { | ||
739 | { 0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5) }, | ||
740 | { } | ||
741 | }; | ||
742 | |||
743 | static void alc880_uniwill_setup(struct hda_codec *codec) | ||
744 | { | ||
745 | struct alc_spec *spec = codec->spec; | ||
746 | |||
747 | spec->autocfg.hp_pins[0] = 0x14; | ||
748 | spec->autocfg.speaker_pins[0] = 0x15; | ||
749 | spec->autocfg.speaker_pins[0] = 0x16; | ||
750 | alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP); | ||
751 | } | ||
752 | |||
753 | static void alc880_uniwill_init_hook(struct hda_codec *codec) | ||
754 | { | ||
755 | alc_hp_automute(codec); | ||
756 | alc88x_simple_mic_automute(codec); | ||
757 | } | ||
758 | |||
759 | static void alc880_uniwill_unsol_event(struct hda_codec *codec, | ||
760 | unsigned int res) | ||
761 | { | ||
762 | /* Looks like the unsol event is incompatible with the standard | ||
763 | * definition. 4bit tag is placed at 28 bit! | ||
764 | */ | ||
765 | res >>= 28; | ||
766 | switch (res) { | ||
767 | case ALC_MIC_EVENT: | ||
768 | alc88x_simple_mic_automute(codec); | ||
769 | break; | ||
770 | default: | ||
771 | alc_exec_unsol_event(codec, res); | ||
772 | break; | ||
773 | } | ||
774 | } | ||
775 | |||
776 | static void alc880_unsol_event(struct hda_codec *codec, unsigned int res) | ||
777 | { | ||
778 | alc_exec_unsol_event(codec, res >> 28); | ||
779 | } | ||
780 | |||
781 | static void alc880_uniwill_p53_setup(struct hda_codec *codec) | ||
782 | { | ||
783 | struct alc_spec *spec = codec->spec; | ||
784 | |||
785 | spec->autocfg.hp_pins[0] = 0x14; | ||
786 | spec->autocfg.speaker_pins[0] = 0x15; | ||
787 | alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP); | ||
788 | } | ||
789 | |||
790 | static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec) | ||
791 | { | ||
792 | unsigned int present; | ||
793 | |||
794 | present = snd_hda_codec_read(codec, 0x21, 0, | ||
795 | AC_VERB_GET_VOLUME_KNOB_CONTROL, 0); | ||
796 | present &= HDA_AMP_VOLMASK; | ||
797 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_OUTPUT, 0, | ||
798 | HDA_AMP_VOLMASK, present); | ||
799 | snd_hda_codec_amp_stereo(codec, 0x0d, HDA_OUTPUT, 0, | ||
800 | HDA_AMP_VOLMASK, present); | ||
801 | } | ||
802 | |||
803 | static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec, | ||
804 | unsigned int res) | ||
805 | { | ||
806 | /* Looks like the unsol event is incompatible with the standard | ||
807 | * definition. 4bit tag is placed at 28 bit! | ||
808 | */ | ||
809 | res >>= 28; | ||
810 | if (res == ALC_DCVOL_EVENT) | ||
811 | alc880_uniwill_p53_dcvol_automute(codec); | ||
812 | else | ||
813 | alc_exec_unsol_event(codec, res); | ||
814 | } | ||
815 | |||
816 | /* | ||
817 | * F1734 pin configuration: | ||
818 | * HP = 0x14, speaker-out = 0x15, mic = 0x18 | ||
819 | */ | ||
820 | static const struct hda_verb alc880_pin_f1734_init_verbs[] = { | ||
821 | {0x07, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
822 | {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, | ||
823 | {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
824 | {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
825 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
826 | |||
827 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
828 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
829 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
830 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
831 | |||
832 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
833 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
834 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50}, | ||
835 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
836 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
837 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
838 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
839 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
840 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
841 | |||
842 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC_HP_EVENT}, | ||
843 | {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC_DCVOL_EVENT}, | ||
844 | |||
845 | { } | ||
846 | }; | ||
847 | |||
848 | /* | ||
849 | * ASUS pin configuration: | ||
850 | * HP/front = 0x14, surr = 0x15, clfe = 0x16, mic = 0x18, line = 0x1a | ||
851 | */ | ||
852 | static const struct hda_verb alc880_pin_asus_init_verbs[] = { | ||
853 | {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, | ||
854 | {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
855 | {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
856 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
857 | |||
858 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
859 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
860 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
861 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
862 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
863 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
864 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
865 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
866 | |||
867 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
868 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
869 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
870 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
871 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
872 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
873 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
874 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
875 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
876 | |||
877 | { } | ||
878 | }; | ||
879 | |||
880 | /* Enable GPIO mask and set output */ | ||
881 | #define alc880_gpio1_init_verbs alc_gpio1_init_verbs | ||
882 | #define alc880_gpio2_init_verbs alc_gpio2_init_verbs | ||
883 | #define alc880_gpio3_init_verbs alc_gpio3_init_verbs | ||
884 | |||
885 | /* Clevo m520g init */ | ||
886 | static const struct hda_verb alc880_pin_clevo_init_verbs[] = { | ||
887 | /* headphone output */ | ||
888 | {0x11, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
889 | /* line-out */ | ||
890 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
891 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
892 | /* Line-in */ | ||
893 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
894 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
895 | /* CD */ | ||
896 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
897 | {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
898 | /* Mic1 (rear panel) */ | ||
899 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
900 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
901 | /* Mic2 (front panel) */ | ||
902 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
903 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
904 | /* headphone */ | ||
905 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
906 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
907 | /* change to EAPD mode */ | ||
908 | {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, | ||
909 | {0x20, AC_VERB_SET_PROC_COEF, 0x3060}, | ||
910 | |||
911 | { } | ||
912 | }; | ||
913 | |||
914 | static const struct hda_verb alc880_pin_tcl_S700_init_verbs[] = { | ||
915 | /* change to EAPD mode */ | ||
916 | {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, | ||
917 | {0x20, AC_VERB_SET_PROC_COEF, 0x3060}, | ||
918 | |||
919 | /* Headphone output */ | ||
920 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
921 | /* Front output*/ | ||
922 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
923 | {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
924 | |||
925 | /* Line In pin widget for input */ | ||
926 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
927 | /* CD pin widget for input */ | ||
928 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
929 | /* Mic1 (rear panel) pin widget for input and vref at 80% */ | ||
930 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
931 | |||
932 | /* change to EAPD mode */ | ||
933 | {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, | ||
934 | {0x20, AC_VERB_SET_PROC_COEF, 0x3070}, | ||
935 | |||
936 | { } | ||
937 | }; | ||
938 | |||
939 | /* | ||
940 | * LG m1 express dual | ||
941 | * | ||
942 | * Pin assignment: | ||
943 | * Rear Line-In/Out (blue): 0x14 | ||
944 | * Build-in Mic-In: 0x15 | ||
945 | * Speaker-out: 0x17 | ||
946 | * HP-Out (green): 0x1b | ||
947 | * Mic-In/Out (red): 0x19 | ||
948 | * SPDIF-Out: 0x1e | ||
949 | */ | ||
950 | |||
951 | /* To make 5.1 output working (green=Front, blue=Surr, red=CLFE) */ | ||
952 | static const hda_nid_t alc880_lg_dac_nids[3] = { | ||
953 | 0x05, 0x02, 0x03 | ||
954 | }; | ||
955 | |||
956 | /* seems analog CD is not working */ | ||
957 | static const struct hda_input_mux alc880_lg_capture_source = { | ||
958 | .num_items = 3, | ||
959 | .items = { | ||
960 | { "Mic", 0x1 }, | ||
961 | { "Line", 0x5 }, | ||
962 | { "Internal Mic", 0x6 }, | ||
963 | }, | ||
964 | }; | ||
965 | |||
966 | /* 2,4,6 channel modes */ | ||
967 | static const struct hda_verb alc880_lg_ch2_init[] = { | ||
968 | /* set line-in and mic-in to input */ | ||
969 | { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | ||
970 | { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, | ||
971 | { } | ||
972 | }; | ||
973 | |||
974 | static const struct hda_verb alc880_lg_ch4_init[] = { | ||
975 | /* set line-in to out and mic-in to input */ | ||
976 | { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
977 | { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, | ||
978 | { } | ||
979 | }; | ||
980 | |||
981 | static const struct hda_verb alc880_lg_ch6_init[] = { | ||
982 | /* set line-in and mic-in to output */ | ||
983 | { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
984 | { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
985 | { } | ||
986 | }; | ||
987 | |||
988 | static const struct hda_channel_mode alc880_lg_ch_modes[3] = { | ||
989 | { 2, alc880_lg_ch2_init }, | ||
990 | { 4, alc880_lg_ch4_init }, | ||
991 | { 6, alc880_lg_ch6_init }, | ||
992 | }; | ||
993 | |||
994 | static const struct snd_kcontrol_new alc880_lg_mixer[] = { | ||
995 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0f, 0x0, HDA_OUTPUT), | ||
996 | HDA_BIND_MUTE("Front Playback Switch", 0x0f, 2, HDA_INPUT), | ||
997 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
998 | HDA_BIND_MUTE("Surround Playback Switch", 0x0c, 2, HDA_INPUT), | ||
999 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT), | ||
1000 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT), | ||
1001 | HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT), | ||
1002 | HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT), | ||
1003 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | ||
1004 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | ||
1005 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x06, HDA_INPUT), | ||
1006 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x06, HDA_INPUT), | ||
1007 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x07, HDA_INPUT), | ||
1008 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x07, HDA_INPUT), | ||
1009 | { | ||
1010 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1011 | .name = "Channel Mode", | ||
1012 | .info = alc_ch_mode_info, | ||
1013 | .get = alc_ch_mode_get, | ||
1014 | .put = alc_ch_mode_put, | ||
1015 | }, | ||
1016 | { } /* end */ | ||
1017 | }; | ||
1018 | |||
1019 | static const struct hda_verb alc880_lg_init_verbs[] = { | ||
1020 | /* set capture source to mic-in */ | ||
1021 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
1022 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
1023 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
1024 | /* mute all amp mixer inputs */ | ||
1025 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)}, | ||
1026 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, | ||
1027 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, | ||
1028 | /* line-in to input */ | ||
1029 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
1030 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1031 | /* built-in mic */ | ||
1032 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1033 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1034 | /* speaker-out */ | ||
1035 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
1036 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1037 | /* mic-in to input */ | ||
1038 | {0x11, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
1039 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1040 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1041 | /* HP-out */ | ||
1042 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x03}, | ||
1043 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
1044 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1045 | /* jack sense */ | ||
1046 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT}, | ||
1047 | { } | ||
1048 | }; | ||
1049 | |||
1050 | /* toggle speaker-output according to the hp-jack state */ | ||
1051 | static void alc880_lg_setup(struct hda_codec *codec) | ||
1052 | { | ||
1053 | struct alc_spec *spec = codec->spec; | ||
1054 | |||
1055 | spec->autocfg.hp_pins[0] = 0x1b; | ||
1056 | spec->autocfg.speaker_pins[0] = 0x17; | ||
1057 | alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP); | ||
1058 | } | ||
1059 | |||
1060 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1061 | static const struct hda_amp_list alc880_lg_loopbacks[] = { | ||
1062 | { 0x0b, HDA_INPUT, 1 }, | ||
1063 | { 0x0b, HDA_INPUT, 6 }, | ||
1064 | { 0x0b, HDA_INPUT, 7 }, | ||
1065 | { } /* end */ | ||
1066 | }; | ||
1067 | #endif | ||
1068 | |||
1069 | /* | ||
1070 | * Test configuration for debugging | ||
1071 | * | ||
1072 | * Almost all inputs/outputs are enabled. I/O pins can be configured via | ||
1073 | * enum controls. | ||
1074 | */ | ||
1075 | #ifdef CONFIG_SND_DEBUG | ||
1076 | static const hda_nid_t alc880_test_dac_nids[4] = { | ||
1077 | 0x02, 0x03, 0x04, 0x05 | ||
1078 | }; | ||
1079 | |||
1080 | static const struct hda_input_mux alc880_test_capture_source = { | ||
1081 | .num_items = 7, | ||
1082 | .items = { | ||
1083 | { "In-1", 0x0 }, | ||
1084 | { "In-2", 0x1 }, | ||
1085 | { "In-3", 0x2 }, | ||
1086 | { "In-4", 0x3 }, | ||
1087 | { "CD", 0x4 }, | ||
1088 | { "Front", 0x5 }, | ||
1089 | { "Surround", 0x6 }, | ||
1090 | }, | ||
1091 | }; | ||
1092 | |||
1093 | static const struct hda_channel_mode alc880_test_modes[4] = { | ||
1094 | { 2, NULL }, | ||
1095 | { 4, NULL }, | ||
1096 | { 6, NULL }, | ||
1097 | { 8, NULL }, | ||
1098 | }; | ||
1099 | |||
1100 | static int alc_test_pin_ctl_info(struct snd_kcontrol *kcontrol, | ||
1101 | struct snd_ctl_elem_info *uinfo) | ||
1102 | { | ||
1103 | static const char * const texts[] = { | ||
1104 | "N/A", "Line Out", "HP Out", | ||
1105 | "In Hi-Z", "In 50%", "In Grd", "In 80%", "In 100%" | ||
1106 | }; | ||
1107 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
1108 | uinfo->count = 1; | ||
1109 | uinfo->value.enumerated.items = 8; | ||
1110 | if (uinfo->value.enumerated.item >= 8) | ||
1111 | uinfo->value.enumerated.item = 7; | ||
1112 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | ||
1113 | return 0; | ||
1114 | } | ||
1115 | |||
1116 | static int alc_test_pin_ctl_get(struct snd_kcontrol *kcontrol, | ||
1117 | struct snd_ctl_elem_value *ucontrol) | ||
1118 | { | ||
1119 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1120 | hda_nid_t nid = (hda_nid_t)kcontrol->private_value; | ||
1121 | unsigned int pin_ctl, item = 0; | ||
1122 | |||
1123 | pin_ctl = snd_hda_codec_read(codec, nid, 0, | ||
1124 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
1125 | if (pin_ctl & AC_PINCTL_OUT_EN) { | ||
1126 | if (pin_ctl & AC_PINCTL_HP_EN) | ||
1127 | item = 2; | ||
1128 | else | ||
1129 | item = 1; | ||
1130 | } else if (pin_ctl & AC_PINCTL_IN_EN) { | ||
1131 | switch (pin_ctl & AC_PINCTL_VREFEN) { | ||
1132 | case AC_PINCTL_VREF_HIZ: item = 3; break; | ||
1133 | case AC_PINCTL_VREF_50: item = 4; break; | ||
1134 | case AC_PINCTL_VREF_GRD: item = 5; break; | ||
1135 | case AC_PINCTL_VREF_80: item = 6; break; | ||
1136 | case AC_PINCTL_VREF_100: item = 7; break; | ||
1137 | } | ||
1138 | } | ||
1139 | ucontrol->value.enumerated.item[0] = item; | ||
1140 | return 0; | ||
1141 | } | ||
1142 | |||
1143 | static int alc_test_pin_ctl_put(struct snd_kcontrol *kcontrol, | ||
1144 | struct snd_ctl_elem_value *ucontrol) | ||
1145 | { | ||
1146 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1147 | hda_nid_t nid = (hda_nid_t)kcontrol->private_value; | ||
1148 | static const unsigned int ctls[] = { | ||
1149 | 0, AC_PINCTL_OUT_EN, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN, | ||
1150 | AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ, | ||
1151 | AC_PINCTL_IN_EN | AC_PINCTL_VREF_50, | ||
1152 | AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD, | ||
1153 | AC_PINCTL_IN_EN | AC_PINCTL_VREF_80, | ||
1154 | AC_PINCTL_IN_EN | AC_PINCTL_VREF_100, | ||
1155 | }; | ||
1156 | unsigned int old_ctl, new_ctl; | ||
1157 | |||
1158 | old_ctl = snd_hda_codec_read(codec, nid, 0, | ||
1159 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
1160 | new_ctl = ctls[ucontrol->value.enumerated.item[0]]; | ||
1161 | if (old_ctl != new_ctl) { | ||
1162 | int val; | ||
1163 | snd_hda_codec_write_cache(codec, nid, 0, | ||
1164 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
1165 | new_ctl); | ||
1166 | val = ucontrol->value.enumerated.item[0] >= 3 ? | ||
1167 | HDA_AMP_MUTE : 0; | ||
1168 | snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, | ||
1169 | HDA_AMP_MUTE, val); | ||
1170 | return 1; | ||
1171 | } | ||
1172 | return 0; | ||
1173 | } | ||
1174 | |||
1175 | static int alc_test_pin_src_info(struct snd_kcontrol *kcontrol, | ||
1176 | struct snd_ctl_elem_info *uinfo) | ||
1177 | { | ||
1178 | static const char * const texts[] = { | ||
1179 | "Front", "Surround", "CLFE", "Side" | ||
1180 | }; | ||
1181 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
1182 | uinfo->count = 1; | ||
1183 | uinfo->value.enumerated.items = 4; | ||
1184 | if (uinfo->value.enumerated.item >= 4) | ||
1185 | uinfo->value.enumerated.item = 3; | ||
1186 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | ||
1187 | return 0; | ||
1188 | } | ||
1189 | |||
1190 | static int alc_test_pin_src_get(struct snd_kcontrol *kcontrol, | ||
1191 | struct snd_ctl_elem_value *ucontrol) | ||
1192 | { | ||
1193 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1194 | hda_nid_t nid = (hda_nid_t)kcontrol->private_value; | ||
1195 | unsigned int sel; | ||
1196 | |||
1197 | sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0); | ||
1198 | ucontrol->value.enumerated.item[0] = sel & 3; | ||
1199 | return 0; | ||
1200 | } | ||
1201 | |||
1202 | static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol, | ||
1203 | struct snd_ctl_elem_value *ucontrol) | ||
1204 | { | ||
1205 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1206 | hda_nid_t nid = (hda_nid_t)kcontrol->private_value; | ||
1207 | unsigned int sel; | ||
1208 | |||
1209 | sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3; | ||
1210 | if (ucontrol->value.enumerated.item[0] != sel) { | ||
1211 | sel = ucontrol->value.enumerated.item[0] & 3; | ||
1212 | snd_hda_codec_write_cache(codec, nid, 0, | ||
1213 | AC_VERB_SET_CONNECT_SEL, sel); | ||
1214 | return 1; | ||
1215 | } | ||
1216 | return 0; | ||
1217 | } | ||
1218 | |||
1219 | #define PIN_CTL_TEST(xname,nid) { \ | ||
1220 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
1221 | .name = xname, \ | ||
1222 | .subdevice = HDA_SUBDEV_NID_FLAG | nid, \ | ||
1223 | .info = alc_test_pin_ctl_info, \ | ||
1224 | .get = alc_test_pin_ctl_get, \ | ||
1225 | .put = alc_test_pin_ctl_put, \ | ||
1226 | .private_value = nid \ | ||
1227 | } | ||
1228 | |||
1229 | #define PIN_SRC_TEST(xname,nid) { \ | ||
1230 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
1231 | .name = xname, \ | ||
1232 | .subdevice = HDA_SUBDEV_NID_FLAG | nid, \ | ||
1233 | .info = alc_test_pin_src_info, \ | ||
1234 | .get = alc_test_pin_src_get, \ | ||
1235 | .put = alc_test_pin_src_put, \ | ||
1236 | .private_value = nid \ | ||
1237 | } | ||
1238 | |||
1239 | static const struct snd_kcontrol_new alc880_test_mixer[] = { | ||
1240 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
1241 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
1242 | HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT), | ||
1243 | HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), | ||
1244 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | ||
1245 | HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), | ||
1246 | HDA_BIND_MUTE("CLFE Playback Switch", 0x0e, 2, HDA_INPUT), | ||
1247 | HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), | ||
1248 | PIN_CTL_TEST("Front Pin Mode", 0x14), | ||
1249 | PIN_CTL_TEST("Surround Pin Mode", 0x15), | ||
1250 | PIN_CTL_TEST("CLFE Pin Mode", 0x16), | ||
1251 | PIN_CTL_TEST("Side Pin Mode", 0x17), | ||
1252 | PIN_CTL_TEST("In-1 Pin Mode", 0x18), | ||
1253 | PIN_CTL_TEST("In-2 Pin Mode", 0x19), | ||
1254 | PIN_CTL_TEST("In-3 Pin Mode", 0x1a), | ||
1255 | PIN_CTL_TEST("In-4 Pin Mode", 0x1b), | ||
1256 | PIN_SRC_TEST("In-1 Pin Source", 0x18), | ||
1257 | PIN_SRC_TEST("In-2 Pin Source", 0x19), | ||
1258 | PIN_SRC_TEST("In-3 Pin Source", 0x1a), | ||
1259 | PIN_SRC_TEST("In-4 Pin Source", 0x1b), | ||
1260 | HDA_CODEC_VOLUME("In-1 Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
1261 | HDA_CODEC_MUTE("In-1 Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
1262 | HDA_CODEC_VOLUME("In-2 Playback Volume", 0x0b, 0x1, HDA_INPUT), | ||
1263 | HDA_CODEC_MUTE("In-2 Playback Switch", 0x0b, 0x1, HDA_INPUT), | ||
1264 | HDA_CODEC_VOLUME("In-3 Playback Volume", 0x0b, 0x2, HDA_INPUT), | ||
1265 | HDA_CODEC_MUTE("In-3 Playback Switch", 0x0b, 0x2, HDA_INPUT), | ||
1266 | HDA_CODEC_VOLUME("In-4 Playback Volume", 0x0b, 0x3, HDA_INPUT), | ||
1267 | HDA_CODEC_MUTE("In-4 Playback Switch", 0x0b, 0x3, HDA_INPUT), | ||
1268 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x4, HDA_INPUT), | ||
1269 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x4, HDA_INPUT), | ||
1270 | { | ||
1271 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1272 | .name = "Channel Mode", | ||
1273 | .info = alc_ch_mode_info, | ||
1274 | .get = alc_ch_mode_get, | ||
1275 | .put = alc_ch_mode_put, | ||
1276 | }, | ||
1277 | { } /* end */ | ||
1278 | }; | ||
1279 | |||
1280 | static const struct hda_verb alc880_test_init_verbs[] = { | ||
1281 | /* Unmute inputs of 0x0c - 0x0f */ | ||
1282 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
1283 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
1284 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
1285 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
1286 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
1287 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
1288 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
1289 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
1290 | /* Vol output for 0x0c-0x0f */ | ||
1291 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
1292 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
1293 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
1294 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
1295 | /* Set output pins 0x14-0x17 */ | ||
1296 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1297 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1298 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1299 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1300 | /* Unmute output pins 0x14-0x17 */ | ||
1301 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1302 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1303 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1304 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1305 | /* Set input pins 0x18-0x1c */ | ||
1306 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1307 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1308 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
1309 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
1310 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
1311 | /* Mute input pins 0x18-0x1b */ | ||
1312 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
1313 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
1314 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
1315 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
1316 | /* ADC set up */ | ||
1317 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
1318 | {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1319 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
1320 | {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1321 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
1322 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1323 | /* Analog input/passthru */ | ||
1324 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
1325 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
1326 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
1327 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
1328 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
1329 | { } | ||
1330 | }; | ||
1331 | #endif | ||
1332 | |||
1333 | /* | ||
1334 | */ | ||
1335 | |||
1336 | static const char * const alc880_models[ALC880_MODEL_LAST] = { | ||
1337 | [ALC880_3ST] = "3stack", | ||
1338 | [ALC880_TCL_S700] = "tcl", | ||
1339 | [ALC880_3ST_DIG] = "3stack-digout", | ||
1340 | [ALC880_CLEVO] = "clevo", | ||
1341 | [ALC880_5ST] = "5stack", | ||
1342 | [ALC880_5ST_DIG] = "5stack-digout", | ||
1343 | [ALC880_W810] = "w810", | ||
1344 | [ALC880_Z71V] = "z71v", | ||
1345 | [ALC880_6ST] = "6stack", | ||
1346 | [ALC880_6ST_DIG] = "6stack-digout", | ||
1347 | [ALC880_ASUS] = "asus", | ||
1348 | [ALC880_ASUS_W1V] = "asus-w1v", | ||
1349 | [ALC880_ASUS_DIG] = "asus-dig", | ||
1350 | [ALC880_ASUS_DIG2] = "asus-dig2", | ||
1351 | [ALC880_UNIWILL_DIG] = "uniwill", | ||
1352 | [ALC880_UNIWILL_P53] = "uniwill-p53", | ||
1353 | [ALC880_FUJITSU] = "fujitsu", | ||
1354 | [ALC880_F1734] = "F1734", | ||
1355 | [ALC880_LG] = "lg", | ||
1356 | #ifdef CONFIG_SND_DEBUG | ||
1357 | [ALC880_TEST] = "test", | ||
1358 | #endif | ||
1359 | [ALC880_AUTO] = "auto", | ||
1360 | }; | ||
1361 | |||
1362 | static const struct snd_pci_quirk alc880_cfg_tbl[] = { | ||
1363 | SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_W810), | ||
1364 | SND_PCI_QUIRK(0x1019, 0xa880, "ECS", ALC880_5ST_DIG), | ||
1365 | SND_PCI_QUIRK(0x1019, 0xa884, "Acer APFV", ALC880_6ST), | ||
1366 | SND_PCI_QUIRK(0x1025, 0x0070, "ULI", ALC880_3ST_DIG), | ||
1367 | SND_PCI_QUIRK(0x1025, 0x0077, "ULI", ALC880_6ST_DIG), | ||
1368 | SND_PCI_QUIRK(0x1025, 0x0078, "ULI", ALC880_6ST_DIG), | ||
1369 | SND_PCI_QUIRK(0x1025, 0x0087, "ULI", ALC880_6ST_DIG), | ||
1370 | SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_3ST_DIG), | ||
1371 | SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_3ST), | ||
1372 | SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_6ST_DIG), | ||
1373 | SND_PCI_QUIRK(0x1043, 0x10b3, "ASUS W1V", ALC880_ASUS_W1V), | ||
1374 | SND_PCI_QUIRK(0x1043, 0x10c2, "ASUS W6A", ALC880_ASUS_DIG), | ||
1375 | SND_PCI_QUIRK(0x1043, 0x10c3, "ASUS Wxx", ALC880_ASUS_DIG), | ||
1376 | SND_PCI_QUIRK(0x1043, 0x1113, "ASUS", ALC880_ASUS_DIG), | ||
1377 | SND_PCI_QUIRK(0x1043, 0x1123, "ASUS", ALC880_ASUS_DIG), | ||
1378 | SND_PCI_QUIRK(0x1043, 0x1173, "ASUS", ALC880_ASUS_DIG), | ||
1379 | SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_Z71V), | ||
1380 | /* SND_PCI_QUIRK(0x1043, 0x1964, "ASUS", ALC880_ASUS_DIG), */ | ||
1381 | SND_PCI_QUIRK(0x1043, 0x1973, "ASUS", ALC880_ASUS_DIG), | ||
1382 | SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS", ALC880_ASUS_DIG), | ||
1383 | SND_PCI_QUIRK(0x1043, 0x814e, "ASUS P5GD1 w/SPDIF", ALC880_6ST_DIG), | ||
1384 | SND_PCI_QUIRK(0x1043, 0x8181, "ASUS P4GPL", ALC880_ASUS_DIG), | ||
1385 | SND_PCI_QUIRK(0x1043, 0x8196, "ASUS P5GD1", ALC880_6ST), | ||
1386 | SND_PCI_QUIRK(0x1043, 0x81b4, "ASUS", ALC880_6ST), | ||
1387 | SND_PCI_QUIRK_VENDOR(0x1043, "ASUS", ALC880_ASUS), /* default ASUS */ | ||
1388 | SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_3ST), | ||
1389 | SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_3ST), | ||
1390 | SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_5ST), | ||
1391 | SND_PCI_QUIRK(0x107b, 0x3033, "Gateway", ALC880_5ST), | ||
1392 | SND_PCI_QUIRK(0x107b, 0x4039, "Gateway", ALC880_5ST), | ||
1393 | SND_PCI_QUIRK(0x1297, 0xc790, "Shuttle ST20G5", ALC880_6ST_DIG), | ||
1394 | SND_PCI_QUIRK(0x1458, 0xa102, "Gigabyte K8", ALC880_6ST_DIG), | ||
1395 | SND_PCI_QUIRK(0x1462, 0x1150, "MSI", ALC880_6ST_DIG), | ||
1396 | SND_PCI_QUIRK(0x1509, 0x925d, "FIC P4M", ALC880_6ST_DIG), | ||
1397 | SND_PCI_QUIRK(0x1558, 0x0520, "Clevo m520G", ALC880_CLEVO), | ||
1398 | SND_PCI_QUIRK(0x1558, 0x0660, "Clevo m655n", ALC880_CLEVO), | ||
1399 | SND_PCI_QUIRK(0x1558, 0x5401, "ASUS", ALC880_ASUS_DIG2), | ||
1400 | SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_5ST_DIG), | ||
1401 | SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_UNIWILL_DIG), | ||
1402 | SND_PCI_QUIRK(0x1584, 0x9054, "Uniwill", ALC880_F1734), | ||
1403 | SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_UNIWILL), | ||
1404 | SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_UNIWILL_P53), | ||
1405 | SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_W810), | ||
1406 | SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_5ST_DIG), | ||
1407 | SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_5ST_DIG), | ||
1408 | SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_F1734), | ||
1409 | SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FUJITSU), | ||
1410 | SND_PCI_QUIRK(0x1734, 0x10ac, "FSC AMILO Xi 1526", ALC880_F1734), | ||
1411 | SND_PCI_QUIRK(0x1734, 0x10b0, "Fujitsu", ALC880_FUJITSU), | ||
1412 | SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_LG), | ||
1413 | SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_LG), | ||
1414 | SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_LG), | ||
1415 | SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_TCL_S700), | ||
1416 | SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_6ST_DIG), /* broken BIOS */ | ||
1417 | SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_6ST_DIG), | ||
1418 | SND_PCI_QUIRK(0x8086, 0xa100, "Intel mobo", ALC880_5ST_DIG), | ||
1419 | SND_PCI_QUIRK(0x8086, 0xd400, "Intel mobo", ALC880_5ST_DIG), | ||
1420 | SND_PCI_QUIRK(0x8086, 0xd401, "Intel mobo", ALC880_5ST_DIG), | ||
1421 | SND_PCI_QUIRK(0x8086, 0xd402, "Intel mobo", ALC880_3ST_DIG), | ||
1422 | SND_PCI_QUIRK(0x8086, 0xe224, "Intel mobo", ALC880_5ST_DIG), | ||
1423 | SND_PCI_QUIRK(0x8086, 0xe305, "Intel mobo", ALC880_3ST_DIG), | ||
1424 | SND_PCI_QUIRK(0x8086, 0xe308, "Intel mobo", ALC880_3ST_DIG), | ||
1425 | SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_5ST_DIG), | ||
1426 | SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_5ST_DIG), | ||
1427 | SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_5ST_DIG), | ||
1428 | /* default Intel */ | ||
1429 | SND_PCI_QUIRK_VENDOR(0x8086, "Intel mobo", ALC880_3ST), | ||
1430 | SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_5ST_DIG), | ||
1431 | SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_6ST_DIG), | ||
1432 | {} | ||
1433 | }; | ||
1434 | |||
1435 | /* | ||
1436 | * ALC880 codec presets | ||
1437 | */ | ||
1438 | static const struct alc_config_preset alc880_presets[] = { | ||
1439 | [ALC880_3ST] = { | ||
1440 | .mixers = { alc880_three_stack_mixer }, | ||
1441 | .init_verbs = { alc880_volume_init_verbs, | ||
1442 | alc880_pin_3stack_init_verbs }, | ||
1443 | .num_dacs = ARRAY_SIZE(alc880_dac_nids), | ||
1444 | .dac_nids = alc880_dac_nids, | ||
1445 | .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), | ||
1446 | .channel_mode = alc880_threestack_modes, | ||
1447 | .need_dac_fix = 1, | ||
1448 | .input_mux = &alc880_capture_source, | ||
1449 | }, | ||
1450 | [ALC880_3ST_DIG] = { | ||
1451 | .mixers = { alc880_three_stack_mixer }, | ||
1452 | .init_verbs = { alc880_volume_init_verbs, | ||
1453 | alc880_pin_3stack_init_verbs }, | ||
1454 | .num_dacs = ARRAY_SIZE(alc880_dac_nids), | ||
1455 | .dac_nids = alc880_dac_nids, | ||
1456 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1457 | .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), | ||
1458 | .channel_mode = alc880_threestack_modes, | ||
1459 | .need_dac_fix = 1, | ||
1460 | .input_mux = &alc880_capture_source, | ||
1461 | }, | ||
1462 | [ALC880_TCL_S700] = { | ||
1463 | .mixers = { alc880_tcl_s700_mixer }, | ||
1464 | .init_verbs = { alc880_volume_init_verbs, | ||
1465 | alc880_pin_tcl_S700_init_verbs, | ||
1466 | alc880_gpio2_init_verbs }, | ||
1467 | .num_dacs = ARRAY_SIZE(alc880_dac_nids), | ||
1468 | .dac_nids = alc880_dac_nids, | ||
1469 | .adc_nids = alc880_adc_nids_alt, /* FIXME: correct? */ | ||
1470 | .num_adc_nids = 1, /* single ADC */ | ||
1471 | .hp_nid = 0x03, | ||
1472 | .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), | ||
1473 | .channel_mode = alc880_2_jack_modes, | ||
1474 | .input_mux = &alc880_capture_source, | ||
1475 | }, | ||
1476 | [ALC880_5ST] = { | ||
1477 | .mixers = { alc880_three_stack_mixer, | ||
1478 | alc880_five_stack_mixer}, | ||
1479 | .init_verbs = { alc880_volume_init_verbs, | ||
1480 | alc880_pin_5stack_init_verbs }, | ||
1481 | .num_dacs = ARRAY_SIZE(alc880_dac_nids), | ||
1482 | .dac_nids = alc880_dac_nids, | ||
1483 | .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes), | ||
1484 | .channel_mode = alc880_fivestack_modes, | ||
1485 | .input_mux = &alc880_capture_source, | ||
1486 | }, | ||
1487 | [ALC880_5ST_DIG] = { | ||
1488 | .mixers = { alc880_three_stack_mixer, | ||
1489 | alc880_five_stack_mixer }, | ||
1490 | .init_verbs = { alc880_volume_init_verbs, | ||
1491 | alc880_pin_5stack_init_verbs }, | ||
1492 | .num_dacs = ARRAY_SIZE(alc880_dac_nids), | ||
1493 | .dac_nids = alc880_dac_nids, | ||
1494 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1495 | .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes), | ||
1496 | .channel_mode = alc880_fivestack_modes, | ||
1497 | .input_mux = &alc880_capture_source, | ||
1498 | }, | ||
1499 | [ALC880_6ST] = { | ||
1500 | .mixers = { alc880_six_stack_mixer }, | ||
1501 | .init_verbs = { alc880_volume_init_verbs, | ||
1502 | alc880_pin_6stack_init_verbs }, | ||
1503 | .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids), | ||
1504 | .dac_nids = alc880_6st_dac_nids, | ||
1505 | .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes), | ||
1506 | .channel_mode = alc880_sixstack_modes, | ||
1507 | .input_mux = &alc880_6stack_capture_source, | ||
1508 | }, | ||
1509 | [ALC880_6ST_DIG] = { | ||
1510 | .mixers = { alc880_six_stack_mixer }, | ||
1511 | .init_verbs = { alc880_volume_init_verbs, | ||
1512 | alc880_pin_6stack_init_verbs }, | ||
1513 | .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids), | ||
1514 | .dac_nids = alc880_6st_dac_nids, | ||
1515 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1516 | .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes), | ||
1517 | .channel_mode = alc880_sixstack_modes, | ||
1518 | .input_mux = &alc880_6stack_capture_source, | ||
1519 | }, | ||
1520 | [ALC880_W810] = { | ||
1521 | .mixers = { alc880_w810_base_mixer }, | ||
1522 | .init_verbs = { alc880_volume_init_verbs, | ||
1523 | alc880_pin_w810_init_verbs, | ||
1524 | alc880_gpio2_init_verbs }, | ||
1525 | .num_dacs = ARRAY_SIZE(alc880_w810_dac_nids), | ||
1526 | .dac_nids = alc880_w810_dac_nids, | ||
1527 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1528 | .num_channel_mode = ARRAY_SIZE(alc880_w810_modes), | ||
1529 | .channel_mode = alc880_w810_modes, | ||
1530 | .input_mux = &alc880_capture_source, | ||
1531 | }, | ||
1532 | [ALC880_Z71V] = { | ||
1533 | .mixers = { alc880_z71v_mixer }, | ||
1534 | .init_verbs = { alc880_volume_init_verbs, | ||
1535 | alc880_pin_z71v_init_verbs }, | ||
1536 | .num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids), | ||
1537 | .dac_nids = alc880_z71v_dac_nids, | ||
1538 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1539 | .hp_nid = 0x03, | ||
1540 | .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), | ||
1541 | .channel_mode = alc880_2_jack_modes, | ||
1542 | .input_mux = &alc880_capture_source, | ||
1543 | }, | ||
1544 | [ALC880_F1734] = { | ||
1545 | .mixers = { alc880_f1734_mixer }, | ||
1546 | .init_verbs = { alc880_volume_init_verbs, | ||
1547 | alc880_pin_f1734_init_verbs }, | ||
1548 | .num_dacs = ARRAY_SIZE(alc880_f1734_dac_nids), | ||
1549 | .dac_nids = alc880_f1734_dac_nids, | ||
1550 | .hp_nid = 0x02, | ||
1551 | .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), | ||
1552 | .channel_mode = alc880_2_jack_modes, | ||
1553 | .input_mux = &alc880_f1734_capture_source, | ||
1554 | .unsol_event = alc880_uniwill_p53_unsol_event, | ||
1555 | .setup = alc880_uniwill_p53_setup, | ||
1556 | .init_hook = alc_hp_automute, | ||
1557 | }, | ||
1558 | [ALC880_ASUS] = { | ||
1559 | .mixers = { alc880_asus_mixer }, | ||
1560 | .init_verbs = { alc880_volume_init_verbs, | ||
1561 | alc880_pin_asus_init_verbs, | ||
1562 | alc880_gpio1_init_verbs }, | ||
1563 | .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), | ||
1564 | .dac_nids = alc880_asus_dac_nids, | ||
1565 | .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), | ||
1566 | .channel_mode = alc880_asus_modes, | ||
1567 | .need_dac_fix = 1, | ||
1568 | .input_mux = &alc880_capture_source, | ||
1569 | }, | ||
1570 | [ALC880_ASUS_DIG] = { | ||
1571 | .mixers = { alc880_asus_mixer }, | ||
1572 | .init_verbs = { alc880_volume_init_verbs, | ||
1573 | alc880_pin_asus_init_verbs, | ||
1574 | alc880_gpio1_init_verbs }, | ||
1575 | .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), | ||
1576 | .dac_nids = alc880_asus_dac_nids, | ||
1577 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1578 | .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), | ||
1579 | .channel_mode = alc880_asus_modes, | ||
1580 | .need_dac_fix = 1, | ||
1581 | .input_mux = &alc880_capture_source, | ||
1582 | }, | ||
1583 | [ALC880_ASUS_DIG2] = { | ||
1584 | .mixers = { alc880_asus_mixer }, | ||
1585 | .init_verbs = { alc880_volume_init_verbs, | ||
1586 | alc880_pin_asus_init_verbs, | ||
1587 | alc880_gpio2_init_verbs }, /* use GPIO2 */ | ||
1588 | .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), | ||
1589 | .dac_nids = alc880_asus_dac_nids, | ||
1590 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1591 | .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), | ||
1592 | .channel_mode = alc880_asus_modes, | ||
1593 | .need_dac_fix = 1, | ||
1594 | .input_mux = &alc880_capture_source, | ||
1595 | }, | ||
1596 | [ALC880_ASUS_W1V] = { | ||
1597 | .mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer }, | ||
1598 | .init_verbs = { alc880_volume_init_verbs, | ||
1599 | alc880_pin_asus_init_verbs, | ||
1600 | alc880_gpio1_init_verbs }, | ||
1601 | .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), | ||
1602 | .dac_nids = alc880_asus_dac_nids, | ||
1603 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1604 | .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), | ||
1605 | .channel_mode = alc880_asus_modes, | ||
1606 | .need_dac_fix = 1, | ||
1607 | .input_mux = &alc880_capture_source, | ||
1608 | }, | ||
1609 | [ALC880_UNIWILL_DIG] = { | ||
1610 | .mixers = { alc880_asus_mixer }, | ||
1611 | .init_verbs = { alc880_volume_init_verbs, | ||
1612 | alc880_pin_asus_init_verbs }, | ||
1613 | .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), | ||
1614 | .dac_nids = alc880_asus_dac_nids, | ||
1615 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1616 | .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), | ||
1617 | .channel_mode = alc880_asus_modes, | ||
1618 | .need_dac_fix = 1, | ||
1619 | .input_mux = &alc880_capture_source, | ||
1620 | }, | ||
1621 | [ALC880_UNIWILL] = { | ||
1622 | .mixers = { alc880_uniwill_mixer }, | ||
1623 | .init_verbs = { alc880_volume_init_verbs, | ||
1624 | alc880_uniwill_init_verbs }, | ||
1625 | .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), | ||
1626 | .dac_nids = alc880_asus_dac_nids, | ||
1627 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1628 | .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), | ||
1629 | .channel_mode = alc880_threestack_modes, | ||
1630 | .need_dac_fix = 1, | ||
1631 | .input_mux = &alc880_capture_source, | ||
1632 | .unsol_event = alc880_uniwill_unsol_event, | ||
1633 | .setup = alc880_uniwill_setup, | ||
1634 | .init_hook = alc880_uniwill_init_hook, | ||
1635 | }, | ||
1636 | [ALC880_UNIWILL_P53] = { | ||
1637 | .mixers = { alc880_uniwill_p53_mixer }, | ||
1638 | .init_verbs = { alc880_volume_init_verbs, | ||
1639 | alc880_uniwill_p53_init_verbs }, | ||
1640 | .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), | ||
1641 | .dac_nids = alc880_asus_dac_nids, | ||
1642 | .num_channel_mode = ARRAY_SIZE(alc880_w810_modes), | ||
1643 | .channel_mode = alc880_threestack_modes, | ||
1644 | .input_mux = &alc880_capture_source, | ||
1645 | .unsol_event = alc880_uniwill_p53_unsol_event, | ||
1646 | .setup = alc880_uniwill_p53_setup, | ||
1647 | .init_hook = alc_hp_automute, | ||
1648 | }, | ||
1649 | [ALC880_FUJITSU] = { | ||
1650 | .mixers = { alc880_fujitsu_mixer }, | ||
1651 | .init_verbs = { alc880_volume_init_verbs, | ||
1652 | alc880_uniwill_p53_init_verbs, | ||
1653 | alc880_beep_init_verbs }, | ||
1654 | .num_dacs = ARRAY_SIZE(alc880_dac_nids), | ||
1655 | .dac_nids = alc880_dac_nids, | ||
1656 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1657 | .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), | ||
1658 | .channel_mode = alc880_2_jack_modes, | ||
1659 | .input_mux = &alc880_capture_source, | ||
1660 | .unsol_event = alc880_uniwill_p53_unsol_event, | ||
1661 | .setup = alc880_uniwill_p53_setup, | ||
1662 | .init_hook = alc_hp_automute, | ||
1663 | }, | ||
1664 | [ALC880_CLEVO] = { | ||
1665 | .mixers = { alc880_three_stack_mixer }, | ||
1666 | .init_verbs = { alc880_volume_init_verbs, | ||
1667 | alc880_pin_clevo_init_verbs }, | ||
1668 | .num_dacs = ARRAY_SIZE(alc880_dac_nids), | ||
1669 | .dac_nids = alc880_dac_nids, | ||
1670 | .hp_nid = 0x03, | ||
1671 | .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), | ||
1672 | .channel_mode = alc880_threestack_modes, | ||
1673 | .need_dac_fix = 1, | ||
1674 | .input_mux = &alc880_capture_source, | ||
1675 | }, | ||
1676 | [ALC880_LG] = { | ||
1677 | .mixers = { alc880_lg_mixer }, | ||
1678 | .init_verbs = { alc880_volume_init_verbs, | ||
1679 | alc880_lg_init_verbs }, | ||
1680 | .num_dacs = ARRAY_SIZE(alc880_lg_dac_nids), | ||
1681 | .dac_nids = alc880_lg_dac_nids, | ||
1682 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1683 | .num_channel_mode = ARRAY_SIZE(alc880_lg_ch_modes), | ||
1684 | .channel_mode = alc880_lg_ch_modes, | ||
1685 | .need_dac_fix = 1, | ||
1686 | .input_mux = &alc880_lg_capture_source, | ||
1687 | .unsol_event = alc880_unsol_event, | ||
1688 | .setup = alc880_lg_setup, | ||
1689 | .init_hook = alc_hp_automute, | ||
1690 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1691 | .loopbacks = alc880_lg_loopbacks, | ||
1692 | #endif | ||
1693 | }, | ||
1694 | #ifdef CONFIG_SND_DEBUG | ||
1695 | [ALC880_TEST] = { | ||
1696 | .mixers = { alc880_test_mixer }, | ||
1697 | .init_verbs = { alc880_test_init_verbs }, | ||
1698 | .num_dacs = ARRAY_SIZE(alc880_test_dac_nids), | ||
1699 | .dac_nids = alc880_test_dac_nids, | ||
1700 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1701 | .num_channel_mode = ARRAY_SIZE(alc880_test_modes), | ||
1702 | .channel_mode = alc880_test_modes, | ||
1703 | .input_mux = &alc880_test_capture_source, | ||
1704 | }, | ||
1705 | #endif | ||
1706 | }; | ||
1707 | |||
diff --git a/sound/pci/hda/alc882_quirks.c b/sound/pci/hda/alc882_quirks.c deleted file mode 100644 index bb364a53f546..000000000000 --- a/sound/pci/hda/alc882_quirks.c +++ /dev/null | |||
@@ -1,866 +0,0 @@ | |||
1 | /* | ||
2 | * ALC882/ALC883/ALC888/ALC889 quirk models | ||
3 | * included by patch_realtek.c | ||
4 | */ | ||
5 | |||
6 | /* ALC882 models */ | ||
7 | enum { | ||
8 | ALC882_AUTO, | ||
9 | ALC885_MBA21, | ||
10 | ALC885_MBP3, | ||
11 | ALC885_MB5, | ||
12 | ALC885_MACMINI3, | ||
13 | ALC885_IMAC91, | ||
14 | ALC889A_MB31, | ||
15 | ALC882_MODEL_LAST, | ||
16 | }; | ||
17 | |||
18 | #define ALC882_DIGOUT_NID 0x06 | ||
19 | #define ALC882_DIGIN_NID 0x0a | ||
20 | #define ALC883_DIGOUT_NID ALC882_DIGOUT_NID | ||
21 | #define ALC883_DIGIN_NID ALC882_DIGIN_NID | ||
22 | #define ALC1200_DIGOUT_NID 0x10 | ||
23 | |||
24 | |||
25 | static const struct hda_channel_mode alc882_ch_modes[1] = { | ||
26 | { 8, NULL } | ||
27 | }; | ||
28 | |||
29 | /* DACs */ | ||
30 | static const hda_nid_t alc882_dac_nids[4] = { | ||
31 | /* front, rear, clfe, rear_surr */ | ||
32 | 0x02, 0x03, 0x04, 0x05 | ||
33 | }; | ||
34 | #define alc883_dac_nids alc882_dac_nids | ||
35 | |||
36 | /* ADCs */ | ||
37 | #define alc882_adc_nids alc880_adc_nids | ||
38 | #define alc882_adc_nids_alt alc880_adc_nids_alt | ||
39 | #define alc883_adc_nids alc882_adc_nids_alt | ||
40 | |||
41 | static const hda_nid_t alc882_capsrc_nids_alt[2] = { 0x23, 0x22 }; | ||
42 | #define alc883_capsrc_nids alc882_capsrc_nids_alt | ||
43 | |||
44 | /* input MUX */ | ||
45 | /* FIXME: should be a matrix-type input source selection */ | ||
46 | |||
47 | static const struct hda_input_mux alc882_capture_source = { | ||
48 | .num_items = 4, | ||
49 | .items = { | ||
50 | { "Mic", 0x0 }, | ||
51 | { "Front Mic", 0x1 }, | ||
52 | { "Line", 0x2 }, | ||
53 | { "CD", 0x4 }, | ||
54 | }, | ||
55 | }; | ||
56 | |||
57 | #define alc883_capture_source alc882_capture_source | ||
58 | |||
59 | static const struct hda_input_mux mb5_capture_source = { | ||
60 | .num_items = 3, | ||
61 | .items = { | ||
62 | { "Mic", 0x1 }, | ||
63 | { "Line", 0x7 }, | ||
64 | { "CD", 0x4 }, | ||
65 | }, | ||
66 | }; | ||
67 | |||
68 | static const struct hda_input_mux macmini3_capture_source = { | ||
69 | .num_items = 2, | ||
70 | .items = { | ||
71 | { "Line", 0x2 }, | ||
72 | { "CD", 0x4 }, | ||
73 | }, | ||
74 | }; | ||
75 | |||
76 | static const struct hda_input_mux alc883_3stack_6ch_intel = { | ||
77 | .num_items = 4, | ||
78 | .items = { | ||
79 | { "Mic", 0x1 }, | ||
80 | { "Front Mic", 0x0 }, | ||
81 | { "Line", 0x2 }, | ||
82 | { "CD", 0x4 }, | ||
83 | }, | ||
84 | }; | ||
85 | |||
86 | static const struct hda_input_mux alc889A_mb31_capture_source = { | ||
87 | .num_items = 2, | ||
88 | .items = { | ||
89 | { "Mic", 0x0 }, | ||
90 | /* Front Mic (0x01) unused */ | ||
91 | { "Line", 0x2 }, | ||
92 | /* Line 2 (0x03) unused */ | ||
93 | /* CD (0x04) unused? */ | ||
94 | }, | ||
95 | }; | ||
96 | |||
97 | static const struct hda_input_mux alc889A_imac91_capture_source = { | ||
98 | .num_items = 2, | ||
99 | .items = { | ||
100 | { "Mic", 0x01 }, | ||
101 | { "Line", 0x2 }, /* Not sure! */ | ||
102 | }, | ||
103 | }; | ||
104 | |||
105 | /* Macbook Air 2,1 */ | ||
106 | |||
107 | static const struct hda_channel_mode alc885_mba21_ch_modes[1] = { | ||
108 | { 2, NULL }, | ||
109 | }; | ||
110 | |||
111 | /* | ||
112 | * macbook pro ALC885 can switch LineIn to LineOut without losing Mic | ||
113 | */ | ||
114 | |||
115 | /* | ||
116 | * 2ch mode | ||
117 | */ | ||
118 | static const struct hda_verb alc885_mbp_ch2_init[] = { | ||
119 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | ||
120 | { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
121 | { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
122 | { } /* end */ | ||
123 | }; | ||
124 | |||
125 | /* | ||
126 | * 4ch mode | ||
127 | */ | ||
128 | static const struct hda_verb alc885_mbp_ch4_init[] = { | ||
129 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
130 | { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
131 | { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 }, | ||
132 | { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
133 | { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
134 | { } /* end */ | ||
135 | }; | ||
136 | |||
137 | static const struct hda_channel_mode alc885_mbp_4ch_modes[2] = { | ||
138 | { 2, alc885_mbp_ch2_init }, | ||
139 | { 4, alc885_mbp_ch4_init }, | ||
140 | }; | ||
141 | |||
142 | /* | ||
143 | * 2ch | ||
144 | * Speakers/Woofer/HP = Front | ||
145 | * LineIn = Input | ||
146 | */ | ||
147 | static const struct hda_verb alc885_mb5_ch2_init[] = { | ||
148 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
149 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
150 | { } /* end */ | ||
151 | }; | ||
152 | |||
153 | /* | ||
154 | * 6ch mode | ||
155 | * Speakers/HP = Front | ||
156 | * Woofer = LFE | ||
157 | * LineIn = Surround | ||
158 | */ | ||
159 | static const struct hda_verb alc885_mb5_ch6_init[] = { | ||
160 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
161 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
162 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
163 | { } /* end */ | ||
164 | }; | ||
165 | |||
166 | static const struct hda_channel_mode alc885_mb5_6ch_modes[2] = { | ||
167 | { 2, alc885_mb5_ch2_init }, | ||
168 | { 6, alc885_mb5_ch6_init }, | ||
169 | }; | ||
170 | |||
171 | #define alc885_macmini3_6ch_modes alc885_mb5_6ch_modes | ||
172 | |||
173 | /* Macbook Air 2,1 same control for HP and internal Speaker */ | ||
174 | |||
175 | static const struct snd_kcontrol_new alc885_mba21_mixer[] = { | ||
176 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT), | ||
177 | HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 0x02, HDA_OUTPUT), | ||
178 | { } | ||
179 | }; | ||
180 | |||
181 | |||
182 | static const struct snd_kcontrol_new alc885_mbp3_mixer[] = { | ||
183 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT), | ||
184 | HDA_BIND_MUTE ("Speaker Playback Switch", 0x0c, 0x02, HDA_INPUT), | ||
185 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0e, 0x00, HDA_OUTPUT), | ||
186 | HDA_BIND_MUTE ("Headphone Playback Switch", 0x0e, 0x02, HDA_INPUT), | ||
187 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT), | ||
188 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | ||
189 | HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | ||
190 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT), | ||
191 | HDA_CODEC_MUTE ("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT), | ||
192 | HDA_CODEC_VOLUME("Line Boost Volume", 0x1a, 0x00, HDA_INPUT), | ||
193 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0x00, HDA_INPUT), | ||
194 | { } /* end */ | ||
195 | }; | ||
196 | |||
197 | static const struct snd_kcontrol_new alc885_mb5_mixer[] = { | ||
198 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT), | ||
199 | HDA_BIND_MUTE ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT), | ||
200 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT), | ||
201 | HDA_BIND_MUTE ("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT), | ||
202 | HDA_CODEC_VOLUME("LFE Playback Volume", 0x0e, 0x00, HDA_OUTPUT), | ||
203 | HDA_BIND_MUTE ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT), | ||
204 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT), | ||
205 | HDA_BIND_MUTE ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT), | ||
206 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x07, HDA_INPUT), | ||
207 | HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x07, HDA_INPUT), | ||
208 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), | ||
209 | HDA_CODEC_MUTE ("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), | ||
210 | HDA_CODEC_VOLUME("Line Boost Volume", 0x15, 0x00, HDA_INPUT), | ||
211 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x19, 0x00, HDA_INPUT), | ||
212 | { } /* end */ | ||
213 | }; | ||
214 | |||
215 | static const struct snd_kcontrol_new alc885_macmini3_mixer[] = { | ||
216 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT), | ||
217 | HDA_BIND_MUTE ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT), | ||
218 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT), | ||
219 | HDA_BIND_MUTE ("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT), | ||
220 | HDA_CODEC_VOLUME("LFE Playback Volume", 0x0e, 0x00, HDA_OUTPUT), | ||
221 | HDA_BIND_MUTE ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT), | ||
222 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT), | ||
223 | HDA_BIND_MUTE ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT), | ||
224 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x07, HDA_INPUT), | ||
225 | HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x07, HDA_INPUT), | ||
226 | HDA_CODEC_VOLUME("Line Boost Volume", 0x15, 0x00, HDA_INPUT), | ||
227 | { } /* end */ | ||
228 | }; | ||
229 | |||
230 | static const struct snd_kcontrol_new alc885_imac91_mixer[] = { | ||
231 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT), | ||
232 | HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 0x02, HDA_INPUT), | ||
233 | { } /* end */ | ||
234 | }; | ||
235 | |||
236 | |||
237 | static const struct snd_kcontrol_new alc882_chmode_mixer[] = { | ||
238 | { | ||
239 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
240 | .name = "Channel Mode", | ||
241 | .info = alc_ch_mode_info, | ||
242 | .get = alc_ch_mode_get, | ||
243 | .put = alc_ch_mode_put, | ||
244 | }, | ||
245 | { } /* end */ | ||
246 | }; | ||
247 | |||
248 | static const struct hda_verb alc882_base_init_verbs[] = { | ||
249 | /* Front mixer: unmute input/output amp left and right (volume = 0) */ | ||
250 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
251 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
252 | /* Rear mixer */ | ||
253 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
254 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
255 | /* CLFE mixer */ | ||
256 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
257 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
258 | /* Side mixer */ | ||
259 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
260 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
261 | |||
262 | /* Front Pin: output 0 (0x0c) */ | ||
263 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
264 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
265 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
266 | /* Rear Pin: output 1 (0x0d) */ | ||
267 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
268 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
269 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
270 | /* CLFE Pin: output 2 (0x0e) */ | ||
271 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
272 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
273 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x02}, | ||
274 | /* Side Pin: output 3 (0x0f) */ | ||
275 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
276 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
277 | {0x17, AC_VERB_SET_CONNECT_SEL, 0x03}, | ||
278 | /* Mic (rear) pin: input vref at 80% */ | ||
279 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
280 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
281 | /* Front Mic pin: input vref at 80% */ | ||
282 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
283 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
284 | /* Line In pin: input */ | ||
285 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
286 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
287 | /* Line-2 In: Headphone output (output 0 - 0x0c) */ | ||
288 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
289 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
290 | {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
291 | /* CD pin widget for input */ | ||
292 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
293 | |||
294 | /* FIXME: use matrix-type input source selection */ | ||
295 | /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ | ||
296 | /* Input mixer2 */ | ||
297 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
298 | /* Input mixer3 */ | ||
299 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
300 | /* ADC2: mute amp left and right */ | ||
301 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
302 | {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
303 | /* ADC3: mute amp left and right */ | ||
304 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
305 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
306 | |||
307 | { } | ||
308 | }; | ||
309 | |||
310 | #define alc883_init_verbs alc882_base_init_verbs | ||
311 | |||
312 | /* Macbook 5,1 */ | ||
313 | static const struct hda_verb alc885_mb5_init_verbs[] = { | ||
314 | /* DACs */ | ||
315 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
316 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
317 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
318 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
319 | /* Front mixer */ | ||
320 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
321 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
322 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
323 | /* Surround mixer */ | ||
324 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
325 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
326 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
327 | /* LFE mixer */ | ||
328 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
329 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
330 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
331 | /* HP mixer */ | ||
332 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
333 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
334 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
335 | /* Front Pin (0x0c) */ | ||
336 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01}, | ||
337 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
338 | {0x18, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
339 | /* LFE Pin (0x0e) */ | ||
340 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01}, | ||
341 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
342 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x02}, | ||
343 | /* HP Pin (0x0f) */ | ||
344 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
345 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
346 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x03}, | ||
347 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN}, | ||
348 | /* Front Mic pin: input vref at 80% */ | ||
349 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
350 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
351 | /* Line In pin */ | ||
352 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
353 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
354 | |||
355 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0x1)}, | ||
356 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0x7)}, | ||
357 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0x4)}, | ||
358 | { } | ||
359 | }; | ||
360 | |||
361 | /* Macmini 3,1 */ | ||
362 | static const struct hda_verb alc885_macmini3_init_verbs[] = { | ||
363 | /* DACs */ | ||
364 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
365 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
366 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
367 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
368 | /* Front mixer */ | ||
369 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
370 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
371 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
372 | /* Surround mixer */ | ||
373 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
374 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
375 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
376 | /* LFE mixer */ | ||
377 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
378 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
379 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
380 | /* HP mixer */ | ||
381 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
382 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
383 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
384 | /* Front Pin (0x0c) */ | ||
385 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01}, | ||
386 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
387 | {0x18, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
388 | /* LFE Pin (0x0e) */ | ||
389 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01}, | ||
390 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
391 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x02}, | ||
392 | /* HP Pin (0x0f) */ | ||
393 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
394 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
395 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x03}, | ||
396 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN}, | ||
397 | /* Line In pin */ | ||
398 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
399 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
400 | |||
401 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
402 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
403 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
404 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
405 | { } | ||
406 | }; | ||
407 | |||
408 | |||
409 | static const struct hda_verb alc885_mba21_init_verbs[] = { | ||
410 | /*Internal and HP Speaker Mixer*/ | ||
411 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
412 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
413 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
414 | /*Internal Speaker Pin (0x0c)*/ | ||
415 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, (PIN_OUT | AC_PINCTL_VREF_50) }, | ||
416 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
417 | {0x18, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
418 | /* HP Pin: output 0 (0x0e) */ | ||
419 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4}, | ||
420 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
421 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
422 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, (ALC_HP_EVENT | AC_USRSP_EN)}, | ||
423 | /* Line in (is hp when jack connected)*/ | ||
424 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_VREF_50}, | ||
425 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
426 | |||
427 | { } | ||
428 | }; | ||
429 | |||
430 | |||
431 | /* Macbook Pro rev3 */ | ||
432 | static const struct hda_verb alc885_mbp3_init_verbs[] = { | ||
433 | /* Front mixer: unmute input/output amp left and right (volume = 0) */ | ||
434 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
435 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
436 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
437 | /* Rear mixer */ | ||
438 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
439 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
440 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
441 | /* HP mixer */ | ||
442 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
443 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
444 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
445 | /* Front Pin: output 0 (0x0c) */ | ||
446 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
447 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
448 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
449 | /* HP Pin: output 0 (0x0e) */ | ||
450 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4}, | ||
451 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
452 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x02}, | ||
453 | {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN}, | ||
454 | /* Mic (rear) pin: input vref at 80% */ | ||
455 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
456 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
457 | /* Front Mic pin: input vref at 80% */ | ||
458 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
459 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
460 | /* Line In pin: use output 1 when in LineOut mode */ | ||
461 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
462 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
463 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
464 | |||
465 | /* FIXME: use matrix-type input source selection */ | ||
466 | /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ | ||
467 | /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ | ||
468 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
469 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
470 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
471 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
472 | /* Input mixer2 */ | ||
473 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
474 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
475 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
476 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
477 | /* Input mixer3 */ | ||
478 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
479 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
480 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
481 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
482 | /* ADC1: mute amp left and right */ | ||
483 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
484 | {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
485 | /* ADC2: mute amp left and right */ | ||
486 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
487 | {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
488 | /* ADC3: mute amp left and right */ | ||
489 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
490 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
491 | |||
492 | { } | ||
493 | }; | ||
494 | |||
495 | /* iMac 9,1 */ | ||
496 | static const struct hda_verb alc885_imac91_init_verbs[] = { | ||
497 | /* Internal Speaker Pin (0x0c) */ | ||
498 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, (PIN_OUT | AC_PINCTL_VREF_50) }, | ||
499 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
500 | {0x18, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
501 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, (PIN_OUT | AC_PINCTL_VREF_50) }, | ||
502 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
503 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
504 | /* HP Pin: Rear */ | ||
505 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
506 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
507 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
508 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, (ALC_HP_EVENT | AC_USRSP_EN)}, | ||
509 | /* Line in Rear */ | ||
510 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_VREF_50}, | ||
511 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
512 | /* Front Mic pin: input vref at 80% */ | ||
513 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
514 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
515 | /* Rear mixer */ | ||
516 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
517 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
518 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
519 | /* Line-Out mixer: unmute input/output amp left and right (volume = 0) */ | ||
520 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
521 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
522 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
523 | /* 0x24 [Audio Mixer] wcaps 0x20010b: Stereo Amp-In */ | ||
524 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
525 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
526 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
527 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
528 | /* 0x23 [Audio Mixer] wcaps 0x20010b: Stereo Amp-In */ | ||
529 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
530 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
531 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
532 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
533 | /* 0x22 [Audio Mixer] wcaps 0x20010b: Stereo Amp-In */ | ||
534 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
535 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
536 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
537 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
538 | /* 0x07 [Audio Input] wcaps 0x10011b: Stereo Amp-In */ | ||
539 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
540 | {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
541 | /* 0x08 [Audio Input] wcaps 0x10011b: Stereo Amp-In */ | ||
542 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
543 | {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
544 | /* 0x09 [Audio Input] wcaps 0x10011b: Stereo Amp-In */ | ||
545 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
546 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
547 | { } | ||
548 | }; | ||
549 | |||
550 | /* Toggle speaker-output according to the hp-jack state */ | ||
551 | static void alc885_imac24_setup(struct hda_codec *codec) | ||
552 | { | ||
553 | struct alc_spec *spec = codec->spec; | ||
554 | |||
555 | spec->autocfg.hp_pins[0] = 0x14; | ||
556 | spec->autocfg.speaker_pins[0] = 0x18; | ||
557 | spec->autocfg.speaker_pins[1] = 0x1a; | ||
558 | alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP); | ||
559 | } | ||
560 | |||
561 | #define alc885_mb5_setup alc885_imac24_setup | ||
562 | #define alc885_macmini3_setup alc885_imac24_setup | ||
563 | |||
564 | /* Macbook Air 2,1 */ | ||
565 | static void alc885_mba21_setup(struct hda_codec *codec) | ||
566 | { | ||
567 | struct alc_spec *spec = codec->spec; | ||
568 | |||
569 | spec->autocfg.hp_pins[0] = 0x14; | ||
570 | spec->autocfg.speaker_pins[0] = 0x18; | ||
571 | alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP); | ||
572 | } | ||
573 | |||
574 | |||
575 | |||
576 | static void alc885_mbp3_setup(struct hda_codec *codec) | ||
577 | { | ||
578 | struct alc_spec *spec = codec->spec; | ||
579 | |||
580 | spec->autocfg.hp_pins[0] = 0x15; | ||
581 | spec->autocfg.speaker_pins[0] = 0x14; | ||
582 | alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP); | ||
583 | } | ||
584 | |||
585 | static void alc885_imac91_setup(struct hda_codec *codec) | ||
586 | { | ||
587 | struct alc_spec *spec = codec->spec; | ||
588 | |||
589 | spec->autocfg.hp_pins[0] = 0x14; | ||
590 | spec->autocfg.speaker_pins[0] = 0x18; | ||
591 | spec->autocfg.speaker_pins[1] = 0x1a; | ||
592 | alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP); | ||
593 | } | ||
594 | |||
595 | /* 2ch mode (Speaker:front, Subwoofer:CLFE, Line:input, Headphones:front) */ | ||
596 | static const struct hda_verb alc889A_mb31_ch2_init[] = { | ||
597 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP as front */ | ||
598 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */ | ||
599 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Line as input */ | ||
600 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Line off */ | ||
601 | { } /* end */ | ||
602 | }; | ||
603 | |||
604 | /* 4ch mode (Speaker:front, Subwoofer:CLFE, Line:CLFE, Headphones:front) */ | ||
605 | static const struct hda_verb alc889A_mb31_ch4_init[] = { | ||
606 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP as front */ | ||
607 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */ | ||
608 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* Line as output */ | ||
609 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Line on */ | ||
610 | { } /* end */ | ||
611 | }; | ||
612 | |||
613 | /* 5ch mode (Speaker:front, Subwoofer:CLFE, Line:input, Headphones:rear) */ | ||
614 | static const struct hda_verb alc889A_mb31_ch5_init[] = { | ||
615 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, /* HP as rear */ | ||
616 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */ | ||
617 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Line as input */ | ||
618 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Line off */ | ||
619 | { } /* end */ | ||
620 | }; | ||
621 | |||
622 | /* 6ch mode (Speaker:front, Subwoofer:off, Line:CLFE, Headphones:Rear) */ | ||
623 | static const struct hda_verb alc889A_mb31_ch6_init[] = { | ||
624 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, /* HP as front */ | ||
625 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Subwoofer off */ | ||
626 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* Line as output */ | ||
627 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Line on */ | ||
628 | { } /* end */ | ||
629 | }; | ||
630 | |||
631 | static const struct hda_channel_mode alc889A_mb31_6ch_modes[4] = { | ||
632 | { 2, alc889A_mb31_ch2_init }, | ||
633 | { 4, alc889A_mb31_ch4_init }, | ||
634 | { 5, alc889A_mb31_ch5_init }, | ||
635 | { 6, alc889A_mb31_ch6_init }, | ||
636 | }; | ||
637 | |||
638 | static const struct snd_kcontrol_new alc883_3ST_6ch_mixer[] = { | ||
639 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
640 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | ||
641 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
642 | HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), | ||
643 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), | ||
644 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), | ||
645 | HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), | ||
646 | HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), | ||
647 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | ||
648 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
649 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
650 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | ||
651 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | ||
652 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
653 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), | ||
654 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
655 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | ||
656 | HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT), | ||
657 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | ||
658 | { } /* end */ | ||
659 | }; | ||
660 | |||
661 | static const struct snd_kcontrol_new alc889A_mb31_mixer[] = { | ||
662 | /* Output mixers */ | ||
663 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT), | ||
664 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 0x02, HDA_INPUT), | ||
665 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT), | ||
666 | HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT), | ||
667 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x00, | ||
668 | HDA_OUTPUT), | ||
669 | HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 0x02, HDA_INPUT), | ||
670 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x00, HDA_OUTPUT), | ||
671 | HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x02, HDA_INPUT), | ||
672 | /* Output switches */ | ||
673 | HDA_CODEC_MUTE("Enable Speaker", 0x14, 0x00, HDA_OUTPUT), | ||
674 | HDA_CODEC_MUTE("Enable Headphones", 0x15, 0x00, HDA_OUTPUT), | ||
675 | HDA_CODEC_MUTE_MONO("Enable LFE", 0x16, 2, 0x00, HDA_OUTPUT), | ||
676 | /* Boost mixers */ | ||
677 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0x00, HDA_INPUT), | ||
678 | HDA_CODEC_VOLUME("Line Boost Volume", 0x1a, 0x00, HDA_INPUT), | ||
679 | /* Input mixers */ | ||
680 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT), | ||
681 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT), | ||
682 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | ||
683 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | ||
684 | { } /* end */ | ||
685 | }; | ||
686 | |||
687 | static const struct snd_kcontrol_new alc883_chmode_mixer[] = { | ||
688 | { | ||
689 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
690 | .name = "Channel Mode", | ||
691 | .info = alc_ch_mode_info, | ||
692 | .get = alc_ch_mode_get, | ||
693 | .put = alc_ch_mode_put, | ||
694 | }, | ||
695 | { } /* end */ | ||
696 | }; | ||
697 | |||
698 | static const struct hda_verb alc889A_mb31_verbs[] = { | ||
699 | /* Init rear pin (used as headphone output) */ | ||
700 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4}, /* Apple Headphones */ | ||
701 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Connect to front */ | ||
702 | {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN}, | ||
703 | /* Init line pin (used as output in 4ch and 6ch mode) */ | ||
704 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x02}, /* Connect to CLFE */ | ||
705 | /* Init line 2 pin (used as headphone out by default) */ | ||
706 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Use as input */ | ||
707 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Mute output */ | ||
708 | { } /* end */ | ||
709 | }; | ||
710 | |||
711 | /* Mute speakers according to the headphone jack state */ | ||
712 | static void alc889A_mb31_automute(struct hda_codec *codec) | ||
713 | { | ||
714 | unsigned int present; | ||
715 | |||
716 | /* Mute only in 2ch or 4ch mode */ | ||
717 | if (snd_hda_codec_read(codec, 0x15, 0, AC_VERB_GET_CONNECT_SEL, 0) | ||
718 | == 0x00) { | ||
719 | present = snd_hda_jack_detect(codec, 0x15); | ||
720 | snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, | ||
721 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); | ||
722 | snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0, | ||
723 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); | ||
724 | } | ||
725 | } | ||
726 | |||
727 | static void alc889A_mb31_unsol_event(struct hda_codec *codec, unsigned int res) | ||
728 | { | ||
729 | if ((res >> 26) == ALC_HP_EVENT) | ||
730 | alc889A_mb31_automute(codec); | ||
731 | } | ||
732 | |||
733 | static void alc882_unsol_event(struct hda_codec *codec, unsigned int res) | ||
734 | { | ||
735 | alc_exec_unsol_event(codec, res >> 26); | ||
736 | } | ||
737 | |||
738 | /* | ||
739 | * configuration and preset | ||
740 | */ | ||
741 | static const char * const alc882_models[ALC882_MODEL_LAST] = { | ||
742 | [ALC885_MB5] = "mb5", | ||
743 | [ALC885_MACMINI3] = "macmini3", | ||
744 | [ALC885_MBA21] = "mba21", | ||
745 | [ALC885_MBP3] = "mbp3", | ||
746 | [ALC885_IMAC91] = "imac91", | ||
747 | [ALC889A_MB31] = "mb31", | ||
748 | [ALC882_AUTO] = "auto", | ||
749 | }; | ||
750 | |||
751 | /* codec SSID table for Intel Mac */ | ||
752 | static const struct snd_pci_quirk alc882_ssid_cfg_tbl[] = { | ||
753 | SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC885_MBP3), | ||
754 | SND_PCI_QUIRK(0x106b, 0x00a1, "Macbook", ALC885_MBP3), | ||
755 | SND_PCI_QUIRK(0x106b, 0x00a4, "MacbookPro 4,1", ALC885_MBP3), | ||
756 | SND_PCI_QUIRK(0x106b, 0x2c00, "MacbookPro rev3", ALC885_MBP3), | ||
757 | SND_PCI_QUIRK(0x106b, 0x3000, "iMac", ALC889A_MB31), | ||
758 | SND_PCI_QUIRK(0x106b, 0x3400, "MacBookAir 1,1", ALC885_MBP3), | ||
759 | SND_PCI_QUIRK(0x106b, 0x3500, "MacBookAir 2,1", ALC885_MBA21), | ||
760 | SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889A_MB31), | ||
761 | SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC885_MBP3), | ||
762 | SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC885_IMAC91), | ||
763 | SND_PCI_QUIRK(0x106b, 0x3f00, "Macbook 5,1", ALC885_MB5), | ||
764 | SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC885_MB5), | ||
765 | /* FIXME: HP jack sense seems not working for MBP 5,1 or 5,2, | ||
766 | * so apparently no perfect solution yet | ||
767 | */ | ||
768 | SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC885_MB5), | ||
769 | SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC885_MB5), | ||
770 | SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC885_MACMINI3), | ||
771 | {} /* terminator */ | ||
772 | }; | ||
773 | |||
774 | static const struct alc_config_preset alc882_presets[] = { | ||
775 | [ALC885_MBA21] = { | ||
776 | .mixers = { alc885_mba21_mixer }, | ||
777 | .init_verbs = { alc885_mba21_init_verbs, alc880_gpio1_init_verbs }, | ||
778 | .num_dacs = 2, | ||
779 | .dac_nids = alc882_dac_nids, | ||
780 | .channel_mode = alc885_mba21_ch_modes, | ||
781 | .num_channel_mode = ARRAY_SIZE(alc885_mba21_ch_modes), | ||
782 | .input_mux = &alc882_capture_source, | ||
783 | .unsol_event = alc882_unsol_event, | ||
784 | .setup = alc885_mba21_setup, | ||
785 | .init_hook = alc_hp_automute, | ||
786 | }, | ||
787 | [ALC885_MBP3] = { | ||
788 | .mixers = { alc885_mbp3_mixer, alc882_chmode_mixer }, | ||
789 | .init_verbs = { alc885_mbp3_init_verbs, | ||
790 | alc880_gpio1_init_verbs }, | ||
791 | .num_dacs = 2, | ||
792 | .dac_nids = alc882_dac_nids, | ||
793 | .hp_nid = 0x04, | ||
794 | .channel_mode = alc885_mbp_4ch_modes, | ||
795 | .num_channel_mode = ARRAY_SIZE(alc885_mbp_4ch_modes), | ||
796 | .input_mux = &alc882_capture_source, | ||
797 | .dig_out_nid = ALC882_DIGOUT_NID, | ||
798 | .dig_in_nid = ALC882_DIGIN_NID, | ||
799 | .unsol_event = alc882_unsol_event, | ||
800 | .setup = alc885_mbp3_setup, | ||
801 | .init_hook = alc_hp_automute, | ||
802 | }, | ||
803 | [ALC885_MB5] = { | ||
804 | .mixers = { alc885_mb5_mixer, alc882_chmode_mixer }, | ||
805 | .init_verbs = { alc885_mb5_init_verbs, | ||
806 | alc880_gpio1_init_verbs }, | ||
807 | .num_dacs = ARRAY_SIZE(alc882_dac_nids), | ||
808 | .dac_nids = alc882_dac_nids, | ||
809 | .channel_mode = alc885_mb5_6ch_modes, | ||
810 | .num_channel_mode = ARRAY_SIZE(alc885_mb5_6ch_modes), | ||
811 | .input_mux = &mb5_capture_source, | ||
812 | .dig_out_nid = ALC882_DIGOUT_NID, | ||
813 | .dig_in_nid = ALC882_DIGIN_NID, | ||
814 | .unsol_event = alc882_unsol_event, | ||
815 | .setup = alc885_mb5_setup, | ||
816 | .init_hook = alc_hp_automute, | ||
817 | }, | ||
818 | [ALC885_MACMINI3] = { | ||
819 | .mixers = { alc885_macmini3_mixer, alc882_chmode_mixer }, | ||
820 | .init_verbs = { alc885_macmini3_init_verbs, | ||
821 | alc880_gpio1_init_verbs }, | ||
822 | .num_dacs = ARRAY_SIZE(alc882_dac_nids), | ||
823 | .dac_nids = alc882_dac_nids, | ||
824 | .channel_mode = alc885_macmini3_6ch_modes, | ||
825 | .num_channel_mode = ARRAY_SIZE(alc885_macmini3_6ch_modes), | ||
826 | .input_mux = &macmini3_capture_source, | ||
827 | .dig_out_nid = ALC882_DIGOUT_NID, | ||
828 | .dig_in_nid = ALC882_DIGIN_NID, | ||
829 | .unsol_event = alc882_unsol_event, | ||
830 | .setup = alc885_macmini3_setup, | ||
831 | .init_hook = alc_hp_automute, | ||
832 | }, | ||
833 | [ALC885_IMAC91] = { | ||
834 | .mixers = {alc885_imac91_mixer}, | ||
835 | .init_verbs = { alc885_imac91_init_verbs, | ||
836 | alc880_gpio1_init_verbs }, | ||
837 | .num_dacs = ARRAY_SIZE(alc882_dac_nids), | ||
838 | .dac_nids = alc882_dac_nids, | ||
839 | .channel_mode = alc885_mba21_ch_modes, | ||
840 | .num_channel_mode = ARRAY_SIZE(alc885_mba21_ch_modes), | ||
841 | .input_mux = &alc889A_imac91_capture_source, | ||
842 | .dig_out_nid = ALC882_DIGOUT_NID, | ||
843 | .dig_in_nid = ALC882_DIGIN_NID, | ||
844 | .unsol_event = alc882_unsol_event, | ||
845 | .setup = alc885_imac91_setup, | ||
846 | .init_hook = alc_hp_automute, | ||
847 | }, | ||
848 | [ALC889A_MB31] = { | ||
849 | .mixers = { alc889A_mb31_mixer, alc883_chmode_mixer}, | ||
850 | .init_verbs = { alc883_init_verbs, alc889A_mb31_verbs, | ||
851 | alc880_gpio1_init_verbs }, | ||
852 | .adc_nids = alc883_adc_nids, | ||
853 | .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), | ||
854 | .capsrc_nids = alc883_capsrc_nids, | ||
855 | .dac_nids = alc883_dac_nids, | ||
856 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), | ||
857 | .channel_mode = alc889A_mb31_6ch_modes, | ||
858 | .num_channel_mode = ARRAY_SIZE(alc889A_mb31_6ch_modes), | ||
859 | .input_mux = &alc889A_mb31_capture_source, | ||
860 | .dig_out_nid = ALC883_DIGOUT_NID, | ||
861 | .unsol_event = alc889A_mb31_unsol_event, | ||
862 | .init_hook = alc889A_mb31_automute, | ||
863 | }, | ||
864 | }; | ||
865 | |||
866 | |||
diff --git a/sound/pci/hda/alc_quirks.c b/sound/pci/hda/alc_quirks.c deleted file mode 100644 index a18952ed4311..000000000000 --- a/sound/pci/hda/alc_quirks.c +++ /dev/null | |||
@@ -1,480 +0,0 @@ | |||
1 | /* | ||
2 | * Common codes for Realtek codec quirks | ||
3 | * included by patch_realtek.c | ||
4 | */ | ||
5 | |||
6 | /* | ||
7 | * configuration template - to be copied to the spec instance | ||
8 | */ | ||
9 | struct alc_config_preset { | ||
10 | const struct snd_kcontrol_new *mixers[5]; /* should be identical size | ||
11 | * with spec | ||
12 | */ | ||
13 | const struct snd_kcontrol_new *cap_mixer; /* capture mixer */ | ||
14 | const struct hda_verb *init_verbs[5]; | ||
15 | unsigned int num_dacs; | ||
16 | const hda_nid_t *dac_nids; | ||
17 | hda_nid_t dig_out_nid; /* optional */ | ||
18 | hda_nid_t hp_nid; /* optional */ | ||
19 | const hda_nid_t *slave_dig_outs; | ||
20 | unsigned int num_adc_nids; | ||
21 | const hda_nid_t *adc_nids; | ||
22 | const hda_nid_t *capsrc_nids; | ||
23 | hda_nid_t dig_in_nid; | ||
24 | unsigned int num_channel_mode; | ||
25 | const struct hda_channel_mode *channel_mode; | ||
26 | int need_dac_fix; | ||
27 | int const_channel_count; | ||
28 | unsigned int num_mux_defs; | ||
29 | const struct hda_input_mux *input_mux; | ||
30 | void (*unsol_event)(struct hda_codec *, unsigned int); | ||
31 | void (*setup)(struct hda_codec *); | ||
32 | void (*init_hook)(struct hda_codec *); | ||
33 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
34 | const struct hda_amp_list *loopbacks; | ||
35 | void (*power_hook)(struct hda_codec *codec); | ||
36 | #endif | ||
37 | }; | ||
38 | |||
39 | /* | ||
40 | * channel mode setting | ||
41 | */ | ||
42 | static int alc_ch_mode_info(struct snd_kcontrol *kcontrol, | ||
43 | struct snd_ctl_elem_info *uinfo) | ||
44 | { | ||
45 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
46 | struct alc_spec *spec = codec->spec; | ||
47 | return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode, | ||
48 | spec->num_channel_mode); | ||
49 | } | ||
50 | |||
51 | static int alc_ch_mode_get(struct snd_kcontrol *kcontrol, | ||
52 | struct snd_ctl_elem_value *ucontrol) | ||
53 | { | ||
54 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
55 | struct alc_spec *spec = codec->spec; | ||
56 | return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode, | ||
57 | spec->num_channel_mode, | ||
58 | spec->ext_channel_count); | ||
59 | } | ||
60 | |||
61 | static int alc_ch_mode_put(struct snd_kcontrol *kcontrol, | ||
62 | struct snd_ctl_elem_value *ucontrol) | ||
63 | { | ||
64 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
65 | struct alc_spec *spec = codec->spec; | ||
66 | int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode, | ||
67 | spec->num_channel_mode, | ||
68 | &spec->ext_channel_count); | ||
69 | if (err >= 0 && !spec->const_channel_count) { | ||
70 | spec->multiout.max_channels = spec->ext_channel_count; | ||
71 | if (spec->need_dac_fix) | ||
72 | spec->multiout.num_dacs = spec->multiout.max_channels / 2; | ||
73 | } | ||
74 | return err; | ||
75 | } | ||
76 | |||
77 | /* | ||
78 | * Control the mode of pin widget settings via the mixer. "pc" is used | ||
79 | * instead of "%" to avoid consequences of accidentally treating the % as | ||
80 | * being part of a format specifier. Maximum allowed length of a value is | ||
81 | * 63 characters plus NULL terminator. | ||
82 | * | ||
83 | * Note: some retasking pin complexes seem to ignore requests for input | ||
84 | * states other than HiZ (eg: PIN_VREFxx) and revert to HiZ if any of these | ||
85 | * are requested. Therefore order this list so that this behaviour will not | ||
86 | * cause problems when mixer clients move through the enum sequentially. | ||
87 | * NIDs 0x0f and 0x10 have been observed to have this behaviour as of | ||
88 | * March 2006. | ||
89 | */ | ||
90 | static const char * const alc_pin_mode_names[] = { | ||
91 | "Mic 50pc bias", "Mic 80pc bias", | ||
92 | "Line in", "Line out", "Headphone out", | ||
93 | }; | ||
94 | static const unsigned char alc_pin_mode_values[] = { | ||
95 | PIN_VREF50, PIN_VREF80, PIN_IN, PIN_OUT, PIN_HP, | ||
96 | }; | ||
97 | /* The control can present all 5 options, or it can limit the options based | ||
98 | * in the pin being assumed to be exclusively an input or an output pin. In | ||
99 | * addition, "input" pins may or may not process the mic bias option | ||
100 | * depending on actual widget capability (NIDs 0x0f and 0x10 don't seem to | ||
101 | * accept requests for bias as of chip versions up to March 2006) and/or | ||
102 | * wiring in the computer. | ||
103 | */ | ||
104 | #define ALC_PIN_DIR_IN 0x00 | ||
105 | #define ALC_PIN_DIR_OUT 0x01 | ||
106 | #define ALC_PIN_DIR_INOUT 0x02 | ||
107 | #define ALC_PIN_DIR_IN_NOMICBIAS 0x03 | ||
108 | #define ALC_PIN_DIR_INOUT_NOMICBIAS 0x04 | ||
109 | |||
110 | /* Info about the pin modes supported by the different pin direction modes. | ||
111 | * For each direction the minimum and maximum values are given. | ||
112 | */ | ||
113 | static const signed char alc_pin_mode_dir_info[5][2] = { | ||
114 | { 0, 2 }, /* ALC_PIN_DIR_IN */ | ||
115 | { 3, 4 }, /* ALC_PIN_DIR_OUT */ | ||
116 | { 0, 4 }, /* ALC_PIN_DIR_INOUT */ | ||
117 | { 2, 2 }, /* ALC_PIN_DIR_IN_NOMICBIAS */ | ||
118 | { 2, 4 }, /* ALC_PIN_DIR_INOUT_NOMICBIAS */ | ||
119 | }; | ||
120 | #define alc_pin_mode_min(_dir) (alc_pin_mode_dir_info[_dir][0]) | ||
121 | #define alc_pin_mode_max(_dir) (alc_pin_mode_dir_info[_dir][1]) | ||
122 | #define alc_pin_mode_n_items(_dir) \ | ||
123 | (alc_pin_mode_max(_dir)-alc_pin_mode_min(_dir)+1) | ||
124 | |||
125 | static int alc_pin_mode_info(struct snd_kcontrol *kcontrol, | ||
126 | struct snd_ctl_elem_info *uinfo) | ||
127 | { | ||
128 | unsigned int item_num = uinfo->value.enumerated.item; | ||
129 | unsigned char dir = (kcontrol->private_value >> 16) & 0xff; | ||
130 | |||
131 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
132 | uinfo->count = 1; | ||
133 | uinfo->value.enumerated.items = alc_pin_mode_n_items(dir); | ||
134 | |||
135 | if (item_num<alc_pin_mode_min(dir) || item_num>alc_pin_mode_max(dir)) | ||
136 | item_num = alc_pin_mode_min(dir); | ||
137 | strcpy(uinfo->value.enumerated.name, alc_pin_mode_names[item_num]); | ||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | static int alc_pin_mode_get(struct snd_kcontrol *kcontrol, | ||
142 | struct snd_ctl_elem_value *ucontrol) | ||
143 | { | ||
144 | unsigned int i; | ||
145 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
146 | hda_nid_t nid = kcontrol->private_value & 0xffff; | ||
147 | unsigned char dir = (kcontrol->private_value >> 16) & 0xff; | ||
148 | long *valp = ucontrol->value.integer.value; | ||
149 | unsigned int pinctl = snd_hda_codec_read(codec, nid, 0, | ||
150 | AC_VERB_GET_PIN_WIDGET_CONTROL, | ||
151 | 0x00); | ||
152 | |||
153 | /* Find enumerated value for current pinctl setting */ | ||
154 | i = alc_pin_mode_min(dir); | ||
155 | while (i <= alc_pin_mode_max(dir) && alc_pin_mode_values[i] != pinctl) | ||
156 | i++; | ||
157 | *valp = i <= alc_pin_mode_max(dir) ? i: alc_pin_mode_min(dir); | ||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | static int alc_pin_mode_put(struct snd_kcontrol *kcontrol, | ||
162 | struct snd_ctl_elem_value *ucontrol) | ||
163 | { | ||
164 | signed int change; | ||
165 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
166 | hda_nid_t nid = kcontrol->private_value & 0xffff; | ||
167 | unsigned char dir = (kcontrol->private_value >> 16) & 0xff; | ||
168 | long val = *ucontrol->value.integer.value; | ||
169 | unsigned int pinctl = snd_hda_codec_read(codec, nid, 0, | ||
170 | AC_VERB_GET_PIN_WIDGET_CONTROL, | ||
171 | 0x00); | ||
172 | |||
173 | if (val < alc_pin_mode_min(dir) || val > alc_pin_mode_max(dir)) | ||
174 | val = alc_pin_mode_min(dir); | ||
175 | |||
176 | change = pinctl != alc_pin_mode_values[val]; | ||
177 | if (change) { | ||
178 | /* Set pin mode to that requested */ | ||
179 | snd_hda_codec_write_cache(codec, nid, 0, | ||
180 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
181 | alc_pin_mode_values[val]); | ||
182 | |||
183 | /* Also enable the retasking pin's input/output as required | ||
184 | * for the requested pin mode. Enum values of 2 or less are | ||
185 | * input modes. | ||
186 | * | ||
187 | * Dynamically switching the input/output buffers probably | ||
188 | * reduces noise slightly (particularly on input) so we'll | ||
189 | * do it. However, having both input and output buffers | ||
190 | * enabled simultaneously doesn't seem to be problematic if | ||
191 | * this turns out to be necessary in the future. | ||
192 | */ | ||
193 | if (val <= 2) { | ||
194 | snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, | ||
195 | HDA_AMP_MUTE, HDA_AMP_MUTE); | ||
196 | snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0, | ||
197 | HDA_AMP_MUTE, 0); | ||
198 | } else { | ||
199 | snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0, | ||
200 | HDA_AMP_MUTE, HDA_AMP_MUTE); | ||
201 | snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, | ||
202 | HDA_AMP_MUTE, 0); | ||
203 | } | ||
204 | } | ||
205 | return change; | ||
206 | } | ||
207 | |||
208 | #define ALC_PIN_MODE(xname, nid, dir) \ | ||
209 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ | ||
210 | .subdevice = HDA_SUBDEV_NID_FLAG | nid, \ | ||
211 | .info = alc_pin_mode_info, \ | ||
212 | .get = alc_pin_mode_get, \ | ||
213 | .put = alc_pin_mode_put, \ | ||
214 | .private_value = nid | (dir<<16) } | ||
215 | |||
216 | /* A switch control for ALC260 GPIO pins. Multiple GPIOs can be ganged | ||
217 | * together using a mask with more than one bit set. This control is | ||
218 | * currently used only by the ALC260 test model. At this stage they are not | ||
219 | * needed for any "production" models. | ||
220 | */ | ||
221 | #ifdef CONFIG_SND_DEBUG | ||
222 | #define alc_gpio_data_info snd_ctl_boolean_mono_info | ||
223 | |||
224 | static int alc_gpio_data_get(struct snd_kcontrol *kcontrol, | ||
225 | struct snd_ctl_elem_value *ucontrol) | ||
226 | { | ||
227 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
228 | hda_nid_t nid = kcontrol->private_value & 0xffff; | ||
229 | unsigned char mask = (kcontrol->private_value >> 16) & 0xff; | ||
230 | long *valp = ucontrol->value.integer.value; | ||
231 | unsigned int val = snd_hda_codec_read(codec, nid, 0, | ||
232 | AC_VERB_GET_GPIO_DATA, 0x00); | ||
233 | |||
234 | *valp = (val & mask) != 0; | ||
235 | return 0; | ||
236 | } | ||
237 | static int alc_gpio_data_put(struct snd_kcontrol *kcontrol, | ||
238 | struct snd_ctl_elem_value *ucontrol) | ||
239 | { | ||
240 | signed int change; | ||
241 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
242 | hda_nid_t nid = kcontrol->private_value & 0xffff; | ||
243 | unsigned char mask = (kcontrol->private_value >> 16) & 0xff; | ||
244 | long val = *ucontrol->value.integer.value; | ||
245 | unsigned int gpio_data = snd_hda_codec_read(codec, nid, 0, | ||
246 | AC_VERB_GET_GPIO_DATA, | ||
247 | 0x00); | ||
248 | |||
249 | /* Set/unset the masked GPIO bit(s) as needed */ | ||
250 | change = (val == 0 ? 0 : mask) != (gpio_data & mask); | ||
251 | if (val == 0) | ||
252 | gpio_data &= ~mask; | ||
253 | else | ||
254 | gpio_data |= mask; | ||
255 | snd_hda_codec_write_cache(codec, nid, 0, | ||
256 | AC_VERB_SET_GPIO_DATA, gpio_data); | ||
257 | |||
258 | return change; | ||
259 | } | ||
260 | #define ALC_GPIO_DATA_SWITCH(xname, nid, mask) \ | ||
261 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ | ||
262 | .subdevice = HDA_SUBDEV_NID_FLAG | nid, \ | ||
263 | .info = alc_gpio_data_info, \ | ||
264 | .get = alc_gpio_data_get, \ | ||
265 | .put = alc_gpio_data_put, \ | ||
266 | .private_value = nid | (mask<<16) } | ||
267 | #endif /* CONFIG_SND_DEBUG */ | ||
268 | |||
269 | /* A switch control to allow the enabling of the digital IO pins on the | ||
270 | * ALC260. This is incredibly simplistic; the intention of this control is | ||
271 | * to provide something in the test model allowing digital outputs to be | ||
272 | * identified if present. If models are found which can utilise these | ||
273 | * outputs a more complete mixer control can be devised for those models if | ||
274 | * necessary. | ||
275 | */ | ||
276 | #ifdef CONFIG_SND_DEBUG | ||
277 | #define alc_spdif_ctrl_info snd_ctl_boolean_mono_info | ||
278 | |||
279 | static int alc_spdif_ctrl_get(struct snd_kcontrol *kcontrol, | ||
280 | struct snd_ctl_elem_value *ucontrol) | ||
281 | { | ||
282 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
283 | hda_nid_t nid = kcontrol->private_value & 0xffff; | ||
284 | unsigned char mask = (kcontrol->private_value >> 16) & 0xff; | ||
285 | long *valp = ucontrol->value.integer.value; | ||
286 | unsigned int val = snd_hda_codec_read(codec, nid, 0, | ||
287 | AC_VERB_GET_DIGI_CONVERT_1, 0x00); | ||
288 | |||
289 | *valp = (val & mask) != 0; | ||
290 | return 0; | ||
291 | } | ||
292 | static int alc_spdif_ctrl_put(struct snd_kcontrol *kcontrol, | ||
293 | struct snd_ctl_elem_value *ucontrol) | ||
294 | { | ||
295 | signed int change; | ||
296 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
297 | hda_nid_t nid = kcontrol->private_value & 0xffff; | ||
298 | unsigned char mask = (kcontrol->private_value >> 16) & 0xff; | ||
299 | long val = *ucontrol->value.integer.value; | ||
300 | unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0, | ||
301 | AC_VERB_GET_DIGI_CONVERT_1, | ||
302 | 0x00); | ||
303 | |||
304 | /* Set/unset the masked control bit(s) as needed */ | ||
305 | change = (val == 0 ? 0 : mask) != (ctrl_data & mask); | ||
306 | if (val==0) | ||
307 | ctrl_data &= ~mask; | ||
308 | else | ||
309 | ctrl_data |= mask; | ||
310 | snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, | ||
311 | ctrl_data); | ||
312 | |||
313 | return change; | ||
314 | } | ||
315 | #define ALC_SPDIF_CTRL_SWITCH(xname, nid, mask) \ | ||
316 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ | ||
317 | .subdevice = HDA_SUBDEV_NID_FLAG | nid, \ | ||
318 | .info = alc_spdif_ctrl_info, \ | ||
319 | .get = alc_spdif_ctrl_get, \ | ||
320 | .put = alc_spdif_ctrl_put, \ | ||
321 | .private_value = nid | (mask<<16) } | ||
322 | #endif /* CONFIG_SND_DEBUG */ | ||
323 | |||
324 | /* A switch control to allow the enabling EAPD digital outputs on the ALC26x. | ||
325 | * Again, this is only used in the ALC26x test models to help identify when | ||
326 | * the EAPD line must be asserted for features to work. | ||
327 | */ | ||
328 | #ifdef CONFIG_SND_DEBUG | ||
329 | #define alc_eapd_ctrl_info snd_ctl_boolean_mono_info | ||
330 | |||
331 | static int alc_eapd_ctrl_get(struct snd_kcontrol *kcontrol, | ||
332 | struct snd_ctl_elem_value *ucontrol) | ||
333 | { | ||
334 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
335 | hda_nid_t nid = kcontrol->private_value & 0xffff; | ||
336 | unsigned char mask = (kcontrol->private_value >> 16) & 0xff; | ||
337 | long *valp = ucontrol->value.integer.value; | ||
338 | unsigned int val = snd_hda_codec_read(codec, nid, 0, | ||
339 | AC_VERB_GET_EAPD_BTLENABLE, 0x00); | ||
340 | |||
341 | *valp = (val & mask) != 0; | ||
342 | return 0; | ||
343 | } | ||
344 | |||
345 | static int alc_eapd_ctrl_put(struct snd_kcontrol *kcontrol, | ||
346 | struct snd_ctl_elem_value *ucontrol) | ||
347 | { | ||
348 | int change; | ||
349 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
350 | hda_nid_t nid = kcontrol->private_value & 0xffff; | ||
351 | unsigned char mask = (kcontrol->private_value >> 16) & 0xff; | ||
352 | long val = *ucontrol->value.integer.value; | ||
353 | unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0, | ||
354 | AC_VERB_GET_EAPD_BTLENABLE, | ||
355 | 0x00); | ||
356 | |||
357 | /* Set/unset the masked control bit(s) as needed */ | ||
358 | change = (!val ? 0 : mask) != (ctrl_data & mask); | ||
359 | if (!val) | ||
360 | ctrl_data &= ~mask; | ||
361 | else | ||
362 | ctrl_data |= mask; | ||
363 | snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE, | ||
364 | ctrl_data); | ||
365 | |||
366 | return change; | ||
367 | } | ||
368 | |||
369 | #define ALC_EAPD_CTRL_SWITCH(xname, nid, mask) \ | ||
370 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ | ||
371 | .subdevice = HDA_SUBDEV_NID_FLAG | nid, \ | ||
372 | .info = alc_eapd_ctrl_info, \ | ||
373 | .get = alc_eapd_ctrl_get, \ | ||
374 | .put = alc_eapd_ctrl_put, \ | ||
375 | .private_value = nid | (mask<<16) } | ||
376 | #endif /* CONFIG_SND_DEBUG */ | ||
377 | |||
378 | static void alc_fixup_autocfg_pin_nums(struct hda_codec *codec) | ||
379 | { | ||
380 | struct alc_spec *spec = codec->spec; | ||
381 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
382 | |||
383 | if (!cfg->line_outs) { | ||
384 | while (cfg->line_outs < AUTO_CFG_MAX_OUTS && | ||
385 | cfg->line_out_pins[cfg->line_outs]) | ||
386 | cfg->line_outs++; | ||
387 | } | ||
388 | if (!cfg->speaker_outs) { | ||
389 | while (cfg->speaker_outs < AUTO_CFG_MAX_OUTS && | ||
390 | cfg->speaker_pins[cfg->speaker_outs]) | ||
391 | cfg->speaker_outs++; | ||
392 | } | ||
393 | if (!cfg->hp_outs) { | ||
394 | while (cfg->hp_outs < AUTO_CFG_MAX_OUTS && | ||
395 | cfg->hp_pins[cfg->hp_outs]) | ||
396 | cfg->hp_outs++; | ||
397 | } | ||
398 | } | ||
399 | |||
400 | /* | ||
401 | * set up from the preset table | ||
402 | */ | ||
403 | static void setup_preset(struct hda_codec *codec, | ||
404 | const struct alc_config_preset *preset) | ||
405 | { | ||
406 | struct alc_spec *spec = codec->spec; | ||
407 | int i; | ||
408 | |||
409 | for (i = 0; i < ARRAY_SIZE(preset->mixers) && preset->mixers[i]; i++) | ||
410 | add_mixer(spec, preset->mixers[i]); | ||
411 | spec->cap_mixer = preset->cap_mixer; | ||
412 | for (i = 0; i < ARRAY_SIZE(preset->init_verbs) && preset->init_verbs[i]; | ||
413 | i++) | ||
414 | add_verb(spec, preset->init_verbs[i]); | ||
415 | |||
416 | spec->channel_mode = preset->channel_mode; | ||
417 | spec->num_channel_mode = preset->num_channel_mode; | ||
418 | spec->need_dac_fix = preset->need_dac_fix; | ||
419 | spec->const_channel_count = preset->const_channel_count; | ||
420 | |||
421 | if (preset->const_channel_count) | ||
422 | spec->multiout.max_channels = preset->const_channel_count; | ||
423 | else | ||
424 | spec->multiout.max_channels = spec->channel_mode[0].channels; | ||
425 | spec->ext_channel_count = spec->channel_mode[0].channels; | ||
426 | |||
427 | spec->multiout.num_dacs = preset->num_dacs; | ||
428 | spec->multiout.dac_nids = preset->dac_nids; | ||
429 | spec->multiout.dig_out_nid = preset->dig_out_nid; | ||
430 | spec->multiout.slave_dig_outs = preset->slave_dig_outs; | ||
431 | spec->multiout.hp_nid = preset->hp_nid; | ||
432 | |||
433 | spec->num_mux_defs = preset->num_mux_defs; | ||
434 | if (!spec->num_mux_defs) | ||
435 | spec->num_mux_defs = 1; | ||
436 | spec->input_mux = preset->input_mux; | ||
437 | |||
438 | spec->num_adc_nids = preset->num_adc_nids; | ||
439 | spec->adc_nids = preset->adc_nids; | ||
440 | spec->capsrc_nids = preset->capsrc_nids; | ||
441 | spec->dig_in_nid = preset->dig_in_nid; | ||
442 | |||
443 | spec->unsol_event = preset->unsol_event; | ||
444 | spec->init_hook = preset->init_hook; | ||
445 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
446 | spec->power_hook = preset->power_hook; | ||
447 | spec->loopback.amplist = preset->loopbacks; | ||
448 | #endif | ||
449 | |||
450 | if (preset->setup) | ||
451 | preset->setup(codec); | ||
452 | |||
453 | alc_fixup_autocfg_pin_nums(codec); | ||
454 | } | ||
455 | |||
456 | static void alc_simple_setup_automute(struct alc_spec *spec, int mode) | ||
457 | { | ||
458 | int lo_pin = spec->autocfg.line_out_pins[0]; | ||
459 | |||
460 | if (lo_pin == spec->autocfg.speaker_pins[0] || | ||
461 | lo_pin == spec->autocfg.hp_pins[0]) | ||
462 | lo_pin = 0; | ||
463 | spec->automute_mode = mode; | ||
464 | spec->detect_hp = !!spec->autocfg.hp_pins[0]; | ||
465 | spec->detect_lo = !!lo_pin; | ||
466 | spec->automute_lo = spec->automute_lo_possible = !!lo_pin; | ||
467 | spec->automute_speaker = spec->automute_speaker_possible = !!spec->autocfg.speaker_pins[0]; | ||
468 | } | ||
469 | |||
470 | /* auto-toggle front mic */ | ||
471 | static void alc88x_simple_mic_automute(struct hda_codec *codec) | ||
472 | { | ||
473 | unsigned int present; | ||
474 | unsigned char bits; | ||
475 | |||
476 | present = snd_hda_jack_detect(codec, 0x18); | ||
477 | bits = present ? HDA_AMP_MUTE : 0; | ||
478 | snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, HDA_AMP_MUTE, bits); | ||
479 | } | ||
480 | |||
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index c2c65f63bf06..7a8fcc4c15f8 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -19,6 +19,7 @@ | |||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <linux/mm.h> | ||
22 | #include <linux/init.h> | 23 | #include <linux/init.h> |
23 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
24 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
@@ -1759,7 +1760,11 @@ static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info, | |||
1759 | parm = ch ? AC_AMP_SET_RIGHT : AC_AMP_SET_LEFT; | 1760 | parm = ch ? AC_AMP_SET_RIGHT : AC_AMP_SET_LEFT; |
1760 | parm |= direction == HDA_OUTPUT ? AC_AMP_SET_OUTPUT : AC_AMP_SET_INPUT; | 1761 | parm |= direction == HDA_OUTPUT ? AC_AMP_SET_OUTPUT : AC_AMP_SET_INPUT; |
1761 | parm |= index << AC_AMP_SET_INDEX_SHIFT; | 1762 | parm |= index << AC_AMP_SET_INDEX_SHIFT; |
1762 | parm |= val; | 1763 | if ((val & HDA_AMP_MUTE) && !(info->amp_caps & AC_AMPCAP_MUTE) && |
1764 | (info->amp_caps & AC_AMPCAP_MIN_MUTE)) | ||
1765 | ; /* set the zero value as a fake mute */ | ||
1766 | else | ||
1767 | parm |= val; | ||
1763 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm); | 1768 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm); |
1764 | info->vol[ch] = val; | 1769 | info->vol[ch] = val; |
1765 | } | 1770 | } |
@@ -2026,7 +2031,7 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, | |||
2026 | val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT); | 2031 | val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT); |
2027 | val1 += ofs; | 2032 | val1 += ofs; |
2028 | val1 = ((int)val1) * ((int)val2); | 2033 | val1 = ((int)val1) * ((int)val2); |
2029 | if (min_mute) | 2034 | if (min_mute || (caps & AC_AMPCAP_MIN_MUTE)) |
2030 | val2 |= TLV_DB_SCALE_MUTE; | 2035 | val2 |= TLV_DB_SCALE_MUTE; |
2031 | if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv)) | 2036 | if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv)) |
2032 | return -EFAULT; | 2037 | return -EFAULT; |
@@ -2300,7 +2305,7 @@ typedef int (*map_slave_func_t)(void *, struct snd_kcontrol *); | |||
2300 | 2305 | ||
2301 | /* apply the function to all matching slave ctls in the mixer list */ | 2306 | /* apply the function to all matching slave ctls in the mixer list */ |
2302 | static int map_slaves(struct hda_codec *codec, const char * const *slaves, | 2307 | static int map_slaves(struct hda_codec *codec, const char * const *slaves, |
2303 | map_slave_func_t func, void *data) | 2308 | const char *suffix, map_slave_func_t func, void *data) |
2304 | { | 2309 | { |
2305 | struct hda_nid_item *items; | 2310 | struct hda_nid_item *items; |
2306 | const char * const *s; | 2311 | const char * const *s; |
@@ -2313,7 +2318,14 @@ static int map_slaves(struct hda_codec *codec, const char * const *slaves, | |||
2313 | sctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER) | 2318 | sctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER) |
2314 | continue; | 2319 | continue; |
2315 | for (s = slaves; *s; s++) { | 2320 | for (s = slaves; *s; s++) { |
2316 | if (!strcmp(sctl->id.name, *s)) { | 2321 | char tmpname[sizeof(sctl->id.name)]; |
2322 | const char *name = *s; | ||
2323 | if (suffix) { | ||
2324 | snprintf(tmpname, sizeof(tmpname), "%s %s", | ||
2325 | name, suffix); | ||
2326 | name = tmpname; | ||
2327 | } | ||
2328 | if (!strcmp(sctl->id.name, name)) { | ||
2317 | err = func(data, sctl); | 2329 | err = func(data, sctl); |
2318 | if (err) | 2330 | if (err) |
2319 | return err; | 2331 | return err; |
@@ -2329,12 +2341,65 @@ static int check_slave_present(void *data, struct snd_kcontrol *sctl) | |||
2329 | return 1; | 2341 | return 1; |
2330 | } | 2342 | } |
2331 | 2343 | ||
2344 | /* guess the value corresponding to 0dB */ | ||
2345 | static int get_kctl_0dB_offset(struct snd_kcontrol *kctl) | ||
2346 | { | ||
2347 | int _tlv[4]; | ||
2348 | const int *tlv = NULL; | ||
2349 | int val = -1; | ||
2350 | |||
2351 | if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { | ||
2352 | /* FIXME: set_fs() hack for obtaining user-space TLV data */ | ||
2353 | mm_segment_t fs = get_fs(); | ||
2354 | set_fs(get_ds()); | ||
2355 | if (!kctl->tlv.c(kctl, 0, sizeof(_tlv), _tlv)) | ||
2356 | tlv = _tlv; | ||
2357 | set_fs(fs); | ||
2358 | } else if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_READ) | ||
2359 | tlv = kctl->tlv.p; | ||
2360 | if (tlv && tlv[0] == SNDRV_CTL_TLVT_DB_SCALE) | ||
2361 | val = -tlv[2] / tlv[3]; | ||
2362 | return val; | ||
2363 | } | ||
2364 | |||
2365 | /* call kctl->put with the given value(s) */ | ||
2366 | static int put_kctl_with_value(struct snd_kcontrol *kctl, int val) | ||
2367 | { | ||
2368 | struct snd_ctl_elem_value *ucontrol; | ||
2369 | ucontrol = kzalloc(sizeof(*ucontrol), GFP_KERNEL); | ||
2370 | if (!ucontrol) | ||
2371 | return -ENOMEM; | ||
2372 | ucontrol->value.integer.value[0] = val; | ||
2373 | ucontrol->value.integer.value[1] = val; | ||
2374 | kctl->put(kctl, ucontrol); | ||
2375 | kfree(ucontrol); | ||
2376 | return 0; | ||
2377 | } | ||
2378 | |||
2379 | /* initialize the slave volume with 0dB */ | ||
2380 | static int init_slave_0dB(void *data, struct snd_kcontrol *slave) | ||
2381 | { | ||
2382 | int offset = get_kctl_0dB_offset(slave); | ||
2383 | if (offset > 0) | ||
2384 | put_kctl_with_value(slave, offset); | ||
2385 | return 0; | ||
2386 | } | ||
2387 | |||
2388 | /* unmute the slave */ | ||
2389 | static int init_slave_unmute(void *data, struct snd_kcontrol *slave) | ||
2390 | { | ||
2391 | return put_kctl_with_value(slave, 1); | ||
2392 | } | ||
2393 | |||
2332 | /** | 2394 | /** |
2333 | * snd_hda_add_vmaster - create a virtual master control and add slaves | 2395 | * snd_hda_add_vmaster - create a virtual master control and add slaves |
2334 | * @codec: HD-audio codec | 2396 | * @codec: HD-audio codec |
2335 | * @name: vmaster control name | 2397 | * @name: vmaster control name |
2336 | * @tlv: TLV data (optional) | 2398 | * @tlv: TLV data (optional) |
2337 | * @slaves: slave control names (optional) | 2399 | * @slaves: slave control names (optional) |
2400 | * @suffix: suffix string to each slave name (optional) | ||
2401 | * @init_slave_vol: initialize slaves to unmute/0dB | ||
2402 | * @ctl_ret: store the vmaster kcontrol in return | ||
2338 | * | 2403 | * |
2339 | * Create a virtual master control with the given name. The TLV data | 2404 | * Create a virtual master control with the given name. The TLV data |
2340 | * must be either NULL or a valid data. | 2405 | * must be either NULL or a valid data. |
@@ -2345,13 +2410,18 @@ static int check_slave_present(void *data, struct snd_kcontrol *sctl) | |||
2345 | * | 2410 | * |
2346 | * This function returns zero if successful or a negative error code. | 2411 | * This function returns zero if successful or a negative error code. |
2347 | */ | 2412 | */ |
2348 | int snd_hda_add_vmaster(struct hda_codec *codec, char *name, | 2413 | int __snd_hda_add_vmaster(struct hda_codec *codec, char *name, |
2349 | unsigned int *tlv, const char * const *slaves) | 2414 | unsigned int *tlv, const char * const *slaves, |
2415 | const char *suffix, bool init_slave_vol, | ||
2416 | struct snd_kcontrol **ctl_ret) | ||
2350 | { | 2417 | { |
2351 | struct snd_kcontrol *kctl; | 2418 | struct snd_kcontrol *kctl; |
2352 | int err; | 2419 | int err; |
2353 | 2420 | ||
2354 | err = map_slaves(codec, slaves, check_slave_present, NULL); | 2421 | if (ctl_ret) |
2422 | *ctl_ret = NULL; | ||
2423 | |||
2424 | err = map_slaves(codec, slaves, suffix, check_slave_present, NULL); | ||
2355 | if (err != 1) { | 2425 | if (err != 1) { |
2356 | snd_printdd("No slave found for %s\n", name); | 2426 | snd_printdd("No slave found for %s\n", name); |
2357 | return 0; | 2427 | return 0; |
@@ -2363,13 +2433,119 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name, | |||
2363 | if (err < 0) | 2433 | if (err < 0) |
2364 | return err; | 2434 | return err; |
2365 | 2435 | ||
2366 | err = map_slaves(codec, slaves, (map_slave_func_t)snd_ctl_add_slave, | 2436 | err = map_slaves(codec, slaves, suffix, |
2367 | kctl); | 2437 | (map_slave_func_t)snd_ctl_add_slave, kctl); |
2368 | if (err < 0) | 2438 | if (err < 0) |
2369 | return err; | 2439 | return err; |
2440 | |||
2441 | /* init with master mute & zero volume */ | ||
2442 | put_kctl_with_value(kctl, 0); | ||
2443 | if (init_slave_vol) | ||
2444 | map_slaves(codec, slaves, suffix, | ||
2445 | tlv ? init_slave_0dB : init_slave_unmute, kctl); | ||
2446 | |||
2447 | if (ctl_ret) | ||
2448 | *ctl_ret = kctl; | ||
2449 | return 0; | ||
2450 | } | ||
2451 | EXPORT_SYMBOL_HDA(__snd_hda_add_vmaster); | ||
2452 | |||
2453 | /* | ||
2454 | * mute-LED control using vmaster | ||
2455 | */ | ||
2456 | static int vmaster_mute_mode_info(struct snd_kcontrol *kcontrol, | ||
2457 | struct snd_ctl_elem_info *uinfo) | ||
2458 | { | ||
2459 | static const char * const texts[] = { | ||
2460 | "Off", "On", "Follow Master" | ||
2461 | }; | ||
2462 | unsigned int index; | ||
2463 | |||
2464 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
2465 | uinfo->count = 1; | ||
2466 | uinfo->value.enumerated.items = 3; | ||
2467 | index = uinfo->value.enumerated.item; | ||
2468 | if (index >= 3) | ||
2469 | index = 2; | ||
2470 | strcpy(uinfo->value.enumerated.name, texts[index]); | ||
2471 | return 0; | ||
2472 | } | ||
2473 | |||
2474 | static int vmaster_mute_mode_get(struct snd_kcontrol *kcontrol, | ||
2475 | struct snd_ctl_elem_value *ucontrol) | ||
2476 | { | ||
2477 | struct hda_vmaster_mute_hook *hook = snd_kcontrol_chip(kcontrol); | ||
2478 | ucontrol->value.enumerated.item[0] = hook->mute_mode; | ||
2370 | return 0; | 2479 | return 0; |
2371 | } | 2480 | } |
2372 | EXPORT_SYMBOL_HDA(snd_hda_add_vmaster); | 2481 | |
2482 | static int vmaster_mute_mode_put(struct snd_kcontrol *kcontrol, | ||
2483 | struct snd_ctl_elem_value *ucontrol) | ||
2484 | { | ||
2485 | struct hda_vmaster_mute_hook *hook = snd_kcontrol_chip(kcontrol); | ||
2486 | unsigned int old_mode = hook->mute_mode; | ||
2487 | |||
2488 | hook->mute_mode = ucontrol->value.enumerated.item[0]; | ||
2489 | if (hook->mute_mode > HDA_VMUTE_FOLLOW_MASTER) | ||
2490 | hook->mute_mode = HDA_VMUTE_FOLLOW_MASTER; | ||
2491 | if (old_mode == hook->mute_mode) | ||
2492 | return 0; | ||
2493 | snd_hda_sync_vmaster_hook(hook); | ||
2494 | return 1; | ||
2495 | } | ||
2496 | |||
2497 | static struct snd_kcontrol_new vmaster_mute_mode = { | ||
2498 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2499 | .name = "Mute-LED Mode", | ||
2500 | .info = vmaster_mute_mode_info, | ||
2501 | .get = vmaster_mute_mode_get, | ||
2502 | .put = vmaster_mute_mode_put, | ||
2503 | }; | ||
2504 | |||
2505 | /* | ||
2506 | * Add a mute-LED hook with the given vmaster switch kctl | ||
2507 | * "Mute-LED Mode" control is automatically created and associated with | ||
2508 | * the given hook. | ||
2509 | */ | ||
2510 | int snd_hda_add_vmaster_hook(struct hda_codec *codec, | ||
2511 | struct hda_vmaster_mute_hook *hook, | ||
2512 | bool expose_enum_ctl) | ||
2513 | { | ||
2514 | struct snd_kcontrol *kctl; | ||
2515 | |||
2516 | if (!hook->hook || !hook->sw_kctl) | ||
2517 | return 0; | ||
2518 | snd_ctl_add_vmaster_hook(hook->sw_kctl, hook->hook, codec); | ||
2519 | hook->codec = codec; | ||
2520 | hook->mute_mode = HDA_VMUTE_FOLLOW_MASTER; | ||
2521 | if (!expose_enum_ctl) | ||
2522 | return 0; | ||
2523 | kctl = snd_ctl_new1(&vmaster_mute_mode, hook); | ||
2524 | if (!kctl) | ||
2525 | return -ENOMEM; | ||
2526 | return snd_hda_ctl_add(codec, 0, kctl); | ||
2527 | } | ||
2528 | EXPORT_SYMBOL_HDA(snd_hda_add_vmaster_hook); | ||
2529 | |||
2530 | /* | ||
2531 | * Call the hook with the current value for synchronization | ||
2532 | * Should be called in init callback | ||
2533 | */ | ||
2534 | void snd_hda_sync_vmaster_hook(struct hda_vmaster_mute_hook *hook) | ||
2535 | { | ||
2536 | if (!hook->hook || !hook->codec) | ||
2537 | return; | ||
2538 | switch (hook->mute_mode) { | ||
2539 | case HDA_VMUTE_FOLLOW_MASTER: | ||
2540 | snd_ctl_sync_vmaster_hook(hook->sw_kctl); | ||
2541 | break; | ||
2542 | default: | ||
2543 | hook->hook(hook->codec, hook->mute_mode); | ||
2544 | break; | ||
2545 | } | ||
2546 | } | ||
2547 | EXPORT_SYMBOL_HDA(snd_hda_sync_vmaster_hook); | ||
2548 | |||
2373 | 2549 | ||
2374 | /** | 2550 | /** |
2375 | * snd_hda_mixer_amp_switch_info - Info callback for a standard AMP mixer switch | 2551 | * snd_hda_mixer_amp_switch_info - Info callback for a standard AMP mixer switch |
@@ -5114,7 +5290,7 @@ static int fill_audio_out_name(struct hda_codec *codec, hda_nid_t nid, | |||
5114 | const char *pfx = "", *sfx = ""; | 5290 | const char *pfx = "", *sfx = ""; |
5115 | 5291 | ||
5116 | /* handle as a speaker if it's a fixed line-out */ | 5292 | /* handle as a speaker if it's a fixed line-out */ |
5117 | if (!strcmp(name, "Line-Out") && attr == INPUT_PIN_ATTR_INT) | 5293 | if (!strcmp(name, "Line Out") && attr == INPUT_PIN_ATTR_INT) |
5118 | name = "Speaker"; | 5294 | name = "Speaker"; |
5119 | /* check the location */ | 5295 | /* check the location */ |
5120 | switch (attr) { | 5296 | switch (attr) { |
@@ -5173,7 +5349,7 @@ int snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid, | |||
5173 | 5349 | ||
5174 | switch (get_defcfg_device(def_conf)) { | 5350 | switch (get_defcfg_device(def_conf)) { |
5175 | case AC_JACK_LINE_OUT: | 5351 | case AC_JACK_LINE_OUT: |
5176 | return fill_audio_out_name(codec, nid, cfg, "Line-Out", | 5352 | return fill_audio_out_name(codec, nid, cfg, "Line Out", |
5177 | label, maxlen, indexp); | 5353 | label, maxlen, indexp); |
5178 | case AC_JACK_SPEAKER: | 5354 | case AC_JACK_SPEAKER: |
5179 | return fill_audio_out_name(codec, nid, cfg, "Speaker", | 5355 | return fill_audio_out_name(codec, nid, cfg, "Speaker", |
@@ -5268,6 +5444,10 @@ int snd_hda_suspend(struct hda_bus *bus) | |||
5268 | list_for_each_entry(codec, &bus->codec_list, list) { | 5444 | list_for_each_entry(codec, &bus->codec_list, list) { |
5269 | if (hda_codec_is_power_on(codec)) | 5445 | if (hda_codec_is_power_on(codec)) |
5270 | hda_call_codec_suspend(codec); | 5446 | hda_call_codec_suspend(codec); |
5447 | else /* forcibly change the power to D3 even if not used */ | ||
5448 | hda_set_power_state(codec, | ||
5449 | codec->afg ? codec->afg : codec->mfg, | ||
5450 | AC_PWRST_D3); | ||
5271 | if (codec->patch_ops.post_suspend) | 5451 | if (codec->patch_ops.post_suspend) |
5272 | codec->patch_ops.post_suspend(codec); | 5452 | codec->patch_ops.post_suspend(codec); |
5273 | } | 5453 | } |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index e9f71dc0d464..9a9f372e1be4 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -298,6 +298,9 @@ enum { | |||
298 | #define AC_AMPCAP_MUTE (1<<31) /* mute capable */ | 298 | #define AC_AMPCAP_MUTE (1<<31) /* mute capable */ |
299 | #define AC_AMPCAP_MUTE_SHIFT 31 | 299 | #define AC_AMPCAP_MUTE_SHIFT 31 |
300 | 300 | ||
301 | /* driver-specific amp-caps: using bits 24-30 */ | ||
302 | #define AC_AMPCAP_MIN_MUTE (1 << 30) /* min-volume = mute */ | ||
303 | |||
301 | /* Connection list */ | 304 | /* Connection list */ |
302 | #define AC_CLIST_LENGTH (0x7f<<0) | 305 | #define AC_CLIST_LENGTH (0x7f<<0) |
303 | #define AC_CLIST_LONG (1<<7) | 306 | #define AC_CLIST_LONG (1<<7) |
@@ -852,6 +855,7 @@ struct hda_codec { | |||
852 | unsigned int pins_shutup:1; /* pins are shut up */ | 855 | unsigned int pins_shutup:1; /* pins are shut up */ |
853 | unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */ | 856 | unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */ |
854 | unsigned int ignore_misc_bit:1; /* ignore MISC_NO_PRESENCE bit */ | 857 | unsigned int ignore_misc_bit:1; /* ignore MISC_NO_PRESENCE bit */ |
858 | unsigned int no_jack_detect:1; /* Machine has no jack-detection */ | ||
855 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 859 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
856 | unsigned int power_on :1; /* current (global) power-state */ | 860 | unsigned int power_on :1; /* current (global) power-state */ |
857 | unsigned int power_transition :1; /* power-state in transition */ | 861 | unsigned int power_transition :1; /* power-state in transition */ |
diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index c1da422e085a..b58b4b1687fa 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c | |||
@@ -385,8 +385,8 @@ error: | |||
385 | static void hdmi_print_pcm_rates(int pcm, char *buf, int buflen) | 385 | static void hdmi_print_pcm_rates(int pcm, char *buf, int buflen) |
386 | { | 386 | { |
387 | static unsigned int alsa_rates[] = { | 387 | static unsigned int alsa_rates[] = { |
388 | 5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200, | 388 | 5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, |
389 | 96000, 176400, 192000, 384000 | 389 | 88200, 96000, 176400, 192000, 384000 |
390 | }; | 390 | }; |
391 | int i, j; | 391 | int i, j; |
392 | 392 | ||
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 95dfb6874941..c19e71a94e1b 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -84,7 +84,7 @@ module_param_array(model, charp, NULL, 0444); | |||
84 | MODULE_PARM_DESC(model, "Use the given board model."); | 84 | MODULE_PARM_DESC(model, "Use the given board model."); |
85 | module_param_array(position_fix, int, NULL, 0444); | 85 | module_param_array(position_fix, int, NULL, 0444); |
86 | MODULE_PARM_DESC(position_fix, "DMA pointer read method." | 86 | MODULE_PARM_DESC(position_fix, "DMA pointer read method." |
87 | "(0 = auto, 1 = LPIB, 2 = POSBUF, 3 = VIACOMBO)."); | 87 | "(0 = auto, 1 = LPIB, 2 = POSBUF, 3 = VIACOMBO, 4 = COMBO)."); |
88 | module_param_array(bdl_pos_adj, int, NULL, 0644); | 88 | module_param_array(bdl_pos_adj, int, NULL, 0644); |
89 | MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset."); | 89 | MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset."); |
90 | module_param_array(probe_mask, int, NULL, 0444); | 90 | module_param_array(probe_mask, int, NULL, 0444); |
@@ -94,7 +94,7 @@ MODULE_PARM_DESC(probe_only, "Only probing and no codec initialization."); | |||
94 | module_param(single_cmd, bool, 0444); | 94 | module_param(single_cmd, bool, 0444); |
95 | MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs " | 95 | MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs " |
96 | "(for debugging only)."); | 96 | "(for debugging only)."); |
97 | module_param(enable_msi, int, 0444); | 97 | module_param(enable_msi, bint, 0444); |
98 | MODULE_PARM_DESC(enable_msi, "Enable Message Signaled Interrupt (MSI)"); | 98 | MODULE_PARM_DESC(enable_msi, "Enable Message Signaled Interrupt (MSI)"); |
99 | #ifdef CONFIG_SND_HDA_PATCH_LOADER | 99 | #ifdef CONFIG_SND_HDA_PATCH_LOADER |
100 | module_param_array(patch, charp, NULL, 0444); | 100 | module_param_array(patch, charp, NULL, 0444); |
@@ -121,8 +121,8 @@ module_param(power_save_controller, bool, 0644); | |||
121 | MODULE_PARM_DESC(power_save_controller, "Reset controller in power save mode."); | 121 | MODULE_PARM_DESC(power_save_controller, "Reset controller in power save mode."); |
122 | #endif | 122 | #endif |
123 | 123 | ||
124 | static bool align_buffer_size = 1; | 124 | static int align_buffer_size = -1; |
125 | module_param(align_buffer_size, bool, 0644); | 125 | module_param(align_buffer_size, bint, 0644); |
126 | MODULE_PARM_DESC(align_buffer_size, | 126 | MODULE_PARM_DESC(align_buffer_size, |
127 | "Force buffer and period sizes to be multiple of 128 bytes."); | 127 | "Force buffer and period sizes to be multiple of 128 bytes."); |
128 | 128 | ||
@@ -148,6 +148,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6}," | |||
148 | "{Intel, PCH}," | 148 | "{Intel, PCH}," |
149 | "{Intel, CPT}," | 149 | "{Intel, CPT}," |
150 | "{Intel, PPT}," | 150 | "{Intel, PPT}," |
151 | "{Intel, LPT}," | ||
151 | "{Intel, PBG}," | 152 | "{Intel, PBG}," |
152 | "{Intel, SCH}," | 153 | "{Intel, SCH}," |
153 | "{ATI, SB450}," | 154 | "{ATI, SB450}," |
@@ -329,6 +330,7 @@ enum { | |||
329 | POS_FIX_LPIB, | 330 | POS_FIX_LPIB, |
330 | POS_FIX_POSBUF, | 331 | POS_FIX_POSBUF, |
331 | POS_FIX_VIACOMBO, | 332 | POS_FIX_VIACOMBO, |
333 | POS_FIX_COMBO, | ||
332 | }; | 334 | }; |
333 | 335 | ||
334 | /* Defines for ATI HD Audio support in SB450 south bridge */ | 336 | /* Defines for ATI HD Audio support in SB450 south bridge */ |
@@ -515,6 +517,7 @@ enum { | |||
515 | #define AZX_DCAPS_SYNC_WRITE (1 << 19) /* sync each cmd write */ | 517 | #define AZX_DCAPS_SYNC_WRITE (1 << 19) /* sync each cmd write */ |
516 | #define AZX_DCAPS_OLD_SSYNC (1 << 20) /* Old SSYNC reg for ICH */ | 518 | #define AZX_DCAPS_OLD_SSYNC (1 << 20) /* Old SSYNC reg for ICH */ |
517 | #define AZX_DCAPS_BUFSIZE (1 << 21) /* no buffer size alignment */ | 519 | #define AZX_DCAPS_BUFSIZE (1 << 21) /* no buffer size alignment */ |
520 | #define AZX_DCAPS_ALIGN_BUFSIZE (1 << 22) /* buffer size alignment */ | ||
518 | 521 | ||
519 | /* quirks for ATI SB / AMD Hudson */ | 522 | /* quirks for ATI SB / AMD Hudson */ |
520 | #define AZX_DCAPS_PRESET_ATI_SB \ | 523 | #define AZX_DCAPS_PRESET_ATI_SB \ |
@@ -527,7 +530,8 @@ enum { | |||
527 | 530 | ||
528 | /* quirks for Nvidia */ | 531 | /* quirks for Nvidia */ |
529 | #define AZX_DCAPS_PRESET_NVIDIA \ | 532 | #define AZX_DCAPS_PRESET_NVIDIA \ |
530 | (AZX_DCAPS_NVIDIA_SNOOP | AZX_DCAPS_RIRB_DELAY | AZX_DCAPS_NO_MSI) | 533 | (AZX_DCAPS_NVIDIA_SNOOP | AZX_DCAPS_RIRB_DELAY | AZX_DCAPS_NO_MSI |\ |
534 | AZX_DCAPS_ALIGN_BUFSIZE) | ||
531 | 535 | ||
532 | static char *driver_short_names[] __devinitdata = { | 536 | static char *driver_short_names[] __devinitdata = { |
533 | [AZX_DRIVER_ICH] = "HDA Intel", | 537 | [AZX_DRIVER_ICH] = "HDA Intel", |
@@ -2347,17 +2351,6 @@ static void azx_power_notify(struct hda_bus *bus) | |||
2347 | * power management | 2351 | * power management |
2348 | */ | 2352 | */ |
2349 | 2353 | ||
2350 | static int snd_hda_codecs_inuse(struct hda_bus *bus) | ||
2351 | { | ||
2352 | struct hda_codec *codec; | ||
2353 | |||
2354 | list_for_each_entry(codec, &bus->codec_list, list) { | ||
2355 | if (snd_hda_codec_needs_resume(codec)) | ||
2356 | return 1; | ||
2357 | } | ||
2358 | return 0; | ||
2359 | } | ||
2360 | |||
2361 | static int azx_suspend(struct pci_dev *pci, pm_message_t state) | 2354 | static int azx_suspend(struct pci_dev *pci, pm_message_t state) |
2362 | { | 2355 | { |
2363 | struct snd_card *card = pci_get_drvdata(pci); | 2356 | struct snd_card *card = pci_get_drvdata(pci); |
@@ -2404,8 +2397,7 @@ static int azx_resume(struct pci_dev *pci) | |||
2404 | return -EIO; | 2397 | return -EIO; |
2405 | azx_init_pci(chip); | 2398 | azx_init_pci(chip); |
2406 | 2399 | ||
2407 | if (snd_hda_codecs_inuse(chip->bus)) | 2400 | azx_init_chip(chip, 1); |
2408 | azx_init_chip(chip, 1); | ||
2409 | 2401 | ||
2410 | snd_hda_resume(chip->bus); | 2402 | snd_hda_resume(chip->bus); |
2411 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 2403 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
@@ -2517,6 +2509,7 @@ static int __devinit check_position_fix(struct azx *chip, int fix) | |||
2517 | case POS_FIX_LPIB: | 2509 | case POS_FIX_LPIB: |
2518 | case POS_FIX_POSBUF: | 2510 | case POS_FIX_POSBUF: |
2519 | case POS_FIX_VIACOMBO: | 2511 | case POS_FIX_VIACOMBO: |
2512 | case POS_FIX_COMBO: | ||
2520 | return fix; | 2513 | return fix; |
2521 | } | 2514 | } |
2522 | 2515 | ||
@@ -2696,6 +2689,12 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
2696 | 2689 | ||
2697 | chip->position_fix[0] = chip->position_fix[1] = | 2690 | chip->position_fix[0] = chip->position_fix[1] = |
2698 | check_position_fix(chip, position_fix[dev]); | 2691 | check_position_fix(chip, position_fix[dev]); |
2692 | /* combo mode uses LPIB for playback */ | ||
2693 | if (chip->position_fix[0] == POS_FIX_COMBO) { | ||
2694 | chip->position_fix[0] = POS_FIX_LPIB; | ||
2695 | chip->position_fix[1] = POS_FIX_AUTO; | ||
2696 | } | ||
2697 | |||
2699 | check_probe_mask(chip, dev); | 2698 | check_probe_mask(chip, dev); |
2700 | 2699 | ||
2701 | chip->single_cmd = single_cmd; | 2700 | chip->single_cmd = single_cmd; |
@@ -2774,9 +2773,16 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
2774 | } | 2773 | } |
2775 | 2774 | ||
2776 | /* disable buffer size rounding to 128-byte multiples if supported */ | 2775 | /* disable buffer size rounding to 128-byte multiples if supported */ |
2777 | chip->align_buffer_size = align_buffer_size; | 2776 | if (align_buffer_size >= 0) |
2778 | if (chip->driver_caps & AZX_DCAPS_BUFSIZE) | 2777 | chip->align_buffer_size = !!align_buffer_size; |
2779 | chip->align_buffer_size = 0; | 2778 | else { |
2779 | if (chip->driver_caps & AZX_DCAPS_BUFSIZE) | ||
2780 | chip->align_buffer_size = 0; | ||
2781 | else if (chip->driver_caps & AZX_DCAPS_ALIGN_BUFSIZE) | ||
2782 | chip->align_buffer_size = 1; | ||
2783 | else | ||
2784 | chip->align_buffer_size = 1; | ||
2785 | } | ||
2780 | 2786 | ||
2781 | /* allow 64bit DMA address if supported by H/W */ | 2787 | /* allow 64bit DMA address if supported by H/W */ |
2782 | if ((gcap & ICH6_GCAP_64OK) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64))) | 2788 | if ((gcap & ICH6_GCAP_64OK) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64))) |
@@ -2992,6 +2998,10 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { | |||
2992 | { PCI_DEVICE(0x8086, 0x1e20), | 2998 | { PCI_DEVICE(0x8086, 0x1e20), |
2993 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | | 2999 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | |
2994 | AZX_DCAPS_BUFSIZE}, | 3000 | AZX_DCAPS_BUFSIZE}, |
3001 | /* Lynx Point */ | ||
3002 | { PCI_DEVICE(0x8086, 0x8c20), | ||
3003 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | | ||
3004 | AZX_DCAPS_BUFSIZE}, | ||
2995 | /* SCH */ | 3005 | /* SCH */ |
2996 | { PCI_DEVICE(0x8086, 0x811b), | 3006 | { PCI_DEVICE(0x8086, 0x811b), |
2997 | .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | | 3007 | .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | |
diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c index 9d819c4b4923..d68948499fbc 100644 --- a/sound/pci/hda/hda_jack.c +++ b/sound/pci/hda/hda_jack.c | |||
@@ -19,6 +19,22 @@ | |||
19 | #include "hda_local.h" | 19 | #include "hda_local.h" |
20 | #include "hda_jack.h" | 20 | #include "hda_jack.h" |
21 | 21 | ||
22 | bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid) | ||
23 | { | ||
24 | if (codec->no_jack_detect) | ||
25 | return false; | ||
26 | if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT)) | ||
27 | return false; | ||
28 | if (!codec->ignore_misc_bit && | ||
29 | (get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) & | ||
30 | AC_DEFCFG_MISC_NO_PRESENCE)) | ||
31 | return false; | ||
32 | if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP)) | ||
33 | return false; | ||
34 | return true; | ||
35 | } | ||
36 | EXPORT_SYMBOL_HDA(is_jack_detectable); | ||
37 | |||
22 | /* execute pin sense measurement */ | 38 | /* execute pin sense measurement */ |
23 | static u32 read_pin_sense(struct hda_codec *codec, hda_nid_t nid) | 39 | static u32 read_pin_sense(struct hda_codec *codec, hda_nid_t nid) |
24 | { | 40 | { |
diff --git a/sound/pci/hda/hda_jack.h b/sound/pci/hda/hda_jack.h index f8f97c71c9c1..c66655cf413a 100644 --- a/sound/pci/hda/hda_jack.h +++ b/sound/pci/hda/hda_jack.h | |||
@@ -62,18 +62,7 @@ int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid, | |||
62 | u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid); | 62 | u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid); |
63 | int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid); | 63 | int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid); |
64 | 64 | ||
65 | static inline bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid) | 65 | bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid); |
66 | { | ||
67 | if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT)) | ||
68 | return false; | ||
69 | if (!codec->ignore_misc_bit && | ||
70 | (get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) & | ||
71 | AC_DEFCFG_MISC_NO_PRESENCE)) | ||
72 | return false; | ||
73 | if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP)) | ||
74 | return false; | ||
75 | return true; | ||
76 | } | ||
77 | 66 | ||
78 | int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, | 67 | int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, |
79 | const char *name, int idx); | 68 | const char *name, int idx); |
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index aca8d3193b95..0ec9248165bc 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -139,10 +139,36 @@ void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir, | |||
139 | unsigned int *tlv); | 139 | unsigned int *tlv); |
140 | struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, | 140 | struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, |
141 | const char *name); | 141 | const char *name); |
142 | int snd_hda_add_vmaster(struct hda_codec *codec, char *name, | 142 | int __snd_hda_add_vmaster(struct hda_codec *codec, char *name, |
143 | unsigned int *tlv, const char * const *slaves); | 143 | unsigned int *tlv, const char * const *slaves, |
144 | const char *suffix, bool init_slave_vol, | ||
145 | struct snd_kcontrol **ctl_ret); | ||
146 | #define snd_hda_add_vmaster(codec, name, tlv, slaves, suffix) \ | ||
147 | __snd_hda_add_vmaster(codec, name, tlv, slaves, suffix, true, NULL) | ||
144 | int snd_hda_codec_reset(struct hda_codec *codec); | 148 | int snd_hda_codec_reset(struct hda_codec *codec); |
145 | 149 | ||
150 | enum { | ||
151 | HDA_VMUTE_OFF, | ||
152 | HDA_VMUTE_ON, | ||
153 | HDA_VMUTE_FOLLOW_MASTER, | ||
154 | }; | ||
155 | |||
156 | struct hda_vmaster_mute_hook { | ||
157 | /* below two fields must be filled by the caller of | ||
158 | * snd_hda_add_vmaster_hook() beforehand | ||
159 | */ | ||
160 | struct snd_kcontrol *sw_kctl; | ||
161 | void (*hook)(void *, int); | ||
162 | /* below are initialized automatically */ | ||
163 | unsigned int mute_mode; /* HDA_VMUTE_XXX */ | ||
164 | struct hda_codec *codec; | ||
165 | }; | ||
166 | |||
167 | int snd_hda_add_vmaster_hook(struct hda_codec *codec, | ||
168 | struct hda_vmaster_mute_hook *hook, | ||
169 | bool expose_enum_ctl); | ||
170 | void snd_hda_sync_vmaster_hook(struct hda_vmaster_mute_hook *hook); | ||
171 | |||
146 | /* amp value bits */ | 172 | /* amp value bits */ |
147 | #define HDA_AMP_MUTE 0x80 | 173 | #define HDA_AMP_MUTE 0x80 |
148 | #define HDA_AMP_UNMUTE 0x00 | 174 | #define HDA_AMP_UNMUTE 0x00 |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 9cb14b42dfff..7143393927da 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -82,6 +82,7 @@ struct ad198x_spec { | |||
82 | unsigned int inv_jack_detect: 1;/* inverted jack-detection */ | 82 | unsigned int inv_jack_detect: 1;/* inverted jack-detection */ |
83 | unsigned int inv_eapd: 1; /* inverted EAPD implementation */ | 83 | unsigned int inv_eapd: 1; /* inverted EAPD implementation */ |
84 | unsigned int analog_beep: 1; /* analog beep input present */ | 84 | unsigned int analog_beep: 1; /* analog beep input present */ |
85 | unsigned int avoid_init_slave_vol:1; | ||
85 | 86 | ||
86 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 87 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
87 | struct hda_loopback_check loopback; | 88 | struct hda_loopback_check loopback; |
@@ -137,51 +138,17 @@ static int ad198x_init(struct hda_codec *codec) | |||
137 | return 0; | 138 | return 0; |
138 | } | 139 | } |
139 | 140 | ||
140 | static const char * const ad_slave_vols[] = { | 141 | static const char * const ad_slave_pfxs[] = { |
141 | "Front Playback Volume", | 142 | "Front", "Surround", "Center", "LFE", "Side", |
142 | "Surround Playback Volume", | 143 | "Headphone", "Mono", "Speaker", "IEC958", |
143 | "Center Playback Volume", | ||
144 | "LFE Playback Volume", | ||
145 | "Side Playback Volume", | ||
146 | "Headphone Playback Volume", | ||
147 | "Mono Playback Volume", | ||
148 | "Speaker Playback Volume", | ||
149 | "IEC958 Playback Volume", | ||
150 | NULL | 144 | NULL |
151 | }; | 145 | }; |
152 | 146 | ||
153 | static const char * const ad_slave_sws[] = { | 147 | static const char * const ad1988_6stack_fp_slave_pfxs[] = { |
154 | "Front Playback Switch", | 148 | "Front", "Surround", "Center", "LFE", "Side", "IEC958", |
155 | "Surround Playback Switch", | ||
156 | "Center Playback Switch", | ||
157 | "LFE Playback Switch", | ||
158 | "Side Playback Switch", | ||
159 | "Headphone Playback Switch", | ||
160 | "Mono Playback Switch", | ||
161 | "Speaker Playback Switch", | ||
162 | "IEC958 Playback Switch", | ||
163 | NULL | 149 | NULL |
164 | }; | 150 | }; |
165 | 151 | ||
166 | static const char * const ad1988_6stack_fp_slave_vols[] = { | ||
167 | "Front Playback Volume", | ||
168 | "Surround Playback Volume", | ||
169 | "Center Playback Volume", | ||
170 | "LFE Playback Volume", | ||
171 | "Side Playback Volume", | ||
172 | "IEC958 Playback Volume", | ||
173 | NULL | ||
174 | }; | ||
175 | |||
176 | static const char * const ad1988_6stack_fp_slave_sws[] = { | ||
177 | "Front Playback Switch", | ||
178 | "Surround Playback Switch", | ||
179 | "Center Playback Switch", | ||
180 | "LFE Playback Switch", | ||
181 | "Side Playback Switch", | ||
182 | "IEC958 Playback Switch", | ||
183 | NULL | ||
184 | }; | ||
185 | static void ad198x_free_kctls(struct hda_codec *codec); | 152 | static void ad198x_free_kctls(struct hda_codec *codec); |
186 | 153 | ||
187 | #ifdef CONFIG_SND_HDA_INPUT_BEEP | 154 | #ifdef CONFIG_SND_HDA_INPUT_BEEP |
@@ -257,10 +224,12 @@ static int ad198x_build_controls(struct hda_codec *codec) | |||
257 | unsigned int vmaster_tlv[4]; | 224 | unsigned int vmaster_tlv[4]; |
258 | snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid, | 225 | snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid, |
259 | HDA_OUTPUT, vmaster_tlv); | 226 | HDA_OUTPUT, vmaster_tlv); |
260 | err = snd_hda_add_vmaster(codec, "Master Playback Volume", | 227 | err = __snd_hda_add_vmaster(codec, "Master Playback Volume", |
261 | vmaster_tlv, | 228 | vmaster_tlv, |
262 | (spec->slave_vols ? | 229 | (spec->slave_vols ? |
263 | spec->slave_vols : ad_slave_vols)); | 230 | spec->slave_vols : ad_slave_pfxs), |
231 | "Playback Volume", | ||
232 | !spec->avoid_init_slave_vol, NULL); | ||
264 | if (err < 0) | 233 | if (err < 0) |
265 | return err; | 234 | return err; |
266 | } | 235 | } |
@@ -268,7 +237,8 @@ static int ad198x_build_controls(struct hda_codec *codec) | |||
268 | err = snd_hda_add_vmaster(codec, "Master Playback Switch", | 237 | err = snd_hda_add_vmaster(codec, "Master Playback Switch", |
269 | NULL, | 238 | NULL, |
270 | (spec->slave_sws ? | 239 | (spec->slave_sws ? |
271 | spec->slave_sws : ad_slave_sws)); | 240 | spec->slave_sws : ad_slave_pfxs), |
241 | "Playback Switch"); | ||
272 | if (err < 0) | 242 | if (err < 0) |
273 | return err; | 243 | return err; |
274 | } | 244 | } |
@@ -3385,8 +3355,8 @@ static int patch_ad1988(struct hda_codec *codec) | |||
3385 | 3355 | ||
3386 | if (spec->autocfg.hp_pins[0]) { | 3356 | if (spec->autocfg.hp_pins[0]) { |
3387 | spec->mixers[spec->num_mixers++] = ad1988_hp_mixers; | 3357 | spec->mixers[spec->num_mixers++] = ad1988_hp_mixers; |
3388 | spec->slave_vols = ad1988_6stack_fp_slave_vols; | 3358 | spec->slave_vols = ad1988_6stack_fp_slave_pfxs; |
3389 | spec->slave_sws = ad1988_6stack_fp_slave_sws; | 3359 | spec->slave_sws = ad1988_6stack_fp_slave_pfxs; |
3390 | spec->alt_dac_nid = ad1988_alt_dac_nid; | 3360 | spec->alt_dac_nid = ad1988_alt_dac_nid; |
3391 | spec->stream_analog_alt_playback = | 3361 | spec->stream_analog_alt_playback = |
3392 | &ad198x_pcm_analog_alt_playback; | 3362 | &ad198x_pcm_analog_alt_playback; |
@@ -3594,16 +3564,8 @@ static const struct hda_amp_list ad1884_loopbacks[] = { | |||
3594 | #endif | 3564 | #endif |
3595 | 3565 | ||
3596 | static const char * const ad1884_slave_vols[] = { | 3566 | static const char * const ad1884_slave_vols[] = { |
3597 | "PCM Playback Volume", | 3567 | "PCM", "Mic", "Mono", "Front Mic", "Mic", "CD", |
3598 | "Mic Playback Volume", | 3568 | "Internal Mic", "Docking Mic", /* "Beep", */ "IEC958", |
3599 | "Mono Playback Volume", | ||
3600 | "Front Mic Playback Volume", | ||
3601 | "Mic Playback Volume", | ||
3602 | "CD Playback Volume", | ||
3603 | "Internal Mic Playback Volume", | ||
3604 | "Docking Mic Playback Volume", | ||
3605 | /* "Beep Playback Volume", */ | ||
3606 | "IEC958 Playback Volume", | ||
3607 | NULL | 3569 | NULL |
3608 | }; | 3570 | }; |
3609 | 3571 | ||
@@ -3644,6 +3606,8 @@ static int patch_ad1884(struct hda_codec *codec) | |||
3644 | spec->vmaster_nid = 0x04; | 3606 | spec->vmaster_nid = 0x04; |
3645 | /* we need to cover all playback volumes */ | 3607 | /* we need to cover all playback volumes */ |
3646 | spec->slave_vols = ad1884_slave_vols; | 3608 | spec->slave_vols = ad1884_slave_vols; |
3609 | /* slaves may contain input volumes, so we can't raise to 0dB blindly */ | ||
3610 | spec->avoid_init_slave_vol = 1; | ||
3647 | 3611 | ||
3648 | codec->patch_ops = ad198x_patch_ops; | 3612 | codec->patch_ops = ad198x_patch_ops; |
3649 | 3613 | ||
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 35abe3c62908..21d91d580da8 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c | |||
@@ -728,18 +728,19 @@ static int ca0132_hp_switch_put(struct snd_kcontrol *kcontrol, | |||
728 | 728 | ||
729 | err = chipio_read(codec, REG_CODEC_MUTE, &data); | 729 | err = chipio_read(codec, REG_CODEC_MUTE, &data); |
730 | if (err < 0) | 730 | if (err < 0) |
731 | return err; | 731 | goto exit; |
732 | 732 | ||
733 | /* *valp 0 is mute, 1 is unmute */ | 733 | /* *valp 0 is mute, 1 is unmute */ |
734 | data = (data & 0x7f) | (*valp ? 0 : 0x80); | 734 | data = (data & 0x7f) | (*valp ? 0 : 0x80); |
735 | chipio_write(codec, REG_CODEC_MUTE, data); | 735 | err = chipio_write(codec, REG_CODEC_MUTE, data); |
736 | if (err < 0) | 736 | if (err < 0) |
737 | return err; | 737 | goto exit; |
738 | 738 | ||
739 | spec->curr_hp_switch = *valp; | 739 | spec->curr_hp_switch = *valp; |
740 | 740 | ||
741 | exit: | ||
741 | snd_hda_power_down(codec); | 742 | snd_hda_power_down(codec); |
742 | return 1; | 743 | return err < 0 ? err : 1; |
743 | } | 744 | } |
744 | 745 | ||
745 | static int ca0132_speaker_switch_get(struct snd_kcontrol *kcontrol, | 746 | static int ca0132_speaker_switch_get(struct snd_kcontrol *kcontrol, |
@@ -770,18 +771,19 @@ static int ca0132_speaker_switch_put(struct snd_kcontrol *kcontrol, | |||
770 | 771 | ||
771 | err = chipio_read(codec, REG_CODEC_MUTE, &data); | 772 | err = chipio_read(codec, REG_CODEC_MUTE, &data); |
772 | if (err < 0) | 773 | if (err < 0) |
773 | return err; | 774 | goto exit; |
774 | 775 | ||
775 | /* *valp 0 is mute, 1 is unmute */ | 776 | /* *valp 0 is mute, 1 is unmute */ |
776 | data = (data & 0xef) | (*valp ? 0 : 0x10); | 777 | data = (data & 0xef) | (*valp ? 0 : 0x10); |
777 | chipio_write(codec, REG_CODEC_MUTE, data); | 778 | err = chipio_write(codec, REG_CODEC_MUTE, data); |
778 | if (err < 0) | 779 | if (err < 0) |
779 | return err; | 780 | goto exit; |
780 | 781 | ||
781 | spec->curr_speaker_switch = *valp; | 782 | spec->curr_speaker_switch = *valp; |
782 | 783 | ||
784 | exit: | ||
783 | snd_hda_power_down(codec); | 785 | snd_hda_power_down(codec); |
784 | return 1; | 786 | return err < 0 ? err : 1; |
785 | } | 787 | } |
786 | 788 | ||
787 | static int ca0132_hp_volume_get(struct snd_kcontrol *kcontrol, | 789 | static int ca0132_hp_volume_get(struct snd_kcontrol *kcontrol, |
@@ -819,25 +821,26 @@ static int ca0132_hp_volume_put(struct snd_kcontrol *kcontrol, | |||
819 | 821 | ||
820 | err = chipio_read(codec, REG_CODEC_HP_VOL_L, &data); | 822 | err = chipio_read(codec, REG_CODEC_HP_VOL_L, &data); |
821 | if (err < 0) | 823 | if (err < 0) |
822 | return err; | 824 | goto exit; |
823 | 825 | ||
824 | val = 31 - left_vol; | 826 | val = 31 - left_vol; |
825 | data = (data & 0xe0) | val; | 827 | data = (data & 0xe0) | val; |
826 | chipio_write(codec, REG_CODEC_HP_VOL_L, data); | 828 | err = chipio_write(codec, REG_CODEC_HP_VOL_L, data); |
827 | if (err < 0) | 829 | if (err < 0) |
828 | return err; | 830 | goto exit; |
829 | 831 | ||
830 | val = 31 - right_vol; | 832 | val = 31 - right_vol; |
831 | data = (data & 0xe0) | val; | 833 | data = (data & 0xe0) | val; |
832 | chipio_write(codec, REG_CODEC_HP_VOL_R, data); | 834 | err = chipio_write(codec, REG_CODEC_HP_VOL_R, data); |
833 | if (err < 0) | 835 | if (err < 0) |
834 | return err; | 836 | goto exit; |
835 | 837 | ||
836 | spec->curr_hp_volume[0] = left_vol; | 838 | spec->curr_hp_volume[0] = left_vol; |
837 | spec->curr_hp_volume[1] = right_vol; | 839 | spec->curr_hp_volume[1] = right_vol; |
838 | 840 | ||
841 | exit: | ||
839 | snd_hda_power_down(codec); | 842 | snd_hda_power_down(codec); |
840 | return 1; | 843 | return err < 0 ? err : 1; |
841 | } | 844 | } |
842 | 845 | ||
843 | static int add_hp_switch(struct hda_codec *codec, hda_nid_t nid) | 846 | static int add_hp_switch(struct hda_codec *codec, hda_nid_t nid) |
@@ -936,6 +939,8 @@ static int ca0132_build_controls(struct hda_codec *codec) | |||
936 | if (err < 0) | 939 | if (err < 0) |
937 | return err; | 940 | return err; |
938 | err = add_in_volume(codec, spec->dig_in, "IEC958"); | 941 | err = add_in_volume(codec, spec->dig_in, "IEC958"); |
942 | if (err < 0) | ||
943 | return err; | ||
939 | } | 944 | } |
940 | return 0; | 945 | return 0; |
941 | } | 946 | } |
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index bc5a993d1146..c83ccdba1e5a 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c | |||
@@ -609,7 +609,7 @@ static int add_output(struct hda_codec *codec, hda_nid_t dac, int idx, | |||
609 | "Front Speaker", "Surround Speaker", "Bass Speaker" | 609 | "Front Speaker", "Surround Speaker", "Bass Speaker" |
610 | }; | 610 | }; |
611 | static const char * const line_outs[] = { | 611 | static const char * const line_outs[] = { |
612 | "Front Line-Out", "Surround Line-Out", "Bass Line-Out" | 612 | "Front Line Out", "Surround Line Out", "Bass Line Out" |
613 | }; | 613 | }; |
614 | 614 | ||
615 | fix_volume_caps(codec, dac); | 615 | fix_volume_caps(codec, dac); |
@@ -635,7 +635,7 @@ static int add_output(struct hda_codec *codec, hda_nid_t dac, int idx, | |||
635 | if (num_ctls > 1) | 635 | if (num_ctls > 1) |
636 | name = line_outs[idx]; | 636 | name = line_outs[idx]; |
637 | else | 637 | else |
638 | name = "Line-Out"; | 638 | name = "Line Out"; |
639 | break; | 639 | break; |
640 | } | 640 | } |
641 | 641 | ||
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 51e3ed4527c3..8c6523bbc797 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -70,6 +70,8 @@ struct conexant_spec { | |||
70 | const struct snd_kcontrol_new *mixers[5]; | 70 | const struct snd_kcontrol_new *mixers[5]; |
71 | int num_mixers; | 71 | int num_mixers; |
72 | hda_nid_t vmaster_nid; | 72 | hda_nid_t vmaster_nid; |
73 | struct hda_vmaster_mute_hook vmaster_mute; | ||
74 | bool vmaster_mute_led; | ||
73 | 75 | ||
74 | const struct hda_verb *init_verbs[5]; /* initialization verbs | 76 | const struct hda_verb *init_verbs[5]; /* initialization verbs |
75 | * don't forget NULL | 77 | * don't forget NULL |
@@ -465,21 +467,8 @@ static const struct snd_kcontrol_new cxt_beep_mixer[] = { | |||
465 | }; | 467 | }; |
466 | #endif | 468 | #endif |
467 | 469 | ||
468 | static const char * const slave_vols[] = { | 470 | static const char * const slave_pfxs[] = { |
469 | "Headphone Playback Volume", | 471 | "Headphone", "Speaker", "Front", "Surround", "CLFE", |
470 | "Speaker Playback Volume", | ||
471 | "Front Playback Volume", | ||
472 | "Surround Playback Volume", | ||
473 | "CLFE Playback Volume", | ||
474 | NULL | ||
475 | }; | ||
476 | |||
477 | static const char * const slave_sws[] = { | ||
478 | "Headphone Playback Switch", | ||
479 | "Speaker Playback Switch", | ||
480 | "Front Playback Switch", | ||
481 | "Surround Playback Switch", | ||
482 | "CLFE Playback Switch", | ||
483 | NULL | 472 | NULL |
484 | }; | 473 | }; |
485 | 474 | ||
@@ -519,14 +508,17 @@ static int conexant_build_controls(struct hda_codec *codec) | |||
519 | snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid, | 508 | snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid, |
520 | HDA_OUTPUT, vmaster_tlv); | 509 | HDA_OUTPUT, vmaster_tlv); |
521 | err = snd_hda_add_vmaster(codec, "Master Playback Volume", | 510 | err = snd_hda_add_vmaster(codec, "Master Playback Volume", |
522 | vmaster_tlv, slave_vols); | 511 | vmaster_tlv, slave_pfxs, |
512 | "Playback Volume"); | ||
523 | if (err < 0) | 513 | if (err < 0) |
524 | return err; | 514 | return err; |
525 | } | 515 | } |
526 | if (spec->vmaster_nid && | 516 | if (spec->vmaster_nid && |
527 | !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { | 517 | !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { |
528 | err = snd_hda_add_vmaster(codec, "Master Playback Switch", | 518 | err = __snd_hda_add_vmaster(codec, "Master Playback Switch", |
529 | NULL, slave_sws); | 519 | NULL, slave_pfxs, |
520 | "Playback Switch", true, | ||
521 | &spec->vmaster_mute.sw_kctl); | ||
530 | if (err < 0) | 522 | if (err < 0) |
531 | return err; | 523 | return err; |
532 | } | 524 | } |
@@ -3034,7 +3026,6 @@ static const struct snd_pci_quirk cxt5066_cfg_tbl[] = { | |||
3034 | SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo U350", CXT5066_ASUS), | 3026 | SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo U350", CXT5066_ASUS), |
3035 | SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G560", CXT5066_ASUS), | 3027 | SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G560", CXT5066_ASUS), |
3036 | SND_PCI_QUIRK(0x17aa, 0x3938, "Lenovo G565", CXT5066_AUTO), | 3028 | SND_PCI_QUIRK(0x17aa, 0x3938, "Lenovo G565", CXT5066_AUTO), |
3037 | SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", CXT5066_IDEAPAD), /* Fallback for Lenovos without dock mic */ | ||
3038 | SND_PCI_QUIRK(0x1b0a, 0x2092, "CyberpowerPC Gamer Xplorer N57001", CXT5066_AUTO), | 3029 | SND_PCI_QUIRK(0x1b0a, 0x2092, "CyberpowerPC Gamer Xplorer N57001", CXT5066_AUTO), |
3039 | {} | 3030 | {} |
3040 | }; | 3031 | }; |
@@ -3482,7 +3473,7 @@ static int cx_automute_mode_info(struct snd_kcontrol *kcontrol, | |||
3482 | "Disabled", "Enabled" | 3473 | "Disabled", "Enabled" |
3483 | }; | 3474 | }; |
3484 | static const char * const texts3[] = { | 3475 | static const char * const texts3[] = { |
3485 | "Disabled", "Speaker Only", "Line-Out+Speaker" | 3476 | "Disabled", "Speaker Only", "Line Out+Speaker" |
3486 | }; | 3477 | }; |
3487 | const char * const *texts; | 3478 | const char * const *texts; |
3488 | 3479 | ||
@@ -3943,6 +3934,63 @@ static void enable_unsol_pins(struct hda_codec *codec, int num_pins, | |||
3943 | snd_hda_jack_detect_enable(codec, pins[i], action); | 3934 | snd_hda_jack_detect_enable(codec, pins[i], action); |
3944 | } | 3935 | } |
3945 | 3936 | ||
3937 | static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums) | ||
3938 | { | ||
3939 | int i; | ||
3940 | for (i = 0; i < nums; i++) | ||
3941 | if (list[i] == nid) | ||
3942 | return true; | ||
3943 | return false; | ||
3944 | } | ||
3945 | |||
3946 | /* is the given NID found in any of autocfg items? */ | ||
3947 | static bool found_in_autocfg(struct auto_pin_cfg *cfg, hda_nid_t nid) | ||
3948 | { | ||
3949 | int i; | ||
3950 | |||
3951 | if (found_in_nid_list(nid, cfg->line_out_pins, cfg->line_outs) || | ||
3952 | found_in_nid_list(nid, cfg->hp_pins, cfg->hp_outs) || | ||
3953 | found_in_nid_list(nid, cfg->speaker_pins, cfg->speaker_outs) || | ||
3954 | found_in_nid_list(nid, cfg->dig_out_pins, cfg->dig_outs)) | ||
3955 | return true; | ||
3956 | for (i = 0; i < cfg->num_inputs; i++) | ||
3957 | if (cfg->inputs[i].pin == nid) | ||
3958 | return true; | ||
3959 | if (cfg->dig_in_pin == nid) | ||
3960 | return true; | ||
3961 | return false; | ||
3962 | } | ||
3963 | |||
3964 | /* clear unsol-event tags on unused pins; Conexant codecs seem to leave | ||
3965 | * invalid unsol tags by some reason | ||
3966 | */ | ||
3967 | static void clear_unsol_on_unused_pins(struct hda_codec *codec) | ||
3968 | { | ||
3969 | struct conexant_spec *spec = codec->spec; | ||
3970 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
3971 | int i; | ||
3972 | |||
3973 | for (i = 0; i < codec->init_pins.used; i++) { | ||
3974 | struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i); | ||
3975 | if (!found_in_autocfg(cfg, pin->nid)) | ||
3976 | snd_hda_codec_write(codec, pin->nid, 0, | ||
3977 | AC_VERB_SET_UNSOLICITED_ENABLE, 0); | ||
3978 | } | ||
3979 | } | ||
3980 | |||
3981 | /* turn on/off EAPD according to Master switch */ | ||
3982 | static void cx_auto_vmaster_hook(void *private_data, int enabled) | ||
3983 | { | ||
3984 | struct hda_codec *codec = private_data; | ||
3985 | struct conexant_spec *spec = codec->spec; | ||
3986 | |||
3987 | if (enabled && spec->pin_eapd_ctrls) { | ||
3988 | cx_auto_update_speakers(codec); | ||
3989 | return; | ||
3990 | } | ||
3991 | cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, enabled); | ||
3992 | } | ||
3993 | |||
3946 | static void cx_auto_init_output(struct hda_codec *codec) | 3994 | static void cx_auto_init_output(struct hda_codec *codec) |
3947 | { | 3995 | { |
3948 | struct conexant_spec *spec = codec->spec; | 3996 | struct conexant_spec *spec = codec->spec; |
@@ -3983,6 +4031,7 @@ static void cx_auto_init_output(struct hda_codec *codec) | |||
3983 | /* turn on all EAPDs if no individual EAPD control is available */ | 4031 | /* turn on all EAPDs if no individual EAPD control is available */ |
3984 | if (!spec->pin_eapd_ctrls) | 4032 | if (!spec->pin_eapd_ctrls) |
3985 | cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, true); | 4033 | cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, true); |
4034 | clear_unsol_on_unused_pins(codec); | ||
3986 | } | 4035 | } |
3987 | 4036 | ||
3988 | static void cx_auto_init_input(struct hda_codec *codec) | 4037 | static void cx_auto_init_input(struct hda_codec *codec) |
@@ -4046,11 +4095,13 @@ static void cx_auto_init_digital(struct hda_codec *codec) | |||
4046 | 4095 | ||
4047 | static int cx_auto_init(struct hda_codec *codec) | 4096 | static int cx_auto_init(struct hda_codec *codec) |
4048 | { | 4097 | { |
4098 | struct conexant_spec *spec = codec->spec; | ||
4049 | /*snd_hda_sequence_write(codec, cx_auto_init_verbs);*/ | 4099 | /*snd_hda_sequence_write(codec, cx_auto_init_verbs);*/ |
4050 | cx_auto_init_output(codec); | 4100 | cx_auto_init_output(codec); |
4051 | cx_auto_init_input(codec); | 4101 | cx_auto_init_input(codec); |
4052 | cx_auto_init_digital(codec); | 4102 | cx_auto_init_digital(codec); |
4053 | snd_hda_jack_report_sync(codec); | 4103 | snd_hda_jack_report_sync(codec); |
4104 | snd_hda_sync_vmaster_hook(&spec->vmaster_mute); | ||
4054 | return 0; | 4105 | return 0; |
4055 | } | 4106 | } |
4056 | 4107 | ||
@@ -4079,7 +4130,8 @@ static int cx_auto_add_volume_idx(struct hda_codec *codec, const char *basename, | |||
4079 | err = snd_hda_ctl_add(codec, nid, kctl); | 4130 | err = snd_hda_ctl_add(codec, nid, kctl); |
4080 | if (err < 0) | 4131 | if (err < 0) |
4081 | return err; | 4132 | return err; |
4082 | if (!(query_amp_caps(codec, nid, hda_dir) & AC_AMPCAP_MUTE)) | 4133 | if (!(query_amp_caps(codec, nid, hda_dir) & |
4134 | (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE))) | ||
4083 | break; | 4135 | break; |
4084 | } | 4136 | } |
4085 | return 0; | 4137 | return 0; |
@@ -4295,6 +4347,13 @@ static int cx_auto_build_controls(struct hda_codec *codec) | |||
4295 | err = snd_hda_jack_add_kctls(codec, &spec->autocfg); | 4347 | err = snd_hda_jack_add_kctls(codec, &spec->autocfg); |
4296 | if (err < 0) | 4348 | if (err < 0) |
4297 | return err; | 4349 | return err; |
4350 | if (spec->vmaster_mute.sw_kctl) { | ||
4351 | spec->vmaster_mute.hook = cx_auto_vmaster_hook; | ||
4352 | err = snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute, | ||
4353 | spec->vmaster_mute_led); | ||
4354 | if (err < 0) | ||
4355 | return err; | ||
4356 | } | ||
4298 | return 0; | 4357 | return 0; |
4299 | } | 4358 | } |
4300 | 4359 | ||
@@ -4319,7 +4378,6 @@ static int cx_auto_search_adcs(struct hda_codec *codec) | |||
4319 | return 0; | 4378 | return 0; |
4320 | } | 4379 | } |
4321 | 4380 | ||
4322 | |||
4323 | static const struct hda_codec_ops cx_auto_patch_ops = { | 4381 | static const struct hda_codec_ops cx_auto_patch_ops = { |
4324 | .build_controls = cx_auto_build_controls, | 4382 | .build_controls = cx_auto_build_controls, |
4325 | .build_pcms = conexant_build_pcms, | 4383 | .build_pcms = conexant_build_pcms, |
@@ -4367,6 +4425,7 @@ static const struct cxt_pincfg cxt_pincfg_lenovo_x200[] = { | |||
4367 | { 0x16, 0x042140ff }, /* HP (seq# overridden) */ | 4425 | { 0x16, 0x042140ff }, /* HP (seq# overridden) */ |
4368 | { 0x17, 0x21a11000 }, /* dock-mic */ | 4426 | { 0x17, 0x21a11000 }, /* dock-mic */ |
4369 | { 0x19, 0x2121103f }, /* dock-HP */ | 4427 | { 0x19, 0x2121103f }, /* dock-HP */ |
4428 | { 0x1c, 0x21440100 }, /* dock SPDIF out */ | ||
4370 | {} | 4429 | {} |
4371 | }; | 4430 | }; |
4372 | 4431 | ||
@@ -4379,6 +4438,22 @@ static const struct snd_pci_quirk cxt_fixups[] = { | |||
4379 | {} | 4438 | {} |
4380 | }; | 4439 | }; |
4381 | 4440 | ||
4441 | /* add "fake" mute amp-caps to DACs on cx5051 so that mixer mute switches | ||
4442 | * can be created (bko#42825) | ||
4443 | */ | ||
4444 | static void add_cx5051_fake_mutes(struct hda_codec *codec) | ||
4445 | { | ||
4446 | static hda_nid_t out_nids[] = { | ||
4447 | 0x10, 0x11, 0 | ||
4448 | }; | ||
4449 | hda_nid_t *p; | ||
4450 | |||
4451 | for (p = out_nids; *p; p++) | ||
4452 | snd_hda_override_amp_caps(codec, *p, HDA_OUTPUT, | ||
4453 | AC_AMPCAP_MIN_MUTE | | ||
4454 | query_amp_caps(codec, *p, HDA_OUTPUT)); | ||
4455 | } | ||
4456 | |||
4382 | static int patch_conexant_auto(struct hda_codec *codec) | 4457 | static int patch_conexant_auto(struct hda_codec *codec) |
4383 | { | 4458 | { |
4384 | struct conexant_spec *spec; | 4459 | struct conexant_spec *spec; |
@@ -4397,10 +4472,25 @@ static int patch_conexant_auto(struct hda_codec *codec) | |||
4397 | case 0x14f15045: | 4472 | case 0x14f15045: |
4398 | spec->single_adc_amp = 1; | 4473 | spec->single_adc_amp = 1; |
4399 | break; | 4474 | break; |
4475 | case 0x14f15051: | ||
4476 | add_cx5051_fake_mutes(codec); | ||
4477 | break; | ||
4400 | } | 4478 | } |
4401 | 4479 | ||
4402 | apply_pin_fixup(codec, cxt_fixups, cxt_pincfg_tbl); | 4480 | apply_pin_fixup(codec, cxt_fixups, cxt_pincfg_tbl); |
4403 | 4481 | ||
4482 | /* Show mute-led control only on HP laptops | ||
4483 | * This is a sort of white-list: on HP laptops, EAPD corresponds | ||
4484 | * only to the mute-LED without actualy amp function. Meanwhile, | ||
4485 | * others may use EAPD really as an amp switch, so it might be | ||
4486 | * not good to expose it blindly. | ||
4487 | */ | ||
4488 | switch (codec->subsystem_id >> 16) { | ||
4489 | case 0x103c: | ||
4490 | spec->vmaster_mute_led = 1; | ||
4491 | break; | ||
4492 | } | ||
4493 | |||
4404 | err = cx_auto_search_adcs(codec); | 4494 | err = cx_auto_search_adcs(codec); |
4405 | if (err < 0) | 4495 | if (err < 0) |
4406 | return err; | 4496 | return err; |
@@ -4414,6 +4504,18 @@ static int patch_conexant_auto(struct hda_codec *codec) | |||
4414 | codec->patch_ops = cx_auto_patch_ops; | 4504 | codec->patch_ops = cx_auto_patch_ops; |
4415 | if (spec->beep_amp) | 4505 | if (spec->beep_amp) |
4416 | snd_hda_attach_beep_device(codec, spec->beep_amp); | 4506 | snd_hda_attach_beep_device(codec, spec->beep_amp); |
4507 | |||
4508 | /* Some laptops with Conexant chips show stalls in S3 resume, | ||
4509 | * which falls into the single-cmd mode. | ||
4510 | * Better to make reset, then. | ||
4511 | */ | ||
4512 | if (!codec->bus->sync_write) { | ||
4513 | snd_printd("hda_codec: " | ||
4514 | "Enable sync_write for stable communication\n"); | ||
4515 | codec->bus->sync_write = 1; | ||
4516 | codec->bus->allow_bus_reset = 1; | ||
4517 | } | ||
4518 | |||
4417 | return 0; | 4519 | return 0; |
4418 | } | 4520 | } |
4419 | 4521 | ||
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 1168ebd3fb5c..540cd13f7f15 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
@@ -1912,6 +1912,7 @@ static const struct hda_codec_preset snd_hda_preset_hdmi[] = { | |||
1912 | { .id = 0x80862804, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi }, | 1912 | { .id = 0x80862804, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi }, |
1913 | { .id = 0x80862805, .name = "CougarPoint HDMI", .patch = patch_generic_hdmi }, | 1913 | { .id = 0x80862805, .name = "CougarPoint HDMI", .patch = patch_generic_hdmi }, |
1914 | { .id = 0x80862806, .name = "PantherPoint HDMI", .patch = patch_generic_hdmi }, | 1914 | { .id = 0x80862806, .name = "PantherPoint HDMI", .patch = patch_generic_hdmi }, |
1915 | { .id = 0x80862880, .name = "CedarTrail HDMI", .patch = patch_generic_hdmi }, | ||
1915 | { .id = 0x808629fb, .name = "Crestline HDMI", .patch = patch_generic_hdmi }, | 1916 | { .id = 0x808629fb, .name = "Crestline HDMI", .patch = patch_generic_hdmi }, |
1916 | {} /* terminator */ | 1917 | {} /* terminator */ |
1917 | }; | 1918 | }; |
@@ -1958,6 +1959,7 @@ MODULE_ALIAS("snd-hda-codec-id:80862803"); | |||
1958 | MODULE_ALIAS("snd-hda-codec-id:80862804"); | 1959 | MODULE_ALIAS("snd-hda-codec-id:80862804"); |
1959 | MODULE_ALIAS("snd-hda-codec-id:80862805"); | 1960 | MODULE_ALIAS("snd-hda-codec-id:80862805"); |
1960 | MODULE_ALIAS("snd-hda-codec-id:80862806"); | 1961 | MODULE_ALIAS("snd-hda-codec-id:80862806"); |
1962 | MODULE_ALIAS("snd-hda-codec-id:80862880"); | ||
1961 | MODULE_ALIAS("snd-hda-codec-id:808629fb"); | 1963 | MODULE_ALIAS("snd-hda-codec-id:808629fb"); |
1962 | 1964 | ||
1963 | MODULE_LICENSE("GPL"); | 1965 | MODULE_LICENSE("GPL"); |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index f6316507d764..8c463a4f79b4 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -80,6 +80,8 @@ enum { | |||
80 | ALC_AUTOMUTE_MIXER, /* mute/unmute mixer widget AMP */ | 80 | ALC_AUTOMUTE_MIXER, /* mute/unmute mixer widget AMP */ |
81 | }; | 81 | }; |
82 | 82 | ||
83 | #define MAX_VOL_NIDS 0x40 | ||
84 | |||
83 | struct alc_spec { | 85 | struct alc_spec { |
84 | /* codec parameterization */ | 86 | /* codec parameterization */ |
85 | const struct snd_kcontrol_new *mixers[5]; /* mixer arrays */ | 87 | const struct snd_kcontrol_new *mixers[5]; /* mixer arrays */ |
@@ -118,8 +120,8 @@ struct alc_spec { | |||
118 | const hda_nid_t *capsrc_nids; | 120 | const hda_nid_t *capsrc_nids; |
119 | hda_nid_t dig_in_nid; /* digital-in NID; optional */ | 121 | hda_nid_t dig_in_nid; /* digital-in NID; optional */ |
120 | hda_nid_t mixer_nid; /* analog-mixer NID */ | 122 | hda_nid_t mixer_nid; /* analog-mixer NID */ |
121 | DECLARE_BITMAP(vol_ctls, 0x20 << 1); | 123 | DECLARE_BITMAP(vol_ctls, MAX_VOL_NIDS << 1); |
122 | DECLARE_BITMAP(sw_ctls, 0x20 << 1); | 124 | DECLARE_BITMAP(sw_ctls, MAX_VOL_NIDS << 1); |
123 | 125 | ||
124 | /* capture setup for dynamic dual-adc switch */ | 126 | /* capture setup for dynamic dual-adc switch */ |
125 | hda_nid_t cur_adc; | 127 | hda_nid_t cur_adc; |
@@ -196,8 +198,11 @@ struct alc_spec { | |||
196 | 198 | ||
197 | /* for virtual master */ | 199 | /* for virtual master */ |
198 | hda_nid_t vmaster_nid; | 200 | hda_nid_t vmaster_nid; |
201 | struct hda_vmaster_mute_hook vmaster_mute; | ||
199 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 202 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
200 | struct hda_loopback_check loopback; | 203 | struct hda_loopback_check loopback; |
204 | int num_loopbacks; | ||
205 | struct hda_amp_list loopback_list[8]; | ||
201 | #endif | 206 | #endif |
202 | 207 | ||
203 | /* for PLL fix */ | 208 | /* for PLL fix */ |
@@ -218,8 +223,6 @@ struct alc_spec { | |||
218 | struct snd_array bind_ctls; | 223 | struct snd_array bind_ctls; |
219 | }; | 224 | }; |
220 | 225 | ||
221 | #define ALC_MODEL_AUTO 0 /* common for all chips */ | ||
222 | |||
223 | static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid, | 226 | static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid, |
224 | int dir, unsigned int bits) | 227 | int dir, unsigned int bits) |
225 | { | 228 | { |
@@ -298,6 +301,9 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx, | |||
298 | int i, type, num_conns; | 301 | int i, type, num_conns; |
299 | hda_nid_t nid; | 302 | hda_nid_t nid; |
300 | 303 | ||
304 | if (!spec->input_mux) | ||
305 | return 0; | ||
306 | |||
301 | mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx; | 307 | mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx; |
302 | imux = &spec->input_mux[mux_idx]; | 308 | imux = &spec->input_mux[mux_idx]; |
303 | if (!imux->num_items && mux_idx > 0) | 309 | if (!imux->num_items && mux_idx > 0) |
@@ -649,15 +655,51 @@ static void alc_exec_unsol_event(struct hda_codec *codec, int action) | |||
649 | snd_hda_jack_report_sync(codec); | 655 | snd_hda_jack_report_sync(codec); |
650 | } | 656 | } |
651 | 657 | ||
658 | /* update the master volume per volume-knob's unsol event */ | ||
659 | static void alc_update_knob_master(struct hda_codec *codec, hda_nid_t nid) | ||
660 | { | ||
661 | unsigned int val; | ||
662 | struct snd_kcontrol *kctl; | ||
663 | struct snd_ctl_elem_value *uctl; | ||
664 | |||
665 | kctl = snd_hda_find_mixer_ctl(codec, "Master Playback Volume"); | ||
666 | if (!kctl) | ||
667 | return; | ||
668 | uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); | ||
669 | if (!uctl) | ||
670 | return; | ||
671 | val = snd_hda_codec_read(codec, nid, 0, | ||
672 | AC_VERB_GET_VOLUME_KNOB_CONTROL, 0); | ||
673 | val &= HDA_AMP_VOLMASK; | ||
674 | uctl->value.integer.value[0] = val; | ||
675 | uctl->value.integer.value[1] = val; | ||
676 | kctl->put(kctl, uctl); | ||
677 | kfree(uctl); | ||
678 | } | ||
679 | |||
652 | /* unsolicited event for HP jack sensing */ | 680 | /* unsolicited event for HP jack sensing */ |
653 | static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res) | 681 | static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res) |
654 | { | 682 | { |
683 | int action; | ||
684 | |||
655 | if (codec->vendor_id == 0x10ec0880) | 685 | if (codec->vendor_id == 0x10ec0880) |
656 | res >>= 28; | 686 | res >>= 28; |
657 | else | 687 | else |
658 | res >>= 26; | 688 | res >>= 26; |
659 | res = snd_hda_jack_get_action(codec, res); | 689 | action = snd_hda_jack_get_action(codec, res); |
660 | alc_exec_unsol_event(codec, res); | 690 | if (action == ALC_DCVOL_EVENT) { |
691 | /* Execute the dc-vol event here as it requires the NID | ||
692 | * but we don't pass NID to alc_exec_unsol_event(). | ||
693 | * Once when we convert all static quirks to the auto-parser, | ||
694 | * this can be integerated into there. | ||
695 | */ | ||
696 | struct hda_jack_tbl *jack; | ||
697 | jack = snd_hda_jack_tbl_get_from_tag(codec, res); | ||
698 | if (jack) | ||
699 | alc_update_knob_master(codec, jack->nid); | ||
700 | return; | ||
701 | } | ||
702 | alc_exec_unsol_event(codec, action); | ||
661 | } | 703 | } |
662 | 704 | ||
663 | /* call init functions of standard auto-mute helpers */ | 705 | /* call init functions of standard auto-mute helpers */ |
@@ -800,7 +842,7 @@ static int alc_automute_mode_info(struct snd_kcontrol *kcontrol, | |||
800 | "Disabled", "Enabled" | 842 | "Disabled", "Enabled" |
801 | }; | 843 | }; |
802 | static const char * const texts3[] = { | 844 | static const char * const texts3[] = { |
803 | "Disabled", "Speaker Only", "Line-Out+Speaker" | 845 | "Disabled", "Speaker Only", "Line Out+Speaker" |
804 | }; | 846 | }; |
805 | const char * const *texts; | 847 | const char * const *texts; |
806 | 848 | ||
@@ -1031,45 +1073,6 @@ static bool alc_check_dyn_adc_switch(struct hda_codec *codec) | |||
1031 | return true; | 1073 | return true; |
1032 | } | 1074 | } |
1033 | 1075 | ||
1034 | /* rebuild imux for matching with the given auto-mic pins (if not yet) */ | ||
1035 | static bool alc_rebuild_imux_for_auto_mic(struct hda_codec *codec) | ||
1036 | { | ||
1037 | struct alc_spec *spec = codec->spec; | ||
1038 | struct hda_input_mux *imux; | ||
1039 | static char * const texts[3] = { | ||
1040 | "Mic", "Internal Mic", "Dock Mic" | ||
1041 | }; | ||
1042 | int i; | ||
1043 | |||
1044 | if (!spec->auto_mic) | ||
1045 | return false; | ||
1046 | imux = &spec->private_imux[0]; | ||
1047 | if (spec->input_mux == imux) | ||
1048 | return true; | ||
1049 | spec->imux_pins[0] = spec->ext_mic_pin; | ||
1050 | spec->imux_pins[1] = spec->int_mic_pin; | ||
1051 | spec->imux_pins[2] = spec->dock_mic_pin; | ||
1052 | for (i = 0; i < 3; i++) { | ||
1053 | strcpy(imux->items[i].label, texts[i]); | ||
1054 | if (spec->imux_pins[i]) { | ||
1055 | hda_nid_t pin = spec->imux_pins[i]; | ||
1056 | int c; | ||
1057 | for (c = 0; c < spec->num_adc_nids; c++) { | ||
1058 | hda_nid_t cap = get_capsrc(spec, c); | ||
1059 | int idx = get_connection_index(codec, cap, pin); | ||
1060 | if (idx >= 0) { | ||
1061 | imux->items[i].index = idx; | ||
1062 | break; | ||
1063 | } | ||
1064 | } | ||
1065 | imux->num_items = i + 1; | ||
1066 | } | ||
1067 | } | ||
1068 | spec->num_mux_defs = 1; | ||
1069 | spec->input_mux = imux; | ||
1070 | return true; | ||
1071 | } | ||
1072 | |||
1073 | /* check whether all auto-mic pins are valid; setup indices if OK */ | 1076 | /* check whether all auto-mic pins are valid; setup indices if OK */ |
1074 | static bool alc_auto_mic_check_imux(struct hda_codec *codec) | 1077 | static bool alc_auto_mic_check_imux(struct hda_codec *codec) |
1075 | { | 1078 | { |
@@ -1439,6 +1442,7 @@ enum { | |||
1439 | ALC_FIXUP_ACT_PRE_PROBE, | 1442 | ALC_FIXUP_ACT_PRE_PROBE, |
1440 | ALC_FIXUP_ACT_PROBE, | 1443 | ALC_FIXUP_ACT_PROBE, |
1441 | ALC_FIXUP_ACT_INIT, | 1444 | ALC_FIXUP_ACT_INIT, |
1445 | ALC_FIXUP_ACT_BUILD, | ||
1442 | }; | 1446 | }; |
1443 | 1447 | ||
1444 | static void alc_apply_fixup(struct hda_codec *codec, int action) | 1448 | static void alc_apply_fixup(struct hda_codec *codec, int action) |
@@ -1518,6 +1522,13 @@ static void alc_pick_fixup(struct hda_codec *codec, | |||
1518 | int id = -1; | 1522 | int id = -1; |
1519 | const char *name = NULL; | 1523 | const char *name = NULL; |
1520 | 1524 | ||
1525 | /* when model=nofixup is given, don't pick up any fixups */ | ||
1526 | if (codec->modelname && !strcmp(codec->modelname, "nofixup")) { | ||
1527 | spec->fixup_list = NULL; | ||
1528 | spec->fixup_id = -1; | ||
1529 | return; | ||
1530 | } | ||
1531 | |||
1521 | if (codec->modelname && models) { | 1532 | if (codec->modelname && models) { |
1522 | while (models->name) { | 1533 | while (models->name) { |
1523 | if (!strcmp(codec->modelname, models->name)) { | 1534 | if (!strcmp(codec->modelname, models->name)) { |
@@ -1845,32 +1856,10 @@ DEFINE_CAPMIX_NOSRC(3); | |||
1845 | /* | 1856 | /* |
1846 | * slave controls for virtual master | 1857 | * slave controls for virtual master |
1847 | */ | 1858 | */ |
1848 | static const char * const alc_slave_vols[] = { | 1859 | static const char * const alc_slave_pfxs[] = { |
1849 | "Front Playback Volume", | 1860 | "Front", "Surround", "Center", "LFE", "Side", |
1850 | "Surround Playback Volume", | 1861 | "Headphone", "Speaker", "Mono", "Line Out", |
1851 | "Center Playback Volume", | 1862 | "CLFE", "Bass Speaker", "PCM", |
1852 | "LFE Playback Volume", | ||
1853 | "Side Playback Volume", | ||
1854 | "Headphone Playback Volume", | ||
1855 | "Speaker Playback Volume", | ||
1856 | "Mono Playback Volume", | ||
1857 | "Line-Out Playback Volume", | ||
1858 | "PCM Playback Volume", | ||
1859 | NULL, | ||
1860 | }; | ||
1861 | |||
1862 | static const char * const alc_slave_sws[] = { | ||
1863 | "Front Playback Switch", | ||
1864 | "Surround Playback Switch", | ||
1865 | "Center Playback Switch", | ||
1866 | "LFE Playback Switch", | ||
1867 | "Side Playback Switch", | ||
1868 | "Headphone Playback Switch", | ||
1869 | "Speaker Playback Switch", | ||
1870 | "Mono Playback Switch", | ||
1871 | "IEC958 Playback Switch", | ||
1872 | "Line-Out Playback Switch", | ||
1873 | "PCM Playback Switch", | ||
1874 | NULL, | 1863 | NULL, |
1875 | }; | 1864 | }; |
1876 | 1865 | ||
@@ -1961,14 +1950,17 @@ static int __alc_build_controls(struct hda_codec *codec) | |||
1961 | snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid, | 1950 | snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid, |
1962 | HDA_OUTPUT, vmaster_tlv); | 1951 | HDA_OUTPUT, vmaster_tlv); |
1963 | err = snd_hda_add_vmaster(codec, "Master Playback Volume", | 1952 | err = snd_hda_add_vmaster(codec, "Master Playback Volume", |
1964 | vmaster_tlv, alc_slave_vols); | 1953 | vmaster_tlv, alc_slave_pfxs, |
1954 | "Playback Volume"); | ||
1965 | if (err < 0) | 1955 | if (err < 0) |
1966 | return err; | 1956 | return err; |
1967 | } | 1957 | } |
1968 | if (!spec->no_analog && | 1958 | if (!spec->no_analog && |
1969 | !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { | 1959 | !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { |
1970 | err = snd_hda_add_vmaster(codec, "Master Playback Switch", | 1960 | err = __snd_hda_add_vmaster(codec, "Master Playback Switch", |
1971 | NULL, alc_slave_sws); | 1961 | NULL, alc_slave_pfxs, |
1962 | "Playback Switch", | ||
1963 | true, &spec->vmaster_mute.sw_kctl); | ||
1972 | if (err < 0) | 1964 | if (err < 0) |
1973 | return err; | 1965 | return err; |
1974 | } | 1966 | } |
@@ -2053,7 +2045,11 @@ static int alc_build_controls(struct hda_codec *codec) | |||
2053 | int err = __alc_build_controls(codec); | 2045 | int err = __alc_build_controls(codec); |
2054 | if (err < 0) | 2046 | if (err < 0) |
2055 | return err; | 2047 | return err; |
2056 | return snd_hda_jack_add_kctls(codec, &spec->autocfg); | 2048 | err = snd_hda_jack_add_kctls(codec, &spec->autocfg); |
2049 | if (err < 0) | ||
2050 | return err; | ||
2051 | alc_apply_fixup(codec, ALC_FIXUP_ACT_BUILD); | ||
2052 | return 0; | ||
2057 | } | 2053 | } |
2058 | 2054 | ||
2059 | 2055 | ||
@@ -2062,21 +2058,23 @@ static int alc_build_controls(struct hda_codec *codec) | |||
2062 | */ | 2058 | */ |
2063 | 2059 | ||
2064 | static void alc_init_special_input_src(struct hda_codec *codec); | 2060 | static void alc_init_special_input_src(struct hda_codec *codec); |
2061 | static void alc_auto_init_std(struct hda_codec *codec); | ||
2065 | 2062 | ||
2066 | static int alc_init(struct hda_codec *codec) | 2063 | static int alc_init(struct hda_codec *codec) |
2067 | { | 2064 | { |
2068 | struct alc_spec *spec = codec->spec; | 2065 | struct alc_spec *spec = codec->spec; |
2069 | unsigned int i; | 2066 | unsigned int i; |
2070 | 2067 | ||
2068 | if (spec->init_hook) | ||
2069 | spec->init_hook(codec); | ||
2070 | |||
2071 | alc_fix_pll(codec); | 2071 | alc_fix_pll(codec); |
2072 | alc_auto_init_amp(codec, spec->init_amp); | 2072 | alc_auto_init_amp(codec, spec->init_amp); |
2073 | 2073 | ||
2074 | for (i = 0; i < spec->num_init_verbs; i++) | 2074 | for (i = 0; i < spec->num_init_verbs; i++) |
2075 | snd_hda_sequence_write(codec, spec->init_verbs[i]); | 2075 | snd_hda_sequence_write(codec, spec->init_verbs[i]); |
2076 | alc_init_special_input_src(codec); | 2076 | alc_init_special_input_src(codec); |
2077 | 2077 | alc_auto_init_std(codec); | |
2078 | if (spec->init_hook) | ||
2079 | spec->init_hook(codec); | ||
2080 | 2078 | ||
2081 | alc_apply_fixup(codec, ALC_FIXUP_ACT_INIT); | 2079 | alc_apply_fixup(codec, ALC_FIXUP_ACT_INIT); |
2082 | 2080 | ||
@@ -2318,7 +2316,7 @@ static int alc_build_pcms(struct hda_codec *codec) | |||
2318 | "%s Analog", codec->chip_name); | 2316 | "%s Analog", codec->chip_name); |
2319 | info->name = spec->stream_name_analog; | 2317 | info->name = spec->stream_name_analog; |
2320 | 2318 | ||
2321 | if (spec->multiout.dac_nids > 0) { | 2319 | if (spec->multiout.num_dacs > 0) { |
2322 | p = spec->stream_analog_playback; | 2320 | p = spec->stream_analog_playback; |
2323 | if (!p) | 2321 | if (!p) |
2324 | p = &alc_pcm_analog_playback; | 2322 | p = &alc_pcm_analog_playback; |
@@ -2665,6 +2663,25 @@ static const char *alc_get_line_out_pfx(struct alc_spec *spec, int ch, | |||
2665 | return channel_name[ch]; | 2663 | return channel_name[ch]; |
2666 | } | 2664 | } |
2667 | 2665 | ||
2666 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
2667 | /* add the powersave loopback-list entry */ | ||
2668 | static void add_loopback_list(struct alc_spec *spec, hda_nid_t mix, int idx) | ||
2669 | { | ||
2670 | struct hda_amp_list *list; | ||
2671 | |||
2672 | if (spec->num_loopbacks >= ARRAY_SIZE(spec->loopback_list) - 1) | ||
2673 | return; | ||
2674 | list = spec->loopback_list + spec->num_loopbacks; | ||
2675 | list->nid = mix; | ||
2676 | list->dir = HDA_INPUT; | ||
2677 | list->idx = idx; | ||
2678 | spec->num_loopbacks++; | ||
2679 | spec->loopback.amplist = spec->loopback_list; | ||
2680 | } | ||
2681 | #else | ||
2682 | #define add_loopback_list(spec, mix, idx) /* NOP */ | ||
2683 | #endif | ||
2684 | |||
2668 | /* create input playback/capture controls for the given pin */ | 2685 | /* create input playback/capture controls for the given pin */ |
2669 | static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, | 2686 | static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, |
2670 | const char *ctlname, int ctlidx, | 2687 | const char *ctlname, int ctlidx, |
@@ -2680,6 +2697,7 @@ static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, | |||
2680 | HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); | 2697 | HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); |
2681 | if (err < 0) | 2698 | if (err < 0) |
2682 | return err; | 2699 | return err; |
2700 | add_loopback_list(spec, mix_nid, idx); | ||
2683 | return 0; | 2701 | return 0; |
2684 | } | 2702 | } |
2685 | 2703 | ||
@@ -2699,9 +2717,6 @@ static int alc_auto_fill_adc_caps(struct hda_codec *codec) | |||
2699 | int max_nums = ARRAY_SIZE(spec->private_adc_nids); | 2717 | int max_nums = ARRAY_SIZE(spec->private_adc_nids); |
2700 | int i, nums = 0; | 2718 | int i, nums = 0; |
2701 | 2719 | ||
2702 | if (spec->shared_mic_hp) | ||
2703 | max_nums = 1; /* no multi streams with the shared HP/mic */ | ||
2704 | |||
2705 | nid = codec->start_nid; | 2720 | nid = codec->start_nid; |
2706 | for (i = 0; i < codec->num_nodes; i++, nid++) { | 2721 | for (i = 0; i < codec->num_nodes; i++, nid++) { |
2707 | hda_nid_t src; | 2722 | hda_nid_t src; |
@@ -2944,10 +2959,27 @@ static int alc_auto_select_dac(struct hda_codec *codec, hda_nid_t pin, | |||
2944 | return 0; | 2959 | return 0; |
2945 | } | 2960 | } |
2946 | 2961 | ||
2962 | static bool alc_is_dac_already_used(struct hda_codec *codec, hda_nid_t nid) | ||
2963 | { | ||
2964 | struct alc_spec *spec = codec->spec; | ||
2965 | int i; | ||
2966 | if (found_in_nid_list(nid, spec->multiout.dac_nids, | ||
2967 | ARRAY_SIZE(spec->private_dac_nids)) || | ||
2968 | found_in_nid_list(nid, spec->multiout.hp_out_nid, | ||
2969 | ARRAY_SIZE(spec->multiout.hp_out_nid)) || | ||
2970 | found_in_nid_list(nid, spec->multiout.extra_out_nid, | ||
2971 | ARRAY_SIZE(spec->multiout.extra_out_nid))) | ||
2972 | return true; | ||
2973 | for (i = 0; i < spec->multi_ios; i++) { | ||
2974 | if (spec->multi_io[i].dac == nid) | ||
2975 | return true; | ||
2976 | } | ||
2977 | return false; | ||
2978 | } | ||
2979 | |||
2947 | /* look for an empty DAC slot */ | 2980 | /* look for an empty DAC slot */ |
2948 | static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin) | 2981 | static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin) |
2949 | { | 2982 | { |
2950 | struct alc_spec *spec = codec->spec; | ||
2951 | hda_nid_t srcs[5]; | 2983 | hda_nid_t srcs[5]; |
2952 | int i, num; | 2984 | int i, num; |
2953 | 2985 | ||
@@ -2957,16 +2989,8 @@ static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin) | |||
2957 | hda_nid_t nid = alc_auto_mix_to_dac(codec, srcs[i]); | 2989 | hda_nid_t nid = alc_auto_mix_to_dac(codec, srcs[i]); |
2958 | if (!nid) | 2990 | if (!nid) |
2959 | continue; | 2991 | continue; |
2960 | if (found_in_nid_list(nid, spec->multiout.dac_nids, | 2992 | if (!alc_is_dac_already_used(codec, nid)) |
2961 | ARRAY_SIZE(spec->private_dac_nids))) | 2993 | return nid; |
2962 | continue; | ||
2963 | if (found_in_nid_list(nid, spec->multiout.hp_out_nid, | ||
2964 | ARRAY_SIZE(spec->multiout.hp_out_nid))) | ||
2965 | continue; | ||
2966 | if (found_in_nid_list(nid, spec->multiout.extra_out_nid, | ||
2967 | ARRAY_SIZE(spec->multiout.extra_out_nid))) | ||
2968 | continue; | ||
2969 | return nid; | ||
2970 | } | 2994 | } |
2971 | return 0; | 2995 | return 0; |
2972 | } | 2996 | } |
@@ -2978,6 +3002,8 @@ static bool alc_auto_is_dac_reachable(struct hda_codec *codec, | |||
2978 | hda_nid_t srcs[5]; | 3002 | hda_nid_t srcs[5]; |
2979 | int i, num; | 3003 | int i, num; |
2980 | 3004 | ||
3005 | if (!pin || !dac) | ||
3006 | return false; | ||
2981 | pin = alc_go_down_to_selector(codec, pin); | 3007 | pin = alc_go_down_to_selector(codec, pin); |
2982 | num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs)); | 3008 | num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs)); |
2983 | for (i = 0; i < num; i++) { | 3009 | for (i = 0; i < num; i++) { |
@@ -2990,83 +3016,260 @@ static bool alc_auto_is_dac_reachable(struct hda_codec *codec, | |||
2990 | 3016 | ||
2991 | static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin) | 3017 | static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin) |
2992 | { | 3018 | { |
3019 | struct alc_spec *spec = codec->spec; | ||
2993 | hda_nid_t sel = alc_go_down_to_selector(codec, pin); | 3020 | hda_nid_t sel = alc_go_down_to_selector(codec, pin); |
2994 | if (snd_hda_get_conn_list(codec, sel, NULL) == 1) | 3021 | hda_nid_t nid, nid_found, srcs[5]; |
3022 | int i, num = snd_hda_get_connections(codec, sel, srcs, | ||
3023 | ARRAY_SIZE(srcs)); | ||
3024 | if (num == 1) | ||
2995 | return alc_auto_look_for_dac(codec, pin); | 3025 | return alc_auto_look_for_dac(codec, pin); |
2996 | return 0; | 3026 | nid_found = 0; |
3027 | for (i = 0; i < num; i++) { | ||
3028 | if (srcs[i] == spec->mixer_nid) | ||
3029 | continue; | ||
3030 | nid = alc_auto_mix_to_dac(codec, srcs[i]); | ||
3031 | if (nid && !alc_is_dac_already_used(codec, nid)) { | ||
3032 | if (nid_found) | ||
3033 | return 0; | ||
3034 | nid_found = nid; | ||
3035 | } | ||
3036 | } | ||
3037 | return nid_found; | ||
2997 | } | 3038 | } |
2998 | 3039 | ||
2999 | /* return 0 if no possible DAC is found, 1 if one or more found */ | 3040 | /* mark up volume and mute control NIDs: used during badness parsing and |
3000 | static int alc_auto_fill_extra_dacs(struct hda_codec *codec, int num_outs, | 3041 | * at creating actual controls |
3001 | const hda_nid_t *pins, hda_nid_t *dacs) | 3042 | */ |
3043 | static inline unsigned int get_ctl_pos(unsigned int data) | ||
3002 | { | 3044 | { |
3003 | int i; | 3045 | hda_nid_t nid = get_amp_nid_(data); |
3046 | unsigned int dir; | ||
3047 | if (snd_BUG_ON(nid >= MAX_VOL_NIDS)) | ||
3048 | return 0; | ||
3049 | dir = get_amp_direction_(data); | ||
3050 | return (nid << 1) | dir; | ||
3051 | } | ||
3004 | 3052 | ||
3005 | if (num_outs && !dacs[0]) { | 3053 | #define is_ctl_used(bits, data) \ |
3006 | dacs[0] = alc_auto_look_for_dac(codec, pins[0]); | 3054 | test_bit(get_ctl_pos(data), bits) |
3007 | if (!dacs[0]) | 3055 | #define mark_ctl_usage(bits, data) \ |
3008 | return 0; | 3056 | set_bit(get_ctl_pos(data), bits) |
3009 | } | ||
3010 | 3057 | ||
3011 | for (i = 1; i < num_outs; i++) | 3058 | static void clear_vol_marks(struct hda_codec *codec) |
3012 | dacs[i] = get_dac_if_single(codec, pins[i]); | 3059 | { |
3013 | for (i = 1; i < num_outs; i++) { | 3060 | struct alc_spec *spec = codec->spec; |
3061 | memset(spec->vol_ctls, 0, sizeof(spec->vol_ctls)); | ||
3062 | memset(spec->sw_ctls, 0, sizeof(spec->sw_ctls)); | ||
3063 | } | ||
3064 | |||
3065 | /* badness definition */ | ||
3066 | enum { | ||
3067 | /* No primary DAC is found for the main output */ | ||
3068 | BAD_NO_PRIMARY_DAC = 0x10000, | ||
3069 | /* No DAC is found for the extra output */ | ||
3070 | BAD_NO_DAC = 0x4000, | ||
3071 | /* No possible multi-ios */ | ||
3072 | BAD_MULTI_IO = 0x103, | ||
3073 | /* No individual DAC for extra output */ | ||
3074 | BAD_NO_EXTRA_DAC = 0x102, | ||
3075 | /* No individual DAC for extra surrounds */ | ||
3076 | BAD_NO_EXTRA_SURR_DAC = 0x101, | ||
3077 | /* Primary DAC shared with main surrounds */ | ||
3078 | BAD_SHARED_SURROUND = 0x100, | ||
3079 | /* Primary DAC shared with main CLFE */ | ||
3080 | BAD_SHARED_CLFE = 0x10, | ||
3081 | /* Primary DAC shared with extra surrounds */ | ||
3082 | BAD_SHARED_EXTRA_SURROUND = 0x10, | ||
3083 | /* Volume widget is shared */ | ||
3084 | BAD_SHARED_VOL = 0x10, | ||
3085 | }; | ||
3086 | |||
3087 | static hda_nid_t alc_look_for_out_mute_nid(struct hda_codec *codec, | ||
3088 | hda_nid_t pin, hda_nid_t dac); | ||
3089 | static hda_nid_t alc_look_for_out_vol_nid(struct hda_codec *codec, | ||
3090 | hda_nid_t pin, hda_nid_t dac); | ||
3091 | |||
3092 | static int eval_shared_vol_badness(struct hda_codec *codec, hda_nid_t pin, | ||
3093 | hda_nid_t dac) | ||
3094 | { | ||
3095 | struct alc_spec *spec = codec->spec; | ||
3096 | hda_nid_t nid; | ||
3097 | unsigned int val; | ||
3098 | int badness = 0; | ||
3099 | |||
3100 | nid = alc_look_for_out_vol_nid(codec, pin, dac); | ||
3101 | if (nid) { | ||
3102 | val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); | ||
3103 | if (is_ctl_used(spec->vol_ctls, nid)) | ||
3104 | badness += BAD_SHARED_VOL; | ||
3105 | else | ||
3106 | mark_ctl_usage(spec->vol_ctls, val); | ||
3107 | } else | ||
3108 | badness += BAD_SHARED_VOL; | ||
3109 | nid = alc_look_for_out_mute_nid(codec, pin, dac); | ||
3110 | if (nid) { | ||
3111 | unsigned int wid_type = get_wcaps_type(get_wcaps(codec, nid)); | ||
3112 | if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT) | ||
3113 | val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); | ||
3114 | else | ||
3115 | val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT); | ||
3116 | if (is_ctl_used(spec->sw_ctls, val)) | ||
3117 | badness += BAD_SHARED_VOL; | ||
3118 | else | ||
3119 | mark_ctl_usage(spec->sw_ctls, val); | ||
3120 | } else | ||
3121 | badness += BAD_SHARED_VOL; | ||
3122 | return badness; | ||
3123 | } | ||
3124 | |||
3125 | struct badness_table { | ||
3126 | int no_primary_dac; /* no primary DAC */ | ||
3127 | int no_dac; /* no secondary DACs */ | ||
3128 | int shared_primary; /* primary DAC is shared with main output */ | ||
3129 | int shared_surr; /* secondary DAC shared with main or primary */ | ||
3130 | int shared_clfe; /* third DAC shared with main or primary */ | ||
3131 | int shared_surr_main; /* secondary DAC sahred with main/DAC0 */ | ||
3132 | }; | ||
3133 | |||
3134 | static struct badness_table main_out_badness = { | ||
3135 | .no_primary_dac = BAD_NO_PRIMARY_DAC, | ||
3136 | .no_dac = BAD_NO_DAC, | ||
3137 | .shared_primary = BAD_NO_PRIMARY_DAC, | ||
3138 | .shared_surr = BAD_SHARED_SURROUND, | ||
3139 | .shared_clfe = BAD_SHARED_CLFE, | ||
3140 | .shared_surr_main = BAD_SHARED_SURROUND, | ||
3141 | }; | ||
3142 | |||
3143 | static struct badness_table extra_out_badness = { | ||
3144 | .no_primary_dac = BAD_NO_DAC, | ||
3145 | .no_dac = BAD_NO_DAC, | ||
3146 | .shared_primary = BAD_NO_EXTRA_DAC, | ||
3147 | .shared_surr = BAD_SHARED_EXTRA_SURROUND, | ||
3148 | .shared_clfe = BAD_SHARED_EXTRA_SURROUND, | ||
3149 | .shared_surr_main = BAD_NO_EXTRA_SURR_DAC, | ||
3150 | }; | ||
3151 | |||
3152 | /* try to assign DACs to pins and return the resultant badness */ | ||
3153 | static int alc_auto_fill_dacs(struct hda_codec *codec, int num_outs, | ||
3154 | const hda_nid_t *pins, hda_nid_t *dacs, | ||
3155 | const struct badness_table *bad) | ||
3156 | { | ||
3157 | struct alc_spec *spec = codec->spec; | ||
3158 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
3159 | int i, j; | ||
3160 | int badness = 0; | ||
3161 | hda_nid_t dac; | ||
3162 | |||
3163 | if (!num_outs) | ||
3164 | return 0; | ||
3165 | |||
3166 | for (i = 0; i < num_outs; i++) { | ||
3167 | hda_nid_t pin = pins[i]; | ||
3014 | if (!dacs[i]) | 3168 | if (!dacs[i]) |
3015 | dacs[i] = alc_auto_look_for_dac(codec, pins[i]); | 3169 | dacs[i] = alc_auto_look_for_dac(codec, pin); |
3170 | if (!dacs[i] && !i) { | ||
3171 | for (j = 1; j < num_outs; j++) { | ||
3172 | if (alc_auto_is_dac_reachable(codec, pin, dacs[j])) { | ||
3173 | dacs[0] = dacs[j]; | ||
3174 | dacs[j] = 0; | ||
3175 | break; | ||
3176 | } | ||
3177 | } | ||
3178 | } | ||
3179 | dac = dacs[i]; | ||
3180 | if (!dac) { | ||
3181 | if (alc_auto_is_dac_reachable(codec, pin, dacs[0])) | ||
3182 | dac = dacs[0]; | ||
3183 | else if (cfg->line_outs > i && | ||
3184 | alc_auto_is_dac_reachable(codec, pin, | ||
3185 | spec->private_dac_nids[i])) | ||
3186 | dac = spec->private_dac_nids[i]; | ||
3187 | if (dac) { | ||
3188 | if (!i) | ||
3189 | badness += bad->shared_primary; | ||
3190 | else if (i == 1) | ||
3191 | badness += bad->shared_surr; | ||
3192 | else | ||
3193 | badness += bad->shared_clfe; | ||
3194 | } else if (alc_auto_is_dac_reachable(codec, pin, | ||
3195 | spec->private_dac_nids[0])) { | ||
3196 | dac = spec->private_dac_nids[0]; | ||
3197 | badness += bad->shared_surr_main; | ||
3198 | } else if (!i) | ||
3199 | badness += bad->no_primary_dac; | ||
3200 | else | ||
3201 | badness += bad->no_dac; | ||
3202 | } | ||
3203 | if (dac) | ||
3204 | badness += eval_shared_vol_badness(codec, pin, dac); | ||
3016 | } | 3205 | } |
3017 | return 1; | 3206 | |
3207 | return badness; | ||
3018 | } | 3208 | } |
3019 | 3209 | ||
3020 | static int alc_auto_fill_multi_ios(struct hda_codec *codec, | 3210 | static int alc_auto_fill_multi_ios(struct hda_codec *codec, |
3021 | unsigned int location, int offset); | 3211 | hda_nid_t reference_pin, |
3022 | static hda_nid_t alc_look_for_out_vol_nid(struct hda_codec *codec, | 3212 | bool hardwired, int offset); |
3023 | hda_nid_t pin, hda_nid_t dac); | 3213 | |
3214 | static bool alc_map_singles(struct hda_codec *codec, int outs, | ||
3215 | const hda_nid_t *pins, hda_nid_t *dacs) | ||
3216 | { | ||
3217 | int i; | ||
3218 | bool found = false; | ||
3219 | for (i = 0; i < outs; i++) { | ||
3220 | if (dacs[i]) | ||
3221 | continue; | ||
3222 | dacs[i] = get_dac_if_single(codec, pins[i]); | ||
3223 | if (dacs[i]) | ||
3224 | found = true; | ||
3225 | } | ||
3226 | return found; | ||
3227 | } | ||
3024 | 3228 | ||
3025 | /* fill in the dac_nids table from the parsed pin configuration */ | 3229 | /* fill in the dac_nids table from the parsed pin configuration */ |
3026 | static int alc_auto_fill_dac_nids(struct hda_codec *codec) | 3230 | static int fill_and_eval_dacs(struct hda_codec *codec, |
3231 | bool fill_hardwired, | ||
3232 | bool fill_mio_first) | ||
3027 | { | 3233 | { |
3028 | struct alc_spec *spec = codec->spec; | 3234 | struct alc_spec *spec = codec->spec; |
3029 | struct auto_pin_cfg *cfg = &spec->autocfg; | 3235 | struct auto_pin_cfg *cfg = &spec->autocfg; |
3030 | unsigned int location, defcfg; | 3236 | int i, err, badness; |
3031 | int num_pins; | ||
3032 | bool redone = false; | ||
3033 | int i; | ||
3034 | 3237 | ||
3035 | again: | ||
3036 | /* set num_dacs once to full for alc_auto_look_for_dac() */ | 3238 | /* set num_dacs once to full for alc_auto_look_for_dac() */ |
3037 | spec->multiout.num_dacs = cfg->line_outs; | 3239 | spec->multiout.num_dacs = cfg->line_outs; |
3038 | spec->multiout.hp_out_nid[0] = 0; | ||
3039 | spec->multiout.extra_out_nid[0] = 0; | ||
3040 | memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids)); | ||
3041 | spec->multiout.dac_nids = spec->private_dac_nids; | 3240 | spec->multiout.dac_nids = spec->private_dac_nids; |
3241 | memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids)); | ||
3242 | memset(spec->multiout.hp_out_nid, 0, sizeof(spec->multiout.hp_out_nid)); | ||
3243 | memset(spec->multiout.extra_out_nid, 0, sizeof(spec->multiout.extra_out_nid)); | ||
3042 | spec->multi_ios = 0; | 3244 | spec->multi_ios = 0; |
3245 | clear_vol_marks(codec); | ||
3246 | badness = 0; | ||
3043 | 3247 | ||
3044 | /* fill hard-wired DACs first */ | 3248 | /* fill hard-wired DACs first */ |
3045 | if (!redone) { | 3249 | if (fill_hardwired) { |
3046 | for (i = 0; i < cfg->line_outs; i++) | 3250 | bool mapped; |
3047 | spec->private_dac_nids[i] = | 3251 | do { |
3048 | get_dac_if_single(codec, cfg->line_out_pins[i]); | 3252 | mapped = alc_map_singles(codec, cfg->line_outs, |
3049 | if (cfg->hp_outs) | 3253 | cfg->line_out_pins, |
3050 | spec->multiout.hp_out_nid[0] = | 3254 | spec->private_dac_nids); |
3051 | get_dac_if_single(codec, cfg->hp_pins[0]); | 3255 | mapped |= alc_map_singles(codec, cfg->hp_outs, |
3052 | if (cfg->speaker_outs) | 3256 | cfg->hp_pins, |
3053 | spec->multiout.extra_out_nid[0] = | 3257 | spec->multiout.hp_out_nid); |
3054 | get_dac_if_single(codec, cfg->speaker_pins[0]); | 3258 | mapped |= alc_map_singles(codec, cfg->speaker_outs, |
3259 | cfg->speaker_pins, | ||
3260 | spec->multiout.extra_out_nid); | ||
3261 | if (fill_mio_first && cfg->line_outs == 1 && | ||
3262 | cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { | ||
3263 | err = alc_auto_fill_multi_ios(codec, cfg->line_out_pins[0], true, 0); | ||
3264 | if (!err) | ||
3265 | mapped = true; | ||
3266 | } | ||
3267 | } while (mapped); | ||
3055 | } | 3268 | } |
3056 | 3269 | ||
3057 | for (i = 0; i < cfg->line_outs; i++) { | 3270 | badness += alc_auto_fill_dacs(codec, cfg->line_outs, cfg->line_out_pins, |
3058 | hda_nid_t pin = cfg->line_out_pins[i]; | 3271 | spec->private_dac_nids, |
3059 | if (spec->private_dac_nids[i]) | 3272 | &main_out_badness); |
3060 | continue; | ||
3061 | spec->private_dac_nids[i] = alc_auto_look_for_dac(codec, pin); | ||
3062 | if (!spec->private_dac_nids[i] && !redone) { | ||
3063 | /* if we can't find primary DACs, re-probe without | ||
3064 | * checking the hard-wired DACs | ||
3065 | */ | ||
3066 | redone = true; | ||
3067 | goto again; | ||
3068 | } | ||
3069 | } | ||
3070 | 3273 | ||
3071 | /* re-count num_dacs and squash invalid entries */ | 3274 | /* re-count num_dacs and squash invalid entries */ |
3072 | spec->multiout.num_dacs = 0; | 3275 | spec->multiout.num_dacs = 0; |
@@ -3081,30 +3284,144 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) | |||
3081 | } | 3284 | } |
3082 | } | 3285 | } |
3083 | 3286 | ||
3084 | if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { | 3287 | if (fill_mio_first && |
3288 | cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { | ||
3085 | /* try to fill multi-io first */ | 3289 | /* try to fill multi-io first */ |
3086 | defcfg = snd_hda_codec_get_pincfg(codec, cfg->line_out_pins[0]); | 3290 | err = alc_auto_fill_multi_ios(codec, cfg->line_out_pins[0], false, 0); |
3087 | location = get_defcfg_location(defcfg); | 3291 | if (err < 0) |
3088 | 3292 | return err; | |
3089 | num_pins = alc_auto_fill_multi_ios(codec, location, 0); | 3293 | /* we don't count badness at this stage yet */ |
3090 | if (num_pins > 0) { | ||
3091 | spec->multi_ios = num_pins; | ||
3092 | spec->ext_channel_count = 2; | ||
3093 | spec->multiout.num_dacs = num_pins + 1; | ||
3094 | } | ||
3095 | } | 3294 | } |
3096 | 3295 | ||
3097 | if (cfg->line_out_type != AUTO_PIN_HP_OUT) | 3296 | if (cfg->line_out_type != AUTO_PIN_HP_OUT) { |
3098 | alc_auto_fill_extra_dacs(codec, cfg->hp_outs, cfg->hp_pins, | 3297 | err = alc_auto_fill_dacs(codec, cfg->hp_outs, cfg->hp_pins, |
3099 | spec->multiout.hp_out_nid); | 3298 | spec->multiout.hp_out_nid, |
3299 | &extra_out_badness); | ||
3300 | if (err < 0) | ||
3301 | return err; | ||
3302 | badness += err; | ||
3303 | } | ||
3100 | if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { | 3304 | if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { |
3101 | int err = alc_auto_fill_extra_dacs(codec, cfg->speaker_outs, | 3305 | err = alc_auto_fill_dacs(codec, cfg->speaker_outs, |
3102 | cfg->speaker_pins, | 3306 | cfg->speaker_pins, |
3103 | spec->multiout.extra_out_nid); | 3307 | spec->multiout.extra_out_nid, |
3104 | /* if no speaker volume is assigned, try again as the primary | 3308 | &extra_out_badness); |
3105 | * output | 3309 | if (err < 0) |
3106 | */ | 3310 | return err; |
3107 | if (!err && cfg->speaker_outs > 0 && | 3311 | badness += err; |
3312 | } | ||
3313 | if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { | ||
3314 | err = alc_auto_fill_multi_ios(codec, cfg->line_out_pins[0], false, 0); | ||
3315 | if (err < 0) | ||
3316 | return err; | ||
3317 | badness += err; | ||
3318 | } | ||
3319 | if (cfg->hp_outs && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) { | ||
3320 | /* try multi-ios with HP + inputs */ | ||
3321 | int offset = 0; | ||
3322 | if (cfg->line_outs >= 3) | ||
3323 | offset = 1; | ||
3324 | err = alc_auto_fill_multi_ios(codec, cfg->hp_pins[0], false, | ||
3325 | offset); | ||
3326 | if (err < 0) | ||
3327 | return err; | ||
3328 | badness += err; | ||
3329 | } | ||
3330 | |||
3331 | if (spec->multi_ios == 2) { | ||
3332 | for (i = 0; i < 2; i++) | ||
3333 | spec->private_dac_nids[spec->multiout.num_dacs++] = | ||
3334 | spec->multi_io[i].dac; | ||
3335 | spec->ext_channel_count = 2; | ||
3336 | } else if (spec->multi_ios) { | ||
3337 | spec->multi_ios = 0; | ||
3338 | badness += BAD_MULTI_IO; | ||
3339 | } | ||
3340 | |||
3341 | return badness; | ||
3342 | } | ||
3343 | |||
3344 | #define DEBUG_BADNESS | ||
3345 | |||
3346 | #ifdef DEBUG_BADNESS | ||
3347 | #define debug_badness snd_printdd | ||
3348 | #else | ||
3349 | #define debug_badness(...) | ||
3350 | #endif | ||
3351 | |||
3352 | static void debug_show_configs(struct alc_spec *spec, struct auto_pin_cfg *cfg) | ||
3353 | { | ||
3354 | debug_badness("multi_outs = %x/%x/%x/%x : %x/%x/%x/%x\n", | ||
3355 | cfg->line_out_pins[0], cfg->line_out_pins[1], | ||
3356 | cfg->line_out_pins[2], cfg->line_out_pins[2], | ||
3357 | spec->multiout.dac_nids[0], | ||
3358 | spec->multiout.dac_nids[1], | ||
3359 | spec->multiout.dac_nids[2], | ||
3360 | spec->multiout.dac_nids[3]); | ||
3361 | if (spec->multi_ios > 0) | ||
3362 | debug_badness("multi_ios(%d) = %x/%x : %x/%x\n", | ||
3363 | spec->multi_ios, | ||
3364 | spec->multi_io[0].pin, spec->multi_io[1].pin, | ||
3365 | spec->multi_io[0].dac, spec->multi_io[1].dac); | ||
3366 | debug_badness("hp_outs = %x/%x/%x/%x : %x/%x/%x/%x\n", | ||
3367 | cfg->hp_pins[0], cfg->hp_pins[1], | ||
3368 | cfg->hp_pins[2], cfg->hp_pins[2], | ||
3369 | spec->multiout.hp_out_nid[0], | ||
3370 | spec->multiout.hp_out_nid[1], | ||
3371 | spec->multiout.hp_out_nid[2], | ||
3372 | spec->multiout.hp_out_nid[3]); | ||
3373 | debug_badness("spk_outs = %x/%x/%x/%x : %x/%x/%x/%x\n", | ||
3374 | cfg->speaker_pins[0], cfg->speaker_pins[1], | ||
3375 | cfg->speaker_pins[2], cfg->speaker_pins[3], | ||
3376 | spec->multiout.extra_out_nid[0], | ||
3377 | spec->multiout.extra_out_nid[1], | ||
3378 | spec->multiout.extra_out_nid[2], | ||
3379 | spec->multiout.extra_out_nid[3]); | ||
3380 | } | ||
3381 | |||
3382 | static int alc_auto_fill_dac_nids(struct hda_codec *codec) | ||
3383 | { | ||
3384 | struct alc_spec *spec = codec->spec; | ||
3385 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
3386 | struct auto_pin_cfg *best_cfg; | ||
3387 | int best_badness = INT_MAX; | ||
3388 | int badness; | ||
3389 | bool fill_hardwired = true, fill_mio_first = true; | ||
3390 | bool best_wired = true, best_mio = true; | ||
3391 | bool hp_spk_swapped = false; | ||
3392 | |||
3393 | best_cfg = kmalloc(sizeof(*best_cfg), GFP_KERNEL); | ||
3394 | if (!best_cfg) | ||
3395 | return -ENOMEM; | ||
3396 | *best_cfg = *cfg; | ||
3397 | |||
3398 | for (;;) { | ||
3399 | badness = fill_and_eval_dacs(codec, fill_hardwired, | ||
3400 | fill_mio_first); | ||
3401 | if (badness < 0) | ||
3402 | return badness; | ||
3403 | debug_badness("==> lo_type=%d, wired=%d, mio=%d, badness=0x%x\n", | ||
3404 | cfg->line_out_type, fill_hardwired, fill_mio_first, | ||
3405 | badness); | ||
3406 | debug_show_configs(spec, cfg); | ||
3407 | if (badness < best_badness) { | ||
3408 | best_badness = badness; | ||
3409 | *best_cfg = *cfg; | ||
3410 | best_wired = fill_hardwired; | ||
3411 | best_mio = fill_mio_first; | ||
3412 | } | ||
3413 | if (!badness) | ||
3414 | break; | ||
3415 | fill_mio_first = !fill_mio_first; | ||
3416 | if (!fill_mio_first) | ||
3417 | continue; | ||
3418 | fill_hardwired = !fill_hardwired; | ||
3419 | if (!fill_hardwired) | ||
3420 | continue; | ||
3421 | if (hp_spk_swapped) | ||
3422 | break; | ||
3423 | hp_spk_swapped = true; | ||
3424 | if (cfg->speaker_outs > 0 && | ||
3108 | cfg->line_out_type == AUTO_PIN_HP_OUT) { | 3425 | cfg->line_out_type == AUTO_PIN_HP_OUT) { |
3109 | cfg->hp_outs = cfg->line_outs; | 3426 | cfg->hp_outs = cfg->line_outs; |
3110 | memcpy(cfg->hp_pins, cfg->line_out_pins, | 3427 | memcpy(cfg->hp_pins, cfg->line_out_pins, |
@@ -3115,45 +3432,45 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) | |||
3115 | cfg->speaker_outs = 0; | 3432 | cfg->speaker_outs = 0; |
3116 | memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins)); | 3433 | memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins)); |
3117 | cfg->line_out_type = AUTO_PIN_SPEAKER_OUT; | 3434 | cfg->line_out_type = AUTO_PIN_SPEAKER_OUT; |
3118 | redone = false; | 3435 | fill_hardwired = true; |
3119 | goto again; | 3436 | continue; |
3120 | } | 3437 | } |
3438 | if (cfg->hp_outs > 0 && | ||
3439 | cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) { | ||
3440 | cfg->speaker_outs = cfg->line_outs; | ||
3441 | memcpy(cfg->speaker_pins, cfg->line_out_pins, | ||
3442 | sizeof(cfg->speaker_pins)); | ||
3443 | cfg->line_outs = cfg->hp_outs; | ||
3444 | memcpy(cfg->line_out_pins, cfg->hp_pins, | ||
3445 | sizeof(cfg->hp_pins)); | ||
3446 | cfg->hp_outs = 0; | ||
3447 | memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins)); | ||
3448 | cfg->line_out_type = AUTO_PIN_HP_OUT; | ||
3449 | fill_hardwired = true; | ||
3450 | continue; | ||
3451 | } | ||
3452 | break; | ||
3121 | } | 3453 | } |
3122 | 3454 | ||
3123 | if (!spec->multi_ios && | 3455 | if (badness) { |
3124 | cfg->line_out_type == AUTO_PIN_SPEAKER_OUT && | 3456 | *cfg = *best_cfg; |
3125 | cfg->hp_outs) { | 3457 | fill_and_eval_dacs(codec, best_wired, best_mio); |
3126 | /* try multi-ios with HP + inputs */ | ||
3127 | defcfg = snd_hda_codec_get_pincfg(codec, cfg->hp_pins[0]); | ||
3128 | location = get_defcfg_location(defcfg); | ||
3129 | |||
3130 | num_pins = alc_auto_fill_multi_ios(codec, location, 1); | ||
3131 | if (num_pins > 0) { | ||
3132 | spec->multi_ios = num_pins; | ||
3133 | spec->ext_channel_count = 2; | ||
3134 | spec->multiout.num_dacs = num_pins + 1; | ||
3135 | } | ||
3136 | } | 3458 | } |
3459 | debug_badness("==> Best config: lo_type=%d, wired=%d, mio=%d\n", | ||
3460 | cfg->line_out_type, best_wired, best_mio); | ||
3461 | debug_show_configs(spec, cfg); | ||
3137 | 3462 | ||
3138 | if (cfg->line_out_pins[0]) | 3463 | if (cfg->line_out_pins[0]) |
3139 | spec->vmaster_nid = | 3464 | spec->vmaster_nid = |
3140 | alc_look_for_out_vol_nid(codec, cfg->line_out_pins[0], | 3465 | alc_look_for_out_vol_nid(codec, cfg->line_out_pins[0], |
3141 | spec->multiout.dac_nids[0]); | 3466 | spec->multiout.dac_nids[0]); |
3142 | return 0; | ||
3143 | } | ||
3144 | 3467 | ||
3145 | static inline unsigned int get_ctl_pos(unsigned int data) | 3468 | /* clear the bitmap flags for creating controls */ |
3146 | { | 3469 | clear_vol_marks(codec); |
3147 | hda_nid_t nid = get_amp_nid_(data); | 3470 | kfree(best_cfg); |
3148 | unsigned int dir = get_amp_direction_(data); | 3471 | return 0; |
3149 | return (nid << 1) | dir; | ||
3150 | } | 3472 | } |
3151 | 3473 | ||
3152 | #define is_ctl_used(bits, data) \ | ||
3153 | test_bit(get_ctl_pos(data), bits) | ||
3154 | #define mark_ctl_usage(bits, data) \ | ||
3155 | set_bit(get_ctl_pos(data), bits) | ||
3156 | |||
3157 | static int alc_auto_add_vol_ctl(struct hda_codec *codec, | 3474 | static int alc_auto_add_vol_ctl(struct hda_codec *codec, |
3158 | const char *pfx, int cidx, | 3475 | const char *pfx, int cidx, |
3159 | hda_nid_t nid, unsigned int chs) | 3476 | hda_nid_t nid, unsigned int chs) |
@@ -3265,14 +3582,17 @@ static int alc_auto_create_multi_out_ctls(struct hda_codec *codec, | |||
3265 | dac = spec->multiout.dac_nids[i]; | 3582 | dac = spec->multiout.dac_nids[i]; |
3266 | if (!dac) | 3583 | if (!dac) |
3267 | continue; | 3584 | continue; |
3268 | if (i >= cfg->line_outs) | 3585 | if (i >= cfg->line_outs) { |
3269 | pin = spec->multi_io[i - 1].pin; | 3586 | pin = spec->multi_io[i - 1].pin; |
3270 | else | 3587 | index = 0; |
3588 | name = channel_name[i]; | ||
3589 | } else { | ||
3271 | pin = cfg->line_out_pins[i]; | 3590 | pin = cfg->line_out_pins[i]; |
3591 | name = alc_get_line_out_pfx(spec, i, true, &index); | ||
3592 | } | ||
3272 | 3593 | ||
3273 | sw = alc_look_for_out_mute_nid(codec, pin, dac); | 3594 | sw = alc_look_for_out_mute_nid(codec, pin, dac); |
3274 | vol = alc_look_for_out_vol_nid(codec, pin, dac); | 3595 | vol = alc_look_for_out_vol_nid(codec, pin, dac); |
3275 | name = alc_get_line_out_pfx(spec, i, true, &index); | ||
3276 | if (!name || !strcmp(name, "CLFE")) { | 3596 | if (!name || !strcmp(name, "CLFE")) { |
3277 | /* Center/LFE */ | 3597 | /* Center/LFE */ |
3278 | err = alc_auto_add_vol_ctl(codec, "Center", 0, vol, 1); | 3598 | err = alc_auto_add_vol_ctl(codec, "Center", 0, vol, 1); |
@@ -3369,41 +3689,31 @@ static int alc_auto_create_extra_outs(struct hda_codec *codec, int num_pins, | |||
3369 | return alc_auto_create_extra_out(codec, *pins, dac, pfx, 0); | 3689 | return alc_auto_create_extra_out(codec, *pins, dac, pfx, 0); |
3370 | } | 3690 | } |
3371 | 3691 | ||
3372 | if (dacs[num_pins - 1]) { | ||
3373 | /* OK, we have a multi-output system with individual volumes */ | ||
3374 | for (i = 0; i < num_pins; i++) { | ||
3375 | if (num_pins >= 3) { | ||
3376 | snprintf(name, sizeof(name), "%s %s", | ||
3377 | pfx, channel_name[i]); | ||
3378 | err = alc_auto_create_extra_out(codec, pins[i], dacs[i], | ||
3379 | name, 0); | ||
3380 | } else { | ||
3381 | err = alc_auto_create_extra_out(codec, pins[i], dacs[i], | ||
3382 | pfx, i); | ||
3383 | } | ||
3384 | if (err < 0) | ||
3385 | return err; | ||
3386 | } | ||
3387 | return 0; | ||
3388 | } | ||
3389 | |||
3390 | /* Let's create a bind-controls */ | ||
3391 | ctl = new_bind_ctl(codec, num_pins, &snd_hda_bind_sw); | ||
3392 | if (!ctl) | ||
3393 | return -ENOMEM; | ||
3394 | n = 0; | ||
3395 | for (i = 0; i < num_pins; i++) { | 3692 | for (i = 0; i < num_pins; i++) { |
3396 | if (get_wcaps(codec, pins[i]) & AC_WCAP_OUT_AMP) | 3693 | hda_nid_t dac; |
3397 | ctl->values[n++] = | 3694 | if (dacs[num_pins - 1]) |
3398 | HDA_COMPOSE_AMP_VAL(pins[i], 3, 0, HDA_OUTPUT); | 3695 | dac = dacs[i]; /* with individual volumes */ |
3399 | } | 3696 | else |
3400 | if (n) { | 3697 | dac = 0; |
3401 | snprintf(name, sizeof(name), "%s Playback Switch", pfx); | 3698 | if (num_pins == 2 && i == 1 && !strcmp(pfx, "Speaker")) { |
3402 | err = add_control(spec, ALC_CTL_BIND_SW, name, 0, (long)ctl); | 3699 | err = alc_auto_create_extra_out(codec, pins[i], dac, |
3700 | "Bass Speaker", 0); | ||
3701 | } else if (num_pins >= 3) { | ||
3702 | snprintf(name, sizeof(name), "%s %s", | ||
3703 | pfx, channel_name[i]); | ||
3704 | err = alc_auto_create_extra_out(codec, pins[i], dac, | ||
3705 | name, 0); | ||
3706 | } else { | ||
3707 | err = alc_auto_create_extra_out(codec, pins[i], dac, | ||
3708 | pfx, i); | ||
3709 | } | ||
3403 | if (err < 0) | 3710 | if (err < 0) |
3404 | return err; | 3711 | return err; |
3405 | } | 3712 | } |
3713 | if (dacs[num_pins - 1]) | ||
3714 | return 0; | ||
3406 | 3715 | ||
3716 | /* Let's create a bind-controls for volumes */ | ||
3407 | ctl = new_bind_ctl(codec, num_pins, &snd_hda_bind_vol); | 3717 | ctl = new_bind_ctl(codec, num_pins, &snd_hda_bind_vol); |
3408 | if (!ctl) | 3718 | if (!ctl) |
3409 | return -ENOMEM; | 3719 | return -ENOMEM; |
@@ -3539,58 +3849,111 @@ static void alc_auto_init_extra_out(struct hda_codec *codec) | |||
3539 | } | 3849 | } |
3540 | } | 3850 | } |
3541 | 3851 | ||
3852 | /* check whether the given pin can be a multi-io pin */ | ||
3853 | static bool can_be_multiio_pin(struct hda_codec *codec, | ||
3854 | unsigned int location, hda_nid_t nid) | ||
3855 | { | ||
3856 | unsigned int defcfg, caps; | ||
3857 | |||
3858 | defcfg = snd_hda_codec_get_pincfg(codec, nid); | ||
3859 | if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX) | ||
3860 | return false; | ||
3861 | if (location && get_defcfg_location(defcfg) != location) | ||
3862 | return false; | ||
3863 | caps = snd_hda_query_pin_caps(codec, nid); | ||
3864 | if (!(caps & AC_PINCAP_OUT)) | ||
3865 | return false; | ||
3866 | return true; | ||
3867 | } | ||
3868 | |||
3542 | /* | 3869 | /* |
3543 | * multi-io helper | 3870 | * multi-io helper |
3871 | * | ||
3872 | * When hardwired is set, try to fill ony hardwired pins, and returns | ||
3873 | * zero if any pins are filled, non-zero if nothing found. | ||
3874 | * When hardwired is off, try to fill possible input pins, and returns | ||
3875 | * the badness value. | ||
3544 | */ | 3876 | */ |
3545 | static int alc_auto_fill_multi_ios(struct hda_codec *codec, | 3877 | static int alc_auto_fill_multi_ios(struct hda_codec *codec, |
3546 | unsigned int location, | 3878 | hda_nid_t reference_pin, |
3547 | int offset) | 3879 | bool hardwired, int offset) |
3548 | { | 3880 | { |
3549 | struct alc_spec *spec = codec->spec; | 3881 | struct alc_spec *spec = codec->spec; |
3550 | struct auto_pin_cfg *cfg = &spec->autocfg; | 3882 | struct auto_pin_cfg *cfg = &spec->autocfg; |
3551 | hda_nid_t prime_dac = spec->private_dac_nids[0]; | 3883 | int type, i, j, dacs, num_pins, old_pins; |
3552 | int type, i, dacs, num_pins = 0; | 3884 | unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin); |
3885 | unsigned int location = get_defcfg_location(defcfg); | ||
3886 | int badness = 0; | ||
3887 | |||
3888 | old_pins = spec->multi_ios; | ||
3889 | if (old_pins >= 2) | ||
3890 | goto end_fill; | ||
3891 | |||
3892 | num_pins = 0; | ||
3893 | for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) { | ||
3894 | for (i = 0; i < cfg->num_inputs; i++) { | ||
3895 | if (cfg->inputs[i].type != type) | ||
3896 | continue; | ||
3897 | if (can_be_multiio_pin(codec, location, | ||
3898 | cfg->inputs[i].pin)) | ||
3899 | num_pins++; | ||
3900 | } | ||
3901 | } | ||
3902 | if (num_pins < 2) | ||
3903 | goto end_fill; | ||
3553 | 3904 | ||
3554 | dacs = spec->multiout.num_dacs; | 3905 | dacs = spec->multiout.num_dacs; |
3555 | for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) { | 3906 | for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) { |
3556 | for (i = 0; i < cfg->num_inputs; i++) { | 3907 | for (i = 0; i < cfg->num_inputs; i++) { |
3557 | hda_nid_t nid = cfg->inputs[i].pin; | 3908 | hda_nid_t nid = cfg->inputs[i].pin; |
3558 | hda_nid_t dac = 0; | 3909 | hda_nid_t dac = 0; |
3559 | unsigned int defcfg, caps; | 3910 | |
3560 | if (cfg->inputs[i].type != type) | 3911 | if (cfg->inputs[i].type != type) |
3561 | continue; | 3912 | continue; |
3562 | defcfg = snd_hda_codec_get_pincfg(codec, nid); | 3913 | if (!can_be_multiio_pin(codec, location, nid)) |
3563 | if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX) | ||
3564 | continue; | ||
3565 | if (location && get_defcfg_location(defcfg) != location) | ||
3566 | continue; | 3914 | continue; |
3567 | caps = snd_hda_query_pin_caps(codec, nid); | 3915 | for (j = 0; j < spec->multi_ios; j++) { |
3568 | if (!(caps & AC_PINCAP_OUT)) | 3916 | if (nid == spec->multi_io[j].pin) |
3917 | break; | ||
3918 | } | ||
3919 | if (j < spec->multi_ios) | ||
3569 | continue; | 3920 | continue; |
3570 | if (offset && offset + num_pins < dacs) { | 3921 | |
3571 | dac = spec->private_dac_nids[offset + num_pins]; | 3922 | if (offset && offset + spec->multi_ios < dacs) { |
3923 | dac = spec->private_dac_nids[offset + spec->multi_ios]; | ||
3572 | if (!alc_auto_is_dac_reachable(codec, nid, dac)) | 3924 | if (!alc_auto_is_dac_reachable(codec, nid, dac)) |
3573 | dac = 0; | 3925 | dac = 0; |
3574 | } | 3926 | } |
3575 | if (!dac) | 3927 | if (hardwired) |
3928 | dac = get_dac_if_single(codec, nid); | ||
3929 | else if (!dac) | ||
3576 | dac = alc_auto_look_for_dac(codec, nid); | 3930 | dac = alc_auto_look_for_dac(codec, nid); |
3577 | if (!dac) | 3931 | if (!dac) { |
3932 | badness++; | ||
3578 | continue; | 3933 | continue; |
3579 | spec->multi_io[num_pins].pin = nid; | 3934 | } |
3580 | spec->multi_io[num_pins].dac = dac; | 3935 | spec->multi_io[spec->multi_ios].pin = nid; |
3581 | num_pins++; | 3936 | spec->multi_io[spec->multi_ios].dac = dac; |
3582 | spec->private_dac_nids[spec->multiout.num_dacs++] = dac; | 3937 | spec->multi_ios++; |
3938 | if (spec->multi_ios >= 2) | ||
3939 | break; | ||
3583 | } | 3940 | } |
3584 | } | 3941 | } |
3585 | spec->multiout.num_dacs = dacs; | 3942 | end_fill: |
3586 | if (num_pins < 2) { | 3943 | if (badness) |
3587 | /* clear up again */ | 3944 | badness = BAD_MULTI_IO; |
3588 | memset(spec->private_dac_nids + dacs, 0, | 3945 | if (old_pins == spec->multi_ios) { |
3589 | sizeof(hda_nid_t) * (AUTO_CFG_MAX_OUTS - dacs)); | 3946 | if (hardwired) |
3590 | spec->private_dac_nids[0] = prime_dac; | 3947 | return 1; /* nothing found */ |
3591 | return 0; | 3948 | else |
3949 | return badness; /* no badness if nothing found */ | ||
3950 | } | ||
3951 | if (!hardwired && spec->multi_ios < 2) { | ||
3952 | spec->multi_ios = old_pins; | ||
3953 | return badness; | ||
3592 | } | 3954 | } |
3593 | return num_pins; | 3955 | |
3956 | return 0; | ||
3594 | } | 3957 | } |
3595 | 3958 | ||
3596 | static int alc_auto_ch_mode_info(struct snd_kcontrol *kcontrol, | 3959 | static int alc_auto_ch_mode_info(struct snd_kcontrol *kcontrol, |
@@ -3710,6 +4073,7 @@ static void alc_remove_invalid_adc_nids(struct hda_codec *codec) | |||
3710 | if (spec->dyn_adc_switch) | 4073 | if (spec->dyn_adc_switch) |
3711 | return; | 4074 | return; |
3712 | 4075 | ||
4076 | again: | ||
3713 | nums = 0; | 4077 | nums = 0; |
3714 | for (n = 0; n < spec->num_adc_nids; n++) { | 4078 | for (n = 0; n < spec->num_adc_nids; n++) { |
3715 | hda_nid_t cap = spec->private_capsrc_nids[n]; | 4079 | hda_nid_t cap = spec->private_capsrc_nids[n]; |
@@ -3730,6 +4094,11 @@ static void alc_remove_invalid_adc_nids(struct hda_codec *codec) | |||
3730 | if (!nums) { | 4094 | if (!nums) { |
3731 | /* check whether ADC-switch is possible */ | 4095 | /* check whether ADC-switch is possible */ |
3732 | if (!alc_check_dyn_adc_switch(codec)) { | 4096 | if (!alc_check_dyn_adc_switch(codec)) { |
4097 | if (spec->shared_mic_hp) { | ||
4098 | spec->shared_mic_hp = 0; | ||
4099 | spec->private_imux[0].num_items = 1; | ||
4100 | goto again; | ||
4101 | } | ||
3733 | printk(KERN_WARNING "hda_codec: %s: no valid ADC found;" | 4102 | printk(KERN_WARNING "hda_codec: %s: no valid ADC found;" |
3734 | " using fallback 0x%x\n", | 4103 | " using fallback 0x%x\n", |
3735 | codec->chip_name, spec->private_adc_nids[0]); | 4104 | codec->chip_name, spec->private_adc_nids[0]); |
@@ -3747,7 +4116,7 @@ static void alc_remove_invalid_adc_nids(struct hda_codec *codec) | |||
3747 | 4116 | ||
3748 | if (spec->auto_mic) | 4117 | if (spec->auto_mic) |
3749 | alc_auto_mic_check_imux(codec); /* check auto-mic setups */ | 4118 | alc_auto_mic_check_imux(codec); /* check auto-mic setups */ |
3750 | else if (spec->input_mux->num_items == 1) | 4119 | else if (spec->input_mux->num_items == 1 || spec->shared_mic_hp) |
3751 | spec->num_adc_nids = 1; /* reduce to a single ADC */ | 4120 | spec->num_adc_nids = 1; /* reduce to a single ADC */ |
3752 | } | 4121 | } |
3753 | 4122 | ||
@@ -3788,7 +4157,7 @@ static void alc_auto_init_input_src(struct hda_codec *codec) | |||
3788 | else | 4157 | else |
3789 | nums = spec->num_adc_nids; | 4158 | nums = spec->num_adc_nids; |
3790 | for (c = 0; c < nums; c++) | 4159 | for (c = 0; c < nums; c++) |
3791 | alc_mux_select(codec, 0, spec->cur_mux[c], true); | 4160 | alc_mux_select(codec, c, spec->cur_mux[c], true); |
3792 | } | 4161 | } |
3793 | 4162 | ||
3794 | /* add mic boosts if needed */ | 4163 | /* add mic boosts if needed */ |
@@ -3945,6 +4314,7 @@ static const struct snd_pci_quirk beep_white_list[] = { | |||
3945 | SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1), | 4314 | SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1), |
3946 | SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1), | 4315 | SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1), |
3947 | SND_PCI_QUIRK(0x1043, 0x834a, "EeePC", 1), | 4316 | SND_PCI_QUIRK(0x1043, 0x834a, "EeePC", 1), |
4317 | SND_PCI_QUIRK(0x1458, 0xa002, "GA-MA790X", 1), | ||
3948 | SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1), | 4318 | SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1), |
3949 | {} | 4319 | {} |
3950 | }; | 4320 | }; |
@@ -4044,6 +4414,9 @@ static int alc_parse_auto_config(struct hda_codec *codec, | |||
4044 | if (spec->kctls.list) | 4414 | if (spec->kctls.list) |
4045 | add_mixer(spec, spec->kctls.list); | 4415 | add_mixer(spec, spec->kctls.list); |
4046 | 4416 | ||
4417 | if (!spec->no_analog && !spec->cap_mixer) | ||
4418 | set_capture_mixer(codec); | ||
4419 | |||
4047 | return 1; | 4420 | return 1; |
4048 | } | 4421 | } |
4049 | 4422 | ||
@@ -4054,26 +4427,47 @@ static int alc880_parse_auto_config(struct hda_codec *codec) | |||
4054 | return alc_parse_auto_config(codec, alc880_ignore, alc880_ssids); | 4427 | return alc_parse_auto_config(codec, alc880_ignore, alc880_ssids); |
4055 | } | 4428 | } |
4056 | 4429 | ||
4057 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
4058 | static const struct hda_amp_list alc880_loopbacks[] = { | ||
4059 | { 0x0b, HDA_INPUT, 0 }, | ||
4060 | { 0x0b, HDA_INPUT, 1 }, | ||
4061 | { 0x0b, HDA_INPUT, 2 }, | ||
4062 | { 0x0b, HDA_INPUT, 3 }, | ||
4063 | { 0x0b, HDA_INPUT, 4 }, | ||
4064 | { } /* end */ | ||
4065 | }; | ||
4066 | #endif | ||
4067 | |||
4068 | /* | 4430 | /* |
4069 | * ALC880 fix-ups | 4431 | * ALC880 fix-ups |
4070 | */ | 4432 | */ |
4071 | enum { | 4433 | enum { |
4434 | ALC880_FIXUP_GPIO1, | ||
4072 | ALC880_FIXUP_GPIO2, | 4435 | ALC880_FIXUP_GPIO2, |
4073 | ALC880_FIXUP_MEDION_RIM, | 4436 | ALC880_FIXUP_MEDION_RIM, |
4437 | ALC880_FIXUP_LG, | ||
4438 | ALC880_FIXUP_W810, | ||
4439 | ALC880_FIXUP_EAPD_COEF, | ||
4440 | ALC880_FIXUP_TCL_S700, | ||
4441 | ALC880_FIXUP_VOL_KNOB, | ||
4442 | ALC880_FIXUP_FUJITSU, | ||
4443 | ALC880_FIXUP_F1734, | ||
4444 | ALC880_FIXUP_UNIWILL, | ||
4445 | ALC880_FIXUP_UNIWILL_DIG, | ||
4446 | ALC880_FIXUP_Z71V, | ||
4447 | ALC880_FIXUP_3ST_BASE, | ||
4448 | ALC880_FIXUP_3ST, | ||
4449 | ALC880_FIXUP_3ST_DIG, | ||
4450 | ALC880_FIXUP_5ST_BASE, | ||
4451 | ALC880_FIXUP_5ST, | ||
4452 | ALC880_FIXUP_5ST_DIG, | ||
4453 | ALC880_FIXUP_6ST_BASE, | ||
4454 | ALC880_FIXUP_6ST, | ||
4455 | ALC880_FIXUP_6ST_DIG, | ||
4074 | }; | 4456 | }; |
4075 | 4457 | ||
4458 | /* enable the volume-knob widget support on NID 0x21 */ | ||
4459 | static void alc880_fixup_vol_knob(struct hda_codec *codec, | ||
4460 | const struct alc_fixup *fix, int action) | ||
4461 | { | ||
4462 | if (action == ALC_FIXUP_ACT_PROBE) | ||
4463 | snd_hda_jack_detect_enable(codec, 0x21, ALC_DCVOL_EVENT); | ||
4464 | } | ||
4465 | |||
4076 | static const struct alc_fixup alc880_fixups[] = { | 4466 | static const struct alc_fixup alc880_fixups[] = { |
4467 | [ALC880_FIXUP_GPIO1] = { | ||
4468 | .type = ALC_FIXUP_VERBS, | ||
4469 | .v.verbs = alc_gpio1_init_verbs, | ||
4470 | }, | ||
4077 | [ALC880_FIXUP_GPIO2] = { | 4471 | [ALC880_FIXUP_GPIO2] = { |
4078 | .type = ALC_FIXUP_VERBS, | 4472 | .type = ALC_FIXUP_VERBS, |
4079 | .v.verbs = alc_gpio2_init_verbs, | 4473 | .v.verbs = alc_gpio2_init_verbs, |
@@ -4088,40 +4482,323 @@ static const struct alc_fixup alc880_fixups[] = { | |||
4088 | .chained = true, | 4482 | .chained = true, |
4089 | .chain_id = ALC880_FIXUP_GPIO2, | 4483 | .chain_id = ALC880_FIXUP_GPIO2, |
4090 | }, | 4484 | }, |
4485 | [ALC880_FIXUP_LG] = { | ||
4486 | .type = ALC_FIXUP_PINS, | ||
4487 | .v.pins = (const struct alc_pincfg[]) { | ||
4488 | /* disable bogus unused pins */ | ||
4489 | { 0x16, 0x411111f0 }, | ||
4490 | { 0x18, 0x411111f0 }, | ||
4491 | { 0x1a, 0x411111f0 }, | ||
4492 | { } | ||
4493 | } | ||
4494 | }, | ||
4495 | [ALC880_FIXUP_W810] = { | ||
4496 | .type = ALC_FIXUP_PINS, | ||
4497 | .v.pins = (const struct alc_pincfg[]) { | ||
4498 | /* disable bogus unused pins */ | ||
4499 | { 0x17, 0x411111f0 }, | ||
4500 | { } | ||
4501 | }, | ||
4502 | .chained = true, | ||
4503 | .chain_id = ALC880_FIXUP_GPIO2, | ||
4504 | }, | ||
4505 | [ALC880_FIXUP_EAPD_COEF] = { | ||
4506 | .type = ALC_FIXUP_VERBS, | ||
4507 | .v.verbs = (const struct hda_verb[]) { | ||
4508 | /* change to EAPD mode */ | ||
4509 | { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 }, | ||
4510 | { 0x20, AC_VERB_SET_PROC_COEF, 0x3060 }, | ||
4511 | {} | ||
4512 | }, | ||
4513 | }, | ||
4514 | [ALC880_FIXUP_TCL_S700] = { | ||
4515 | .type = ALC_FIXUP_VERBS, | ||
4516 | .v.verbs = (const struct hda_verb[]) { | ||
4517 | /* change to EAPD mode */ | ||
4518 | { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 }, | ||
4519 | { 0x20, AC_VERB_SET_PROC_COEF, 0x3070 }, | ||
4520 | {} | ||
4521 | }, | ||
4522 | .chained = true, | ||
4523 | .chain_id = ALC880_FIXUP_GPIO2, | ||
4524 | }, | ||
4525 | [ALC880_FIXUP_VOL_KNOB] = { | ||
4526 | .type = ALC_FIXUP_FUNC, | ||
4527 | .v.func = alc880_fixup_vol_knob, | ||
4528 | }, | ||
4529 | [ALC880_FIXUP_FUJITSU] = { | ||
4530 | /* override all pins as BIOS on old Amilo is broken */ | ||
4531 | .type = ALC_FIXUP_PINS, | ||
4532 | .v.pins = (const struct alc_pincfg[]) { | ||
4533 | { 0x14, 0x0121411f }, /* HP */ | ||
4534 | { 0x15, 0x99030120 }, /* speaker */ | ||
4535 | { 0x16, 0x99030130 }, /* bass speaker */ | ||
4536 | { 0x17, 0x411111f0 }, /* N/A */ | ||
4537 | { 0x18, 0x411111f0 }, /* N/A */ | ||
4538 | { 0x19, 0x01a19950 }, /* mic-in */ | ||
4539 | { 0x1a, 0x411111f0 }, /* N/A */ | ||
4540 | { 0x1b, 0x411111f0 }, /* N/A */ | ||
4541 | { 0x1c, 0x411111f0 }, /* N/A */ | ||
4542 | { 0x1d, 0x411111f0 }, /* N/A */ | ||
4543 | { 0x1e, 0x01454140 }, /* SPDIF out */ | ||
4544 | { } | ||
4545 | }, | ||
4546 | .chained = true, | ||
4547 | .chain_id = ALC880_FIXUP_VOL_KNOB, | ||
4548 | }, | ||
4549 | [ALC880_FIXUP_F1734] = { | ||
4550 | /* almost compatible with FUJITSU, but no bass and SPDIF */ | ||
4551 | .type = ALC_FIXUP_PINS, | ||
4552 | .v.pins = (const struct alc_pincfg[]) { | ||
4553 | { 0x14, 0x0121411f }, /* HP */ | ||
4554 | { 0x15, 0x99030120 }, /* speaker */ | ||
4555 | { 0x16, 0x411111f0 }, /* N/A */ | ||
4556 | { 0x17, 0x411111f0 }, /* N/A */ | ||
4557 | { 0x18, 0x411111f0 }, /* N/A */ | ||
4558 | { 0x19, 0x01a19950 }, /* mic-in */ | ||
4559 | { 0x1a, 0x411111f0 }, /* N/A */ | ||
4560 | { 0x1b, 0x411111f0 }, /* N/A */ | ||
4561 | { 0x1c, 0x411111f0 }, /* N/A */ | ||
4562 | { 0x1d, 0x411111f0 }, /* N/A */ | ||
4563 | { 0x1e, 0x411111f0 }, /* N/A */ | ||
4564 | { } | ||
4565 | }, | ||
4566 | .chained = true, | ||
4567 | .chain_id = ALC880_FIXUP_VOL_KNOB, | ||
4568 | }, | ||
4569 | [ALC880_FIXUP_UNIWILL] = { | ||
4570 | /* need to fix HP and speaker pins to be parsed correctly */ | ||
4571 | .type = ALC_FIXUP_PINS, | ||
4572 | .v.pins = (const struct alc_pincfg[]) { | ||
4573 | { 0x14, 0x0121411f }, /* HP */ | ||
4574 | { 0x15, 0x99030120 }, /* speaker */ | ||
4575 | { 0x16, 0x99030130 }, /* bass speaker */ | ||
4576 | { } | ||
4577 | }, | ||
4578 | }, | ||
4579 | [ALC880_FIXUP_UNIWILL_DIG] = { | ||
4580 | .type = ALC_FIXUP_PINS, | ||
4581 | .v.pins = (const struct alc_pincfg[]) { | ||
4582 | /* disable bogus unused pins */ | ||
4583 | { 0x17, 0x411111f0 }, | ||
4584 | { 0x19, 0x411111f0 }, | ||
4585 | { 0x1b, 0x411111f0 }, | ||
4586 | { 0x1f, 0x411111f0 }, | ||
4587 | { } | ||
4588 | } | ||
4589 | }, | ||
4590 | [ALC880_FIXUP_Z71V] = { | ||
4591 | .type = ALC_FIXUP_PINS, | ||
4592 | .v.pins = (const struct alc_pincfg[]) { | ||
4593 | /* set up the whole pins as BIOS is utterly broken */ | ||
4594 | { 0x14, 0x99030120 }, /* speaker */ | ||
4595 | { 0x15, 0x0121411f }, /* HP */ | ||
4596 | { 0x16, 0x411111f0 }, /* N/A */ | ||
4597 | { 0x17, 0x411111f0 }, /* N/A */ | ||
4598 | { 0x18, 0x01a19950 }, /* mic-in */ | ||
4599 | { 0x19, 0x411111f0 }, /* N/A */ | ||
4600 | { 0x1a, 0x01813031 }, /* line-in */ | ||
4601 | { 0x1b, 0x411111f0 }, /* N/A */ | ||
4602 | { 0x1c, 0x411111f0 }, /* N/A */ | ||
4603 | { 0x1d, 0x411111f0 }, /* N/A */ | ||
4604 | { 0x1e, 0x0144111e }, /* SPDIF */ | ||
4605 | { } | ||
4606 | } | ||
4607 | }, | ||
4608 | [ALC880_FIXUP_3ST_BASE] = { | ||
4609 | .type = ALC_FIXUP_PINS, | ||
4610 | .v.pins = (const struct alc_pincfg[]) { | ||
4611 | { 0x14, 0x01014010 }, /* line-out */ | ||
4612 | { 0x15, 0x411111f0 }, /* N/A */ | ||
4613 | { 0x16, 0x411111f0 }, /* N/A */ | ||
4614 | { 0x17, 0x411111f0 }, /* N/A */ | ||
4615 | { 0x18, 0x01a19c30 }, /* mic-in */ | ||
4616 | { 0x19, 0x0121411f }, /* HP */ | ||
4617 | { 0x1a, 0x01813031 }, /* line-in */ | ||
4618 | { 0x1b, 0x02a19c40 }, /* front-mic */ | ||
4619 | { 0x1c, 0x411111f0 }, /* N/A */ | ||
4620 | { 0x1d, 0x411111f0 }, /* N/A */ | ||
4621 | /* 0x1e is filled in below */ | ||
4622 | { 0x1f, 0x411111f0 }, /* N/A */ | ||
4623 | { } | ||
4624 | } | ||
4625 | }, | ||
4626 | [ALC880_FIXUP_3ST] = { | ||
4627 | .type = ALC_FIXUP_PINS, | ||
4628 | .v.pins = (const struct alc_pincfg[]) { | ||
4629 | { 0x1e, 0x411111f0 }, /* N/A */ | ||
4630 | { } | ||
4631 | }, | ||
4632 | .chained = true, | ||
4633 | .chain_id = ALC880_FIXUP_3ST_BASE, | ||
4634 | }, | ||
4635 | [ALC880_FIXUP_3ST_DIG] = { | ||
4636 | .type = ALC_FIXUP_PINS, | ||
4637 | .v.pins = (const struct alc_pincfg[]) { | ||
4638 | { 0x1e, 0x0144111e }, /* SPDIF */ | ||
4639 | { } | ||
4640 | }, | ||
4641 | .chained = true, | ||
4642 | .chain_id = ALC880_FIXUP_3ST_BASE, | ||
4643 | }, | ||
4644 | [ALC880_FIXUP_5ST_BASE] = { | ||
4645 | .type = ALC_FIXUP_PINS, | ||
4646 | .v.pins = (const struct alc_pincfg[]) { | ||
4647 | { 0x14, 0x01014010 }, /* front */ | ||
4648 | { 0x15, 0x411111f0 }, /* N/A */ | ||
4649 | { 0x16, 0x01011411 }, /* CLFE */ | ||
4650 | { 0x17, 0x01016412 }, /* surr */ | ||
4651 | { 0x18, 0x01a19c30 }, /* mic-in */ | ||
4652 | { 0x19, 0x0121411f }, /* HP */ | ||
4653 | { 0x1a, 0x01813031 }, /* line-in */ | ||
4654 | { 0x1b, 0x02a19c40 }, /* front-mic */ | ||
4655 | { 0x1c, 0x411111f0 }, /* N/A */ | ||
4656 | { 0x1d, 0x411111f0 }, /* N/A */ | ||
4657 | /* 0x1e is filled in below */ | ||
4658 | { 0x1f, 0x411111f0 }, /* N/A */ | ||
4659 | { } | ||
4660 | } | ||
4661 | }, | ||
4662 | [ALC880_FIXUP_5ST] = { | ||
4663 | .type = ALC_FIXUP_PINS, | ||
4664 | .v.pins = (const struct alc_pincfg[]) { | ||
4665 | { 0x1e, 0x411111f0 }, /* N/A */ | ||
4666 | { } | ||
4667 | }, | ||
4668 | .chained = true, | ||
4669 | .chain_id = ALC880_FIXUP_5ST_BASE, | ||
4670 | }, | ||
4671 | [ALC880_FIXUP_5ST_DIG] = { | ||
4672 | .type = ALC_FIXUP_PINS, | ||
4673 | .v.pins = (const struct alc_pincfg[]) { | ||
4674 | { 0x1e, 0x0144111e }, /* SPDIF */ | ||
4675 | { } | ||
4676 | }, | ||
4677 | .chained = true, | ||
4678 | .chain_id = ALC880_FIXUP_5ST_BASE, | ||
4679 | }, | ||
4680 | [ALC880_FIXUP_6ST_BASE] = { | ||
4681 | .type = ALC_FIXUP_PINS, | ||
4682 | .v.pins = (const struct alc_pincfg[]) { | ||
4683 | { 0x14, 0x01014010 }, /* front */ | ||
4684 | { 0x15, 0x01016412 }, /* surr */ | ||
4685 | { 0x16, 0x01011411 }, /* CLFE */ | ||
4686 | { 0x17, 0x01012414 }, /* side */ | ||
4687 | { 0x18, 0x01a19c30 }, /* mic-in */ | ||
4688 | { 0x19, 0x02a19c40 }, /* front-mic */ | ||
4689 | { 0x1a, 0x01813031 }, /* line-in */ | ||
4690 | { 0x1b, 0x0121411f }, /* HP */ | ||
4691 | { 0x1c, 0x411111f0 }, /* N/A */ | ||
4692 | { 0x1d, 0x411111f0 }, /* N/A */ | ||
4693 | /* 0x1e is filled in below */ | ||
4694 | { 0x1f, 0x411111f0 }, /* N/A */ | ||
4695 | { } | ||
4696 | } | ||
4697 | }, | ||
4698 | [ALC880_FIXUP_6ST] = { | ||
4699 | .type = ALC_FIXUP_PINS, | ||
4700 | .v.pins = (const struct alc_pincfg[]) { | ||
4701 | { 0x1e, 0x411111f0 }, /* N/A */ | ||
4702 | { } | ||
4703 | }, | ||
4704 | .chained = true, | ||
4705 | .chain_id = ALC880_FIXUP_6ST_BASE, | ||
4706 | }, | ||
4707 | [ALC880_FIXUP_6ST_DIG] = { | ||
4708 | .type = ALC_FIXUP_PINS, | ||
4709 | .v.pins = (const struct alc_pincfg[]) { | ||
4710 | { 0x1e, 0x0144111e }, /* SPDIF */ | ||
4711 | { } | ||
4712 | }, | ||
4713 | .chained = true, | ||
4714 | .chain_id = ALC880_FIXUP_6ST_BASE, | ||
4715 | }, | ||
4091 | }; | 4716 | }; |
4092 | 4717 | ||
4093 | static const struct snd_pci_quirk alc880_fixup_tbl[] = { | 4718 | static const struct snd_pci_quirk alc880_fixup_tbl[] = { |
4719 | SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_FIXUP_W810), | ||
4720 | SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_FIXUP_Z71V), | ||
4721 | SND_PCI_QUIRK_VENDOR(0x1043, "ASUS", ALC880_FIXUP_GPIO1), | ||
4722 | SND_PCI_QUIRK(0x1558, 0x5401, "Clevo GPIO2", ALC880_FIXUP_GPIO2), | ||
4723 | SND_PCI_QUIRK_VENDOR(0x1558, "Clevo", ALC880_FIXUP_EAPD_COEF), | ||
4724 | SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_FIXUP_UNIWILL_DIG), | ||
4725 | SND_PCI_QUIRK(0x1584, 0x9054, "Uniwill", ALC880_FIXUP_F1734), | ||
4726 | SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_FIXUP_UNIWILL), | ||
4727 | SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_FIXUP_VOL_KNOB), | ||
4728 | SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_FIXUP_W810), | ||
4094 | SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_FIXUP_MEDION_RIM), | 4729 | SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_FIXUP_MEDION_RIM), |
4730 | SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_FIXUP_F1734), | ||
4731 | SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FIXUP_FUJITSU), | ||
4732 | SND_PCI_QUIRK(0x1734, 0x10ac, "FSC AMILO Xi 1526", ALC880_FIXUP_F1734), | ||
4733 | SND_PCI_QUIRK(0x1734, 0x10b0, "FSC Amilo Pi1556", ALC880_FIXUP_FUJITSU), | ||
4734 | SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_FIXUP_LG), | ||
4735 | SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_FIXUP_LG), | ||
4736 | SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_FIXUP_LG), | ||
4737 | SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_FIXUP_TCL_S700), | ||
4738 | |||
4739 | /* Below is the copied entries from alc880_quirks.c. | ||
4740 | * It's not quite sure whether BIOS sets the correct pin-config table | ||
4741 | * on these machines, thus they are kept to be compatible with | ||
4742 | * the old static quirks. Once when it's confirmed to work without | ||
4743 | * these overrides, it'd be better to remove. | ||
4744 | */ | ||
4745 | SND_PCI_QUIRK(0x1019, 0xa880, "ECS", ALC880_FIXUP_5ST_DIG), | ||
4746 | SND_PCI_QUIRK(0x1019, 0xa884, "Acer APFV", ALC880_FIXUP_6ST), | ||
4747 | SND_PCI_QUIRK(0x1025, 0x0070, "ULI", ALC880_FIXUP_3ST_DIG), | ||
4748 | SND_PCI_QUIRK(0x1025, 0x0077, "ULI", ALC880_FIXUP_6ST_DIG), | ||
4749 | SND_PCI_QUIRK(0x1025, 0x0078, "ULI", ALC880_FIXUP_6ST_DIG), | ||
4750 | SND_PCI_QUIRK(0x1025, 0x0087, "ULI", ALC880_FIXUP_6ST_DIG), | ||
4751 | SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_FIXUP_3ST_DIG), | ||
4752 | SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_FIXUP_3ST), | ||
4753 | SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_FIXUP_6ST_DIG), | ||
4754 | SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_FIXUP_3ST), | ||
4755 | SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_FIXUP_3ST), | ||
4756 | SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_FIXUP_5ST), | ||
4757 | SND_PCI_QUIRK(0x107b, 0x3033, "Gateway", ALC880_FIXUP_5ST), | ||
4758 | SND_PCI_QUIRK(0x107b, 0x4039, "Gateway", ALC880_FIXUP_5ST), | ||
4759 | SND_PCI_QUIRK(0x1297, 0xc790, "Shuttle ST20G5", ALC880_FIXUP_6ST_DIG), | ||
4760 | SND_PCI_QUIRK(0x1458, 0xa102, "Gigabyte K8", ALC880_FIXUP_6ST_DIG), | ||
4761 | SND_PCI_QUIRK(0x1462, 0x1150, "MSI", ALC880_FIXUP_6ST_DIG), | ||
4762 | SND_PCI_QUIRK(0x1509, 0x925d, "FIC P4M", ALC880_FIXUP_6ST_DIG), | ||
4763 | SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_FIXUP_5ST_DIG), | ||
4764 | SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_FIXUP_5ST_DIG), | ||
4765 | SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_FIXUP_5ST_DIG), | ||
4766 | SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_FIXUP_6ST_DIG), /* broken BIOS */ | ||
4767 | SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_FIXUP_6ST_DIG), | ||
4768 | SND_PCI_QUIRK(0x8086, 0xa100, "Intel mobo", ALC880_FIXUP_5ST_DIG), | ||
4769 | SND_PCI_QUIRK(0x8086, 0xd400, "Intel mobo", ALC880_FIXUP_5ST_DIG), | ||
4770 | SND_PCI_QUIRK(0x8086, 0xd401, "Intel mobo", ALC880_FIXUP_5ST_DIG), | ||
4771 | SND_PCI_QUIRK(0x8086, 0xd402, "Intel mobo", ALC880_FIXUP_3ST_DIG), | ||
4772 | SND_PCI_QUIRK(0x8086, 0xe224, "Intel mobo", ALC880_FIXUP_5ST_DIG), | ||
4773 | SND_PCI_QUIRK(0x8086, 0xe305, "Intel mobo", ALC880_FIXUP_3ST_DIG), | ||
4774 | SND_PCI_QUIRK(0x8086, 0xe308, "Intel mobo", ALC880_FIXUP_3ST_DIG), | ||
4775 | SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_FIXUP_5ST_DIG), | ||
4776 | SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_FIXUP_5ST_DIG), | ||
4777 | SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_FIXUP_5ST_DIG), | ||
4778 | /* default Intel */ | ||
4779 | SND_PCI_QUIRK_VENDOR(0x8086, "Intel mobo", ALC880_FIXUP_3ST), | ||
4780 | SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_FIXUP_5ST_DIG), | ||
4781 | SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_FIXUP_6ST_DIG), | ||
4095 | {} | 4782 | {} |
4096 | }; | 4783 | }; |
4097 | 4784 | ||
4785 | static const struct alc_model_fixup alc880_fixup_models[] = { | ||
4786 | {.id = ALC880_FIXUP_3ST, .name = "3stack"}, | ||
4787 | {.id = ALC880_FIXUP_3ST_DIG, .name = "3stack-digout"}, | ||
4788 | {.id = ALC880_FIXUP_5ST, .name = "5stack"}, | ||
4789 | {.id = ALC880_FIXUP_5ST_DIG, .name = "5stack-digout"}, | ||
4790 | {.id = ALC880_FIXUP_6ST, .name = "6stack"}, | ||
4791 | {.id = ALC880_FIXUP_6ST_DIG, .name = "6stack-digout"}, | ||
4792 | {} | ||
4793 | }; | ||
4098 | 4794 | ||
4099 | /* | ||
4100 | * board setups | ||
4101 | */ | ||
4102 | #ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS | ||
4103 | #define alc_board_config \ | ||
4104 | snd_hda_check_board_config | ||
4105 | #define alc_board_codec_sid_config \ | ||
4106 | snd_hda_check_board_codec_sid_config | ||
4107 | #include "alc_quirks.c" | ||
4108 | #else | ||
4109 | #define alc_board_config(codec, nums, models, tbl) -1 | ||
4110 | #define alc_board_codec_sid_config(codec, nums, models, tbl) -1 | ||
4111 | #define setup_preset(codec, x) /* NOP */ | ||
4112 | #endif | ||
4113 | 4795 | ||
4114 | /* | 4796 | /* |
4115 | * OK, here we have finally the patch for ALC880 | 4797 | * OK, here we have finally the patch for ALC880 |
4116 | */ | 4798 | */ |
4117 | #ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS | ||
4118 | #include "alc880_quirks.c" | ||
4119 | #endif | ||
4120 | |||
4121 | static int patch_alc880(struct hda_codec *codec) | 4799 | static int patch_alc880(struct hda_codec *codec) |
4122 | { | 4800 | { |
4123 | struct alc_spec *spec; | 4801 | struct alc_spec *spec; |
4124 | int board_config; | ||
4125 | int err; | 4802 | int err; |
4126 | 4803 | ||
4127 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 4804 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
@@ -4133,47 +4810,14 @@ static int patch_alc880(struct hda_codec *codec) | |||
4133 | spec->mixer_nid = 0x0b; | 4810 | spec->mixer_nid = 0x0b; |
4134 | spec->need_dac_fix = 1; | 4811 | spec->need_dac_fix = 1; |
4135 | 4812 | ||
4136 | board_config = alc_board_config(codec, ALC880_MODEL_LAST, | 4813 | alc_pick_fixup(codec, alc880_fixup_models, alc880_fixup_tbl, |
4137 | alc880_models, alc880_cfg_tbl); | 4814 | alc880_fixups); |
4138 | if (board_config < 0) { | 4815 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); |
4139 | printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", | ||
4140 | codec->chip_name); | ||
4141 | board_config = ALC_MODEL_AUTO; | ||
4142 | } | ||
4143 | |||
4144 | if (board_config == ALC_MODEL_AUTO) { | ||
4145 | alc_pick_fixup(codec, NULL, alc880_fixup_tbl, alc880_fixups); | ||
4146 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); | ||
4147 | } | ||
4148 | |||
4149 | if (board_config == ALC_MODEL_AUTO) { | ||
4150 | /* automatic parse from the BIOS config */ | ||
4151 | err = alc880_parse_auto_config(codec); | ||
4152 | if (err < 0) | ||
4153 | goto error; | ||
4154 | #ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS | ||
4155 | else if (!err) { | ||
4156 | printk(KERN_INFO | ||
4157 | "hda_codec: Cannot set up configuration " | ||
4158 | "from BIOS. Using 3-stack mode...\n"); | ||
4159 | board_config = ALC880_3ST; | ||
4160 | } | ||
4161 | #endif | ||
4162 | } | ||
4163 | |||
4164 | if (board_config != ALC_MODEL_AUTO) { | ||
4165 | spec->vmaster_nid = 0x0c; | ||
4166 | setup_preset(codec, &alc880_presets[board_config]); | ||
4167 | } | ||
4168 | |||
4169 | if (!spec->no_analog && !spec->adc_nids) { | ||
4170 | alc_auto_fill_adc_caps(codec); | ||
4171 | alc_rebuild_imux_for_auto_mic(codec); | ||
4172 | alc_remove_invalid_adc_nids(codec); | ||
4173 | } | ||
4174 | 4816 | ||
4175 | if (!spec->no_analog && !spec->cap_mixer) | 4817 | /* automatic parse from the BIOS config */ |
4176 | set_capture_mixer(codec); | 4818 | err = alc880_parse_auto_config(codec); |
4819 | if (err < 0) | ||
4820 | goto error; | ||
4177 | 4821 | ||
4178 | if (!spec->no_analog) { | 4822 | if (!spec->no_analog) { |
4179 | err = snd_hda_attach_beep_device(codec, 0x1); | 4823 | err = snd_hda_attach_beep_device(codec, 0x1); |
@@ -4182,17 +4826,9 @@ static int patch_alc880(struct hda_codec *codec) | |||
4182 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | 4826 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); |
4183 | } | 4827 | } |
4184 | 4828 | ||
4185 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); | ||
4186 | |||
4187 | codec->patch_ops = alc_patch_ops; | 4829 | codec->patch_ops = alc_patch_ops; |
4188 | if (board_config == ALC_MODEL_AUTO) | 4830 | |
4189 | spec->init_hook = alc_auto_init_std; | 4831 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); |
4190 | else | ||
4191 | codec->patch_ops.build_controls = __alc_build_controls; | ||
4192 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
4193 | if (!spec->loopback.amplist) | ||
4194 | spec->loopback.amplist = alc880_loopbacks; | ||
4195 | #endif | ||
4196 | 4832 | ||
4197 | return 0; | 4833 | return 0; |
4198 | 4834 | ||
@@ -4212,49 +4848,115 @@ static int alc260_parse_auto_config(struct hda_codec *codec) | |||
4212 | return alc_parse_auto_config(codec, alc260_ignore, alc260_ssids); | 4848 | return alc_parse_auto_config(codec, alc260_ignore, alc260_ssids); |
4213 | } | 4849 | } |
4214 | 4850 | ||
4215 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
4216 | static const struct hda_amp_list alc260_loopbacks[] = { | ||
4217 | { 0x07, HDA_INPUT, 0 }, | ||
4218 | { 0x07, HDA_INPUT, 1 }, | ||
4219 | { 0x07, HDA_INPUT, 2 }, | ||
4220 | { 0x07, HDA_INPUT, 3 }, | ||
4221 | { 0x07, HDA_INPUT, 4 }, | ||
4222 | { } /* end */ | ||
4223 | }; | ||
4224 | #endif | ||
4225 | |||
4226 | /* | 4851 | /* |
4227 | * Pin config fixes | 4852 | * Pin config fixes |
4228 | */ | 4853 | */ |
4229 | enum { | 4854 | enum { |
4230 | PINFIX_HP_DC5750, | 4855 | ALC260_FIXUP_HP_DC5750, |
4856 | ALC260_FIXUP_HP_PIN_0F, | ||
4857 | ALC260_FIXUP_COEF, | ||
4858 | ALC260_FIXUP_GPIO1, | ||
4859 | ALC260_FIXUP_GPIO1_TOGGLE, | ||
4860 | ALC260_FIXUP_REPLACER, | ||
4861 | ALC260_FIXUP_HP_B1900, | ||
4231 | }; | 4862 | }; |
4232 | 4863 | ||
4864 | static void alc260_gpio1_automute(struct hda_codec *codec) | ||
4865 | { | ||
4866 | struct alc_spec *spec = codec->spec; | ||
4867 | snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, | ||
4868 | spec->hp_jack_present); | ||
4869 | } | ||
4870 | |||
4871 | static void alc260_fixup_gpio1_toggle(struct hda_codec *codec, | ||
4872 | const struct alc_fixup *fix, int action) | ||
4873 | { | ||
4874 | struct alc_spec *spec = codec->spec; | ||
4875 | if (action == ALC_FIXUP_ACT_PROBE) { | ||
4876 | /* although the machine has only one output pin, we need to | ||
4877 | * toggle GPIO1 according to the jack state | ||
4878 | */ | ||
4879 | spec->automute_hook = alc260_gpio1_automute; | ||
4880 | spec->detect_hp = 1; | ||
4881 | spec->automute_speaker = 1; | ||
4882 | spec->autocfg.hp_pins[0] = 0x0f; /* copy it for automute */ | ||
4883 | snd_hda_jack_detect_enable(codec, 0x0f, ALC_HP_EVENT); | ||
4884 | spec->unsol_event = alc_sku_unsol_event; | ||
4885 | add_verb(codec->spec, alc_gpio1_init_verbs); | ||
4886 | } | ||
4887 | } | ||
4888 | |||
4233 | static const struct alc_fixup alc260_fixups[] = { | 4889 | static const struct alc_fixup alc260_fixups[] = { |
4234 | [PINFIX_HP_DC5750] = { | 4890 | [ALC260_FIXUP_HP_DC5750] = { |
4235 | .type = ALC_FIXUP_PINS, | 4891 | .type = ALC_FIXUP_PINS, |
4236 | .v.pins = (const struct alc_pincfg[]) { | 4892 | .v.pins = (const struct alc_pincfg[]) { |
4237 | { 0x11, 0x90130110 }, /* speaker */ | 4893 | { 0x11, 0x90130110 }, /* speaker */ |
4238 | { } | 4894 | { } |
4239 | } | 4895 | } |
4240 | }, | 4896 | }, |
4897 | [ALC260_FIXUP_HP_PIN_0F] = { | ||
4898 | .type = ALC_FIXUP_PINS, | ||
4899 | .v.pins = (const struct alc_pincfg[]) { | ||
4900 | { 0x0f, 0x01214000 }, /* HP */ | ||
4901 | { } | ||
4902 | } | ||
4903 | }, | ||
4904 | [ALC260_FIXUP_COEF] = { | ||
4905 | .type = ALC_FIXUP_VERBS, | ||
4906 | .v.verbs = (const struct hda_verb[]) { | ||
4907 | { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 }, | ||
4908 | { 0x20, AC_VERB_SET_PROC_COEF, 0x3040 }, | ||
4909 | { } | ||
4910 | }, | ||
4911 | .chained = true, | ||
4912 | .chain_id = ALC260_FIXUP_HP_PIN_0F, | ||
4913 | }, | ||
4914 | [ALC260_FIXUP_GPIO1] = { | ||
4915 | .type = ALC_FIXUP_VERBS, | ||
4916 | .v.verbs = alc_gpio1_init_verbs, | ||
4917 | }, | ||
4918 | [ALC260_FIXUP_GPIO1_TOGGLE] = { | ||
4919 | .type = ALC_FIXUP_FUNC, | ||
4920 | .v.func = alc260_fixup_gpio1_toggle, | ||
4921 | .chained = true, | ||
4922 | .chain_id = ALC260_FIXUP_HP_PIN_0F, | ||
4923 | }, | ||
4924 | [ALC260_FIXUP_REPLACER] = { | ||
4925 | .type = ALC_FIXUP_VERBS, | ||
4926 | .v.verbs = (const struct hda_verb[]) { | ||
4927 | { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 }, | ||
4928 | { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 }, | ||
4929 | { } | ||
4930 | }, | ||
4931 | .chained = true, | ||
4932 | .chain_id = ALC260_FIXUP_GPIO1_TOGGLE, | ||
4933 | }, | ||
4934 | [ALC260_FIXUP_HP_B1900] = { | ||
4935 | .type = ALC_FIXUP_FUNC, | ||
4936 | .v.func = alc260_fixup_gpio1_toggle, | ||
4937 | .chained = true, | ||
4938 | .chain_id = ALC260_FIXUP_COEF, | ||
4939 | } | ||
4241 | }; | 4940 | }; |
4242 | 4941 | ||
4243 | static const struct snd_pci_quirk alc260_fixup_tbl[] = { | 4942 | static const struct snd_pci_quirk alc260_fixup_tbl[] = { |
4244 | SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", PINFIX_HP_DC5750), | 4943 | SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_FIXUP_GPIO1), |
4944 | SND_PCI_QUIRK(0x1025, 0x007f, "Acer Aspire 9500", ALC260_FIXUP_COEF), | ||
4945 | SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_FIXUP_GPIO1), | ||
4946 | SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", ALC260_FIXUP_HP_DC5750), | ||
4947 | SND_PCI_QUIRK(0x103c, 0x30ba, "HP Presario B1900", ALC260_FIXUP_HP_B1900), | ||
4948 | SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FIXUP_GPIO1), | ||
4949 | SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_FIXUP_REPLACER), | ||
4950 | SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_FIXUP_COEF), | ||
4245 | {} | 4951 | {} |
4246 | }; | 4952 | }; |
4247 | 4953 | ||
4248 | /* | 4954 | /* |
4249 | */ | 4955 | */ |
4250 | #ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS | ||
4251 | #include "alc260_quirks.c" | ||
4252 | #endif | ||
4253 | |||
4254 | static int patch_alc260(struct hda_codec *codec) | 4956 | static int patch_alc260(struct hda_codec *codec) |
4255 | { | 4957 | { |
4256 | struct alc_spec *spec; | 4958 | struct alc_spec *spec; |
4257 | int err, board_config; | 4959 | int err; |
4258 | 4960 | ||
4259 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 4961 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
4260 | if (spec == NULL) | 4962 | if (spec == NULL) |
@@ -4264,47 +4966,13 @@ static int patch_alc260(struct hda_codec *codec) | |||
4264 | 4966 | ||
4265 | spec->mixer_nid = 0x07; | 4967 | spec->mixer_nid = 0x07; |
4266 | 4968 | ||
4267 | board_config = alc_board_config(codec, ALC260_MODEL_LAST, | 4969 | alc_pick_fixup(codec, NULL, alc260_fixup_tbl, alc260_fixups); |
4268 | alc260_models, alc260_cfg_tbl); | 4970 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); |
4269 | if (board_config < 0) { | ||
4270 | snd_printd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", | ||
4271 | codec->chip_name); | ||
4272 | board_config = ALC_MODEL_AUTO; | ||
4273 | } | ||
4274 | |||
4275 | if (board_config == ALC_MODEL_AUTO) { | ||
4276 | alc_pick_fixup(codec, NULL, alc260_fixup_tbl, alc260_fixups); | ||
4277 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); | ||
4278 | } | ||
4279 | |||
4280 | if (board_config == ALC_MODEL_AUTO) { | ||
4281 | /* automatic parse from the BIOS config */ | ||
4282 | err = alc260_parse_auto_config(codec); | ||
4283 | if (err < 0) | ||
4284 | goto error; | ||
4285 | #ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS | ||
4286 | else if (!err) { | ||
4287 | printk(KERN_INFO | ||
4288 | "hda_codec: Cannot set up configuration " | ||
4289 | "from BIOS. Using base mode...\n"); | ||
4290 | board_config = ALC260_BASIC; | ||
4291 | } | ||
4292 | #endif | ||
4293 | } | ||
4294 | |||
4295 | if (board_config != ALC_MODEL_AUTO) { | ||
4296 | setup_preset(codec, &alc260_presets[board_config]); | ||
4297 | spec->vmaster_nid = 0x08; | ||
4298 | } | ||
4299 | |||
4300 | if (!spec->no_analog && !spec->adc_nids) { | ||
4301 | alc_auto_fill_adc_caps(codec); | ||
4302 | alc_rebuild_imux_for_auto_mic(codec); | ||
4303 | alc_remove_invalid_adc_nids(codec); | ||
4304 | } | ||
4305 | 4971 | ||
4306 | if (!spec->no_analog && !spec->cap_mixer) | 4972 | /* automatic parse from the BIOS config */ |
4307 | set_capture_mixer(codec); | 4973 | err = alc260_parse_auto_config(codec); |
4974 | if (err < 0) | ||
4975 | goto error; | ||
4308 | 4976 | ||
4309 | if (!spec->no_analog) { | 4977 | if (!spec->no_analog) { |
4310 | err = snd_hda_attach_beep_device(codec, 0x1); | 4978 | err = snd_hda_attach_beep_device(codec, 0x1); |
@@ -4313,18 +4981,10 @@ static int patch_alc260(struct hda_codec *codec) | |||
4313 | set_beep_amp(spec, 0x07, 0x05, HDA_INPUT); | 4981 | set_beep_amp(spec, 0x07, 0x05, HDA_INPUT); |
4314 | } | 4982 | } |
4315 | 4983 | ||
4316 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); | ||
4317 | |||
4318 | codec->patch_ops = alc_patch_ops; | 4984 | codec->patch_ops = alc_patch_ops; |
4319 | if (board_config == ALC_MODEL_AUTO) | ||
4320 | spec->init_hook = alc_auto_init_std; | ||
4321 | else | ||
4322 | codec->patch_ops.build_controls = __alc_build_controls; | ||
4323 | spec->shutup = alc_eapd_shutup; | 4985 | spec->shutup = alc_eapd_shutup; |
4324 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 4986 | |
4325 | if (!spec->loopback.amplist) | 4987 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); |
4326 | spec->loopback.amplist = alc260_loopbacks; | ||
4327 | #endif | ||
4328 | 4988 | ||
4329 | return 0; | 4989 | return 0; |
4330 | 4990 | ||
@@ -4345,9 +5005,6 @@ static int patch_alc260(struct hda_codec *codec) | |||
4345 | * In addition, an independent DAC for the multi-playback (not used in this | 5005 | * In addition, an independent DAC for the multi-playback (not used in this |
4346 | * driver yet). | 5006 | * driver yet). |
4347 | */ | 5007 | */ |
4348 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
4349 | #define alc882_loopbacks alc880_loopbacks | ||
4350 | #endif | ||
4351 | 5008 | ||
4352 | /* | 5009 | /* |
4353 | * Pin config fixes | 5010 | * Pin config fixes |
@@ -4358,11 +5015,14 @@ enum { | |||
4358 | ALC882_FIXUP_PB_M5210, | 5015 | ALC882_FIXUP_PB_M5210, |
4359 | ALC882_FIXUP_ACER_ASPIRE_7736, | 5016 | ALC882_FIXUP_ACER_ASPIRE_7736, |
4360 | ALC882_FIXUP_ASUS_W90V, | 5017 | ALC882_FIXUP_ASUS_W90V, |
5018 | ALC889_FIXUP_CD, | ||
4361 | ALC889_FIXUP_VAIO_TT, | 5019 | ALC889_FIXUP_VAIO_TT, |
4362 | ALC888_FIXUP_EEE1601, | 5020 | ALC888_FIXUP_EEE1601, |
4363 | ALC882_FIXUP_EAPD, | 5021 | ALC882_FIXUP_EAPD, |
4364 | ALC883_FIXUP_EAPD, | 5022 | ALC883_FIXUP_EAPD, |
4365 | ALC883_FIXUP_ACER_EAPD, | 5023 | ALC883_FIXUP_ACER_EAPD, |
5024 | ALC882_FIXUP_GPIO1, | ||
5025 | ALC882_FIXUP_GPIO2, | ||
4366 | ALC882_FIXUP_GPIO3, | 5026 | ALC882_FIXUP_GPIO3, |
4367 | ALC889_FIXUP_COEF, | 5027 | ALC889_FIXUP_COEF, |
4368 | ALC882_FIXUP_ASUS_W2JC, | 5028 | ALC882_FIXUP_ASUS_W2JC, |
@@ -4370,6 +5030,9 @@ enum { | |||
4370 | ALC882_FIXUP_ACER_ASPIRE_8930G, | 5030 | ALC882_FIXUP_ACER_ASPIRE_8930G, |
4371 | ALC882_FIXUP_ASPIRE_8930G_VERBS, | 5031 | ALC882_FIXUP_ASPIRE_8930G_VERBS, |
4372 | ALC885_FIXUP_MACPRO_GPIO, | 5032 | ALC885_FIXUP_MACPRO_GPIO, |
5033 | ALC889_FIXUP_DAC_ROUTE, | ||
5034 | ALC889_FIXUP_MBP_VREF, | ||
5035 | ALC889_FIXUP_IMAC91_VREF, | ||
4373 | }; | 5036 | }; |
4374 | 5037 | ||
4375 | static void alc889_fixup_coef(struct hda_codec *codec, | 5038 | static void alc889_fixup_coef(struct hda_codec *codec, |
@@ -4423,6 +5086,76 @@ static void alc885_fixup_macpro_gpio(struct hda_codec *codec, | |||
4423 | alc882_gpio_mute(codec, 1, 0); | 5086 | alc882_gpio_mute(codec, 1, 0); |
4424 | } | 5087 | } |
4425 | 5088 | ||
5089 | /* Fix the connection of some pins for ALC889: | ||
5090 | * At least, Acer Aspire 5935 shows the connections to DAC3/4 don't | ||
5091 | * work correctly (bko#42740) | ||
5092 | */ | ||
5093 | static void alc889_fixup_dac_route(struct hda_codec *codec, | ||
5094 | const struct alc_fixup *fix, int action) | ||
5095 | { | ||
5096 | if (action == ALC_FIXUP_ACT_PRE_PROBE) { | ||
5097 | /* fake the connections during parsing the tree */ | ||
5098 | hda_nid_t conn1[2] = { 0x0c, 0x0d }; | ||
5099 | hda_nid_t conn2[2] = { 0x0e, 0x0f }; | ||
5100 | snd_hda_override_conn_list(codec, 0x14, 2, conn1); | ||
5101 | snd_hda_override_conn_list(codec, 0x15, 2, conn1); | ||
5102 | snd_hda_override_conn_list(codec, 0x18, 2, conn2); | ||
5103 | snd_hda_override_conn_list(codec, 0x1a, 2, conn2); | ||
5104 | } else if (action == ALC_FIXUP_ACT_PROBE) { | ||
5105 | /* restore the connections */ | ||
5106 | hda_nid_t conn[5] = { 0x0c, 0x0d, 0x0e, 0x0f, 0x26 }; | ||
5107 | snd_hda_override_conn_list(codec, 0x14, 5, conn); | ||
5108 | snd_hda_override_conn_list(codec, 0x15, 5, conn); | ||
5109 | snd_hda_override_conn_list(codec, 0x18, 5, conn); | ||
5110 | snd_hda_override_conn_list(codec, 0x1a, 5, conn); | ||
5111 | } | ||
5112 | } | ||
5113 | |||
5114 | /* Set VREF on HP pin */ | ||
5115 | static void alc889_fixup_mbp_vref(struct hda_codec *codec, | ||
5116 | const struct alc_fixup *fix, int action) | ||
5117 | { | ||
5118 | struct alc_spec *spec = codec->spec; | ||
5119 | static hda_nid_t nids[2] = { 0x14, 0x15 }; | ||
5120 | int i; | ||
5121 | |||
5122 | if (action != ALC_FIXUP_ACT_INIT) | ||
5123 | return; | ||
5124 | for (i = 0; i < ARRAY_SIZE(nids); i++) { | ||
5125 | unsigned int val = snd_hda_codec_get_pincfg(codec, nids[i]); | ||
5126 | if (get_defcfg_device(val) != AC_JACK_HP_OUT) | ||
5127 | continue; | ||
5128 | val = snd_hda_codec_read(codec, nids[i], 0, | ||
5129 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
5130 | val |= AC_PINCTL_VREF_80; | ||
5131 | snd_hda_codec_write(codec, nids[i], 0, | ||
5132 | AC_VERB_SET_PIN_WIDGET_CONTROL, val); | ||
5133 | spec->keep_vref_in_automute = 1; | ||
5134 | break; | ||
5135 | } | ||
5136 | } | ||
5137 | |||
5138 | /* Set VREF on speaker pins on imac91 */ | ||
5139 | static void alc889_fixup_imac91_vref(struct hda_codec *codec, | ||
5140 | const struct alc_fixup *fix, int action) | ||
5141 | { | ||
5142 | struct alc_spec *spec = codec->spec; | ||
5143 | static hda_nid_t nids[2] = { 0x18, 0x1a }; | ||
5144 | int i; | ||
5145 | |||
5146 | if (action != ALC_FIXUP_ACT_INIT) | ||
5147 | return; | ||
5148 | for (i = 0; i < ARRAY_SIZE(nids); i++) { | ||
5149 | unsigned int val; | ||
5150 | val = snd_hda_codec_read(codec, nids[i], 0, | ||
5151 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
5152 | val |= AC_PINCTL_VREF_50; | ||
5153 | snd_hda_codec_write(codec, nids[i], 0, | ||
5154 | AC_VERB_SET_PIN_WIDGET_CONTROL, val); | ||
5155 | } | ||
5156 | spec->keep_vref_in_automute = 1; | ||
5157 | } | ||
5158 | |||
4426 | static const struct alc_fixup alc882_fixups[] = { | 5159 | static const struct alc_fixup alc882_fixups[] = { |
4427 | [ALC882_FIXUP_ABIT_AW9D_MAX] = { | 5160 | [ALC882_FIXUP_ABIT_AW9D_MAX] = { |
4428 | .type = ALC_FIXUP_PINS, | 5161 | .type = ALC_FIXUP_PINS, |
@@ -4459,6 +5192,13 @@ static const struct alc_fixup alc882_fixups[] = { | |||
4459 | { } | 5192 | { } |
4460 | } | 5193 | } |
4461 | }, | 5194 | }, |
5195 | [ALC889_FIXUP_CD] = { | ||
5196 | .type = ALC_FIXUP_PINS, | ||
5197 | .v.pins = (const struct alc_pincfg[]) { | ||
5198 | { 0x1c, 0x993301f0 }, /* CD */ | ||
5199 | { } | ||
5200 | } | ||
5201 | }, | ||
4462 | [ALC889_FIXUP_VAIO_TT] = { | 5202 | [ALC889_FIXUP_VAIO_TT] = { |
4463 | .type = ALC_FIXUP_PINS, | 5203 | .type = ALC_FIXUP_PINS, |
4464 | .v.pins = (const struct alc_pincfg[]) { | 5204 | .v.pins = (const struct alc_pincfg[]) { |
@@ -4501,6 +5241,14 @@ static const struct alc_fixup alc882_fixups[] = { | |||
4501 | { } | 5241 | { } |
4502 | } | 5242 | } |
4503 | }, | 5243 | }, |
5244 | [ALC882_FIXUP_GPIO1] = { | ||
5245 | .type = ALC_FIXUP_VERBS, | ||
5246 | .v.verbs = alc_gpio1_init_verbs, | ||
5247 | }, | ||
5248 | [ALC882_FIXUP_GPIO2] = { | ||
5249 | .type = ALC_FIXUP_VERBS, | ||
5250 | .v.verbs = alc_gpio2_init_verbs, | ||
5251 | }, | ||
4504 | [ALC882_FIXUP_GPIO3] = { | 5252 | [ALC882_FIXUP_GPIO3] = { |
4505 | .type = ALC_FIXUP_VERBS, | 5253 | .type = ALC_FIXUP_VERBS, |
4506 | .v.verbs = alc_gpio3_init_verbs, | 5254 | .v.verbs = alc_gpio3_init_verbs, |
@@ -4570,6 +5318,22 @@ static const struct alc_fixup alc882_fixups[] = { | |||
4570 | .type = ALC_FIXUP_FUNC, | 5318 | .type = ALC_FIXUP_FUNC, |
4571 | .v.func = alc885_fixup_macpro_gpio, | 5319 | .v.func = alc885_fixup_macpro_gpio, |
4572 | }, | 5320 | }, |
5321 | [ALC889_FIXUP_DAC_ROUTE] = { | ||
5322 | .type = ALC_FIXUP_FUNC, | ||
5323 | .v.func = alc889_fixup_dac_route, | ||
5324 | }, | ||
5325 | [ALC889_FIXUP_MBP_VREF] = { | ||
5326 | .type = ALC_FIXUP_FUNC, | ||
5327 | .v.func = alc889_fixup_mbp_vref, | ||
5328 | .chained = true, | ||
5329 | .chain_id = ALC882_FIXUP_GPIO1, | ||
5330 | }, | ||
5331 | [ALC889_FIXUP_IMAC91_VREF] = { | ||
5332 | .type = ALC_FIXUP_FUNC, | ||
5333 | .v.func = alc889_fixup_imac91_vref, | ||
5334 | .chained = true, | ||
5335 | .chain_id = ALC882_FIXUP_GPIO1, | ||
5336 | }, | ||
4573 | }; | 5337 | }; |
4574 | 5338 | ||
4575 | static const struct snd_pci_quirk alc882_fixup_tbl[] = { | 5339 | static const struct snd_pci_quirk alc882_fixup_tbl[] = { |
@@ -4594,6 +5358,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { | |||
4594 | SND_PCI_QUIRK(0x1025, 0x0142, "Acer Aspire 7730G", | 5358 | SND_PCI_QUIRK(0x1025, 0x0142, "Acer Aspire 7730G", |
4595 | ALC882_FIXUP_ACER_ASPIRE_4930G), | 5359 | ALC882_FIXUP_ACER_ASPIRE_4930G), |
4596 | SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", ALC882_FIXUP_PB_M5210), | 5360 | SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", ALC882_FIXUP_PB_M5210), |
5361 | SND_PCI_QUIRK(0x1025, 0x0259, "Acer Aspire 5935", ALC889_FIXUP_DAC_ROUTE), | ||
4597 | SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", ALC882_FIXUP_ACER_ASPIRE_7736), | 5362 | SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", ALC882_FIXUP_ACER_ASPIRE_7736), |
4598 | SND_PCI_QUIRK(0x1043, 0x13c2, "Asus A7M", ALC882_FIXUP_EAPD), | 5363 | SND_PCI_QUIRK(0x1043, 0x13c2, "Asus A7M", ALC882_FIXUP_EAPD), |
4599 | SND_PCI_QUIRK(0x1043, 0x1873, "ASUS W90V", ALC882_FIXUP_ASUS_W90V), | 5364 | SND_PCI_QUIRK(0x1043, 0x1873, "ASUS W90V", ALC882_FIXUP_ASUS_W90V), |
@@ -4602,14 +5367,30 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { | |||
4602 | SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC889_FIXUP_VAIO_TT), | 5367 | SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC889_FIXUP_VAIO_TT), |
4603 | 5368 | ||
4604 | /* All Apple entries are in codec SSIDs */ | 5369 | /* All Apple entries are in codec SSIDs */ |
5370 | SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC889_FIXUP_MBP_VREF), | ||
5371 | SND_PCI_QUIRK(0x106b, 0x00a1, "Macbook", ALC889_FIXUP_MBP_VREF), | ||
5372 | SND_PCI_QUIRK(0x106b, 0x00a4, "MacbookPro 4,1", ALC889_FIXUP_MBP_VREF), | ||
4605 | SND_PCI_QUIRK(0x106b, 0x0c00, "Mac Pro", ALC885_FIXUP_MACPRO_GPIO), | 5373 | SND_PCI_QUIRK(0x106b, 0x0c00, "Mac Pro", ALC885_FIXUP_MACPRO_GPIO), |
4606 | SND_PCI_QUIRK(0x106b, 0x1000, "iMac 24", ALC885_FIXUP_MACPRO_GPIO), | 5374 | SND_PCI_QUIRK(0x106b, 0x1000, "iMac 24", ALC885_FIXUP_MACPRO_GPIO), |
4607 | SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_FIXUP_MACPRO_GPIO), | 5375 | SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_FIXUP_MACPRO_GPIO), |
5376 | SND_PCI_QUIRK(0x106b, 0x2c00, "MacbookPro rev3", ALC889_FIXUP_MBP_VREF), | ||
5377 | SND_PCI_QUIRK(0x106b, 0x3000, "iMac", ALC889_FIXUP_MBP_VREF), | ||
4608 | SND_PCI_QUIRK(0x106b, 0x3200, "iMac 7,1 Aluminum", ALC882_FIXUP_EAPD), | 5378 | SND_PCI_QUIRK(0x106b, 0x3200, "iMac 7,1 Aluminum", ALC882_FIXUP_EAPD), |
5379 | SND_PCI_QUIRK(0x106b, 0x3400, "MacBookAir 1,1", ALC889_FIXUP_MBP_VREF), | ||
5380 | SND_PCI_QUIRK(0x106b, 0x3500, "MacBookAir 2,1", ALC889_FIXUP_MBP_VREF), | ||
5381 | SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889_FIXUP_MBP_VREF), | ||
5382 | SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC889_FIXUP_MBP_VREF), | ||
4609 | SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_FIXUP_MACPRO_GPIO), | 5383 | SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_FIXUP_MACPRO_GPIO), |
5384 | SND_PCI_QUIRK(0x106b, 0x3f00, "Macbook 5,1", ALC889_FIXUP_IMAC91_VREF), | ||
5385 | SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC889_FIXUP_IMAC91_VREF), | ||
5386 | SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC889_FIXUP_IMAC91_VREF), | ||
5387 | SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC889_FIXUP_IMAC91_VREF), | ||
5388 | SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC889_FIXUP_IMAC91_VREF), | ||
5389 | SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_IMAC91_VREF), | ||
4610 | 5390 | ||
4611 | SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD), | 5391 | SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD), |
4612 | SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3), | 5392 | SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3), |
5393 | SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3", ALC889_FIXUP_CD), | ||
4613 | SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX), | 5394 | SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX), |
4614 | SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD), | 5395 | SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD), |
4615 | SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD), | 5396 | SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD), |
@@ -4631,14 +5412,10 @@ static int alc882_parse_auto_config(struct hda_codec *codec) | |||
4631 | 5412 | ||
4632 | /* | 5413 | /* |
4633 | */ | 5414 | */ |
4634 | #ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS | ||
4635 | #include "alc882_quirks.c" | ||
4636 | #endif | ||
4637 | |||
4638 | static int patch_alc882(struct hda_codec *codec) | 5415 | static int patch_alc882(struct hda_codec *codec) |
4639 | { | 5416 | { |
4640 | struct alc_spec *spec; | 5417 | struct alc_spec *spec; |
4641 | int err, board_config; | 5418 | int err; |
4642 | 5419 | ||
4643 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 5420 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
4644 | if (spec == NULL) | 5421 | if (spec == NULL) |
@@ -4662,45 +5439,15 @@ static int patch_alc882(struct hda_codec *codec) | |||
4662 | if (err < 0) | 5439 | if (err < 0) |
4663 | goto error; | 5440 | goto error; |
4664 | 5441 | ||
4665 | board_config = alc_board_config(codec, ALC882_MODEL_LAST, | 5442 | alc_pick_fixup(codec, NULL, alc882_fixup_tbl, alc882_fixups); |
4666 | alc882_models, NULL); | 5443 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); |
4667 | if (board_config < 0) | ||
4668 | board_config = alc_board_codec_sid_config(codec, | ||
4669 | ALC882_MODEL_LAST, alc882_models, alc882_ssid_cfg_tbl); | ||
4670 | |||
4671 | if (board_config < 0) { | ||
4672 | printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", | ||
4673 | codec->chip_name); | ||
4674 | board_config = ALC_MODEL_AUTO; | ||
4675 | } | ||
4676 | |||
4677 | if (board_config == ALC_MODEL_AUTO) { | ||
4678 | alc_pick_fixup(codec, NULL, alc882_fixup_tbl, alc882_fixups); | ||
4679 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); | ||
4680 | } | ||
4681 | 5444 | ||
4682 | alc_auto_parse_customize_define(codec); | 5445 | alc_auto_parse_customize_define(codec); |
4683 | 5446 | ||
4684 | if (board_config == ALC_MODEL_AUTO) { | 5447 | /* automatic parse from the BIOS config */ |
4685 | /* automatic parse from the BIOS config */ | 5448 | err = alc882_parse_auto_config(codec); |
4686 | err = alc882_parse_auto_config(codec); | 5449 | if (err < 0) |
4687 | if (err < 0) | 5450 | goto error; |
4688 | goto error; | ||
4689 | } | ||
4690 | |||
4691 | if (board_config != ALC_MODEL_AUTO) { | ||
4692 | setup_preset(codec, &alc882_presets[board_config]); | ||
4693 | spec->vmaster_nid = 0x0c; | ||
4694 | } | ||
4695 | |||
4696 | if (!spec->no_analog && !spec->adc_nids) { | ||
4697 | alc_auto_fill_adc_caps(codec); | ||
4698 | alc_rebuild_imux_for_auto_mic(codec); | ||
4699 | alc_remove_invalid_adc_nids(codec); | ||
4700 | } | ||
4701 | |||
4702 | if (!spec->no_analog && !spec->cap_mixer) | ||
4703 | set_capture_mixer(codec); | ||
4704 | 5451 | ||
4705 | if (!spec->no_analog && has_cdefine_beep(codec)) { | 5452 | if (!spec->no_analog && has_cdefine_beep(codec)) { |
4706 | err = snd_hda_attach_beep_device(codec, 0x1); | 5453 | err = snd_hda_attach_beep_device(codec, 0x1); |
@@ -4709,18 +5456,9 @@ static int patch_alc882(struct hda_codec *codec) | |||
4709 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | 5456 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); |
4710 | } | 5457 | } |
4711 | 5458 | ||
4712 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); | ||
4713 | |||
4714 | codec->patch_ops = alc_patch_ops; | 5459 | codec->patch_ops = alc_patch_ops; |
4715 | if (board_config == ALC_MODEL_AUTO) | ||
4716 | spec->init_hook = alc_auto_init_std; | ||
4717 | else | ||
4718 | codec->patch_ops.build_controls = __alc_build_controls; | ||
4719 | 5460 | ||
4720 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 5461 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); |
4721 | if (!spec->loopback.amplist) | ||
4722 | spec->loopback.amplist = alc882_loopbacks; | ||
4723 | #endif | ||
4724 | 5462 | ||
4725 | return 0; | 5463 | return 0; |
4726 | 5464 | ||
@@ -4816,10 +5554,6 @@ static const struct snd_pci_quirk alc262_fixup_tbl[] = { | |||
4816 | }; | 5554 | }; |
4817 | 5555 | ||
4818 | 5556 | ||
4819 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
4820 | #define alc262_loopbacks alc880_loopbacks | ||
4821 | #endif | ||
4822 | |||
4823 | /* | 5557 | /* |
4824 | */ | 5558 | */ |
4825 | static int patch_alc262(struct hda_codec *codec) | 5559 | static int patch_alc262(struct hda_codec *codec) |
@@ -4859,15 +5593,6 @@ static int patch_alc262(struct hda_codec *codec) | |||
4859 | if (err < 0) | 5593 | if (err < 0) |
4860 | goto error; | 5594 | goto error; |
4861 | 5595 | ||
4862 | if (!spec->no_analog && !spec->adc_nids) { | ||
4863 | alc_auto_fill_adc_caps(codec); | ||
4864 | alc_rebuild_imux_for_auto_mic(codec); | ||
4865 | alc_remove_invalid_adc_nids(codec); | ||
4866 | } | ||
4867 | |||
4868 | if (!spec->no_analog && !spec->cap_mixer) | ||
4869 | set_capture_mixer(codec); | ||
4870 | |||
4871 | if (!spec->no_analog && has_cdefine_beep(codec)) { | 5596 | if (!spec->no_analog && has_cdefine_beep(codec)) { |
4872 | err = snd_hda_attach_beep_device(codec, 0x1); | 5597 | err = snd_hda_attach_beep_device(codec, 0x1); |
4873 | if (err < 0) | 5598 | if (err < 0) |
@@ -4875,16 +5600,10 @@ static int patch_alc262(struct hda_codec *codec) | |||
4875 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | 5600 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); |
4876 | } | 5601 | } |
4877 | 5602 | ||
4878 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); | ||
4879 | |||
4880 | codec->patch_ops = alc_patch_ops; | 5603 | codec->patch_ops = alc_patch_ops; |
4881 | spec->init_hook = alc_auto_init_std; | ||
4882 | spec->shutup = alc_eapd_shutup; | 5604 | spec->shutup = alc_eapd_shutup; |
4883 | 5605 | ||
4884 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 5606 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); |
4885 | if (!spec->loopback.amplist) | ||
4886 | spec->loopback.amplist = alc262_loopbacks; | ||
4887 | #endif | ||
4888 | 5607 | ||
4889 | return 0; | 5608 | return 0; |
4890 | 5609 | ||
@@ -4978,17 +5697,7 @@ static int patch_alc268(struct hda_codec *codec) | |||
4978 | (0 << AC_AMPCAP_MUTE_SHIFT)); | 5697 | (0 << AC_AMPCAP_MUTE_SHIFT)); |
4979 | } | 5698 | } |
4980 | 5699 | ||
4981 | if (!spec->no_analog && !spec->adc_nids) { | ||
4982 | alc_auto_fill_adc_caps(codec); | ||
4983 | alc_rebuild_imux_for_auto_mic(codec); | ||
4984 | alc_remove_invalid_adc_nids(codec); | ||
4985 | } | ||
4986 | |||
4987 | if (!spec->no_analog && !spec->cap_mixer) | ||
4988 | set_capture_mixer(codec); | ||
4989 | |||
4990 | codec->patch_ops = alc_patch_ops; | 5700 | codec->patch_ops = alc_patch_ops; |
4991 | spec->init_hook = alc_auto_init_std; | ||
4992 | spec->shutup = alc_eapd_shutup; | 5701 | spec->shutup = alc_eapd_shutup; |
4993 | 5702 | ||
4994 | return 0; | 5703 | return 0; |
@@ -5001,10 +5710,6 @@ static int patch_alc268(struct hda_codec *codec) | |||
5001 | /* | 5710 | /* |
5002 | * ALC269 | 5711 | * ALC269 |
5003 | */ | 5712 | */ |
5004 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
5005 | #define alc269_loopbacks alc880_loopbacks | ||
5006 | #endif | ||
5007 | |||
5008 | static const struct hda_pcm_stream alc269_44k_pcm_analog_playback = { | 5713 | static const struct hda_pcm_stream alc269_44k_pcm_analog_playback = { |
5009 | .substreams = 1, | 5714 | .substreams = 1, |
5010 | .channels_min = 2, | 5715 | .channels_min = 2, |
@@ -5026,35 +5731,6 @@ static const struct hda_pcm_stream alc269_44k_pcm_analog_capture = { | |||
5026 | /* NID is set in alc_build_pcms */ | 5731 | /* NID is set in alc_build_pcms */ |
5027 | }; | 5732 | }; |
5028 | 5733 | ||
5029 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
5030 | static int alc269_mic2_for_mute_led(struct hda_codec *codec) | ||
5031 | { | ||
5032 | switch (codec->subsystem_id) { | ||
5033 | case 0x103c1586: | ||
5034 | return 1; | ||
5035 | } | ||
5036 | return 0; | ||
5037 | } | ||
5038 | |||
5039 | static int alc269_mic2_mute_check_ps(struct hda_codec *codec, hda_nid_t nid) | ||
5040 | { | ||
5041 | /* update mute-LED according to the speaker mute state */ | ||
5042 | if (nid == 0x01 || nid == 0x14) { | ||
5043 | int pinval; | ||
5044 | if (snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0) & | ||
5045 | HDA_AMP_MUTE) | ||
5046 | pinval = 0x24; | ||
5047 | else | ||
5048 | pinval = 0x20; | ||
5049 | /* mic2 vref pin is used for mute LED control */ | ||
5050 | snd_hda_codec_update_cache(codec, 0x19, 0, | ||
5051 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
5052 | pinval); | ||
5053 | } | ||
5054 | return alc_check_power_status(codec, nid); | ||
5055 | } | ||
5056 | #endif /* CONFIG_SND_HDA_POWER_SAVE */ | ||
5057 | |||
5058 | /* different alc269-variants */ | 5734 | /* different alc269-variants */ |
5059 | enum { | 5735 | enum { |
5060 | ALC269_TYPE_ALC269VA, | 5736 | ALC269_TYPE_ALC269VA, |
@@ -5205,6 +5881,31 @@ static void alc269_fixup_quanta_mute(struct hda_codec *codec, | |||
5205 | spec->automute_hook = alc269_quanta_automute; | 5881 | spec->automute_hook = alc269_quanta_automute; |
5206 | } | 5882 | } |
5207 | 5883 | ||
5884 | /* update mute-LED according to the speaker mute state via mic2 VREF pin */ | ||
5885 | static void alc269_fixup_mic2_mute_hook(void *private_data, int enabled) | ||
5886 | { | ||
5887 | struct hda_codec *codec = private_data; | ||
5888 | unsigned int pinval = enabled ? 0x20 : 0x24; | ||
5889 | snd_hda_codec_update_cache(codec, 0x19, 0, | ||
5890 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
5891 | pinval); | ||
5892 | } | ||
5893 | |||
5894 | static void alc269_fixup_mic2_mute(struct hda_codec *codec, | ||
5895 | const struct alc_fixup *fix, int action) | ||
5896 | { | ||
5897 | struct alc_spec *spec = codec->spec; | ||
5898 | switch (action) { | ||
5899 | case ALC_FIXUP_ACT_BUILD: | ||
5900 | spec->vmaster_mute.hook = alc269_fixup_mic2_mute_hook; | ||
5901 | snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute, true); | ||
5902 | /* fallthru */ | ||
5903 | case ALC_FIXUP_ACT_INIT: | ||
5904 | snd_hda_sync_vmaster_hook(&spec->vmaster_mute); | ||
5905 | break; | ||
5906 | } | ||
5907 | } | ||
5908 | |||
5208 | enum { | 5909 | enum { |
5209 | ALC269_FIXUP_SONY_VAIO, | 5910 | ALC269_FIXUP_SONY_VAIO, |
5210 | ALC275_FIXUP_SONY_VAIO_GPIO2, | 5911 | ALC275_FIXUP_SONY_VAIO_GPIO2, |
@@ -5222,6 +5923,7 @@ enum { | |||
5222 | ALC269_FIXUP_DMIC, | 5923 | ALC269_FIXUP_DMIC, |
5223 | ALC269VB_FIXUP_AMIC, | 5924 | ALC269VB_FIXUP_AMIC, |
5224 | ALC269VB_FIXUP_DMIC, | 5925 | ALC269VB_FIXUP_DMIC, |
5926 | ALC269_FIXUP_MIC2_MUTE_LED, | ||
5225 | }; | 5927 | }; |
5226 | 5928 | ||
5227 | static const struct alc_fixup alc269_fixups[] = { | 5929 | static const struct alc_fixup alc269_fixups[] = { |
@@ -5342,9 +6044,14 @@ static const struct alc_fixup alc269_fixups[] = { | |||
5342 | { } | 6044 | { } |
5343 | }, | 6045 | }, |
5344 | }, | 6046 | }, |
6047 | [ALC269_FIXUP_MIC2_MUTE_LED] = { | ||
6048 | .type = ALC_FIXUP_FUNC, | ||
6049 | .v.func = alc269_fixup_mic2_mute, | ||
6050 | }, | ||
5345 | }; | 6051 | }; |
5346 | 6052 | ||
5347 | static const struct snd_pci_quirk alc269_fixup_tbl[] = { | 6053 | static const struct snd_pci_quirk alc269_fixup_tbl[] = { |
6054 | SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_MIC2_MUTE_LED), | ||
5348 | SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), | 6055 | SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), |
5349 | SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC), | 6056 | SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC), |
5350 | SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC), | 6057 | SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC), |
@@ -5367,7 +6074,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
5367 | SND_PCI_QUIRK(0x17aa, 0x3bf8, "Lenovo Ideapd", ALC269_FIXUP_PCM_44K), | 6074 | SND_PCI_QUIRK(0x17aa, 0x3bf8, "Lenovo Ideapd", ALC269_FIXUP_PCM_44K), |
5368 | SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD), | 6075 | SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD), |
5369 | 6076 | ||
5370 | #if 1 | 6077 | #if 0 |
5371 | /* Below is a quirk table taken from the old code. | 6078 | /* Below is a quirk table taken from the old code. |
5372 | * Basically the device should work as is without the fixup table. | 6079 | * Basically the device should work as is without the fixup table. |
5373 | * If BIOS doesn't give a proper info, enable the corresponding | 6080 | * If BIOS doesn't give a proper info, enable the corresponding |
@@ -5425,10 +6132,14 @@ static const struct alc_model_fixup alc269_fixup_models[] = { | |||
5425 | }; | 6132 | }; |
5426 | 6133 | ||
5427 | 6134 | ||
5428 | static int alc269_fill_coef(struct hda_codec *codec) | 6135 | static void alc269_fill_coef(struct hda_codec *codec) |
5429 | { | 6136 | { |
6137 | struct alc_spec *spec = codec->spec; | ||
5430 | int val; | 6138 | int val; |
5431 | 6139 | ||
6140 | if (spec->codec_variant != ALC269_TYPE_ALC269VB) | ||
6141 | return; | ||
6142 | |||
5432 | if ((alc_get_coef0(codec) & 0x00ff) < 0x015) { | 6143 | if ((alc_get_coef0(codec) & 0x00ff) < 0x015) { |
5433 | alc_write_coef_idx(codec, 0xf, 0x960b); | 6144 | alc_write_coef_idx(codec, 0xf, 0x960b); |
5434 | alc_write_coef_idx(codec, 0xe, 0x8817); | 6145 | alc_write_coef_idx(codec, 0xe, 0x8817); |
@@ -5463,8 +6174,6 @@ static int alc269_fill_coef(struct hda_codec *codec) | |||
5463 | 6174 | ||
5464 | val = alc_read_coef_idx(codec, 0x4); /* HP */ | 6175 | val = alc_read_coef_idx(codec, 0x4); /* HP */ |
5465 | alc_write_coef_idx(codec, 0x4, val | (1<<11)); | 6176 | alc_write_coef_idx(codec, 0x4, val | (1<<11)); |
5466 | |||
5467 | return 0; | ||
5468 | } | 6177 | } |
5469 | 6178 | ||
5470 | /* | 6179 | /* |
@@ -5508,6 +6217,7 @@ static int patch_alc269(struct hda_codec *codec) | |||
5508 | } | 6217 | } |
5509 | if (err < 0) | 6218 | if (err < 0) |
5510 | goto error; | 6219 | goto error; |
6220 | spec->init_hook = alc269_fill_coef; | ||
5511 | alc269_fill_coef(codec); | 6221 | alc269_fill_coef(codec); |
5512 | } | 6222 | } |
5513 | 6223 | ||
@@ -5520,15 +6230,6 @@ static int patch_alc269(struct hda_codec *codec) | |||
5520 | if (err < 0) | 6230 | if (err < 0) |
5521 | goto error; | 6231 | goto error; |
5522 | 6232 | ||
5523 | if (!spec->no_analog && !spec->adc_nids) { | ||
5524 | alc_auto_fill_adc_caps(codec); | ||
5525 | alc_rebuild_imux_for_auto_mic(codec); | ||
5526 | alc_remove_invalid_adc_nids(codec); | ||
5527 | } | ||
5528 | |||
5529 | if (!spec->no_analog && !spec->cap_mixer) | ||
5530 | set_capture_mixer(codec); | ||
5531 | |||
5532 | if (!spec->no_analog && has_cdefine_beep(codec)) { | 6233 | if (!spec->no_analog && has_cdefine_beep(codec)) { |
5533 | err = snd_hda_attach_beep_device(codec, 0x1); | 6234 | err = snd_hda_attach_beep_device(codec, 0x1); |
5534 | if (err < 0) | 6235 | if (err < 0) |
@@ -5536,21 +6237,13 @@ static int patch_alc269(struct hda_codec *codec) | |||
5536 | set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); | 6237 | set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); |
5537 | } | 6238 | } |
5538 | 6239 | ||
5539 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); | ||
5540 | |||
5541 | codec->patch_ops = alc_patch_ops; | 6240 | codec->patch_ops = alc_patch_ops; |
5542 | #ifdef CONFIG_PM | 6241 | #ifdef CONFIG_PM |
5543 | codec->patch_ops.resume = alc269_resume; | 6242 | codec->patch_ops.resume = alc269_resume; |
5544 | #endif | 6243 | #endif |
5545 | spec->init_hook = alc_auto_init_std; | ||
5546 | spec->shutup = alc269_shutup; | 6244 | spec->shutup = alc269_shutup; |
5547 | 6245 | ||
5548 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 6246 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); |
5549 | if (!spec->loopback.amplist) | ||
5550 | spec->loopback.amplist = alc269_loopbacks; | ||
5551 | if (alc269_mic2_for_mute_led(codec)) | ||
5552 | codec->patch_ops.check_power_status = alc269_mic2_mute_check_ps; | ||
5553 | #endif | ||
5554 | 6247 | ||
5555 | return 0; | 6248 | return 0; |
5556 | 6249 | ||
@@ -5570,21 +6263,12 @@ static int alc861_parse_auto_config(struct hda_codec *codec) | |||
5570 | return alc_parse_auto_config(codec, alc861_ignore, alc861_ssids); | 6263 | return alc_parse_auto_config(codec, alc861_ignore, alc861_ssids); |
5571 | } | 6264 | } |
5572 | 6265 | ||
5573 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
5574 | static const struct hda_amp_list alc861_loopbacks[] = { | ||
5575 | { 0x15, HDA_INPUT, 0 }, | ||
5576 | { 0x15, HDA_INPUT, 1 }, | ||
5577 | { 0x15, HDA_INPUT, 2 }, | ||
5578 | { 0x15, HDA_INPUT, 3 }, | ||
5579 | { } /* end */ | ||
5580 | }; | ||
5581 | #endif | ||
5582 | |||
5583 | |||
5584 | /* Pin config fixes */ | 6266 | /* Pin config fixes */ |
5585 | enum { | 6267 | enum { |
5586 | PINFIX_FSC_AMILO_PI1505, | 6268 | ALC861_FIXUP_FSC_AMILO_PI1505, |
5587 | PINFIX_ASUS_A6RP, | 6269 | ALC861_FIXUP_AMP_VREF_0F, |
6270 | ALC861_FIXUP_NO_JACK_DETECT, | ||
6271 | ALC861_FIXUP_ASUS_A6RP, | ||
5588 | }; | 6272 | }; |
5589 | 6273 | ||
5590 | /* On some laptops, VREF of pin 0x0f is abused for controlling the main amp */ | 6274 | /* On some laptops, VREF of pin 0x0f is abused for controlling the main amp */ |
@@ -5606,8 +6290,16 @@ static void alc861_fixup_asus_amp_vref_0f(struct hda_codec *codec, | |||
5606 | spec->keep_vref_in_automute = 1; | 6290 | spec->keep_vref_in_automute = 1; |
5607 | } | 6291 | } |
5608 | 6292 | ||
6293 | /* suppress the jack-detection */ | ||
6294 | static void alc_fixup_no_jack_detect(struct hda_codec *codec, | ||
6295 | const struct alc_fixup *fix, int action) | ||
6296 | { | ||
6297 | if (action == ALC_FIXUP_ACT_PRE_PROBE) | ||
6298 | codec->no_jack_detect = 1; | ||
6299 | } | ||
6300 | |||
5609 | static const struct alc_fixup alc861_fixups[] = { | 6301 | static const struct alc_fixup alc861_fixups[] = { |
5610 | [PINFIX_FSC_AMILO_PI1505] = { | 6302 | [ALC861_FIXUP_FSC_AMILO_PI1505] = { |
5611 | .type = ALC_FIXUP_PINS, | 6303 | .type = ALC_FIXUP_PINS, |
5612 | .v.pins = (const struct alc_pincfg[]) { | 6304 | .v.pins = (const struct alc_pincfg[]) { |
5613 | { 0x0b, 0x0221101f }, /* HP */ | 6305 | { 0x0b, 0x0221101f }, /* HP */ |
@@ -5615,16 +6307,29 @@ static const struct alc_fixup alc861_fixups[] = { | |||
5615 | { } | 6307 | { } |
5616 | } | 6308 | } |
5617 | }, | 6309 | }, |
5618 | [PINFIX_ASUS_A6RP] = { | 6310 | [ALC861_FIXUP_AMP_VREF_0F] = { |
5619 | .type = ALC_FIXUP_FUNC, | 6311 | .type = ALC_FIXUP_FUNC, |
5620 | .v.func = alc861_fixup_asus_amp_vref_0f, | 6312 | .v.func = alc861_fixup_asus_amp_vref_0f, |
5621 | }, | 6313 | }, |
6314 | [ALC861_FIXUP_NO_JACK_DETECT] = { | ||
6315 | .type = ALC_FIXUP_FUNC, | ||
6316 | .v.func = alc_fixup_no_jack_detect, | ||
6317 | }, | ||
6318 | [ALC861_FIXUP_ASUS_A6RP] = { | ||
6319 | .type = ALC_FIXUP_FUNC, | ||
6320 | .v.func = alc861_fixup_asus_amp_vref_0f, | ||
6321 | .chained = true, | ||
6322 | .chain_id = ALC861_FIXUP_NO_JACK_DETECT, | ||
6323 | } | ||
5622 | }; | 6324 | }; |
5623 | 6325 | ||
5624 | static const struct snd_pci_quirk alc861_fixup_tbl[] = { | 6326 | static const struct snd_pci_quirk alc861_fixup_tbl[] = { |
5625 | SND_PCI_QUIRK_VENDOR(0x1043, "ASUS laptop", PINFIX_ASUS_A6RP), | 6327 | SND_PCI_QUIRK(0x1043, 0x1393, "ASUS A6Rp", ALC861_FIXUP_ASUS_A6RP), |
5626 | SND_PCI_QUIRK(0x1584, 0x2b01, "Haier W18", PINFIX_ASUS_A6RP), | 6328 | SND_PCI_QUIRK_VENDOR(0x1043, "ASUS laptop", ALC861_FIXUP_AMP_VREF_0F), |
5627 | SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505), | 6329 | SND_PCI_QUIRK(0x1462, 0x7254, "HP DX2200", ALC861_FIXUP_NO_JACK_DETECT), |
6330 | SND_PCI_QUIRK(0x1584, 0x2b01, "Haier W18", ALC861_FIXUP_AMP_VREF_0F), | ||
6331 | SND_PCI_QUIRK(0x1584, 0x0000, "Uniwill ECS M31EI", ALC861_FIXUP_AMP_VREF_0F), | ||
6332 | SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", ALC861_FIXUP_FSC_AMILO_PI1505), | ||
5628 | {} | 6333 | {} |
5629 | }; | 6334 | }; |
5630 | 6335 | ||
@@ -5651,15 +6356,6 @@ static int patch_alc861(struct hda_codec *codec) | |||
5651 | if (err < 0) | 6356 | if (err < 0) |
5652 | goto error; | 6357 | goto error; |
5653 | 6358 | ||
5654 | if (!spec->no_analog && !spec->adc_nids) { | ||
5655 | alc_auto_fill_adc_caps(codec); | ||
5656 | alc_rebuild_imux_for_auto_mic(codec); | ||
5657 | alc_remove_invalid_adc_nids(codec); | ||
5658 | } | ||
5659 | |||
5660 | if (!spec->no_analog && !spec->cap_mixer) | ||
5661 | set_capture_mixer(codec); | ||
5662 | |||
5663 | if (!spec->no_analog) { | 6359 | if (!spec->no_analog) { |
5664 | err = snd_hda_attach_beep_device(codec, 0x23); | 6360 | err = snd_hda_attach_beep_device(codec, 0x23); |
5665 | if (err < 0) | 6361 | if (err < 0) |
@@ -5667,16 +6363,13 @@ static int patch_alc861(struct hda_codec *codec) | |||
5667 | set_beep_amp(spec, 0x23, 0, HDA_OUTPUT); | 6363 | set_beep_amp(spec, 0x23, 0, HDA_OUTPUT); |
5668 | } | 6364 | } |
5669 | 6365 | ||
5670 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); | ||
5671 | |||
5672 | codec->patch_ops = alc_patch_ops; | 6366 | codec->patch_ops = alc_patch_ops; |
5673 | spec->init_hook = alc_auto_init_std; | ||
5674 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 6367 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
5675 | spec->power_hook = alc_power_eapd; | 6368 | spec->power_hook = alc_power_eapd; |
5676 | if (!spec->loopback.amplist) | ||
5677 | spec->loopback.amplist = alc861_loopbacks; | ||
5678 | #endif | 6369 | #endif |
5679 | 6370 | ||
6371 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); | ||
6372 | |||
5680 | return 0; | 6373 | return 0; |
5681 | 6374 | ||
5682 | error: | 6375 | error: |
@@ -5691,10 +6384,6 @@ static int patch_alc861(struct hda_codec *codec) | |||
5691 | * | 6384 | * |
5692 | * In addition, an independent DAC | 6385 | * In addition, an independent DAC |
5693 | */ | 6386 | */ |
5694 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
5695 | #define alc861vd_loopbacks alc880_loopbacks | ||
5696 | #endif | ||
5697 | |||
5698 | static int alc861vd_parse_auto_config(struct hda_codec *codec) | 6387 | static int alc861vd_parse_auto_config(struct hda_codec *codec) |
5699 | { | 6388 | { |
5700 | static const hda_nid_t alc861vd_ignore[] = { 0x1d, 0 }; | 6389 | static const hda_nid_t alc861vd_ignore[] = { 0x1d, 0 }; |
@@ -5775,15 +6464,6 @@ static int patch_alc861vd(struct hda_codec *codec) | |||
5775 | add_verb(spec, alc660vd_eapd_verbs); | 6464 | add_verb(spec, alc660vd_eapd_verbs); |
5776 | } | 6465 | } |
5777 | 6466 | ||
5778 | if (!spec->no_analog && !spec->adc_nids) { | ||
5779 | alc_auto_fill_adc_caps(codec); | ||
5780 | alc_rebuild_imux_for_auto_mic(codec); | ||
5781 | alc_remove_invalid_adc_nids(codec); | ||
5782 | } | ||
5783 | |||
5784 | if (!spec->no_analog && !spec->cap_mixer) | ||
5785 | set_capture_mixer(codec); | ||
5786 | |||
5787 | if (!spec->no_analog) { | 6467 | if (!spec->no_analog) { |
5788 | err = snd_hda_attach_beep_device(codec, 0x23); | 6468 | err = snd_hda_attach_beep_device(codec, 0x23); |
5789 | if (err < 0) | 6469 | if (err < 0) |
@@ -5791,16 +6471,11 @@ static int patch_alc861vd(struct hda_codec *codec) | |||
5791 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | 6471 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); |
5792 | } | 6472 | } |
5793 | 6473 | ||
5794 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); | ||
5795 | |||
5796 | codec->patch_ops = alc_patch_ops; | 6474 | codec->patch_ops = alc_patch_ops; |
5797 | 6475 | ||
5798 | spec->init_hook = alc_auto_init_std; | ||
5799 | spec->shutup = alc_eapd_shutup; | 6476 | spec->shutup = alc_eapd_shutup; |
5800 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 6477 | |
5801 | if (!spec->loopback.amplist) | 6478 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); |
5802 | spec->loopback.amplist = alc861vd_loopbacks; | ||
5803 | #endif | ||
5804 | 6479 | ||
5805 | return 0; | 6480 | return 0; |
5806 | 6481 | ||
@@ -5820,9 +6495,6 @@ static int patch_alc861vd(struct hda_codec *codec) | |||
5820 | * In addition, an independent DAC for the multi-playback (not used in this | 6495 | * In addition, an independent DAC for the multi-playback (not used in this |
5821 | * driver yet). | 6496 | * driver yet). |
5822 | */ | 6497 | */ |
5823 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
5824 | #define alc662_loopbacks alc880_loopbacks | ||
5825 | #endif | ||
5826 | 6498 | ||
5827 | /* | 6499 | /* |
5828 | * BIOS auto configuration | 6500 | * BIOS auto configuration |
@@ -5872,6 +6544,7 @@ enum { | |||
5872 | ALC662_FIXUP_ASUS_MODE6, | 6544 | ALC662_FIXUP_ASUS_MODE6, |
5873 | ALC662_FIXUP_ASUS_MODE7, | 6545 | ALC662_FIXUP_ASUS_MODE7, |
5874 | ALC662_FIXUP_ASUS_MODE8, | 6546 | ALC662_FIXUP_ASUS_MODE8, |
6547 | ALC662_FIXUP_NO_JACK_DETECT, | ||
5875 | }; | 6548 | }; |
5876 | 6549 | ||
5877 | static const struct alc_fixup alc662_fixups[] = { | 6550 | static const struct alc_fixup alc662_fixups[] = { |
@@ -6017,6 +6690,10 @@ static const struct alc_fixup alc662_fixups[] = { | |||
6017 | .chained = true, | 6690 | .chained = true, |
6018 | .chain_id = ALC662_FIXUP_SKU_IGNORE | 6691 | .chain_id = ALC662_FIXUP_SKU_IGNORE |
6019 | }, | 6692 | }, |
6693 | [ALC662_FIXUP_NO_JACK_DETECT] = { | ||
6694 | .type = ALC_FIXUP_FUNC, | ||
6695 | .v.func = alc_fixup_no_jack_detect, | ||
6696 | }, | ||
6020 | }; | 6697 | }; |
6021 | 6698 | ||
6022 | static const struct snd_pci_quirk alc662_fixup_tbl[] = { | 6699 | static const struct snd_pci_quirk alc662_fixup_tbl[] = { |
@@ -6025,6 +6702,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { | |||
6025 | SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE), | 6702 | SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE), |
6026 | SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), | 6703 | SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), |
6027 | SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800), | 6704 | SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800), |
6705 | SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT), | ||
6028 | SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ASUS_MODE2), | 6706 | SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ASUS_MODE2), |
6029 | SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD), | 6707 | SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD), |
6030 | SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD), | 6708 | SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD), |
@@ -6146,15 +6824,6 @@ static int patch_alc662(struct hda_codec *codec) | |||
6146 | if (err < 0) | 6824 | if (err < 0) |
6147 | goto error; | 6825 | goto error; |
6148 | 6826 | ||
6149 | if (!spec->no_analog && !spec->adc_nids) { | ||
6150 | alc_auto_fill_adc_caps(codec); | ||
6151 | alc_rebuild_imux_for_auto_mic(codec); | ||
6152 | alc_remove_invalid_adc_nids(codec); | ||
6153 | } | ||
6154 | |||
6155 | if (!spec->no_analog && !spec->cap_mixer) | ||
6156 | set_capture_mixer(codec); | ||
6157 | |||
6158 | if (!spec->no_analog && has_cdefine_beep(codec)) { | 6827 | if (!spec->no_analog && has_cdefine_beep(codec)) { |
6159 | err = snd_hda_attach_beep_device(codec, 0x1); | 6828 | err = snd_hda_attach_beep_device(codec, 0x1); |
6160 | if (err < 0) | 6829 | if (err < 0) |
@@ -6174,16 +6843,10 @@ static int patch_alc662(struct hda_codec *codec) | |||
6174 | } | 6843 | } |
6175 | } | 6844 | } |
6176 | 6845 | ||
6177 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); | ||
6178 | |||
6179 | codec->patch_ops = alc_patch_ops; | 6846 | codec->patch_ops = alc_patch_ops; |
6180 | spec->init_hook = alc_auto_init_std; | ||
6181 | spec->shutup = alc_eapd_shutup; | 6847 | spec->shutup = alc_eapd_shutup; |
6182 | 6848 | ||
6183 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 6849 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); |
6184 | if (!spec->loopback.amplist) | ||
6185 | spec->loopback.amplist = alc662_loopbacks; | ||
6186 | #endif | ||
6187 | 6850 | ||
6188 | return 0; | 6851 | return 0; |
6189 | 6852 | ||
@@ -6223,11 +6886,7 @@ static int patch_alc680(struct hda_codec *codec) | |||
6223 | return err; | 6886 | return err; |
6224 | } | 6887 | } |
6225 | 6888 | ||
6226 | if (!spec->no_analog && !spec->cap_mixer) | ||
6227 | set_capture_mixer(codec); | ||
6228 | |||
6229 | codec->patch_ops = alc_patch_ops; | 6889 | codec->patch_ops = alc_patch_ops; |
6230 | spec->init_hook = alc_auto_init_std; | ||
6231 | 6890 | ||
6232 | return 0; | 6891 | return 0; |
6233 | } | 6892 | } |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 948f0be2f4f3..33a9946b492c 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -99,6 +99,7 @@ enum { | |||
99 | STAC_DELL_VOSTRO_3500, | 99 | STAC_DELL_VOSTRO_3500, |
100 | STAC_92HD83XXX_HP_cNB11_INTQUAD, | 100 | STAC_92HD83XXX_HP_cNB11_INTQUAD, |
101 | STAC_HP_DV7_4000, | 101 | STAC_HP_DV7_4000, |
102 | STAC_HP_ZEPHYR, | ||
102 | STAC_92HD83XXX_MODELS | 103 | STAC_92HD83XXX_MODELS |
103 | }; | 104 | }; |
104 | 105 | ||
@@ -309,6 +310,8 @@ struct sigmatel_spec { | |||
309 | unsigned long auto_capvols[MAX_ADCS_NUM]; | 310 | unsigned long auto_capvols[MAX_ADCS_NUM]; |
310 | unsigned auto_dmic_cnt; | 311 | unsigned auto_dmic_cnt; |
311 | hda_nid_t auto_dmic_nids[MAX_DMICS_NUM]; | 312 | hda_nid_t auto_dmic_nids[MAX_DMICS_NUM]; |
313 | |||
314 | struct hda_vmaster_mute_hook vmaster_mute; | ||
312 | }; | 315 | }; |
313 | 316 | ||
314 | static const hda_nid_t stac9200_adc_nids[1] = { | 317 | static const hda_nid_t stac9200_adc_nids[1] = { |
@@ -662,7 +665,6 @@ static int stac92xx_smux_enum_put(struct snd_kcontrol *kcontrol, | |||
662 | return 0; | 665 | return 0; |
663 | } | 666 | } |
664 | 667 | ||
665 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
666 | static int stac_vrefout_set(struct hda_codec *codec, | 668 | static int stac_vrefout_set(struct hda_codec *codec, |
667 | hda_nid_t nid, unsigned int new_vref) | 669 | hda_nid_t nid, unsigned int new_vref) |
668 | { | 670 | { |
@@ -686,7 +688,6 @@ static int stac_vrefout_set(struct hda_codec *codec, | |||
686 | 688 | ||
687 | return 1; | 689 | return 1; |
688 | } | 690 | } |
689 | #endif | ||
690 | 691 | ||
691 | static unsigned int stac92xx_vref_set(struct hda_codec *codec, | 692 | static unsigned int stac92xx_vref_set(struct hda_codec *codec, |
692 | hda_nid_t nid, unsigned int new_vref) | 693 | hda_nid_t nid, unsigned int new_vref) |
@@ -894,6 +895,13 @@ static const struct hda_verb stac92hd83xxx_core_init[] = { | |||
894 | {} | 895 | {} |
895 | }; | 896 | }; |
896 | 897 | ||
898 | static const struct hda_verb stac92hd83xxx_hp_zephyr_init[] = { | ||
899 | { 0x22, 0x785, 0x43 }, | ||
900 | { 0x22, 0x782, 0xe0 }, | ||
901 | { 0x22, 0x795, 0x00 }, | ||
902 | {} | ||
903 | }; | ||
904 | |||
897 | static const struct hda_verb stac92hd71bxx_core_init[] = { | 905 | static const struct hda_verb stac92hd71bxx_core_init[] = { |
898 | /* set master volume and direct control */ | 906 | /* set master volume and direct control */ |
899 | { 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | 907 | { 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, |
@@ -999,8 +1007,8 @@ static const struct hda_verb stac9205_core_init[] = { | |||
999 | } | 1007 | } |
1000 | 1008 | ||
1001 | static const struct snd_kcontrol_new stac9200_mixer[] = { | 1009 | static const struct snd_kcontrol_new stac9200_mixer[] = { |
1002 | HDA_CODEC_VOLUME_MIN_MUTE("Master Playback Volume", 0xb, 0, HDA_OUTPUT), | 1010 | HDA_CODEC_VOLUME_MIN_MUTE("PCM Playback Volume", 0xb, 0, HDA_OUTPUT), |
1003 | HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT), | 1011 | HDA_CODEC_MUTE("PCM Playback Switch", 0xb, 0, HDA_OUTPUT), |
1004 | HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT), | 1012 | HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT), |
1005 | HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT), | 1013 | HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT), |
1006 | { } /* end */ | 1014 | { } /* end */ |
@@ -1027,8 +1035,8 @@ static const struct snd_kcontrol_new stac92hd71bxx_loopback[] = { | |||
1027 | }; | 1035 | }; |
1028 | 1036 | ||
1029 | static const struct snd_kcontrol_new stac925x_mixer[] = { | 1037 | static const struct snd_kcontrol_new stac925x_mixer[] = { |
1030 | HDA_CODEC_VOLUME_MIN_MUTE("Master Playback Volume", 0xe, 0, HDA_OUTPUT), | 1038 | HDA_CODEC_VOLUME_MIN_MUTE("PCM Playback Volume", 0xe, 0, HDA_OUTPUT), |
1031 | HDA_CODEC_MUTE("Master Playback Switch", 0x0e, 0, HDA_OUTPUT), | 1039 | HDA_CODEC_MUTE("PCM Playback Switch", 0x0e, 0, HDA_OUTPUT), |
1032 | { } /* end */ | 1040 | { } /* end */ |
1033 | }; | 1041 | }; |
1034 | 1042 | ||
@@ -1060,34 +1068,25 @@ static struct snd_kcontrol_new stac_smux_mixer = { | |||
1060 | .put = stac92xx_smux_enum_put, | 1068 | .put = stac92xx_smux_enum_put, |
1061 | }; | 1069 | }; |
1062 | 1070 | ||
1063 | static const char * const slave_vols[] = { | 1071 | static const char * const slave_pfxs[] = { |
1064 | "Front Playback Volume", | 1072 | "Front", "Surround", "Center", "LFE", "Side", |
1065 | "Surround Playback Volume", | 1073 | "Headphone", "Speaker", "IEC958", |
1066 | "Center Playback Volume", | ||
1067 | "LFE Playback Volume", | ||
1068 | "Side Playback Volume", | ||
1069 | "Headphone Playback Volume", | ||
1070 | "Speaker Playback Volume", | ||
1071 | NULL | 1074 | NULL |
1072 | }; | 1075 | }; |
1073 | 1076 | ||
1074 | static const char * const slave_sws[] = { | 1077 | static void stac92xx_update_led_status(struct hda_codec *codec, int enabled); |
1075 | "Front Playback Switch", | 1078 | |
1076 | "Surround Playback Switch", | 1079 | static void stac92xx_vmaster_hook(void *private_data, int val) |
1077 | "Center Playback Switch", | 1080 | { |
1078 | "LFE Playback Switch", | 1081 | stac92xx_update_led_status(private_data, val); |
1079 | "Side Playback Switch", | 1082 | } |
1080 | "Headphone Playback Switch", | ||
1081 | "Speaker Playback Switch", | ||
1082 | "IEC958 Playback Switch", | ||
1083 | NULL | ||
1084 | }; | ||
1085 | 1083 | ||
1086 | static void stac92xx_free_kctls(struct hda_codec *codec); | 1084 | static void stac92xx_free_kctls(struct hda_codec *codec); |
1087 | 1085 | ||
1088 | static int stac92xx_build_controls(struct hda_codec *codec) | 1086 | static int stac92xx_build_controls(struct hda_codec *codec) |
1089 | { | 1087 | { |
1090 | struct sigmatel_spec *spec = codec->spec; | 1088 | struct sigmatel_spec *spec = codec->spec; |
1089 | unsigned int vmaster_tlv[4]; | ||
1091 | int err; | 1090 | int err; |
1092 | int i; | 1091 | int i; |
1093 | 1092 | ||
@@ -1144,22 +1143,28 @@ static int stac92xx_build_controls(struct hda_codec *codec) | |||
1144 | } | 1143 | } |
1145 | 1144 | ||
1146 | /* if we have no master control, let's create it */ | 1145 | /* if we have no master control, let's create it */ |
1147 | if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { | 1146 | snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0], |
1148 | unsigned int vmaster_tlv[4]; | 1147 | HDA_OUTPUT, vmaster_tlv); |
1149 | snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0], | 1148 | /* correct volume offset */ |
1150 | HDA_OUTPUT, vmaster_tlv); | 1149 | vmaster_tlv[2] += vmaster_tlv[3] * spec->volume_offset; |
1151 | /* correct volume offset */ | 1150 | /* minimum value is actually mute */ |
1152 | vmaster_tlv[2] += vmaster_tlv[3] * spec->volume_offset; | 1151 | vmaster_tlv[3] |= TLV_DB_SCALE_MUTE; |
1153 | /* minimum value is actually mute */ | 1152 | err = snd_hda_add_vmaster(codec, "Master Playback Volume", |
1154 | vmaster_tlv[3] |= TLV_DB_SCALE_MUTE; | 1153 | vmaster_tlv, slave_pfxs, |
1155 | err = snd_hda_add_vmaster(codec, "Master Playback Volume", | 1154 | "Playback Volume"); |
1156 | vmaster_tlv, slave_vols); | 1155 | if (err < 0) |
1157 | if (err < 0) | 1156 | return err; |
1158 | return err; | 1157 | |
1159 | } | 1158 | err = __snd_hda_add_vmaster(codec, "Master Playback Switch", |
1160 | if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { | 1159 | NULL, slave_pfxs, |
1161 | err = snd_hda_add_vmaster(codec, "Master Playback Switch", | 1160 | "Playback Switch", true, |
1162 | NULL, slave_sws); | 1161 | &spec->vmaster_mute.sw_kctl); |
1162 | if (err < 0) | ||
1163 | return err; | ||
1164 | |||
1165 | if (spec->gpio_led) { | ||
1166 | spec->vmaster_mute.hook = stac92xx_vmaster_hook; | ||
1167 | err = snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute, true); | ||
1163 | if (err < 0) | 1168 | if (err < 0) |
1164 | return err; | 1169 | return err; |
1165 | } | 1170 | } |
@@ -1636,6 +1641,12 @@ static const unsigned int hp_dv7_4000_pin_configs[10] = { | |||
1636 | 0x40f000f0, 0x40f000f0, | 1641 | 0x40f000f0, 0x40f000f0, |
1637 | }; | 1642 | }; |
1638 | 1643 | ||
1644 | static const unsigned int hp_zephyr_pin_configs[10] = { | ||
1645 | 0x01813050, 0x0421201f, 0x04a1205e, 0x96130310, | ||
1646 | 0x96130310, 0x0101401f, 0x1111611f, 0xd5a30130, | ||
1647 | 0, 0, | ||
1648 | }; | ||
1649 | |||
1639 | static const unsigned int hp_cNB11_intquad_pin_configs[10] = { | 1650 | static const unsigned int hp_cNB11_intquad_pin_configs[10] = { |
1640 | 0x40f000f0, 0x0221101f, 0x02a11020, 0x92170110, | 1651 | 0x40f000f0, 0x0221101f, 0x02a11020, 0x92170110, |
1641 | 0x40f000f0, 0x92170110, 0x40f000f0, 0xd5a30130, | 1652 | 0x40f000f0, 0x92170110, 0x40f000f0, 0xd5a30130, |
@@ -1649,6 +1660,7 @@ static const unsigned int *stac92hd83xxx_brd_tbl[STAC_92HD83XXX_MODELS] = { | |||
1649 | [STAC_DELL_VOSTRO_3500] = dell_vostro_3500_pin_configs, | 1660 | [STAC_DELL_VOSTRO_3500] = dell_vostro_3500_pin_configs, |
1650 | [STAC_92HD83XXX_HP_cNB11_INTQUAD] = hp_cNB11_intquad_pin_configs, | 1661 | [STAC_92HD83XXX_HP_cNB11_INTQUAD] = hp_cNB11_intquad_pin_configs, |
1651 | [STAC_HP_DV7_4000] = hp_dv7_4000_pin_configs, | 1662 | [STAC_HP_DV7_4000] = hp_dv7_4000_pin_configs, |
1663 | [STAC_HP_ZEPHYR] = hp_zephyr_pin_configs, | ||
1652 | }; | 1664 | }; |
1653 | 1665 | ||
1654 | static const char * const stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = { | 1666 | static const char * const stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = { |
@@ -1659,6 +1671,7 @@ static const char * const stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = { | |||
1659 | [STAC_DELL_VOSTRO_3500] = "dell-vostro-3500", | 1671 | [STAC_DELL_VOSTRO_3500] = "dell-vostro-3500", |
1660 | [STAC_92HD83XXX_HP_cNB11_INTQUAD] = "hp_cNB11_intquad", | 1672 | [STAC_92HD83XXX_HP_cNB11_INTQUAD] = "hp_cNB11_intquad", |
1661 | [STAC_HP_DV7_4000] = "hp-dv7-4000", | 1673 | [STAC_HP_DV7_4000] = "hp-dv7-4000", |
1674 | [STAC_HP_ZEPHYR] = "hp-zephyr", | ||
1662 | }; | 1675 | }; |
1663 | 1676 | ||
1664 | static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { | 1677 | static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { |
@@ -1711,6 +1724,14 @@ static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { | |||
1711 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | 1724 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), |
1712 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3593, | 1725 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3593, |
1713 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | 1726 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), |
1727 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3561, | ||
1728 | "HP", STAC_HP_ZEPHYR), | ||
1729 | {} /* terminator */ | ||
1730 | }; | ||
1731 | |||
1732 | static const struct snd_pci_quirk stac92hd83xxx_codec_id_cfg_tbl[] = { | ||
1733 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3561, | ||
1734 | "HP", STAC_HP_ZEPHYR), | ||
1714 | {} /* terminator */ | 1735 | {} /* terminator */ |
1715 | }; | 1736 | }; |
1716 | 1737 | ||
@@ -4410,8 +4431,7 @@ static int stac92xx_init(struct hda_codec *codec) | |||
4410 | snd_hda_jack_report_sync(codec); | 4431 | snd_hda_jack_report_sync(codec); |
4411 | 4432 | ||
4412 | /* sync mute LED */ | 4433 | /* sync mute LED */ |
4413 | if (spec->gpio_led) | 4434 | snd_hda_sync_vmaster_hook(&spec->vmaster_mute); |
4414 | hda_call_check_power_status(codec, 0x01); | ||
4415 | if (spec->dac_list) | 4435 | if (spec->dac_list) |
4416 | stac92xx_power_down(codec); | 4436 | stac92xx_power_down(codec); |
4417 | return 0; | 4437 | return 0; |
@@ -4629,7 +4649,7 @@ static void stac92xx_hp_detect(struct hda_codec *codec) | |||
4629 | unsigned int val = AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN; | 4649 | unsigned int val = AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN; |
4630 | if (no_hp_sensing(spec, i)) | 4650 | if (no_hp_sensing(spec, i)) |
4631 | continue; | 4651 | continue; |
4632 | if (presence) | 4652 | if (1 /*presence*/) |
4633 | stac92xx_set_pinctl(codec, cfg->hp_pins[i], val); | 4653 | stac92xx_set_pinctl(codec, cfg->hp_pins[i], val); |
4634 | #if 0 /* FIXME */ | 4654 | #if 0 /* FIXME */ |
4635 | /* Resetting the pinctl like below may lead to (a sort of) regressions | 4655 | /* Resetting the pinctl like below may lead to (a sort of) regressions |
@@ -4989,7 +5009,6 @@ static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state) | |||
4989 | return 0; | 5009 | return 0; |
4990 | } | 5010 | } |
4991 | 5011 | ||
4992 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
4993 | static int stac92xx_pre_resume(struct hda_codec *codec) | 5012 | static int stac92xx_pre_resume(struct hda_codec *codec) |
4994 | { | 5013 | { |
4995 | struct sigmatel_spec *spec = codec->spec; | 5014 | struct sigmatel_spec *spec = codec->spec; |
@@ -5024,83 +5043,41 @@ static void stac92xx_set_power_state(struct hda_codec *codec, hda_nid_t fg, | |||
5024 | afg_power_state); | 5043 | afg_power_state); |
5025 | snd_hda_codec_set_power_to_all(codec, fg, power_state, true); | 5044 | snd_hda_codec_set_power_to_all(codec, fg, power_state, true); |
5026 | } | 5045 | } |
5046 | #else | ||
5047 | #define stac92xx_suspend NULL | ||
5048 | #define stac92xx_resume NULL | ||
5049 | #define stac92xx_pre_resume NULL | ||
5050 | #define stac92xx_set_power_state NULL | ||
5051 | #endif /* CONFIG_PM */ | ||
5027 | 5052 | ||
5028 | /* | 5053 | /* update mute-LED accoring to the master switch */ |
5029 | * For this feature CONFIG_SND_HDA_POWER_SAVE is needed | 5054 | static void stac92xx_update_led_status(struct hda_codec *codec, int enabled) |
5030 | * as mute LED state is updated in check_power_status hook | ||
5031 | */ | ||
5032 | static int stac92xx_update_led_status(struct hda_codec *codec) | ||
5033 | { | 5055 | { |
5034 | struct sigmatel_spec *spec = codec->spec; | 5056 | struct sigmatel_spec *spec = codec->spec; |
5035 | int i, num_ext_dacs, muted = 1; | 5057 | int muted = !enabled; |
5036 | unsigned int muted_lvl, notmtd_lvl; | ||
5037 | hda_nid_t nid; | ||
5038 | 5058 | ||
5039 | if (!spec->gpio_led) | 5059 | if (!spec->gpio_led) |
5040 | return 0; | 5060 | return; |
5061 | |||
5062 | /* LED state is inverted on these systems */ | ||
5063 | if (spec->gpio_led_polarity) | ||
5064 | muted = !muted; | ||
5041 | 5065 | ||
5042 | for (i = 0; i < spec->multiout.num_dacs; i++) { | ||
5043 | nid = spec->multiout.dac_nids[i]; | ||
5044 | if (!(snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) & | ||
5045 | HDA_AMP_MUTE)) { | ||
5046 | muted = 0; /* something heard */ | ||
5047 | break; | ||
5048 | } | ||
5049 | } | ||
5050 | if (muted && spec->multiout.hp_nid) | ||
5051 | if (!(snd_hda_codec_amp_read(codec, | ||
5052 | spec->multiout.hp_nid, 0, HDA_OUTPUT, 0) & | ||
5053 | HDA_AMP_MUTE)) { | ||
5054 | muted = 0; /* HP is not muted */ | ||
5055 | } | ||
5056 | num_ext_dacs = ARRAY_SIZE(spec->multiout.extra_out_nid); | ||
5057 | for (i = 0; muted && i < num_ext_dacs; i++) { | ||
5058 | nid = spec->multiout.extra_out_nid[i]; | ||
5059 | if (nid == 0) | ||
5060 | break; | ||
5061 | if (!(snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) & | ||
5062 | HDA_AMP_MUTE)) { | ||
5063 | muted = 0; /* extra output is not muted */ | ||
5064 | } | ||
5065 | } | ||
5066 | /*polarity defines *not* muted state level*/ | 5066 | /*polarity defines *not* muted state level*/ |
5067 | if (!spec->vref_mute_led_nid) { | 5067 | if (!spec->vref_mute_led_nid) { |
5068 | if (muted) | 5068 | if (muted) |
5069 | spec->gpio_data &= ~spec->gpio_led; /* orange */ | 5069 | spec->gpio_data &= ~spec->gpio_led; /* orange */ |
5070 | else | 5070 | else |
5071 | spec->gpio_data |= spec->gpio_led; /* white */ | 5071 | spec->gpio_data |= spec->gpio_led; /* white */ |
5072 | |||
5073 | if (!spec->gpio_led_polarity) { | ||
5074 | /* LED state is inverted on these systems */ | ||
5075 | spec->gpio_data ^= spec->gpio_led; | ||
5076 | } | ||
5077 | stac_gpio_set(codec, spec->gpio_mask, | 5072 | stac_gpio_set(codec, spec->gpio_mask, |
5078 | spec->gpio_dir, spec->gpio_data); | 5073 | spec->gpio_dir, spec->gpio_data); |
5079 | } else { | 5074 | } else { |
5080 | notmtd_lvl = spec->gpio_led_polarity ? | 5075 | spec->vref_led = muted ? AC_PINCTL_VREF_50 : AC_PINCTL_VREF_GRD; |
5081 | AC_PINCTL_VREF_HIZ : AC_PINCTL_VREF_GRD; | ||
5082 | muted_lvl = spec->gpio_led_polarity ? | ||
5083 | AC_PINCTL_VREF_GRD : AC_PINCTL_VREF_HIZ; | ||
5084 | spec->vref_led = muted ? muted_lvl : notmtd_lvl; | ||
5085 | stac_vrefout_set(codec, spec->vref_mute_led_nid, | 5076 | stac_vrefout_set(codec, spec->vref_mute_led_nid, |
5086 | spec->vref_led); | 5077 | spec->vref_led); |
5087 | } | 5078 | } |
5088 | return 0; | ||
5089 | } | 5079 | } |
5090 | 5080 | ||
5091 | /* | ||
5092 | * use power check for controlling mute led of HP notebooks | ||
5093 | */ | ||
5094 | static int stac92xx_check_power_status(struct hda_codec *codec, | ||
5095 | hda_nid_t nid) | ||
5096 | { | ||
5097 | stac92xx_update_led_status(codec); | ||
5098 | |||
5099 | return 0; | ||
5100 | } | ||
5101 | #endif /* CONFIG_SND_HDA_POWER_SAVE */ | ||
5102 | #endif /* CONFIG_PM */ | ||
5103 | |||
5104 | static const struct hda_codec_ops stac92xx_patch_ops = { | 5081 | static const struct hda_codec_ops stac92xx_patch_ops = { |
5105 | .build_controls = stac92xx_build_controls, | 5082 | .build_controls = stac92xx_build_controls, |
5106 | .build_pcms = stac92xx_build_pcms, | 5083 | .build_pcms = stac92xx_build_pcms, |
@@ -5580,6 +5557,12 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) | |||
5580 | STAC_92HD83XXX_MODELS, | 5557 | STAC_92HD83XXX_MODELS, |
5581 | stac92hd83xxx_models, | 5558 | stac92hd83xxx_models, |
5582 | stac92hd83xxx_cfg_tbl); | 5559 | stac92hd83xxx_cfg_tbl); |
5560 | /* check codec subsystem id if not found */ | ||
5561 | if (spec->board_config < 0) | ||
5562 | spec->board_config = | ||
5563 | snd_hda_check_board_codec_sid_config(codec, | ||
5564 | STAC_92HD83XXX_MODELS, stac92hd83xxx_models, | ||
5565 | stac92hd83xxx_codec_id_cfg_tbl); | ||
5583 | again: | 5566 | again: |
5584 | if (spec->board_config < 0) | 5567 | if (spec->board_config < 0) |
5585 | snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", | 5568 | snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", |
@@ -5590,12 +5573,17 @@ again: | |||
5590 | 5573 | ||
5591 | codec->patch_ops = stac92xx_patch_ops; | 5574 | codec->patch_ops = stac92xx_patch_ops; |
5592 | 5575 | ||
5576 | switch (spec->board_config) { | ||
5577 | case STAC_HP_ZEPHYR: | ||
5578 | spec->init = stac92hd83xxx_hp_zephyr_init; | ||
5579 | break; | ||
5580 | } | ||
5581 | |||
5593 | if (find_mute_led_cfg(codec, -1/*no default cfg*/)) | 5582 | if (find_mute_led_cfg(codec, -1/*no default cfg*/)) |
5594 | snd_printd("mute LED gpio %d polarity %d\n", | 5583 | snd_printd("mute LED gpio %d polarity %d\n", |
5595 | spec->gpio_led, | 5584 | spec->gpio_led, |
5596 | spec->gpio_led_polarity); | 5585 | spec->gpio_led_polarity); |
5597 | 5586 | ||
5598 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
5599 | if (spec->gpio_led) { | 5587 | if (spec->gpio_led) { |
5600 | if (!spec->vref_mute_led_nid) { | 5588 | if (!spec->vref_mute_led_nid) { |
5601 | spec->gpio_mask |= spec->gpio_led; | 5589 | spec->gpio_mask |= spec->gpio_led; |
@@ -5605,11 +5593,10 @@ again: | |||
5605 | codec->patch_ops.set_power_state = | 5593 | codec->patch_ops.set_power_state = |
5606 | stac92xx_set_power_state; | 5594 | stac92xx_set_power_state; |
5607 | } | 5595 | } |
5596 | #ifdef CONFIG_PM | ||
5608 | codec->patch_ops.pre_resume = stac92xx_pre_resume; | 5597 | codec->patch_ops.pre_resume = stac92xx_pre_resume; |
5609 | codec->patch_ops.check_power_status = | 5598 | #endif |
5610 | stac92xx_check_power_status; | ||
5611 | } | 5599 | } |
5612 | #endif | ||
5613 | 5600 | ||
5614 | err = stac92xx_parse_auto_config(codec); | 5601 | err = stac92xx_parse_auto_config(codec); |
5615 | if (!err) { | 5602 | if (!err) { |
@@ -5906,7 +5893,6 @@ again: | |||
5906 | spec->gpio_led, | 5893 | spec->gpio_led, |
5907 | spec->gpio_led_polarity); | 5894 | spec->gpio_led_polarity); |
5908 | 5895 | ||
5909 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
5910 | if (spec->gpio_led) { | 5896 | if (spec->gpio_led) { |
5911 | if (!spec->vref_mute_led_nid) { | 5897 | if (!spec->vref_mute_led_nid) { |
5912 | spec->gpio_mask |= spec->gpio_led; | 5898 | spec->gpio_mask |= spec->gpio_led; |
@@ -5916,11 +5902,10 @@ again: | |||
5916 | codec->patch_ops.set_power_state = | 5902 | codec->patch_ops.set_power_state = |
5917 | stac92xx_set_power_state; | 5903 | stac92xx_set_power_state; |
5918 | } | 5904 | } |
5905 | #ifdef CONFIG_PM | ||
5919 | codec->patch_ops.pre_resume = stac92xx_pre_resume; | 5906 | codec->patch_ops.pre_resume = stac92xx_pre_resume; |
5920 | codec->patch_ops.check_power_status = | 5907 | #endif |
5921 | stac92xx_check_power_status; | ||
5922 | } | 5908 | } |
5923 | #endif | ||
5924 | 5909 | ||
5925 | spec->multiout.dac_nids = spec->dac_nids; | 5910 | spec->multiout.dac_nids = spec->dac_nids; |
5926 | 5911 | ||
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 284e311040fe..06214fdc9486 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c | |||
@@ -550,7 +550,10 @@ static void via_auto_init_output(struct hda_codec *codec, | |||
550 | pin = path->path[path->depth - 1]; | 550 | pin = path->path[path->depth - 1]; |
551 | 551 | ||
552 | init_output_pin(codec, pin, pin_type); | 552 | init_output_pin(codec, pin, pin_type); |
553 | caps = query_amp_caps(codec, pin, HDA_OUTPUT); | 553 | if (get_wcaps(codec, pin) & AC_WCAP_OUT_AMP) |
554 | caps = query_amp_caps(codec, pin, HDA_OUTPUT); | ||
555 | else | ||
556 | caps = 0; | ||
554 | if (caps & AC_AMPCAP_MUTE) { | 557 | if (caps & AC_AMPCAP_MUTE) { |
555 | unsigned int val; | 558 | unsigned int val; |
556 | val = (caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT; | 559 | val = (caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT; |
@@ -645,6 +648,10 @@ static void via_auto_init_analog_input(struct hda_codec *codec) | |||
645 | 648 | ||
646 | /* init ADCs */ | 649 | /* init ADCs */ |
647 | for (i = 0; i < spec->num_adc_nids; i++) { | 650 | for (i = 0; i < spec->num_adc_nids; i++) { |
651 | hda_nid_t nid = spec->adc_nids[i]; | ||
652 | if (!(get_wcaps(codec, nid) & AC_WCAP_IN_AMP) || | ||
653 | !(query_amp_caps(codec, nid, HDA_INPUT) & AC_AMPCAP_MUTE)) | ||
654 | continue; | ||
648 | snd_hda_codec_write(codec, spec->adc_nids[i], 0, | 655 | snd_hda_codec_write(codec, spec->adc_nids[i], 0, |
649 | AC_VERB_SET_AMP_GAIN_MUTE, | 656 | AC_VERB_SET_AMP_GAIN_MUTE, |
650 | AMP_IN_UNMUTE(0)); | 657 | AMP_IN_UNMUTE(0)); |
@@ -666,6 +673,9 @@ static void via_auto_init_analog_input(struct hda_codec *codec) | |||
666 | /* init input-src */ | 673 | /* init input-src */ |
667 | for (i = 0; i < spec->num_adc_nids; i++) { | 674 | for (i = 0; i < spec->num_adc_nids; i++) { |
668 | int adc_idx = spec->inputs[spec->cur_mux[i]].adc_idx; | 675 | int adc_idx = spec->inputs[spec->cur_mux[i]].adc_idx; |
676 | /* secondary ADCs must have the unique MUX */ | ||
677 | if (i > 0 && !spec->mux_nids[i]) | ||
678 | break; | ||
669 | if (spec->mux_nids[adc_idx]) { | 679 | if (spec->mux_nids[adc_idx]) { |
670 | int mux_idx = spec->inputs[spec->cur_mux[i]].mux_idx; | 680 | int mux_idx = spec->inputs[spec->cur_mux[i]].mux_idx; |
671 | snd_hda_codec_write(codec, spec->mux_nids[adc_idx], 0, | 681 | snd_hda_codec_write(codec, spec->mux_nids[adc_idx], 0, |
@@ -1442,25 +1452,9 @@ static const struct hda_pcm_stream via_pcm_digital_capture = { | |||
1442 | /* | 1452 | /* |
1443 | * slave controls for virtual master | 1453 | * slave controls for virtual master |
1444 | */ | 1454 | */ |
1445 | static const char * const via_slave_vols[] = { | 1455 | static const char * const via_slave_pfxs[] = { |
1446 | "Front Playback Volume", | 1456 | "Front", "Surround", "Center", "LFE", "Side", |
1447 | "Surround Playback Volume", | 1457 | "Headphone", "Speaker", |
1448 | "Center Playback Volume", | ||
1449 | "LFE Playback Volume", | ||
1450 | "Side Playback Volume", | ||
1451 | "Headphone Playback Volume", | ||
1452 | "Speaker Playback Volume", | ||
1453 | NULL, | ||
1454 | }; | ||
1455 | |||
1456 | static const char * const via_slave_sws[] = { | ||
1457 | "Front Playback Switch", | ||
1458 | "Surround Playback Switch", | ||
1459 | "Center Playback Switch", | ||
1460 | "LFE Playback Switch", | ||
1461 | "Side Playback Switch", | ||
1462 | "Headphone Playback Switch", | ||
1463 | "Speaker Playback Switch", | ||
1464 | NULL, | 1458 | NULL, |
1465 | }; | 1459 | }; |
1466 | 1460 | ||
@@ -1505,13 +1499,15 @@ static int via_build_controls(struct hda_codec *codec) | |||
1505 | snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0], | 1499 | snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0], |
1506 | HDA_OUTPUT, vmaster_tlv); | 1500 | HDA_OUTPUT, vmaster_tlv); |
1507 | err = snd_hda_add_vmaster(codec, "Master Playback Volume", | 1501 | err = snd_hda_add_vmaster(codec, "Master Playback Volume", |
1508 | vmaster_tlv, via_slave_vols); | 1502 | vmaster_tlv, via_slave_pfxs, |
1503 | "Playback Volume"); | ||
1509 | if (err < 0) | 1504 | if (err < 0) |
1510 | return err; | 1505 | return err; |
1511 | } | 1506 | } |
1512 | if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { | 1507 | if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { |
1513 | err = snd_hda_add_vmaster(codec, "Master Playback Switch", | 1508 | err = snd_hda_add_vmaster(codec, "Master Playback Switch", |
1514 | NULL, via_slave_sws); | 1509 | NULL, via_slave_pfxs, |
1510 | "Playback Switch"); | ||
1515 | if (err < 0) | 1511 | if (err < 0) |
1516 | return err; | 1512 | return err; |
1517 | } | 1513 | } |
@@ -1519,6 +1515,8 @@ static int via_build_controls(struct hda_codec *codec) | |||
1519 | /* assign Capture Source enums to NID */ | 1515 | /* assign Capture Source enums to NID */ |
1520 | kctl = snd_hda_find_mixer_ctl(codec, "Input Source"); | 1516 | kctl = snd_hda_find_mixer_ctl(codec, "Input Source"); |
1521 | for (i = 0; kctl && i < kctl->count; i++) { | 1517 | for (i = 0; kctl && i < kctl->count; i++) { |
1518 | if (!spec->mux_nids[i]) | ||
1519 | continue; | ||
1522 | err = snd_hda_add_nid(codec, kctl, i, spec->mux_nids[i]); | 1520 | err = snd_hda_add_nid(codec, kctl, i, spec->mux_nids[i]); |
1523 | if (err < 0) | 1521 | if (err < 0) |
1524 | return err; | 1522 | return err; |
@@ -2485,6 +2483,8 @@ static int create_mic_boost_ctls(struct hda_codec *codec) | |||
2485 | { | 2483 | { |
2486 | struct via_spec *spec = codec->spec; | 2484 | struct via_spec *spec = codec->spec; |
2487 | const struct auto_pin_cfg *cfg = &spec->autocfg; | 2485 | const struct auto_pin_cfg *cfg = &spec->autocfg; |
2486 | const char *prev_label = NULL; | ||
2487 | int type_idx = 0; | ||
2488 | int i, err; | 2488 | int i, err; |
2489 | 2489 | ||
2490 | for (i = 0; i < cfg->num_inputs; i++) { | 2490 | for (i = 0; i < cfg->num_inputs; i++) { |
@@ -2499,8 +2499,13 @@ static int create_mic_boost_ctls(struct hda_codec *codec) | |||
2499 | if (caps == -1 || !(caps & AC_AMPCAP_NUM_STEPS)) | 2499 | if (caps == -1 || !(caps & AC_AMPCAP_NUM_STEPS)) |
2500 | continue; | 2500 | continue; |
2501 | label = hda_get_autocfg_input_label(codec, cfg, i); | 2501 | label = hda_get_autocfg_input_label(codec, cfg, i); |
2502 | if (prev_label && !strcmp(label, prev_label)) | ||
2503 | type_idx++; | ||
2504 | else | ||
2505 | type_idx = 0; | ||
2506 | prev_label = label; | ||
2502 | snprintf(name, sizeof(name), "%s Boost Volume", label); | 2507 | snprintf(name, sizeof(name), "%s Boost Volume", label); |
2503 | err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name, | 2508 | err = __via_add_control(spec, VIA_CTL_WIDGET_VOL, name, type_idx, |
2504 | HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_INPUT)); | 2509 | HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_INPUT)); |
2505 | if (err < 0) | 2510 | if (err < 0) |
2506 | return err; | 2511 | return err; |
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index 92362973764d..812d10e43ae0 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c | |||
@@ -1013,6 +1013,25 @@ static int set_rate_constraints(struct snd_ice1712 *ice, | |||
1013 | ice->hw_rates); | 1013 | ice->hw_rates); |
1014 | } | 1014 | } |
1015 | 1015 | ||
1016 | /* if the card has the internal rate locked (is_pro_locked), limit runtime | ||
1017 | hw rates to the current internal rate only. | ||
1018 | */ | ||
1019 | static void constrain_rate_if_locked(struct snd_pcm_substream *substream) | ||
1020 | { | ||
1021 | struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); | ||
1022 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
1023 | unsigned int rate; | ||
1024 | if (is_pro_rate_locked(ice)) { | ||
1025 | rate = ice->get_rate(ice); | ||
1026 | if (rate >= runtime->hw.rate_min | ||
1027 | && rate <= runtime->hw.rate_max) { | ||
1028 | runtime->hw.rate_min = rate; | ||
1029 | runtime->hw.rate_max = rate; | ||
1030 | } | ||
1031 | } | ||
1032 | } | ||
1033 | |||
1034 | |||
1016 | /* multi-channel playback needs alignment 8x32bit regardless of the channels | 1035 | /* multi-channel playback needs alignment 8x32bit regardless of the channels |
1017 | * actually used | 1036 | * actually used |
1018 | */ | 1037 | */ |
@@ -1046,6 +1065,7 @@ static int snd_vt1724_playback_pro_open(struct snd_pcm_substream *substream) | |||
1046 | VT1724_BUFFER_ALIGN); | 1065 | VT1724_BUFFER_ALIGN); |
1047 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, | 1066 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, |
1048 | VT1724_BUFFER_ALIGN); | 1067 | VT1724_BUFFER_ALIGN); |
1068 | constrain_rate_if_locked(substream); | ||
1049 | if (ice->pro_open) | 1069 | if (ice->pro_open) |
1050 | ice->pro_open(ice, substream); | 1070 | ice->pro_open(ice, substream); |
1051 | return 0; | 1071 | return 0; |
@@ -1066,6 +1086,7 @@ static int snd_vt1724_capture_pro_open(struct snd_pcm_substream *substream) | |||
1066 | VT1724_BUFFER_ALIGN); | 1086 | VT1724_BUFFER_ALIGN); |
1067 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, | 1087 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, |
1068 | VT1724_BUFFER_ALIGN); | 1088 | VT1724_BUFFER_ALIGN); |
1089 | constrain_rate_if_locked(substream); | ||
1069 | if (ice->pro_open) | 1090 | if (ice->pro_open) |
1070 | ice->pro_open(ice, substream); | 1091 | ice->pro_open(ice, substream); |
1071 | return 0; | 1092 | return 0; |
@@ -1215,6 +1236,7 @@ static int snd_vt1724_playback_spdif_open(struct snd_pcm_substream *substream) | |||
1215 | VT1724_BUFFER_ALIGN); | 1236 | VT1724_BUFFER_ALIGN); |
1216 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, | 1237 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, |
1217 | VT1724_BUFFER_ALIGN); | 1238 | VT1724_BUFFER_ALIGN); |
1239 | constrain_rate_if_locked(substream); | ||
1218 | if (ice->spdif.ops.open) | 1240 | if (ice->spdif.ops.open) |
1219 | ice->spdif.ops.open(ice, substream); | 1241 | ice->spdif.ops.open(ice, substream); |
1220 | return 0; | 1242 | return 0; |
@@ -1251,6 +1273,7 @@ static int snd_vt1724_capture_spdif_open(struct snd_pcm_substream *substream) | |||
1251 | VT1724_BUFFER_ALIGN); | 1273 | VT1724_BUFFER_ALIGN); |
1252 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, | 1274 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, |
1253 | VT1724_BUFFER_ALIGN); | 1275 | VT1724_BUFFER_ALIGN); |
1276 | constrain_rate_if_locked(substream); | ||
1254 | if (ice->spdif.ops.open) | 1277 | if (ice->spdif.ops.open) |
1255 | ice->spdif.ops.open(ice, substream); | 1278 | ice->spdif.ops.open(ice, substream); |
1256 | return 0; | 1279 | return 0; |
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 9f3b01bb72c8..e0a4263baa20 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c | |||
@@ -2102,6 +2102,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { | |||
2102 | }, | 2102 | }, |
2103 | { | 2103 | { |
2104 | .subvendor = 0x161f, | 2104 | .subvendor = 0x161f, |
2105 | .subdevice = 0x202f, | ||
2106 | .name = "Gateway M520", | ||
2107 | .type = AC97_TUNE_INV_EAPD | ||
2108 | }, | ||
2109 | { | ||
2110 | .subvendor = 0x161f, | ||
2105 | .subdevice = 0x203a, | 2111 | .subdevice = 0x203a, |
2106 | .name = "Gateway 4525GZ", /* AD1981B */ | 2112 | .name = "Gateway 4525GZ", /* AD1981B */ |
2107 | .type = AC97_TUNE_INV_EAPD | 2113 | .type = AC97_TUNE_INV_EAPD |
diff --git a/sound/pci/oxygen/oxygen_mixer.c b/sound/pci/oxygen/oxygen_mixer.c index 26c7e8bcb229..c0dbb52d45be 100644 --- a/sound/pci/oxygen/oxygen_mixer.c +++ b/sound/pci/oxygen/oxygen_mixer.c | |||
@@ -618,9 +618,12 @@ static int ac97_volume_get(struct snd_kcontrol *ctl, | |||
618 | mutex_lock(&chip->mutex); | 618 | mutex_lock(&chip->mutex); |
619 | reg = oxygen_read_ac97(chip, codec, index); | 619 | reg = oxygen_read_ac97(chip, codec, index); |
620 | mutex_unlock(&chip->mutex); | 620 | mutex_unlock(&chip->mutex); |
621 | value->value.integer.value[0] = 31 - (reg & 0x1f); | 621 | if (!stereo) { |
622 | if (stereo) | 622 | value->value.integer.value[0] = 31 - (reg & 0x1f); |
623 | value->value.integer.value[1] = 31 - ((reg >> 8) & 0x1f); | 623 | } else { |
624 | value->value.integer.value[0] = 31 - ((reg >> 8) & 0x1f); | ||
625 | value->value.integer.value[1] = 31 - (reg & 0x1f); | ||
626 | } | ||
624 | return 0; | 627 | return 0; |
625 | } | 628 | } |
626 | 629 | ||
@@ -636,14 +639,14 @@ static int ac97_volume_put(struct snd_kcontrol *ctl, | |||
636 | 639 | ||
637 | mutex_lock(&chip->mutex); | 640 | mutex_lock(&chip->mutex); |
638 | oldreg = oxygen_read_ac97(chip, codec, index); | 641 | oldreg = oxygen_read_ac97(chip, codec, index); |
639 | newreg = oldreg; | 642 | if (!stereo) { |
640 | newreg = (newreg & ~0x1f) | | 643 | newreg = oldreg & ~0x1f; |
641 | (31 - (value->value.integer.value[0] & 0x1f)); | 644 | newreg |= 31 - (value->value.integer.value[0] & 0x1f); |
642 | if (stereo) | 645 | } else { |
643 | newreg = (newreg & ~0x1f00) | | 646 | newreg = oldreg & ~0x1f1f; |
644 | ((31 - (value->value.integer.value[1] & 0x1f)) << 8); | 647 | newreg |= (31 - (value->value.integer.value[0] & 0x1f)) << 8; |
645 | else | 648 | newreg |= 31 - (value->value.integer.value[1] & 0x1f); |
646 | newreg = (newreg & ~0x1f00) | ((newreg & 0x1f) << 8); | 649 | } |
647 | change = newreg != oldreg; | 650 | change = newreg != oldreg; |
648 | if (change) | 651 | if (change) |
649 | oxygen_write_ac97(chip, codec, index, newreg); | 652 | oxygen_write_ac97(chip, codec, index, newreg); |
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index cc9f6c83d661..bc030a2088da 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c | |||
@@ -6333,6 +6333,7 @@ static int __devinit snd_hdspm_create_hwdep(struct snd_card *card, | |||
6333 | 6333 | ||
6334 | hw->ops.open = snd_hdspm_hwdep_dummy_op; | 6334 | hw->ops.open = snd_hdspm_hwdep_dummy_op; |
6335 | hw->ops.ioctl = snd_hdspm_hwdep_ioctl; | 6335 | hw->ops.ioctl = snd_hdspm_hwdep_ioctl; |
6336 | hw->ops.ioctl_compat = snd_hdspm_hwdep_ioctl; | ||
6336 | hw->ops.release = snd_hdspm_hwdep_dummy_op; | 6337 | hw->ops.release = snd_hdspm_hwdep_dummy_op; |
6337 | 6338 | ||
6338 | return 0; | 6339 | return 0; |
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index 12a9a2b03387..a8159b81e9c4 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c | |||
@@ -2317,6 +2317,10 @@ int snd_ymfpci_suspend(struct pci_dev *pci, pm_message_t state) | |||
2317 | for (i = 0; i < YDSXGR_NUM_SAVED_REGS; i++) | 2317 | for (i = 0; i < YDSXGR_NUM_SAVED_REGS; i++) |
2318 | chip->saved_regs[i] = snd_ymfpci_readl(chip, saved_regs_index[i]); | 2318 | chip->saved_regs[i] = snd_ymfpci_readl(chip, saved_regs_index[i]); |
2319 | chip->saved_ydsxgr_mode = snd_ymfpci_readl(chip, YDSXGR_MODE); | 2319 | chip->saved_ydsxgr_mode = snd_ymfpci_readl(chip, YDSXGR_MODE); |
2320 | pci_read_config_word(chip->pci, PCIR_DSXG_LEGACY, | ||
2321 | &chip->saved_dsxg_legacy); | ||
2322 | pci_read_config_word(chip->pci, PCIR_DSXG_ELEGACY, | ||
2323 | &chip->saved_dsxg_elegacy); | ||
2320 | snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0); | 2324 | snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0); |
2321 | snd_ymfpci_writel(chip, YDSXGR_BUF441OUTVOL, 0); | 2325 | snd_ymfpci_writel(chip, YDSXGR_BUF441OUTVOL, 0); |
2322 | snd_ymfpci_disable_dsp(chip); | 2326 | snd_ymfpci_disable_dsp(chip); |
@@ -2351,6 +2355,11 @@ int snd_ymfpci_resume(struct pci_dev *pci) | |||
2351 | 2355 | ||
2352 | snd_ac97_resume(chip->ac97); | 2356 | snd_ac97_resume(chip->ac97); |
2353 | 2357 | ||
2358 | pci_write_config_word(chip->pci, PCIR_DSXG_LEGACY, | ||
2359 | chip->saved_dsxg_legacy); | ||
2360 | pci_write_config_word(chip->pci, PCIR_DSXG_ELEGACY, | ||
2361 | chip->saved_dsxg_elegacy); | ||
2362 | |||
2354 | /* start hw again */ | 2363 | /* start hw again */ |
2355 | if (chip->start_count > 0) { | 2364 | if (chip->start_count > 0) { |
2356 | spin_lock_irq(&chip->reg_lock); | 2365 | spin_lock_irq(&chip->reg_lock); |