diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/core/jack.c | 9 | ||||
-rw-r--r-- | sound/pci/Kconfig | 124 | ||||
-rw-r--r-- | sound/pci/hda/Kconfig | 139 | ||||
-rw-r--r-- | sound/pci/hda/Makefile | 2 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.c | 534 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 65 | ||||
-rw-r--r-- | sound/pci/hda/hda_eld.c | 590 | ||||
-rw-r--r-- | sound/pci/hda/hda_generic.c | 20 | ||||
-rw-r--r-- | sound/pci/hda/hda_hwdep.c | 232 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.c | 311 | ||||
-rw-r--r-- | sound/pci/hda/hda_local.h | 100 | ||||
-rw-r--r-- | sound/pci/hda/hda_patch.h | 2 | ||||
-rw-r--r-- | sound/pci/hda/hda_proc.c | 73 | ||||
-rw-r--r-- | sound/pci/hda/patch_analog.c | 105 | ||||
-rw-r--r-- | sound/pci/hda/patch_atihdmi.c | 1 | ||||
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 11 | ||||
-rw-r--r-- | sound/pci/hda/patch_intelhdmi.c | 685 | ||||
-rw-r--r-- | sound/pci/hda/patch_nvhdmi.c | 1 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 1602 | ||||
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 512 | ||||
-rw-r--r-- | sound/pci/hda/patch_via.c | 73 |
21 files changed, 3711 insertions, 1480 deletions
diff --git a/sound/core/jack.c b/sound/core/jack.c index 8133a2b173a5..438445f77d6d 100644 --- a/sound/core/jack.c +++ b/sound/core/jack.c | |||
@@ -34,6 +34,7 @@ static int snd_jack_dev_free(struct snd_device *device) | |||
34 | else | 34 | else |
35 | input_free_device(jack->input_dev); | 35 | input_free_device(jack->input_dev); |
36 | 36 | ||
37 | kfree(jack->id); | ||
37 | kfree(jack); | 38 | kfree(jack); |
38 | 39 | ||
39 | return 0; | 40 | return 0; |
@@ -87,7 +88,7 @@ int snd_jack_new(struct snd_card *card, const char *id, int type, | |||
87 | if (jack == NULL) | 88 | if (jack == NULL) |
88 | return -ENOMEM; | 89 | return -ENOMEM; |
89 | 90 | ||
90 | jack->id = id; | 91 | jack->id = kstrdup(id, GFP_KERNEL); |
91 | 92 | ||
92 | jack->input_dev = input_allocate_device(); | 93 | jack->input_dev = input_allocate_device(); |
93 | if (jack->input_dev == NULL) { | 94 | if (jack->input_dev == NULL) { |
@@ -102,6 +103,9 @@ int snd_jack_new(struct snd_card *card, const char *id, int type, | |||
102 | if (type & SND_JACK_HEADPHONE) | 103 | if (type & SND_JACK_HEADPHONE) |
103 | input_set_capability(jack->input_dev, EV_SW, | 104 | input_set_capability(jack->input_dev, EV_SW, |
104 | SW_HEADPHONE_INSERT); | 105 | SW_HEADPHONE_INSERT); |
106 | if (type & SND_JACK_LINEOUT) | ||
107 | input_set_capability(jack->input_dev, EV_SW, | ||
108 | SW_LINEOUT_INSERT); | ||
105 | if (type & SND_JACK_MICROPHONE) | 109 | if (type & SND_JACK_MICROPHONE) |
106 | input_set_capability(jack->input_dev, EV_SW, | 110 | input_set_capability(jack->input_dev, EV_SW, |
107 | SW_MICROPHONE_INSERT); | 111 | SW_MICROPHONE_INSERT); |
@@ -150,6 +154,9 @@ void snd_jack_report(struct snd_jack *jack, int status) | |||
150 | if (jack->type & SND_JACK_HEADPHONE) | 154 | if (jack->type & SND_JACK_HEADPHONE) |
151 | input_report_switch(jack->input_dev, SW_HEADPHONE_INSERT, | 155 | input_report_switch(jack->input_dev, SW_HEADPHONE_INSERT, |
152 | status & SND_JACK_HEADPHONE); | 156 | status & SND_JACK_HEADPHONE); |
157 | if (jack->type & SND_JACK_LINEOUT) | ||
158 | input_report_switch(jack->input_dev, SW_LINEOUT_INSERT, | ||
159 | status & SND_JACK_LINEOUT); | ||
153 | if (jack->type & SND_JACK_MICROPHONE) | 160 | if (jack->type & SND_JACK_MICROPHONE) |
154 | input_report_switch(jack->input_dev, SW_MICROPHONE_INSERT, | 161 | input_report_switch(jack->input_dev, SW_MICROPHONE_INSERT, |
155 | status & SND_JACK_MICROPHONE); | 162 | status & SND_JACK_MICROPHONE); |
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index 7003711f4fcc..caebf296b62b 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig | |||
@@ -497,129 +497,7 @@ config SND_FM801_TEA575X | |||
497 | depends on SND_FM801_TEA575X_BOOL | 497 | depends on SND_FM801_TEA575X_BOOL |
498 | default SND_FM801 | 498 | default SND_FM801 |
499 | 499 | ||
500 | config SND_HDA_INTEL | 500 | source "sound/pci/hda/Kconfig" |
501 | tristate "Intel HD Audio" | ||
502 | select SND_PCM | ||
503 | select SND_VMASTER | ||
504 | help | ||
505 | Say Y here to include support for Intel "High Definition | ||
506 | Audio" (Azalia) motherboard devices. | ||
507 | |||
508 | To compile this driver as a module, choose M here: the module | ||
509 | will be called snd-hda-intel. | ||
510 | |||
511 | config SND_HDA_HWDEP | ||
512 | bool "Build hwdep interface for HD-audio driver" | ||
513 | depends on SND_HDA_INTEL | ||
514 | select SND_HWDEP | ||
515 | help | ||
516 | Say Y here to build a hwdep interface for HD-audio driver. | ||
517 | This interface can be used for out-of-band communication | ||
518 | with codecs for debugging purposes. | ||
519 | |||
520 | config SND_HDA_INPUT_BEEP | ||
521 | bool "Support digital beep via input layer" | ||
522 | depends on SND_HDA_INTEL | ||
523 | depends on INPUT=y || INPUT=SND_HDA_INTEL | ||
524 | help | ||
525 | Say Y here to build a digital beep interface for HD-audio | ||
526 | driver. This interface is used to generate digital beeps. | ||
527 | |||
528 | config SND_HDA_CODEC_REALTEK | ||
529 | bool "Build Realtek HD-audio codec support" | ||
530 | depends on SND_HDA_INTEL | ||
531 | default y | ||
532 | help | ||
533 | Say Y here to include Realtek HD-audio codec support in | ||
534 | snd-hda-intel driver, such as ALC880. | ||
535 | |||
536 | config SND_HDA_CODEC_ANALOG | ||
537 | bool "Build Analog Device HD-audio codec support" | ||
538 | depends on SND_HDA_INTEL | ||
539 | default y | ||
540 | help | ||
541 | Say Y here to include Analog Device HD-audio codec support in | ||
542 | snd-hda-intel driver, such as AD1986A. | ||
543 | |||
544 | config SND_HDA_CODEC_SIGMATEL | ||
545 | bool "Build IDT/Sigmatel HD-audio codec support" | ||
546 | depends on SND_HDA_INTEL | ||
547 | default y | ||
548 | help | ||
549 | Say Y here to include IDT (Sigmatel) HD-audio codec support in | ||
550 | snd-hda-intel driver, such as STAC9200. | ||
551 | |||
552 | config SND_HDA_CODEC_VIA | ||
553 | bool "Build VIA HD-audio codec support" | ||
554 | depends on SND_HDA_INTEL | ||
555 | default y | ||
556 | help | ||
557 | Say Y here to include VIA HD-audio codec support in | ||
558 | snd-hda-intel driver, such as VT1708. | ||
559 | |||
560 | config SND_HDA_CODEC_ATIHDMI | ||
561 | bool "Build ATI HDMI HD-audio codec support" | ||
562 | depends on SND_HDA_INTEL | ||
563 | default y | ||
564 | help | ||
565 | Say Y here to include ATI HDMI HD-audio codec support in | ||
566 | snd-hda-intel driver, such as ATI RS600 HDMI. | ||
567 | |||
568 | config SND_HDA_CODEC_NVHDMI | ||
569 | bool "Build NVIDIA HDMI HD-audio codec support" | ||
570 | depends on SND_HDA_INTEL | ||
571 | default y | ||
572 | help | ||
573 | Say Y here to include NVIDIA HDMI HD-audio codec support in | ||
574 | snd-hda-intel driver, such as NVIDIA MCP78 HDMI. | ||
575 | |||
576 | config SND_HDA_CODEC_CONEXANT | ||
577 | bool "Build Conexant HD-audio codec support" | ||
578 | depends on SND_HDA_INTEL | ||
579 | default y | ||
580 | help | ||
581 | Say Y here to include Conexant HD-audio codec support in | ||
582 | snd-hda-intel driver, such as CX20549. | ||
583 | |||
584 | config SND_HDA_CODEC_CMEDIA | ||
585 | bool "Build C-Media HD-audio codec support" | ||
586 | depends on SND_HDA_INTEL | ||
587 | default y | ||
588 | help | ||
589 | Say Y here to include C-Media HD-audio codec support in | ||
590 | snd-hda-intel driver, such as CMI9880. | ||
591 | |||
592 | config SND_HDA_CODEC_SI3054 | ||
593 | bool "Build Silicon Labs 3054 HD-modem codec support" | ||
594 | depends on SND_HDA_INTEL | ||
595 | default y | ||
596 | help | ||
597 | Say Y here to include Silicon Labs 3054 HD-modem codec | ||
598 | (and compatibles) support in snd-hda-intel driver. | ||
599 | |||
600 | config SND_HDA_GENERIC | ||
601 | bool "Enable generic HD-audio codec parser" | ||
602 | depends on SND_HDA_INTEL | ||
603 | default y | ||
604 | help | ||
605 | Say Y here to enable the generic HD-audio codec parser | ||
606 | in snd-hda-intel driver. | ||
607 | |||
608 | config SND_HDA_POWER_SAVE | ||
609 | bool "Aggressive power-saving on HD-audio" | ||
610 | depends on SND_HDA_INTEL && EXPERIMENTAL | ||
611 | help | ||
612 | Say Y here to enable more aggressive power-saving mode on | ||
613 | HD-audio driver. The power-saving timeout can be configured | ||
614 | via power_save option or over sysfs on-the-fly. | ||
615 | |||
616 | config SND_HDA_POWER_SAVE_DEFAULT | ||
617 | int "Default time-out for HD-audio power-save mode" | ||
618 | depends on SND_HDA_POWER_SAVE | ||
619 | default 0 | ||
620 | help | ||
621 | The default time-out value in seconds for HD-audio automatic | ||
622 | power-save mode. 0 means to disable the power-save mode. | ||
623 | 501 | ||
624 | config SND_HDSP | 502 | config SND_HDSP |
625 | tristate "RME Hammerfall DSP Audio" | 503 | tristate "RME Hammerfall DSP Audio" |
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig new file mode 100644 index 000000000000..7c60f1a45a8d --- /dev/null +++ b/sound/pci/hda/Kconfig | |||
@@ -0,0 +1,139 @@ | |||
1 | menuconfig SND_HDA_INTEL | ||
2 | tristate "Intel HD Audio" | ||
3 | select SND_PCM | ||
4 | select SND_VMASTER | ||
5 | select SND_JACK if INPUT=y || INPUT=SND | ||
6 | help | ||
7 | Say Y here to include support for Intel "High Definition | ||
8 | Audio" (Azalia) and its compatible devices. | ||
9 | |||
10 | This option enables the HD-audio controller. Don't forget | ||
11 | to choose the appropriate codec options below. | ||
12 | |||
13 | To compile this driver as a module, choose M here: the module | ||
14 | will be called snd-hda-intel. | ||
15 | |||
16 | if SND_HDA_INTEL | ||
17 | |||
18 | config SND_HDA_HWDEP | ||
19 | bool "Build hwdep interface for HD-audio driver" | ||
20 | select SND_HWDEP | ||
21 | help | ||
22 | Say Y here to build a hwdep interface for HD-audio driver. | ||
23 | This interface can be used for out-of-band communication | ||
24 | with codecs for debugging purposes. | ||
25 | |||
26 | config SND_HDA_RECONFIG | ||
27 | bool "Allow dynamic codec reconfiguration (EXPERIMENTAL)" | ||
28 | depends on SND_HDA_HWDEP && EXPERIMENTAL | ||
29 | help | ||
30 | Say Y here to enable the HD-audio codec re-configuration feature. | ||
31 | This adds the sysfs interfaces to allow user to clear the whole | ||
32 | codec configuration, change the codec setup, add extra verbs, | ||
33 | and re-configure the codec dynamically. | ||
34 | |||
35 | config SND_HDA_INPUT_BEEP | ||
36 | bool "Support digital beep via input layer" | ||
37 | depends on INPUT=y || INPUT=SND_HDA_INTEL | ||
38 | help | ||
39 | Say Y here to build a digital beep interface for HD-audio | ||
40 | driver. This interface is used to generate digital beeps. | ||
41 | |||
42 | config SND_HDA_CODEC_REALTEK | ||
43 | bool "Build Realtek HD-audio codec support" | ||
44 | default y | ||
45 | help | ||
46 | Say Y here to include Realtek HD-audio codec support in | ||
47 | snd-hda-intel driver, such as ALC880. | ||
48 | |||
49 | config SND_HDA_CODEC_ANALOG | ||
50 | bool "Build Analog Device HD-audio codec support" | ||
51 | default y | ||
52 | help | ||
53 | Say Y here to include Analog Device HD-audio codec support in | ||
54 | snd-hda-intel driver, such as AD1986A. | ||
55 | |||
56 | config SND_HDA_CODEC_SIGMATEL | ||
57 | bool "Build IDT/Sigmatel HD-audio codec support" | ||
58 | default y | ||
59 | help | ||
60 | Say Y here to include IDT (Sigmatel) HD-audio codec support in | ||
61 | snd-hda-intel driver, such as STAC9200. | ||
62 | |||
63 | config SND_HDA_CODEC_VIA | ||
64 | bool "Build VIA HD-audio codec support" | ||
65 | default y | ||
66 | help | ||
67 | Say Y here to include VIA HD-audio codec support in | ||
68 | snd-hda-intel driver, such as VT1708. | ||
69 | |||
70 | config SND_HDA_CODEC_ATIHDMI | ||
71 | bool "Build ATI HDMI HD-audio codec support" | ||
72 | default y | ||
73 | help | ||
74 | Say Y here to include ATI HDMI HD-audio codec support in | ||
75 | snd-hda-intel driver, such as ATI RS600 HDMI. | ||
76 | |||
77 | config SND_HDA_CODEC_NVHDMI | ||
78 | bool "Build NVIDIA HDMI HD-audio codec support" | ||
79 | default y | ||
80 | help | ||
81 | Say Y here to include NVIDIA HDMI HD-audio codec support in | ||
82 | snd-hda-intel driver, such as NVIDIA MCP78 HDMI. | ||
83 | |||
84 | config SND_HDA_CODEC_INTELHDMI | ||
85 | bool "Build INTEL HDMI HD-audio codec support" | ||
86 | default y | ||
87 | help | ||
88 | Say Y here to include INTEL HDMI HD-audio codec support in | ||
89 | snd-hda-intel driver, such as Eaglelake integrated HDMI. | ||
90 | |||
91 | config SND_HDA_ELD | ||
92 | def_bool y | ||
93 | depends on SND_HDA_CODEC_INTELHDMI | ||
94 | |||
95 | config SND_HDA_CODEC_CONEXANT | ||
96 | bool "Build Conexant HD-audio codec support" | ||
97 | default y | ||
98 | help | ||
99 | Say Y here to include Conexant HD-audio codec support in | ||
100 | snd-hda-intel driver, such as CX20549. | ||
101 | |||
102 | config SND_HDA_CODEC_CMEDIA | ||
103 | bool "Build C-Media HD-audio codec support" | ||
104 | default y | ||
105 | help | ||
106 | Say Y here to include C-Media HD-audio codec support in | ||
107 | snd-hda-intel driver, such as CMI9880. | ||
108 | |||
109 | config SND_HDA_CODEC_SI3054 | ||
110 | bool "Build Silicon Labs 3054 HD-modem codec support" | ||
111 | default y | ||
112 | help | ||
113 | Say Y here to include Silicon Labs 3054 HD-modem codec | ||
114 | (and compatibles) support in snd-hda-intel driver. | ||
115 | |||
116 | config SND_HDA_GENERIC | ||
117 | bool "Enable generic HD-audio codec parser" | ||
118 | default y | ||
119 | help | ||
120 | Say Y here to enable the generic HD-audio codec parser | ||
121 | in snd-hda-intel driver. | ||
122 | |||
123 | config SND_HDA_POWER_SAVE | ||
124 | bool "Aggressive power-saving on HD-audio" | ||
125 | depends on EXPERIMENTAL | ||
126 | help | ||
127 | Say Y here to enable more aggressive power-saving mode on | ||
128 | HD-audio driver. The power-saving timeout can be configured | ||
129 | via power_save option or over sysfs on-the-fly. | ||
130 | |||
131 | config SND_HDA_POWER_SAVE_DEFAULT | ||
132 | int "Default time-out for HD-audio power-save mode" | ||
133 | depends on SND_HDA_POWER_SAVE | ||
134 | default 0 | ||
135 | help | ||
136 | The default time-out value in seconds for HD-audio automatic | ||
137 | power-save mode. 0 means to disable the power-save mode. | ||
138 | |||
139 | endif | ||
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile index 1980c6d207e7..6daf5fd9a279 100644 --- a/sound/pci/hda/Makefile +++ b/sound/pci/hda/Makefile | |||
@@ -4,6 +4,7 @@ snd-hda-intel-y := hda_intel.o | |||
4 | # designed to be individual modules | 4 | # designed to be individual modules |
5 | snd-hda-intel-y += hda_codec.o | 5 | snd-hda-intel-y += hda_codec.o |
6 | snd-hda-intel-$(CONFIG_PROC_FS) += hda_proc.o | 6 | snd-hda-intel-$(CONFIG_PROC_FS) += hda_proc.o |
7 | snd-hda-intel-$(CONFIG_SND_HDA_ELD) += hda_eld.o | ||
7 | snd-hda-intel-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o | 8 | snd-hda-intel-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o |
8 | snd-hda-intel-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o | 9 | snd-hda-intel-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o |
9 | snd-hda-intel-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o | 10 | snd-hda-intel-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o |
@@ -16,5 +17,6 @@ snd-hda-intel-$(CONFIG_SND_HDA_CODEC_ATIHDMI) += patch_atihdmi.o | |||
16 | snd-hda-intel-$(CONFIG_SND_HDA_CODEC_CONEXANT) += patch_conexant.o | 17 | snd-hda-intel-$(CONFIG_SND_HDA_CODEC_CONEXANT) += patch_conexant.o |
17 | snd-hda-intel-$(CONFIG_SND_HDA_CODEC_VIA) += patch_via.o | 18 | snd-hda-intel-$(CONFIG_SND_HDA_CODEC_VIA) += patch_via.o |
18 | snd-hda-intel-$(CONFIG_SND_HDA_CODEC_NVHDMI) += patch_nvhdmi.o | 19 | snd-hda-intel-$(CONFIG_SND_HDA_CODEC_NVHDMI) += patch_nvhdmi.o |
20 | snd-hda-intel-$(CONFIG_SND_HDA_CODEC_INTELHDMI) += patch_intelhdmi.o | ||
19 | 21 | ||
20 | obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-intel.o | 22 | obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-intel.o |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index eb9164176dab..53f64eb75ec6 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -98,6 +98,9 @@ static const struct hda_codec_preset *hda_preset_tables[] = { | |||
98 | #ifdef CONFIG_SND_HDA_CODEC_NVHDMI | 98 | #ifdef CONFIG_SND_HDA_CODEC_NVHDMI |
99 | snd_hda_preset_nvhdmi, | 99 | snd_hda_preset_nvhdmi, |
100 | #endif | 100 | #endif |
101 | #ifdef CONFIG_SND_HDA_CODEC_INTELHDMI | ||
102 | snd_hda_preset_intelhdmi, | ||
103 | #endif | ||
101 | NULL | 104 | NULL |
102 | }; | 105 | }; |
103 | 106 | ||
@@ -108,6 +111,69 @@ static void hda_keep_power_on(struct hda_codec *codec); | |||
108 | static inline void hda_keep_power_on(struct hda_codec *codec) {} | 111 | static inline void hda_keep_power_on(struct hda_codec *codec) {} |
109 | #endif | 112 | #endif |
110 | 113 | ||
114 | const char *snd_hda_get_jack_location(u32 cfg) | ||
115 | { | ||
116 | static char *bases[7] = { | ||
117 | "N/A", "Rear", "Front", "Left", "Right", "Top", "Bottom", | ||
118 | }; | ||
119 | static unsigned char specials_idx[] = { | ||
120 | 0x07, 0x08, | ||
121 | 0x17, 0x18, 0x19, | ||
122 | 0x37, 0x38 | ||
123 | }; | ||
124 | static char *specials[] = { | ||
125 | "Rear Panel", "Drive Bar", | ||
126 | "Riser", "HDMI", "ATAPI", | ||
127 | "Mobile-In", "Mobile-Out" | ||
128 | }; | ||
129 | int i; | ||
130 | cfg = (cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT; | ||
131 | if ((cfg & 0x0f) < 7) | ||
132 | return bases[cfg & 0x0f]; | ||
133 | for (i = 0; i < ARRAY_SIZE(specials_idx); i++) { | ||
134 | if (cfg == specials_idx[i]) | ||
135 | return specials[i]; | ||
136 | } | ||
137 | return "UNKNOWN"; | ||
138 | } | ||
139 | |||
140 | const char *snd_hda_get_jack_connectivity(u32 cfg) | ||
141 | { | ||
142 | static char *jack_locations[4] = { "Ext", "Int", "Sep", "Oth" }; | ||
143 | |||
144 | return jack_locations[(cfg >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3]; | ||
145 | } | ||
146 | |||
147 | const char *snd_hda_get_jack_type(u32 cfg) | ||
148 | { | ||
149 | static char *jack_types[16] = { | ||
150 | "Line Out", "Speaker", "HP Out", "CD", | ||
151 | "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand", | ||
152 | "Line In", "Aux", "Mic", "Telephony", | ||
153 | "SPDIF In", "Digitial In", "Reserved", "Other" | ||
154 | }; | ||
155 | |||
156 | return jack_types[(cfg & AC_DEFCFG_DEVICE) | ||
157 | >> AC_DEFCFG_DEVICE_SHIFT]; | ||
158 | } | ||
159 | |||
160 | /* | ||
161 | * Compose a 32bit command word to be sent to the HD-audio controller | ||
162 | */ | ||
163 | static inline unsigned int | ||
164 | make_codec_cmd(struct hda_codec *codec, hda_nid_t nid, int direct, | ||
165 | unsigned int verb, unsigned int parm) | ||
166 | { | ||
167 | u32 val; | ||
168 | |||
169 | val = (u32)(codec->addr & 0x0f) << 28; | ||
170 | val |= (u32)direct << 27; | ||
171 | val |= (u32)nid << 20; | ||
172 | val |= verb << 8; | ||
173 | val |= parm; | ||
174 | return val; | ||
175 | } | ||
176 | |||
111 | /** | 177 | /** |
112 | * snd_hda_codec_read - send a command and get the response | 178 | * snd_hda_codec_read - send a command and get the response |
113 | * @codec: the HDA codec | 179 | * @codec: the HDA codec |
@@ -124,14 +190,17 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, | |||
124 | int direct, | 190 | int direct, |
125 | unsigned int verb, unsigned int parm) | 191 | unsigned int verb, unsigned int parm) |
126 | { | 192 | { |
193 | struct hda_bus *bus = codec->bus; | ||
127 | unsigned int res; | 194 | unsigned int res; |
195 | |||
196 | res = make_codec_cmd(codec, nid, direct, verb, parm); | ||
128 | snd_hda_power_up(codec); | 197 | snd_hda_power_up(codec); |
129 | mutex_lock(&codec->bus->cmd_mutex); | 198 | mutex_lock(&bus->cmd_mutex); |
130 | if (!codec->bus->ops.command(codec, nid, direct, verb, parm)) | 199 | if (!bus->ops.command(bus, res)) |
131 | res = codec->bus->ops.get_response(codec); | 200 | res = bus->ops.get_response(bus); |
132 | else | 201 | else |
133 | res = (unsigned int)-1; | 202 | res = (unsigned int)-1; |
134 | mutex_unlock(&codec->bus->cmd_mutex); | 203 | mutex_unlock(&bus->cmd_mutex); |
135 | snd_hda_power_down(codec); | 204 | snd_hda_power_down(codec); |
136 | return res; | 205 | return res; |
137 | } | 206 | } |
@@ -151,11 +220,15 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, | |||
151 | int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct, | 220 | int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct, |
152 | unsigned int verb, unsigned int parm) | 221 | unsigned int verb, unsigned int parm) |
153 | { | 222 | { |
223 | struct hda_bus *bus = codec->bus; | ||
224 | unsigned int res; | ||
154 | int err; | 225 | int err; |
226 | |||
227 | res = make_codec_cmd(codec, nid, direct, verb, parm); | ||
155 | snd_hda_power_up(codec); | 228 | snd_hda_power_up(codec); |
156 | mutex_lock(&codec->bus->cmd_mutex); | 229 | mutex_lock(&bus->cmd_mutex); |
157 | err = codec->bus->ops.command(codec, nid, direct, verb, parm); | 230 | err = bus->ops.command(bus, res); |
158 | mutex_unlock(&codec->bus->cmd_mutex); | 231 | mutex_unlock(&bus->cmd_mutex); |
159 | snd_hda_power_down(codec); | 232 | snd_hda_power_down(codec); |
160 | return err; | 233 | return err; |
161 | } | 234 | } |
@@ -345,7 +418,7 @@ static void process_unsol_events(struct work_struct *work) | |||
345 | /* | 418 | /* |
346 | * initialize unsolicited queue | 419 | * initialize unsolicited queue |
347 | */ | 420 | */ |
348 | static int __devinit init_unsol_queue(struct hda_bus *bus) | 421 | static int init_unsol_queue(struct hda_bus *bus) |
349 | { | 422 | { |
350 | struct hda_bus_unsolicited *unsol; | 423 | struct hda_bus_unsolicited *unsol; |
351 | 424 | ||
@@ -391,9 +464,24 @@ static int snd_hda_bus_free(struct hda_bus *bus) | |||
391 | static int snd_hda_bus_dev_free(struct snd_device *device) | 464 | static int snd_hda_bus_dev_free(struct snd_device *device) |
392 | { | 465 | { |
393 | struct hda_bus *bus = device->device_data; | 466 | struct hda_bus *bus = device->device_data; |
467 | bus->shutdown = 1; | ||
394 | return snd_hda_bus_free(bus); | 468 | return snd_hda_bus_free(bus); |
395 | } | 469 | } |
396 | 470 | ||
471 | #ifdef CONFIG_SND_HDA_HWDEP | ||
472 | static int snd_hda_bus_dev_register(struct snd_device *device) | ||
473 | { | ||
474 | struct hda_bus *bus = device->device_data; | ||
475 | struct hda_codec *codec; | ||
476 | list_for_each_entry(codec, &bus->codec_list, list) { | ||
477 | snd_hda_hwdep_add_sysfs(codec); | ||
478 | } | ||
479 | return 0; | ||
480 | } | ||
481 | #else | ||
482 | #define snd_hda_bus_dev_register NULL | ||
483 | #endif | ||
484 | |||
397 | /** | 485 | /** |
398 | * snd_hda_bus_new - create a HDA bus | 486 | * snd_hda_bus_new - create a HDA bus |
399 | * @card: the card entry | 487 | * @card: the card entry |
@@ -409,6 +497,7 @@ int __devinit snd_hda_bus_new(struct snd_card *card, | |||
409 | struct hda_bus *bus; | 497 | struct hda_bus *bus; |
410 | int err; | 498 | int err; |
411 | static struct snd_device_ops dev_ops = { | 499 | static struct snd_device_ops dev_ops = { |
500 | .dev_register = snd_hda_bus_dev_register, | ||
412 | .dev_free = snd_hda_bus_dev_free, | 501 | .dev_free = snd_hda_bus_dev_free, |
413 | }; | 502 | }; |
414 | 503 | ||
@@ -447,7 +536,7 @@ int __devinit snd_hda_bus_new(struct snd_card *card, | |||
447 | 536 | ||
448 | #ifdef CONFIG_SND_HDA_GENERIC | 537 | #ifdef CONFIG_SND_HDA_GENERIC |
449 | #define is_generic_config(codec) \ | 538 | #define is_generic_config(codec) \ |
450 | (codec->bus->modelname && !strcmp(codec->bus->modelname, "generic")) | 539 | (codec->modelname && !strcmp(codec->modelname, "generic")) |
451 | #else | 540 | #else |
452 | #define is_generic_config(codec) 0 | 541 | #define is_generic_config(codec) 0 |
453 | #endif | 542 | #endif |
@@ -455,7 +544,7 @@ int __devinit snd_hda_bus_new(struct snd_card *card, | |||
455 | /* | 544 | /* |
456 | * find a matching codec preset | 545 | * find a matching codec preset |
457 | */ | 546 | */ |
458 | static const struct hda_codec_preset __devinit * | 547 | static const struct hda_codec_preset * |
459 | find_codec_preset(struct hda_codec *codec) | 548 | find_codec_preset(struct hda_codec *codec) |
460 | { | 549 | { |
461 | const struct hda_codec_preset **tbl, *preset; | 550 | const struct hda_codec_preset **tbl, *preset; |
@@ -482,15 +571,14 @@ find_codec_preset(struct hda_codec *codec) | |||
482 | } | 571 | } |
483 | 572 | ||
484 | /* | 573 | /* |
485 | * snd_hda_get_codec_name - store the codec name | 574 | * get_codec_name - store the codec name |
486 | */ | 575 | */ |
487 | void snd_hda_get_codec_name(struct hda_codec *codec, | 576 | static int get_codec_name(struct hda_codec *codec) |
488 | char *name, int namelen) | ||
489 | { | 577 | { |
490 | const struct hda_vendor_id *c; | 578 | const struct hda_vendor_id *c; |
491 | const char *vendor = NULL; | 579 | const char *vendor = NULL; |
492 | u16 vendor_id = codec->vendor_id >> 16; | 580 | u16 vendor_id = codec->vendor_id >> 16; |
493 | char tmp[16]; | 581 | char tmp[16], name[32]; |
494 | 582 | ||
495 | for (c = hda_vendor_ids; c->id; c++) { | 583 | for (c = hda_vendor_ids; c->id; c++) { |
496 | if (c->id == vendor_id) { | 584 | if (c->id == vendor_id) { |
@@ -503,10 +591,15 @@ void snd_hda_get_codec_name(struct hda_codec *codec, | |||
503 | vendor = tmp; | 591 | vendor = tmp; |
504 | } | 592 | } |
505 | if (codec->preset && codec->preset->name) | 593 | if (codec->preset && codec->preset->name) |
506 | snprintf(name, namelen, "%s %s", vendor, codec->preset->name); | 594 | snprintf(name, sizeof(name), "%s %s", vendor, |
595 | codec->preset->name); | ||
507 | else | 596 | else |
508 | snprintf(name, namelen, "%s ID %x", vendor, | 597 | snprintf(name, sizeof(name), "%s ID %x", vendor, |
509 | codec->vendor_id & 0xffff); | 598 | codec->vendor_id & 0xffff); |
599 | codec->name = kstrdup(name, GFP_KERNEL); | ||
600 | if (!codec->name) | ||
601 | return -ENOMEM; | ||
602 | return 0; | ||
510 | } | 603 | } |
511 | 604 | ||
512 | /* | 605 | /* |
@@ -571,11 +664,14 @@ static void snd_hda_codec_free(struct hda_codec *codec) | |||
571 | flush_scheduled_work(); | 664 | flush_scheduled_work(); |
572 | #endif | 665 | #endif |
573 | list_del(&codec->list); | 666 | list_del(&codec->list); |
667 | snd_array_free(&codec->mixers); | ||
574 | codec->bus->caddr_tbl[codec->addr] = NULL; | 668 | codec->bus->caddr_tbl[codec->addr] = NULL; |
575 | if (codec->patch_ops.free) | 669 | if (codec->patch_ops.free) |
576 | codec->patch_ops.free(codec); | 670 | codec->patch_ops.free(codec); |
577 | free_hda_cache(&codec->amp_cache); | 671 | free_hda_cache(&codec->amp_cache); |
578 | free_hda_cache(&codec->cmd_cache); | 672 | free_hda_cache(&codec->cmd_cache); |
673 | kfree(codec->name); | ||
674 | kfree(codec->modelname); | ||
579 | kfree(codec->wcaps); | 675 | kfree(codec->wcaps); |
580 | kfree(codec); | 676 | kfree(codec); |
581 | } | 677 | } |
@@ -617,6 +713,14 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, | |||
617 | mutex_init(&codec->spdif_mutex); | 713 | mutex_init(&codec->spdif_mutex); |
618 | init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); | 714 | init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); |
619 | init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); | 715 | init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); |
716 | snd_array_init(&codec->mixers, sizeof(struct snd_kcontrol *), 32); | ||
717 | if (codec->bus->modelname) { | ||
718 | codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL); | ||
719 | if (!codec->modelname) { | ||
720 | snd_hda_codec_free(codec); | ||
721 | return -ENODEV; | ||
722 | } | ||
723 | } | ||
620 | 724 | ||
621 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 725 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
622 | INIT_DELAYED_WORK(&codec->power_work, hda_power_work); | 726 | INIT_DELAYED_WORK(&codec->power_work, hda_power_work); |
@@ -662,12 +766,41 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, | |||
662 | snd_hda_codec_read(codec, nid, 0, | 766 | snd_hda_codec_read(codec, nid, 0, |
663 | AC_VERB_GET_SUBSYSTEM_ID, 0); | 767 | AC_VERB_GET_SUBSYSTEM_ID, 0); |
664 | } | 768 | } |
769 | if (bus->modelname) | ||
770 | codec->modelname = kstrdup(bus->modelname, GFP_KERNEL); | ||
771 | |||
772 | err = snd_hda_codec_configure(codec); | ||
773 | if (err < 0) { | ||
774 | snd_hda_codec_free(codec); | ||
775 | return err; | ||
776 | } | ||
777 | snd_hda_codec_proc_new(codec); | ||
778 | |||
779 | snd_hda_create_hwdep(codec); | ||
780 | |||
781 | sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id, | ||
782 | codec->subsystem_id, codec->revision_id); | ||
783 | snd_component_add(codec->bus->card, component); | ||
784 | |||
785 | if (codecp) | ||
786 | *codecp = codec; | ||
787 | return 0; | ||
788 | } | ||
789 | |||
790 | int snd_hda_codec_configure(struct hda_codec *codec) | ||
791 | { | ||
792 | int err; | ||
665 | 793 | ||
666 | codec->preset = find_codec_preset(codec); | 794 | codec->preset = find_codec_preset(codec); |
795 | if (!codec->name) { | ||
796 | err = get_codec_name(codec); | ||
797 | if (err < 0) | ||
798 | return err; | ||
799 | } | ||
667 | /* audio codec should override the mixer name */ | 800 | /* audio codec should override the mixer name */ |
668 | if (codec->afg || !*bus->card->mixername) | 801 | if (codec->afg || !*codec->bus->card->mixername) |
669 | snd_hda_get_codec_name(codec, bus->card->mixername, | 802 | strlcpy(codec->bus->card->mixername, codec->name, |
670 | sizeof(bus->card->mixername)); | 803 | sizeof(codec->bus->card->mixername)); |
671 | 804 | ||
672 | if (is_generic_config(codec)) { | 805 | if (is_generic_config(codec)) { |
673 | err = snd_hda_parse_generic_codec(codec); | 806 | err = snd_hda_parse_generic_codec(codec); |
@@ -684,25 +817,9 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, | |||
684 | printk(KERN_ERR "hda-codec: No codec parser is available\n"); | 817 | printk(KERN_ERR "hda-codec: No codec parser is available\n"); |
685 | 818 | ||
686 | patched: | 819 | patched: |
687 | if (err < 0) { | 820 | if (!err && codec->patch_ops.unsol_event) |
688 | snd_hda_codec_free(codec); | 821 | err = init_unsol_queue(codec->bus); |
689 | return err; | 822 | return err; |
690 | } | ||
691 | |||
692 | if (codec->patch_ops.unsol_event) | ||
693 | init_unsol_queue(bus); | ||
694 | |||
695 | snd_hda_codec_proc_new(codec); | ||
696 | #ifdef CONFIG_SND_HDA_HWDEP | ||
697 | snd_hda_create_hwdep(codec); | ||
698 | #endif | ||
699 | |||
700 | sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id, codec->subsystem_id, codec->revision_id); | ||
701 | snd_component_add(codec->bus->card, component); | ||
702 | |||
703 | if (codecp) | ||
704 | *codecp = codec; | ||
705 | return 0; | ||
706 | } | 823 | } |
707 | 824 | ||
708 | /** | 825 | /** |
@@ -757,12 +874,12 @@ static void __devinit init_hda_cache(struct hda_cache_rec *cache, | |||
757 | { | 874 | { |
758 | memset(cache, 0, sizeof(*cache)); | 875 | memset(cache, 0, sizeof(*cache)); |
759 | memset(cache->hash, 0xff, sizeof(cache->hash)); | 876 | memset(cache->hash, 0xff, sizeof(cache->hash)); |
760 | cache->record_size = record_size; | 877 | snd_array_init(&cache->buf, record_size, 64); |
761 | } | 878 | } |
762 | 879 | ||
763 | static void free_hda_cache(struct hda_cache_rec *cache) | 880 | static void free_hda_cache(struct hda_cache_rec *cache) |
764 | { | 881 | { |
765 | kfree(cache->buffer); | 882 | snd_array_free(&cache->buf); |
766 | } | 883 | } |
767 | 884 | ||
768 | /* query the hash. allocate an entry if not found. */ | 885 | /* query the hash. allocate an entry if not found. */ |
@@ -774,35 +891,17 @@ static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache, | |||
774 | struct hda_cache_head *info; | 891 | struct hda_cache_head *info; |
775 | 892 | ||
776 | while (cur != 0xffff) { | 893 | while (cur != 0xffff) { |
777 | info = (struct hda_cache_head *)(cache->buffer + | 894 | info = snd_array_elem(&cache->buf, cur); |
778 | cur * cache->record_size); | ||
779 | if (info->key == key) | 895 | if (info->key == key) |
780 | return info; | 896 | return info; |
781 | cur = info->next; | 897 | cur = info->next; |
782 | } | 898 | } |
783 | 899 | ||
784 | /* add a new hash entry */ | 900 | /* add a new hash entry */ |
785 | if (cache->num_entries >= cache->size) { | 901 | info = snd_array_new(&cache->buf); |
786 | /* reallocate the array */ | 902 | if (!info) |
787 | unsigned int new_size = cache->size + 64; | 903 | return NULL; |
788 | void *new_buffer; | 904 | cur = snd_array_index(&cache->buf, info); |
789 | new_buffer = kcalloc(new_size, cache->record_size, GFP_KERNEL); | ||
790 | if (!new_buffer) { | ||
791 | snd_printk(KERN_ERR "hda_codec: " | ||
792 | "can't malloc amp_info\n"); | ||
793 | return NULL; | ||
794 | } | ||
795 | if (cache->buffer) { | ||
796 | memcpy(new_buffer, cache->buffer, | ||
797 | cache->size * cache->record_size); | ||
798 | kfree(cache->buffer); | ||
799 | } | ||
800 | cache->size = new_size; | ||
801 | cache->buffer = new_buffer; | ||
802 | } | ||
803 | cur = cache->num_entries++; | ||
804 | info = (struct hda_cache_head *)(cache->buffer + | ||
805 | cur * cache->record_size); | ||
806 | info->key = key; | 905 | info->key = key; |
807 | info->val = 0; | 906 | info->val = 0; |
808 | info->next = cache->hash[idx]; | 907 | info->next = cache->hash[idx]; |
@@ -943,10 +1042,10 @@ int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid, | |||
943 | /* resume the all amp commands from the cache */ | 1042 | /* resume the all amp commands from the cache */ |
944 | void snd_hda_codec_resume_amp(struct hda_codec *codec) | 1043 | void snd_hda_codec_resume_amp(struct hda_codec *codec) |
945 | { | 1044 | { |
946 | struct hda_amp_info *buffer = codec->amp_cache.buffer; | 1045 | struct hda_amp_info *buffer = codec->amp_cache.buf.list; |
947 | int i; | 1046 | int i; |
948 | 1047 | ||
949 | for (i = 0; i < codec->amp_cache.size; i++, buffer++) { | 1048 | for (i = 0; i < codec->amp_cache.buf.used; i++, buffer++) { |
950 | u32 key = buffer->head.key; | 1049 | u32 key = buffer->head.key; |
951 | hda_nid_t nid; | 1050 | hda_nid_t nid; |
952 | unsigned int idx, dir, ch; | 1051 | unsigned int idx, dir, ch; |
@@ -1098,6 +1197,57 @@ struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, | |||
1098 | return _snd_hda_find_mixer_ctl(codec, name, 0); | 1197 | return _snd_hda_find_mixer_ctl(codec, name, 0); |
1099 | } | 1198 | } |
1100 | 1199 | ||
1200 | /* Add a control element and assign to the codec */ | ||
1201 | int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl) | ||
1202 | { | ||
1203 | int err; | ||
1204 | struct snd_kcontrol **knewp; | ||
1205 | |||
1206 | err = snd_ctl_add(codec->bus->card, kctl); | ||
1207 | if (err < 0) | ||
1208 | return err; | ||
1209 | knewp = snd_array_new(&codec->mixers); | ||
1210 | if (!knewp) | ||
1211 | return -ENOMEM; | ||
1212 | *knewp = kctl; | ||
1213 | return 0; | ||
1214 | } | ||
1215 | |||
1216 | /* Clear all controls assigned to the given codec */ | ||
1217 | void snd_hda_ctls_clear(struct hda_codec *codec) | ||
1218 | { | ||
1219 | int i; | ||
1220 | struct snd_kcontrol **kctls = codec->mixers.list; | ||
1221 | for (i = 0; i < codec->mixers.used; i++) | ||
1222 | snd_ctl_remove(codec->bus->card, kctls[i]); | ||
1223 | snd_array_free(&codec->mixers); | ||
1224 | } | ||
1225 | |||
1226 | void snd_hda_codec_reset(struct hda_codec *codec) | ||
1227 | { | ||
1228 | int i; | ||
1229 | |||
1230 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1231 | cancel_delayed_work(&codec->power_work); | ||
1232 | flush_scheduled_work(); | ||
1233 | #endif | ||
1234 | snd_hda_ctls_clear(codec); | ||
1235 | /* relase PCMs */ | ||
1236 | for (i = 0; i < codec->num_pcms; i++) { | ||
1237 | if (codec->pcm_info[i].pcm) | ||
1238 | snd_device_free(codec->bus->card, | ||
1239 | codec->pcm_info[i].pcm); | ||
1240 | } | ||
1241 | if (codec->patch_ops.free) | ||
1242 | codec->patch_ops.free(codec); | ||
1243 | codec->spec = NULL; | ||
1244 | free_hda_cache(&codec->amp_cache); | ||
1245 | free_hda_cache(&codec->cmd_cache); | ||
1246 | codec->num_pcms = 0; | ||
1247 | codec->pcm_info = NULL; | ||
1248 | codec->preset = NULL; | ||
1249 | } | ||
1250 | |||
1101 | /* create a virtual master control and add slaves */ | 1251 | /* create a virtual master control and add slaves */ |
1102 | int snd_hda_add_vmaster(struct hda_codec *codec, char *name, | 1252 | int snd_hda_add_vmaster(struct hda_codec *codec, char *name, |
1103 | unsigned int *tlv, const char **slaves) | 1253 | unsigned int *tlv, const char **slaves) |
@@ -1115,7 +1265,7 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name, | |||
1115 | kctl = snd_ctl_make_virtual_master(name, tlv); | 1265 | kctl = snd_ctl_make_virtual_master(name, tlv); |
1116 | if (!kctl) | 1266 | if (!kctl) |
1117 | return -ENOMEM; | 1267 | return -ENOMEM; |
1118 | err = snd_ctl_add(codec->bus->card, kctl); | 1268 | err = snd_hda_ctl_add(codec, kctl); |
1119 | if (err < 0) | 1269 | if (err < 0) |
1120 | return err; | 1270 | return err; |
1121 | 1271 | ||
@@ -1577,9 +1727,11 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid) | |||
1577 | } | 1727 | } |
1578 | for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) { | 1728 | for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) { |
1579 | kctl = snd_ctl_new1(dig_mix, codec); | 1729 | kctl = snd_ctl_new1(dig_mix, codec); |
1730 | if (!kctl) | ||
1731 | return -ENOMEM; | ||
1580 | kctl->id.index = idx; | 1732 | kctl->id.index = idx; |
1581 | kctl->private_value = nid; | 1733 | kctl->private_value = nid; |
1582 | err = snd_ctl_add(codec->bus->card, kctl); | 1734 | err = snd_hda_ctl_add(codec, kctl); |
1583 | if (err < 0) | 1735 | if (err < 0) |
1584 | return err; | 1736 | return err; |
1585 | } | 1737 | } |
@@ -1623,7 +1775,7 @@ int snd_hda_create_spdif_share_sw(struct hda_codec *codec, | |||
1623 | if (!mout->dig_out_nid) | 1775 | if (!mout->dig_out_nid) |
1624 | return 0; | 1776 | return 0; |
1625 | /* ATTENTION: here mout is passed as private_data, instead of codec */ | 1777 | /* ATTENTION: here mout is passed as private_data, instead of codec */ |
1626 | return snd_ctl_add(codec->bus->card, | 1778 | return snd_hda_ctl_add(codec, |
1627 | snd_ctl_new1(&spdif_share_sw, mout)); | 1779 | snd_ctl_new1(&spdif_share_sw, mout)); |
1628 | } | 1780 | } |
1629 | 1781 | ||
@@ -1725,7 +1877,7 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid) | |||
1725 | for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) { | 1877 | for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) { |
1726 | kctl = snd_ctl_new1(dig_mix, codec); | 1878 | kctl = snd_ctl_new1(dig_mix, codec); |
1727 | kctl->private_value = nid; | 1879 | kctl->private_value = nid; |
1728 | err = snd_ctl_add(codec->bus->card, kctl); | 1880 | err = snd_hda_ctl_add(codec, kctl); |
1729 | if (err < 0) | 1881 | if (err < 0) |
1730 | return err; | 1882 | return err; |
1731 | } | 1883 | } |
@@ -1761,10 +1913,14 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid) | |||
1761 | int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, | 1913 | int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, |
1762 | int direct, unsigned int verb, unsigned int parm) | 1914 | int direct, unsigned int verb, unsigned int parm) |
1763 | { | 1915 | { |
1916 | struct hda_bus *bus = codec->bus; | ||
1917 | unsigned int res; | ||
1764 | int err; | 1918 | int err; |
1919 | |||
1920 | res = make_codec_cmd(codec, nid, direct, verb, parm); | ||
1765 | snd_hda_power_up(codec); | 1921 | snd_hda_power_up(codec); |
1766 | mutex_lock(&codec->bus->cmd_mutex); | 1922 | mutex_lock(&bus->cmd_mutex); |
1767 | err = codec->bus->ops.command(codec, nid, direct, verb, parm); | 1923 | err = bus->ops.command(bus, res); |
1768 | if (!err) { | 1924 | if (!err) { |
1769 | struct hda_cache_head *c; | 1925 | struct hda_cache_head *c; |
1770 | u32 key = build_cmd_cache_key(nid, verb); | 1926 | u32 key = build_cmd_cache_key(nid, verb); |
@@ -1772,7 +1928,7 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, | |||
1772 | if (c) | 1928 | if (c) |
1773 | c->val = parm; | 1929 | c->val = parm; |
1774 | } | 1930 | } |
1775 | mutex_unlock(&codec->bus->cmd_mutex); | 1931 | mutex_unlock(&bus->cmd_mutex); |
1776 | snd_hda_power_down(codec); | 1932 | snd_hda_power_down(codec); |
1777 | return err; | 1933 | return err; |
1778 | } | 1934 | } |
@@ -1780,10 +1936,10 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, | |||
1780 | /* resume the all commands from the cache */ | 1936 | /* resume the all commands from the cache */ |
1781 | void snd_hda_codec_resume_cache(struct hda_codec *codec) | 1937 | void snd_hda_codec_resume_cache(struct hda_codec *codec) |
1782 | { | 1938 | { |
1783 | struct hda_cache_head *buffer = codec->cmd_cache.buffer; | 1939 | struct hda_cache_head *buffer = codec->cmd_cache.buf.list; |
1784 | int i; | 1940 | int i; |
1785 | 1941 | ||
1786 | for (i = 0; i < codec->cmd_cache.size; i++, buffer++) { | 1942 | for (i = 0; i < codec->cmd_cache.buf.used; i++, buffer++) { |
1787 | u32 key = buffer->key; | 1943 | u32 key = buffer->key; |
1788 | if (!key) | 1944 | if (!key) |
1789 | continue; | 1945 | continue; |
@@ -1868,6 +2024,17 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, | |||
1868 | } | 2024 | } |
1869 | } | 2025 | } |
1870 | 2026 | ||
2027 | #ifdef CONFIG_SND_HDA_HWDEP | ||
2028 | /* execute additional init verbs */ | ||
2029 | static void hda_exec_init_verbs(struct hda_codec *codec) | ||
2030 | { | ||
2031 | if (codec->init_verbs.list) | ||
2032 | snd_hda_sequence_write(codec, codec->init_verbs.list); | ||
2033 | } | ||
2034 | #else | ||
2035 | static inline void hda_exec_init_verbs(struct hda_codec *codec) {} | ||
2036 | #endif | ||
2037 | |||
1871 | #ifdef SND_HDA_NEEDS_RESUME | 2038 | #ifdef SND_HDA_NEEDS_RESUME |
1872 | /* | 2039 | /* |
1873 | * call suspend and power-down; used both from PM and power-save | 2040 | * call suspend and power-down; used both from PM and power-save |
@@ -1894,6 +2061,7 @@ static void hda_call_codec_resume(struct hda_codec *codec) | |||
1894 | hda_set_power_state(codec, | 2061 | hda_set_power_state(codec, |
1895 | codec->afg ? codec->afg : codec->mfg, | 2062 | codec->afg ? codec->afg : codec->mfg, |
1896 | AC_PWRST_D0); | 2063 | AC_PWRST_D0); |
2064 | hda_exec_init_verbs(codec); | ||
1897 | if (codec->patch_ops.resume) | 2065 | if (codec->patch_ops.resume) |
1898 | codec->patch_ops.resume(codec); | 2066 | codec->patch_ops.resume(codec); |
1899 | else { | 2067 | else { |
@@ -1919,23 +2087,31 @@ int __devinit snd_hda_build_controls(struct hda_bus *bus) | |||
1919 | struct hda_codec *codec; | 2087 | struct hda_codec *codec; |
1920 | 2088 | ||
1921 | list_for_each_entry(codec, &bus->codec_list, list) { | 2089 | list_for_each_entry(codec, &bus->codec_list, list) { |
1922 | int err = 0; | 2090 | int err = snd_hda_codec_build_controls(codec); |
1923 | /* fake as if already powered-on */ | ||
1924 | hda_keep_power_on(codec); | ||
1925 | /* then fire up */ | ||
1926 | hda_set_power_state(codec, | ||
1927 | codec->afg ? codec->afg : codec->mfg, | ||
1928 | AC_PWRST_D0); | ||
1929 | /* continue to initialize... */ | ||
1930 | if (codec->patch_ops.init) | ||
1931 | err = codec->patch_ops.init(codec); | ||
1932 | if (!err && codec->patch_ops.build_controls) | ||
1933 | err = codec->patch_ops.build_controls(codec); | ||
1934 | snd_hda_power_down(codec); | ||
1935 | if (err < 0) | 2091 | if (err < 0) |
1936 | return err; | 2092 | return err; |
1937 | } | 2093 | } |
2094 | return 0; | ||
2095 | } | ||
1938 | 2096 | ||
2097 | int snd_hda_codec_build_controls(struct hda_codec *codec) | ||
2098 | { | ||
2099 | int err = 0; | ||
2100 | /* fake as if already powered-on */ | ||
2101 | hda_keep_power_on(codec); | ||
2102 | /* then fire up */ | ||
2103 | hda_set_power_state(codec, | ||
2104 | codec->afg ? codec->afg : codec->mfg, | ||
2105 | AC_PWRST_D0); | ||
2106 | hda_exec_init_verbs(codec); | ||
2107 | /* continue to initialize... */ | ||
2108 | if (codec->patch_ops.init) | ||
2109 | err = codec->patch_ops.init(codec); | ||
2110 | if (!err && codec->patch_ops.build_controls) | ||
2111 | err = codec->patch_ops.build_controls(codec); | ||
2112 | snd_hda_power_down(codec); | ||
2113 | if (err < 0) | ||
2114 | return err; | ||
1939 | return 0; | 2115 | return 0; |
1940 | } | 2116 | } |
1941 | 2117 | ||
@@ -2236,8 +2412,8 @@ static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo, | |||
2236 | return 0; | 2412 | return 0; |
2237 | } | 2413 | } |
2238 | 2414 | ||
2239 | static int __devinit set_pcm_default_values(struct hda_codec *codec, | 2415 | static int set_pcm_default_values(struct hda_codec *codec, |
2240 | struct hda_pcm_stream *info) | 2416 | struct hda_pcm_stream *info) |
2241 | { | 2417 | { |
2242 | /* query support PCM information from the given NID */ | 2418 | /* query support PCM information from the given NID */ |
2243 | if (info->nid && (!info->rates || !info->formats)) { | 2419 | if (info->nid && (!info->rates || !info->formats)) { |
@@ -2263,6 +2439,29 @@ static int __devinit set_pcm_default_values(struct hda_codec *codec, | |||
2263 | return 0; | 2439 | return 0; |
2264 | } | 2440 | } |
2265 | 2441 | ||
2442 | /* | ||
2443 | * attach a new PCM stream | ||
2444 | */ | ||
2445 | static int __devinit | ||
2446 | snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm) | ||
2447 | { | ||
2448 | struct hda_bus *bus = codec->bus; | ||
2449 | struct hda_pcm_stream *info; | ||
2450 | int stream, err; | ||
2451 | |||
2452 | if (snd_BUG_ON(!pcm->name)) | ||
2453 | return -EINVAL; | ||
2454 | for (stream = 0; stream < 2; stream++) { | ||
2455 | info = &pcm->stream[stream]; | ||
2456 | if (info->substreams) { | ||
2457 | err = set_pcm_default_values(codec, info); | ||
2458 | if (err < 0) | ||
2459 | return err; | ||
2460 | } | ||
2461 | } | ||
2462 | return bus->ops.attach_pcm(bus, codec, pcm); | ||
2463 | } | ||
2464 | |||
2266 | /** | 2465 | /** |
2267 | * snd_hda_build_pcms - build PCM information | 2466 | * snd_hda_build_pcms - build PCM information |
2268 | * @bus: the BUS | 2467 | * @bus: the BUS |
@@ -2289,25 +2488,72 @@ static int __devinit set_pcm_default_values(struct hda_codec *codec, | |||
2289 | * | 2488 | * |
2290 | * This function returns 0 if successfull, or a negative error code. | 2489 | * This function returns 0 if successfull, or a negative error code. |
2291 | */ | 2490 | */ |
2292 | int __devinit snd_hda_build_pcms(struct hda_bus *bus) | 2491 | int snd_hda_build_pcms(struct hda_bus *bus) |
2293 | { | 2492 | { |
2493 | static const char *dev_name[HDA_PCM_NTYPES] = { | ||
2494 | "Audio", "SPDIF", "HDMI", "Modem" | ||
2495 | }; | ||
2496 | /* starting device index for each PCM type */ | ||
2497 | static int dev_idx[HDA_PCM_NTYPES] = { | ||
2498 | [HDA_PCM_TYPE_AUDIO] = 0, | ||
2499 | [HDA_PCM_TYPE_SPDIF] = 1, | ||
2500 | [HDA_PCM_TYPE_HDMI] = 3, | ||
2501 | [HDA_PCM_TYPE_MODEM] = 6 | ||
2502 | }; | ||
2503 | /* normal audio device indices; not linear to keep compatibility */ | ||
2504 | static int audio_idx[4] = { 0, 2, 4, 5 }; | ||
2294 | struct hda_codec *codec; | 2505 | struct hda_codec *codec; |
2506 | int num_devs[HDA_PCM_NTYPES]; | ||
2295 | 2507 | ||
2508 | memset(num_devs, 0, sizeof(num_devs)); | ||
2296 | list_for_each_entry(codec, &bus->codec_list, list) { | 2509 | list_for_each_entry(codec, &bus->codec_list, list) { |
2297 | unsigned int pcm, s; | 2510 | unsigned int pcm; |
2298 | int err; | 2511 | int err; |
2299 | if (!codec->patch_ops.build_pcms) | 2512 | if (!codec->num_pcms) { |
2300 | continue; | 2513 | if (!codec->patch_ops.build_pcms) |
2301 | err = codec->patch_ops.build_pcms(codec); | 2514 | continue; |
2302 | if (err < 0) | 2515 | err = codec->patch_ops.build_pcms(codec); |
2303 | return err; | 2516 | if (err < 0) |
2517 | return err; | ||
2518 | } | ||
2304 | for (pcm = 0; pcm < codec->num_pcms; pcm++) { | 2519 | for (pcm = 0; pcm < codec->num_pcms; pcm++) { |
2305 | for (s = 0; s < 2; s++) { | 2520 | struct hda_pcm *cpcm = &codec->pcm_info[pcm]; |
2306 | struct hda_pcm_stream *info; | 2521 | int type = cpcm->pcm_type; |
2307 | info = &codec->pcm_info[pcm].stream[s]; | 2522 | int dev; |
2308 | if (!info->substreams) | 2523 | |
2524 | if (!cpcm->stream[0].substreams && | ||
2525 | !cpcm->stream[1].substreams) | ||
2526 | continue; /* no substreams assigned */ | ||
2527 | |||
2528 | switch (type) { | ||
2529 | case HDA_PCM_TYPE_AUDIO: | ||
2530 | if (num_devs[type] >= ARRAY_SIZE(audio_idx)) { | ||
2531 | snd_printk(KERN_WARNING | ||
2532 | "Too many audio devices\n"); | ||
2533 | continue; | ||
2534 | } | ||
2535 | dev = audio_idx[num_devs[type]]; | ||
2536 | break; | ||
2537 | case HDA_PCM_TYPE_SPDIF: | ||
2538 | case HDA_PCM_TYPE_HDMI: | ||
2539 | case HDA_PCM_TYPE_MODEM: | ||
2540 | if (num_devs[type]) { | ||
2541 | snd_printk(KERN_WARNING | ||
2542 | "%s already defined\n", | ||
2543 | dev_name[type]); | ||
2309 | continue; | 2544 | continue; |
2310 | err = set_pcm_default_values(codec, info); | 2545 | } |
2546 | dev = dev_idx[type]; | ||
2547 | break; | ||
2548 | default: | ||
2549 | snd_printk(KERN_WARNING | ||
2550 | "Invalid PCM type %d\n", type); | ||
2551 | continue; | ||
2552 | } | ||
2553 | num_devs[type]++; | ||
2554 | if (!cpcm->pcm) { | ||
2555 | cpcm->device = dev; | ||
2556 | err = snd_hda_attach_pcm(codec, cpcm); | ||
2311 | if (err < 0) | 2557 | if (err < 0) |
2312 | return err; | 2558 | return err; |
2313 | } | 2559 | } |
@@ -2333,11 +2579,11 @@ int snd_hda_check_board_config(struct hda_codec *codec, | |||
2333 | int num_configs, const char **models, | 2579 | int num_configs, const char **models, |
2334 | const struct snd_pci_quirk *tbl) | 2580 | const struct snd_pci_quirk *tbl) |
2335 | { | 2581 | { |
2336 | if (codec->bus->modelname && models) { | 2582 | if (codec->modelname && models) { |
2337 | int i; | 2583 | int i; |
2338 | for (i = 0; i < num_configs; i++) { | 2584 | for (i = 0; i < num_configs; i++) { |
2339 | if (models[i] && | 2585 | if (models[i] && |
2340 | !strcmp(codec->bus->modelname, models[i])) { | 2586 | !strcmp(codec->modelname, models[i])) { |
2341 | snd_printd(KERN_INFO "hda_codec: model '%s' is " | 2587 | snd_printd(KERN_INFO "hda_codec: model '%s' is " |
2342 | "selected\n", models[i]); | 2588 | "selected\n", models[i]); |
2343 | return i; | 2589 | return i; |
@@ -2390,7 +2636,7 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew) | |||
2390 | kctl = snd_ctl_new1(knew, codec); | 2636 | kctl = snd_ctl_new1(knew, codec); |
2391 | if (!kctl) | 2637 | if (!kctl) |
2392 | return -ENOMEM; | 2638 | return -ENOMEM; |
2393 | err = snd_ctl_add(codec->bus->card, kctl); | 2639 | err = snd_hda_ctl_add(codec, kctl); |
2394 | if (err < 0) { | 2640 | if (err < 0) { |
2395 | if (!codec->addr) | 2641 | if (!codec->addr) |
2396 | return err; | 2642 | return err; |
@@ -2398,7 +2644,7 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew) | |||
2398 | if (!kctl) | 2644 | if (!kctl) |
2399 | return -ENOMEM; | 2645 | return -ENOMEM; |
2400 | kctl->id.device = codec->addr; | 2646 | kctl->id.device = codec->addr; |
2401 | err = snd_ctl_add(codec->bus->card, kctl); | 2647 | err = snd_hda_ctl_add(codec, kctl); |
2402 | if (err < 0) | 2648 | if (err < 0) |
2403 | return err; | 2649 | return err; |
2404 | } | 2650 | } |
@@ -2414,6 +2660,7 @@ static void hda_power_work(struct work_struct *work) | |||
2414 | { | 2660 | { |
2415 | struct hda_codec *codec = | 2661 | struct hda_codec *codec = |
2416 | container_of(work, struct hda_codec, power_work.work); | 2662 | container_of(work, struct hda_codec, power_work.work); |
2663 | struct hda_bus *bus = codec->bus; | ||
2417 | 2664 | ||
2418 | if (!codec->power_on || codec->power_count) { | 2665 | if (!codec->power_on || codec->power_count) { |
2419 | codec->power_transition = 0; | 2666 | codec->power_transition = 0; |
@@ -2421,8 +2668,8 @@ static void hda_power_work(struct work_struct *work) | |||
2421 | } | 2668 | } |
2422 | 2669 | ||
2423 | hda_call_codec_suspend(codec); | 2670 | hda_call_codec_suspend(codec); |
2424 | if (codec->bus->ops.pm_notify) | 2671 | if (bus->ops.pm_notify) |
2425 | codec->bus->ops.pm_notify(codec); | 2672 | bus->ops.pm_notify(bus); |
2426 | } | 2673 | } |
2427 | 2674 | ||
2428 | static void hda_keep_power_on(struct hda_codec *codec) | 2675 | static void hda_keep_power_on(struct hda_codec *codec) |
@@ -2433,13 +2680,15 @@ static void hda_keep_power_on(struct hda_codec *codec) | |||
2433 | 2680 | ||
2434 | void snd_hda_power_up(struct hda_codec *codec) | 2681 | void snd_hda_power_up(struct hda_codec *codec) |
2435 | { | 2682 | { |
2683 | struct hda_bus *bus = codec->bus; | ||
2684 | |||
2436 | codec->power_count++; | 2685 | codec->power_count++; |
2437 | if (codec->power_on || codec->power_transition) | 2686 | if (codec->power_on || codec->power_transition) |
2438 | return; | 2687 | return; |
2439 | 2688 | ||
2440 | codec->power_on = 1; | 2689 | codec->power_on = 1; |
2441 | if (codec->bus->ops.pm_notify) | 2690 | if (bus->ops.pm_notify) |
2442 | codec->bus->ops.pm_notify(codec); | 2691 | bus->ops.pm_notify(bus); |
2443 | hda_call_codec_resume(codec); | 2692 | hda_call_codec_resume(codec); |
2444 | cancel_delayed_work(&codec->power_work); | 2693 | cancel_delayed_work(&codec->power_work); |
2445 | codec->power_transition = 0; | 2694 | codec->power_transition = 0; |
@@ -3139,3 +3388,70 @@ int snd_hda_codecs_inuse(struct hda_bus *bus) | |||
3139 | } | 3388 | } |
3140 | #endif | 3389 | #endif |
3141 | #endif | 3390 | #endif |
3391 | |||
3392 | /* | ||
3393 | * generic arrays | ||
3394 | */ | ||
3395 | |||
3396 | /* get a new element from the given array | ||
3397 | * if it exceeds the pre-allocated array size, re-allocate the array | ||
3398 | */ | ||
3399 | void *snd_array_new(struct snd_array *array) | ||
3400 | { | ||
3401 | if (array->used >= array->alloced) { | ||
3402 | int num = array->alloced + array->alloc_align; | ||
3403 | void *nlist; | ||
3404 | if (snd_BUG_ON(num >= 4096)) | ||
3405 | return NULL; | ||
3406 | nlist = kcalloc(num + 1, array->elem_size, GFP_KERNEL); | ||
3407 | if (!nlist) | ||
3408 | return NULL; | ||
3409 | if (array->list) { | ||
3410 | memcpy(nlist, array->list, | ||
3411 | array->elem_size * array->alloced); | ||
3412 | kfree(array->list); | ||
3413 | } | ||
3414 | array->list = nlist; | ||
3415 | array->alloced = num; | ||
3416 | } | ||
3417 | return snd_array_elem(array, array->used++); | ||
3418 | } | ||
3419 | |||
3420 | /* free the given array elements */ | ||
3421 | void snd_array_free(struct snd_array *array) | ||
3422 | { | ||
3423 | kfree(array->list); | ||
3424 | array->used = 0; | ||
3425 | array->alloced = 0; | ||
3426 | array->list = NULL; | ||
3427 | } | ||
3428 | |||
3429 | /* | ||
3430 | * used by hda_proc.c and hda_eld.c | ||
3431 | */ | ||
3432 | void snd_print_pcm_rates(int pcm, char *buf, int buflen) | ||
3433 | { | ||
3434 | static unsigned int rates[] = { | ||
3435 | 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200, | ||
3436 | 96000, 176400, 192000, 384000 | ||
3437 | }; | ||
3438 | int i, j; | ||
3439 | |||
3440 | for (i = 0, j = 0; i < ARRAY_SIZE(rates); i++) | ||
3441 | if (pcm & (1 << i)) | ||
3442 | j += snprintf(buf + j, buflen - j, " %d", rates[i]); | ||
3443 | |||
3444 | buf[j] = '\0'; /* necessary when j == 0 */ | ||
3445 | } | ||
3446 | |||
3447 | void snd_print_pcm_bits(int pcm, char *buf, int buflen) | ||
3448 | { | ||
3449 | static unsigned int bits[] = { 8, 16, 20, 24, 32 }; | ||
3450 | int i, j; | ||
3451 | |||
3452 | for (i = 0, j = 0; i < ARRAY_SIZE(bits); i++) | ||
3453 | if (pcm & (AC_SUPPCM_BITS_8 << i)) | ||
3454 | j += snprintf(buf + j, buflen - j, " %d", bits[i]); | ||
3455 | |||
3456 | buf[j] = '\0'; /* necessary when j == 0 */ | ||
3457 | } | ||
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 60468f562400..a70b181bbace 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -520,6 +520,36 @@ enum { | |||
520 | #define HDA_MAX_CODEC_ADDRESS 0x0f | 520 | #define HDA_MAX_CODEC_ADDRESS 0x0f |
521 | 521 | ||
522 | /* | 522 | /* |
523 | * generic arrays | ||
524 | */ | ||
525 | struct snd_array { | ||
526 | unsigned int used; | ||
527 | unsigned int alloced; | ||
528 | unsigned int elem_size; | ||
529 | unsigned int alloc_align; | ||
530 | void *list; | ||
531 | }; | ||
532 | |||
533 | void *snd_array_new(struct snd_array *array); | ||
534 | void snd_array_free(struct snd_array *array); | ||
535 | static inline void snd_array_init(struct snd_array *array, unsigned int size, | ||
536 | unsigned int align) | ||
537 | { | ||
538 | array->elem_size = size; | ||
539 | array->alloc_align = align; | ||
540 | } | ||
541 | |||
542 | static inline void *snd_array_elem(struct snd_array *array, unsigned int idx) | ||
543 | { | ||
544 | return array->list + idx * array->elem_size; | ||
545 | } | ||
546 | |||
547 | static inline unsigned int snd_array_index(struct snd_array *array, void *ptr) | ||
548 | { | ||
549 | return (unsigned long)(ptr - array->list) / array->elem_size; | ||
550 | } | ||
551 | |||
552 | /* | ||
523 | * Structures | 553 | * Structures |
524 | */ | 554 | */ |
525 | 555 | ||
@@ -536,15 +566,17 @@ typedef u16 hda_nid_t; | |||
536 | /* bus operators */ | 566 | /* bus operators */ |
537 | struct hda_bus_ops { | 567 | struct hda_bus_ops { |
538 | /* send a single command */ | 568 | /* send a single command */ |
539 | int (*command)(struct hda_codec *codec, hda_nid_t nid, int direct, | 569 | int (*command)(struct hda_bus *bus, unsigned int cmd); |
540 | unsigned int verb, unsigned int parm); | ||
541 | /* get a response from the last command */ | 570 | /* get a response from the last command */ |
542 | unsigned int (*get_response)(struct hda_codec *codec); | 571 | unsigned int (*get_response)(struct hda_bus *bus); |
543 | /* free the private data */ | 572 | /* free the private data */ |
544 | void (*private_free)(struct hda_bus *); | 573 | void (*private_free)(struct hda_bus *); |
574 | /* attach a PCM stream */ | ||
575 | int (*attach_pcm)(struct hda_bus *bus, struct hda_codec *codec, | ||
576 | struct hda_pcm *pcm); | ||
545 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 577 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
546 | /* notify power-up/down from codec to controller */ | 578 | /* notify power-up/down from codec to controller */ |
547 | void (*pm_notify)(struct hda_codec *codec); | 579 | void (*pm_notify)(struct hda_bus *bus); |
548 | #endif | 580 | #endif |
549 | }; | 581 | }; |
550 | 582 | ||
@@ -585,6 +617,7 @@ struct hda_bus { | |||
585 | 617 | ||
586 | /* misc op flags */ | 618 | /* misc op flags */ |
587 | unsigned int needs_damn_long_delay :1; | 619 | unsigned int needs_damn_long_delay :1; |
620 | unsigned int shutdown :1; /* being unloaded */ | ||
588 | }; | 621 | }; |
589 | 622 | ||
590 | /* | 623 | /* |
@@ -635,10 +668,7 @@ struct hda_amp_info { | |||
635 | 668 | ||
636 | struct hda_cache_rec { | 669 | struct hda_cache_rec { |
637 | u16 hash[64]; /* hash table for index */ | 670 | u16 hash[64]; /* hash table for index */ |
638 | unsigned int num_entries; /* number of assigned entries */ | 671 | struct snd_array buf; /* record entries */ |
639 | unsigned int size; /* allocated size */ | ||
640 | unsigned int record_size; /* record size (including header) */ | ||
641 | void *buffer; /* hash table entries */ | ||
642 | }; | 672 | }; |
643 | 673 | ||
644 | /* PCM callbacks */ | 674 | /* PCM callbacks */ |
@@ -680,7 +710,8 @@ struct hda_pcm { | |||
680 | char *name; | 710 | char *name; |
681 | struct hda_pcm_stream stream[2]; | 711 | struct hda_pcm_stream stream[2]; |
682 | unsigned int pcm_type; /* HDA_PCM_TYPE_XXX */ | 712 | unsigned int pcm_type; /* HDA_PCM_TYPE_XXX */ |
683 | int device; /* assigned device number */ | 713 | int device; /* device number to assign */ |
714 | struct snd_pcm *pcm; /* assigned PCM instance */ | ||
684 | }; | 715 | }; |
685 | 716 | ||
686 | /* codec information */ | 717 | /* codec information */ |
@@ -699,6 +730,8 @@ struct hda_codec { | |||
699 | 730 | ||
700 | /* detected preset */ | 731 | /* detected preset */ |
701 | const struct hda_codec_preset *preset; | 732 | const struct hda_codec_preset *preset; |
733 | const char *name; /* codec name */ | ||
734 | const char *modelname; /* model name for preset */ | ||
702 | 735 | ||
703 | /* set by patch */ | 736 | /* set by patch */ |
704 | struct hda_codec_ops patch_ops; | 737 | struct hda_codec_ops patch_ops; |
@@ -718,6 +751,8 @@ struct hda_codec { | |||
718 | hda_nid_t start_nid; | 751 | hda_nid_t start_nid; |
719 | u32 *wcaps; | 752 | u32 *wcaps; |
720 | 753 | ||
754 | struct snd_array mixers; /* list of assigned mixer elements */ | ||
755 | |||
721 | struct hda_cache_rec amp_cache; /* cache for amp access */ | 756 | struct hda_cache_rec amp_cache; /* cache for amp access */ |
722 | struct hda_cache_rec cmd_cache; /* cache for other commands */ | 757 | struct hda_cache_rec cmd_cache; /* cache for other commands */ |
723 | 758 | ||
@@ -727,7 +762,11 @@ struct hda_codec { | |||
727 | unsigned int spdif_in_enable; /* SPDIF input enable? */ | 762 | unsigned int spdif_in_enable; /* SPDIF input enable? */ |
728 | hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */ | 763 | hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */ |
729 | 764 | ||
765 | #ifdef CONFIG_SND_HDA_HWDEP | ||
730 | struct snd_hwdep *hwdep; /* assigned hwdep device */ | 766 | struct snd_hwdep *hwdep; /* assigned hwdep device */ |
767 | struct snd_array init_verbs; /* additional init verbs */ | ||
768 | struct snd_array hints; /* additional hints */ | ||
769 | #endif | ||
731 | 770 | ||
732 | /* misc flags */ | 771 | /* misc flags */ |
733 | unsigned int spdif_status_reset :1; /* needs to toggle SPDIF for each | 772 | unsigned int spdif_status_reset :1; /* needs to toggle SPDIF for each |
@@ -799,6 +838,7 @@ void snd_hda_codec_resume_cache(struct hda_codec *codec); | |||
799 | * Mixer | 838 | * Mixer |
800 | */ | 839 | */ |
801 | int snd_hda_build_controls(struct hda_bus *bus); | 840 | int snd_hda_build_controls(struct hda_bus *bus); |
841 | int snd_hda_codec_build_controls(struct hda_codec *codec); | ||
802 | 842 | ||
803 | /* | 843 | /* |
804 | * PCM | 844 | * PCM |
@@ -831,6 +871,13 @@ int snd_hda_resume(struct hda_bus *bus); | |||
831 | #endif | 871 | #endif |
832 | 872 | ||
833 | /* | 873 | /* |
874 | * get widget information | ||
875 | */ | ||
876 | const char *snd_hda_get_jack_connectivity(u32 cfg); | ||
877 | const char *snd_hda_get_jack_type(u32 cfg); | ||
878 | const char *snd_hda_get_jack_location(u32 cfg); | ||
879 | |||
880 | /* | ||
834 | * power saving | 881 | * power saving |
835 | */ | 882 | */ |
836 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 883 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c new file mode 100644 index 000000000000..fcad5ec31773 --- /dev/null +++ b/sound/pci/hda/hda_eld.c | |||
@@ -0,0 +1,590 @@ | |||
1 | /* | ||
2 | * Generic routines and proc interface for ELD(EDID Like Data) information | ||
3 | * | ||
4 | * Copyright(c) 2008 Intel Corporation. | ||
5 | * | ||
6 | * Authors: | ||
7 | * Wu Fengguang <wfg@linux.intel.com> | ||
8 | * | ||
9 | * This driver is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This driver is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | */ | ||
23 | |||
24 | #include <linux/init.h> | ||
25 | #include <sound/core.h> | ||
26 | #include <asm/unaligned.h> | ||
27 | #include "hda_codec.h" | ||
28 | #include "hda_local.h" | ||
29 | |||
30 | enum eld_versions { | ||
31 | ELD_VER_CEA_861D = 2, | ||
32 | ELD_VER_PARTIAL = 31, | ||
33 | }; | ||
34 | |||
35 | enum cea_edid_versions { | ||
36 | CEA_EDID_VER_NONE = 0, | ||
37 | CEA_EDID_VER_CEA861 = 1, | ||
38 | CEA_EDID_VER_CEA861A = 2, | ||
39 | CEA_EDID_VER_CEA861BCD = 3, | ||
40 | CEA_EDID_VER_RESERVED = 4, | ||
41 | }; | ||
42 | |||
43 | static char *cea_speaker_allocation_names[] = { | ||
44 | /* 0 */ "FL/FR", | ||
45 | /* 1 */ "LFE", | ||
46 | /* 2 */ "FC", | ||
47 | /* 3 */ "RL/RR", | ||
48 | /* 4 */ "RC", | ||
49 | /* 5 */ "FLC/FRC", | ||
50 | /* 6 */ "RLC/RRC", | ||
51 | /* 7 */ "FLW/FRW", | ||
52 | /* 8 */ "FLH/FRH", | ||
53 | /* 9 */ "TC", | ||
54 | /* 10 */ "FCH", | ||
55 | }; | ||
56 | |||
57 | static char *eld_connection_type_names[4] = { | ||
58 | "HDMI", | ||
59 | "DisplayPort", | ||
60 | "2-reserved", | ||
61 | "3-reserved" | ||
62 | }; | ||
63 | |||
64 | enum cea_audio_coding_types { | ||
65 | AUDIO_CODING_TYPE_REF_STREAM_HEADER = 0, | ||
66 | AUDIO_CODING_TYPE_LPCM = 1, | ||
67 | AUDIO_CODING_TYPE_AC3 = 2, | ||
68 | AUDIO_CODING_TYPE_MPEG1 = 3, | ||
69 | AUDIO_CODING_TYPE_MP3 = 4, | ||
70 | AUDIO_CODING_TYPE_MPEG2 = 5, | ||
71 | AUDIO_CODING_TYPE_AACLC = 6, | ||
72 | AUDIO_CODING_TYPE_DTS = 7, | ||
73 | AUDIO_CODING_TYPE_ATRAC = 8, | ||
74 | AUDIO_CODING_TYPE_SACD = 9, | ||
75 | AUDIO_CODING_TYPE_EAC3 = 10, | ||
76 | AUDIO_CODING_TYPE_DTS_HD = 11, | ||
77 | AUDIO_CODING_TYPE_MLP = 12, | ||
78 | AUDIO_CODING_TYPE_DST = 13, | ||
79 | AUDIO_CODING_TYPE_WMAPRO = 14, | ||
80 | AUDIO_CODING_TYPE_REF_CXT = 15, | ||
81 | /* also include valid xtypes below */ | ||
82 | AUDIO_CODING_TYPE_HE_AAC = 15, | ||
83 | AUDIO_CODING_TYPE_HE_AAC2 = 16, | ||
84 | AUDIO_CODING_TYPE_MPEG_SURROUND = 17, | ||
85 | }; | ||
86 | |||
87 | enum cea_audio_coding_xtypes { | ||
88 | AUDIO_CODING_XTYPE_HE_REF_CT = 0, | ||
89 | AUDIO_CODING_XTYPE_HE_AAC = 1, | ||
90 | AUDIO_CODING_XTYPE_HE_AAC2 = 2, | ||
91 | AUDIO_CODING_XTYPE_MPEG_SURROUND = 3, | ||
92 | AUDIO_CODING_XTYPE_FIRST_RESERVED = 4, | ||
93 | }; | ||
94 | |||
95 | static char *cea_audio_coding_type_names[] = { | ||
96 | /* 0 */ "undefined", | ||
97 | /* 1 */ "LPCM", | ||
98 | /* 2 */ "AC-3", | ||
99 | /* 3 */ "MPEG1", | ||
100 | /* 4 */ "MP3", | ||
101 | /* 5 */ "MPEG2", | ||
102 | /* 6 */ "AAC-LC", | ||
103 | /* 7 */ "DTS", | ||
104 | /* 8 */ "ATRAC", | ||
105 | /* 9 */ "DSD (One Bit Audio)", | ||
106 | /* 10 */ "E-AC-3/DD+ (Dolby Digital Plus)", | ||
107 | /* 11 */ "DTS-HD", | ||
108 | /* 12 */ "MLP (Dolby TrueHD)", | ||
109 | /* 13 */ "DST", | ||
110 | /* 14 */ "WMAPro", | ||
111 | /* 15 */ "HE-AAC", | ||
112 | /* 16 */ "HE-AACv2", | ||
113 | /* 17 */ "MPEG Surround", | ||
114 | }; | ||
115 | |||
116 | /* | ||
117 | * The following two lists are shared between | ||
118 | * - HDMI audio InfoFrame (source to sink) | ||
119 | * - CEA E-EDID Extension (sink to source) | ||
120 | */ | ||
121 | |||
122 | /* | ||
123 | * SS1:SS0 index => sample size | ||
124 | */ | ||
125 | static int cea_sample_sizes[4] = { | ||
126 | 0, /* 0: Refer to Stream Header */ | ||
127 | AC_SUPPCM_BITS_16, /* 1: 16 bits */ | ||
128 | AC_SUPPCM_BITS_20, /* 2: 20 bits */ | ||
129 | AC_SUPPCM_BITS_24, /* 3: 24 bits */ | ||
130 | }; | ||
131 | |||
132 | /* | ||
133 | * SF2:SF1:SF0 index => sampling frequency | ||
134 | */ | ||
135 | static int cea_sampling_frequencies[8] = { | ||
136 | 0, /* 0: Refer to Stream Header */ | ||
137 | SNDRV_PCM_RATE_32000, /* 1: 32000Hz */ | ||
138 | SNDRV_PCM_RATE_44100, /* 2: 44100Hz */ | ||
139 | SNDRV_PCM_RATE_48000, /* 3: 48000Hz */ | ||
140 | SNDRV_PCM_RATE_88200, /* 4: 88200Hz */ | ||
141 | SNDRV_PCM_RATE_96000, /* 5: 96000Hz */ | ||
142 | SNDRV_PCM_RATE_176400, /* 6: 176400Hz */ | ||
143 | SNDRV_PCM_RATE_192000, /* 7: 192000Hz */ | ||
144 | }; | ||
145 | |||
146 | static unsigned char hdmi_get_eld_byte(struct hda_codec *codec, hda_nid_t nid, | ||
147 | int byte_index) | ||
148 | { | ||
149 | unsigned int val; | ||
150 | |||
151 | val = snd_hda_codec_read(codec, nid, 0, | ||
152 | AC_VERB_GET_HDMI_ELDD, byte_index); | ||
153 | |||
154 | #ifdef BE_PARANOID | ||
155 | printk(KERN_INFO "HDMI: ELD data byte %d: 0x%x\n", byte_index, val); | ||
156 | #endif | ||
157 | |||
158 | if ((val & AC_ELDD_ELD_VALID) == 0) { | ||
159 | snd_printd(KERN_INFO "HDMI: invalid ELD data byte %d\n", | ||
160 | byte_index); | ||
161 | val = 0; | ||
162 | } | ||
163 | |||
164 | return val & AC_ELDD_ELD_DATA; | ||
165 | } | ||
166 | |||
167 | #define GRAB_BITS(buf, byte, lowbit, bits) \ | ||
168 | ({ \ | ||
169 | BUILD_BUG_ON(lowbit > 7); \ | ||
170 | BUILD_BUG_ON(bits > 8); \ | ||
171 | BUILD_BUG_ON(bits <= 0); \ | ||
172 | \ | ||
173 | (buf[byte] >> (lowbit)) & ((1 << (bits)) - 1); \ | ||
174 | }) | ||
175 | |||
176 | static void hdmi_update_short_audio_desc(struct cea_sad *a, | ||
177 | const unsigned char *buf) | ||
178 | { | ||
179 | int i; | ||
180 | int val; | ||
181 | |||
182 | val = GRAB_BITS(buf, 1, 0, 7); | ||
183 | a->rates = 0; | ||
184 | for (i = 0; i < 7; i++) | ||
185 | if (val & (1 << i)) | ||
186 | a->rates |= cea_sampling_frequencies[i + 1]; | ||
187 | |||
188 | a->channels = GRAB_BITS(buf, 0, 0, 3); | ||
189 | a->channels++; | ||
190 | |||
191 | a->format = GRAB_BITS(buf, 0, 3, 4); | ||
192 | switch (a->format) { | ||
193 | case AUDIO_CODING_TYPE_REF_STREAM_HEADER: | ||
194 | snd_printd(KERN_INFO | ||
195 | "HDMI: audio coding type 0 not expected\n"); | ||
196 | break; | ||
197 | |||
198 | case AUDIO_CODING_TYPE_LPCM: | ||
199 | val = GRAB_BITS(buf, 2, 0, 3); | ||
200 | a->sample_bits = 0; | ||
201 | for (i = 0; i < 3; i++) | ||
202 | if (val & (1 << i)) | ||
203 | a->sample_bits |= cea_sample_sizes[i + 1]; | ||
204 | break; | ||
205 | |||
206 | case AUDIO_CODING_TYPE_AC3: | ||
207 | case AUDIO_CODING_TYPE_MPEG1: | ||
208 | case AUDIO_CODING_TYPE_MP3: | ||
209 | case AUDIO_CODING_TYPE_MPEG2: | ||
210 | case AUDIO_CODING_TYPE_AACLC: | ||
211 | case AUDIO_CODING_TYPE_DTS: | ||
212 | case AUDIO_CODING_TYPE_ATRAC: | ||
213 | a->max_bitrate = GRAB_BITS(buf, 2, 0, 8); | ||
214 | a->max_bitrate *= 8000; | ||
215 | break; | ||
216 | |||
217 | case AUDIO_CODING_TYPE_SACD: | ||
218 | break; | ||
219 | |||
220 | case AUDIO_CODING_TYPE_EAC3: | ||
221 | break; | ||
222 | |||
223 | case AUDIO_CODING_TYPE_DTS_HD: | ||
224 | break; | ||
225 | |||
226 | case AUDIO_CODING_TYPE_MLP: | ||
227 | break; | ||
228 | |||
229 | case AUDIO_CODING_TYPE_DST: | ||
230 | break; | ||
231 | |||
232 | case AUDIO_CODING_TYPE_WMAPRO: | ||
233 | a->profile = GRAB_BITS(buf, 2, 0, 3); | ||
234 | break; | ||
235 | |||
236 | case AUDIO_CODING_TYPE_REF_CXT: | ||
237 | a->format = GRAB_BITS(buf, 2, 3, 5); | ||
238 | if (a->format == AUDIO_CODING_XTYPE_HE_REF_CT || | ||
239 | a->format >= AUDIO_CODING_XTYPE_FIRST_RESERVED) { | ||
240 | snd_printd(KERN_INFO | ||
241 | "HDMI: audio coding xtype %d not expected\n", | ||
242 | a->format); | ||
243 | a->format = 0; | ||
244 | } else | ||
245 | a->format += AUDIO_CODING_TYPE_HE_AAC - | ||
246 | AUDIO_CODING_XTYPE_HE_AAC; | ||
247 | break; | ||
248 | } | ||
249 | } | ||
250 | |||
251 | /* | ||
252 | * Be careful, ELD buf could be totally rubbish! | ||
253 | */ | ||
254 | static int hdmi_update_eld(struct hdmi_eld *e, | ||
255 | const unsigned char *buf, int size) | ||
256 | { | ||
257 | int mnl; | ||
258 | int i; | ||
259 | |||
260 | e->eld_ver = GRAB_BITS(buf, 0, 3, 5); | ||
261 | if (e->eld_ver != ELD_VER_CEA_861D && | ||
262 | e->eld_ver != ELD_VER_PARTIAL) { | ||
263 | snd_printd(KERN_INFO "HDMI: Unknown ELD version %d\n", | ||
264 | e->eld_ver); | ||
265 | goto out_fail; | ||
266 | } | ||
267 | |||
268 | e->eld_size = size; | ||
269 | e->baseline_len = GRAB_BITS(buf, 2, 0, 8); | ||
270 | mnl = GRAB_BITS(buf, 4, 0, 5); | ||
271 | e->cea_edid_ver = GRAB_BITS(buf, 4, 5, 3); | ||
272 | |||
273 | e->support_hdcp = GRAB_BITS(buf, 5, 0, 1); | ||
274 | e->support_ai = GRAB_BITS(buf, 5, 1, 1); | ||
275 | e->conn_type = GRAB_BITS(buf, 5, 2, 2); | ||
276 | e->sad_count = GRAB_BITS(buf, 5, 4, 4); | ||
277 | |||
278 | e->aud_synch_delay = GRAB_BITS(buf, 6, 0, 8) * 2; | ||
279 | e->spk_alloc = GRAB_BITS(buf, 7, 0, 7); | ||
280 | |||
281 | e->port_id = get_unaligned_le64(buf + 8); | ||
282 | |||
283 | /* not specified, but the spec's tendency is little endian */ | ||
284 | e->manufacture_id = get_unaligned_le16(buf + 16); | ||
285 | e->product_id = get_unaligned_le16(buf + 18); | ||
286 | |||
287 | if (mnl > ELD_MAX_MNL) { | ||
288 | snd_printd(KERN_INFO "HDMI: MNL is reserved value %d\n", mnl); | ||
289 | goto out_fail; | ||
290 | } else if (ELD_FIXED_BYTES + mnl > size) { | ||
291 | snd_printd(KERN_INFO "HDMI: out of range MNL %d\n", mnl); | ||
292 | goto out_fail; | ||
293 | } else | ||
294 | strlcpy(e->monitor_name, buf + ELD_FIXED_BYTES, mnl); | ||
295 | |||
296 | for (i = 0; i < e->sad_count; i++) { | ||
297 | if (ELD_FIXED_BYTES + mnl + 3 * (i + 1) > size) { | ||
298 | snd_printd(KERN_INFO "HDMI: out of range SAD %d\n", i); | ||
299 | goto out_fail; | ||
300 | } | ||
301 | hdmi_update_short_audio_desc(e->sad + i, | ||
302 | buf + ELD_FIXED_BYTES + mnl + 3 * i); | ||
303 | } | ||
304 | |||
305 | return 0; | ||
306 | |||
307 | out_fail: | ||
308 | e->eld_ver = 0; | ||
309 | return -EINVAL; | ||
310 | } | ||
311 | |||
312 | static int hdmi_present_sense(struct hda_codec *codec, hda_nid_t nid) | ||
313 | { | ||
314 | return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0); | ||
315 | } | ||
316 | |||
317 | static int hdmi_eld_valid(struct hda_codec *codec, hda_nid_t nid) | ||
318 | { | ||
319 | int eldv; | ||
320 | int present; | ||
321 | |||
322 | present = hdmi_present_sense(codec, nid); | ||
323 | eldv = (present & AC_PINSENSE_ELDV); | ||
324 | present = (present & AC_PINSENSE_PRESENCE); | ||
325 | |||
326 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
327 | printk(KERN_INFO "HDMI: sink_present = %d, eld_valid = %d\n", | ||
328 | !!present, !!eldv); | ||
329 | #endif | ||
330 | |||
331 | return eldv && present; | ||
332 | } | ||
333 | |||
334 | int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid) | ||
335 | { | ||
336 | return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE, | ||
337 | AC_DIPSIZE_ELD_BUF); | ||
338 | } | ||
339 | |||
340 | int snd_hdmi_get_eld(struct hdmi_eld *eld, | ||
341 | struct hda_codec *codec, hda_nid_t nid) | ||
342 | { | ||
343 | int i; | ||
344 | int ret; | ||
345 | int size; | ||
346 | unsigned char *buf; | ||
347 | |||
348 | if (!hdmi_eld_valid(codec, nid)) | ||
349 | return -ENOENT; | ||
350 | |||
351 | size = snd_hdmi_get_eld_size(codec, nid); | ||
352 | if (size == 0) { | ||
353 | /* wfg: workaround for ASUS P5E-VM HDMI board */ | ||
354 | snd_printd(KERN_INFO "HDMI: ELD buf size is 0, force 128\n"); | ||
355 | size = 128; | ||
356 | } | ||
357 | if (size < ELD_FIXED_BYTES || size > PAGE_SIZE) { | ||
358 | snd_printd(KERN_INFO "HDMI: invalid ELD buf size %d\n", size); | ||
359 | return -ERANGE; | ||
360 | } | ||
361 | |||
362 | buf = kmalloc(size, GFP_KERNEL); | ||
363 | if (!buf) | ||
364 | return -ENOMEM; | ||
365 | |||
366 | for (i = 0; i < size; i++) | ||
367 | buf[i] = hdmi_get_eld_byte(codec, nid, i); | ||
368 | |||
369 | ret = hdmi_update_eld(eld, buf, size); | ||
370 | |||
371 | kfree(buf); | ||
372 | return ret; | ||
373 | } | ||
374 | |||
375 | static void hdmi_show_short_audio_desc(struct cea_sad *a) | ||
376 | { | ||
377 | char buf[SND_PRINT_RATES_ADVISED_BUFSIZE]; | ||
378 | char buf2[8 + SND_PRINT_BITS_ADVISED_BUFSIZE] = ", bits ="; | ||
379 | |||
380 | if (!a->format) | ||
381 | return; | ||
382 | |||
383 | snd_print_pcm_rates(a->rates, buf, sizeof(buf)); | ||
384 | |||
385 | if (a->format == AUDIO_CODING_TYPE_LPCM) | ||
386 | snd_print_pcm_bits(a->sample_bits, buf2 + 8, sizeof(buf2 - 8)); | ||
387 | else if (a->max_bitrate) | ||
388 | snprintf(buf2, sizeof(buf2), | ||
389 | ", max bitrate = %d", a->max_bitrate); | ||
390 | else | ||
391 | buf2[0] = '\0'; | ||
392 | |||
393 | printk(KERN_INFO "HDMI: supports coding type %s:" | ||
394 | " channels = %d, rates =%s%s\n", | ||
395 | cea_audio_coding_type_names[a->format], | ||
396 | a->channels, | ||
397 | buf, | ||
398 | buf2); | ||
399 | } | ||
400 | |||
401 | void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen) | ||
402 | { | ||
403 | int i, j; | ||
404 | |||
405 | for (i = 0, j = 0; i < ARRAY_SIZE(cea_speaker_allocation_names); i++) { | ||
406 | if (spk_alloc & (1 << i)) | ||
407 | j += snprintf(buf + j, buflen - j, " %s", | ||
408 | cea_speaker_allocation_names[i]); | ||
409 | } | ||
410 | buf[j] = '\0'; /* necessary when j == 0 */ | ||
411 | } | ||
412 | |||
413 | void snd_hdmi_show_eld(struct hdmi_eld *e) | ||
414 | { | ||
415 | int i; | ||
416 | |||
417 | printk(KERN_INFO "HDMI: detected monitor %s at connection type %s\n", | ||
418 | e->monitor_name, | ||
419 | eld_connection_type_names[e->conn_type]); | ||
420 | |||
421 | if (e->spk_alloc) { | ||
422 | char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; | ||
423 | snd_print_channel_allocation(e->spk_alloc, buf, sizeof(buf)); | ||
424 | printk(KERN_INFO "HDMI: available speakers:%s\n", buf); | ||
425 | } | ||
426 | |||
427 | for (i = 0; i < e->sad_count; i++) | ||
428 | hdmi_show_short_audio_desc(e->sad + i); | ||
429 | } | ||
430 | |||
431 | #ifdef CONFIG_PROC_FS | ||
432 | |||
433 | static void hdmi_print_sad_info(int i, struct cea_sad *a, | ||
434 | struct snd_info_buffer *buffer) | ||
435 | { | ||
436 | char buf[SND_PRINT_RATES_ADVISED_BUFSIZE]; | ||
437 | |||
438 | snd_iprintf(buffer, "sad%d_coding_type\t[0x%x] %s\n", | ||
439 | i, a->format, cea_audio_coding_type_names[a->format]); | ||
440 | snd_iprintf(buffer, "sad%d_channels\t\t%d\n", i, a->channels); | ||
441 | |||
442 | snd_print_pcm_rates(a->rates, buf, sizeof(buf)); | ||
443 | snd_iprintf(buffer, "sad%d_rates\t\t[0x%x]%s\n", i, a->rates, buf); | ||
444 | |||
445 | if (a->format == AUDIO_CODING_TYPE_LPCM) { | ||
446 | snd_print_pcm_bits(a->sample_bits, buf, sizeof(buf)); | ||
447 | snd_iprintf(buffer, "sad%d_bits\t\t[0x%x]%s\n", | ||
448 | i, a->sample_bits, buf); | ||
449 | } | ||
450 | |||
451 | if (a->max_bitrate) | ||
452 | snd_iprintf(buffer, "sad%d_max_bitrate\t%d\n", | ||
453 | i, a->max_bitrate); | ||
454 | |||
455 | if (a->profile) | ||
456 | snd_iprintf(buffer, "sad%d_profile\t\t%d\n", i, a->profile); | ||
457 | } | ||
458 | |||
459 | static void hdmi_print_eld_info(struct snd_info_entry *entry, | ||
460 | struct snd_info_buffer *buffer) | ||
461 | { | ||
462 | struct hdmi_eld *e = entry->private_data; | ||
463 | char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; | ||
464 | int i; | ||
465 | static char *eld_versoin_names[32] = { | ||
466 | "reserved", | ||
467 | "reserved", | ||
468 | "CEA-861D or below", | ||
469 | [3 ... 30] = "reserved", | ||
470 | [31] = "partial" | ||
471 | }; | ||
472 | static char *cea_edid_version_names[8] = { | ||
473 | "no CEA EDID Timing Extension block present", | ||
474 | "CEA-861", | ||
475 | "CEA-861-A", | ||
476 | "CEA-861-B, C or D", | ||
477 | [4 ... 7] = "reserved" | ||
478 | }; | ||
479 | |||
480 | snd_iprintf(buffer, "monitor_name\t\t%s\n", e->monitor_name); | ||
481 | snd_iprintf(buffer, "connection_type\t\t%s\n", | ||
482 | eld_connection_type_names[e->conn_type]); | ||
483 | snd_iprintf(buffer, "eld_version\t\t[0x%x] %s\n", e->eld_ver, | ||
484 | eld_versoin_names[e->eld_ver]); | ||
485 | snd_iprintf(buffer, "edid_version\t\t[0x%x] %s\n", e->cea_edid_ver, | ||
486 | cea_edid_version_names[e->cea_edid_ver]); | ||
487 | snd_iprintf(buffer, "manufacture_id\t\t0x%x\n", e->manufacture_id); | ||
488 | snd_iprintf(buffer, "product_id\t\t0x%x\n", e->product_id); | ||
489 | snd_iprintf(buffer, "port_id\t\t\t0x%llx\n", (long long)e->port_id); | ||
490 | snd_iprintf(buffer, "support_hdcp\t\t%d\n", e->support_hdcp); | ||
491 | snd_iprintf(buffer, "support_ai\t\t%d\n", e->support_ai); | ||
492 | snd_iprintf(buffer, "audio_sync_delay\t%d\n", e->aud_synch_delay); | ||
493 | |||
494 | snd_print_channel_allocation(e->spk_alloc, buf, sizeof(buf)); | ||
495 | snd_iprintf(buffer, "speakers\t\t[0x%x]%s\n", e->spk_alloc, buf); | ||
496 | |||
497 | snd_iprintf(buffer, "sad_count\t\t%d\n", e->sad_count); | ||
498 | |||
499 | for (i = 0; i < e->sad_count; i++) | ||
500 | hdmi_print_sad_info(i, e->sad + i, buffer); | ||
501 | } | ||
502 | |||
503 | static void hdmi_write_eld_info(struct snd_info_entry *entry, | ||
504 | struct snd_info_buffer *buffer) | ||
505 | { | ||
506 | struct hdmi_eld *e = entry->private_data; | ||
507 | char line[64]; | ||
508 | char name[64]; | ||
509 | char *sname; | ||
510 | long long val; | ||
511 | int n; | ||
512 | |||
513 | while (!snd_info_get_line(buffer, line, sizeof(line))) { | ||
514 | if (sscanf(line, "%s %llx", name, &val) != 2) | ||
515 | continue; | ||
516 | /* | ||
517 | * We don't allow modification to these fields: | ||
518 | * monitor_name manufacture_id product_id | ||
519 | * eld_version edid_version | ||
520 | */ | ||
521 | if (!strcmp(name, "connection_type")) | ||
522 | e->conn_type = val; | ||
523 | else if (!strcmp(name, "port_id")) | ||
524 | e->port_id = val; | ||
525 | else if (!strcmp(name, "support_hdcp")) | ||
526 | e->support_hdcp = val; | ||
527 | else if (!strcmp(name, "support_ai")) | ||
528 | e->support_ai = val; | ||
529 | else if (!strcmp(name, "audio_sync_delay")) | ||
530 | e->aud_synch_delay = val; | ||
531 | else if (!strcmp(name, "speakers")) | ||
532 | e->spk_alloc = val; | ||
533 | else if (!strcmp(name, "sad_count")) | ||
534 | e->sad_count = val; | ||
535 | else if (!strncmp(name, "sad", 3)) { | ||
536 | sname = name + 4; | ||
537 | n = name[3] - '0'; | ||
538 | if (name[4] >= '0' && name[4] <= '9') { | ||
539 | sname++; | ||
540 | n = 10 * n + name[4] - '0'; | ||
541 | } | ||
542 | if (n < 0 || n > 31) /* double the CEA limit */ | ||
543 | continue; | ||
544 | if (!strcmp(sname, "_coding_type")) | ||
545 | e->sad[n].format = val; | ||
546 | else if (!strcmp(sname, "_channels")) | ||
547 | e->sad[n].channels = val; | ||
548 | else if (!strcmp(sname, "_rates")) | ||
549 | e->sad[n].rates = val; | ||
550 | else if (!strcmp(sname, "_bits")) | ||
551 | e->sad[n].sample_bits = val; | ||
552 | else if (!strcmp(sname, "_max_bitrate")) | ||
553 | e->sad[n].max_bitrate = val; | ||
554 | else if (!strcmp(sname, "_profile")) | ||
555 | e->sad[n].profile = val; | ||
556 | if (n >= e->sad_count) | ||
557 | e->sad_count = n + 1; | ||
558 | } | ||
559 | } | ||
560 | } | ||
561 | |||
562 | |||
563 | int snd_hda_eld_proc_new(struct hda_codec *codec, struct hdmi_eld *eld) | ||
564 | { | ||
565 | char name[32]; | ||
566 | struct snd_info_entry *entry; | ||
567 | int err; | ||
568 | |||
569 | snprintf(name, sizeof(name), "eld#%d", codec->addr); | ||
570 | err = snd_card_proc_new(codec->bus->card, name, &entry); | ||
571 | if (err < 0) | ||
572 | return err; | ||
573 | |||
574 | snd_info_set_text_ops(entry, eld, hdmi_print_eld_info); | ||
575 | entry->c.text.write = hdmi_write_eld_info; | ||
576 | entry->mode |= S_IWUSR; | ||
577 | eld->proc_entry = entry; | ||
578 | |||
579 | return 0; | ||
580 | } | ||
581 | |||
582 | void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld) | ||
583 | { | ||
584 | if (!codec->bus->shutdown && eld->proc_entry) { | ||
585 | snd_device_free(codec->bus->card, eld->proc_entry); | ||
586 | eld->proc_entry = NULL; | ||
587 | } | ||
588 | } | ||
589 | |||
590 | #endif /* CONFIG_PROC_FS */ | ||
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 0ca30894f7c6..98ff010d5b95 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c | |||
@@ -723,7 +723,8 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node, | |||
723 | if (is_loopback) | 723 | if (is_loopback) |
724 | add_input_loopback(codec, node->nid, HDA_INPUT, index); | 724 | add_input_loopback(codec, node->nid, HDA_INPUT, index); |
725 | snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index); | 725 | snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index); |
726 | if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0) | 726 | err = snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec)); |
727 | if (err < 0) | ||
727 | return err; | 728 | return err; |
728 | created = 1; | 729 | created = 1; |
729 | } else if ((node->wid_caps & AC_WCAP_OUT_AMP) && | 730 | } else if ((node->wid_caps & AC_WCAP_OUT_AMP) && |
@@ -732,7 +733,8 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node, | |||
732 | if (is_loopback) | 733 | if (is_loopback) |
733 | add_input_loopback(codec, node->nid, HDA_OUTPUT, 0); | 734 | add_input_loopback(codec, node->nid, HDA_OUTPUT, 0); |
734 | snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid); | 735 | snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid); |
735 | if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0) | 736 | err = snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec)); |
737 | if (err < 0) | ||
736 | return err; | 738 | return err; |
737 | created = 1; | 739 | created = 1; |
738 | } | 740 | } |
@@ -745,14 +747,16 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node, | |||
745 | (node->amp_in_caps & AC_AMPCAP_NUM_STEPS)) { | 747 | (node->amp_in_caps & AC_AMPCAP_NUM_STEPS)) { |
746 | knew = (struct snd_kcontrol_new)HDA_CODEC_VOLUME(name, node->nid, index, HDA_INPUT); | 748 | knew = (struct snd_kcontrol_new)HDA_CODEC_VOLUME(name, node->nid, index, HDA_INPUT); |
747 | snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index); | 749 | snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index); |
748 | if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0) | 750 | err = snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec)); |
751 | if (err < 0) | ||
749 | return err; | 752 | return err; |
750 | created = 1; | 753 | created = 1; |
751 | } else if ((node->wid_caps & AC_WCAP_OUT_AMP) && | 754 | } else if ((node->wid_caps & AC_WCAP_OUT_AMP) && |
752 | (node->amp_out_caps & AC_AMPCAP_NUM_STEPS)) { | 755 | (node->amp_out_caps & AC_AMPCAP_NUM_STEPS)) { |
753 | knew = (struct snd_kcontrol_new)HDA_CODEC_VOLUME(name, node->nid, 0, HDA_OUTPUT); | 756 | knew = (struct snd_kcontrol_new)HDA_CODEC_VOLUME(name, node->nid, 0, HDA_OUTPUT); |
754 | snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid); | 757 | snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid); |
755 | if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0) | 758 | err = snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec)); |
759 | if (err < 0) | ||
756 | return err; | 760 | return err; |
757 | created = 1; | 761 | created = 1; |
758 | } | 762 | } |
@@ -849,8 +853,8 @@ static int build_input_controls(struct hda_codec *codec) | |||
849 | } | 853 | } |
850 | 854 | ||
851 | /* create input MUX if multiple sources are available */ | 855 | /* create input MUX if multiple sources are available */ |
852 | if ((err = snd_ctl_add(codec->bus->card, | 856 | err = snd_hda_ctl_add(codec, snd_ctl_new1(&cap_sel, codec)); |
853 | snd_ctl_new1(&cap_sel, codec))) < 0) | 857 | if (err < 0) |
854 | return err; | 858 | return err; |
855 | 859 | ||
856 | /* no volume control? */ | 860 | /* no volume control? */ |
@@ -867,8 +871,8 @@ static int build_input_controls(struct hda_codec *codec) | |||
867 | HDA_CODEC_VOLUME(name, adc_node->nid, | 871 | HDA_CODEC_VOLUME(name, adc_node->nid, |
868 | spec->input_mux.items[i].index, | 872 | spec->input_mux.items[i].index, |
869 | HDA_INPUT); | 873 | HDA_INPUT); |
870 | if ((err = snd_ctl_add(codec->bus->card, | 874 | err = snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec)); |
871 | snd_ctl_new1(&knew, codec))) < 0) | 875 | if (err < 0) |
872 | return err; | 876 | return err; |
873 | } | 877 | } |
874 | 878 | ||
diff --git a/sound/pci/hda/hda_hwdep.c b/sound/pci/hda/hda_hwdep.c index 6e18a422d993..5868bbc131cd 100644 --- a/sound/pci/hda/hda_hwdep.c +++ b/sound/pci/hda/hda_hwdep.c | |||
@@ -23,10 +23,12 @@ | |||
23 | #include <linux/pci.h> | 23 | #include <linux/pci.h> |
24 | #include <linux/compat.h> | 24 | #include <linux/compat.h> |
25 | #include <linux/mutex.h> | 25 | #include <linux/mutex.h> |
26 | #include <linux/ctype.h> | ||
26 | #include <sound/core.h> | 27 | #include <sound/core.h> |
27 | #include "hda_codec.h" | 28 | #include "hda_codec.h" |
28 | #include "hda_local.h" | 29 | #include "hda_local.h" |
29 | #include <sound/hda_hwdep.h> | 30 | #include <sound/hda_hwdep.h> |
31 | #include <sound/minors.h> | ||
30 | 32 | ||
31 | /* | 33 | /* |
32 | * write/read an out-of-bound verb | 34 | * write/read an out-of-bound verb |
@@ -95,6 +97,25 @@ static int hda_hwdep_open(struct snd_hwdep *hw, struct file *file) | |||
95 | return 0; | 97 | return 0; |
96 | } | 98 | } |
97 | 99 | ||
100 | static void clear_hwdep_elements(struct hda_codec *codec) | ||
101 | { | ||
102 | char **head; | ||
103 | int i; | ||
104 | |||
105 | /* clear init verbs */ | ||
106 | snd_array_free(&codec->init_verbs); | ||
107 | /* clear hints */ | ||
108 | head = codec->hints.list; | ||
109 | for (i = 0; i < codec->hints.used; i++, head++) | ||
110 | kfree(*head); | ||
111 | snd_array_free(&codec->hints); | ||
112 | } | ||
113 | |||
114 | static void hwdep_free(struct snd_hwdep *hwdep) | ||
115 | { | ||
116 | clear_hwdep_elements(hwdep->private_data); | ||
117 | } | ||
118 | |||
98 | int __devinit snd_hda_create_hwdep(struct hda_codec *codec) | 119 | int __devinit snd_hda_create_hwdep(struct hda_codec *codec) |
99 | { | 120 | { |
100 | char hwname[16]; | 121 | char hwname[16]; |
@@ -109,6 +130,7 @@ int __devinit snd_hda_create_hwdep(struct hda_codec *codec) | |||
109 | sprintf(hwdep->name, "HDA Codec %d", codec->addr); | 130 | sprintf(hwdep->name, "HDA Codec %d", codec->addr); |
110 | hwdep->iface = SNDRV_HWDEP_IFACE_HDA; | 131 | hwdep->iface = SNDRV_HWDEP_IFACE_HDA; |
111 | hwdep->private_data = codec; | 132 | hwdep->private_data = codec; |
133 | hwdep->private_free = hwdep_free; | ||
112 | hwdep->exclusive = 1; | 134 | hwdep->exclusive = 1; |
113 | 135 | ||
114 | hwdep->ops.open = hda_hwdep_open; | 136 | hwdep->ops.open = hda_hwdep_open; |
@@ -117,5 +139,215 @@ int __devinit snd_hda_create_hwdep(struct hda_codec *codec) | |||
117 | hwdep->ops.ioctl_compat = hda_hwdep_ioctl_compat; | 139 | hwdep->ops.ioctl_compat = hda_hwdep_ioctl_compat; |
118 | #endif | 140 | #endif |
119 | 141 | ||
142 | snd_array_init(&codec->init_verbs, sizeof(struct hda_verb), 32); | ||
143 | snd_array_init(&codec->hints, sizeof(char *), 32); | ||
144 | |||
120 | return 0; | 145 | return 0; |
121 | } | 146 | } |
147 | |||
148 | #ifdef CONFIG_SND_HDA_RECONFIG | ||
149 | |||
150 | /* | ||
151 | * sysfs interface | ||
152 | */ | ||
153 | |||
154 | static int clear_codec(struct hda_codec *codec) | ||
155 | { | ||
156 | snd_hda_codec_reset(codec); | ||
157 | clear_hwdep_elements(codec); | ||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | static int reconfig_codec(struct hda_codec *codec) | ||
162 | { | ||
163 | int err; | ||
164 | |||
165 | snd_printk(KERN_INFO "hda-codec: reconfiguring\n"); | ||
166 | snd_hda_codec_reset(codec); | ||
167 | err = snd_hda_codec_configure(codec); | ||
168 | if (err < 0) | ||
169 | return err; | ||
170 | /* rebuild PCMs */ | ||
171 | err = snd_hda_build_pcms(codec->bus); | ||
172 | if (err < 0) | ||
173 | return err; | ||
174 | /* rebuild mixers */ | ||
175 | err = snd_hda_codec_build_controls(codec); | ||
176 | if (err < 0) | ||
177 | return err; | ||
178 | return 0; | ||
179 | } | ||
180 | |||
181 | /* | ||
182 | * allocate a string at most len chars, and remove the trailing EOL | ||
183 | */ | ||
184 | static char *kstrndup_noeol(const char *src, size_t len) | ||
185 | { | ||
186 | char *s = kstrndup(src, len, GFP_KERNEL); | ||
187 | char *p; | ||
188 | if (!s) | ||
189 | return NULL; | ||
190 | p = strchr(s, '\n'); | ||
191 | if (p) | ||
192 | *p = 0; | ||
193 | return s; | ||
194 | } | ||
195 | |||
196 | #define CODEC_INFO_SHOW(type) \ | ||
197 | static ssize_t type##_show(struct device *dev, \ | ||
198 | struct device_attribute *attr, \ | ||
199 | char *buf) \ | ||
200 | { \ | ||
201 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); \ | ||
202 | struct hda_codec *codec = hwdep->private_data; \ | ||
203 | return sprintf(buf, "0x%x\n", codec->type); \ | ||
204 | } | ||
205 | |||
206 | #define CODEC_INFO_STR_SHOW(type) \ | ||
207 | static ssize_t type##_show(struct device *dev, \ | ||
208 | struct device_attribute *attr, \ | ||
209 | char *buf) \ | ||
210 | { \ | ||
211 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); \ | ||
212 | struct hda_codec *codec = hwdep->private_data; \ | ||
213 | return sprintf(buf, "%s\n", \ | ||
214 | codec->type ? codec->type : ""); \ | ||
215 | } | ||
216 | |||
217 | CODEC_INFO_SHOW(vendor_id); | ||
218 | CODEC_INFO_SHOW(subsystem_id); | ||
219 | CODEC_INFO_SHOW(revision_id); | ||
220 | CODEC_INFO_SHOW(afg); | ||
221 | CODEC_INFO_SHOW(mfg); | ||
222 | CODEC_INFO_STR_SHOW(name); | ||
223 | CODEC_INFO_STR_SHOW(modelname); | ||
224 | |||
225 | #define CODEC_INFO_STORE(type) \ | ||
226 | static ssize_t type##_store(struct device *dev, \ | ||
227 | struct device_attribute *attr, \ | ||
228 | const char *buf, size_t count) \ | ||
229 | { \ | ||
230 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); \ | ||
231 | struct hda_codec *codec = hwdep->private_data; \ | ||
232 | char *after; \ | ||
233 | codec->type = simple_strtoul(buf, &after, 0); \ | ||
234 | return count; \ | ||
235 | } | ||
236 | |||
237 | #define CODEC_INFO_STR_STORE(type) \ | ||
238 | static ssize_t type##_store(struct device *dev, \ | ||
239 | struct device_attribute *attr, \ | ||
240 | const char *buf, size_t count) \ | ||
241 | { \ | ||
242 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); \ | ||
243 | struct hda_codec *codec = hwdep->private_data; \ | ||
244 | char *s = kstrndup_noeol(buf, 64); \ | ||
245 | if (!s) \ | ||
246 | return -ENOMEM; \ | ||
247 | kfree(codec->type); \ | ||
248 | codec->type = s; \ | ||
249 | return count; \ | ||
250 | } | ||
251 | |||
252 | CODEC_INFO_STORE(vendor_id); | ||
253 | CODEC_INFO_STORE(subsystem_id); | ||
254 | CODEC_INFO_STORE(revision_id); | ||
255 | CODEC_INFO_STR_STORE(name); | ||
256 | CODEC_INFO_STR_STORE(modelname); | ||
257 | |||
258 | #define CODEC_ACTION_STORE(type) \ | ||
259 | static ssize_t type##_store(struct device *dev, \ | ||
260 | struct device_attribute *attr, \ | ||
261 | const char *buf, size_t count) \ | ||
262 | { \ | ||
263 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); \ | ||
264 | struct hda_codec *codec = hwdep->private_data; \ | ||
265 | int err = 0; \ | ||
266 | if (*buf) \ | ||
267 | err = type##_codec(codec); \ | ||
268 | return err < 0 ? err : count; \ | ||
269 | } | ||
270 | |||
271 | CODEC_ACTION_STORE(reconfig); | ||
272 | CODEC_ACTION_STORE(clear); | ||
273 | |||
274 | static ssize_t init_verbs_store(struct device *dev, | ||
275 | struct device_attribute *attr, | ||
276 | const char *buf, size_t count) | ||
277 | { | ||
278 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); | ||
279 | struct hda_codec *codec = hwdep->private_data; | ||
280 | char *p; | ||
281 | struct hda_verb verb, *v; | ||
282 | |||
283 | verb.nid = simple_strtoul(buf, &p, 0); | ||
284 | verb.verb = simple_strtoul(p, &p, 0); | ||
285 | verb.param = simple_strtoul(p, &p, 0); | ||
286 | if (!verb.nid || !verb.verb || !verb.param) | ||
287 | return -EINVAL; | ||
288 | v = snd_array_new(&codec->init_verbs); | ||
289 | if (!v) | ||
290 | return -ENOMEM; | ||
291 | *v = verb; | ||
292 | return count; | ||
293 | } | ||
294 | |||
295 | static ssize_t hints_store(struct device *dev, | ||
296 | struct device_attribute *attr, | ||
297 | const char *buf, size_t count) | ||
298 | { | ||
299 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); | ||
300 | struct hda_codec *codec = hwdep->private_data; | ||
301 | char *p; | ||
302 | char **hint; | ||
303 | |||
304 | if (!*buf || isspace(*buf) || *buf == '#' || *buf == '\n') | ||
305 | return count; | ||
306 | p = kstrndup_noeol(buf, 1024); | ||
307 | if (!p) | ||
308 | return -ENOMEM; | ||
309 | hint = snd_array_new(&codec->hints); | ||
310 | if (!hint) { | ||
311 | kfree(p); | ||
312 | return -ENOMEM; | ||
313 | } | ||
314 | *hint = p; | ||
315 | return count; | ||
316 | } | ||
317 | |||
318 | #define CODEC_ATTR_RW(type) \ | ||
319 | __ATTR(type, 0644, type##_show, type##_store) | ||
320 | #define CODEC_ATTR_RO(type) \ | ||
321 | __ATTR_RO(type) | ||
322 | #define CODEC_ATTR_WO(type) \ | ||
323 | __ATTR(type, 0200, NULL, type##_store) | ||
324 | |||
325 | static struct device_attribute codec_attrs[] = { | ||
326 | CODEC_ATTR_RW(vendor_id), | ||
327 | CODEC_ATTR_RW(subsystem_id), | ||
328 | CODEC_ATTR_RW(revision_id), | ||
329 | CODEC_ATTR_RO(afg), | ||
330 | CODEC_ATTR_RO(mfg), | ||
331 | CODEC_ATTR_RW(name), | ||
332 | CODEC_ATTR_RW(modelname), | ||
333 | CODEC_ATTR_WO(init_verbs), | ||
334 | CODEC_ATTR_WO(hints), | ||
335 | CODEC_ATTR_WO(reconfig), | ||
336 | CODEC_ATTR_WO(clear), | ||
337 | }; | ||
338 | |||
339 | /* | ||
340 | * create sysfs files on hwdep directory | ||
341 | */ | ||
342 | int snd_hda_hwdep_add_sysfs(struct hda_codec *codec) | ||
343 | { | ||
344 | struct snd_hwdep *hwdep = codec->hwdep; | ||
345 | int i; | ||
346 | |||
347 | for (i = 0; i < ARRAY_SIZE(codec_attrs); i++) | ||
348 | snd_add_device_sysfs_file(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, | ||
349 | hwdep->device, &codec_attrs[i]); | ||
350 | return 0; | ||
351 | } | ||
352 | |||
353 | #endif /* CONFIG_SND_HDA_RECONFIG */ | ||
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index c04ac38e2b2e..6462d758e641 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -292,6 +292,8 @@ enum { | |||
292 | /* Define VIA HD Audio Device ID*/ | 292 | /* Define VIA HD Audio Device ID*/ |
293 | #define VIA_HDAC_DEVICE_ID 0x3288 | 293 | #define VIA_HDAC_DEVICE_ID 0x3288 |
294 | 294 | ||
295 | /* HD Audio class code */ | ||
296 | #define PCI_CLASS_MULTIMEDIA_HD_AUDIO 0x0403 | ||
295 | 297 | ||
296 | /* | 298 | /* |
297 | */ | 299 | */ |
@@ -392,6 +394,7 @@ struct azx { | |||
392 | unsigned int msi :1; | 394 | unsigned int msi :1; |
393 | unsigned int irq_pending_warned :1; | 395 | unsigned int irq_pending_warned :1; |
394 | unsigned int via_dmapos_patch :1; /* enable DMA-position fix for VIA */ | 396 | unsigned int via_dmapos_patch :1; /* enable DMA-position fix for VIA */ |
397 | unsigned int probing :1; /* codec probing phase */ | ||
395 | 398 | ||
396 | /* for debugging */ | 399 | /* for debugging */ |
397 | unsigned int last_cmd; /* last issued command (to sync) */ | 400 | unsigned int last_cmd; /* last issued command (to sync) */ |
@@ -414,6 +417,7 @@ enum { | |||
414 | AZX_DRIVER_ULI, | 417 | AZX_DRIVER_ULI, |
415 | AZX_DRIVER_NVIDIA, | 418 | AZX_DRIVER_NVIDIA, |
416 | AZX_DRIVER_TERA, | 419 | AZX_DRIVER_TERA, |
420 | AZX_DRIVER_GENERIC, | ||
417 | AZX_NUM_DRIVERS, /* keep this as last entry */ | 421 | AZX_NUM_DRIVERS, /* keep this as last entry */ |
418 | }; | 422 | }; |
419 | 423 | ||
@@ -427,6 +431,7 @@ static char *driver_short_names[] __devinitdata = { | |||
427 | [AZX_DRIVER_ULI] = "HDA ULI M5461", | 431 | [AZX_DRIVER_ULI] = "HDA ULI M5461", |
428 | [AZX_DRIVER_NVIDIA] = "HDA NVidia", | 432 | [AZX_DRIVER_NVIDIA] = "HDA NVidia", |
429 | [AZX_DRIVER_TERA] = "HDA Teradici", | 433 | [AZX_DRIVER_TERA] = "HDA Teradici", |
434 | [AZX_DRIVER_GENERIC] = "HD-Audio Generic", | ||
430 | }; | 435 | }; |
431 | 436 | ||
432 | /* | 437 | /* |
@@ -527,9 +532,9 @@ static void azx_free_cmd_io(struct azx *chip) | |||
527 | } | 532 | } |
528 | 533 | ||
529 | /* send a command */ | 534 | /* send a command */ |
530 | static int azx_corb_send_cmd(struct hda_codec *codec, u32 val) | 535 | static int azx_corb_send_cmd(struct hda_bus *bus, u32 val) |
531 | { | 536 | { |
532 | struct azx *chip = codec->bus->private_data; | 537 | struct azx *chip = bus->private_data; |
533 | unsigned int wp; | 538 | unsigned int wp; |
534 | 539 | ||
535 | /* add command to corb */ | 540 | /* add command to corb */ |
@@ -577,9 +582,9 @@ static void azx_update_rirb(struct azx *chip) | |||
577 | } | 582 | } |
578 | 583 | ||
579 | /* receive a response */ | 584 | /* receive a response */ |
580 | static unsigned int azx_rirb_get_response(struct hda_codec *codec) | 585 | static unsigned int azx_rirb_get_response(struct hda_bus *bus) |
581 | { | 586 | { |
582 | struct azx *chip = codec->bus->private_data; | 587 | struct azx *chip = bus->private_data; |
583 | unsigned long timeout; | 588 | unsigned long timeout; |
584 | 589 | ||
585 | again: | 590 | again: |
@@ -596,7 +601,7 @@ static unsigned int azx_rirb_get_response(struct hda_codec *codec) | |||
596 | } | 601 | } |
597 | if (time_after(jiffies, timeout)) | 602 | if (time_after(jiffies, timeout)) |
598 | break; | 603 | break; |
599 | if (codec->bus->needs_damn_long_delay) | 604 | if (bus->needs_damn_long_delay) |
600 | msleep(2); /* temporary workaround */ | 605 | msleep(2); /* temporary workaround */ |
601 | else { | 606 | else { |
602 | udelay(10); | 607 | udelay(10); |
@@ -624,6 +629,14 @@ static unsigned int azx_rirb_get_response(struct hda_codec *codec) | |||
624 | goto again; | 629 | goto again; |
625 | } | 630 | } |
626 | 631 | ||
632 | if (chip->probing) { | ||
633 | /* If this critical timeout happens during the codec probing | ||
634 | * phase, this is likely an access to a non-existing codec | ||
635 | * slot. Better to return an error and reset the system. | ||
636 | */ | ||
637 | return -1; | ||
638 | } | ||
639 | |||
627 | snd_printk(KERN_ERR "hda_intel: azx_get_response timeout, " | 640 | snd_printk(KERN_ERR "hda_intel: azx_get_response timeout, " |
628 | "switching to single_cmd mode: last cmd=0x%08x\n", | 641 | "switching to single_cmd mode: last cmd=0x%08x\n", |
629 | chip->last_cmd); | 642 | chip->last_cmd); |
@@ -646,9 +659,9 @@ static unsigned int azx_rirb_get_response(struct hda_codec *codec) | |||
646 | */ | 659 | */ |
647 | 660 | ||
648 | /* send a command */ | 661 | /* send a command */ |
649 | static int azx_single_send_cmd(struct hda_codec *codec, u32 val) | 662 | static int azx_single_send_cmd(struct hda_bus *bus, u32 val) |
650 | { | 663 | { |
651 | struct azx *chip = codec->bus->private_data; | 664 | struct azx *chip = bus->private_data; |
652 | int timeout = 50; | 665 | int timeout = 50; |
653 | 666 | ||
654 | while (timeout--) { | 667 | while (timeout--) { |
@@ -671,9 +684,9 @@ static int azx_single_send_cmd(struct hda_codec *codec, u32 val) | |||
671 | } | 684 | } |
672 | 685 | ||
673 | /* receive a response */ | 686 | /* receive a response */ |
674 | static unsigned int azx_single_get_response(struct hda_codec *codec) | 687 | static unsigned int azx_single_get_response(struct hda_bus *bus) |
675 | { | 688 | { |
676 | struct azx *chip = codec->bus->private_data; | 689 | struct azx *chip = bus->private_data; |
677 | int timeout = 50; | 690 | int timeout = 50; |
678 | 691 | ||
679 | while (timeout--) { | 692 | while (timeout--) { |
@@ -696,38 +709,29 @@ static unsigned int azx_single_get_response(struct hda_codec *codec) | |||
696 | */ | 709 | */ |
697 | 710 | ||
698 | /* send a command */ | 711 | /* send a command */ |
699 | static int azx_send_cmd(struct hda_codec *codec, hda_nid_t nid, | 712 | static int azx_send_cmd(struct hda_bus *bus, unsigned int val) |
700 | int direct, unsigned int verb, | ||
701 | unsigned int para) | ||
702 | { | 713 | { |
703 | struct azx *chip = codec->bus->private_data; | 714 | struct azx *chip = bus->private_data; |
704 | u32 val; | ||
705 | |||
706 | val = (u32)(codec->addr & 0x0f) << 28; | ||
707 | val |= (u32)direct << 27; | ||
708 | val |= (u32)nid << 20; | ||
709 | val |= verb << 8; | ||
710 | val |= para; | ||
711 | chip->last_cmd = val; | ||
712 | 715 | ||
716 | chip->last_cmd = val; | ||
713 | if (chip->single_cmd) | 717 | if (chip->single_cmd) |
714 | return azx_single_send_cmd(codec, val); | 718 | return azx_single_send_cmd(bus, val); |
715 | else | 719 | else |
716 | return azx_corb_send_cmd(codec, val); | 720 | return azx_corb_send_cmd(bus, val); |
717 | } | 721 | } |
718 | 722 | ||
719 | /* get a response */ | 723 | /* get a response */ |
720 | static unsigned int azx_get_response(struct hda_codec *codec) | 724 | static unsigned int azx_get_response(struct hda_bus *bus) |
721 | { | 725 | { |
722 | struct azx *chip = codec->bus->private_data; | 726 | struct azx *chip = bus->private_data; |
723 | if (chip->single_cmd) | 727 | if (chip->single_cmd) |
724 | return azx_single_get_response(codec); | 728 | return azx_single_get_response(bus); |
725 | else | 729 | else |
726 | return azx_rirb_get_response(codec); | 730 | return azx_rirb_get_response(bus); |
727 | } | 731 | } |
728 | 732 | ||
729 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 733 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
730 | static void azx_power_notify(struct hda_codec *codec); | 734 | static void azx_power_notify(struct hda_bus *bus); |
731 | #endif | 735 | #endif |
732 | 736 | ||
733 | /* reset codec link */ | 737 | /* reset codec link */ |
@@ -1184,6 +1188,28 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) | |||
1184 | return 0; | 1188 | return 0; |
1185 | } | 1189 | } |
1186 | 1190 | ||
1191 | /* | ||
1192 | * Probe the given codec address | ||
1193 | */ | ||
1194 | static int probe_codec(struct azx *chip, int addr) | ||
1195 | { | ||
1196 | unsigned int cmd = (addr << 28) | (AC_NODE_ROOT << 20) | | ||
1197 | (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID; | ||
1198 | unsigned int res; | ||
1199 | |||
1200 | chip->probing = 1; | ||
1201 | azx_send_cmd(chip->bus, cmd); | ||
1202 | res = azx_get_response(chip->bus); | ||
1203 | chip->probing = 0; | ||
1204 | if (res == -1) | ||
1205 | return -EIO; | ||
1206 | snd_printdd("hda_intel: codec #%d probed OK\n", addr); | ||
1207 | return 0; | ||
1208 | } | ||
1209 | |||
1210 | static int azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec, | ||
1211 | struct hda_pcm *cpcm); | ||
1212 | static void azx_stop_chip(struct azx *chip); | ||
1187 | 1213 | ||
1188 | /* | 1214 | /* |
1189 | * Codec initialization | 1215 | * Codec initialization |
@@ -1194,21 +1220,12 @@ static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] __devinitdata = { | |||
1194 | [AZX_DRIVER_TERA] = 1, | 1220 | [AZX_DRIVER_TERA] = 1, |
1195 | }; | 1221 | }; |
1196 | 1222 | ||
1197 | /* number of slots to probe as default | ||
1198 | * this can be different from azx_max_codecs[] -- e.g. some boards | ||
1199 | * report wrongly the non-existing 4th slot availability | ||
1200 | */ | ||
1201 | static unsigned int azx_default_codecs[AZX_NUM_DRIVERS] __devinitdata = { | ||
1202 | [AZX_DRIVER_ICH] = 3, | ||
1203 | [AZX_DRIVER_ATI] = 3, | ||
1204 | }; | ||
1205 | |||
1206 | static int __devinit azx_codec_create(struct azx *chip, const char *model, | 1223 | static int __devinit azx_codec_create(struct azx *chip, const char *model, |
1207 | unsigned int codec_probe_mask) | 1224 | unsigned int codec_probe_mask) |
1208 | { | 1225 | { |
1209 | struct hda_bus_template bus_temp; | 1226 | struct hda_bus_template bus_temp; |
1210 | int c, codecs, audio_codecs, err; | 1227 | int c, codecs, err; |
1211 | int def_slots, max_slots; | 1228 | int max_slots; |
1212 | 1229 | ||
1213 | memset(&bus_temp, 0, sizeof(bus_temp)); | 1230 | memset(&bus_temp, 0, sizeof(bus_temp)); |
1214 | bus_temp.private_data = chip; | 1231 | bus_temp.private_data = chip; |
@@ -1216,6 +1233,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model, | |||
1216 | bus_temp.pci = chip->pci; | 1233 | bus_temp.pci = chip->pci; |
1217 | bus_temp.ops.command = azx_send_cmd; | 1234 | bus_temp.ops.command = azx_send_cmd; |
1218 | bus_temp.ops.get_response = azx_get_response; | 1235 | bus_temp.ops.get_response = azx_get_response; |
1236 | bus_temp.ops.attach_pcm = azx_attach_pcm_stream; | ||
1219 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 1237 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
1220 | bus_temp.ops.pm_notify = azx_power_notify; | 1238 | bus_temp.ops.pm_notify = azx_power_notify; |
1221 | #endif | 1239 | #endif |
@@ -1227,33 +1245,43 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model, | |||
1227 | if (chip->driver_type == AZX_DRIVER_NVIDIA) | 1245 | if (chip->driver_type == AZX_DRIVER_NVIDIA) |
1228 | chip->bus->needs_damn_long_delay = 1; | 1246 | chip->bus->needs_damn_long_delay = 1; |
1229 | 1247 | ||
1230 | codecs = audio_codecs = 0; | 1248 | codecs = 0; |
1231 | max_slots = azx_max_codecs[chip->driver_type]; | 1249 | max_slots = azx_max_codecs[chip->driver_type]; |
1232 | if (!max_slots) | 1250 | if (!max_slots) |
1233 | max_slots = AZX_MAX_CODECS; | 1251 | max_slots = AZX_MAX_CODECS; |
1234 | def_slots = azx_default_codecs[chip->driver_type]; | 1252 | |
1235 | if (!def_slots) | 1253 | /* First try to probe all given codec slots */ |
1236 | def_slots = max_slots; | 1254 | for (c = 0; c < max_slots; c++) { |
1237 | for (c = 0; c < def_slots; c++) { | 1255 | if ((chip->codec_mask & (1 << c)) & codec_probe_mask) { |
1256 | if (probe_codec(chip, c) < 0) { | ||
1257 | /* Some BIOSen give you wrong codec addresses | ||
1258 | * that don't exist | ||
1259 | */ | ||
1260 | snd_printk(KERN_WARNING | ||
1261 | "hda_intel: Codec #%d probe error; " | ||
1262 | "disabling it...\n", c); | ||
1263 | chip->codec_mask &= ~(1 << c); | ||
1264 | /* More badly, accessing to a non-existing | ||
1265 | * codec often screws up the controller chip, | ||
1266 | * and distrubs the further communications. | ||
1267 | * Thus if an error occurs during probing, | ||
1268 | * better to reset the controller chip to | ||
1269 | * get back to the sanity state. | ||
1270 | */ | ||
1271 | azx_stop_chip(chip); | ||
1272 | azx_init_chip(chip); | ||
1273 | } | ||
1274 | } | ||
1275 | } | ||
1276 | |||
1277 | /* Then create codec instances */ | ||
1278 | for (c = 0; c < max_slots; c++) { | ||
1238 | if ((chip->codec_mask & (1 << c)) & codec_probe_mask) { | 1279 | if ((chip->codec_mask & (1 << c)) & codec_probe_mask) { |
1239 | struct hda_codec *codec; | 1280 | struct hda_codec *codec; |
1240 | err = snd_hda_codec_new(chip->bus, c, &codec); | 1281 | err = snd_hda_codec_new(chip->bus, c, &codec); |
1241 | if (err < 0) | 1282 | if (err < 0) |
1242 | continue; | 1283 | continue; |
1243 | codecs++; | 1284 | codecs++; |
1244 | if (codec->afg) | ||
1245 | audio_codecs++; | ||
1246 | } | ||
1247 | } | ||
1248 | if (!audio_codecs) { | ||
1249 | /* probe additional slots if no codec is found */ | ||
1250 | for (; c < max_slots; c++) { | ||
1251 | if ((chip->codec_mask & (1 << c)) & codec_probe_mask) { | ||
1252 | err = snd_hda_codec_new(chip->bus, c, NULL); | ||
1253 | if (err < 0) | ||
1254 | continue; | ||
1255 | codecs++; | ||
1256 | } | ||
1257 | } | 1285 | } |
1258 | } | 1286 | } |
1259 | if (!codecs) { | 1287 | if (!codecs) { |
@@ -1722,111 +1750,59 @@ static struct snd_pcm_ops azx_pcm_ops = { | |||
1722 | 1750 | ||
1723 | static void azx_pcm_free(struct snd_pcm *pcm) | 1751 | static void azx_pcm_free(struct snd_pcm *pcm) |
1724 | { | 1752 | { |
1725 | kfree(pcm->private_data); | 1753 | struct azx_pcm *apcm = pcm->private_data; |
1754 | if (apcm) { | ||
1755 | apcm->chip->pcm[pcm->device] = NULL; | ||
1756 | kfree(apcm); | ||
1757 | } | ||
1726 | } | 1758 | } |
1727 | 1759 | ||
1728 | static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec, | 1760 | static int |
1729 | struct hda_pcm *cpcm) | 1761 | azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec, |
1762 | struct hda_pcm *cpcm) | ||
1730 | { | 1763 | { |
1731 | int err; | 1764 | struct azx *chip = bus->private_data; |
1732 | struct snd_pcm *pcm; | 1765 | struct snd_pcm *pcm; |
1733 | struct azx_pcm *apcm; | 1766 | struct azx_pcm *apcm; |
1767 | int pcm_dev = cpcm->device; | ||
1768 | int s, err; | ||
1734 | 1769 | ||
1735 | /* if no substreams are defined for both playback and capture, | 1770 | if (pcm_dev >= AZX_MAX_PCMS) { |
1736 | * it's just a placeholder. ignore it. | 1771 | snd_printk(KERN_ERR SFX "Invalid PCM device number %d\n", |
1737 | */ | 1772 | pcm_dev); |
1738 | if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams) | ||
1739 | return 0; | ||
1740 | |||
1741 | if (snd_BUG_ON(!cpcm->name)) | ||
1742 | return -EINVAL; | 1773 | return -EINVAL; |
1743 | 1774 | } | |
1744 | err = snd_pcm_new(chip->card, cpcm->name, cpcm->device, | 1775 | if (chip->pcm[pcm_dev]) { |
1745 | cpcm->stream[0].substreams, | 1776 | snd_printk(KERN_ERR SFX "PCM %d already exists\n", pcm_dev); |
1746 | cpcm->stream[1].substreams, | 1777 | return -EBUSY; |
1778 | } | ||
1779 | err = snd_pcm_new(chip->card, cpcm->name, pcm_dev, | ||
1780 | cpcm->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams, | ||
1781 | cpcm->stream[SNDRV_PCM_STREAM_CAPTURE].substreams, | ||
1747 | &pcm); | 1782 | &pcm); |
1748 | if (err < 0) | 1783 | if (err < 0) |
1749 | return err; | 1784 | return err; |
1750 | strcpy(pcm->name, cpcm->name); | 1785 | strcpy(pcm->name, cpcm->name); |
1751 | apcm = kmalloc(sizeof(*apcm), GFP_KERNEL); | 1786 | apcm = kzalloc(sizeof(*apcm), GFP_KERNEL); |
1752 | if (apcm == NULL) | 1787 | if (apcm == NULL) |
1753 | return -ENOMEM; | 1788 | return -ENOMEM; |
1754 | apcm->chip = chip; | 1789 | apcm->chip = chip; |
1755 | apcm->codec = codec; | 1790 | apcm->codec = codec; |
1756 | apcm->hinfo[0] = &cpcm->stream[0]; | ||
1757 | apcm->hinfo[1] = &cpcm->stream[1]; | ||
1758 | pcm->private_data = apcm; | 1791 | pcm->private_data = apcm; |
1759 | pcm->private_free = azx_pcm_free; | 1792 | pcm->private_free = azx_pcm_free; |
1760 | if (cpcm->stream[0].substreams) | 1793 | if (cpcm->pcm_type == HDA_PCM_TYPE_MODEM) |
1761 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &azx_pcm_ops); | 1794 | pcm->dev_class = SNDRV_PCM_CLASS_MODEM; |
1762 | if (cpcm->stream[1].substreams) | 1795 | chip->pcm[pcm_dev] = pcm; |
1763 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &azx_pcm_ops); | 1796 | cpcm->pcm = pcm; |
1797 | for (s = 0; s < 2; s++) { | ||
1798 | apcm->hinfo[s] = &cpcm->stream[s]; | ||
1799 | if (cpcm->stream[s].substreams) | ||
1800 | snd_pcm_set_ops(pcm, s, &azx_pcm_ops); | ||
1801 | } | ||
1802 | /* buffer pre-allocation */ | ||
1764 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, | 1803 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, |
1765 | snd_dma_pci_data(chip->pci), | 1804 | snd_dma_pci_data(chip->pci), |
1766 | 1024 * 64, 32 * 1024 * 1024); | 1805 | 1024 * 64, 32 * 1024 * 1024); |
1767 | chip->pcm[cpcm->device] = pcm; | ||
1768 | return 0; | ||
1769 | } | ||
1770 | |||
1771 | static int __devinit azx_pcm_create(struct azx *chip) | ||
1772 | { | ||
1773 | static const char *dev_name[HDA_PCM_NTYPES] = { | ||
1774 | "Audio", "SPDIF", "HDMI", "Modem" | ||
1775 | }; | ||
1776 | /* starting device index for each PCM type */ | ||
1777 | static int dev_idx[HDA_PCM_NTYPES] = { | ||
1778 | [HDA_PCM_TYPE_AUDIO] = 0, | ||
1779 | [HDA_PCM_TYPE_SPDIF] = 1, | ||
1780 | [HDA_PCM_TYPE_HDMI] = 3, | ||
1781 | [HDA_PCM_TYPE_MODEM] = 6 | ||
1782 | }; | ||
1783 | /* normal audio device indices; not linear to keep compatibility */ | ||
1784 | static int audio_idx[4] = { 0, 2, 4, 5 }; | ||
1785 | struct hda_codec *codec; | ||
1786 | int c, err; | ||
1787 | int num_devs[HDA_PCM_NTYPES]; | ||
1788 | |||
1789 | err = snd_hda_build_pcms(chip->bus); | ||
1790 | if (err < 0) | ||
1791 | return err; | ||
1792 | |||
1793 | /* create audio PCMs */ | ||
1794 | memset(num_devs, 0, sizeof(num_devs)); | ||
1795 | list_for_each_entry(codec, &chip->bus->codec_list, list) { | ||
1796 | for (c = 0; c < codec->num_pcms; c++) { | ||
1797 | struct hda_pcm *cpcm = &codec->pcm_info[c]; | ||
1798 | int type = cpcm->pcm_type; | ||
1799 | switch (type) { | ||
1800 | case HDA_PCM_TYPE_AUDIO: | ||
1801 | if (num_devs[type] >= ARRAY_SIZE(audio_idx)) { | ||
1802 | snd_printk(KERN_WARNING | ||
1803 | "Too many audio devices\n"); | ||
1804 | continue; | ||
1805 | } | ||
1806 | cpcm->device = audio_idx[num_devs[type]]; | ||
1807 | break; | ||
1808 | case HDA_PCM_TYPE_SPDIF: | ||
1809 | case HDA_PCM_TYPE_HDMI: | ||
1810 | case HDA_PCM_TYPE_MODEM: | ||
1811 | if (num_devs[type]) { | ||
1812 | snd_printk(KERN_WARNING | ||
1813 | "%s already defined\n", | ||
1814 | dev_name[type]); | ||
1815 | continue; | ||
1816 | } | ||
1817 | cpcm->device = dev_idx[type]; | ||
1818 | break; | ||
1819 | default: | ||
1820 | snd_printk(KERN_WARNING | ||
1821 | "Invalid PCM type %d\n", type); | ||
1822 | continue; | ||
1823 | } | ||
1824 | num_devs[type]++; | ||
1825 | err = create_codec_pcm(chip, codec, cpcm); | ||
1826 | if (err < 0) | ||
1827 | return err; | ||
1828 | } | ||
1829 | } | ||
1830 | return 0; | 1806 | return 0; |
1831 | } | 1807 | } |
1832 | 1808 | ||
@@ -1903,13 +1879,13 @@ static void azx_stop_chip(struct azx *chip) | |||
1903 | 1879 | ||
1904 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 1880 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
1905 | /* power-up/down the controller */ | 1881 | /* power-up/down the controller */ |
1906 | static void azx_power_notify(struct hda_codec *codec) | 1882 | static void azx_power_notify(struct hda_bus *bus) |
1907 | { | 1883 | { |
1908 | struct azx *chip = codec->bus->private_data; | 1884 | struct azx *chip = bus->private_data; |
1909 | struct hda_codec *c; | 1885 | struct hda_codec *c; |
1910 | int power_on = 0; | 1886 | int power_on = 0; |
1911 | 1887 | ||
1912 | list_for_each_entry(c, &codec->bus->codec_list, list) { | 1888 | list_for_each_entry(c, &bus->codec_list, list) { |
1913 | if (c->power_on) { | 1889 | if (c->power_on) { |
1914 | power_on = 1; | 1890 | power_on = 1; |
1915 | break; | 1891 | break; |
@@ -2095,6 +2071,10 @@ static struct snd_pci_quirk probe_mask_list[] __devinitdata = { | |||
2095 | SND_PCI_QUIRK(0x1014, 0x05b7, "Thinkpad Z60", 0x01), | 2071 | SND_PCI_QUIRK(0x1014, 0x05b7, "Thinkpad Z60", 0x01), |
2096 | SND_PCI_QUIRK(0x17aa, 0x2010, "Thinkpad X/T/R60", 0x01), | 2072 | SND_PCI_QUIRK(0x17aa, 0x2010, "Thinkpad X/T/R60", 0x01), |
2097 | SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X/T/R61", 0x01), | 2073 | SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X/T/R61", 0x01), |
2074 | /* broken BIOS */ | ||
2075 | SND_PCI_QUIRK(0x1028, 0x20ac, "Dell Studio Desktop", 0x01), | ||
2076 | /* including bogus ALC268 in slot#2 that conflicts with ALC888 */ | ||
2077 | SND_PCI_QUIRK(0x17c0, 0x4085, "Medion MD96630", 0x01), | ||
2098 | {} | 2078 | {} |
2099 | }; | 2079 | }; |
2100 | 2080 | ||
@@ -2229,6 +2209,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
2229 | chip->playback_streams = ATIHDMI_NUM_PLAYBACK; | 2209 | chip->playback_streams = ATIHDMI_NUM_PLAYBACK; |
2230 | chip->capture_streams = ATIHDMI_NUM_CAPTURE; | 2210 | chip->capture_streams = ATIHDMI_NUM_CAPTURE; |
2231 | break; | 2211 | break; |
2212 | case AZX_DRIVER_GENERIC: | ||
2232 | default: | 2213 | default: |
2233 | chip->playback_streams = ICH6_NUM_PLAYBACK; | 2214 | chip->playback_streams = ICH6_NUM_PLAYBACK; |
2234 | chip->capture_streams = ICH6_NUM_CAPTURE; | 2215 | chip->capture_streams = ICH6_NUM_CAPTURE; |
@@ -2338,40 +2319,30 @@ static int __devinit azx_probe(struct pci_dev *pci, | |||
2338 | } | 2319 | } |
2339 | 2320 | ||
2340 | err = azx_create(card, pci, dev, pci_id->driver_data, &chip); | 2321 | err = azx_create(card, pci, dev, pci_id->driver_data, &chip); |
2341 | if (err < 0) { | 2322 | if (err < 0) |
2342 | snd_card_free(card); | 2323 | goto out_free; |
2343 | return err; | ||
2344 | } | ||
2345 | card->private_data = chip; | 2324 | card->private_data = chip; |
2346 | 2325 | ||
2347 | /* create codec instances */ | 2326 | /* create codec instances */ |
2348 | err = azx_codec_create(chip, model[dev], probe_mask[dev]); | 2327 | err = azx_codec_create(chip, model[dev], probe_mask[dev]); |
2349 | if (err < 0) { | 2328 | if (err < 0) |
2350 | snd_card_free(card); | 2329 | goto out_free; |
2351 | return err; | ||
2352 | } | ||
2353 | 2330 | ||
2354 | /* create PCM streams */ | 2331 | /* create PCM streams */ |
2355 | err = azx_pcm_create(chip); | 2332 | err = snd_hda_build_pcms(chip->bus); |
2356 | if (err < 0) { | 2333 | if (err < 0) |
2357 | snd_card_free(card); | 2334 | goto out_free; |
2358 | return err; | ||
2359 | } | ||
2360 | 2335 | ||
2361 | /* create mixer controls */ | 2336 | /* create mixer controls */ |
2362 | err = azx_mixer_create(chip); | 2337 | err = azx_mixer_create(chip); |
2363 | if (err < 0) { | 2338 | if (err < 0) |
2364 | snd_card_free(card); | 2339 | goto out_free; |
2365 | return err; | ||
2366 | } | ||
2367 | 2340 | ||
2368 | snd_card_set_dev(card, &pci->dev); | 2341 | snd_card_set_dev(card, &pci->dev); |
2369 | 2342 | ||
2370 | err = snd_card_register(card); | 2343 | err = snd_card_register(card); |
2371 | if (err < 0) { | 2344 | if (err < 0) |
2372 | snd_card_free(card); | 2345 | goto out_free; |
2373 | return err; | ||
2374 | } | ||
2375 | 2346 | ||
2376 | pci_set_drvdata(pci, card); | 2347 | pci_set_drvdata(pci, card); |
2377 | chip->running = 1; | 2348 | chip->running = 1; |
@@ -2380,6 +2351,9 @@ static int __devinit azx_probe(struct pci_dev *pci, | |||
2380 | 2351 | ||
2381 | dev++; | 2352 | dev++; |
2382 | return err; | 2353 | return err; |
2354 | out_free: | ||
2355 | snd_card_free(card); | ||
2356 | return err; | ||
2383 | } | 2357 | } |
2384 | 2358 | ||
2385 | static void __devexit azx_remove(struct pci_dev *pci) | 2359 | static void __devexit azx_remove(struct pci_dev *pci) |
@@ -2453,6 +2427,11 @@ static struct pci_device_id azx_ids[] = { | |||
2453 | { PCI_DEVICE(0x10de, 0x0bd7), .driver_data = AZX_DRIVER_NVIDIA }, | 2427 | { PCI_DEVICE(0x10de, 0x0bd7), .driver_data = AZX_DRIVER_NVIDIA }, |
2454 | /* Teradici */ | 2428 | /* Teradici */ |
2455 | { PCI_DEVICE(0x6549, 0x1200), .driver_data = AZX_DRIVER_TERA }, | 2429 | { PCI_DEVICE(0x6549, 0x1200), .driver_data = AZX_DRIVER_TERA }, |
2430 | /* AMD Generic, PCI class code and Vendor ID for HD Audio */ | ||
2431 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_ANY_ID), | ||
2432 | .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, | ||
2433 | .class_mask = 0xffffff, | ||
2434 | .driver_data = AZX_DRIVER_GENERIC }, | ||
2456 | { 0, } | 2435 | { 0, } |
2457 | }; | 2436 | }; |
2458 | MODULE_DEVICE_TABLE(pci, azx_ids); | 2437 | MODULE_DEVICE_TABLE(pci, azx_ids); |
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 7957fefda730..6f2fe0f9fdd8 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -96,6 +96,8 @@ struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, | |||
96 | const char *name); | 96 | const char *name); |
97 | int snd_hda_add_vmaster(struct hda_codec *codec, char *name, | 97 | int snd_hda_add_vmaster(struct hda_codec *codec, char *name, |
98 | unsigned int *tlv, const char **slaves); | 98 | unsigned int *tlv, const char **slaves); |
99 | void snd_hda_codec_reset(struct hda_codec *codec); | ||
100 | int snd_hda_codec_configure(struct hda_codec *codec); | ||
99 | 101 | ||
100 | /* amp value bits */ | 102 | /* amp value bits */ |
101 | #define HDA_AMP_MUTE 0x80 | 103 | #define HDA_AMP_MUTE 0x80 |
@@ -282,6 +284,12 @@ int snd_hda_codec_proc_new(struct hda_codec *codec); | |||
282 | static inline int snd_hda_codec_proc_new(struct hda_codec *codec) { return 0; } | 284 | static inline int snd_hda_codec_proc_new(struct hda_codec *codec) { return 0; } |
283 | #endif | 285 | #endif |
284 | 286 | ||
287 | #define SND_PRINT_RATES_ADVISED_BUFSIZE 80 | ||
288 | void snd_print_pcm_rates(int pcm, char *buf, int buflen); | ||
289 | |||
290 | #define SND_PRINT_BITS_ADVISED_BUFSIZE 16 | ||
291 | void snd_print_pcm_bits(int pcm, char *buf, int buflen); | ||
292 | |||
285 | /* | 293 | /* |
286 | * Misc | 294 | * Misc |
287 | */ | 295 | */ |
@@ -364,17 +372,17 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
364 | /* amp values */ | 372 | /* amp values */ |
365 | #define AMP_IN_MUTE(idx) (0x7080 | ((idx)<<8)) | 373 | #define AMP_IN_MUTE(idx) (0x7080 | ((idx)<<8)) |
366 | #define AMP_IN_UNMUTE(idx) (0x7000 | ((idx)<<8)) | 374 | #define AMP_IN_UNMUTE(idx) (0x7000 | ((idx)<<8)) |
367 | #define AMP_OUT_MUTE 0xb080 | 375 | #define AMP_OUT_MUTE 0xb080 |
368 | #define AMP_OUT_UNMUTE 0xb000 | 376 | #define AMP_OUT_UNMUTE 0xb000 |
369 | #define AMP_OUT_ZERO 0xb000 | 377 | #define AMP_OUT_ZERO 0xb000 |
370 | /* pinctl values */ | 378 | /* pinctl values */ |
371 | #define PIN_IN (AC_PINCTL_IN_EN) | 379 | #define PIN_IN (AC_PINCTL_IN_EN) |
372 | #define PIN_VREFHIZ (AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ) | 380 | #define PIN_VREFHIZ (AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ) |
373 | #define PIN_VREF50 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_50) | 381 | #define PIN_VREF50 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_50) |
374 | #define PIN_VREFGRD (AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD) | 382 | #define PIN_VREFGRD (AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD) |
375 | #define PIN_VREF80 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_80) | 383 | #define PIN_VREF80 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_80) |
376 | #define PIN_VREF100 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_100) | 384 | #define PIN_VREF100 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_100) |
377 | #define PIN_OUT (AC_PINCTL_OUT_EN) | 385 | #define PIN_OUT (AC_PINCTL_OUT_EN) |
378 | #define PIN_HP (AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN) | 386 | #define PIN_HP (AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN) |
379 | #define PIN_HP_AMP (AC_PINCTL_HP_EN) | 387 | #define PIN_HP_AMP (AC_PINCTL_HP_EN) |
380 | 388 | ||
@@ -393,10 +401,26 @@ u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction); | |||
393 | int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, | 401 | int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, |
394 | unsigned int caps); | 402 | unsigned int caps); |
395 | 403 | ||
404 | int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl); | ||
405 | void snd_hda_ctls_clear(struct hda_codec *codec); | ||
406 | |||
396 | /* | 407 | /* |
397 | * hwdep interface | 408 | * hwdep interface |
398 | */ | 409 | */ |
410 | #ifdef CONFIG_SND_HDA_HWDEP | ||
399 | int snd_hda_create_hwdep(struct hda_codec *codec); | 411 | int snd_hda_create_hwdep(struct hda_codec *codec); |
412 | #else | ||
413 | static inline int snd_hda_create_hwdep(struct hda_codec *codec) { return 0; } | ||
414 | #endif | ||
415 | |||
416 | #ifdef CONFIG_SND_HDA_RECONFIG | ||
417 | int snd_hda_hwdep_add_sysfs(struct hda_codec *codec); | ||
418 | #else | ||
419 | static inline int snd_hda_hwdep_add_sysfs(struct hda_codec *codec) | ||
420 | { | ||
421 | return 0; | ||
422 | } | ||
423 | #endif | ||
400 | 424 | ||
401 | /* | 425 | /* |
402 | * power-management | 426 | * power-management |
@@ -430,4 +454,66 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec, | |||
430 | #define get_amp_direction(kc) (((kc)->private_value >> 18) & 0x1) | 454 | #define get_amp_direction(kc) (((kc)->private_value >> 18) & 0x1) |
431 | #define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf) | 455 | #define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf) |
432 | 456 | ||
457 | /* | ||
458 | * CEA Short Audio Descriptor data | ||
459 | */ | ||
460 | struct cea_sad { | ||
461 | int channels; | ||
462 | int format; /* (format == 0) indicates invalid SAD */ | ||
463 | int rates; | ||
464 | int sample_bits; /* for LPCM */ | ||
465 | int max_bitrate; /* for AC3...ATRAC */ | ||
466 | int profile; /* for WMAPRO */ | ||
467 | }; | ||
468 | |||
469 | #define ELD_FIXED_BYTES 20 | ||
470 | #define ELD_MAX_MNL 16 | ||
471 | #define ELD_MAX_SAD 16 | ||
472 | |||
473 | /* | ||
474 | * ELD: EDID Like Data | ||
475 | */ | ||
476 | struct hdmi_eld { | ||
477 | int eld_size; | ||
478 | int baseline_len; | ||
479 | int eld_ver; /* (eld_ver == 0) indicates invalid ELD */ | ||
480 | int cea_edid_ver; | ||
481 | char monitor_name[ELD_MAX_MNL + 1]; | ||
482 | int manufacture_id; | ||
483 | int product_id; | ||
484 | u64 port_id; | ||
485 | int support_hdcp; | ||
486 | int support_ai; | ||
487 | int conn_type; | ||
488 | int aud_synch_delay; | ||
489 | int spk_alloc; | ||
490 | int sad_count; | ||
491 | struct cea_sad sad[ELD_MAX_SAD]; | ||
492 | #ifdef CONFIG_PROC_FS | ||
493 | struct snd_info_entry *proc_entry; | ||
494 | #endif | ||
495 | }; | ||
496 | |||
497 | int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid); | ||
498 | int snd_hdmi_get_eld(struct hdmi_eld *, struct hda_codec *, hda_nid_t); | ||
499 | void snd_hdmi_show_eld(struct hdmi_eld *eld); | ||
500 | |||
501 | #ifdef CONFIG_PROC_FS | ||
502 | int snd_hda_eld_proc_new(struct hda_codec *codec, struct hdmi_eld *eld); | ||
503 | void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld); | ||
504 | #else | ||
505 | static inline int snd_hda_eld_proc_new(struct hda_codec *codec, | ||
506 | struct hdmi_eld *eld) | ||
507 | { | ||
508 | return 0; | ||
509 | } | ||
510 | static inline void snd_hda_eld_proc_free(struct hda_codec *codec, | ||
511 | struct hdmi_eld *eld) | ||
512 | { | ||
513 | } | ||
514 | #endif | ||
515 | |||
516 | #define SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE 80 | ||
517 | void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen); | ||
518 | |||
433 | #endif /* __SOUND_HDA_LOCAL_H */ | 519 | #endif /* __SOUND_HDA_LOCAL_H */ |
diff --git a/sound/pci/hda/hda_patch.h b/sound/pci/hda/hda_patch.h index dfbcfa88da44..38212c1020a6 100644 --- a/sound/pci/hda/hda_patch.h +++ b/sound/pci/hda/hda_patch.h | |||
@@ -20,3 +20,5 @@ extern struct hda_codec_preset snd_hda_preset_conexant[]; | |||
20 | extern struct hda_codec_preset snd_hda_preset_via[]; | 20 | extern struct hda_codec_preset snd_hda_preset_via[]; |
21 | /* NVIDIA HDMI codecs */ | 21 | /* NVIDIA HDMI codecs */ |
22 | extern struct hda_codec_preset snd_hda_preset_nvhdmi[]; | 22 | extern struct hda_codec_preset snd_hda_preset_nvhdmi[]; |
23 | /* INTEL HDMI codecs */ | ||
24 | extern struct hda_codec_preset snd_hda_preset_intelhdmi[]; | ||
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index c39af986bff1..a2eba4f17e9c 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c | |||
@@ -91,31 +91,21 @@ static void print_amp_vals(struct snd_info_buffer *buffer, | |||
91 | 91 | ||
92 | static void print_pcm_rates(struct snd_info_buffer *buffer, unsigned int pcm) | 92 | static void print_pcm_rates(struct snd_info_buffer *buffer, unsigned int pcm) |
93 | { | 93 | { |
94 | static unsigned int rates[] = { | 94 | char buf[SND_PRINT_RATES_ADVISED_BUFSIZE]; |
95 | 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200, | ||
96 | 96000, 176400, 192000, 384000 | ||
97 | }; | ||
98 | int i; | ||
99 | 95 | ||
100 | pcm &= AC_SUPPCM_RATES; | 96 | pcm &= AC_SUPPCM_RATES; |
101 | snd_iprintf(buffer, " rates [0x%x]:", pcm); | 97 | snd_iprintf(buffer, " rates [0x%x]:", pcm); |
102 | for (i = 0; i < ARRAY_SIZE(rates); i++) | 98 | snd_print_pcm_rates(pcm, buf, sizeof(buf)); |
103 | if (pcm & (1 << i)) | 99 | snd_iprintf(buffer, "%s\n", buf); |
104 | snd_iprintf(buffer, " %d", rates[i]); | ||
105 | snd_iprintf(buffer, "\n"); | ||
106 | } | 100 | } |
107 | 101 | ||
108 | static void print_pcm_bits(struct snd_info_buffer *buffer, unsigned int pcm) | 102 | static void print_pcm_bits(struct snd_info_buffer *buffer, unsigned int pcm) |
109 | { | 103 | { |
110 | static unsigned int bits[] = { 8, 16, 20, 24, 32 }; | 104 | char buf[SND_PRINT_BITS_ADVISED_BUFSIZE]; |
111 | int i; | ||
112 | 105 | ||
113 | pcm = (pcm >> 16) & 0xff; | 106 | snd_iprintf(buffer, " bits [0x%x]:", (pcm & AC_SUPPCM_RATES) >> 16); |
114 | snd_iprintf(buffer, " bits [0x%x]:", pcm); | 107 | snd_print_pcm_bits(pcm, buf, sizeof(buf)); |
115 | for (i = 0; i < ARRAY_SIZE(bits); i++) | 108 | snd_iprintf(buffer, "%s\n", buf); |
116 | if (pcm & (1 << i)) | ||
117 | snd_iprintf(buffer, " %d", bits[i]); | ||
118 | snd_iprintf(buffer, "\n"); | ||
119 | } | 109 | } |
120 | 110 | ||
121 | static void print_pcm_formats(struct snd_info_buffer *buffer, | 111 | static void print_pcm_formats(struct snd_info_buffer *buffer, |
@@ -145,32 +135,6 @@ static void print_pcm_caps(struct snd_info_buffer *buffer, | |||
145 | print_pcm_formats(buffer, stream); | 135 | print_pcm_formats(buffer, stream); |
146 | } | 136 | } |
147 | 137 | ||
148 | static const char *get_jack_location(u32 cfg) | ||
149 | { | ||
150 | static char *bases[7] = { | ||
151 | "N/A", "Rear", "Front", "Left", "Right", "Top", "Bottom", | ||
152 | }; | ||
153 | static unsigned char specials_idx[] = { | ||
154 | 0x07, 0x08, | ||
155 | 0x17, 0x18, 0x19, | ||
156 | 0x37, 0x38 | ||
157 | }; | ||
158 | static char *specials[] = { | ||
159 | "Rear Panel", "Drive Bar", | ||
160 | "Riser", "HDMI", "ATAPI", | ||
161 | "Mobile-In", "Mobile-Out" | ||
162 | }; | ||
163 | int i; | ||
164 | cfg = (cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT; | ||
165 | if ((cfg & 0x0f) < 7) | ||
166 | return bases[cfg & 0x0f]; | ||
167 | for (i = 0; i < ARRAY_SIZE(specials_idx); i++) { | ||
168 | if (cfg == specials_idx[i]) | ||
169 | return specials[i]; | ||
170 | } | ||
171 | return "UNKNOWN"; | ||
172 | } | ||
173 | |||
174 | static const char *get_jack_connection(u32 cfg) | 138 | static const char *get_jack_connection(u32 cfg) |
175 | { | 139 | { |
176 | static char *names[16] = { | 140 | static char *names[16] = { |
@@ -206,13 +170,6 @@ static void print_pin_caps(struct snd_info_buffer *buffer, | |||
206 | int *supports_vref) | 170 | int *supports_vref) |
207 | { | 171 | { |
208 | static char *jack_conns[4] = { "Jack", "N/A", "Fixed", "Both" }; | 172 | static char *jack_conns[4] = { "Jack", "N/A", "Fixed", "Both" }; |
209 | static char *jack_types[16] = { | ||
210 | "Line Out", "Speaker", "HP Out", "CD", | ||
211 | "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand", | ||
212 | "Line In", "Aux", "Mic", "Telephony", | ||
213 | "SPDIF In", "Digitial In", "Reserved", "Other" | ||
214 | }; | ||
215 | static char *jack_locations[4] = { "Ext", "Int", "Sep", "Oth" }; | ||
216 | unsigned int caps, val; | 173 | unsigned int caps, val; |
217 | 174 | ||
218 | caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); | 175 | caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); |
@@ -274,9 +231,9 @@ static void print_pin_caps(struct snd_info_buffer *buffer, | |||
274 | caps = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); | 231 | caps = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); |
275 | snd_iprintf(buffer, " Pin Default 0x%08x: [%s] %s at %s %s\n", caps, | 232 | snd_iprintf(buffer, " Pin Default 0x%08x: [%s] %s at %s %s\n", caps, |
276 | jack_conns[(caps & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT], | 233 | jack_conns[(caps & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT], |
277 | jack_types[(caps & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT], | 234 | snd_hda_get_jack_type(caps), |
278 | jack_locations[(caps >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3], | 235 | snd_hda_get_jack_connectivity(caps), |
279 | get_jack_location(caps)); | 236 | snd_hda_get_jack_location(caps)); |
280 | snd_iprintf(buffer, " Conn = %s, Color = %s\n", | 237 | snd_iprintf(buffer, " Conn = %s, Color = %s\n", |
281 | get_jack_connection(caps), | 238 | get_jack_connection(caps), |
282 | get_jack_color(caps)); | 239 | get_jack_color(caps)); |
@@ -500,12 +457,13 @@ static void print_gpio(struct snd_info_buffer *buffer, | |||
500 | for (i = 0; i < max; ++i) | 457 | for (i = 0; i < max; ++i) |
501 | snd_iprintf(buffer, | 458 | snd_iprintf(buffer, |
502 | " IO[%d]: enable=%d, dir=%d, wake=%d, " | 459 | " IO[%d]: enable=%d, dir=%d, wake=%d, " |
503 | "sticky=%d, data=%d\n", i, | 460 | "sticky=%d, data=%d, unsol=%d\n", i, |
504 | (enable & (1<<i)) ? 1 : 0, | 461 | (enable & (1<<i)) ? 1 : 0, |
505 | (direction & (1<<i)) ? 1 : 0, | 462 | (direction & (1<<i)) ? 1 : 0, |
506 | (wake & (1<<i)) ? 1 : 0, | 463 | (wake & (1<<i)) ? 1 : 0, |
507 | (sticky & (1<<i)) ? 1 : 0, | 464 | (sticky & (1<<i)) ? 1 : 0, |
508 | (data & (1<<i)) ? 1 : 0); | 465 | (data & (1<<i)) ? 1 : 0, |
466 | (unsol & (1<<i)) ? 1 : 0); | ||
509 | /* FIXME: add GPO and GPI pin information */ | 467 | /* FIXME: add GPO and GPI pin information */ |
510 | } | 468 | } |
511 | 469 | ||
@@ -513,12 +471,11 @@ static void print_codec_info(struct snd_info_entry *entry, | |||
513 | struct snd_info_buffer *buffer) | 471 | struct snd_info_buffer *buffer) |
514 | { | 472 | { |
515 | struct hda_codec *codec = entry->private_data; | 473 | struct hda_codec *codec = entry->private_data; |
516 | char buf[32]; | ||
517 | hda_nid_t nid; | 474 | hda_nid_t nid; |
518 | int i, nodes; | 475 | int i, nodes; |
519 | 476 | ||
520 | snd_hda_get_codec_name(codec, buf, sizeof(buf)); | 477 | snd_iprintf(buffer, "Codec: %s\n", |
521 | snd_iprintf(buffer, "Codec: %s\n", buf); | 478 | codec->name ? codec->name : "Not Set"); |
522 | snd_iprintf(buffer, "Address: %d\n", codec->addr); | 479 | snd_iprintf(buffer, "Address: %d\n", codec->addr); |
523 | snd_iprintf(buffer, "Vendor Id: 0x%x\n", codec->vendor_id); | 480 | snd_iprintf(buffer, "Vendor Id: 0x%x\n", codec->vendor_id); |
524 | snd_iprintf(buffer, "Subsystem Id: 0x%x\n", codec->subsystem_id); | 481 | snd_iprintf(buffer, "Subsystem Id: 0x%x\n", codec->subsystem_id); |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 686c77491dea..0cc6be12b8b7 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -67,8 +67,7 @@ struct ad198x_spec { | |||
67 | 67 | ||
68 | /* dynamic controls, init_verbs and input_mux */ | 68 | /* dynamic controls, init_verbs and input_mux */ |
69 | struct auto_pin_cfg autocfg; | 69 | struct auto_pin_cfg autocfg; |
70 | unsigned int num_kctl_alloc, num_kctl_used; | 70 | struct snd_array kctls; |
71 | struct snd_kcontrol_new *kctl_alloc; | ||
72 | struct hda_input_mux private_imux; | 71 | struct hda_input_mux private_imux; |
73 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; | 72 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; |
74 | 73 | ||
@@ -154,6 +153,8 @@ static const char *ad_slave_sws[] = { | |||
154 | NULL | 153 | NULL |
155 | }; | 154 | }; |
156 | 155 | ||
156 | static void ad198x_free_kctls(struct hda_codec *codec); | ||
157 | |||
157 | static int ad198x_build_controls(struct hda_codec *codec) | 158 | static int ad198x_build_controls(struct hda_codec *codec) |
158 | { | 159 | { |
159 | struct ad198x_spec *spec = codec->spec; | 160 | struct ad198x_spec *spec = codec->spec; |
@@ -202,6 +203,7 @@ static int ad198x_build_controls(struct hda_codec *codec) | |||
202 | return err; | 203 | return err; |
203 | } | 204 | } |
204 | 205 | ||
206 | ad198x_free_kctls(codec); /* no longer needed */ | ||
205 | return 0; | 207 | return 0; |
206 | } | 208 | } |
207 | 209 | ||
@@ -375,16 +377,27 @@ static int ad198x_build_pcms(struct hda_codec *codec) | |||
375 | return 0; | 377 | return 0; |
376 | } | 378 | } |
377 | 379 | ||
378 | static void ad198x_free(struct hda_codec *codec) | 380 | static void ad198x_free_kctls(struct hda_codec *codec) |
379 | { | 381 | { |
380 | struct ad198x_spec *spec = codec->spec; | 382 | struct ad198x_spec *spec = codec->spec; |
381 | unsigned int i; | ||
382 | 383 | ||
383 | if (spec->kctl_alloc) { | 384 | if (spec->kctls.list) { |
384 | for (i = 0; i < spec->num_kctl_used; i++) | 385 | struct snd_kcontrol_new *kctl = spec->kctls.list; |
385 | kfree(spec->kctl_alloc[i].name); | 386 | int i; |
386 | kfree(spec->kctl_alloc); | 387 | for (i = 0; i < spec->kctls.used; i++) |
388 | kfree(kctl[i].name); | ||
387 | } | 389 | } |
390 | snd_array_free(&spec->kctls); | ||
391 | } | ||
392 | |||
393 | static void ad198x_free(struct hda_codec *codec) | ||
394 | { | ||
395 | struct ad198x_spec *spec = codec->spec; | ||
396 | |||
397 | if (!spec) | ||
398 | return; | ||
399 | |||
400 | ad198x_free_kctls(codec); | ||
388 | kfree(codec->spec); | 401 | kfree(codec->spec); |
389 | } | 402 | } |
390 | 403 | ||
@@ -629,6 +642,36 @@ static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = { | |||
629 | HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw), | 642 | HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw), |
630 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT), | 643 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT), |
631 | HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), | 644 | HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), |
645 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0, HDA_OUTPUT), | ||
646 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0, HDA_OUTPUT), | ||
647 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), | ||
648 | HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), | ||
649 | HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT), | ||
650 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), | ||
651 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT), | ||
652 | { | ||
653 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
654 | .name = "Capture Source", | ||
655 | .info = ad198x_mux_enum_info, | ||
656 | .get = ad198x_mux_enum_get, | ||
657 | .put = ad198x_mux_enum_put, | ||
658 | }, | ||
659 | { | ||
660 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
661 | .name = "External Amplifier", | ||
662 | .info = ad198x_eapd_info, | ||
663 | .get = ad198x_eapd_get, | ||
664 | .put = ad198x_eapd_put, | ||
665 | .private_value = 0x1b | (1 << 8), /* port-D, inversed */ | ||
666 | }, | ||
667 | { } /* end */ | ||
668 | }; | ||
669 | |||
670 | static struct snd_kcontrol_new ad1986a_samsung_mixers[] = { | ||
671 | HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol), | ||
672 | HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw), | ||
673 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT), | ||
674 | HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), | ||
632 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), | 675 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), |
633 | HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), | 676 | HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), |
634 | HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT), | 677 | HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT), |
@@ -917,6 +960,7 @@ enum { | |||
917 | AD1986A_LAPTOP_EAPD, | 960 | AD1986A_LAPTOP_EAPD, |
918 | AD1986A_LAPTOP_AUTOMUTE, | 961 | AD1986A_LAPTOP_AUTOMUTE, |
919 | AD1986A_ULTRA, | 962 | AD1986A_ULTRA, |
963 | AD1986A_SAMSUNG, | ||
920 | AD1986A_MODELS | 964 | AD1986A_MODELS |
921 | }; | 965 | }; |
922 | 966 | ||
@@ -927,6 +971,7 @@ static const char *ad1986a_models[AD1986A_MODELS] = { | |||
927 | [AD1986A_LAPTOP_EAPD] = "laptop-eapd", | 971 | [AD1986A_LAPTOP_EAPD] = "laptop-eapd", |
928 | [AD1986A_LAPTOP_AUTOMUTE] = "laptop-automute", | 972 | [AD1986A_LAPTOP_AUTOMUTE] = "laptop-automute", |
929 | [AD1986A_ULTRA] = "ultra", | 973 | [AD1986A_ULTRA] = "ultra", |
974 | [AD1986A_SAMSUNG] = "samsung", | ||
930 | }; | 975 | }; |
931 | 976 | ||
932 | static struct snd_pci_quirk ad1986a_cfg_tbl[] = { | 977 | static struct snd_pci_quirk ad1986a_cfg_tbl[] = { |
@@ -949,9 +994,9 @@ static struct snd_pci_quirk ad1986a_cfg_tbl[] = { | |||
949 | SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba", AD1986A_LAPTOP_EAPD), | 994 | SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba", AD1986A_LAPTOP_EAPD), |
950 | SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK), | 995 | SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK), |
951 | SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP), | 996 | SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP), |
952 | SND_PCI_QUIRK(0x144d, 0xc023, "Samsung X60", AD1986A_LAPTOP_EAPD), | 997 | SND_PCI_QUIRK(0x144d, 0xc023, "Samsung X60", AD1986A_SAMSUNG), |
953 | SND_PCI_QUIRK(0x144d, 0xc024, "Samsung R65", AD1986A_LAPTOP_EAPD), | 998 | SND_PCI_QUIRK(0x144d, 0xc024, "Samsung R65", AD1986A_SAMSUNG), |
954 | SND_PCI_QUIRK(0x144d, 0xc026, "Samsung X11", AD1986A_LAPTOP_EAPD), | 999 | SND_PCI_QUIRK(0x144d, 0xc026, "Samsung X11", AD1986A_SAMSUNG), |
955 | SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA), | 1000 | SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA), |
956 | SND_PCI_QUIRK(0x144d, 0xc504, "Samsung Q35", AD1986A_3STACK), | 1001 | SND_PCI_QUIRK(0x144d, 0xc504, "Samsung Q35", AD1986A_3STACK), |
957 | SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_LAPTOP), | 1002 | SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_LAPTOP), |
@@ -1033,6 +1078,17 @@ static int patch_ad1986a(struct hda_codec *codec) | |||
1033 | break; | 1078 | break; |
1034 | case AD1986A_LAPTOP_EAPD: | 1079 | case AD1986A_LAPTOP_EAPD: |
1035 | spec->mixers[0] = ad1986a_laptop_eapd_mixers; | 1080 | spec->mixers[0] = ad1986a_laptop_eapd_mixers; |
1081 | spec->num_init_verbs = 2; | ||
1082 | spec->init_verbs[1] = ad1986a_eapd_init_verbs; | ||
1083 | spec->multiout.max_channels = 2; | ||
1084 | spec->multiout.num_dacs = 1; | ||
1085 | spec->multiout.dac_nids = ad1986a_laptop_dac_nids; | ||
1086 | if (!is_jack_available(codec, 0x25)) | ||
1087 | spec->multiout.dig_out_nid = 0; | ||
1088 | spec->input_mux = &ad1986a_laptop_eapd_capture_source; | ||
1089 | break; | ||
1090 | case AD1986A_SAMSUNG: | ||
1091 | spec->mixers[0] = ad1986a_samsung_mixers; | ||
1036 | spec->num_init_verbs = 3; | 1092 | spec->num_init_verbs = 3; |
1037 | spec->init_verbs[1] = ad1986a_eapd_init_verbs; | 1093 | spec->init_verbs[1] = ad1986a_eapd_init_verbs; |
1038 | spec->init_verbs[2] = ad1986a_automic_verbs; | 1094 | spec->init_verbs[2] = ad1986a_automic_verbs; |
@@ -2452,9 +2508,6 @@ static struct hda_amp_list ad1988_loopbacks[] = { | |||
2452 | * Automatic parse of I/O pins from the BIOS configuration | 2508 | * Automatic parse of I/O pins from the BIOS configuration |
2453 | */ | 2509 | */ |
2454 | 2510 | ||
2455 | #define NUM_CONTROL_ALLOC 32 | ||
2456 | #define NUM_VERB_ALLOC 32 | ||
2457 | |||
2458 | enum { | 2511 | enum { |
2459 | AD_CTL_WIDGET_VOL, | 2512 | AD_CTL_WIDGET_VOL, |
2460 | AD_CTL_WIDGET_MUTE, | 2513 | AD_CTL_WIDGET_MUTE, |
@@ -2472,27 +2525,15 @@ static int add_control(struct ad198x_spec *spec, int type, const char *name, | |||
2472 | { | 2525 | { |
2473 | struct snd_kcontrol_new *knew; | 2526 | struct snd_kcontrol_new *knew; |
2474 | 2527 | ||
2475 | if (spec->num_kctl_used >= spec->num_kctl_alloc) { | 2528 | snd_array_init(&spec->kctls, sizeof(*knew), 32); |
2476 | int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC; | 2529 | knew = snd_array_new(&spec->kctls); |
2477 | 2530 | if (!knew) | |
2478 | knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */ | 2531 | return -ENOMEM; |
2479 | if (! knew) | ||
2480 | return -ENOMEM; | ||
2481 | if (spec->kctl_alloc) { | ||
2482 | memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc); | ||
2483 | kfree(spec->kctl_alloc); | ||
2484 | } | ||
2485 | spec->kctl_alloc = knew; | ||
2486 | spec->num_kctl_alloc = num; | ||
2487 | } | ||
2488 | |||
2489 | knew = &spec->kctl_alloc[spec->num_kctl_used]; | ||
2490 | *knew = ad1988_control_templates[type]; | 2532 | *knew = ad1988_control_templates[type]; |
2491 | knew->name = kstrdup(name, GFP_KERNEL); | 2533 | knew->name = kstrdup(name, GFP_KERNEL); |
2492 | if (! knew->name) | 2534 | if (! knew->name) |
2493 | return -ENOMEM; | 2535 | return -ENOMEM; |
2494 | knew->private_value = val; | 2536 | knew->private_value = val; |
2495 | spec->num_kctl_used++; | ||
2496 | return 0; | 2537 | return 0; |
2497 | } | 2538 | } |
2498 | 2539 | ||
@@ -2846,8 +2887,8 @@ static int ad1988_parse_auto_config(struct hda_codec *codec) | |||
2846 | if (spec->autocfg.dig_in_pin) | 2887 | if (spec->autocfg.dig_in_pin) |
2847 | spec->dig_in_nid = AD1988_SPDIF_IN; | 2888 | spec->dig_in_nid = AD1988_SPDIF_IN; |
2848 | 2889 | ||
2849 | if (spec->kctl_alloc) | 2890 | if (spec->kctls.list) |
2850 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 2891 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
2851 | 2892 | ||
2852 | spec->init_verbs[spec->num_init_verbs++] = ad1988_6stack_init_verbs; | 2893 | spec->init_verbs[spec->num_init_verbs++] = ad1988_6stack_init_verbs; |
2853 | 2894 | ||
diff --git a/sound/pci/hda/patch_atihdmi.c b/sound/pci/hda/patch_atihdmi.c index ba61575983fd..5603a1acddb1 100644 --- a/sound/pci/hda/patch_atihdmi.c +++ b/sound/pci/hda/patch_atihdmi.c | |||
@@ -193,7 +193,6 @@ struct hda_codec_preset snd_hda_preset_atihdmi[] = { | |||
193 | { .id = 0x1002791a, .name = "ATI RS690/780 HDMI", .patch = patch_atihdmi }, | 193 | { .id = 0x1002791a, .name = "ATI RS690/780 HDMI", .patch = patch_atihdmi }, |
194 | { .id = 0x1002aa01, .name = "ATI R6xx HDMI", .patch = patch_atihdmi }, | 194 | { .id = 0x1002aa01, .name = "ATI R6xx HDMI", .patch = patch_atihdmi }, |
195 | { .id = 0x10951390, .name = "SiI1390 HDMI", .patch = patch_atihdmi }, | 195 | { .id = 0x10951390, .name = "SiI1390 HDMI", .patch = patch_atihdmi }, |
196 | { .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_atihdmi }, | ||
197 | { .id = 0x17e80047, .name = "Chrontel HDMI", .patch = patch_atihdmi }, | 196 | { .id = 0x17e80047, .name = "Chrontel HDMI", .patch = patch_atihdmi }, |
198 | {} /* terminator */ | 197 | {} /* terminator */ |
199 | }; | 198 | }; |
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 7c1eb23f0cec..076010708152 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -86,8 +86,6 @@ struct conexant_spec { | |||
86 | 86 | ||
87 | /* dynamic controls, init_verbs and input_mux */ | 87 | /* dynamic controls, init_verbs and input_mux */ |
88 | struct auto_pin_cfg autocfg; | 88 | struct auto_pin_cfg autocfg; |
89 | unsigned int num_kctl_alloc, num_kctl_used; | ||
90 | struct snd_kcontrol_new *kctl_alloc; | ||
91 | struct hda_input_mux private_imux; | 89 | struct hda_input_mux private_imux; |
92 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; | 90 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; |
93 | 91 | ||
@@ -344,15 +342,6 @@ static int conexant_init(struct hda_codec *codec) | |||
344 | 342 | ||
345 | static void conexant_free(struct hda_codec *codec) | 343 | static void conexant_free(struct hda_codec *codec) |
346 | { | 344 | { |
347 | struct conexant_spec *spec = codec->spec; | ||
348 | unsigned int i; | ||
349 | |||
350 | if (spec->kctl_alloc) { | ||
351 | for (i = 0; i < spec->num_kctl_used; i++) | ||
352 | kfree(spec->kctl_alloc[i].name); | ||
353 | kfree(spec->kctl_alloc); | ||
354 | } | ||
355 | |||
356 | kfree(codec->spec); | 345 | kfree(codec->spec); |
357 | } | 346 | } |
358 | 347 | ||
diff --git a/sound/pci/hda/patch_intelhdmi.c b/sound/pci/hda/patch_intelhdmi.c new file mode 100644 index 000000000000..fe08bef897cd --- /dev/null +++ b/sound/pci/hda/patch_intelhdmi.c | |||
@@ -0,0 +1,685 @@ | |||
1 | /* | ||
2 | * | ||
3 | * patch_intelhdmi.c - Patch for Intel HDMI codecs | ||
4 | * | ||
5 | * Copyright(c) 2008 Intel Corporation. All rights reserved. | ||
6 | * | ||
7 | * Authors: | ||
8 | * Jiang Zhe <zhe.jiang@intel.com> | ||
9 | * Wu Fengguang <wfg@linux.intel.com> | ||
10 | * | ||
11 | * Maintained by: | ||
12 | * Wu Fengguang <wfg@linux.intel.com> | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify it | ||
15 | * under the terms of the GNU General Public License as published by the Free | ||
16 | * Software Foundation; either version 2 of the License, or (at your option) | ||
17 | * any later version. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, but | ||
20 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | ||
21 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
22 | * for more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License | ||
25 | * along with this program; if not, write to the Free Software Foundation, | ||
26 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
27 | */ | ||
28 | |||
29 | #include <linux/init.h> | ||
30 | #include <linux/delay.h> | ||
31 | #include <linux/slab.h> | ||
32 | #include <sound/core.h> | ||
33 | #include "hda_codec.h" | ||
34 | #include "hda_local.h" | ||
35 | #include "hda_patch.h" | ||
36 | |||
37 | #define CVT_NID 0x02 /* audio converter */ | ||
38 | #define PIN_NID 0x03 /* HDMI output pin */ | ||
39 | |||
40 | #define INTEL_HDMI_EVENT_TAG 0x08 | ||
41 | |||
42 | struct intel_hdmi_spec { | ||
43 | struct hda_multi_out multiout; | ||
44 | struct hda_pcm pcm_rec; | ||
45 | struct hdmi_eld sink_eld; | ||
46 | }; | ||
47 | |||
48 | static struct hda_verb pinout_enable_verb[] = { | ||
49 | {PIN_NID, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
50 | {} /* terminator */ | ||
51 | }; | ||
52 | |||
53 | static struct hda_verb pinout_disable_verb[] = { | ||
54 | {PIN_NID, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00}, | ||
55 | {} | ||
56 | }; | ||
57 | |||
58 | static struct hda_verb unsolicited_response_verb[] = { | ||
59 | {PIN_NID, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | | ||
60 | INTEL_HDMI_EVENT_TAG}, | ||
61 | {} | ||
62 | }; | ||
63 | |||
64 | static struct hda_verb def_chan_map[] = { | ||
65 | {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x00}, | ||
66 | {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x11}, | ||
67 | {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x22}, | ||
68 | {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x33}, | ||
69 | {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x44}, | ||
70 | {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x55}, | ||
71 | {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x66}, | ||
72 | {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x77}, | ||
73 | {} | ||
74 | }; | ||
75 | |||
76 | |||
77 | struct hdmi_audio_infoframe { | ||
78 | u8 type; /* 0x84 */ | ||
79 | u8 ver; /* 0x01 */ | ||
80 | u8 len; /* 0x0a */ | ||
81 | |||
82 | u8 checksum; /* PB0 */ | ||
83 | u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */ | ||
84 | u8 SS01_SF24; | ||
85 | u8 CXT04; | ||
86 | u8 CA; | ||
87 | u8 LFEPBL01_LSV36_DM_INH7; | ||
88 | u8 reserved[5]; /* PB6 - PB10 */ | ||
89 | }; | ||
90 | |||
91 | /* | ||
92 | * CEA speaker placement: | ||
93 | * | ||
94 | * FLH FCH FRH | ||
95 | * FLW FL FLC FC FRC FR FRW | ||
96 | * | ||
97 | * LFE | ||
98 | * TC | ||
99 | * | ||
100 | * RL RLC RC RRC RR | ||
101 | * | ||
102 | * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to | ||
103 | * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC. | ||
104 | */ | ||
105 | enum cea_speaker_placement { | ||
106 | FL = (1 << 0), /* Front Left */ | ||
107 | FC = (1 << 1), /* Front Center */ | ||
108 | FR = (1 << 2), /* Front Right */ | ||
109 | FLC = (1 << 3), /* Front Left Center */ | ||
110 | FRC = (1 << 4), /* Front Right Center */ | ||
111 | RL = (1 << 5), /* Rear Left */ | ||
112 | RC = (1 << 6), /* Rear Center */ | ||
113 | RR = (1 << 7), /* Rear Right */ | ||
114 | RLC = (1 << 8), /* Rear Left Center */ | ||
115 | RRC = (1 << 9), /* Rear Right Center */ | ||
116 | LFE = (1 << 10), /* Low Frequency Effect */ | ||
117 | FLW = (1 << 11), /* Front Left Wide */ | ||
118 | FRW = (1 << 12), /* Front Right Wide */ | ||
119 | FLH = (1 << 13), /* Front Left High */ | ||
120 | FCH = (1 << 14), /* Front Center High */ | ||
121 | FRH = (1 << 15), /* Front Right High */ | ||
122 | TC = (1 << 16), /* Top Center */ | ||
123 | }; | ||
124 | |||
125 | /* | ||
126 | * ELD SA bits in the CEA Speaker Allocation data block | ||
127 | */ | ||
128 | static int eld_speaker_allocation_bits[] = { | ||
129 | [0] = FL | FR, | ||
130 | [1] = LFE, | ||
131 | [2] = FC, | ||
132 | [3] = RL | RR, | ||
133 | [4] = RC, | ||
134 | [5] = FLC | FRC, | ||
135 | [6] = RLC | RRC, | ||
136 | /* the following are not defined in ELD yet */ | ||
137 | [7] = FLW | FRW, | ||
138 | [8] = FLH | FRH, | ||
139 | [9] = TC, | ||
140 | [10] = FCH, | ||
141 | }; | ||
142 | |||
143 | struct cea_channel_speaker_allocation { | ||
144 | int ca_index; | ||
145 | int speakers[8]; | ||
146 | |||
147 | /* derived values, just for convenience */ | ||
148 | int channels; | ||
149 | int spk_mask; | ||
150 | }; | ||
151 | |||
152 | /* | ||
153 | * This is an ordered list! | ||
154 | * | ||
155 | * The preceding ones have better chances to be selected by | ||
156 | * hdmi_setup_channel_allocation(). | ||
157 | */ | ||
158 | static struct cea_channel_speaker_allocation channel_allocations[] = { | ||
159 | /* channel: 8 7 6 5 4 3 2 1 */ | ||
160 | { .ca_index = 0x00, .speakers = { 0, 0, 0, 0, 0, 0, FR, FL } }, | ||
161 | /* 2.1 */ | ||
162 | { .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL } }, | ||
163 | /* Dolby Surround */ | ||
164 | { .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL } }, | ||
165 | { .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL } }, | ||
166 | { .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL } }, | ||
167 | { .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL } }, | ||
168 | { .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL } }, | ||
169 | { .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL } }, | ||
170 | { .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } }, | ||
171 | { .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } }, | ||
172 | { .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } }, | ||
173 | /* 5.1 */ | ||
174 | { .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } }, | ||
175 | { .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL } }, | ||
176 | { .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL } }, | ||
177 | { .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL } }, | ||
178 | /* 6.1 */ | ||
179 | { .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } }, | ||
180 | { .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL } }, | ||
181 | { .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL } }, | ||
182 | { .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL } }, | ||
183 | /* 7.1 */ | ||
184 | { .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } }, | ||
185 | { .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL } }, | ||
186 | { .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL } }, | ||
187 | { .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL } }, | ||
188 | { .ca_index = 0x17, .speakers = { FRC, FLC, 0, 0, FC, LFE, FR, FL } }, | ||
189 | { .ca_index = 0x18, .speakers = { FRC, FLC, 0, RC, 0, 0, FR, FL } }, | ||
190 | { .ca_index = 0x19, .speakers = { FRC, FLC, 0, RC, 0, LFE, FR, FL } }, | ||
191 | { .ca_index = 0x1a, .speakers = { FRC, FLC, 0, RC, FC, 0, FR, FL } }, | ||
192 | { .ca_index = 0x1b, .speakers = { FRC, FLC, 0, RC, FC, LFE, FR, FL } }, | ||
193 | { .ca_index = 0x1c, .speakers = { FRC, FLC, RR, RL, 0, 0, FR, FL } }, | ||
194 | { .ca_index = 0x1d, .speakers = { FRC, FLC, RR, RL, 0, LFE, FR, FL } }, | ||
195 | { .ca_index = 0x1e, .speakers = { FRC, FLC, RR, RL, FC, 0, FR, FL } }, | ||
196 | { .ca_index = 0x1f, .speakers = { FRC, FLC, RR, RL, FC, LFE, FR, FL } }, | ||
197 | { .ca_index = 0x20, .speakers = { 0, FCH, RR, RL, FC, 0, FR, FL } }, | ||
198 | { .ca_index = 0x21, .speakers = { 0, FCH, RR, RL, FC, LFE, FR, FL } }, | ||
199 | { .ca_index = 0x22, .speakers = { TC, 0, RR, RL, FC, 0, FR, FL } }, | ||
200 | { .ca_index = 0x23, .speakers = { TC, 0, RR, RL, FC, LFE, FR, FL } }, | ||
201 | { .ca_index = 0x24, .speakers = { FRH, FLH, RR, RL, 0, 0, FR, FL } }, | ||
202 | { .ca_index = 0x25, .speakers = { FRH, FLH, RR, RL, 0, LFE, FR, FL } }, | ||
203 | { .ca_index = 0x26, .speakers = { FRW, FLW, RR, RL, 0, 0, FR, FL } }, | ||
204 | { .ca_index = 0x27, .speakers = { FRW, FLW, RR, RL, 0, LFE, FR, FL } }, | ||
205 | { .ca_index = 0x28, .speakers = { TC, RC, RR, RL, FC, 0, FR, FL } }, | ||
206 | { .ca_index = 0x29, .speakers = { TC, RC, RR, RL, FC, LFE, FR, FL } }, | ||
207 | { .ca_index = 0x2a, .speakers = { FCH, RC, RR, RL, FC, 0, FR, FL } }, | ||
208 | { .ca_index = 0x2b, .speakers = { FCH, RC, RR, RL, FC, LFE, FR, FL } }, | ||
209 | { .ca_index = 0x2c, .speakers = { TC, FCH, RR, RL, FC, 0, FR, FL } }, | ||
210 | { .ca_index = 0x2d, .speakers = { TC, FCH, RR, RL, FC, LFE, FR, FL } }, | ||
211 | { .ca_index = 0x2e, .speakers = { FRH, FLH, RR, RL, FC, 0, FR, FL } }, | ||
212 | { .ca_index = 0x2f, .speakers = { FRH, FLH, RR, RL, FC, LFE, FR, FL } }, | ||
213 | { .ca_index = 0x30, .speakers = { FRW, FLW, RR, RL, FC, 0, FR, FL } }, | ||
214 | { .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } }, | ||
215 | }; | ||
216 | |||
217 | /* | ||
218 | * HDMI routines | ||
219 | */ | ||
220 | |||
221 | #ifdef BE_PARANOID | ||
222 | static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t nid, | ||
223 | int *packet_index, int *byte_index) | ||
224 | { | ||
225 | int val; | ||
226 | |||
227 | val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_INDEX, 0); | ||
228 | |||
229 | *packet_index = val >> 5; | ||
230 | *byte_index = val & 0x1f; | ||
231 | } | ||
232 | #endif | ||
233 | |||
234 | static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t nid, | ||
235 | int packet_index, int byte_index) | ||
236 | { | ||
237 | int val; | ||
238 | |||
239 | val = (packet_index << 5) | (byte_index & 0x1f); | ||
240 | |||
241 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val); | ||
242 | } | ||
243 | |||
244 | static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t nid, | ||
245 | unsigned char val) | ||
246 | { | ||
247 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val); | ||
248 | } | ||
249 | |||
250 | static void hdmi_enable_output(struct hda_codec *codec) | ||
251 | { | ||
252 | /* Enable Audio InfoFrame Transmission */ | ||
253 | hdmi_set_dip_index(codec, PIN_NID, 0x0, 0x0); | ||
254 | snd_hda_codec_write(codec, PIN_NID, 0, AC_VERB_SET_HDMI_DIP_XMIT, | ||
255 | AC_DIPXMIT_BEST); | ||
256 | /* Unmute */ | ||
257 | if (get_wcaps(codec, PIN_NID) & AC_WCAP_OUT_AMP) | ||
258 | snd_hda_codec_write(codec, PIN_NID, 0, | ||
259 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); | ||
260 | /* Enable pin out */ | ||
261 | snd_hda_sequence_write(codec, pinout_enable_verb); | ||
262 | } | ||
263 | |||
264 | static void hdmi_disable_output(struct hda_codec *codec) | ||
265 | { | ||
266 | snd_hda_sequence_write(codec, pinout_disable_verb); | ||
267 | if (get_wcaps(codec, PIN_NID) & AC_WCAP_OUT_AMP) | ||
268 | snd_hda_codec_write(codec, PIN_NID, 0, | ||
269 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); | ||
270 | |||
271 | /* | ||
272 | * FIXME: noises may arise when playing music after reloading the | ||
273 | * kernel module, until the next X restart or monitor repower. | ||
274 | */ | ||
275 | } | ||
276 | |||
277 | static int hdmi_get_channel_count(struct hda_codec *codec) | ||
278 | { | ||
279 | return 1 + snd_hda_codec_read(codec, CVT_NID, 0, | ||
280 | AC_VERB_GET_CVT_CHAN_COUNT, 0); | ||
281 | } | ||
282 | |||
283 | static void hdmi_set_channel_count(struct hda_codec *codec, int chs) | ||
284 | { | ||
285 | snd_hda_codec_write(codec, CVT_NID, 0, | ||
286 | AC_VERB_SET_CVT_CHAN_COUNT, chs - 1); | ||
287 | |||
288 | if (chs != hdmi_get_channel_count(codec)) | ||
289 | snd_printd(KERN_INFO "HDMI channel count: expect %d, get %d\n", | ||
290 | chs, hdmi_get_channel_count(codec)); | ||
291 | } | ||
292 | |||
293 | static void hdmi_debug_channel_mapping(struct hda_codec *codec) | ||
294 | { | ||
295 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
296 | int i; | ||
297 | int slot; | ||
298 | |||
299 | for (i = 0; i < 8; i++) { | ||
300 | slot = snd_hda_codec_read(codec, CVT_NID, 0, | ||
301 | AC_VERB_GET_HDMI_CHAN_SLOT, i); | ||
302 | printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n", | ||
303 | slot >> 4, slot & 0x7); | ||
304 | } | ||
305 | #endif | ||
306 | } | ||
307 | |||
308 | static void hdmi_parse_eld(struct hda_codec *codec) | ||
309 | { | ||
310 | struct intel_hdmi_spec *spec = codec->spec; | ||
311 | struct hdmi_eld *eld = &spec->sink_eld; | ||
312 | |||
313 | if (!snd_hdmi_get_eld(eld, codec, PIN_NID)) | ||
314 | snd_hdmi_show_eld(eld); | ||
315 | } | ||
316 | |||
317 | |||
318 | /* | ||
319 | * Audio InfoFrame routines | ||
320 | */ | ||
321 | |||
322 | static void hdmi_debug_dip_size(struct hda_codec *codec) | ||
323 | { | ||
324 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
325 | int i; | ||
326 | int size; | ||
327 | |||
328 | size = snd_hdmi_get_eld_size(codec, PIN_NID); | ||
329 | printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size); | ||
330 | |||
331 | for (i = 0; i < 8; i++) { | ||
332 | size = snd_hda_codec_read(codec, PIN_NID, 0, | ||
333 | AC_VERB_GET_HDMI_DIP_SIZE, i); | ||
334 | printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size); | ||
335 | } | ||
336 | #endif | ||
337 | } | ||
338 | |||
339 | static void hdmi_clear_dip_buffers(struct hda_codec *codec) | ||
340 | { | ||
341 | #ifdef BE_PARANOID | ||
342 | int i, j; | ||
343 | int size; | ||
344 | int pi, bi; | ||
345 | for (i = 0; i < 8; i++) { | ||
346 | size = snd_hda_codec_read(codec, PIN_NID, 0, | ||
347 | AC_VERB_GET_HDMI_DIP_SIZE, i); | ||
348 | if (size == 0) | ||
349 | continue; | ||
350 | |||
351 | hdmi_set_dip_index(codec, PIN_NID, i, 0x0); | ||
352 | for (j = 1; j < 1000; j++) { | ||
353 | hdmi_write_dip_byte(codec, PIN_NID, 0x0); | ||
354 | hdmi_get_dip_index(codec, PIN_NID, &pi, &bi); | ||
355 | if (pi != i) | ||
356 | snd_printd(KERN_INFO "dip index %d: %d != %d\n", | ||
357 | bi, pi, i); | ||
358 | if (bi == 0) /* byte index wrapped around */ | ||
359 | break; | ||
360 | } | ||
361 | snd_printd(KERN_INFO | ||
362 | "HDMI: DIP GP[%d] buf reported size=%d, written=%d\n", | ||
363 | i, size, j); | ||
364 | } | ||
365 | #endif | ||
366 | } | ||
367 | |||
368 | static void hdmi_fill_audio_infoframe(struct hda_codec *codec, | ||
369 | struct hdmi_audio_infoframe *ai) | ||
370 | { | ||
371 | u8 *params = (u8 *)ai; | ||
372 | int i; | ||
373 | |||
374 | hdmi_debug_dip_size(codec); | ||
375 | hdmi_clear_dip_buffers(codec); /* be paranoid */ | ||
376 | |||
377 | hdmi_set_dip_index(codec, PIN_NID, 0x0, 0x0); | ||
378 | for (i = 0; i < sizeof(ai); i++) | ||
379 | hdmi_write_dip_byte(codec, PIN_NID, params[i]); | ||
380 | } | ||
381 | |||
382 | /* | ||
383 | * Compute derived values in channel_allocations[]. | ||
384 | */ | ||
385 | static void init_channel_allocations(void) | ||
386 | { | ||
387 | int i, j; | ||
388 | struct cea_channel_speaker_allocation *p; | ||
389 | |||
390 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { | ||
391 | p = channel_allocations + i; | ||
392 | p->channels = 0; | ||
393 | p->spk_mask = 0; | ||
394 | for (j = 0; j < ARRAY_SIZE(p->speakers); j++) | ||
395 | if (p->speakers[j]) { | ||
396 | p->channels++; | ||
397 | p->spk_mask |= p->speakers[j]; | ||
398 | } | ||
399 | } | ||
400 | } | ||
401 | |||
402 | /* | ||
403 | * The transformation takes two steps: | ||
404 | * | ||
405 | * eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask | ||
406 | * spk_mask => (channel_allocations[]) => ai->CA | ||
407 | * | ||
408 | * TODO: it could select the wrong CA from multiple candidates. | ||
409 | */ | ||
410 | static int hdmi_setup_channel_allocation(struct hda_codec *codec, | ||
411 | struct hdmi_audio_infoframe *ai) | ||
412 | { | ||
413 | struct intel_hdmi_spec *spec = codec->spec; | ||
414 | struct hdmi_eld *eld = &spec->sink_eld; | ||
415 | int i; | ||
416 | int spk_mask = 0; | ||
417 | int channels = 1 + (ai->CC02_CT47 & 0x7); | ||
418 | char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; | ||
419 | |||
420 | /* | ||
421 | * CA defaults to 0 for basic stereo audio | ||
422 | */ | ||
423 | if (!eld->eld_ver) | ||
424 | return 0; | ||
425 | if (!eld->spk_alloc) | ||
426 | return 0; | ||
427 | if (channels <= 2) | ||
428 | return 0; | ||
429 | |||
430 | /* | ||
431 | * expand ELD's speaker allocation mask | ||
432 | * | ||
433 | * ELD tells the speaker mask in a compact(paired) form, | ||
434 | * expand ELD's notions to match the ones used by Audio InfoFrame. | ||
435 | */ | ||
436 | for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) { | ||
437 | if (eld->spk_alloc & (1 << i)) | ||
438 | spk_mask |= eld_speaker_allocation_bits[i]; | ||
439 | } | ||
440 | |||
441 | /* search for the first working match in the CA table */ | ||
442 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { | ||
443 | if (channels == channel_allocations[i].channels && | ||
444 | (spk_mask & channel_allocations[i].spk_mask) == | ||
445 | channel_allocations[i].spk_mask) { | ||
446 | ai->CA = channel_allocations[i].ca_index; | ||
447 | break; | ||
448 | } | ||
449 | } | ||
450 | |||
451 | snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf)); | ||
452 | snd_printdd(KERN_INFO | ||
453 | "HDMI: select CA 0x%x for %d-channel allocation: %s\n", | ||
454 | ai->CA, channels, buf); | ||
455 | |||
456 | return ai->CA; | ||
457 | } | ||
458 | |||
459 | static void hdmi_setup_channel_mapping(struct hda_codec *codec, | ||
460 | struct hdmi_audio_infoframe *ai) | ||
461 | { | ||
462 | if (!ai->CA) | ||
463 | return; | ||
464 | |||
465 | /* | ||
466 | * TODO: adjust channel mapping if necessary | ||
467 | * ALSA sequence is front/surr/clfe/side? | ||
468 | */ | ||
469 | |||
470 | snd_hda_sequence_write(codec, def_chan_map); | ||
471 | hdmi_debug_channel_mapping(codec); | ||
472 | } | ||
473 | |||
474 | |||
475 | static void hdmi_setup_audio_infoframe(struct hda_codec *codec, | ||
476 | struct snd_pcm_substream *substream) | ||
477 | { | ||
478 | struct hdmi_audio_infoframe ai = { | ||
479 | .type = 0x84, | ||
480 | .ver = 0x01, | ||
481 | .len = 0x0a, | ||
482 | .CC02_CT47 = substream->runtime->channels - 1, | ||
483 | }; | ||
484 | |||
485 | hdmi_setup_channel_allocation(codec, &ai); | ||
486 | hdmi_setup_channel_mapping(codec, &ai); | ||
487 | |||
488 | hdmi_fill_audio_infoframe(codec, &ai); | ||
489 | } | ||
490 | |||
491 | |||
492 | /* | ||
493 | * Unsolicited events | ||
494 | */ | ||
495 | |||
496 | static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) | ||
497 | { | ||
498 | int pind = !!(res & AC_UNSOL_RES_PD); | ||
499 | int eldv = !!(res & AC_UNSOL_RES_ELDV); | ||
500 | |||
501 | printk(KERN_INFO | ||
502 | "HDMI hot plug event: Presence_Detect=%d ELD_Valid=%d\n", | ||
503 | pind, eldv); | ||
504 | |||
505 | if (pind && eldv) { | ||
506 | hdmi_parse_eld(codec); | ||
507 | /* TODO: do real things about ELD */ | ||
508 | } | ||
509 | } | ||
510 | |||
511 | static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) | ||
512 | { | ||
513 | int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; | ||
514 | int cp_state = !!(res & AC_UNSOL_RES_CP_STATE); | ||
515 | int cp_ready = !!(res & AC_UNSOL_RES_CP_READY); | ||
516 | |||
517 | printk(KERN_INFO | ||
518 | "HDMI content protection event: SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n", | ||
519 | subtag, | ||
520 | cp_state, | ||
521 | cp_ready); | ||
522 | |||
523 | /* TODO */ | ||
524 | if (cp_state) | ||
525 | ; | ||
526 | if (cp_ready) | ||
527 | ; | ||
528 | } | ||
529 | |||
530 | |||
531 | static void intel_hdmi_unsol_event(struct hda_codec *codec, unsigned int res) | ||
532 | { | ||
533 | int tag = res >> AC_UNSOL_RES_TAG_SHIFT; | ||
534 | int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; | ||
535 | |||
536 | if (tag != INTEL_HDMI_EVENT_TAG) { | ||
537 | snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag); | ||
538 | return; | ||
539 | } | ||
540 | |||
541 | if (subtag == 0) | ||
542 | hdmi_intrinsic_event(codec, res); | ||
543 | else | ||
544 | hdmi_non_intrinsic_event(codec, res); | ||
545 | } | ||
546 | |||
547 | /* | ||
548 | * Callbacks | ||
549 | */ | ||
550 | |||
551 | static int intel_hdmi_playback_pcm_open(struct hda_pcm_stream *hinfo, | ||
552 | struct hda_codec *codec, | ||
553 | struct snd_pcm_substream *substream) | ||
554 | { | ||
555 | struct intel_hdmi_spec *spec = codec->spec; | ||
556 | |||
557 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); | ||
558 | } | ||
559 | |||
560 | static int intel_hdmi_playback_pcm_close(struct hda_pcm_stream *hinfo, | ||
561 | struct hda_codec *codec, | ||
562 | struct snd_pcm_substream *substream) | ||
563 | { | ||
564 | struct intel_hdmi_spec *spec = codec->spec; | ||
565 | |||
566 | hdmi_disable_output(codec); | ||
567 | |||
568 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | ||
569 | } | ||
570 | |||
571 | static int intel_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
572 | struct hda_codec *codec, | ||
573 | unsigned int stream_tag, | ||
574 | unsigned int format, | ||
575 | struct snd_pcm_substream *substream) | ||
576 | { | ||
577 | struct intel_hdmi_spec *spec = codec->spec; | ||
578 | |||
579 | snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag, | ||
580 | format, substream); | ||
581 | |||
582 | hdmi_set_channel_count(codec, substream->runtime->channels); | ||
583 | |||
584 | hdmi_setup_audio_infoframe(codec, substream); | ||
585 | |||
586 | hdmi_enable_output(codec); | ||
587 | |||
588 | return 0; | ||
589 | } | ||
590 | |||
591 | static struct hda_pcm_stream intel_hdmi_pcm_playback = { | ||
592 | .substreams = 1, | ||
593 | .channels_min = 2, | ||
594 | .channels_max = 8, | ||
595 | .nid = CVT_NID, /* NID to query formats and rates and setup streams */ | ||
596 | .ops = { | ||
597 | .open = intel_hdmi_playback_pcm_open, | ||
598 | .close = intel_hdmi_playback_pcm_close, | ||
599 | .prepare = intel_hdmi_playback_pcm_prepare | ||
600 | }, | ||
601 | }; | ||
602 | |||
603 | static int intel_hdmi_build_pcms(struct hda_codec *codec) | ||
604 | { | ||
605 | struct intel_hdmi_spec *spec = codec->spec; | ||
606 | struct hda_pcm *info = &spec->pcm_rec; | ||
607 | |||
608 | codec->num_pcms = 1; | ||
609 | codec->pcm_info = info; | ||
610 | |||
611 | info->name = "INTEL HDMI"; | ||
612 | info->pcm_type = HDA_PCM_TYPE_HDMI; | ||
613 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = intel_hdmi_pcm_playback; | ||
614 | |||
615 | return 0; | ||
616 | } | ||
617 | |||
618 | static int intel_hdmi_build_controls(struct hda_codec *codec) | ||
619 | { | ||
620 | struct intel_hdmi_spec *spec = codec->spec; | ||
621 | int err; | ||
622 | |||
623 | err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); | ||
624 | if (err < 0) | ||
625 | return err; | ||
626 | |||
627 | return 0; | ||
628 | } | ||
629 | |||
630 | static int intel_hdmi_init(struct hda_codec *codec) | ||
631 | { | ||
632 | /* disable audio output as early as possible */ | ||
633 | hdmi_disable_output(codec); | ||
634 | |||
635 | snd_hda_sequence_write(codec, unsolicited_response_verb); | ||
636 | |||
637 | return 0; | ||
638 | } | ||
639 | |||
640 | static void intel_hdmi_free(struct hda_codec *codec) | ||
641 | { | ||
642 | struct intel_hdmi_spec *spec = codec->spec; | ||
643 | |||
644 | snd_hda_eld_proc_free(codec, &spec->sink_eld); | ||
645 | kfree(spec); | ||
646 | } | ||
647 | |||
648 | static struct hda_codec_ops intel_hdmi_patch_ops = { | ||
649 | .init = intel_hdmi_init, | ||
650 | .free = intel_hdmi_free, | ||
651 | .build_pcms = intel_hdmi_build_pcms, | ||
652 | .build_controls = intel_hdmi_build_controls, | ||
653 | .unsol_event = intel_hdmi_unsol_event, | ||
654 | }; | ||
655 | |||
656 | static int patch_intel_hdmi(struct hda_codec *codec) | ||
657 | { | ||
658 | struct intel_hdmi_spec *spec; | ||
659 | |||
660 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
661 | if (spec == NULL) | ||
662 | return -ENOMEM; | ||
663 | |||
664 | spec->multiout.num_dacs = 0; /* no analog */ | ||
665 | spec->multiout.max_channels = 8; | ||
666 | spec->multiout.dig_out_nid = CVT_NID; | ||
667 | |||
668 | codec->spec = spec; | ||
669 | codec->patch_ops = intel_hdmi_patch_ops; | ||
670 | |||
671 | snd_hda_eld_proc_new(codec, &spec->sink_eld); | ||
672 | |||
673 | init_channel_allocations(); | ||
674 | |||
675 | return 0; | ||
676 | } | ||
677 | |||
678 | struct hda_codec_preset snd_hda_preset_intelhdmi[] = { | ||
679 | { .id = 0x808629fb, .name = "INTEL G45 DEVCL", .patch = patch_intel_hdmi }, | ||
680 | { .id = 0x80862801, .name = "INTEL G45 DEVBLC", .patch = patch_intel_hdmi }, | ||
681 | { .id = 0x80862802, .name = "INTEL G45 DEVCTG", .patch = patch_intel_hdmi }, | ||
682 | { .id = 0x80862803, .name = "INTEL G45 DEVELK", .patch = patch_intel_hdmi }, | ||
683 | { .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_intel_hdmi }, | ||
684 | {} /* terminator */ | ||
685 | }; | ||
diff --git a/sound/pci/hda/patch_nvhdmi.c b/sound/pci/hda/patch_nvhdmi.c index 2eed2c8b98da..1360d54a7d01 100644 --- a/sound/pci/hda/patch_nvhdmi.c +++ b/sound/pci/hda/patch_nvhdmi.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <sound/core.h> | 28 | #include <sound/core.h> |
29 | #include "hda_codec.h" | 29 | #include "hda_codec.h" |
30 | #include "hda_local.h" | 30 | #include "hda_local.h" |
31 | #include "hda_patch.h" | ||
31 | 32 | ||
32 | struct nvhdmi_spec { | 33 | struct nvhdmi_spec { |
33 | struct hda_multi_out multiout; | 34 | struct hda_multi_out multiout; |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index a378c0145125..f52e271edd57 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -114,6 +114,7 @@ enum { | |||
114 | ALC268_3ST, | 114 | ALC268_3ST, |
115 | ALC268_TOSHIBA, | 115 | ALC268_TOSHIBA, |
116 | ALC268_ACER, | 116 | ALC268_ACER, |
117 | ALC268_ACER_DMIC, | ||
117 | ALC268_ACER_ASPIRE_ONE, | 118 | ALC268_ACER_ASPIRE_ONE, |
118 | ALC268_DELL, | 119 | ALC268_DELL, |
119 | ALC268_ZEPTO, | 120 | ALC268_ZEPTO, |
@@ -130,6 +131,8 @@ enum { | |||
130 | ALC269_QUANTA_FL1, | 131 | ALC269_QUANTA_FL1, |
131 | ALC269_ASUS_EEEPC_P703, | 132 | ALC269_ASUS_EEEPC_P703, |
132 | ALC269_ASUS_EEEPC_P901, | 133 | ALC269_ASUS_EEEPC_P901, |
134 | ALC269_FUJITSU, | ||
135 | ALC269_LIFEBOOK, | ||
133 | ALC269_AUTO, | 136 | ALC269_AUTO, |
134 | ALC269_MODEL_LAST /* last tag */ | 137 | ALC269_MODEL_LAST /* last tag */ |
135 | }; | 138 | }; |
@@ -152,6 +155,7 @@ enum { | |||
152 | enum { | 155 | enum { |
153 | ALC660VD_3ST, | 156 | ALC660VD_3ST, |
154 | ALC660VD_3ST_DIG, | 157 | ALC660VD_3ST_DIG, |
158 | ALC660VD_ASUS_V1S, | ||
155 | ALC861VD_3ST, | 159 | ALC861VD_3ST, |
156 | ALC861VD_3ST_DIG, | 160 | ALC861VD_3ST_DIG, |
157 | ALC861VD_6ST_DIG, | 161 | ALC861VD_6ST_DIG, |
@@ -212,6 +216,7 @@ enum { | |||
212 | ALC883_TARGA_2ch_DIG, | 216 | ALC883_TARGA_2ch_DIG, |
213 | ALC883_ACER, | 217 | ALC883_ACER, |
214 | ALC883_ACER_ASPIRE, | 218 | ALC883_ACER_ASPIRE, |
219 | ALC888_ACER_ASPIRE_4930G, | ||
215 | ALC883_MEDION, | 220 | ALC883_MEDION, |
216 | ALC883_MEDION_MD2, | 221 | ALC883_MEDION_MD2, |
217 | ALC883_LAPTOP_EAPD, | 222 | ALC883_LAPTOP_EAPD, |
@@ -225,9 +230,11 @@ enum { | |||
225 | ALC883_MITAC, | 230 | ALC883_MITAC, |
226 | ALC883_CLEVO_M720, | 231 | ALC883_CLEVO_M720, |
227 | ALC883_FUJITSU_PI2515, | 232 | ALC883_FUJITSU_PI2515, |
233 | ALC888_FUJITSU_XA3530, | ||
228 | ALC883_3ST_6ch_INTEL, | 234 | ALC883_3ST_6ch_INTEL, |
229 | ALC888_ASUS_M90V, | 235 | ALC888_ASUS_M90V, |
230 | ALC888_ASUS_EEE1601, | 236 | ALC888_ASUS_EEE1601, |
237 | ALC1200_ASUS_P5Q, | ||
231 | ALC883_AUTO, | 238 | ALC883_AUTO, |
232 | ALC883_MODEL_LAST, | 239 | ALC883_MODEL_LAST, |
233 | }; | 240 | }; |
@@ -239,6 +246,7 @@ struct alc_spec { | |||
239 | /* codec parameterization */ | 246 | /* codec parameterization */ |
240 | struct snd_kcontrol_new *mixers[5]; /* mixer arrays */ | 247 | struct snd_kcontrol_new *mixers[5]; /* mixer arrays */ |
241 | unsigned int num_mixers; | 248 | unsigned int num_mixers; |
249 | struct snd_kcontrol_new *cap_mixer; /* capture mixer */ | ||
242 | 250 | ||
243 | const struct hda_verb *init_verbs[5]; /* initialization verbs | 251 | const struct hda_verb *init_verbs[5]; /* initialization verbs |
244 | * don't forget NULL | 252 | * don't forget NULL |
@@ -268,6 +276,7 @@ struct alc_spec { | |||
268 | hda_nid_t *adc_nids; | 276 | hda_nid_t *adc_nids; |
269 | hda_nid_t *capsrc_nids; | 277 | hda_nid_t *capsrc_nids; |
270 | hda_nid_t dig_in_nid; /* digital-in NID; optional */ | 278 | hda_nid_t dig_in_nid; /* digital-in NID; optional */ |
279 | unsigned char is_mix_capture; /* matrix-style capture (non-mux) */ | ||
271 | 280 | ||
272 | /* capture source */ | 281 | /* capture source */ |
273 | unsigned int num_mux_defs; | 282 | unsigned int num_mux_defs; |
@@ -284,8 +293,7 @@ struct alc_spec { | |||
284 | 293 | ||
285 | /* dynamic controls, init_verbs and input_mux */ | 294 | /* dynamic controls, init_verbs and input_mux */ |
286 | struct auto_pin_cfg autocfg; | 295 | struct auto_pin_cfg autocfg; |
287 | unsigned int num_kctl_alloc, num_kctl_used; | 296 | struct snd_array kctls; |
288 | struct snd_kcontrol_new *kctl_alloc; | ||
289 | struct hda_input_mux private_imux; | 297 | struct hda_input_mux private_imux; |
290 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; | 298 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; |
291 | 299 | ||
@@ -323,6 +331,7 @@ struct alc_config_preset { | |||
323 | struct snd_kcontrol_new *mixers[5]; /* should be identical size | 331 | struct snd_kcontrol_new *mixers[5]; /* should be identical size |
324 | * with spec | 332 | * with spec |
325 | */ | 333 | */ |
334 | struct snd_kcontrol_new *cap_mixer; /* capture mixer */ | ||
326 | const struct hda_verb *init_verbs[5]; | 335 | const struct hda_verb *init_verbs[5]; |
327 | unsigned int num_dacs; | 336 | unsigned int num_dacs; |
328 | hda_nid_t *dac_nids; | 337 | hda_nid_t *dac_nids; |
@@ -375,14 +384,39 @@ static int alc_mux_enum_put(struct snd_kcontrol *kcontrol, | |||
375 | { | 384 | { |
376 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 385 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
377 | struct alc_spec *spec = codec->spec; | 386 | struct alc_spec *spec = codec->spec; |
387 | const struct hda_input_mux *imux; | ||
378 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | 388 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); |
379 | unsigned int mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx; | 389 | unsigned int mux_idx; |
380 | hda_nid_t nid = spec->capsrc_nids ? | 390 | hda_nid_t nid = spec->capsrc_nids ? |
381 | spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx]; | 391 | spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx]; |
382 | return snd_hda_input_mux_put(codec, &spec->input_mux[mux_idx], ucontrol, | ||
383 | nid, &spec->cur_mux[adc_idx]); | ||
384 | } | ||
385 | 392 | ||
393 | mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx; | ||
394 | imux = &spec->input_mux[mux_idx]; | ||
395 | |||
396 | if (spec->is_mix_capture) { | ||
397 | /* Matrix-mixer style (e.g. ALC882) */ | ||
398 | unsigned int *cur_val = &spec->cur_mux[adc_idx]; | ||
399 | unsigned int i, idx; | ||
400 | |||
401 | idx = ucontrol->value.enumerated.item[0]; | ||
402 | if (idx >= imux->num_items) | ||
403 | idx = imux->num_items - 1; | ||
404 | if (*cur_val == idx) | ||
405 | return 0; | ||
406 | for (i = 0; i < imux->num_items; i++) { | ||
407 | unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE; | ||
408 | snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, | ||
409 | imux->items[i].index, | ||
410 | HDA_AMP_MUTE, v); | ||
411 | } | ||
412 | *cur_val = idx; | ||
413 | return 1; | ||
414 | } else { | ||
415 | /* MUX style (e.g. ALC880) */ | ||
416 | return snd_hda_input_mux_put(codec, imux, ucontrol, nid, | ||
417 | &spec->cur_mux[adc_idx]); | ||
418 | } | ||
419 | } | ||
386 | 420 | ||
387 | /* | 421 | /* |
388 | * channel mode setting | 422 | * channel mode setting |
@@ -717,6 +751,22 @@ static int alc_eapd_ctrl_put(struct snd_kcontrol *kcontrol, | |||
717 | #endif /* CONFIG_SND_DEBUG */ | 751 | #endif /* CONFIG_SND_DEBUG */ |
718 | 752 | ||
719 | /* | 753 | /* |
754 | */ | ||
755 | static void add_mixer(struct alc_spec *spec, struct snd_kcontrol_new *mix) | ||
756 | { | ||
757 | if (snd_BUG_ON(spec->num_mixers >= ARRAY_SIZE(spec->mixers))) | ||
758 | return; | ||
759 | spec->mixers[spec->num_mixers++] = mix; | ||
760 | } | ||
761 | |||
762 | static void add_verb(struct alc_spec *spec, const struct hda_verb *verb) | ||
763 | { | ||
764 | if (snd_BUG_ON(spec->num_init_verbs >= ARRAY_SIZE(spec->init_verbs))) | ||
765 | return; | ||
766 | spec->init_verbs[spec->num_init_verbs++] = verb; | ||
767 | } | ||
768 | |||
769 | /* | ||
720 | * set up from the preset table | 770 | * set up from the preset table |
721 | */ | 771 | */ |
722 | static void setup_preset(struct alc_spec *spec, | 772 | static void setup_preset(struct alc_spec *spec, |
@@ -725,11 +775,11 @@ static void setup_preset(struct alc_spec *spec, | |||
725 | int i; | 775 | int i; |
726 | 776 | ||
727 | for (i = 0; i < ARRAY_SIZE(preset->mixers) && preset->mixers[i]; i++) | 777 | for (i = 0; i < ARRAY_SIZE(preset->mixers) && preset->mixers[i]; i++) |
728 | spec->mixers[spec->num_mixers++] = preset->mixers[i]; | 778 | add_mixer(spec, preset->mixers[i]); |
779 | spec->cap_mixer = preset->cap_mixer; | ||
729 | for (i = 0; i < ARRAY_SIZE(preset->init_verbs) && preset->init_verbs[i]; | 780 | for (i = 0; i < ARRAY_SIZE(preset->init_verbs) && preset->init_verbs[i]; |
730 | i++) | 781 | i++) |
731 | spec->init_verbs[spec->num_init_verbs++] = | 782 | add_verb(spec, preset->init_verbs[i]); |
732 | preset->init_verbs[i]; | ||
733 | 783 | ||
734 | spec->channel_mode = preset->channel_mode; | 784 | spec->channel_mode = preset->channel_mode; |
735 | spec->num_channel_mode = preset->num_channel_mode; | 785 | spec->num_channel_mode = preset->num_channel_mode; |
@@ -1107,6 +1157,226 @@ static void alc_fix_pincfg(struct hda_codec *codec, | |||
1107 | } | 1157 | } |
1108 | 1158 | ||
1109 | /* | 1159 | /* |
1160 | * ALC888 | ||
1161 | */ | ||
1162 | |||
1163 | /* | ||
1164 | * 2ch mode | ||
1165 | */ | ||
1166 | static struct hda_verb alc888_4ST_ch2_intel_init[] = { | ||
1167 | /* Mic-in jack as mic in */ | ||
1168 | { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, | ||
1169 | { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, | ||
1170 | /* Line-in jack as Line in */ | ||
1171 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | ||
1172 | { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, | ||
1173 | /* Line-Out as Front */ | ||
1174 | { 0x17, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1175 | { } /* end */ | ||
1176 | }; | ||
1177 | |||
1178 | /* | ||
1179 | * 4ch mode | ||
1180 | */ | ||
1181 | static struct hda_verb alc888_4ST_ch4_intel_init[] = { | ||
1182 | /* Mic-in jack as mic in */ | ||
1183 | { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, | ||
1184 | { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, | ||
1185 | /* Line-in jack as Surround */ | ||
1186 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
1187 | { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, | ||
1188 | /* Line-Out as Front */ | ||
1189 | { 0x17, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1190 | { } /* end */ | ||
1191 | }; | ||
1192 | |||
1193 | /* | ||
1194 | * 6ch mode | ||
1195 | */ | ||
1196 | static struct hda_verb alc888_4ST_ch6_intel_init[] = { | ||
1197 | /* Mic-in jack as CLFE */ | ||
1198 | { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
1199 | { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, | ||
1200 | /* Line-in jack as Surround */ | ||
1201 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
1202 | { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, | ||
1203 | /* Line-Out as CLFE (workaround because Mic-in is not loud enough) */ | ||
1204 | { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03}, | ||
1205 | { } /* end */ | ||
1206 | }; | ||
1207 | |||
1208 | /* | ||
1209 | * 8ch mode | ||
1210 | */ | ||
1211 | static struct hda_verb alc888_4ST_ch8_intel_init[] = { | ||
1212 | /* Mic-in jack as CLFE */ | ||
1213 | { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
1214 | { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, | ||
1215 | /* Line-in jack as Surround */ | ||
1216 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
1217 | { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, | ||
1218 | /* Line-Out as Side */ | ||
1219 | { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03}, | ||
1220 | { } /* end */ | ||
1221 | }; | ||
1222 | |||
1223 | static struct hda_channel_mode alc888_4ST_8ch_intel_modes[4] = { | ||
1224 | { 2, alc888_4ST_ch2_intel_init }, | ||
1225 | { 4, alc888_4ST_ch4_intel_init }, | ||
1226 | { 6, alc888_4ST_ch6_intel_init }, | ||
1227 | { 8, alc888_4ST_ch8_intel_init }, | ||
1228 | }; | ||
1229 | |||
1230 | /* | ||
1231 | * ALC888 Fujitsu Siemens Amillo xa3530 | ||
1232 | */ | ||
1233 | |||
1234 | static struct hda_verb alc888_fujitsu_xa3530_verbs[] = { | ||
1235 | /* Front Mic: set to PIN_IN (empty by default) */ | ||
1236 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
1237 | /* Connect Internal HP to Front */ | ||
1238 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1239 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1240 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1241 | /* Connect Bass HP to Front */ | ||
1242 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1243 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1244 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1245 | /* Connect Line-Out side jack (SPDIF) to Side */ | ||
1246 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1247 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1248 | {0x17, AC_VERB_SET_CONNECT_SEL, 0x03}, | ||
1249 | /* Connect Mic jack to CLFE */ | ||
1250 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1251 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1252 | {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, | ||
1253 | /* Connect Line-in jack to Surround */ | ||
1254 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1255 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1256 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
1257 | /* Connect HP out jack to Front */ | ||
1258 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1259 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1260 | {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1261 | /* Enable unsolicited event for HP jack and Line-out jack */ | ||
1262 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, | ||
1263 | {0x17, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, | ||
1264 | {} | ||
1265 | }; | ||
1266 | |||
1267 | static void alc888_fujitsu_xa3530_automute(struct hda_codec *codec) | ||
1268 | { | ||
1269 | unsigned int present; | ||
1270 | unsigned int bits; | ||
1271 | /* Line out presence */ | ||
1272 | present = snd_hda_codec_read(codec, 0x17, 0, | ||
1273 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
1274 | /* HP out presence */ | ||
1275 | present = present || snd_hda_codec_read(codec, 0x1b, 0, | ||
1276 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
1277 | bits = present ? HDA_AMP_MUTE : 0; | ||
1278 | /* Toggle internal speakers muting */ | ||
1279 | snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, | ||
1280 | HDA_AMP_MUTE, bits); | ||
1281 | /* Toggle internal bass muting */ | ||
1282 | snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, | ||
1283 | HDA_AMP_MUTE, bits); | ||
1284 | } | ||
1285 | |||
1286 | static void alc888_fujitsu_xa3530_unsol_event(struct hda_codec *codec, | ||
1287 | unsigned int res) | ||
1288 | { | ||
1289 | if (res >> 26 == ALC880_HP_EVENT) | ||
1290 | alc888_fujitsu_xa3530_automute(codec); | ||
1291 | } | ||
1292 | |||
1293 | |||
1294 | /* | ||
1295 | * ALC888 Acer Aspire 4930G model | ||
1296 | */ | ||
1297 | |||
1298 | static struct hda_verb alc888_acer_aspire_4930g_verbs[] = { | ||
1299 | /* Front Mic: set to PIN_IN (empty by default) */ | ||
1300 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
1301 | /* Unselect Front Mic by default in input mixer 3 */ | ||
1302 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0xb)}, | ||
1303 | /* Enable unsolicited event for HP jack */ | ||
1304 | {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, | ||
1305 | /* Connect Internal HP to front */ | ||
1306 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1307 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1308 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1309 | /* Connect HP out to front */ | ||
1310 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1311 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1312 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1313 | { } | ||
1314 | }; | ||
1315 | |||
1316 | static struct hda_input_mux alc888_2_capture_sources[2] = { | ||
1317 | /* Front mic only available on one ADC */ | ||
1318 | { | ||
1319 | .num_items = 4, | ||
1320 | .items = { | ||
1321 | { "Mic", 0x0 }, | ||
1322 | { "Line", 0x2 }, | ||
1323 | { "CD", 0x4 }, | ||
1324 | { "Front Mic", 0xb }, | ||
1325 | }, | ||
1326 | }, | ||
1327 | { | ||
1328 | .num_items = 3, | ||
1329 | .items = { | ||
1330 | { "Mic", 0x0 }, | ||
1331 | { "Line", 0x2 }, | ||
1332 | { "CD", 0x4 }, | ||
1333 | }, | ||
1334 | } | ||
1335 | }; | ||
1336 | |||
1337 | static struct snd_kcontrol_new alc888_base_mixer[] = { | ||
1338 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
1339 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | ||
1340 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
1341 | HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), | ||
1342 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, | ||
1343 | HDA_OUTPUT), | ||
1344 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), | ||
1345 | HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), | ||
1346 | HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), | ||
1347 | HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), | ||
1348 | HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), | ||
1349 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
1350 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
1351 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | ||
1352 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | ||
1353 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
1354 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | ||
1355 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
1356 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
1357 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
1358 | { } /* end */ | ||
1359 | }; | ||
1360 | |||
1361 | static void alc888_acer_aspire_4930g_automute(struct hda_codec *codec) | ||
1362 | { | ||
1363 | unsigned int present; | ||
1364 | unsigned int bits; | ||
1365 | present = snd_hda_codec_read(codec, 0x15, 0, | ||
1366 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
1367 | bits = present ? HDA_AMP_MUTE : 0; | ||
1368 | snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, | ||
1369 | HDA_AMP_MUTE, bits); | ||
1370 | } | ||
1371 | |||
1372 | static void alc888_acer_aspire_4930g_unsol_event(struct hda_codec *codec, | ||
1373 | unsigned int res) | ||
1374 | { | ||
1375 | if (res >> 26 == ALC880_HP_EVENT) | ||
1376 | alc888_acer_aspire_4930g_automute(codec); | ||
1377 | } | ||
1378 | |||
1379 | /* | ||
1110 | * ALC880 3-stack model | 1380 | * ALC880 3-stack model |
1111 | * | 1381 | * |
1112 | * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e) | 1382 | * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e) |
@@ -1205,49 +1475,126 @@ static struct snd_kcontrol_new alc880_three_stack_mixer[] = { | |||
1205 | }; | 1475 | }; |
1206 | 1476 | ||
1207 | /* capture mixer elements */ | 1477 | /* capture mixer elements */ |
1208 | static struct snd_kcontrol_new alc880_capture_mixer[] = { | 1478 | static int alc_cap_vol_info(struct snd_kcontrol *kcontrol, |
1209 | HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT), | 1479 | struct snd_ctl_elem_info *uinfo) |
1210 | HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT), | 1480 | { |
1211 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT), | 1481 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
1212 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT), | 1482 | struct alc_spec *spec = codec->spec; |
1213 | HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT), | 1483 | int err; |
1214 | HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT), | ||
1215 | { | ||
1216 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1217 | /* The multiple "Capture Source" controls confuse alsamixer | ||
1218 | * So call somewhat different.. | ||
1219 | */ | ||
1220 | /* .name = "Capture Source", */ | ||
1221 | .name = "Input Source", | ||
1222 | .count = 3, | ||
1223 | .info = alc_mux_enum_info, | ||
1224 | .get = alc_mux_enum_get, | ||
1225 | .put = alc_mux_enum_put, | ||
1226 | }, | ||
1227 | { } /* end */ | ||
1228 | }; | ||
1229 | 1484 | ||
1230 | /* capture mixer elements (in case NID 0x07 not available) */ | 1485 | mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */ |
1231 | static struct snd_kcontrol_new alc880_capture_alt_mixer[] = { | 1486 | kcontrol->private_value = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0, |
1232 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | 1487 | HDA_INPUT); |
1233 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | 1488 | err = snd_hda_mixer_amp_volume_info(kcontrol, uinfo); |
1234 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), | 1489 | mutex_unlock(&codec->spdif_mutex); /* reuse spdif_mutex */ |
1235 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), | 1490 | return err; |
1236 | { | 1491 | } |
1237 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1238 | /* The multiple "Capture Source" controls confuse alsamixer | ||
1239 | * So call somewhat different.. | ||
1240 | */ | ||
1241 | /* .name = "Capture Source", */ | ||
1242 | .name = "Input Source", | ||
1243 | .count = 2, | ||
1244 | .info = alc_mux_enum_info, | ||
1245 | .get = alc_mux_enum_get, | ||
1246 | .put = alc_mux_enum_put, | ||
1247 | }, | ||
1248 | { } /* end */ | ||
1249 | }; | ||
1250 | 1492 | ||
1493 | static int alc_cap_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag, | ||
1494 | unsigned int size, unsigned int __user *tlv) | ||
1495 | { | ||
1496 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1497 | struct alc_spec *spec = codec->spec; | ||
1498 | int err; | ||
1499 | |||
1500 | mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */ | ||
1501 | kcontrol->private_value = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0, | ||
1502 | HDA_INPUT); | ||
1503 | err = snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, tlv); | ||
1504 | mutex_unlock(&codec->spdif_mutex); /* reuse spdif_mutex */ | ||
1505 | return err; | ||
1506 | } | ||
1507 | |||
1508 | typedef int (*getput_call_t)(struct snd_kcontrol *kcontrol, | ||
1509 | struct snd_ctl_elem_value *ucontrol); | ||
1510 | |||
1511 | static int alc_cap_getput_caller(struct snd_kcontrol *kcontrol, | ||
1512 | struct snd_ctl_elem_value *ucontrol, | ||
1513 | getput_call_t func) | ||
1514 | { | ||
1515 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1516 | struct alc_spec *spec = codec->spec; | ||
1517 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | ||
1518 | int err; | ||
1519 | |||
1520 | mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */ | ||
1521 | kcontrol->private_value = HDA_COMPOSE_AMP_VAL(spec->adc_nids[adc_idx], | ||
1522 | 3, 0, HDA_INPUT); | ||
1523 | err = func(kcontrol, ucontrol); | ||
1524 | mutex_unlock(&codec->spdif_mutex); /* reuse spdif_mutex */ | ||
1525 | return err; | ||
1526 | } | ||
1527 | |||
1528 | static int alc_cap_vol_get(struct snd_kcontrol *kcontrol, | ||
1529 | struct snd_ctl_elem_value *ucontrol) | ||
1530 | { | ||
1531 | return alc_cap_getput_caller(kcontrol, ucontrol, | ||
1532 | snd_hda_mixer_amp_volume_get); | ||
1533 | } | ||
1534 | |||
1535 | static int alc_cap_vol_put(struct snd_kcontrol *kcontrol, | ||
1536 | struct snd_ctl_elem_value *ucontrol) | ||
1537 | { | ||
1538 | return alc_cap_getput_caller(kcontrol, ucontrol, | ||
1539 | snd_hda_mixer_amp_volume_put); | ||
1540 | } | ||
1541 | |||
1542 | /* capture mixer elements */ | ||
1543 | #define alc_cap_sw_info snd_ctl_boolean_stereo_info | ||
1544 | |||
1545 | static int alc_cap_sw_get(struct snd_kcontrol *kcontrol, | ||
1546 | struct snd_ctl_elem_value *ucontrol) | ||
1547 | { | ||
1548 | return alc_cap_getput_caller(kcontrol, ucontrol, | ||
1549 | snd_hda_mixer_amp_switch_get); | ||
1550 | } | ||
1551 | |||
1552 | static int alc_cap_sw_put(struct snd_kcontrol *kcontrol, | ||
1553 | struct snd_ctl_elem_value *ucontrol) | ||
1554 | { | ||
1555 | return alc_cap_getput_caller(kcontrol, ucontrol, | ||
1556 | snd_hda_mixer_amp_switch_put); | ||
1557 | } | ||
1558 | |||
1559 | #define DEFINE_CAPMIX(num) \ | ||
1560 | static struct snd_kcontrol_new alc_capture_mixer ## num[] = { \ | ||
1561 | { \ | ||
1562 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
1563 | .name = "Capture Switch", \ | ||
1564 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ | ||
1565 | .count = num, \ | ||
1566 | .info = alc_cap_sw_info, \ | ||
1567 | .get = alc_cap_sw_get, \ | ||
1568 | .put = alc_cap_sw_put, \ | ||
1569 | }, \ | ||
1570 | { \ | ||
1571 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
1572 | .name = "Capture Volume", \ | ||
1573 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | \ | ||
1574 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ | ||
1575 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK), \ | ||
1576 | .count = num, \ | ||
1577 | .info = alc_cap_vol_info, \ | ||
1578 | .get = alc_cap_vol_get, \ | ||
1579 | .put = alc_cap_vol_put, \ | ||
1580 | .tlv = { .c = alc_cap_vol_tlv }, \ | ||
1581 | }, \ | ||
1582 | { \ | ||
1583 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
1584 | /* .name = "Capture Source", */ \ | ||
1585 | .name = "Input Source", \ | ||
1586 | .count = num, \ | ||
1587 | .info = alc_mux_enum_info, \ | ||
1588 | .get = alc_mux_enum_get, \ | ||
1589 | .put = alc_mux_enum_put, \ | ||
1590 | }, \ | ||
1591 | { } /* end */ \ | ||
1592 | } | ||
1593 | |||
1594 | /* up to three ADCs */ | ||
1595 | DEFINE_CAPMIX(1); | ||
1596 | DEFINE_CAPMIX(2); | ||
1597 | DEFINE_CAPMIX(3); | ||
1251 | 1598 | ||
1252 | 1599 | ||
1253 | /* | 1600 | /* |
@@ -1533,18 +1880,6 @@ static struct snd_kcontrol_new alc880_tcl_s700_mixer[] = { | |||
1533 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0B, 0x0, HDA_INPUT), | 1880 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0B, 0x0, HDA_INPUT), |
1534 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | 1881 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), |
1535 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | 1882 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), |
1536 | { | ||
1537 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1538 | /* The multiple "Capture Source" controls confuse alsamixer | ||
1539 | * So call somewhat different.. | ||
1540 | */ | ||
1541 | /* .name = "Capture Source", */ | ||
1542 | .name = "Input Source", | ||
1543 | .count = 1, | ||
1544 | .info = alc_mux_enum_info, | ||
1545 | .get = alc_mux_enum_get, | ||
1546 | .put = alc_mux_enum_put, | ||
1547 | }, | ||
1548 | { } /* end */ | 1883 | { } /* end */ |
1549 | }; | 1884 | }; |
1550 | 1885 | ||
@@ -1619,6 +1954,7 @@ static const char *alc_slave_vols[] = { | |||
1619 | "Speaker Playback Volume", | 1954 | "Speaker Playback Volume", |
1620 | "Mono Playback Volume", | 1955 | "Mono Playback Volume", |
1621 | "Line-Out Playback Volume", | 1956 | "Line-Out Playback Volume", |
1957 | "PCM Playback Volume", | ||
1622 | NULL, | 1958 | NULL, |
1623 | }; | 1959 | }; |
1624 | 1960 | ||
@@ -1638,6 +1974,9 @@ static const char *alc_slave_sws[] = { | |||
1638 | /* | 1974 | /* |
1639 | * build control elements | 1975 | * build control elements |
1640 | */ | 1976 | */ |
1977 | |||
1978 | static void alc_free_kctls(struct hda_codec *codec); | ||
1979 | |||
1641 | static int alc_build_controls(struct hda_codec *codec) | 1980 | static int alc_build_controls(struct hda_codec *codec) |
1642 | { | 1981 | { |
1643 | struct alc_spec *spec = codec->spec; | 1982 | struct alc_spec *spec = codec->spec; |
@@ -1649,7 +1988,11 @@ static int alc_build_controls(struct hda_codec *codec) | |||
1649 | if (err < 0) | 1988 | if (err < 0) |
1650 | return err; | 1989 | return err; |
1651 | } | 1990 | } |
1652 | 1991 | if (spec->cap_mixer) { | |
1992 | err = snd_hda_add_new_ctls(codec, spec->cap_mixer); | ||
1993 | if (err < 0) | ||
1994 | return err; | ||
1995 | } | ||
1653 | if (spec->multiout.dig_out_nid) { | 1996 | if (spec->multiout.dig_out_nid) { |
1654 | err = snd_hda_create_spdif_out_ctls(codec, | 1997 | err = snd_hda_create_spdif_out_ctls(codec, |
1655 | spec->multiout.dig_out_nid); | 1998 | spec->multiout.dig_out_nid); |
@@ -1684,6 +2027,7 @@ static int alc_build_controls(struct hda_codec *codec) | |||
1684 | return err; | 2027 | return err; |
1685 | } | 2028 | } |
1686 | 2029 | ||
2030 | alc_free_kctls(codec); /* no longer needed */ | ||
1687 | return 0; | 2031 | return 0; |
1688 | } | 2032 | } |
1689 | 2033 | ||
@@ -2774,19 +3118,27 @@ static int alc_build_pcms(struct hda_codec *codec) | |||
2774 | return 0; | 3118 | return 0; |
2775 | } | 3119 | } |
2776 | 3120 | ||
3121 | static void alc_free_kctls(struct hda_codec *codec) | ||
3122 | { | ||
3123 | struct alc_spec *spec = codec->spec; | ||
3124 | |||
3125 | if (spec->kctls.list) { | ||
3126 | struct snd_kcontrol_new *kctl = spec->kctls.list; | ||
3127 | int i; | ||
3128 | for (i = 0; i < spec->kctls.used; i++) | ||
3129 | kfree(kctl[i].name); | ||
3130 | } | ||
3131 | snd_array_free(&spec->kctls); | ||
3132 | } | ||
3133 | |||
2777 | static void alc_free(struct hda_codec *codec) | 3134 | static void alc_free(struct hda_codec *codec) |
2778 | { | 3135 | { |
2779 | struct alc_spec *spec = codec->spec; | 3136 | struct alc_spec *spec = codec->spec; |
2780 | unsigned int i; | ||
2781 | 3137 | ||
2782 | if (!spec) | 3138 | if (!spec) |
2783 | return; | 3139 | return; |
2784 | 3140 | ||
2785 | if (spec->kctl_alloc) { | 3141 | alc_free_kctls(codec); |
2786 | for (i = 0; i < spec->num_kctl_used; i++) | ||
2787 | kfree(spec->kctl_alloc[i].name); | ||
2788 | kfree(spec->kctl_alloc); | ||
2789 | } | ||
2790 | kfree(spec); | 3142 | kfree(spec); |
2791 | codec->spec = NULL; /* to be sure */ | 3143 | codec->spec = NULL; /* to be sure */ |
2792 | } | 3144 | } |
@@ -3268,6 +3620,8 @@ static struct alc_config_preset alc880_presets[] = { | |||
3268 | alc880_gpio2_init_verbs }, | 3620 | alc880_gpio2_init_verbs }, |
3269 | .num_dacs = ARRAY_SIZE(alc880_dac_nids), | 3621 | .num_dacs = ARRAY_SIZE(alc880_dac_nids), |
3270 | .dac_nids = alc880_dac_nids, | 3622 | .dac_nids = alc880_dac_nids, |
3623 | .adc_nids = alc880_adc_nids_alt, /* FIXME: correct? */ | ||
3624 | .num_adc_nids = 1, /* single ADC */ | ||
3271 | .hp_nid = 0x03, | 3625 | .hp_nid = 0x03, |
3272 | .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), | 3626 | .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), |
3273 | .channel_mode = alc880_2_jack_modes, | 3627 | .channel_mode = alc880_2_jack_modes, |
@@ -3532,9 +3886,6 @@ static struct alc_config_preset alc880_presets[] = { | |||
3532 | * Automatic parse of I/O pins from the BIOS configuration | 3886 | * Automatic parse of I/O pins from the BIOS configuration |
3533 | */ | 3887 | */ |
3534 | 3888 | ||
3535 | #define NUM_CONTROL_ALLOC 32 | ||
3536 | #define NUM_VERB_ALLOC 32 | ||
3537 | |||
3538 | enum { | 3889 | enum { |
3539 | ALC_CTL_WIDGET_VOL, | 3890 | ALC_CTL_WIDGET_VOL, |
3540 | ALC_CTL_WIDGET_MUTE, | 3891 | ALC_CTL_WIDGET_MUTE, |
@@ -3552,29 +3903,15 @@ static int add_control(struct alc_spec *spec, int type, const char *name, | |||
3552 | { | 3903 | { |
3553 | struct snd_kcontrol_new *knew; | 3904 | struct snd_kcontrol_new *knew; |
3554 | 3905 | ||
3555 | if (spec->num_kctl_used >= spec->num_kctl_alloc) { | 3906 | snd_array_init(&spec->kctls, sizeof(*knew), 32); |
3556 | int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC; | 3907 | knew = snd_array_new(&spec->kctls); |
3557 | 3908 | if (!knew) | |
3558 | /* array + terminator */ | 3909 | return -ENOMEM; |
3559 | knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); | ||
3560 | if (!knew) | ||
3561 | return -ENOMEM; | ||
3562 | if (spec->kctl_alloc) { | ||
3563 | memcpy(knew, spec->kctl_alloc, | ||
3564 | sizeof(*knew) * spec->num_kctl_alloc); | ||
3565 | kfree(spec->kctl_alloc); | ||
3566 | } | ||
3567 | spec->kctl_alloc = knew; | ||
3568 | spec->num_kctl_alloc = num; | ||
3569 | } | ||
3570 | |||
3571 | knew = &spec->kctl_alloc[spec->num_kctl_used]; | ||
3572 | *knew = alc880_control_templates[type]; | 3910 | *knew = alc880_control_templates[type]; |
3573 | knew->name = kstrdup(name, GFP_KERNEL); | 3911 | knew->name = kstrdup(name, GFP_KERNEL); |
3574 | if (!knew->name) | 3912 | if (!knew->name) |
3575 | return -ENOMEM; | 3913 | return -ENOMEM; |
3576 | knew->private_value = val; | 3914 | knew->private_value = val; |
3577 | spec->num_kctl_used++; | ||
3578 | return 0; | 3915 | return 0; |
3579 | } | 3916 | } |
3580 | 3917 | ||
@@ -3898,10 +4235,10 @@ static int alc880_parse_auto_config(struct hda_codec *codec) | |||
3898 | if (spec->autocfg.dig_in_pin) | 4235 | if (spec->autocfg.dig_in_pin) |
3899 | spec->dig_in_nid = ALC880_DIGIN_NID; | 4236 | spec->dig_in_nid = ALC880_DIGIN_NID; |
3900 | 4237 | ||
3901 | if (spec->kctl_alloc) | 4238 | if (spec->kctls.list) |
3902 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 4239 | add_mixer(spec, spec->kctls.list); |
3903 | 4240 | ||
3904 | spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs; | 4241 | add_verb(spec, alc880_volume_init_verbs); |
3905 | 4242 | ||
3906 | spec->num_mux_defs = 1; | 4243 | spec->num_mux_defs = 1; |
3907 | spec->input_mux = &spec->private_imux; | 4244 | spec->input_mux = &spec->private_imux; |
@@ -3925,6 +4262,17 @@ static void alc880_auto_init(struct hda_codec *codec) | |||
3925 | * OK, here we have finally the patch for ALC880 | 4262 | * OK, here we have finally the patch for ALC880 |
3926 | */ | 4263 | */ |
3927 | 4264 | ||
4265 | static void set_capture_mixer(struct alc_spec *spec) | ||
4266 | { | ||
4267 | static struct snd_kcontrol_new *caps[3] = { | ||
4268 | alc_capture_mixer1, | ||
4269 | alc_capture_mixer2, | ||
4270 | alc_capture_mixer3, | ||
4271 | }; | ||
4272 | if (spec->num_adc_nids > 0 && spec->num_adc_nids < 3) | ||
4273 | spec->cap_mixer = caps[spec->num_adc_nids - 1]; | ||
4274 | } | ||
4275 | |||
3928 | static int patch_alc880(struct hda_codec *codec) | 4276 | static int patch_alc880(struct hda_codec *codec) |
3929 | { | 4277 | { |
3930 | struct alc_spec *spec; | 4278 | struct alc_spec *spec; |
@@ -3980,16 +4328,12 @@ static int patch_alc880(struct hda_codec *codec) | |||
3980 | if (wcap != AC_WID_AUD_IN) { | 4328 | if (wcap != AC_WID_AUD_IN) { |
3981 | spec->adc_nids = alc880_adc_nids_alt; | 4329 | spec->adc_nids = alc880_adc_nids_alt; |
3982 | spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids_alt); | 4330 | spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids_alt); |
3983 | spec->mixers[spec->num_mixers] = | ||
3984 | alc880_capture_alt_mixer; | ||
3985 | spec->num_mixers++; | ||
3986 | } else { | 4331 | } else { |
3987 | spec->adc_nids = alc880_adc_nids; | 4332 | spec->adc_nids = alc880_adc_nids; |
3988 | spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids); | 4333 | spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids); |
3989 | spec->mixers[spec->num_mixers] = alc880_capture_mixer; | ||
3990 | spec->num_mixers++; | ||
3991 | } | 4334 | } |
3992 | } | 4335 | } |
4336 | set_capture_mixer(spec); | ||
3993 | 4337 | ||
3994 | spec->vmaster_nid = 0x0c; | 4338 | spec->vmaster_nid = 0x0c; |
3995 | 4339 | ||
@@ -4024,11 +4368,6 @@ static hda_nid_t alc260_adc_nids_alt[1] = { | |||
4024 | 0x05, | 4368 | 0x05, |
4025 | }; | 4369 | }; |
4026 | 4370 | ||
4027 | static hda_nid_t alc260_hp_adc_nids[2] = { | ||
4028 | /* ADC1, 0 */ | ||
4029 | 0x05, 0x04 | ||
4030 | }; | ||
4031 | |||
4032 | /* NIDs used when simultaneous access to both ADCs makes sense. Note that | 4371 | /* NIDs used when simultaneous access to both ADCs makes sense. Note that |
4033 | * alc260_capture_mixer assumes ADC0 (nid 0x04) is the first ADC. | 4372 | * alc260_capture_mixer assumes ADC0 (nid 0x04) is the first ADC. |
4034 | */ | 4373 | */ |
@@ -4157,13 +4496,13 @@ static void alc260_hp_master_update(struct hda_codec *codec, | |||
4157 | struct alc_spec *spec = codec->spec; | 4496 | struct alc_spec *spec = codec->spec; |
4158 | unsigned int val = spec->master_sw ? PIN_HP : 0; | 4497 | unsigned int val = spec->master_sw ? PIN_HP : 0; |
4159 | /* change HP and line-out pins */ | 4498 | /* change HP and line-out pins */ |
4160 | snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | 4499 | snd_hda_codec_write(codec, hp, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, |
4161 | val); | 4500 | val); |
4162 | snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | 4501 | snd_hda_codec_write(codec, line, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, |
4163 | val); | 4502 | val); |
4164 | /* mono (speaker) depending on the HP jack sense */ | 4503 | /* mono (speaker) depending on the HP jack sense */ |
4165 | val = (val && !spec->jack_present) ? PIN_OUT : 0; | 4504 | val = (val && !spec->jack_present) ? PIN_OUT : 0; |
4166 | snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | 4505 | snd_hda_codec_write(codec, mono, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, |
4167 | val); | 4506 | val); |
4168 | } | 4507 | } |
4169 | 4508 | ||
@@ -4242,7 +4581,7 @@ static struct snd_kcontrol_new alc260_hp_3013_mixer[] = { | |||
4242 | .info = snd_ctl_boolean_mono_info, | 4581 | .info = snd_ctl_boolean_mono_info, |
4243 | .get = alc260_hp_master_sw_get, | 4582 | .get = alc260_hp_master_sw_get, |
4244 | .put = alc260_hp_master_sw_put, | 4583 | .put = alc260_hp_master_sw_put, |
4245 | .private_value = (0x10 << 16) | (0x15 << 8) | 0x11 | 4584 | .private_value = (0x15 << 16) | (0x10 << 8) | 0x11 |
4246 | }, | 4585 | }, |
4247 | HDA_CODEC_VOLUME("Front Playback Volume", 0x09, 0x0, HDA_OUTPUT), | 4586 | HDA_CODEC_VOLUME("Front Playback Volume", 0x09, 0x0, HDA_OUTPUT), |
4248 | HDA_CODEC_MUTE("Front Playback Switch", 0x10, 0x0, HDA_OUTPUT), | 4587 | HDA_CODEC_MUTE("Front Playback Switch", 0x10, 0x0, HDA_OUTPUT), |
@@ -4295,7 +4634,7 @@ static void alc260_hp_3013_automute(struct hda_codec *codec) | |||
4295 | present = snd_hda_codec_read(codec, 0x15, 0, | 4634 | present = snd_hda_codec_read(codec, 0x15, 0, |
4296 | AC_VERB_GET_PIN_SENSE, 0); | 4635 | AC_VERB_GET_PIN_SENSE, 0); |
4297 | spec->jack_present = (present & AC_PINSENSE_PRESENCE) != 0; | 4636 | spec->jack_present = (present & AC_PINSENSE_PRESENCE) != 0; |
4298 | alc260_hp_master_update(codec, 0x10, 0x15, 0x11); | 4637 | alc260_hp_master_update(codec, 0x15, 0x10, 0x11); |
4299 | } | 4638 | } |
4300 | 4639 | ||
4301 | static void alc260_hp_3013_unsol_event(struct hda_codec *codec, | 4640 | static void alc260_hp_3013_unsol_event(struct hda_codec *codec, |
@@ -4427,45 +4766,6 @@ static struct snd_kcontrol_new alc260_replacer_672v_mixer[] = { | |||
4427 | { } /* end */ | 4766 | { } /* end */ |
4428 | }; | 4767 | }; |
4429 | 4768 | ||
4430 | /* capture mixer elements */ | ||
4431 | static struct snd_kcontrol_new alc260_capture_mixer[] = { | ||
4432 | HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT), | ||
4433 | HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT), | ||
4434 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x05, 0x0, HDA_INPUT), | ||
4435 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x05, 0x0, HDA_INPUT), | ||
4436 | { | ||
4437 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
4438 | /* The multiple "Capture Source" controls confuse alsamixer | ||
4439 | * So call somewhat different.. | ||
4440 | */ | ||
4441 | /* .name = "Capture Source", */ | ||
4442 | .name = "Input Source", | ||
4443 | .count = 2, | ||
4444 | .info = alc_mux_enum_info, | ||
4445 | .get = alc_mux_enum_get, | ||
4446 | .put = alc_mux_enum_put, | ||
4447 | }, | ||
4448 | { } /* end */ | ||
4449 | }; | ||
4450 | |||
4451 | static struct snd_kcontrol_new alc260_capture_alt_mixer[] = { | ||
4452 | HDA_CODEC_VOLUME("Capture Volume", 0x05, 0x0, HDA_INPUT), | ||
4453 | HDA_CODEC_MUTE("Capture Switch", 0x05, 0x0, HDA_INPUT), | ||
4454 | { | ||
4455 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
4456 | /* The multiple "Capture Source" controls confuse alsamixer | ||
4457 | * So call somewhat different.. | ||
4458 | */ | ||
4459 | /* .name = "Capture Source", */ | ||
4460 | .name = "Input Source", | ||
4461 | .count = 1, | ||
4462 | .info = alc_mux_enum_info, | ||
4463 | .get = alc_mux_enum_get, | ||
4464 | .put = alc_mux_enum_put, | ||
4465 | }, | ||
4466 | { } /* end */ | ||
4467 | }; | ||
4468 | |||
4469 | /* | 4769 | /* |
4470 | * initialization verbs | 4770 | * initialization verbs |
4471 | */ | 4771 | */ |
@@ -5282,7 +5582,6 @@ static struct hda_verb alc260_volume_init_verbs[] = { | |||
5282 | static int alc260_parse_auto_config(struct hda_codec *codec) | 5582 | static int alc260_parse_auto_config(struct hda_codec *codec) |
5283 | { | 5583 | { |
5284 | struct alc_spec *spec = codec->spec; | 5584 | struct alc_spec *spec = codec->spec; |
5285 | unsigned int wcap; | ||
5286 | int err; | 5585 | int err; |
5287 | static hda_nid_t alc260_ignore[] = { 0x17, 0 }; | 5586 | static hda_nid_t alc260_ignore[] = { 0x17, 0 }; |
5288 | 5587 | ||
@@ -5293,7 +5592,7 @@ static int alc260_parse_auto_config(struct hda_codec *codec) | |||
5293 | err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg); | 5592 | err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg); |
5294 | if (err < 0) | 5593 | if (err < 0) |
5295 | return err; | 5594 | return err; |
5296 | if (!spec->kctl_alloc) | 5595 | if (!spec->kctls.list) |
5297 | return 0; /* can't find valid BIOS pin config */ | 5596 | return 0; /* can't find valid BIOS pin config */ |
5298 | err = alc260_auto_create_analog_input_ctls(spec, &spec->autocfg); | 5597 | err = alc260_auto_create_analog_input_ctls(spec, &spec->autocfg); |
5299 | if (err < 0) | 5598 | if (err < 0) |
@@ -5303,28 +5602,14 @@ static int alc260_parse_auto_config(struct hda_codec *codec) | |||
5303 | 5602 | ||
5304 | if (spec->autocfg.dig_out_pin) | 5603 | if (spec->autocfg.dig_out_pin) |
5305 | spec->multiout.dig_out_nid = ALC260_DIGOUT_NID; | 5604 | spec->multiout.dig_out_nid = ALC260_DIGOUT_NID; |
5306 | if (spec->kctl_alloc) | 5605 | if (spec->kctls.list) |
5307 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 5606 | add_mixer(spec, spec->kctls.list); |
5308 | 5607 | ||
5309 | spec->init_verbs[spec->num_init_verbs++] = alc260_volume_init_verbs; | 5608 | add_verb(spec, alc260_volume_init_verbs); |
5310 | 5609 | ||
5311 | spec->num_mux_defs = 1; | 5610 | spec->num_mux_defs = 1; |
5312 | spec->input_mux = &spec->private_imux; | 5611 | spec->input_mux = &spec->private_imux; |
5313 | 5612 | ||
5314 | /* check whether NID 0x04 is valid */ | ||
5315 | wcap = get_wcaps(codec, 0x04); | ||
5316 | wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */ | ||
5317 | if (wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) { | ||
5318 | spec->adc_nids = alc260_adc_nids_alt; | ||
5319 | spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt); | ||
5320 | spec->mixers[spec->num_mixers] = alc260_capture_alt_mixer; | ||
5321 | } else { | ||
5322 | spec->adc_nids = alc260_adc_nids; | ||
5323 | spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids); | ||
5324 | spec->mixers[spec->num_mixers] = alc260_capture_mixer; | ||
5325 | } | ||
5326 | spec->num_mixers++; | ||
5327 | |||
5328 | store_pin_configs(codec); | 5613 | store_pin_configs(codec); |
5329 | return 1; | 5614 | return 1; |
5330 | } | 5615 | } |
@@ -5394,12 +5679,11 @@ static struct alc_config_preset alc260_presets[] = { | |||
5394 | [ALC260_BASIC] = { | 5679 | [ALC260_BASIC] = { |
5395 | .mixers = { alc260_base_output_mixer, | 5680 | .mixers = { alc260_base_output_mixer, |
5396 | alc260_input_mixer, | 5681 | alc260_input_mixer, |
5397 | alc260_pc_beep_mixer, | 5682 | alc260_pc_beep_mixer }, |
5398 | alc260_capture_mixer }, | ||
5399 | .init_verbs = { alc260_init_verbs }, | 5683 | .init_verbs = { alc260_init_verbs }, |
5400 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), | 5684 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), |
5401 | .dac_nids = alc260_dac_nids, | 5685 | .dac_nids = alc260_dac_nids, |
5402 | .num_adc_nids = ARRAY_SIZE(alc260_adc_nids), | 5686 | .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids), |
5403 | .adc_nids = alc260_adc_nids, | 5687 | .adc_nids = alc260_adc_nids, |
5404 | .num_channel_mode = ARRAY_SIZE(alc260_modes), | 5688 | .num_channel_mode = ARRAY_SIZE(alc260_modes), |
5405 | .channel_mode = alc260_modes, | 5689 | .channel_mode = alc260_modes, |
@@ -5407,14 +5691,13 @@ static struct alc_config_preset alc260_presets[] = { | |||
5407 | }, | 5691 | }, |
5408 | [ALC260_HP] = { | 5692 | [ALC260_HP] = { |
5409 | .mixers = { alc260_hp_output_mixer, | 5693 | .mixers = { alc260_hp_output_mixer, |
5410 | alc260_input_mixer, | 5694 | alc260_input_mixer }, |
5411 | alc260_capture_alt_mixer }, | ||
5412 | .init_verbs = { alc260_init_verbs, | 5695 | .init_verbs = { alc260_init_verbs, |
5413 | alc260_hp_unsol_verbs }, | 5696 | alc260_hp_unsol_verbs }, |
5414 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), | 5697 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), |
5415 | .dac_nids = alc260_dac_nids, | 5698 | .dac_nids = alc260_dac_nids, |
5416 | .num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids), | 5699 | .num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt), |
5417 | .adc_nids = alc260_hp_adc_nids, | 5700 | .adc_nids = alc260_adc_nids_alt, |
5418 | .num_channel_mode = ARRAY_SIZE(alc260_modes), | 5701 | .num_channel_mode = ARRAY_SIZE(alc260_modes), |
5419 | .channel_mode = alc260_modes, | 5702 | .channel_mode = alc260_modes, |
5420 | .input_mux = &alc260_capture_source, | 5703 | .input_mux = &alc260_capture_source, |
@@ -5423,14 +5706,13 @@ static struct alc_config_preset alc260_presets[] = { | |||
5423 | }, | 5706 | }, |
5424 | [ALC260_HP_DC7600] = { | 5707 | [ALC260_HP_DC7600] = { |
5425 | .mixers = { alc260_hp_dc7600_mixer, | 5708 | .mixers = { alc260_hp_dc7600_mixer, |
5426 | alc260_input_mixer, | 5709 | alc260_input_mixer }, |
5427 | alc260_capture_alt_mixer }, | ||
5428 | .init_verbs = { alc260_init_verbs, | 5710 | .init_verbs = { alc260_init_verbs, |
5429 | alc260_hp_dc7600_verbs }, | 5711 | alc260_hp_dc7600_verbs }, |
5430 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), | 5712 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), |
5431 | .dac_nids = alc260_dac_nids, | 5713 | .dac_nids = alc260_dac_nids, |
5432 | .num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids), | 5714 | .num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt), |
5433 | .adc_nids = alc260_hp_adc_nids, | 5715 | .adc_nids = alc260_adc_nids_alt, |
5434 | .num_channel_mode = ARRAY_SIZE(alc260_modes), | 5716 | .num_channel_mode = ARRAY_SIZE(alc260_modes), |
5435 | .channel_mode = alc260_modes, | 5717 | .channel_mode = alc260_modes, |
5436 | .input_mux = &alc260_capture_source, | 5718 | .input_mux = &alc260_capture_source, |
@@ -5439,14 +5721,13 @@ static struct alc_config_preset alc260_presets[] = { | |||
5439 | }, | 5721 | }, |
5440 | [ALC260_HP_3013] = { | 5722 | [ALC260_HP_3013] = { |
5441 | .mixers = { alc260_hp_3013_mixer, | 5723 | .mixers = { alc260_hp_3013_mixer, |
5442 | alc260_input_mixer, | 5724 | alc260_input_mixer }, |
5443 | alc260_capture_alt_mixer }, | ||
5444 | .init_verbs = { alc260_hp_3013_init_verbs, | 5725 | .init_verbs = { alc260_hp_3013_init_verbs, |
5445 | alc260_hp_3013_unsol_verbs }, | 5726 | alc260_hp_3013_unsol_verbs }, |
5446 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), | 5727 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), |
5447 | .dac_nids = alc260_dac_nids, | 5728 | .dac_nids = alc260_dac_nids, |
5448 | .num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids), | 5729 | .num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt), |
5449 | .adc_nids = alc260_hp_adc_nids, | 5730 | .adc_nids = alc260_adc_nids_alt, |
5450 | .num_channel_mode = ARRAY_SIZE(alc260_modes), | 5731 | .num_channel_mode = ARRAY_SIZE(alc260_modes), |
5451 | .channel_mode = alc260_modes, | 5732 | .channel_mode = alc260_modes, |
5452 | .input_mux = &alc260_capture_source, | 5733 | .input_mux = &alc260_capture_source, |
@@ -5454,8 +5735,7 @@ static struct alc_config_preset alc260_presets[] = { | |||
5454 | .init_hook = alc260_hp_3013_automute, | 5735 | .init_hook = alc260_hp_3013_automute, |
5455 | }, | 5736 | }, |
5456 | [ALC260_FUJITSU_S702X] = { | 5737 | [ALC260_FUJITSU_S702X] = { |
5457 | .mixers = { alc260_fujitsu_mixer, | 5738 | .mixers = { alc260_fujitsu_mixer }, |
5458 | alc260_capture_mixer }, | ||
5459 | .init_verbs = { alc260_fujitsu_init_verbs }, | 5739 | .init_verbs = { alc260_fujitsu_init_verbs }, |
5460 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), | 5740 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), |
5461 | .dac_nids = alc260_dac_nids, | 5741 | .dac_nids = alc260_dac_nids, |
@@ -5467,8 +5747,7 @@ static struct alc_config_preset alc260_presets[] = { | |||
5467 | .input_mux = alc260_fujitsu_capture_sources, | 5747 | .input_mux = alc260_fujitsu_capture_sources, |
5468 | }, | 5748 | }, |
5469 | [ALC260_ACER] = { | 5749 | [ALC260_ACER] = { |
5470 | .mixers = { alc260_acer_mixer, | 5750 | .mixers = { alc260_acer_mixer }, |
5471 | alc260_capture_mixer }, | ||
5472 | .init_verbs = { alc260_acer_init_verbs }, | 5751 | .init_verbs = { alc260_acer_init_verbs }, |
5473 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), | 5752 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), |
5474 | .dac_nids = alc260_dac_nids, | 5753 | .dac_nids = alc260_dac_nids, |
@@ -5480,8 +5759,7 @@ static struct alc_config_preset alc260_presets[] = { | |||
5480 | .input_mux = alc260_acer_capture_sources, | 5759 | .input_mux = alc260_acer_capture_sources, |
5481 | }, | 5760 | }, |
5482 | [ALC260_WILL] = { | 5761 | [ALC260_WILL] = { |
5483 | .mixers = { alc260_will_mixer, | 5762 | .mixers = { alc260_will_mixer }, |
5484 | alc260_capture_mixer }, | ||
5485 | .init_verbs = { alc260_init_verbs, alc260_will_verbs }, | 5763 | .init_verbs = { alc260_init_verbs, alc260_will_verbs }, |
5486 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), | 5764 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), |
5487 | .dac_nids = alc260_dac_nids, | 5765 | .dac_nids = alc260_dac_nids, |
@@ -5493,8 +5771,7 @@ static struct alc_config_preset alc260_presets[] = { | |||
5493 | .input_mux = &alc260_capture_source, | 5771 | .input_mux = &alc260_capture_source, |
5494 | }, | 5772 | }, |
5495 | [ALC260_REPLACER_672V] = { | 5773 | [ALC260_REPLACER_672V] = { |
5496 | .mixers = { alc260_replacer_672v_mixer, | 5774 | .mixers = { alc260_replacer_672v_mixer }, |
5497 | alc260_capture_mixer }, | ||
5498 | .init_verbs = { alc260_init_verbs, alc260_replacer_672v_verbs }, | 5775 | .init_verbs = { alc260_init_verbs, alc260_replacer_672v_verbs }, |
5499 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), | 5776 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), |
5500 | .dac_nids = alc260_dac_nids, | 5777 | .dac_nids = alc260_dac_nids, |
@@ -5509,8 +5786,7 @@ static struct alc_config_preset alc260_presets[] = { | |||
5509 | }, | 5786 | }, |
5510 | #ifdef CONFIG_SND_DEBUG | 5787 | #ifdef CONFIG_SND_DEBUG |
5511 | [ALC260_TEST] = { | 5788 | [ALC260_TEST] = { |
5512 | .mixers = { alc260_test_mixer, | 5789 | .mixers = { alc260_test_mixer }, |
5513 | alc260_capture_mixer }, | ||
5514 | .init_verbs = { alc260_test_init_verbs }, | 5790 | .init_verbs = { alc260_test_init_verbs }, |
5515 | .num_dacs = ARRAY_SIZE(alc260_test_dac_nids), | 5791 | .num_dacs = ARRAY_SIZE(alc260_test_dac_nids), |
5516 | .dac_nids = alc260_test_dac_nids, | 5792 | .dac_nids = alc260_test_dac_nids, |
@@ -5569,6 +5845,21 @@ static int patch_alc260(struct hda_codec *codec) | |||
5569 | spec->stream_digital_playback = &alc260_pcm_digital_playback; | 5845 | spec->stream_digital_playback = &alc260_pcm_digital_playback; |
5570 | spec->stream_digital_capture = &alc260_pcm_digital_capture; | 5846 | spec->stream_digital_capture = &alc260_pcm_digital_capture; |
5571 | 5847 | ||
5848 | if (!spec->adc_nids && spec->input_mux) { | ||
5849 | /* check whether NID 0x04 is valid */ | ||
5850 | unsigned int wcap = get_wcaps(codec, 0x04); | ||
5851 | wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; | ||
5852 | /* get type */ | ||
5853 | if (wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) { | ||
5854 | spec->adc_nids = alc260_adc_nids_alt; | ||
5855 | spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt); | ||
5856 | } else { | ||
5857 | spec->adc_nids = alc260_adc_nids; | ||
5858 | spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids); | ||
5859 | } | ||
5860 | } | ||
5861 | set_capture_mixer(spec); | ||
5862 | |||
5572 | spec->vmaster_nid = 0x08; | 5863 | spec->vmaster_nid = 0x08; |
5573 | 5864 | ||
5574 | codec->patch_ops = alc_patch_ops; | 5865 | codec->patch_ops = alc_patch_ops; |
@@ -5625,36 +5916,6 @@ static struct hda_input_mux alc882_capture_source = { | |||
5625 | { "CD", 0x4 }, | 5916 | { "CD", 0x4 }, |
5626 | }, | 5917 | }, |
5627 | }; | 5918 | }; |
5628 | #define alc882_mux_enum_info alc_mux_enum_info | ||
5629 | #define alc882_mux_enum_get alc_mux_enum_get | ||
5630 | |||
5631 | static int alc882_mux_enum_put(struct snd_kcontrol *kcontrol, | ||
5632 | struct snd_ctl_elem_value *ucontrol) | ||
5633 | { | ||
5634 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
5635 | struct alc_spec *spec = codec->spec; | ||
5636 | const struct hda_input_mux *imux = spec->input_mux; | ||
5637 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | ||
5638 | hda_nid_t nid = spec->capsrc_nids ? | ||
5639 | spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx]; | ||
5640 | unsigned int *cur_val = &spec->cur_mux[adc_idx]; | ||
5641 | unsigned int i, idx; | ||
5642 | |||
5643 | idx = ucontrol->value.enumerated.item[0]; | ||
5644 | if (idx >= imux->num_items) | ||
5645 | idx = imux->num_items - 1; | ||
5646 | if (*cur_val == idx) | ||
5647 | return 0; | ||
5648 | for (i = 0; i < imux->num_items; i++) { | ||
5649 | unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE; | ||
5650 | snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, | ||
5651 | imux->items[i].index, | ||
5652 | HDA_AMP_MUTE, v); | ||
5653 | } | ||
5654 | *cur_val = idx; | ||
5655 | return 1; | ||
5656 | } | ||
5657 | |||
5658 | /* | 5919 | /* |
5659 | * 2ch mode | 5920 | * 2ch mode |
5660 | */ | 5921 | */ |
@@ -6337,49 +6598,6 @@ static struct hda_verb alc882_auto_init_verbs[] = { | |||
6337 | { } | 6598 | { } |
6338 | }; | 6599 | }; |
6339 | 6600 | ||
6340 | /* capture mixer elements */ | ||
6341 | static struct snd_kcontrol_new alc882_capture_alt_mixer[] = { | ||
6342 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
6343 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
6344 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), | ||
6345 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), | ||
6346 | { | ||
6347 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
6348 | /* The multiple "Capture Source" controls confuse alsamixer | ||
6349 | * So call somewhat different.. | ||
6350 | */ | ||
6351 | /* .name = "Capture Source", */ | ||
6352 | .name = "Input Source", | ||
6353 | .count = 2, | ||
6354 | .info = alc882_mux_enum_info, | ||
6355 | .get = alc882_mux_enum_get, | ||
6356 | .put = alc882_mux_enum_put, | ||
6357 | }, | ||
6358 | { } /* end */ | ||
6359 | }; | ||
6360 | |||
6361 | static struct snd_kcontrol_new alc882_capture_mixer[] = { | ||
6362 | HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT), | ||
6363 | HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT), | ||
6364 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT), | ||
6365 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT), | ||
6366 | HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT), | ||
6367 | HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT), | ||
6368 | { | ||
6369 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
6370 | /* The multiple "Capture Source" controls confuse alsamixer | ||
6371 | * So call somewhat different.. | ||
6372 | */ | ||
6373 | /* .name = "Capture Source", */ | ||
6374 | .name = "Input Source", | ||
6375 | .count = 3, | ||
6376 | .info = alc882_mux_enum_info, | ||
6377 | .get = alc882_mux_enum_get, | ||
6378 | .put = alc882_mux_enum_put, | ||
6379 | }, | ||
6380 | { } /* end */ | ||
6381 | }; | ||
6382 | |||
6383 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 6601 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
6384 | #define alc882_loopbacks alc880_loopbacks | 6602 | #define alc882_loopbacks alc880_loopbacks |
6385 | #endif | 6603 | #endif |
@@ -6508,8 +6726,7 @@ static struct alc_config_preset alc882_presets[] = { | |||
6508 | .init_hook = alc885_imac24_init_hook, | 6726 | .init_hook = alc885_imac24_init_hook, |
6509 | }, | 6727 | }, |
6510 | [ALC882_TARGA] = { | 6728 | [ALC882_TARGA] = { |
6511 | .mixers = { alc882_targa_mixer, alc882_chmode_mixer, | 6729 | .mixers = { alc882_targa_mixer, alc882_chmode_mixer }, |
6512 | alc882_capture_mixer }, | ||
6513 | .init_verbs = { alc882_init_verbs, alc882_targa_verbs}, | 6730 | .init_verbs = { alc882_init_verbs, alc882_targa_verbs}, |
6514 | .num_dacs = ARRAY_SIZE(alc882_dac_nids), | 6731 | .num_dacs = ARRAY_SIZE(alc882_dac_nids), |
6515 | .dac_nids = alc882_dac_nids, | 6732 | .dac_nids = alc882_dac_nids, |
@@ -6525,8 +6742,7 @@ static struct alc_config_preset alc882_presets[] = { | |||
6525 | .init_hook = alc882_targa_automute, | 6742 | .init_hook = alc882_targa_automute, |
6526 | }, | 6743 | }, |
6527 | [ALC882_ASUS_A7J] = { | 6744 | [ALC882_ASUS_A7J] = { |
6528 | .mixers = { alc882_asus_a7j_mixer, alc882_chmode_mixer, | 6745 | .mixers = { alc882_asus_a7j_mixer, alc882_chmode_mixer }, |
6529 | alc882_capture_mixer }, | ||
6530 | .init_verbs = { alc882_init_verbs, alc882_asus_a7j_verbs}, | 6746 | .init_verbs = { alc882_init_verbs, alc882_asus_a7j_verbs}, |
6531 | .num_dacs = ARRAY_SIZE(alc882_dac_nids), | 6747 | .num_dacs = ARRAY_SIZE(alc882_dac_nids), |
6532 | .dac_nids = alc882_dac_nids, | 6748 | .dac_nids = alc882_dac_nids, |
@@ -6831,6 +7047,7 @@ static int patch_alc882(struct hda_codec *codec) | |||
6831 | spec->stream_digital_playback = &alc882_pcm_digital_playback; | 7047 | spec->stream_digital_playback = &alc882_pcm_digital_playback; |
6832 | spec->stream_digital_capture = &alc882_pcm_digital_capture; | 7048 | spec->stream_digital_capture = &alc882_pcm_digital_capture; |
6833 | 7049 | ||
7050 | spec->is_mix_capture = 1; /* matrix-style capture */ | ||
6834 | if (!spec->adc_nids && spec->input_mux) { | 7051 | if (!spec->adc_nids && spec->input_mux) { |
6835 | /* check whether NID 0x07 is valid */ | 7052 | /* check whether NID 0x07 is valid */ |
6836 | unsigned int wcap = get_wcaps(codec, 0x07); | 7053 | unsigned int wcap = get_wcaps(codec, 0x07); |
@@ -6840,17 +7057,13 @@ static int patch_alc882(struct hda_codec *codec) | |||
6840 | spec->adc_nids = alc882_adc_nids_alt; | 7057 | spec->adc_nids = alc882_adc_nids_alt; |
6841 | spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids_alt); | 7058 | spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids_alt); |
6842 | spec->capsrc_nids = alc882_capsrc_nids_alt; | 7059 | spec->capsrc_nids = alc882_capsrc_nids_alt; |
6843 | spec->mixers[spec->num_mixers] = | ||
6844 | alc882_capture_alt_mixer; | ||
6845 | spec->num_mixers++; | ||
6846 | } else { | 7060 | } else { |
6847 | spec->adc_nids = alc882_adc_nids; | 7061 | spec->adc_nids = alc882_adc_nids; |
6848 | spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids); | 7062 | spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids); |
6849 | spec->capsrc_nids = alc882_capsrc_nids; | 7063 | spec->capsrc_nids = alc882_capsrc_nids; |
6850 | spec->mixers[spec->num_mixers] = alc882_capture_mixer; | ||
6851 | spec->num_mixers++; | ||
6852 | } | 7064 | } |
6853 | } | 7065 | } |
7066 | set_capture_mixer(spec); | ||
6854 | 7067 | ||
6855 | spec->vmaster_nid = 0x0c; | 7068 | spec->vmaster_nid = 0x0c; |
6856 | 7069 | ||
@@ -6879,6 +7092,8 @@ static int patch_alc882(struct hda_codec *codec) | |||
6879 | #define ALC883_DIGOUT_NID 0x06 | 7092 | #define ALC883_DIGOUT_NID 0x06 |
6880 | #define ALC883_DIGIN_NID 0x0a | 7093 | #define ALC883_DIGIN_NID 0x0a |
6881 | 7094 | ||
7095 | #define ALC1200_DIGOUT_NID 0x10 | ||
7096 | |||
6882 | static hda_nid_t alc883_dac_nids[4] = { | 7097 | static hda_nid_t alc883_dac_nids[4] = { |
6883 | /* front, rear, clfe, rear_surr */ | 7098 | /* front, rear, clfe, rear_surr */ |
6884 | 0x02, 0x03, 0x04, 0x05 | 7099 | 0x02, 0x03, 0x04, 0x05 |
@@ -6889,8 +7104,20 @@ static hda_nid_t alc883_adc_nids[2] = { | |||
6889 | 0x08, 0x09, | 7104 | 0x08, 0x09, |
6890 | }; | 7105 | }; |
6891 | 7106 | ||
7107 | static hda_nid_t alc883_adc_nids_alt[1] = { | ||
7108 | /* ADC1 */ | ||
7109 | 0x08, | ||
7110 | }; | ||
7111 | |||
7112 | static hda_nid_t alc883_adc_nids_rev[2] = { | ||
7113 | /* ADC2-1 */ | ||
7114 | 0x09, 0x08 | ||
7115 | }; | ||
7116 | |||
6892 | static hda_nid_t alc883_capsrc_nids[2] = { 0x23, 0x22 }; | 7117 | static hda_nid_t alc883_capsrc_nids[2] = { 0x23, 0x22 }; |
6893 | 7118 | ||
7119 | static hda_nid_t alc883_capsrc_nids_rev[2] = { 0x22, 0x23 }; | ||
7120 | |||
6894 | /* input MUX */ | 7121 | /* input MUX */ |
6895 | /* FIXME: should be a matrix-type input source selection */ | 7122 | /* FIXME: should be a matrix-type input source selection */ |
6896 | 7123 | ||
@@ -6957,11 +7184,6 @@ static struct hda_input_mux alc883_asus_eee1601_capture_source = { | |||
6957 | }, | 7184 | }, |
6958 | }; | 7185 | }; |
6959 | 7186 | ||
6960 | #define alc883_mux_enum_info alc_mux_enum_info | ||
6961 | #define alc883_mux_enum_get alc_mux_enum_get | ||
6962 | /* ALC883 has the ALC882-type input selection */ | ||
6963 | #define alc883_mux_enum_put alc882_mux_enum_put | ||
6964 | |||
6965 | /* | 7187 | /* |
6966 | * 2ch mode | 7188 | * 2ch mode |
6967 | */ | 7189 | */ |
@@ -7115,19 +7337,6 @@ static struct snd_kcontrol_new alc883_base_mixer[] = { | |||
7115 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 7337 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
7116 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | 7338 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), |
7117 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | 7339 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), |
7118 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
7119 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
7120 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), | ||
7121 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), | ||
7122 | { | ||
7123 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
7124 | /* .name = "Capture Source", */ | ||
7125 | .name = "Input Source", | ||
7126 | .count = 2, | ||
7127 | .info = alc883_mux_enum_info, | ||
7128 | .get = alc883_mux_enum_get, | ||
7129 | .put = alc883_mux_enum_put, | ||
7130 | }, | ||
7131 | { } /* end */ | 7340 | { } /* end */ |
7132 | }; | 7341 | }; |
7133 | 7342 | ||
@@ -7145,19 +7354,6 @@ static struct snd_kcontrol_new alc883_mitac_mixer[] = { | |||
7145 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 7354 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
7146 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | 7355 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), |
7147 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 7356 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
7148 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
7149 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
7150 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), | ||
7151 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), | ||
7152 | { | ||
7153 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
7154 | /* .name = "Capture Source", */ | ||
7155 | .name = "Input Source", | ||
7156 | .count = 2, | ||
7157 | .info = alc883_mux_enum_info, | ||
7158 | .get = alc883_mux_enum_get, | ||
7159 | .put = alc883_mux_enum_put, | ||
7160 | }, | ||
7161 | { } /* end */ | 7357 | { } /* end */ |
7162 | }; | 7358 | }; |
7163 | 7359 | ||
@@ -7172,19 +7368,6 @@ static struct snd_kcontrol_new alc883_clevo_m720_mixer[] = { | |||
7172 | HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 7368 | HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
7173 | HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT), | 7369 | HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT), |
7174 | HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 7370 | HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
7175 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
7176 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
7177 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), | ||
7178 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), | ||
7179 | { | ||
7180 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
7181 | /* .name = "Capture Source", */ | ||
7182 | .name = "Input Source", | ||
7183 | .count = 2, | ||
7184 | .info = alc883_mux_enum_info, | ||
7185 | .get = alc883_mux_enum_get, | ||
7186 | .put = alc883_mux_enum_put, | ||
7187 | }, | ||
7188 | { } /* end */ | 7371 | { } /* end */ |
7189 | }; | 7372 | }; |
7190 | 7373 | ||
@@ -7199,19 +7382,6 @@ static struct snd_kcontrol_new alc883_2ch_fujitsu_pi2515_mixer[] = { | |||
7199 | HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 7382 | HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
7200 | HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT), | 7383 | HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT), |
7201 | HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 7384 | HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
7202 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
7203 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
7204 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), | ||
7205 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), | ||
7206 | { | ||
7207 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
7208 | /* .name = "Capture Source", */ | ||
7209 | .name = "Input Source", | ||
7210 | .count = 2, | ||
7211 | .info = alc883_mux_enum_info, | ||
7212 | .get = alc883_mux_enum_get, | ||
7213 | .put = alc883_mux_enum_put, | ||
7214 | }, | ||
7215 | { } /* end */ | 7385 | { } /* end */ |
7216 | }; | 7386 | }; |
7217 | 7387 | ||
@@ -7231,19 +7401,6 @@ static struct snd_kcontrol_new alc883_3ST_2ch_mixer[] = { | |||
7231 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 7401 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
7232 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | 7402 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), |
7233 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | 7403 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), |
7234 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
7235 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
7236 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), | ||
7237 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), | ||
7238 | { | ||
7239 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
7240 | /* .name = "Capture Source", */ | ||
7241 | .name = "Input Source", | ||
7242 | .count = 2, | ||
7243 | .info = alc883_mux_enum_info, | ||
7244 | .get = alc883_mux_enum_get, | ||
7245 | .put = alc883_mux_enum_put, | ||
7246 | }, | ||
7247 | { } /* end */ | 7404 | { } /* end */ |
7248 | }; | 7405 | }; |
7249 | 7406 | ||
@@ -7269,17 +7426,6 @@ static struct snd_kcontrol_new alc883_3ST_6ch_mixer[] = { | |||
7269 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 7426 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
7270 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | 7427 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), |
7271 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | 7428 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), |
7272 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
7273 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
7274 | { | ||
7275 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
7276 | /* .name = "Capture Source", */ | ||
7277 | .name = "Input Source", | ||
7278 | .count = 1, | ||
7279 | .info = alc883_mux_enum_info, | ||
7280 | .get = alc883_mux_enum_get, | ||
7281 | .put = alc883_mux_enum_put, | ||
7282 | }, | ||
7283 | { } /* end */ | 7429 | { } /* end */ |
7284 | }; | 7430 | }; |
7285 | 7431 | ||
@@ -7306,19 +7452,6 @@ static struct snd_kcontrol_new alc883_3ST_6ch_intel_mixer[] = { | |||
7306 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 7452 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
7307 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | 7453 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), |
7308 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | 7454 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), |
7309 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
7310 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
7311 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), | ||
7312 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), | ||
7313 | { | ||
7314 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
7315 | /* .name = "Capture Source", */ | ||
7316 | .name = "Input Source", | ||
7317 | .count = 2, | ||
7318 | .info = alc883_mux_enum_info, | ||
7319 | .get = alc883_mux_enum_get, | ||
7320 | .put = alc883_mux_enum_put, | ||
7321 | }, | ||
7322 | { } /* end */ | 7455 | { } /* end */ |
7323 | }; | 7456 | }; |
7324 | 7457 | ||
@@ -7344,18 +7477,6 @@ static struct snd_kcontrol_new alc883_fivestack_mixer[] = { | |||
7344 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 7477 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
7345 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | 7478 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), |
7346 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | 7479 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), |
7347 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
7348 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
7349 | |||
7350 | { | ||
7351 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
7352 | /* .name = "Capture Source", */ | ||
7353 | .name = "Input Source", | ||
7354 | .count = 1, | ||
7355 | .info = alc883_mux_enum_info, | ||
7356 | .get = alc883_mux_enum_get, | ||
7357 | .put = alc883_mux_enum_put, | ||
7358 | }, | ||
7359 | { } /* end */ | 7480 | { } /* end */ |
7360 | }; | 7481 | }; |
7361 | 7482 | ||
@@ -7376,19 +7497,6 @@ static struct snd_kcontrol_new alc883_tagra_mixer[] = { | |||
7376 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 7497 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
7377 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 7498 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), |
7378 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 7499 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
7379 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
7380 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
7381 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), | ||
7382 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), | ||
7383 | { | ||
7384 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
7385 | /* .name = "Capture Source", */ | ||
7386 | .name = "Input Source", | ||
7387 | .count = 2, | ||
7388 | .info = alc883_mux_enum_info, | ||
7389 | .get = alc883_mux_enum_get, | ||
7390 | .put = alc883_mux_enum_put, | ||
7391 | }, | ||
7392 | { } /* end */ | 7500 | { } /* end */ |
7393 | }; | 7501 | }; |
7394 | 7502 | ||
@@ -7404,19 +7512,6 @@ static struct snd_kcontrol_new alc883_tagra_2ch_mixer[] = { | |||
7404 | HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 7512 | HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
7405 | HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT), | 7513 | HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT), |
7406 | HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 7514 | HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
7407 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
7408 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
7409 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), | ||
7410 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), | ||
7411 | { | ||
7412 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
7413 | /* .name = "Capture Source", */ | ||
7414 | .name = "Input Source", | ||
7415 | .count = 2, | ||
7416 | .info = alc883_mux_enum_info, | ||
7417 | .get = alc883_mux_enum_get, | ||
7418 | .put = alc883_mux_enum_put, | ||
7419 | }, | ||
7420 | { } /* end */ | 7515 | { } /* end */ |
7421 | }; | 7516 | }; |
7422 | 7517 | ||
@@ -7429,17 +7524,6 @@ static struct snd_kcontrol_new alc883_lenovo_101e_2ch_mixer[] = { | |||
7429 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 7524 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
7430 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 7525 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), |
7431 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 7526 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
7432 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
7433 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
7434 | { | ||
7435 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
7436 | /* .name = "Capture Source", */ | ||
7437 | .name = "Input Source", | ||
7438 | .count = 1, | ||
7439 | .info = alc883_mux_enum_info, | ||
7440 | .get = alc883_mux_enum_get, | ||
7441 | .put = alc883_mux_enum_put, | ||
7442 | }, | ||
7443 | { } /* end */ | 7527 | { } /* end */ |
7444 | }; | 7528 | }; |
7445 | 7529 | ||
@@ -7453,19 +7537,6 @@ static struct snd_kcontrol_new alc883_lenovo_nb0763_mixer[] = { | |||
7453 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 7537 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
7454 | HDA_CODEC_VOLUME("iMic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 7538 | HDA_CODEC_VOLUME("iMic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
7455 | HDA_CODEC_MUTE("iMic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 7539 | HDA_CODEC_MUTE("iMic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
7456 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
7457 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
7458 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), | ||
7459 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), | ||
7460 | { | ||
7461 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
7462 | /* .name = "Capture Source", */ | ||
7463 | .name = "Input Source", | ||
7464 | .count = 2, | ||
7465 | .info = alc883_mux_enum_info, | ||
7466 | .get = alc883_mux_enum_get, | ||
7467 | .put = alc883_mux_enum_put, | ||
7468 | }, | ||
7469 | { } /* end */ | 7540 | { } /* end */ |
7470 | }; | 7541 | }; |
7471 | 7542 | ||
@@ -7479,19 +7550,6 @@ static struct snd_kcontrol_new alc883_medion_md2_mixer[] = { | |||
7479 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 7550 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
7480 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | 7551 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), |
7481 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | 7552 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), |
7482 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
7483 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
7484 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), | ||
7485 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), | ||
7486 | { | ||
7487 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
7488 | /* .name = "Capture Source", */ | ||
7489 | .name = "Input Source", | ||
7490 | .count = 2, | ||
7491 | .info = alc883_mux_enum_info, | ||
7492 | .get = alc883_mux_enum_get, | ||
7493 | .put = alc883_mux_enum_put, | ||
7494 | }, | ||
7495 | { } /* end */ | 7553 | { } /* end */ |
7496 | }; | 7554 | }; |
7497 | 7555 | ||
@@ -7504,19 +7562,6 @@ static struct snd_kcontrol_new alc883_acer_aspire_mixer[] = { | |||
7504 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 7562 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
7505 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 7563 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), |
7506 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 7564 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
7507 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
7508 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
7509 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), | ||
7510 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), | ||
7511 | { | ||
7512 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
7513 | /* .name = "Capture Source", */ | ||
7514 | .name = "Input Source", | ||
7515 | .count = 2, | ||
7516 | .info = alc883_mux_enum_info, | ||
7517 | .get = alc883_mux_enum_get, | ||
7518 | .put = alc883_mux_enum_put, | ||
7519 | }, | ||
7520 | { } /* end */ | 7565 | { } /* end */ |
7521 | }; | 7566 | }; |
7522 | 7567 | ||
@@ -7544,19 +7589,6 @@ static struct snd_kcontrol_new alc888_lenovo_sky_mixer[] = { | |||
7544 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 7589 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
7545 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | 7590 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), |
7546 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 7591 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
7547 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
7548 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
7549 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), | ||
7550 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), | ||
7551 | { | ||
7552 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
7553 | /* .name = "Capture Source", */ | ||
7554 | .name = "Input Source", | ||
7555 | .count = 2, | ||
7556 | .info = alc883_mux_enum_info, | ||
7557 | .get = alc883_mux_enum_get, | ||
7558 | .put = alc883_mux_enum_put, | ||
7559 | }, | ||
7560 | { } /* end */ | 7592 | { } /* end */ |
7561 | }; | 7593 | }; |
7562 | 7594 | ||
@@ -7587,6 +7619,10 @@ static struct snd_kcontrol_new alc883_asus_eee1601_mixer[] = { | |||
7587 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 7619 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
7588 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 7620 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), |
7589 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 7621 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
7622 | { } /* end */ | ||
7623 | }; | ||
7624 | |||
7625 | static struct snd_kcontrol_new alc883_asus_eee1601_cap_mixer[] = { | ||
7590 | HDA_BIND_VOL("Capture Volume", &alc883_bind_cap_vol), | 7626 | HDA_BIND_VOL("Capture Volume", &alc883_bind_cap_vol), |
7591 | HDA_BIND_SW("Capture Switch", &alc883_bind_cap_switch), | 7627 | HDA_BIND_SW("Capture Switch", &alc883_bind_cap_switch), |
7592 | { | 7628 | { |
@@ -7594,9 +7630,9 @@ static struct snd_kcontrol_new alc883_asus_eee1601_mixer[] = { | |||
7594 | /* .name = "Capture Source", */ | 7630 | /* .name = "Capture Source", */ |
7595 | .name = "Input Source", | 7631 | .name = "Input Source", |
7596 | .count = 1, | 7632 | .count = 1, |
7597 | .info = alc883_mux_enum_info, | 7633 | .info = alc_mux_enum_info, |
7598 | .get = alc883_mux_enum_get, | 7634 | .get = alc_mux_enum_get, |
7599 | .put = alc883_mux_enum_put, | 7635 | .put = alc_mux_enum_put, |
7600 | }, | 7636 | }, |
7601 | { } /* end */ | 7637 | { } /* end */ |
7602 | }; | 7638 | }; |
@@ -8251,27 +8287,6 @@ static struct hda_verb alc883_auto_init_verbs[] = { | |||
8251 | { } | 8287 | { } |
8252 | }; | 8288 | }; |
8253 | 8289 | ||
8254 | /* capture mixer elements */ | ||
8255 | static struct snd_kcontrol_new alc883_capture_mixer[] = { | ||
8256 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
8257 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
8258 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), | ||
8259 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), | ||
8260 | { | ||
8261 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
8262 | /* The multiple "Capture Source" controls confuse alsamixer | ||
8263 | * So call somewhat different.. | ||
8264 | */ | ||
8265 | /* .name = "Capture Source", */ | ||
8266 | .name = "Input Source", | ||
8267 | .count = 2, | ||
8268 | .info = alc882_mux_enum_info, | ||
8269 | .get = alc882_mux_enum_get, | ||
8270 | .put = alc882_mux_enum_put, | ||
8271 | }, | ||
8272 | { } /* end */ | ||
8273 | }; | ||
8274 | |||
8275 | static struct hda_verb alc888_asus_m90v_verbs[] = { | 8290 | static struct hda_verb alc888_asus_m90v_verbs[] = { |
8276 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | 8291 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
8277 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | 8292 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
@@ -8394,6 +8409,7 @@ static const char *alc883_models[ALC883_MODEL_LAST] = { | |||
8394 | [ALC883_TARGA_2ch_DIG] = "targa-2ch-dig", | 8409 | [ALC883_TARGA_2ch_DIG] = "targa-2ch-dig", |
8395 | [ALC883_ACER] = "acer", | 8410 | [ALC883_ACER] = "acer", |
8396 | [ALC883_ACER_ASPIRE] = "acer-aspire", | 8411 | [ALC883_ACER_ASPIRE] = "acer-aspire", |
8412 | [ALC888_ACER_ASPIRE_4930G] = "acer-aspire-4930g", | ||
8397 | [ALC883_MEDION] = "medion", | 8413 | [ALC883_MEDION] = "medion", |
8398 | [ALC883_MEDION_MD2] = "medion-md2", | 8414 | [ALC883_MEDION_MD2] = "medion-md2", |
8399 | [ALC883_LAPTOP_EAPD] = "laptop-eapd", | 8415 | [ALC883_LAPTOP_EAPD] = "laptop-eapd", |
@@ -8407,7 +8423,9 @@ static const char *alc883_models[ALC883_MODEL_LAST] = { | |||
8407 | [ALC883_MITAC] = "mitac", | 8423 | [ALC883_MITAC] = "mitac", |
8408 | [ALC883_CLEVO_M720] = "clevo-m720", | 8424 | [ALC883_CLEVO_M720] = "clevo-m720", |
8409 | [ALC883_FUJITSU_PI2515] = "fujitsu-pi2515", | 8425 | [ALC883_FUJITSU_PI2515] = "fujitsu-pi2515", |
8426 | [ALC888_FUJITSU_XA3530] = "fujitsu-xa3530", | ||
8410 | [ALC883_3ST_6ch_INTEL] = "3stack-6ch-intel", | 8427 | [ALC883_3ST_6ch_INTEL] = "3stack-6ch-intel", |
8428 | [ALC1200_ASUS_P5Q] = "asus-p5q", | ||
8411 | [ALC883_AUTO] = "auto", | 8429 | [ALC883_AUTO] = "auto", |
8412 | }; | 8430 | }; |
8413 | 8431 | ||
@@ -8418,6 +8436,8 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { | |||
8418 | SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_ACER_ASPIRE), | 8436 | SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_ACER_ASPIRE), |
8419 | SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_ACER_ASPIRE), | 8437 | SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_ACER_ASPIRE), |
8420 | SND_PCI_QUIRK(0x1025, 0x0121, "Acer Aspire 5920G", ALC883_ACER_ASPIRE), | 8438 | SND_PCI_QUIRK(0x1025, 0x0121, "Acer Aspire 5920G", ALC883_ACER_ASPIRE), |
8439 | SND_PCI_QUIRK(0x1025, 0x013e, "Acer Aspire 4930G", | ||
8440 | ALC888_ACER_ASPIRE_4930G), | ||
8421 | SND_PCI_QUIRK(0x1025, 0, "Acer laptop", ALC883_ACER), /* default Acer */ | 8441 | SND_PCI_QUIRK(0x1025, 0, "Acer laptop", ALC883_ACER), /* default Acer */ |
8422 | SND_PCI_QUIRK(0x1028, 0x020d, "Dell Inspiron 530", ALC888_6ST_DELL), | 8442 | SND_PCI_QUIRK(0x1028, 0x020d, "Dell Inspiron 530", ALC888_6ST_DELL), |
8423 | SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavillion", ALC883_6ST_DIG), | 8443 | SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavillion", ALC883_6ST_DIG), |
@@ -8426,6 +8446,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { | |||
8426 | SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC883_6ST_DIG), | 8446 | SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC883_6ST_DIG), |
8427 | SND_PCI_QUIRK(0x1043, 0x1873, "Asus M90V", ALC888_ASUS_M90V), | 8447 | SND_PCI_QUIRK(0x1043, 0x1873, "Asus M90V", ALC888_ASUS_M90V), |
8428 | SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG), | 8448 | SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG), |
8449 | SND_PCI_QUIRK(0x1043, 0x82fe, "Asus P5Q-EM HDMI", ALC1200_ASUS_P5Q), | ||
8429 | SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_ASUS_EEE1601), | 8450 | SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_ASUS_EEE1601), |
8430 | SND_PCI_QUIRK(0x105b, 0x0ce8, "Foxconn P35AX-S", ALC883_6ST_DIG), | 8451 | SND_PCI_QUIRK(0x105b, 0x0ce8, "Foxconn P35AX-S", ALC883_6ST_DIG), |
8431 | SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC883_6ST_DIG), | 8452 | SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC883_6ST_DIG), |
@@ -8463,6 +8484,8 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { | |||
8463 | SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch), | 8484 | SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch), |
8464 | SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION), | 8485 | SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION), |
8465 | SND_PCI_QUIRK(0x1734, 0x1108, "Fujitsu AMILO Pi2515", ALC883_FUJITSU_PI2515), | 8486 | SND_PCI_QUIRK(0x1734, 0x1108, "Fujitsu AMILO Pi2515", ALC883_FUJITSU_PI2515), |
8487 | SND_PCI_QUIRK(0x1734, 0x113d, "Fujitsu AMILO Xa3530", | ||
8488 | ALC888_FUJITSU_XA3530), | ||
8466 | SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo 101e", ALC883_LENOVO_101E_2ch), | 8489 | SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo 101e", ALC883_LENOVO_101E_2ch), |
8467 | SND_PCI_QUIRK(0x17aa, 0x2085, "Lenovo NB0763", ALC883_LENOVO_NB0763), | 8490 | SND_PCI_QUIRK(0x17aa, 0x2085, "Lenovo NB0763", ALC883_LENOVO_NB0763), |
8468 | SND_PCI_QUIRK(0x17aa, 0x3bfc, "Lenovo NB0763", ALC883_LENOVO_NB0763), | 8491 | SND_PCI_QUIRK(0x17aa, 0x3bfc, "Lenovo NB0763", ALC883_LENOVO_NB0763), |
@@ -8553,6 +8576,8 @@ static struct alc_config_preset alc883_presets[] = { | |||
8553 | .init_verbs = { alc883_init_verbs, alc883_tagra_verbs}, | 8576 | .init_verbs = { alc883_init_verbs, alc883_tagra_verbs}, |
8554 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), | 8577 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), |
8555 | .dac_nids = alc883_dac_nids, | 8578 | .dac_nids = alc883_dac_nids, |
8579 | .adc_nids = alc883_adc_nids_alt, | ||
8580 | .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt), | ||
8556 | .dig_out_nid = ALC883_DIGOUT_NID, | 8581 | .dig_out_nid = ALC883_DIGOUT_NID, |
8557 | .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), | 8582 | .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), |
8558 | .channel_mode = alc883_3ST_2ch_modes, | 8583 | .channel_mode = alc883_3ST_2ch_modes, |
@@ -8586,6 +8611,26 @@ static struct alc_config_preset alc883_presets[] = { | |||
8586 | .unsol_event = alc883_acer_aspire_unsol_event, | 8611 | .unsol_event = alc883_acer_aspire_unsol_event, |
8587 | .init_hook = alc883_acer_aspire_automute, | 8612 | .init_hook = alc883_acer_aspire_automute, |
8588 | }, | 8613 | }, |
8614 | [ALC888_ACER_ASPIRE_4930G] = { | ||
8615 | .mixers = { alc888_base_mixer, | ||
8616 | alc883_chmode_mixer }, | ||
8617 | .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs, | ||
8618 | alc888_acer_aspire_4930g_verbs }, | ||
8619 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), | ||
8620 | .dac_nids = alc883_dac_nids, | ||
8621 | .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev), | ||
8622 | .adc_nids = alc883_adc_nids_rev, | ||
8623 | .capsrc_nids = alc883_capsrc_nids_rev, | ||
8624 | .dig_out_nid = ALC883_DIGOUT_NID, | ||
8625 | .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes), | ||
8626 | .channel_mode = alc883_3ST_6ch_modes, | ||
8627 | .need_dac_fix = 1, | ||
8628 | .num_mux_defs = | ||
8629 | ARRAY_SIZE(alc888_2_capture_sources), | ||
8630 | .input_mux = alc888_2_capture_sources, | ||
8631 | .unsol_event = alc888_acer_aspire_4930g_unsol_event, | ||
8632 | .init_hook = alc888_acer_aspire_4930g_automute, | ||
8633 | }, | ||
8589 | [ALC883_MEDION] = { | 8634 | [ALC883_MEDION] = { |
8590 | .mixers = { alc883_fivestack_mixer, | 8635 | .mixers = { alc883_fivestack_mixer, |
8591 | alc883_chmode_mixer }, | 8636 | alc883_chmode_mixer }, |
@@ -8593,6 +8638,8 @@ static struct alc_config_preset alc883_presets[] = { | |||
8593 | alc883_medion_eapd_verbs }, | 8638 | alc883_medion_eapd_verbs }, |
8594 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), | 8639 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), |
8595 | .dac_nids = alc883_dac_nids, | 8640 | .dac_nids = alc883_dac_nids, |
8641 | .adc_nids = alc883_adc_nids_alt, | ||
8642 | .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt), | ||
8596 | .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes), | 8643 | .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes), |
8597 | .channel_mode = alc883_sixstack_modes, | 8644 | .channel_mode = alc883_sixstack_modes, |
8598 | .input_mux = &alc883_capture_source, | 8645 | .input_mux = &alc883_capture_source, |
@@ -8635,6 +8682,8 @@ static struct alc_config_preset alc883_presets[] = { | |||
8635 | .init_verbs = { alc883_init_verbs, alc883_lenovo_101e_verbs}, | 8682 | .init_verbs = { alc883_init_verbs, alc883_lenovo_101e_verbs}, |
8636 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), | 8683 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), |
8637 | .dac_nids = alc883_dac_nids, | 8684 | .dac_nids = alc883_dac_nids, |
8685 | .adc_nids = alc883_adc_nids_alt, | ||
8686 | .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt), | ||
8638 | .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), | 8687 | .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), |
8639 | .channel_mode = alc883_3ST_2ch_modes, | 8688 | .channel_mode = alc883_3ST_2ch_modes, |
8640 | .input_mux = &alc883_lenovo_101e_capture_source, | 8689 | .input_mux = &alc883_lenovo_101e_capture_source, |
@@ -8725,14 +8774,30 @@ static struct alc_config_preset alc883_presets[] = { | |||
8725 | .unsol_event = alc883_2ch_fujitsu_pi2515_unsol_event, | 8774 | .unsol_event = alc883_2ch_fujitsu_pi2515_unsol_event, |
8726 | .init_hook = alc883_2ch_fujitsu_pi2515_automute, | 8775 | .init_hook = alc883_2ch_fujitsu_pi2515_automute, |
8727 | }, | 8776 | }, |
8777 | [ALC888_FUJITSU_XA3530] = { | ||
8778 | .mixers = { alc888_base_mixer, alc883_chmode_mixer }, | ||
8779 | .init_verbs = { alc883_init_verbs, | ||
8780 | alc888_fujitsu_xa3530_verbs }, | ||
8781 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), | ||
8782 | .dac_nids = alc883_dac_nids, | ||
8783 | .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev), | ||
8784 | .adc_nids = alc883_adc_nids_rev, | ||
8785 | .capsrc_nids = alc883_capsrc_nids_rev, | ||
8786 | .dig_out_nid = ALC883_DIGOUT_NID, | ||
8787 | .num_channel_mode = ARRAY_SIZE(alc888_4ST_8ch_intel_modes), | ||
8788 | .channel_mode = alc888_4ST_8ch_intel_modes, | ||
8789 | .num_mux_defs = | ||
8790 | ARRAY_SIZE(alc888_2_capture_sources), | ||
8791 | .input_mux = alc888_2_capture_sources, | ||
8792 | .unsol_event = alc888_fujitsu_xa3530_unsol_event, | ||
8793 | .init_hook = alc888_fujitsu_xa3530_automute, | ||
8794 | }, | ||
8728 | [ALC888_LENOVO_SKY] = { | 8795 | [ALC888_LENOVO_SKY] = { |
8729 | .mixers = { alc888_lenovo_sky_mixer, alc883_chmode_mixer }, | 8796 | .mixers = { alc888_lenovo_sky_mixer, alc883_chmode_mixer }, |
8730 | .init_verbs = { alc883_init_verbs, alc888_lenovo_sky_verbs}, | 8797 | .init_verbs = { alc883_init_verbs, alc888_lenovo_sky_verbs}, |
8731 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), | 8798 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), |
8732 | .dac_nids = alc883_dac_nids, | 8799 | .dac_nids = alc883_dac_nids, |
8733 | .dig_out_nid = ALC883_DIGOUT_NID, | 8800 | .dig_out_nid = ALC883_DIGOUT_NID, |
8734 | .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), | ||
8735 | .adc_nids = alc883_adc_nids, | ||
8736 | .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes), | 8801 | .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes), |
8737 | .channel_mode = alc883_sixstack_modes, | 8802 | .channel_mode = alc883_sixstack_modes, |
8738 | .need_dac_fix = 1, | 8803 | .need_dac_fix = 1, |
@@ -8756,6 +8821,7 @@ static struct alc_config_preset alc883_presets[] = { | |||
8756 | }, | 8821 | }, |
8757 | [ALC888_ASUS_EEE1601] = { | 8822 | [ALC888_ASUS_EEE1601] = { |
8758 | .mixers = { alc883_asus_eee1601_mixer }, | 8823 | .mixers = { alc883_asus_eee1601_mixer }, |
8824 | .cap_mixer = alc883_asus_eee1601_cap_mixer, | ||
8759 | .init_verbs = { alc883_init_verbs, alc888_asus_eee1601_verbs }, | 8825 | .init_verbs = { alc883_init_verbs, alc888_asus_eee1601_verbs }, |
8760 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), | 8826 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), |
8761 | .dac_nids = alc883_dac_nids, | 8827 | .dac_nids = alc883_dac_nids, |
@@ -8768,6 +8834,17 @@ static struct alc_config_preset alc883_presets[] = { | |||
8768 | .unsol_event = alc883_eee1601_unsol_event, | 8834 | .unsol_event = alc883_eee1601_unsol_event, |
8769 | .init_hook = alc883_eee1601_inithook, | 8835 | .init_hook = alc883_eee1601_inithook, |
8770 | }, | 8836 | }, |
8837 | [ALC1200_ASUS_P5Q] = { | ||
8838 | .mixers = { alc883_base_mixer, alc883_chmode_mixer }, | ||
8839 | .init_verbs = { alc883_init_verbs }, | ||
8840 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), | ||
8841 | .dac_nids = alc883_dac_nids, | ||
8842 | .dig_out_nid = ALC1200_DIGOUT_NID, | ||
8843 | .dig_in_nid = ALC883_DIGIN_NID, | ||
8844 | .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes), | ||
8845 | .channel_mode = alc883_sixstack_modes, | ||
8846 | .input_mux = &alc883_capture_source, | ||
8847 | }, | ||
8771 | }; | 8848 | }; |
8772 | 8849 | ||
8773 | 8850 | ||
@@ -8862,8 +8939,6 @@ static int alc883_parse_auto_config(struct hda_codec *codec) | |||
8862 | 8939 | ||
8863 | /* hack - override the init verbs */ | 8940 | /* hack - override the init verbs */ |
8864 | spec->init_verbs[0] = alc883_auto_init_verbs; | 8941 | spec->init_verbs[0] = alc883_auto_init_verbs; |
8865 | spec->mixers[spec->num_mixers] = alc883_capture_mixer; | ||
8866 | spec->num_mixers++; | ||
8867 | 8942 | ||
8868 | return 1; /* config found */ | 8943 | return 1; /* config found */ |
8869 | } | 8944 | } |
@@ -8946,9 +9021,15 @@ static int patch_alc883(struct hda_codec *codec) | |||
8946 | spec->stream_digital_playback = &alc883_pcm_digital_playback; | 9021 | spec->stream_digital_playback = &alc883_pcm_digital_playback; |
8947 | spec->stream_digital_capture = &alc883_pcm_digital_capture; | 9022 | spec->stream_digital_capture = &alc883_pcm_digital_capture; |
8948 | 9023 | ||
8949 | spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids); | 9024 | if (!spec->num_adc_nids) { |
8950 | spec->adc_nids = alc883_adc_nids; | 9025 | spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids); |
8951 | spec->capsrc_nids = alc883_capsrc_nids; | 9026 | spec->adc_nids = alc883_adc_nids; |
9027 | } | ||
9028 | if (!spec->capsrc_nids) | ||
9029 | spec->capsrc_nids = alc883_capsrc_nids; | ||
9030 | spec->is_mix_capture = 1; /* matrix-style capture */ | ||
9031 | if (!spec->cap_mixer) | ||
9032 | set_capture_mixer(spec); | ||
8952 | 9033 | ||
8953 | spec->vmaster_nid = 0x0c; | 9034 | spec->vmaster_nid = 0x0c; |
8954 | 9035 | ||
@@ -9439,20 +9520,6 @@ static struct snd_kcontrol_new alc262_toshiba_s06_mixer[] = { | |||
9439 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), | 9520 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), |
9440 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 9521 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
9441 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 9522 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
9442 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), | ||
9443 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), | ||
9444 | { | ||
9445 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
9446 | /* The multiple "Capture Source" controls confuse alsamixer | ||
9447 | * So call somewhat different.. | ||
9448 | */ | ||
9449 | /* .name = "Capture Source", */ | ||
9450 | .name = "Input Source", | ||
9451 | .count = 1, | ||
9452 | .info = alc_mux_enum_info, | ||
9453 | .get = alc_mux_enum_get, | ||
9454 | .put = alc_mux_enum_put, | ||
9455 | }, | ||
9456 | { } /* end */ | 9523 | { } /* end */ |
9457 | }; | 9524 | }; |
9458 | 9525 | ||
@@ -9969,7 +10036,7 @@ static int alc262_ultra_mux_enum_put(struct snd_kcontrol *kcontrol, | |||
9969 | struct alc_spec *spec = codec->spec; | 10036 | struct alc_spec *spec = codec->spec; |
9970 | int ret; | 10037 | int ret; |
9971 | 10038 | ||
9972 | ret = alc882_mux_enum_put(kcontrol, ucontrol); | 10039 | ret = alc_mux_enum_put(kcontrol, ucontrol); |
9973 | if (!ret) | 10040 | if (!ret) |
9974 | return 0; | 10041 | return 0; |
9975 | /* reprogram the HP pin as mic or HP according to the input source */ | 10042 | /* reprogram the HP pin as mic or HP according to the input source */ |
@@ -9986,8 +10053,8 @@ static struct snd_kcontrol_new alc262_ultra_capture_mixer[] = { | |||
9986 | { | 10053 | { |
9987 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 10054 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
9988 | .name = "Capture Source", | 10055 | .name = "Capture Source", |
9989 | .info = alc882_mux_enum_info, | 10056 | .info = alc_mux_enum_info, |
9990 | .get = alc882_mux_enum_get, | 10057 | .get = alc_mux_enum_get, |
9991 | .put = alc262_ultra_mux_enum_put, | 10058 | .put = alc262_ultra_mux_enum_put, |
9992 | }, | 10059 | }, |
9993 | { } /* end */ | 10060 | { } /* end */ |
@@ -10380,10 +10447,10 @@ static int alc262_parse_auto_config(struct hda_codec *codec) | |||
10380 | if (spec->autocfg.dig_in_pin) | 10447 | if (spec->autocfg.dig_in_pin) |
10381 | spec->dig_in_nid = ALC262_DIGIN_NID; | 10448 | spec->dig_in_nid = ALC262_DIGIN_NID; |
10382 | 10449 | ||
10383 | if (spec->kctl_alloc) | 10450 | if (spec->kctls.list) |
10384 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 10451 | add_mixer(spec, spec->kctls.list); |
10385 | 10452 | ||
10386 | spec->init_verbs[spec->num_init_verbs++] = alc262_volume_init_verbs; | 10453 | add_verb(spec, alc262_volume_init_verbs); |
10387 | spec->num_mux_defs = 1; | 10454 | spec->num_mux_defs = 1; |
10388 | spec->input_mux = &spec->private_imux; | 10455 | spec->input_mux = &spec->private_imux; |
10389 | 10456 | ||
@@ -10624,7 +10691,8 @@ static struct alc_config_preset alc262_presets[] = { | |||
10624 | .init_hook = alc262_hippo_automute, | 10691 | .init_hook = alc262_hippo_automute, |
10625 | }, | 10692 | }, |
10626 | [ALC262_ULTRA] = { | 10693 | [ALC262_ULTRA] = { |
10627 | .mixers = { alc262_ultra_mixer, alc262_ultra_capture_mixer }, | 10694 | .mixers = { alc262_ultra_mixer }, |
10695 | .cap_mixer = alc262_ultra_capture_mixer, | ||
10628 | .init_verbs = { alc262_ultra_verbs }, | 10696 | .init_verbs = { alc262_ultra_verbs }, |
10629 | .num_dacs = ARRAY_SIZE(alc262_dac_nids), | 10697 | .num_dacs = ARRAY_SIZE(alc262_dac_nids), |
10630 | .dac_nids = alc262_dac_nids, | 10698 | .dac_nids = alc262_dac_nids, |
@@ -10750,6 +10818,7 @@ static int patch_alc262(struct hda_codec *codec) | |||
10750 | spec->stream_digital_playback = &alc262_pcm_digital_playback; | 10818 | spec->stream_digital_playback = &alc262_pcm_digital_playback; |
10751 | spec->stream_digital_capture = &alc262_pcm_digital_capture; | 10819 | spec->stream_digital_capture = &alc262_pcm_digital_capture; |
10752 | 10820 | ||
10821 | spec->is_mix_capture = 1; | ||
10753 | if (!spec->adc_nids && spec->input_mux) { | 10822 | if (!spec->adc_nids && spec->input_mux) { |
10754 | /* check whether NID 0x07 is valid */ | 10823 | /* check whether NID 0x07 is valid */ |
10755 | unsigned int wcap = get_wcaps(codec, 0x07); | 10824 | unsigned int wcap = get_wcaps(codec, 0x07); |
@@ -10760,17 +10829,14 @@ static int patch_alc262(struct hda_codec *codec) | |||
10760 | spec->adc_nids = alc262_adc_nids_alt; | 10829 | spec->adc_nids = alc262_adc_nids_alt; |
10761 | spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids_alt); | 10830 | spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids_alt); |
10762 | spec->capsrc_nids = alc262_capsrc_nids_alt; | 10831 | spec->capsrc_nids = alc262_capsrc_nids_alt; |
10763 | spec->mixers[spec->num_mixers] = | ||
10764 | alc262_capture_alt_mixer; | ||
10765 | spec->num_mixers++; | ||
10766 | } else { | 10832 | } else { |
10767 | spec->adc_nids = alc262_adc_nids; | 10833 | spec->adc_nids = alc262_adc_nids; |
10768 | spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids); | 10834 | spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids); |
10769 | spec->capsrc_nids = alc262_capsrc_nids; | 10835 | spec->capsrc_nids = alc262_capsrc_nids; |
10770 | spec->mixers[spec->num_mixers] = alc262_capture_mixer; | ||
10771 | spec->num_mixers++; | ||
10772 | } | 10836 | } |
10773 | } | 10837 | } |
10838 | if (!spec->cap_mixer) | ||
10839 | set_capture_mixer(spec); | ||
10774 | 10840 | ||
10775 | spec->vmaster_nid = 0x0c; | 10841 | spec->vmaster_nid = 0x0c; |
10776 | 10842 | ||
@@ -10942,6 +11008,22 @@ static struct snd_kcontrol_new alc268_acer_mixer[] = { | |||
10942 | { } | 11008 | { } |
10943 | }; | 11009 | }; |
10944 | 11010 | ||
11011 | static struct snd_kcontrol_new alc268_acer_dmic_mixer[] = { | ||
11012 | /* output mixer control */ | ||
11013 | HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol), | ||
11014 | { | ||
11015 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
11016 | .name = "Master Playback Switch", | ||
11017 | .info = snd_hda_mixer_amp_switch_info, | ||
11018 | .get = snd_hda_mixer_amp_switch_get, | ||
11019 | .put = alc268_acer_master_sw_put, | ||
11020 | .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT), | ||
11021 | }, | ||
11022 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | ||
11023 | HDA_CODEC_VOLUME("Line In Boost", 0x1a, 0, HDA_INPUT), | ||
11024 | { } | ||
11025 | }; | ||
11026 | |||
10945 | static struct hda_verb alc268_acer_aspire_one_verbs[] = { | 11027 | static struct hda_verb alc268_acer_aspire_one_verbs[] = { |
10946 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | 11028 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, |
10947 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | 11029 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, |
@@ -11218,10 +11300,6 @@ static struct hda_verb alc268_volume_init_verbs[] = { | |||
11218 | { } | 11300 | { } |
11219 | }; | 11301 | }; |
11220 | 11302 | ||
11221 | #define alc268_mux_enum_info alc_mux_enum_info | ||
11222 | #define alc268_mux_enum_get alc_mux_enum_get | ||
11223 | #define alc268_mux_enum_put alc_mux_enum_put | ||
11224 | |||
11225 | static struct snd_kcontrol_new alc268_capture_alt_mixer[] = { | 11303 | static struct snd_kcontrol_new alc268_capture_alt_mixer[] = { |
11226 | HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT), | 11304 | HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT), |
11227 | HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT), | 11305 | HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT), |
@@ -11233,9 +11311,9 @@ static struct snd_kcontrol_new alc268_capture_alt_mixer[] = { | |||
11233 | /* .name = "Capture Source", */ | 11311 | /* .name = "Capture Source", */ |
11234 | .name = "Input Source", | 11312 | .name = "Input Source", |
11235 | .count = 1, | 11313 | .count = 1, |
11236 | .info = alc268_mux_enum_info, | 11314 | .info = alc_mux_enum_info, |
11237 | .get = alc268_mux_enum_get, | 11315 | .get = alc_mux_enum_get, |
11238 | .put = alc268_mux_enum_put, | 11316 | .put = alc_mux_enum_put, |
11239 | }, | 11317 | }, |
11240 | { } /* end */ | 11318 | { } /* end */ |
11241 | }; | 11319 | }; |
@@ -11253,9 +11331,9 @@ static struct snd_kcontrol_new alc268_capture_mixer[] = { | |||
11253 | /* .name = "Capture Source", */ | 11331 | /* .name = "Capture Source", */ |
11254 | .name = "Input Source", | 11332 | .name = "Input Source", |
11255 | .count = 2, | 11333 | .count = 2, |
11256 | .info = alc268_mux_enum_info, | 11334 | .info = alc_mux_enum_info, |
11257 | .get = alc268_mux_enum_get, | 11335 | .get = alc_mux_enum_get, |
11258 | .put = alc268_mux_enum_put, | 11336 | .put = alc_mux_enum_put, |
11259 | }, | 11337 | }, |
11260 | { } /* end */ | 11338 | { } /* end */ |
11261 | }; | 11339 | }; |
@@ -11274,6 +11352,15 @@ static struct hda_input_mux alc268_acer_capture_source = { | |||
11274 | .num_items = 3, | 11352 | .num_items = 3, |
11275 | .items = { | 11353 | .items = { |
11276 | { "Mic", 0x0 }, | 11354 | { "Mic", 0x0 }, |
11355 | { "Internal Mic", 0x1 }, | ||
11356 | { "Line", 0x2 }, | ||
11357 | }, | ||
11358 | }; | ||
11359 | |||
11360 | static struct hda_input_mux alc268_acer_dmic_capture_source = { | ||
11361 | .num_items = 3, | ||
11362 | .items = { | ||
11363 | { "Mic", 0x0 }, | ||
11277 | { "Internal Mic", 0x6 }, | 11364 | { "Internal Mic", 0x6 }, |
11278 | { "Line", 0x2 }, | 11365 | { "Line", 0x2 }, |
11279 | }, | 11366 | }, |
@@ -11512,13 +11599,13 @@ static int alc268_parse_auto_config(struct hda_codec *codec) | |||
11512 | if (spec->autocfg.dig_out_pin) | 11599 | if (spec->autocfg.dig_out_pin) |
11513 | spec->multiout.dig_out_nid = ALC268_DIGOUT_NID; | 11600 | spec->multiout.dig_out_nid = ALC268_DIGOUT_NID; |
11514 | 11601 | ||
11515 | if (spec->kctl_alloc) | 11602 | if (spec->kctls.list) |
11516 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 11603 | add_mixer(spec, spec->kctls.list); |
11517 | 11604 | ||
11518 | if (spec->autocfg.speaker_pins[0] != 0x1d) | 11605 | if (spec->autocfg.speaker_pins[0] != 0x1d) |
11519 | spec->mixers[spec->num_mixers++] = alc268_beep_mixer; | 11606 | add_mixer(spec, alc268_beep_mixer); |
11520 | 11607 | ||
11521 | spec->init_verbs[spec->num_init_verbs++] = alc268_volume_init_verbs; | 11608 | add_verb(spec, alc268_volume_init_verbs); |
11522 | spec->num_mux_defs = 1; | 11609 | spec->num_mux_defs = 1; |
11523 | spec->input_mux = &spec->private_imux; | 11610 | spec->input_mux = &spec->private_imux; |
11524 | 11611 | ||
@@ -11554,6 +11641,7 @@ static const char *alc268_models[ALC268_MODEL_LAST] = { | |||
11554 | [ALC268_3ST] = "3stack", | 11641 | [ALC268_3ST] = "3stack", |
11555 | [ALC268_TOSHIBA] = "toshiba", | 11642 | [ALC268_TOSHIBA] = "toshiba", |
11556 | [ALC268_ACER] = "acer", | 11643 | [ALC268_ACER] = "acer", |
11644 | [ALC268_ACER_DMIC] = "acer-dmic", | ||
11557 | [ALC268_ACER_ASPIRE_ONE] = "acer-aspire", | 11645 | [ALC268_ACER_ASPIRE_ONE] = "acer-aspire", |
11558 | [ALC268_DELL] = "dell", | 11646 | [ALC268_DELL] = "dell", |
11559 | [ALC268_ZEPTO] = "zepto", | 11647 | [ALC268_ZEPTO] = "zepto", |
@@ -11649,6 +11737,23 @@ static struct alc_config_preset alc268_presets[] = { | |||
11649 | .unsol_event = alc268_acer_unsol_event, | 11737 | .unsol_event = alc268_acer_unsol_event, |
11650 | .init_hook = alc268_acer_init_hook, | 11738 | .init_hook = alc268_acer_init_hook, |
11651 | }, | 11739 | }, |
11740 | [ALC268_ACER_DMIC] = { | ||
11741 | .mixers = { alc268_acer_dmic_mixer, alc268_capture_alt_mixer, | ||
11742 | alc268_beep_mixer }, | ||
11743 | .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, | ||
11744 | alc268_acer_verbs }, | ||
11745 | .num_dacs = ARRAY_SIZE(alc268_dac_nids), | ||
11746 | .dac_nids = alc268_dac_nids, | ||
11747 | .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt), | ||
11748 | .adc_nids = alc268_adc_nids_alt, | ||
11749 | .capsrc_nids = alc268_capsrc_nids, | ||
11750 | .hp_nid = 0x02, | ||
11751 | .num_channel_mode = ARRAY_SIZE(alc268_modes), | ||
11752 | .channel_mode = alc268_modes, | ||
11753 | .input_mux = &alc268_acer_dmic_capture_source, | ||
11754 | .unsol_event = alc268_acer_unsol_event, | ||
11755 | .init_hook = alc268_acer_init_hook, | ||
11756 | }, | ||
11652 | [ALC268_ACER_ASPIRE_ONE] = { | 11757 | [ALC268_ACER_ASPIRE_ONE] = { |
11653 | .mixers = { alc268_acer_aspire_one_mixer, | 11758 | .mixers = { alc268_acer_aspire_one_mixer, |
11654 | alc268_capture_alt_mixer }, | 11759 | alc268_capture_alt_mixer }, |
@@ -11787,15 +11892,11 @@ static int patch_alc268(struct hda_codec *codec) | |||
11787 | if (wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) { | 11892 | if (wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) { |
11788 | spec->adc_nids = alc268_adc_nids_alt; | 11893 | spec->adc_nids = alc268_adc_nids_alt; |
11789 | spec->num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt); | 11894 | spec->num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt); |
11790 | spec->mixers[spec->num_mixers] = | 11895 | add_mixer(spec, alc268_capture_alt_mixer); |
11791 | alc268_capture_alt_mixer; | ||
11792 | spec->num_mixers++; | ||
11793 | } else { | 11896 | } else { |
11794 | spec->adc_nids = alc268_adc_nids; | 11897 | spec->adc_nids = alc268_adc_nids; |
11795 | spec->num_adc_nids = ARRAY_SIZE(alc268_adc_nids); | 11898 | spec->num_adc_nids = ARRAY_SIZE(alc268_adc_nids); |
11796 | spec->mixers[spec->num_mixers] = | 11899 | add_mixer(spec, alc268_capture_mixer); |
11797 | alc268_capture_mixer; | ||
11798 | spec->num_mixers++; | ||
11799 | } | 11900 | } |
11800 | spec->capsrc_nids = alc268_capsrc_nids; | 11901 | spec->capsrc_nids = alc268_capsrc_nids; |
11801 | /* set default input source */ | 11902 | /* set default input source */ |
@@ -11893,6 +11994,31 @@ static struct snd_kcontrol_new alc269_quanta_fl1_mixer[] = { | |||
11893 | { } | 11994 | { } |
11894 | }; | 11995 | }; |
11895 | 11996 | ||
11997 | static struct snd_kcontrol_new alc269_lifebook_mixer[] = { | ||
11998 | /* output mixer control */ | ||
11999 | HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol), | ||
12000 | { | ||
12001 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
12002 | .name = "Master Playback Switch", | ||
12003 | .info = snd_hda_mixer_amp_switch_info, | ||
12004 | .get = snd_hda_mixer_amp_switch_get, | ||
12005 | .put = alc268_acer_master_sw_put, | ||
12006 | .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT), | ||
12007 | }, | ||
12008 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
12009 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
12010 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | ||
12011 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), | ||
12012 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), | ||
12013 | HDA_CODEC_VOLUME("Internal Mic Boost", 0x19, 0, HDA_INPUT), | ||
12014 | HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x0b, 0x03, HDA_INPUT), | ||
12015 | HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x0b, 0x03, HDA_INPUT), | ||
12016 | HDA_CODEC_VOLUME("Dock Mic Boost", 0x1b, 0, HDA_INPUT), | ||
12017 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
12018 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
12019 | { } | ||
12020 | }; | ||
12021 | |||
11896 | /* bind volumes of both NID 0x0c and 0x0d */ | 12022 | /* bind volumes of both NID 0x0c and 0x0d */ |
11897 | static struct hda_bind_ctls alc269_epc_bind_vol = { | 12023 | static struct hda_bind_ctls alc269_epc_bind_vol = { |
11898 | .ops = &snd_hda_bind_vol, | 12024 | .ops = &snd_hda_bind_vol, |
@@ -11911,28 +12037,18 @@ static struct snd_kcontrol_new alc269_eeepc_mixer[] = { | |||
11911 | }; | 12037 | }; |
11912 | 12038 | ||
11913 | /* capture mixer elements */ | 12039 | /* capture mixer elements */ |
11914 | static struct snd_kcontrol_new alc269_capture_mixer[] = { | 12040 | static struct snd_kcontrol_new alc269_epc_capture_mixer[] = { |
11915 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | 12041 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), |
11916 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | 12042 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), |
11917 | { | 12043 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), |
11918 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
11919 | /* The multiple "Capture Source" controls confuse alsamixer | ||
11920 | * So call somewhat different.. | ||
11921 | */ | ||
11922 | /* .name = "Capture Source", */ | ||
11923 | .name = "Input Source", | ||
11924 | .count = 1, | ||
11925 | .info = alc_mux_enum_info, | ||
11926 | .get = alc_mux_enum_get, | ||
11927 | .put = alc_mux_enum_put, | ||
11928 | }, | ||
11929 | { } /* end */ | 12044 | { } /* end */ |
11930 | }; | 12045 | }; |
11931 | 12046 | ||
11932 | /* capture mixer elements */ | 12047 | /* FSC amilo */ |
11933 | static struct snd_kcontrol_new alc269_epc_capture_mixer[] = { | 12048 | static struct snd_kcontrol_new alc269_fujitsu_mixer[] = { |
11934 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | 12049 | HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT), |
11935 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | 12050 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), |
12051 | HDA_BIND_VOL("PCM Playback Volume", &alc269_epc_bind_vol), | ||
11936 | { } /* end */ | 12052 | { } /* end */ |
11937 | }; | 12053 | }; |
11938 | 12054 | ||
@@ -11953,6 +12069,20 @@ static struct hda_verb alc269_quanta_fl1_verbs[] = { | |||
11953 | { } | 12069 | { } |
11954 | }; | 12070 | }; |
11955 | 12071 | ||
12072 | static struct hda_verb alc269_lifebook_verbs[] = { | ||
12073 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
12074 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
12075 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
12076 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
12077 | {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, | ||
12078 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
12079 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
12080 | {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, | ||
12081 | {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT}, | ||
12082 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
12083 | { } | ||
12084 | }; | ||
12085 | |||
11956 | /* toggle speaker-output according to the hp-jack state */ | 12086 | /* toggle speaker-output according to the hp-jack state */ |
11957 | static void alc269_quanta_fl1_speaker_automute(struct hda_codec *codec) | 12087 | static void alc269_quanta_fl1_speaker_automute(struct hda_codec *codec) |
11958 | { | 12088 | { |
@@ -11978,6 +12108,37 @@ static void alc269_quanta_fl1_speaker_automute(struct hda_codec *codec) | |||
11978 | AC_VERB_SET_PROC_COEF, 0x480); | 12108 | AC_VERB_SET_PROC_COEF, 0x480); |
11979 | } | 12109 | } |
11980 | 12110 | ||
12111 | /* toggle speaker-output according to the hp-jacks state */ | ||
12112 | static void alc269_lifebook_speaker_automute(struct hda_codec *codec) | ||
12113 | { | ||
12114 | unsigned int present; | ||
12115 | unsigned char bits; | ||
12116 | |||
12117 | /* Check laptop headphone socket */ | ||
12118 | present = snd_hda_codec_read(codec, 0x15, 0, | ||
12119 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
12120 | |||
12121 | /* Check port replicator headphone socket */ | ||
12122 | present |= snd_hda_codec_read(codec, 0x1a, 0, | ||
12123 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
12124 | |||
12125 | bits = present ? AMP_IN_MUTE(0) : 0; | ||
12126 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0, | ||
12127 | AMP_IN_MUTE(0), bits); | ||
12128 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1, | ||
12129 | AMP_IN_MUTE(0), bits); | ||
12130 | |||
12131 | snd_hda_codec_write(codec, 0x20, 0, | ||
12132 | AC_VERB_SET_COEF_INDEX, 0x0c); | ||
12133 | snd_hda_codec_write(codec, 0x20, 0, | ||
12134 | AC_VERB_SET_PROC_COEF, 0x680); | ||
12135 | |||
12136 | snd_hda_codec_write(codec, 0x20, 0, | ||
12137 | AC_VERB_SET_COEF_INDEX, 0x0c); | ||
12138 | snd_hda_codec_write(codec, 0x20, 0, | ||
12139 | AC_VERB_SET_PROC_COEF, 0x480); | ||
12140 | } | ||
12141 | |||
11981 | static void alc269_quanta_fl1_mic_automute(struct hda_codec *codec) | 12142 | static void alc269_quanta_fl1_mic_automute(struct hda_codec *codec) |
11982 | { | 12143 | { |
11983 | unsigned int present; | 12144 | unsigned int present; |
@@ -11988,6 +12149,29 @@ static void alc269_quanta_fl1_mic_automute(struct hda_codec *codec) | |||
11988 | AC_VERB_SET_CONNECT_SEL, present ? 0x0 : 0x1); | 12149 | AC_VERB_SET_CONNECT_SEL, present ? 0x0 : 0x1); |
11989 | } | 12150 | } |
11990 | 12151 | ||
12152 | static void alc269_lifebook_mic_autoswitch(struct hda_codec *codec) | ||
12153 | { | ||
12154 | unsigned int present_laptop; | ||
12155 | unsigned int present_dock; | ||
12156 | |||
12157 | present_laptop = snd_hda_codec_read(codec, 0x18, 0, | ||
12158 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
12159 | |||
12160 | present_dock = snd_hda_codec_read(codec, 0x1b, 0, | ||
12161 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
12162 | |||
12163 | /* Laptop mic port overrides dock mic port, design decision */ | ||
12164 | if (present_dock) | ||
12165 | snd_hda_codec_write(codec, 0x23, 0, | ||
12166 | AC_VERB_SET_CONNECT_SEL, 0x3); | ||
12167 | if (present_laptop) | ||
12168 | snd_hda_codec_write(codec, 0x23, 0, | ||
12169 | AC_VERB_SET_CONNECT_SEL, 0x0); | ||
12170 | if (!present_dock && !present_laptop) | ||
12171 | snd_hda_codec_write(codec, 0x23, 0, | ||
12172 | AC_VERB_SET_CONNECT_SEL, 0x1); | ||
12173 | } | ||
12174 | |||
11991 | static void alc269_quanta_fl1_unsol_event(struct hda_codec *codec, | 12175 | static void alc269_quanta_fl1_unsol_event(struct hda_codec *codec, |
11992 | unsigned int res) | 12176 | unsigned int res) |
11993 | { | 12177 | { |
@@ -11997,12 +12181,27 @@ static void alc269_quanta_fl1_unsol_event(struct hda_codec *codec, | |||
11997 | alc269_quanta_fl1_mic_automute(codec); | 12181 | alc269_quanta_fl1_mic_automute(codec); |
11998 | } | 12182 | } |
11999 | 12183 | ||
12184 | static void alc269_lifebook_unsol_event(struct hda_codec *codec, | ||
12185 | unsigned int res) | ||
12186 | { | ||
12187 | if ((res >> 26) == ALC880_HP_EVENT) | ||
12188 | alc269_lifebook_speaker_automute(codec); | ||
12189 | if ((res >> 26) == ALC880_MIC_EVENT) | ||
12190 | alc269_lifebook_mic_autoswitch(codec); | ||
12191 | } | ||
12192 | |||
12000 | static void alc269_quanta_fl1_init_hook(struct hda_codec *codec) | 12193 | static void alc269_quanta_fl1_init_hook(struct hda_codec *codec) |
12001 | { | 12194 | { |
12002 | alc269_quanta_fl1_speaker_automute(codec); | 12195 | alc269_quanta_fl1_speaker_automute(codec); |
12003 | alc269_quanta_fl1_mic_automute(codec); | 12196 | alc269_quanta_fl1_mic_automute(codec); |
12004 | } | 12197 | } |
12005 | 12198 | ||
12199 | static void alc269_lifebook_init_hook(struct hda_codec *codec) | ||
12200 | { | ||
12201 | alc269_lifebook_speaker_automute(codec); | ||
12202 | alc269_lifebook_mic_autoswitch(codec); | ||
12203 | } | ||
12204 | |||
12006 | static struct hda_verb alc269_eeepc_dmic_init_verbs[] = { | 12205 | static struct hda_verb alc269_eeepc_dmic_init_verbs[] = { |
12007 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, | 12206 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, |
12008 | {0x23, AC_VERB_SET_CONNECT_SEL, 0x05}, | 12207 | {0x23, AC_VERB_SET_CONNECT_SEL, 0x05}, |
@@ -12303,17 +12502,17 @@ static int alc269_parse_auto_config(struct hda_codec *codec) | |||
12303 | if (spec->autocfg.dig_out_pin) | 12502 | if (spec->autocfg.dig_out_pin) |
12304 | spec->multiout.dig_out_nid = ALC269_DIGOUT_NID; | 12503 | spec->multiout.dig_out_nid = ALC269_DIGOUT_NID; |
12305 | 12504 | ||
12306 | if (spec->kctl_alloc) | 12505 | if (spec->kctls.list) |
12307 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 12506 | add_mixer(spec, spec->kctls.list); |
12308 | 12507 | ||
12309 | /* create a beep mixer control if the pin 0x1d isn't assigned */ | 12508 | /* create a beep mixer control if the pin 0x1d isn't assigned */ |
12310 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.input_pins); i++) | 12509 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.input_pins); i++) |
12311 | if (spec->autocfg.input_pins[i] == 0x1d) | 12510 | if (spec->autocfg.input_pins[i] == 0x1d) |
12312 | break; | 12511 | break; |
12313 | if (i >= ARRAY_SIZE(spec->autocfg.input_pins)) | 12512 | if (i >= ARRAY_SIZE(spec->autocfg.input_pins)) |
12314 | spec->mixers[spec->num_mixers++] = alc269_beep_mixer; | 12513 | add_mixer(spec, alc269_beep_mixer); |
12315 | 12514 | ||
12316 | spec->init_verbs[spec->num_init_verbs++] = alc269_init_verbs; | 12515 | add_verb(spec, alc269_init_verbs); |
12317 | spec->num_mux_defs = 1; | 12516 | spec->num_mux_defs = 1; |
12318 | spec->input_mux = &spec->private_imux; | 12517 | spec->input_mux = &spec->private_imux; |
12319 | /* set default input source */ | 12518 | /* set default input source */ |
@@ -12325,8 +12524,8 @@ static int alc269_parse_auto_config(struct hda_codec *codec) | |||
12325 | if (err < 0) | 12524 | if (err < 0) |
12326 | return err; | 12525 | return err; |
12327 | 12526 | ||
12328 | spec->mixers[spec->num_mixers] = alc269_capture_mixer; | 12527 | if (!spec->cap_mixer) |
12329 | spec->num_mixers++; | 12528 | set_capture_mixer(spec); |
12330 | 12529 | ||
12331 | store_pin_configs(codec); | 12530 | store_pin_configs(codec); |
12332 | return 1; | 12531 | return 1; |
@@ -12355,7 +12554,9 @@ static const char *alc269_models[ALC269_MODEL_LAST] = { | |||
12355 | [ALC269_BASIC] = "basic", | 12554 | [ALC269_BASIC] = "basic", |
12356 | [ALC269_QUANTA_FL1] = "quanta", | 12555 | [ALC269_QUANTA_FL1] = "quanta", |
12357 | [ALC269_ASUS_EEEPC_P703] = "eeepc-p703", | 12556 | [ALC269_ASUS_EEEPC_P703] = "eeepc-p703", |
12358 | [ALC269_ASUS_EEEPC_P901] = "eeepc-p901" | 12557 | [ALC269_ASUS_EEEPC_P901] = "eeepc-p901", |
12558 | [ALC269_FUJITSU] = "fujitsu", | ||
12559 | [ALC269_LIFEBOOK] = "lifebook" | ||
12359 | }; | 12560 | }; |
12360 | 12561 | ||
12361 | static struct snd_pci_quirk alc269_cfg_tbl[] = { | 12562 | static struct snd_pci_quirk alc269_cfg_tbl[] = { |
@@ -12366,12 +12567,14 @@ static struct snd_pci_quirk alc269_cfg_tbl[] = { | |||
12366 | ALC269_ASUS_EEEPC_P901), | 12567 | ALC269_ASUS_EEEPC_P901), |
12367 | SND_PCI_QUIRK(0x1043, 0x834a, "ASUS Eeepc S101", | 12568 | SND_PCI_QUIRK(0x1043, 0x834a, "ASUS Eeepc S101", |
12368 | ALC269_ASUS_EEEPC_P901), | 12569 | ALC269_ASUS_EEEPC_P901), |
12570 | SND_PCI_QUIRK(0x1734, 0x115d, "FSC Amilo", ALC269_FUJITSU), | ||
12571 | SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook ICH9M-based", ALC269_LIFEBOOK), | ||
12369 | {} | 12572 | {} |
12370 | }; | 12573 | }; |
12371 | 12574 | ||
12372 | static struct alc_config_preset alc269_presets[] = { | 12575 | static struct alc_config_preset alc269_presets[] = { |
12373 | [ALC269_BASIC] = { | 12576 | [ALC269_BASIC] = { |
12374 | .mixers = { alc269_base_mixer, alc269_capture_mixer }, | 12577 | .mixers = { alc269_base_mixer }, |
12375 | .init_verbs = { alc269_init_verbs }, | 12578 | .init_verbs = { alc269_init_verbs }, |
12376 | .num_dacs = ARRAY_SIZE(alc269_dac_nids), | 12579 | .num_dacs = ARRAY_SIZE(alc269_dac_nids), |
12377 | .dac_nids = alc269_dac_nids, | 12580 | .dac_nids = alc269_dac_nids, |
@@ -12393,7 +12596,8 @@ static struct alc_config_preset alc269_presets[] = { | |||
12393 | .init_hook = alc269_quanta_fl1_init_hook, | 12596 | .init_hook = alc269_quanta_fl1_init_hook, |
12394 | }, | 12597 | }, |
12395 | [ALC269_ASUS_EEEPC_P703] = { | 12598 | [ALC269_ASUS_EEEPC_P703] = { |
12396 | .mixers = { alc269_eeepc_mixer, alc269_epc_capture_mixer }, | 12599 | .mixers = { alc269_eeepc_mixer }, |
12600 | .cap_mixer = alc269_epc_capture_mixer, | ||
12397 | .init_verbs = { alc269_init_verbs, | 12601 | .init_verbs = { alc269_init_verbs, |
12398 | alc269_eeepc_amic_init_verbs }, | 12602 | alc269_eeepc_amic_init_verbs }, |
12399 | .num_dacs = ARRAY_SIZE(alc269_dac_nids), | 12603 | .num_dacs = ARRAY_SIZE(alc269_dac_nids), |
@@ -12406,7 +12610,8 @@ static struct alc_config_preset alc269_presets[] = { | |||
12406 | .init_hook = alc269_eeepc_amic_inithook, | 12610 | .init_hook = alc269_eeepc_amic_inithook, |
12407 | }, | 12611 | }, |
12408 | [ALC269_ASUS_EEEPC_P901] = { | 12612 | [ALC269_ASUS_EEEPC_P901] = { |
12409 | .mixers = { alc269_eeepc_mixer, alc269_epc_capture_mixer}, | 12613 | .mixers = { alc269_eeepc_mixer }, |
12614 | .cap_mixer = alc269_epc_capture_mixer, | ||
12410 | .init_verbs = { alc269_init_verbs, | 12615 | .init_verbs = { alc269_init_verbs, |
12411 | alc269_eeepc_dmic_init_verbs }, | 12616 | alc269_eeepc_dmic_init_verbs }, |
12412 | .num_dacs = ARRAY_SIZE(alc269_dac_nids), | 12617 | .num_dacs = ARRAY_SIZE(alc269_dac_nids), |
@@ -12418,6 +12623,32 @@ static struct alc_config_preset alc269_presets[] = { | |||
12418 | .unsol_event = alc269_eeepc_dmic_unsol_event, | 12623 | .unsol_event = alc269_eeepc_dmic_unsol_event, |
12419 | .init_hook = alc269_eeepc_dmic_inithook, | 12624 | .init_hook = alc269_eeepc_dmic_inithook, |
12420 | }, | 12625 | }, |
12626 | [ALC269_FUJITSU] = { | ||
12627 | .mixers = { alc269_fujitsu_mixer, alc269_beep_mixer }, | ||
12628 | .cap_mixer = alc269_epc_capture_mixer, | ||
12629 | .init_verbs = { alc269_init_verbs, | ||
12630 | alc269_eeepc_dmic_init_verbs }, | ||
12631 | .num_dacs = ARRAY_SIZE(alc269_dac_nids), | ||
12632 | .dac_nids = alc269_dac_nids, | ||
12633 | .hp_nid = 0x03, | ||
12634 | .num_channel_mode = ARRAY_SIZE(alc269_modes), | ||
12635 | .channel_mode = alc269_modes, | ||
12636 | .input_mux = &alc269_eeepc_dmic_capture_source, | ||
12637 | .unsol_event = alc269_eeepc_dmic_unsol_event, | ||
12638 | .init_hook = alc269_eeepc_dmic_inithook, | ||
12639 | }, | ||
12640 | [ALC269_LIFEBOOK] = { | ||
12641 | .mixers = { alc269_lifebook_mixer }, | ||
12642 | .init_verbs = { alc269_init_verbs, alc269_lifebook_verbs }, | ||
12643 | .num_dacs = ARRAY_SIZE(alc269_dac_nids), | ||
12644 | .dac_nids = alc269_dac_nids, | ||
12645 | .hp_nid = 0x03, | ||
12646 | .num_channel_mode = ARRAY_SIZE(alc269_modes), | ||
12647 | .channel_mode = alc269_modes, | ||
12648 | .input_mux = &alc269_capture_source, | ||
12649 | .unsol_event = alc269_lifebook_unsol_event, | ||
12650 | .init_hook = alc269_lifebook_init_hook, | ||
12651 | }, | ||
12421 | }; | 12652 | }; |
12422 | 12653 | ||
12423 | static int patch_alc269(struct hda_codec *codec) | 12654 | static int patch_alc269(struct hda_codec *codec) |
@@ -12472,6 +12703,8 @@ static int patch_alc269(struct hda_codec *codec) | |||
12472 | spec->adc_nids = alc269_adc_nids; | 12703 | spec->adc_nids = alc269_adc_nids; |
12473 | spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids); | 12704 | spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids); |
12474 | spec->capsrc_nids = alc269_capsrc_nids; | 12705 | spec->capsrc_nids = alc269_capsrc_nids; |
12706 | if (!spec->cap_mixer) | ||
12707 | set_capture_mixer(spec); | ||
12475 | 12708 | ||
12476 | codec->patch_ops = alc_patch_ops; | 12709 | codec->patch_ops = alc_patch_ops; |
12477 | if (board_config == ALC269_AUTO) | 12710 | if (board_config == ALC269_AUTO) |
@@ -12612,17 +12845,6 @@ static struct snd_kcontrol_new alc861_base_mixer[] = { | |||
12612 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), | 12845 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), |
12613 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT), | 12846 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT), |
12614 | 12847 | ||
12615 | /* Capture mixer control */ | ||
12616 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
12617 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
12618 | { | ||
12619 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
12620 | .name = "Capture Source", | ||
12621 | .count = 1, | ||
12622 | .info = alc_mux_enum_info, | ||
12623 | .get = alc_mux_enum_get, | ||
12624 | .put = alc_mux_enum_put, | ||
12625 | }, | ||
12626 | { } /* end */ | 12848 | { } /* end */ |
12627 | }; | 12849 | }; |
12628 | 12850 | ||
@@ -12646,17 +12868,6 @@ static struct snd_kcontrol_new alc861_3ST_mixer[] = { | |||
12646 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), | 12868 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), |
12647 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT), | 12869 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT), |
12648 | 12870 | ||
12649 | /* Capture mixer control */ | ||
12650 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
12651 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
12652 | { | ||
12653 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
12654 | .name = "Capture Source", | ||
12655 | .count = 1, | ||
12656 | .info = alc_mux_enum_info, | ||
12657 | .get = alc_mux_enum_get, | ||
12658 | .put = alc_mux_enum_put, | ||
12659 | }, | ||
12660 | { | 12871 | { |
12661 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 12872 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
12662 | .name = "Channel Mode", | 12873 | .name = "Channel Mode", |
@@ -12674,18 +12885,6 @@ static struct snd_kcontrol_new alc861_toshiba_mixer[] = { | |||
12674 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT), | 12885 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT), |
12675 | HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT), | 12886 | HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT), |
12676 | 12887 | ||
12677 | /*Capture mixer control */ | ||
12678 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
12679 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
12680 | { | ||
12681 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
12682 | .name = "Capture Source", | ||
12683 | .count = 1, | ||
12684 | .info = alc_mux_enum_info, | ||
12685 | .get = alc_mux_enum_get, | ||
12686 | .put = alc_mux_enum_put, | ||
12687 | }, | ||
12688 | |||
12689 | { } /* end */ | 12888 | { } /* end */ |
12690 | }; | 12889 | }; |
12691 | 12890 | ||
@@ -12709,17 +12908,6 @@ static struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = { | |||
12709 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), | 12908 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), |
12710 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT), | 12909 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT), |
12711 | 12910 | ||
12712 | /* Capture mixer control */ | ||
12713 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
12714 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
12715 | { | ||
12716 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
12717 | .name = "Capture Source", | ||
12718 | .count = 1, | ||
12719 | .info = alc_mux_enum_info, | ||
12720 | .get = alc_mux_enum_get, | ||
12721 | .put = alc_mux_enum_put, | ||
12722 | }, | ||
12723 | { | 12911 | { |
12724 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 12912 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
12725 | .name = "Channel Mode", | 12913 | .name = "Channel Mode", |
@@ -12751,17 +12939,6 @@ static struct snd_kcontrol_new alc861_asus_mixer[] = { | |||
12751 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), | 12939 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), |
12752 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_OUTPUT), | 12940 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_OUTPUT), |
12753 | 12941 | ||
12754 | /* Capture mixer control */ | ||
12755 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
12756 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
12757 | { | ||
12758 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
12759 | .name = "Capture Source", | ||
12760 | .count = 1, | ||
12761 | .info = alc_mux_enum_info, | ||
12762 | .get = alc_mux_enum_get, | ||
12763 | .put = alc_mux_enum_put, | ||
12764 | }, | ||
12765 | { | 12942 | { |
12766 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 12943 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
12767 | .name = "Channel Mode", | 12944 | .name = "Channel Mode", |
@@ -13293,25 +13470,6 @@ static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec, | |||
13293 | return 0; | 13470 | return 0; |
13294 | } | 13471 | } |
13295 | 13472 | ||
13296 | static struct snd_kcontrol_new alc861_capture_mixer[] = { | ||
13297 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
13298 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
13299 | |||
13300 | { | ||
13301 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
13302 | /* The multiple "Capture Source" controls confuse alsamixer | ||
13303 | * So call somewhat different.. | ||
13304 | */ | ||
13305 | /* .name = "Capture Source", */ | ||
13306 | .name = "Input Source", | ||
13307 | .count = 1, | ||
13308 | .info = alc_mux_enum_info, | ||
13309 | .get = alc_mux_enum_get, | ||
13310 | .put = alc_mux_enum_put, | ||
13311 | }, | ||
13312 | { } /* end */ | ||
13313 | }; | ||
13314 | |||
13315 | static void alc861_auto_set_output_and_unmute(struct hda_codec *codec, | 13473 | static void alc861_auto_set_output_and_unmute(struct hda_codec *codec, |
13316 | hda_nid_t nid, | 13474 | hda_nid_t nid, |
13317 | int pin_type, int dac_idx) | 13475 | int pin_type, int dac_idx) |
@@ -13402,18 +13560,17 @@ static int alc861_parse_auto_config(struct hda_codec *codec) | |||
13402 | if (spec->autocfg.dig_out_pin) | 13560 | if (spec->autocfg.dig_out_pin) |
13403 | spec->multiout.dig_out_nid = ALC861_DIGOUT_NID; | 13561 | spec->multiout.dig_out_nid = ALC861_DIGOUT_NID; |
13404 | 13562 | ||
13405 | if (spec->kctl_alloc) | 13563 | if (spec->kctls.list) |
13406 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 13564 | add_mixer(spec, spec->kctls.list); |
13407 | 13565 | ||
13408 | spec->init_verbs[spec->num_init_verbs++] = alc861_auto_init_verbs; | 13566 | add_verb(spec, alc861_auto_init_verbs); |
13409 | 13567 | ||
13410 | spec->num_mux_defs = 1; | 13568 | spec->num_mux_defs = 1; |
13411 | spec->input_mux = &spec->private_imux; | 13569 | spec->input_mux = &spec->private_imux; |
13412 | 13570 | ||
13413 | spec->adc_nids = alc861_adc_nids; | 13571 | spec->adc_nids = alc861_adc_nids; |
13414 | spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids); | 13572 | spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids); |
13415 | spec->mixers[spec->num_mixers] = alc861_capture_mixer; | 13573 | set_capture_mixer(spec); |
13416 | spec->num_mixers++; | ||
13417 | 13574 | ||
13418 | store_pin_configs(codec); | 13575 | store_pin_configs(codec); |
13419 | return 1; | 13576 | return 1; |
@@ -13709,11 +13866,6 @@ static struct hda_input_mux alc861vd_hp_capture_source = { | |||
13709 | }, | 13866 | }, |
13710 | }; | 13867 | }; |
13711 | 13868 | ||
13712 | #define alc861vd_mux_enum_info alc_mux_enum_info | ||
13713 | #define alc861vd_mux_enum_get alc_mux_enum_get | ||
13714 | /* ALC861VD has the ALC882-type input selection (but has only one ADC) */ | ||
13715 | #define alc861vd_mux_enum_put alc882_mux_enum_put | ||
13716 | |||
13717 | /* | 13869 | /* |
13718 | * 2ch mode | 13870 | * 2ch mode |
13719 | */ | 13871 | */ |
@@ -13759,25 +13911,6 @@ static struct snd_kcontrol_new alc861vd_chmode_mixer[] = { | |||
13759 | { } /* end */ | 13911 | { } /* end */ |
13760 | }; | 13912 | }; |
13761 | 13913 | ||
13762 | static struct snd_kcontrol_new alc861vd_capture_mixer[] = { | ||
13763 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), | ||
13764 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), | ||
13765 | |||
13766 | { | ||
13767 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
13768 | /* The multiple "Capture Source" controls confuse alsamixer | ||
13769 | * So call somewhat different.. | ||
13770 | */ | ||
13771 | /* .name = "Capture Source", */ | ||
13772 | .name = "Input Source", | ||
13773 | .count = 1, | ||
13774 | .info = alc861vd_mux_enum_info, | ||
13775 | .get = alc861vd_mux_enum_get, | ||
13776 | .put = alc861vd_mux_enum_put, | ||
13777 | }, | ||
13778 | { } /* end */ | ||
13779 | }; | ||
13780 | |||
13781 | /* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17 | 13914 | /* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17 |
13782 | * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b | 13915 | * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b |
13783 | */ | 13916 | */ |
@@ -14169,6 +14302,7 @@ static void alc861vd_dallas_unsol_event(struct hda_codec *codec, unsigned int re | |||
14169 | static const char *alc861vd_models[ALC861VD_MODEL_LAST] = { | 14302 | static const char *alc861vd_models[ALC861VD_MODEL_LAST] = { |
14170 | [ALC660VD_3ST] = "3stack-660", | 14303 | [ALC660VD_3ST] = "3stack-660", |
14171 | [ALC660VD_3ST_DIG] = "3stack-660-digout", | 14304 | [ALC660VD_3ST_DIG] = "3stack-660-digout", |
14305 | [ALC660VD_ASUS_V1S] = "asus-v1s", | ||
14172 | [ALC861VD_3ST] = "3stack", | 14306 | [ALC861VD_3ST] = "3stack", |
14173 | [ALC861VD_3ST_DIG] = "3stack-digout", | 14307 | [ALC861VD_3ST_DIG] = "3stack-digout", |
14174 | [ALC861VD_6ST_DIG] = "6stack-digout", | 14308 | [ALC861VD_6ST_DIG] = "6stack-digout", |
@@ -14183,7 +14317,7 @@ static struct snd_pci_quirk alc861vd_cfg_tbl[] = { | |||
14183 | SND_PCI_QUIRK(0x103c, 0x30bf, "HP TX1000", ALC861VD_HP), | 14317 | SND_PCI_QUIRK(0x103c, 0x30bf, "HP TX1000", ALC861VD_HP), |
14184 | SND_PCI_QUIRK(0x1043, 0x12e2, "Asus z35m", ALC660VD_3ST), | 14318 | SND_PCI_QUIRK(0x1043, 0x12e2, "Asus z35m", ALC660VD_3ST), |
14185 | SND_PCI_QUIRK(0x1043, 0x1339, "Asus G1", ALC660VD_3ST), | 14319 | SND_PCI_QUIRK(0x1043, 0x1339, "Asus G1", ALC660VD_3ST), |
14186 | SND_PCI_QUIRK(0x1043, 0x1633, "Asus V1Sn", ALC861VD_LENOVO), | 14320 | SND_PCI_QUIRK(0x1043, 0x1633, "Asus V1Sn", ALC660VD_ASUS_V1S), |
14187 | SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS", ALC660VD_3ST_DIG), | 14321 | SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS", ALC660VD_3ST_DIG), |
14188 | SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST), | 14322 | SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST), |
14189 | SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba A135", ALC861VD_LENOVO), | 14323 | SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba A135", ALC861VD_LENOVO), |
@@ -14290,6 +14424,21 @@ static struct alc_config_preset alc861vd_presets[] = { | |||
14290 | .unsol_event = alc861vd_dallas_unsol_event, | 14424 | .unsol_event = alc861vd_dallas_unsol_event, |
14291 | .init_hook = alc861vd_dallas_automute, | 14425 | .init_hook = alc861vd_dallas_automute, |
14292 | }, | 14426 | }, |
14427 | [ALC660VD_ASUS_V1S] = { | ||
14428 | .mixers = { alc861vd_lenovo_mixer }, | ||
14429 | .init_verbs = { alc861vd_volume_init_verbs, | ||
14430 | alc861vd_3stack_init_verbs, | ||
14431 | alc861vd_eapd_verbs, | ||
14432 | alc861vd_lenovo_unsol_verbs }, | ||
14433 | .num_dacs = ARRAY_SIZE(alc660vd_dac_nids), | ||
14434 | .dac_nids = alc660vd_dac_nids, | ||
14435 | .dig_out_nid = ALC861VD_DIGOUT_NID, | ||
14436 | .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes), | ||
14437 | .channel_mode = alc861vd_3stack_2ch_modes, | ||
14438 | .input_mux = &alc861vd_capture_source, | ||
14439 | .unsol_event = alc861vd_lenovo_unsol_event, | ||
14440 | .init_hook = alc861vd_lenovo_automute, | ||
14441 | }, | ||
14293 | }; | 14442 | }; |
14294 | 14443 | ||
14295 | /* | 14444 | /* |
@@ -14514,11 +14663,10 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec) | |||
14514 | if (spec->autocfg.dig_out_pin) | 14663 | if (spec->autocfg.dig_out_pin) |
14515 | spec->multiout.dig_out_nid = ALC861VD_DIGOUT_NID; | 14664 | spec->multiout.dig_out_nid = ALC861VD_DIGOUT_NID; |
14516 | 14665 | ||
14517 | if (spec->kctl_alloc) | 14666 | if (spec->kctls.list) |
14518 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 14667 | add_mixer(spec, spec->kctls.list); |
14519 | 14668 | ||
14520 | spec->init_verbs[spec->num_init_verbs++] | 14669 | add_verb(spec, alc861vd_volume_init_verbs); |
14521 | = alc861vd_volume_init_verbs; | ||
14522 | 14670 | ||
14523 | spec->num_mux_defs = 1; | 14671 | spec->num_mux_defs = 1; |
14524 | spec->input_mux = &spec->private_imux; | 14672 | spec->input_mux = &spec->private_imux; |
@@ -14585,7 +14733,7 @@ static int patch_alc861vd(struct hda_codec *codec) | |||
14585 | spec->stream_name_analog = "ALC660-VD Analog"; | 14733 | spec->stream_name_analog = "ALC660-VD Analog"; |
14586 | spec->stream_name_digital = "ALC660-VD Digital"; | 14734 | spec->stream_name_digital = "ALC660-VD Digital"; |
14587 | /* always turn on EAPD */ | 14735 | /* always turn on EAPD */ |
14588 | spec->init_verbs[spec->num_init_verbs++] = alc660vd_eapd_verbs; | 14736 | add_verb(spec, alc660vd_eapd_verbs); |
14589 | } else { | 14737 | } else { |
14590 | spec->stream_name_analog = "ALC861VD Analog"; | 14738 | spec->stream_name_analog = "ALC861VD Analog"; |
14591 | spec->stream_name_digital = "ALC861VD Digital"; | 14739 | spec->stream_name_digital = "ALC861VD Digital"; |
@@ -14600,9 +14748,9 @@ static int patch_alc861vd(struct hda_codec *codec) | |||
14600 | spec->adc_nids = alc861vd_adc_nids; | 14748 | spec->adc_nids = alc861vd_adc_nids; |
14601 | spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids); | 14749 | spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids); |
14602 | spec->capsrc_nids = alc861vd_capsrc_nids; | 14750 | spec->capsrc_nids = alc861vd_capsrc_nids; |
14751 | spec->is_mix_capture = 1; | ||
14603 | 14752 | ||
14604 | spec->mixers[spec->num_mixers] = alc861vd_capture_mixer; | 14753 | set_capture_mixer(spec); |
14605 | spec->num_mixers++; | ||
14606 | 14754 | ||
14607 | spec->vmaster_nid = 0x02; | 14755 | spec->vmaster_nid = 0x02; |
14608 | 14756 | ||
@@ -14689,10 +14837,6 @@ static struct hda_input_mux alc663_m51va_capture_source = { | |||
14689 | }, | 14837 | }, |
14690 | }; | 14838 | }; |
14691 | 14839 | ||
14692 | #define alc662_mux_enum_info alc_mux_enum_info | ||
14693 | #define alc662_mux_enum_get alc_mux_enum_get | ||
14694 | #define alc662_mux_enum_put alc882_mux_enum_put | ||
14695 | |||
14696 | /* | 14840 | /* |
14697 | * 2ch mode | 14841 | * 2ch mode |
14698 | */ | 14842 | */ |
@@ -15278,25 +15422,6 @@ static struct hda_verb alc662_ecs_init_verbs[] = { | |||
15278 | {} | 15422 | {} |
15279 | }; | 15423 | }; |
15280 | 15424 | ||
15281 | /* capture mixer elements */ | ||
15282 | static struct snd_kcontrol_new alc662_capture_mixer[] = { | ||
15283 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), | ||
15284 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), | ||
15285 | { | ||
15286 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
15287 | /* The multiple "Capture Source" controls confuse alsamixer | ||
15288 | * So call somewhat different.. | ||
15289 | */ | ||
15290 | /* .name = "Capture Source", */ | ||
15291 | .name = "Input Source", | ||
15292 | .count = 1, | ||
15293 | .info = alc662_mux_enum_info, | ||
15294 | .get = alc662_mux_enum_get, | ||
15295 | .put = alc662_mux_enum_put, | ||
15296 | }, | ||
15297 | { } /* end */ | ||
15298 | }; | ||
15299 | |||
15300 | static struct snd_kcontrol_new alc662_auto_capture_mixer[] = { | 15425 | static struct snd_kcontrol_new alc662_auto_capture_mixer[] = { |
15301 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), | 15426 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), |
15302 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), | 15427 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), |
@@ -15868,7 +15993,7 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = { | |||
15868 | 15993 | ||
15869 | static struct alc_config_preset alc662_presets[] = { | 15994 | static struct alc_config_preset alc662_presets[] = { |
15870 | [ALC662_3ST_2ch_DIG] = { | 15995 | [ALC662_3ST_2ch_DIG] = { |
15871 | .mixers = { alc662_3ST_2ch_mixer, alc662_capture_mixer }, | 15996 | .mixers = { alc662_3ST_2ch_mixer }, |
15872 | .init_verbs = { alc662_init_verbs }, | 15997 | .init_verbs = { alc662_init_verbs }, |
15873 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 15998 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
15874 | .dac_nids = alc662_dac_nids, | 15999 | .dac_nids = alc662_dac_nids, |
@@ -15879,8 +16004,7 @@ static struct alc_config_preset alc662_presets[] = { | |||
15879 | .input_mux = &alc662_capture_source, | 16004 | .input_mux = &alc662_capture_source, |
15880 | }, | 16005 | }, |
15881 | [ALC662_3ST_6ch_DIG] = { | 16006 | [ALC662_3ST_6ch_DIG] = { |
15882 | .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer, | 16007 | .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer }, |
15883 | alc662_capture_mixer }, | ||
15884 | .init_verbs = { alc662_init_verbs }, | 16008 | .init_verbs = { alc662_init_verbs }, |
15885 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 16009 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
15886 | .dac_nids = alc662_dac_nids, | 16010 | .dac_nids = alc662_dac_nids, |
@@ -15892,8 +16016,7 @@ static struct alc_config_preset alc662_presets[] = { | |||
15892 | .input_mux = &alc662_capture_source, | 16016 | .input_mux = &alc662_capture_source, |
15893 | }, | 16017 | }, |
15894 | [ALC662_3ST_6ch] = { | 16018 | [ALC662_3ST_6ch] = { |
15895 | .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer, | 16019 | .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer }, |
15896 | alc662_capture_mixer }, | ||
15897 | .init_verbs = { alc662_init_verbs }, | 16020 | .init_verbs = { alc662_init_verbs }, |
15898 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 16021 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
15899 | .dac_nids = alc662_dac_nids, | 16022 | .dac_nids = alc662_dac_nids, |
@@ -15903,8 +16026,7 @@ static struct alc_config_preset alc662_presets[] = { | |||
15903 | .input_mux = &alc662_capture_source, | 16026 | .input_mux = &alc662_capture_source, |
15904 | }, | 16027 | }, |
15905 | [ALC662_5ST_DIG] = { | 16028 | [ALC662_5ST_DIG] = { |
15906 | .mixers = { alc662_base_mixer, alc662_chmode_mixer, | 16029 | .mixers = { alc662_base_mixer, alc662_chmode_mixer }, |
15907 | alc662_capture_mixer }, | ||
15908 | .init_verbs = { alc662_init_verbs }, | 16030 | .init_verbs = { alc662_init_verbs }, |
15909 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 16031 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
15910 | .dac_nids = alc662_dac_nids, | 16032 | .dac_nids = alc662_dac_nids, |
@@ -15915,7 +16037,7 @@ static struct alc_config_preset alc662_presets[] = { | |||
15915 | .input_mux = &alc662_capture_source, | 16037 | .input_mux = &alc662_capture_source, |
15916 | }, | 16038 | }, |
15917 | [ALC662_LENOVO_101E] = { | 16039 | [ALC662_LENOVO_101E] = { |
15918 | .mixers = { alc662_lenovo_101e_mixer, alc662_capture_mixer }, | 16040 | .mixers = { alc662_lenovo_101e_mixer }, |
15919 | .init_verbs = { alc662_init_verbs, alc662_sue_init_verbs }, | 16041 | .init_verbs = { alc662_init_verbs, alc662_sue_init_verbs }, |
15920 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 16042 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
15921 | .dac_nids = alc662_dac_nids, | 16043 | .dac_nids = alc662_dac_nids, |
@@ -15926,7 +16048,7 @@ static struct alc_config_preset alc662_presets[] = { | |||
15926 | .init_hook = alc662_lenovo_101e_all_automute, | 16048 | .init_hook = alc662_lenovo_101e_all_automute, |
15927 | }, | 16049 | }, |
15928 | [ALC662_ASUS_EEEPC_P701] = { | 16050 | [ALC662_ASUS_EEEPC_P701] = { |
15929 | .mixers = { alc662_eeepc_p701_mixer, alc662_capture_mixer }, | 16051 | .mixers = { alc662_eeepc_p701_mixer }, |
15930 | .init_verbs = { alc662_init_verbs, | 16052 | .init_verbs = { alc662_init_verbs, |
15931 | alc662_eeepc_sue_init_verbs }, | 16053 | alc662_eeepc_sue_init_verbs }, |
15932 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 16054 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
@@ -15938,7 +16060,7 @@ static struct alc_config_preset alc662_presets[] = { | |||
15938 | .init_hook = alc662_eeepc_inithook, | 16060 | .init_hook = alc662_eeepc_inithook, |
15939 | }, | 16061 | }, |
15940 | [ALC662_ASUS_EEEPC_EP20] = { | 16062 | [ALC662_ASUS_EEEPC_EP20] = { |
15941 | .mixers = { alc662_eeepc_ep20_mixer, alc662_capture_mixer, | 16063 | .mixers = { alc662_eeepc_ep20_mixer, |
15942 | alc662_chmode_mixer }, | 16064 | alc662_chmode_mixer }, |
15943 | .init_verbs = { alc662_init_verbs, | 16065 | .init_verbs = { alc662_init_verbs, |
15944 | alc662_eeepc_ep20_sue_init_verbs }, | 16066 | alc662_eeepc_ep20_sue_init_verbs }, |
@@ -15951,7 +16073,7 @@ static struct alc_config_preset alc662_presets[] = { | |||
15951 | .init_hook = alc662_eeepc_ep20_inithook, | 16073 | .init_hook = alc662_eeepc_ep20_inithook, |
15952 | }, | 16074 | }, |
15953 | [ALC662_ECS] = { | 16075 | [ALC662_ECS] = { |
15954 | .mixers = { alc662_ecs_mixer, alc662_capture_mixer }, | 16076 | .mixers = { alc662_ecs_mixer }, |
15955 | .init_verbs = { alc662_init_verbs, | 16077 | .init_verbs = { alc662_init_verbs, |
15956 | alc662_ecs_init_verbs }, | 16078 | alc662_ecs_init_verbs }, |
15957 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 16079 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
@@ -15963,7 +16085,7 @@ static struct alc_config_preset alc662_presets[] = { | |||
15963 | .init_hook = alc662_eeepc_inithook, | 16085 | .init_hook = alc662_eeepc_inithook, |
15964 | }, | 16086 | }, |
15965 | [ALC663_ASUS_M51VA] = { | 16087 | [ALC663_ASUS_M51VA] = { |
15966 | .mixers = { alc663_m51va_mixer, alc662_capture_mixer}, | 16088 | .mixers = { alc663_m51va_mixer }, |
15967 | .init_verbs = { alc662_init_verbs, alc663_m51va_init_verbs }, | 16089 | .init_verbs = { alc662_init_verbs, alc663_m51va_init_verbs }, |
15968 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 16090 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
15969 | .dac_nids = alc662_dac_nids, | 16091 | .dac_nids = alc662_dac_nids, |
@@ -15975,7 +16097,7 @@ static struct alc_config_preset alc662_presets[] = { | |||
15975 | .init_hook = alc663_m51va_inithook, | 16097 | .init_hook = alc663_m51va_inithook, |
15976 | }, | 16098 | }, |
15977 | [ALC663_ASUS_G71V] = { | 16099 | [ALC663_ASUS_G71V] = { |
15978 | .mixers = { alc663_g71v_mixer, alc662_capture_mixer}, | 16100 | .mixers = { alc663_g71v_mixer }, |
15979 | .init_verbs = { alc662_init_verbs, alc663_g71v_init_verbs }, | 16101 | .init_verbs = { alc662_init_verbs, alc663_g71v_init_verbs }, |
15980 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 16102 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
15981 | .dac_nids = alc662_dac_nids, | 16103 | .dac_nids = alc662_dac_nids, |
@@ -15987,7 +16109,7 @@ static struct alc_config_preset alc662_presets[] = { | |||
15987 | .init_hook = alc663_g71v_inithook, | 16109 | .init_hook = alc663_g71v_inithook, |
15988 | }, | 16110 | }, |
15989 | [ALC663_ASUS_H13] = { | 16111 | [ALC663_ASUS_H13] = { |
15990 | .mixers = { alc663_m51va_mixer, alc662_capture_mixer}, | 16112 | .mixers = { alc663_m51va_mixer }, |
15991 | .init_verbs = { alc662_init_verbs, alc663_m51va_init_verbs }, | 16113 | .init_verbs = { alc662_init_verbs, alc663_m51va_init_verbs }, |
15992 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 16114 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
15993 | .dac_nids = alc662_dac_nids, | 16115 | .dac_nids = alc662_dac_nids, |
@@ -15998,7 +16120,7 @@ static struct alc_config_preset alc662_presets[] = { | |||
15998 | .init_hook = alc663_m51va_inithook, | 16120 | .init_hook = alc663_m51va_inithook, |
15999 | }, | 16121 | }, |
16000 | [ALC663_ASUS_G50V] = { | 16122 | [ALC663_ASUS_G50V] = { |
16001 | .mixers = { alc663_g50v_mixer, alc662_capture_mixer}, | 16123 | .mixers = { alc663_g50v_mixer }, |
16002 | .init_verbs = { alc662_init_verbs, alc663_g50v_init_verbs }, | 16124 | .init_verbs = { alc662_init_verbs, alc663_g50v_init_verbs }, |
16003 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 16125 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
16004 | .dac_nids = alc662_dac_nids, | 16126 | .dac_nids = alc662_dac_nids, |
@@ -16010,7 +16132,8 @@ static struct alc_config_preset alc662_presets[] = { | |||
16010 | .init_hook = alc663_g50v_inithook, | 16132 | .init_hook = alc663_g50v_inithook, |
16011 | }, | 16133 | }, |
16012 | [ALC663_ASUS_MODE1] = { | 16134 | [ALC663_ASUS_MODE1] = { |
16013 | .mixers = { alc663_m51va_mixer, alc662_auto_capture_mixer }, | 16135 | .mixers = { alc663_m51va_mixer }, |
16136 | .cap_mixer = alc662_auto_capture_mixer, | ||
16014 | .init_verbs = { alc662_init_verbs, | 16137 | .init_verbs = { alc662_init_verbs, |
16015 | alc663_21jd_amic_init_verbs }, | 16138 | alc663_21jd_amic_init_verbs }, |
16016 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 16139 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
@@ -16024,7 +16147,8 @@ static struct alc_config_preset alc662_presets[] = { | |||
16024 | .init_hook = alc663_mode1_inithook, | 16147 | .init_hook = alc663_mode1_inithook, |
16025 | }, | 16148 | }, |
16026 | [ALC662_ASUS_MODE2] = { | 16149 | [ALC662_ASUS_MODE2] = { |
16027 | .mixers = { alc662_1bjd_mixer, alc662_auto_capture_mixer }, | 16150 | .mixers = { alc662_1bjd_mixer }, |
16151 | .cap_mixer = alc662_auto_capture_mixer, | ||
16028 | .init_verbs = { alc662_init_verbs, | 16152 | .init_verbs = { alc662_init_verbs, |
16029 | alc662_1bjd_amic_init_verbs }, | 16153 | alc662_1bjd_amic_init_verbs }, |
16030 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 16154 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
@@ -16037,7 +16161,8 @@ static struct alc_config_preset alc662_presets[] = { | |||
16037 | .init_hook = alc662_mode2_inithook, | 16161 | .init_hook = alc662_mode2_inithook, |
16038 | }, | 16162 | }, |
16039 | [ALC663_ASUS_MODE3] = { | 16163 | [ALC663_ASUS_MODE3] = { |
16040 | .mixers = { alc663_two_hp_m1_mixer, alc662_auto_capture_mixer }, | 16164 | .mixers = { alc663_two_hp_m1_mixer }, |
16165 | .cap_mixer = alc662_auto_capture_mixer, | ||
16041 | .init_verbs = { alc662_init_verbs, | 16166 | .init_verbs = { alc662_init_verbs, |
16042 | alc663_two_hp_amic_m1_init_verbs }, | 16167 | alc663_two_hp_amic_m1_init_verbs }, |
16043 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 16168 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
@@ -16051,8 +16176,8 @@ static struct alc_config_preset alc662_presets[] = { | |||
16051 | .init_hook = alc663_mode3_inithook, | 16176 | .init_hook = alc663_mode3_inithook, |
16052 | }, | 16177 | }, |
16053 | [ALC663_ASUS_MODE4] = { | 16178 | [ALC663_ASUS_MODE4] = { |
16054 | .mixers = { alc663_asus_21jd_clfe_mixer, | 16179 | .mixers = { alc663_asus_21jd_clfe_mixer }, |
16055 | alc662_auto_capture_mixer}, | 16180 | .cap_mixer = alc662_auto_capture_mixer, |
16056 | .init_verbs = { alc662_init_verbs, | 16181 | .init_verbs = { alc662_init_verbs, |
16057 | alc663_21jd_amic_init_verbs}, | 16182 | alc663_21jd_amic_init_verbs}, |
16058 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 16183 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
@@ -16066,8 +16191,8 @@ static struct alc_config_preset alc662_presets[] = { | |||
16066 | .init_hook = alc663_mode4_inithook, | 16191 | .init_hook = alc663_mode4_inithook, |
16067 | }, | 16192 | }, |
16068 | [ALC663_ASUS_MODE5] = { | 16193 | [ALC663_ASUS_MODE5] = { |
16069 | .mixers = { alc663_asus_15jd_clfe_mixer, | 16194 | .mixers = { alc663_asus_15jd_clfe_mixer }, |
16070 | alc662_auto_capture_mixer }, | 16195 | .cap_mixer = alc662_auto_capture_mixer, |
16071 | .init_verbs = { alc662_init_verbs, | 16196 | .init_verbs = { alc662_init_verbs, |
16072 | alc663_15jd_amic_init_verbs }, | 16197 | alc663_15jd_amic_init_verbs }, |
16073 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 16198 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
@@ -16081,7 +16206,8 @@ static struct alc_config_preset alc662_presets[] = { | |||
16081 | .init_hook = alc663_mode5_inithook, | 16206 | .init_hook = alc663_mode5_inithook, |
16082 | }, | 16207 | }, |
16083 | [ALC663_ASUS_MODE6] = { | 16208 | [ALC663_ASUS_MODE6] = { |
16084 | .mixers = { alc663_two_hp_m2_mixer, alc662_auto_capture_mixer }, | 16209 | .mixers = { alc663_two_hp_m2_mixer }, |
16210 | .cap_mixer = alc662_auto_capture_mixer, | ||
16085 | .init_verbs = { alc662_init_verbs, | 16211 | .init_verbs = { alc662_init_verbs, |
16086 | alc663_two_hp_amic_m2_init_verbs }, | 16212 | alc663_two_hp_amic_m2_init_verbs }, |
16087 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 16213 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
@@ -16342,24 +16468,20 @@ static int alc662_parse_auto_config(struct hda_codec *codec) | |||
16342 | if (spec->autocfg.dig_out_pin) | 16468 | if (spec->autocfg.dig_out_pin) |
16343 | spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; | 16469 | spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; |
16344 | 16470 | ||
16345 | if (spec->kctl_alloc) | 16471 | if (spec->kctls.list) |
16346 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 16472 | add_mixer(spec, spec->kctls.list); |
16347 | 16473 | ||
16348 | spec->num_mux_defs = 1; | 16474 | spec->num_mux_defs = 1; |
16349 | spec->input_mux = &spec->private_imux; | 16475 | spec->input_mux = &spec->private_imux; |
16350 | 16476 | ||
16351 | spec->init_verbs[spec->num_init_verbs++] = alc662_auto_init_verbs; | 16477 | add_verb(spec, alc662_auto_init_verbs); |
16352 | if (codec->vendor_id == 0x10ec0663) | 16478 | if (codec->vendor_id == 0x10ec0663) |
16353 | spec->init_verbs[spec->num_init_verbs++] = | 16479 | add_verb(spec, alc663_auto_init_verbs); |
16354 | alc663_auto_init_verbs; | ||
16355 | 16480 | ||
16356 | err = alc_auto_add_mic_boost(codec); | 16481 | err = alc_auto_add_mic_boost(codec); |
16357 | if (err < 0) | 16482 | if (err < 0) |
16358 | return err; | 16483 | return err; |
16359 | 16484 | ||
16360 | spec->mixers[spec->num_mixers] = alc662_capture_mixer; | ||
16361 | spec->num_mixers++; | ||
16362 | |||
16363 | store_pin_configs(codec); | 16485 | store_pin_configs(codec); |
16364 | return 1; | 16486 | return 1; |
16365 | } | 16487 | } |
@@ -16435,6 +16557,10 @@ static int patch_alc662(struct hda_codec *codec) | |||
16435 | spec->adc_nids = alc662_adc_nids; | 16557 | spec->adc_nids = alc662_adc_nids; |
16436 | spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids); | 16558 | spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids); |
16437 | spec->capsrc_nids = alc662_capsrc_nids; | 16559 | spec->capsrc_nids = alc662_capsrc_nids; |
16560 | spec->is_mix_capture = 1; | ||
16561 | |||
16562 | if (!spec->cap_mixer) | ||
16563 | set_capture_mixer(spec); | ||
16438 | 16564 | ||
16439 | spec->vmaster_nid = 0x02; | 16565 | spec->vmaster_nid = 0x02; |
16440 | 16566 | ||
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 5a29699c6fdb..09b3f4b1db4d 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -30,13 +30,12 @@ | |||
30 | #include <linux/pci.h> | 30 | #include <linux/pci.h> |
31 | #include <sound/core.h> | 31 | #include <sound/core.h> |
32 | #include <sound/asoundef.h> | 32 | #include <sound/asoundef.h> |
33 | #include <sound/jack.h> | ||
33 | #include "hda_codec.h" | 34 | #include "hda_codec.h" |
34 | #include "hda_local.h" | 35 | #include "hda_local.h" |
35 | #include "hda_patch.h" | 36 | #include "hda_patch.h" |
36 | #include "hda_beep.h" | 37 | #include "hda_beep.h" |
37 | 38 | ||
38 | #define NUM_CONTROL_ALLOC 32 | ||
39 | |||
40 | #define STAC_VREF_EVENT 0x00 | 39 | #define STAC_VREF_EVENT 0x00 |
41 | #define STAC_INSERT_EVENT 0x10 | 40 | #define STAC_INSERT_EVENT 0x10 |
42 | #define STAC_PWR_EVENT 0x20 | 41 | #define STAC_PWR_EVENT 0x20 |
@@ -133,6 +132,17 @@ enum { | |||
133 | STAC_927X_MODELS | 132 | STAC_927X_MODELS |
134 | }; | 133 | }; |
135 | 134 | ||
135 | struct sigmatel_event { | ||
136 | hda_nid_t nid; | ||
137 | int data; | ||
138 | }; | ||
139 | |||
140 | struct sigmatel_jack { | ||
141 | hda_nid_t nid; | ||
142 | int type; | ||
143 | struct snd_jack *jack; | ||
144 | }; | ||
145 | |||
136 | struct sigmatel_spec { | 146 | struct sigmatel_spec { |
137 | struct snd_kcontrol_new *mixers[4]; | 147 | struct snd_kcontrol_new *mixers[4]; |
138 | unsigned int num_mixers; | 148 | unsigned int num_mixers; |
@@ -166,6 +176,12 @@ struct sigmatel_spec { | |||
166 | hda_nid_t *pwr_nids; | 176 | hda_nid_t *pwr_nids; |
167 | hda_nid_t *dac_list; | 177 | hda_nid_t *dac_list; |
168 | 178 | ||
179 | /* jack detection */ | ||
180 | struct snd_array jacks; | ||
181 | |||
182 | /* events */ | ||
183 | struct snd_array events; | ||
184 | |||
169 | /* playback */ | 185 | /* playback */ |
170 | struct hda_input_mux *mono_mux; | 186 | struct hda_input_mux *mono_mux; |
171 | struct hda_input_mux *amp_mux; | 187 | struct hda_input_mux *amp_mux; |
@@ -195,7 +211,6 @@ struct sigmatel_spec { | |||
195 | hda_nid_t *pin_nids; | 211 | hda_nid_t *pin_nids; |
196 | unsigned int num_pins; | 212 | unsigned int num_pins; |
197 | unsigned int *pin_configs; | 213 | unsigned int *pin_configs; |
198 | unsigned int *bios_pin_configs; | ||
199 | 214 | ||
200 | /* codec specific stuff */ | 215 | /* codec specific stuff */ |
201 | struct hda_verb *init; | 216 | struct hda_verb *init; |
@@ -223,8 +238,7 @@ struct sigmatel_spec { | |||
223 | 238 | ||
224 | /* dynamic controls and input_mux */ | 239 | /* dynamic controls and input_mux */ |
225 | struct auto_pin_cfg autocfg; | 240 | struct auto_pin_cfg autocfg; |
226 | unsigned int num_kctl_alloc, num_kctl_used; | 241 | struct snd_array kctls; |
227 | struct snd_kcontrol_new *kctl_alloc; | ||
228 | struct hda_input_mux private_dimux; | 242 | struct hda_input_mux private_dimux; |
229 | struct hda_input_mux private_imux; | 243 | struct hda_input_mux private_imux; |
230 | struct hda_input_mux private_smux; | 244 | struct hda_input_mux private_smux; |
@@ -1234,9 +1248,14 @@ static const char *slave_sws[] = { | |||
1234 | NULL | 1248 | NULL |
1235 | }; | 1249 | }; |
1236 | 1250 | ||
1251 | static void stac92xx_free_kctls(struct hda_codec *codec); | ||
1252 | static int stac92xx_add_jack(struct hda_codec *codec, hda_nid_t nid, int type); | ||
1253 | |||
1237 | static int stac92xx_build_controls(struct hda_codec *codec) | 1254 | static int stac92xx_build_controls(struct hda_codec *codec) |
1238 | { | 1255 | { |
1239 | struct sigmatel_spec *spec = codec->spec; | 1256 | struct sigmatel_spec *spec = codec->spec; |
1257 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
1258 | hda_nid_t nid; | ||
1240 | int err; | 1259 | int err; |
1241 | int i; | 1260 | int i; |
1242 | 1261 | ||
@@ -1251,7 +1270,7 @@ static int stac92xx_build_controls(struct hda_codec *codec) | |||
1251 | } | 1270 | } |
1252 | if (spec->num_dmuxes > 0) { | 1271 | if (spec->num_dmuxes > 0) { |
1253 | stac_dmux_mixer.count = spec->num_dmuxes; | 1272 | stac_dmux_mixer.count = spec->num_dmuxes; |
1254 | err = snd_ctl_add(codec->bus->card, | 1273 | err = snd_hda_ctl_add(codec, |
1255 | snd_ctl_new1(&stac_dmux_mixer, codec)); | 1274 | snd_ctl_new1(&stac_dmux_mixer, codec)); |
1256 | if (err < 0) | 1275 | if (err < 0) |
1257 | return err; | 1276 | return err; |
@@ -1306,6 +1325,37 @@ static int stac92xx_build_controls(struct hda_codec *codec) | |||
1306 | return err; | 1325 | return err; |
1307 | } | 1326 | } |
1308 | 1327 | ||
1328 | stac92xx_free_kctls(codec); /* no longer needed */ | ||
1329 | |||
1330 | /* create jack input elements */ | ||
1331 | if (spec->hp_detect) { | ||
1332 | for (i = 0; i < cfg->hp_outs; i++) { | ||
1333 | int type = SND_JACK_HEADPHONE; | ||
1334 | nid = cfg->hp_pins[i]; | ||
1335 | /* jack detection */ | ||
1336 | if (cfg->hp_outs == i) | ||
1337 | type |= SND_JACK_LINEOUT; | ||
1338 | err = stac92xx_add_jack(codec, nid, type); | ||
1339 | if (err < 0) | ||
1340 | return err; | ||
1341 | } | ||
1342 | } | ||
1343 | for (i = 0; i < cfg->line_outs; i++) { | ||
1344 | err = stac92xx_add_jack(codec, cfg->line_out_pins[i], | ||
1345 | SND_JACK_LINEOUT); | ||
1346 | if (err < 0) | ||
1347 | return err; | ||
1348 | } | ||
1349 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
1350 | nid = cfg->input_pins[i]; | ||
1351 | if (nid) { | ||
1352 | err = stac92xx_add_jack(codec, nid, | ||
1353 | SND_JACK_MICROPHONE); | ||
1354 | if (err < 0) | ||
1355 | return err; | ||
1356 | } | ||
1357 | } | ||
1358 | |||
1309 | return 0; | 1359 | return 0; |
1310 | } | 1360 | } |
1311 | 1361 | ||
@@ -1617,7 +1667,7 @@ static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = { | |||
1617 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, | 1667 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, |
1618 | "DFI LanParty", STAC_92HD73XX_REF), | 1668 | "DFI LanParty", STAC_92HD73XX_REF), |
1619 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0254, | 1669 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0254, |
1620 | "unknown Dell", STAC_DELL_M6), | 1670 | "Dell Studio 1535", STAC_DELL_M6), |
1621 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0255, | 1671 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0255, |
1622 | "unknown Dell", STAC_DELL_M6), | 1672 | "unknown Dell", STAC_DELL_M6), |
1623 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0256, | 1673 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0256, |
@@ -2185,12 +2235,11 @@ static int stac92xx_save_bios_config_regs(struct hda_codec *codec) | |||
2185 | int i; | 2235 | int i; |
2186 | struct sigmatel_spec *spec = codec->spec; | 2236 | struct sigmatel_spec *spec = codec->spec; |
2187 | 2237 | ||
2188 | if (! spec->bios_pin_configs) { | 2238 | kfree(spec->pin_configs); |
2189 | spec->bios_pin_configs = kcalloc(spec->num_pins, | 2239 | spec->pin_configs = kcalloc(spec->num_pins, sizeof(*spec->pin_configs), |
2190 | sizeof(*spec->bios_pin_configs), GFP_KERNEL); | 2240 | GFP_KERNEL); |
2191 | if (! spec->bios_pin_configs) | 2241 | if (!spec->pin_configs) |
2192 | return -ENOMEM; | 2242 | return -ENOMEM; |
2193 | } | ||
2194 | 2243 | ||
2195 | for (i = 0; i < spec->num_pins; i++) { | 2244 | for (i = 0; i < spec->num_pins; i++) { |
2196 | hda_nid_t nid = spec->pin_nids[i]; | 2245 | hda_nid_t nid = spec->pin_nids[i]; |
@@ -2200,7 +2249,7 @@ static int stac92xx_save_bios_config_regs(struct hda_codec *codec) | |||
2200 | AC_VERB_GET_CONFIG_DEFAULT, 0x00); | 2249 | AC_VERB_GET_CONFIG_DEFAULT, 0x00); |
2201 | snd_printdd(KERN_INFO "hda_codec: pin nid %2.2x bios pin config %8.8x\n", | 2250 | snd_printdd(KERN_INFO "hda_codec: pin nid %2.2x bios pin config %8.8x\n", |
2202 | nid, pin_cfg); | 2251 | nid, pin_cfg); |
2203 | spec->bios_pin_configs[i] = pin_cfg; | 2252 | spec->pin_configs[i] = pin_cfg; |
2204 | } | 2253 | } |
2205 | 2254 | ||
2206 | return 0; | 2255 | return 0; |
@@ -2242,6 +2291,39 @@ static void stac92xx_set_config_regs(struct hda_codec *codec) | |||
2242 | spec->pin_configs[i]); | 2291 | spec->pin_configs[i]); |
2243 | } | 2292 | } |
2244 | 2293 | ||
2294 | static int stac_save_pin_cfgs(struct hda_codec *codec, unsigned int *pins) | ||
2295 | { | ||
2296 | struct sigmatel_spec *spec = codec->spec; | ||
2297 | |||
2298 | if (!pins) | ||
2299 | return stac92xx_save_bios_config_regs(codec); | ||
2300 | |||
2301 | kfree(spec->pin_configs); | ||
2302 | spec->pin_configs = kmemdup(pins, | ||
2303 | spec->num_pins * sizeof(*pins), | ||
2304 | GFP_KERNEL); | ||
2305 | if (!spec->pin_configs) | ||
2306 | return -ENOMEM; | ||
2307 | |||
2308 | stac92xx_set_config_regs(codec); | ||
2309 | return 0; | ||
2310 | } | ||
2311 | |||
2312 | static void stac_change_pin_config(struct hda_codec *codec, hda_nid_t nid, | ||
2313 | unsigned int cfg) | ||
2314 | { | ||
2315 | struct sigmatel_spec *spec = codec->spec; | ||
2316 | int i; | ||
2317 | |||
2318 | for (i = 0; i < spec->num_pins; i++) { | ||
2319 | if (spec->pin_nids[i] == nid) { | ||
2320 | spec->pin_configs[i] = cfg; | ||
2321 | stac92xx_set_config_reg(codec, nid, cfg); | ||
2322 | break; | ||
2323 | } | ||
2324 | } | ||
2325 | } | ||
2326 | |||
2245 | /* | 2327 | /* |
2246 | * Analog playback callbacks | 2328 | * Analog playback callbacks |
2247 | */ | 2329 | */ |
@@ -2479,7 +2561,7 @@ static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol, | |||
2479 | /* check to be sure that the ports are upto date with | 2561 | /* check to be sure that the ports are upto date with |
2480 | * switch changes | 2562 | * switch changes |
2481 | */ | 2563 | */ |
2482 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | 2564 | codec->patch_ops.unsol_event(codec, (STAC_HP_EVENT | nid) << 26); |
2483 | 2565 | ||
2484 | return 1; | 2566 | return 1; |
2485 | } | 2567 | } |
@@ -2519,7 +2601,8 @@ static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
2519 | * appropriately according to the pin direction | 2601 | * appropriately according to the pin direction |
2520 | */ | 2602 | */ |
2521 | if (spec->hp_detect) | 2603 | if (spec->hp_detect) |
2522 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | 2604 | codec->patch_ops.unsol_event(codec, |
2605 | (STAC_HP_EVENT | nid) << 26); | ||
2523 | 2606 | ||
2524 | return 1; | 2607 | return 1; |
2525 | } | 2608 | } |
@@ -2614,28 +2697,16 @@ static int stac92xx_add_control_temp(struct sigmatel_spec *spec, | |||
2614 | { | 2697 | { |
2615 | struct snd_kcontrol_new *knew; | 2698 | struct snd_kcontrol_new *knew; |
2616 | 2699 | ||
2617 | if (spec->num_kctl_used >= spec->num_kctl_alloc) { | 2700 | snd_array_init(&spec->kctls, sizeof(*knew), 32); |
2618 | int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC; | 2701 | knew = snd_array_new(&spec->kctls); |
2619 | 2702 | if (!knew) | |
2620 | knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */ | 2703 | return -ENOMEM; |
2621 | if (! knew) | ||
2622 | return -ENOMEM; | ||
2623 | if (spec->kctl_alloc) { | ||
2624 | memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc); | ||
2625 | kfree(spec->kctl_alloc); | ||
2626 | } | ||
2627 | spec->kctl_alloc = knew; | ||
2628 | spec->num_kctl_alloc = num; | ||
2629 | } | ||
2630 | |||
2631 | knew = &spec->kctl_alloc[spec->num_kctl_used]; | ||
2632 | *knew = *ktemp; | 2704 | *knew = *ktemp; |
2633 | knew->index = idx; | 2705 | knew->index = idx; |
2634 | knew->name = kstrdup(name, GFP_KERNEL); | 2706 | knew->name = kstrdup(name, GFP_KERNEL); |
2635 | if (!knew->name) | 2707 | if (!knew->name) |
2636 | return -ENOMEM; | 2708 | return -ENOMEM; |
2637 | knew->private_value = val; | 2709 | knew->private_value = val; |
2638 | spec->num_kctl_used++; | ||
2639 | return 0; | 2710 | return 0; |
2640 | } | 2711 | } |
2641 | 2712 | ||
@@ -2891,7 +2962,7 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec, | |||
2891 | cfg->hp_outs && !spec->multiout.hp_nid) | 2962 | cfg->hp_outs && !spec->multiout.hp_nid) |
2892 | spec->multiout.hp_nid = nid; | 2963 | spec->multiout.hp_nid = nid; |
2893 | 2964 | ||
2894 | if (cfg->hp_outs > 1) { | 2965 | if (cfg->hp_outs > 1 && cfg->line_out_type == AUTO_PIN_LINE_OUT) { |
2895 | err = stac92xx_add_control(spec, | 2966 | err = stac92xx_add_control(spec, |
2896 | STAC_CTL_WIDGET_HP_SWITCH, | 2967 | STAC_CTL_WIDGET_HP_SWITCH, |
2897 | "Headphone as Line Out Switch", | 2968 | "Headphone as Line Out Switch", |
@@ -3512,8 +3583,8 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
3512 | if (dig_in && spec->autocfg.dig_in_pin) | 3583 | if (dig_in && spec->autocfg.dig_in_pin) |
3513 | spec->dig_in_nid = dig_in; | 3584 | spec->dig_in_nid = dig_in; |
3514 | 3585 | ||
3515 | if (spec->kctl_alloc) | 3586 | if (spec->kctls.list) |
3516 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 3587 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
3517 | 3588 | ||
3518 | spec->input_mux = &spec->private_imux; | 3589 | spec->input_mux = &spec->private_imux; |
3519 | spec->dinput_mux = &spec->private_dimux; | 3590 | spec->dinput_mux = &spec->private_dimux; |
@@ -3620,8 +3691,8 @@ static int stac9200_parse_auto_config(struct hda_codec *codec) | |||
3620 | if (spec->autocfg.dig_in_pin) | 3691 | if (spec->autocfg.dig_in_pin) |
3621 | spec->dig_in_nid = 0x04; | 3692 | spec->dig_in_nid = 0x04; |
3622 | 3693 | ||
3623 | if (spec->kctl_alloc) | 3694 | if (spec->kctls.list) |
3624 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 3695 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
3625 | 3696 | ||
3626 | spec->input_mux = &spec->private_imux; | 3697 | spec->input_mux = &spec->private_imux; |
3627 | spec->dinput_mux = &spec->private_dimux; | 3698 | spec->dinput_mux = &spec->private_dimux; |
@@ -3665,13 +3736,74 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask, | |||
3665 | AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */ | 3736 | AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */ |
3666 | } | 3737 | } |
3667 | 3738 | ||
3739 | static int stac92xx_add_jack(struct hda_codec *codec, | ||
3740 | hda_nid_t nid, int type) | ||
3741 | { | ||
3742 | #ifdef CONFIG_SND_JACK | ||
3743 | struct sigmatel_spec *spec = codec->spec; | ||
3744 | struct sigmatel_jack *jack; | ||
3745 | int def_conf = snd_hda_codec_read(codec, nid, | ||
3746 | 0, AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
3747 | int connectivity = get_defcfg_connect(def_conf); | ||
3748 | char name[32]; | ||
3749 | |||
3750 | if (connectivity && connectivity != AC_JACK_PORT_FIXED) | ||
3751 | return 0; | ||
3752 | |||
3753 | snd_array_init(&spec->jacks, sizeof(*jack), 32); | ||
3754 | jack = snd_array_new(&spec->jacks); | ||
3755 | if (!jack) | ||
3756 | return -ENOMEM; | ||
3757 | jack->nid = nid; | ||
3758 | jack->type = type; | ||
3759 | |||
3760 | sprintf(name, "%s at %s %s Jack", | ||
3761 | snd_hda_get_jack_type(def_conf), | ||
3762 | snd_hda_get_jack_connectivity(def_conf), | ||
3763 | snd_hda_get_jack_location(def_conf)); | ||
3764 | |||
3765 | return snd_jack_new(codec->bus->card, name, type, &jack->jack); | ||
3766 | #else | ||
3767 | return 0; | ||
3768 | #endif | ||
3769 | } | ||
3770 | |||
3771 | static int stac92xx_add_event(struct sigmatel_spec *spec, hda_nid_t nid, | ||
3772 | int data) | ||
3773 | { | ||
3774 | struct sigmatel_event *event; | ||
3775 | |||
3776 | snd_array_init(&spec->events, sizeof(*event), 32); | ||
3777 | event = snd_array_new(&spec->events); | ||
3778 | if (!event) | ||
3779 | return -ENOMEM; | ||
3780 | event->nid = nid; | ||
3781 | event->data = data; | ||
3782 | |||
3783 | return 0; | ||
3784 | } | ||
3785 | |||
3786 | static int stac92xx_event_data(struct hda_codec *codec, hda_nid_t nid) | ||
3787 | { | ||
3788 | struct sigmatel_spec *spec = codec->spec; | ||
3789 | struct sigmatel_event *events = spec->events.list; | ||
3790 | if (events) { | ||
3791 | int i; | ||
3792 | for (i = 0; i < spec->events.used; i++) | ||
3793 | if (events[i].nid == nid) | ||
3794 | return events[i].data; | ||
3795 | } | ||
3796 | return 0; | ||
3797 | } | ||
3798 | |||
3668 | static void enable_pin_detect(struct hda_codec *codec, hda_nid_t nid, | 3799 | static void enable_pin_detect(struct hda_codec *codec, hda_nid_t nid, |
3669 | unsigned int event) | 3800 | unsigned int event) |
3670 | { | 3801 | { |
3671 | if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) | 3802 | if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) { |
3672 | snd_hda_codec_write_cache(codec, nid, 0, | 3803 | snd_hda_codec_write_cache(codec, nid, 0, |
3673 | AC_VERB_SET_UNSOLICITED_ENABLE, | 3804 | AC_VERB_SET_UNSOLICITED_ENABLE, |
3674 | (AC_USRSP_EN | event)); | 3805 | (AC_USRSP_EN | event | nid)); |
3806 | } | ||
3675 | } | 3807 | } |
3676 | 3808 | ||
3677 | static int is_nid_hp_pin(struct auto_pin_cfg *cfg, hda_nid_t nid) | 3809 | static int is_nid_hp_pin(struct auto_pin_cfg *cfg, hda_nid_t nid) |
@@ -3728,17 +3860,18 @@ static int stac92xx_init(struct hda_codec *codec) | |||
3728 | /* set up pins */ | 3860 | /* set up pins */ |
3729 | if (spec->hp_detect) { | 3861 | if (spec->hp_detect) { |
3730 | /* Enable unsolicited responses on the HP widget */ | 3862 | /* Enable unsolicited responses on the HP widget */ |
3731 | for (i = 0; i < cfg->hp_outs; i++) | 3863 | for (i = 0; i < cfg->hp_outs; i++) { |
3732 | enable_pin_detect(codec, cfg->hp_pins[i], | 3864 | hda_nid_t nid = cfg->hp_pins[i]; |
3733 | STAC_HP_EVENT); | 3865 | enable_pin_detect(codec, nid, STAC_HP_EVENT | nid); |
3866 | } | ||
3734 | /* force to enable the first line-out; the others are set up | 3867 | /* force to enable the first line-out; the others are set up |
3735 | * in unsol_event | 3868 | * in unsol_event |
3736 | */ | 3869 | */ |
3737 | stac92xx_auto_set_pinctl(codec, spec->autocfg.line_out_pins[0], | 3870 | stac92xx_auto_set_pinctl(codec, spec->autocfg.line_out_pins[0], |
3738 | AC_PINCTL_OUT_EN); | 3871 | AC_PINCTL_OUT_EN); |
3739 | stac92xx_auto_init_hp_out(codec); | ||
3740 | /* fake event to set up pins */ | 3872 | /* fake event to set up pins */ |
3741 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | 3873 | codec->patch_ops.unsol_event(codec, |
3874 | (STAC_HP_EVENT | spec->autocfg.hp_pins[0]) << 26); | ||
3742 | } else { | 3875 | } else { |
3743 | stac92xx_auto_init_multi_out(codec); | 3876 | stac92xx_auto_init_multi_out(codec); |
3744 | stac92xx_auto_init_hp_out(codec); | 3877 | stac92xx_auto_init_hp_out(codec); |
@@ -3759,6 +3892,7 @@ static int stac92xx_init(struct hda_codec *codec) | |||
3759 | } | 3892 | } |
3760 | pinctl |= AC_PINCTL_IN_EN; | 3893 | pinctl |= AC_PINCTL_IN_EN; |
3761 | stac92xx_auto_set_pinctl(codec, nid, pinctl); | 3894 | stac92xx_auto_set_pinctl(codec, nid, pinctl); |
3895 | enable_pin_detect(codec, nid, STAC_INSERT_EVENT | nid); | ||
3762 | } | 3896 | } |
3763 | } | 3897 | } |
3764 | for (i = 0; i < spec->num_dmics; i++) | 3898 | for (i = 0; i < spec->num_dmics; i++) |
@@ -3804,22 +3938,44 @@ static int stac92xx_init(struct hda_codec *codec) | |||
3804 | return 0; | 3938 | return 0; |
3805 | } | 3939 | } |
3806 | 3940 | ||
3941 | static void stac92xx_free_jacks(struct hda_codec *codec) | ||
3942 | { | ||
3943 | #ifdef CONFIG_SND_JACK | ||
3944 | /* free jack instances manually when clearing/reconfiguring */ | ||
3945 | struct sigmatel_spec *spec = codec->spec; | ||
3946 | if (!codec->bus->shutdown && spec->jacks.list) { | ||
3947 | struct sigmatel_jack *jacks = spec->jacks.list; | ||
3948 | int i; | ||
3949 | for (i = 0; i < spec->jacks.used; i++) | ||
3950 | snd_device_free(codec->bus->card, &jacks[i].jack); | ||
3951 | } | ||
3952 | snd_array_free(&spec->jacks); | ||
3953 | #endif | ||
3954 | } | ||
3955 | |||
3956 | static void stac92xx_free_kctls(struct hda_codec *codec) | ||
3957 | { | ||
3958 | struct sigmatel_spec *spec = codec->spec; | ||
3959 | |||
3960 | if (spec->kctls.list) { | ||
3961 | struct snd_kcontrol_new *kctl = spec->kctls.list; | ||
3962 | int i; | ||
3963 | for (i = 0; i < spec->kctls.used; i++) | ||
3964 | kfree(kctl[i].name); | ||
3965 | } | ||
3966 | snd_array_free(&spec->kctls); | ||
3967 | } | ||
3968 | |||
3807 | static void stac92xx_free(struct hda_codec *codec) | 3969 | static void stac92xx_free(struct hda_codec *codec) |
3808 | { | 3970 | { |
3809 | struct sigmatel_spec *spec = codec->spec; | 3971 | struct sigmatel_spec *spec = codec->spec; |
3810 | int i; | ||
3811 | 3972 | ||
3812 | if (! spec) | 3973 | if (! spec) |
3813 | return; | 3974 | return; |
3814 | 3975 | ||
3815 | if (spec->kctl_alloc) { | 3976 | kfree(spec->pin_configs); |
3816 | for (i = 0; i < spec->num_kctl_used; i++) | 3977 | stac92xx_free_jacks(codec); |
3817 | kfree(spec->kctl_alloc[i].name); | 3978 | snd_array_free(&spec->events); |
3818 | kfree(spec->kctl_alloc); | ||
3819 | } | ||
3820 | |||
3821 | if (spec->bios_pin_configs) | ||
3822 | kfree(spec->bios_pin_configs); | ||
3823 | 3979 | ||
3824 | kfree(spec); | 3980 | kfree(spec); |
3825 | snd_hda_detach_beep_device(codec); | 3981 | snd_hda_detach_beep_device(codec); |
@@ -3999,22 +4155,55 @@ static void stac92xx_pin_sense(struct hda_codec *codec, hda_nid_t nid) | |||
3999 | stac_toggle_power_map(codec, nid, get_hp_pin_presence(codec, nid)); | 4155 | stac_toggle_power_map(codec, nid, get_hp_pin_presence(codec, nid)); |
4000 | } | 4156 | } |
4001 | 4157 | ||
4158 | static void stac92xx_report_jack(struct hda_codec *codec, hda_nid_t nid) | ||
4159 | { | ||
4160 | struct sigmatel_spec *spec = codec->spec; | ||
4161 | struct sigmatel_jack *jacks = spec->jacks.list; | ||
4162 | |||
4163 | if (jacks) { | ||
4164 | int i; | ||
4165 | for (i = 0; i < spec->jacks.used; i++) { | ||
4166 | if (jacks->nid == nid) { | ||
4167 | unsigned int pin_ctl = | ||
4168 | snd_hda_codec_read(codec, nid, | ||
4169 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, | ||
4170 | 0x00); | ||
4171 | int type = jacks->type; | ||
4172 | if (type == (SND_JACK_LINEOUT | ||
4173 | | SND_JACK_HEADPHONE)) | ||
4174 | type = (pin_ctl & AC_PINCTL_HP_EN) | ||
4175 | ? SND_JACK_HEADPHONE : SND_JACK_LINEOUT; | ||
4176 | snd_jack_report(jacks->jack, | ||
4177 | get_hp_pin_presence(codec, nid) | ||
4178 | ? type : 0); | ||
4179 | } | ||
4180 | jacks++; | ||
4181 | } | ||
4182 | } | ||
4183 | } | ||
4184 | |||
4002 | static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) | 4185 | static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) |
4003 | { | 4186 | { |
4004 | struct sigmatel_spec *spec = codec->spec; | 4187 | struct sigmatel_spec *spec = codec->spec; |
4005 | int idx = res >> 26 & 0x0f; | 4188 | int event = (res >> 26) & 0x70; |
4189 | int nid = res >> 26 & 0x0f; | ||
4006 | 4190 | ||
4007 | switch ((res >> 26) & 0x70) { | 4191 | switch (event) { |
4008 | case STAC_HP_EVENT: | 4192 | case STAC_HP_EVENT: |
4009 | stac92xx_hp_detect(codec, res); | 4193 | stac92xx_hp_detect(codec, res); |
4010 | /* fallthru */ | 4194 | /* fallthru */ |
4195 | case STAC_INSERT_EVENT: | ||
4011 | case STAC_PWR_EVENT: | 4196 | case STAC_PWR_EVENT: |
4012 | if (spec->num_pwrs > 0) | 4197 | if (nid) { |
4013 | stac92xx_pin_sense(codec, idx); | 4198 | if (spec->num_pwrs > 0) |
4199 | stac92xx_pin_sense(codec, nid); | ||
4200 | stac92xx_report_jack(codec, nid); | ||
4201 | } | ||
4014 | break; | 4202 | break; |
4015 | case STAC_VREF_EVENT: { | 4203 | case STAC_VREF_EVENT: { |
4016 | int data = snd_hda_codec_read(codec, codec->afg, 0, | 4204 | int data = snd_hda_codec_read(codec, codec->afg, 0, |
4017 | AC_VERB_GET_GPIO_DATA, 0); | 4205 | AC_VERB_GET_GPIO_DATA, 0); |
4206 | int idx = stac92xx_event_data(codec, nid); | ||
4018 | /* toggle VREF state based on GPIOx status */ | 4207 | /* toggle VREF state based on GPIOx status */ |
4019 | snd_hda_codec_write(codec, codec->afg, 0, 0x7e0, | 4208 | snd_hda_codec_write(codec, codec->afg, 0, 0x7e0, |
4020 | !!(data & (1 << idx))); | 4209 | !!(data & (1 << idx))); |
@@ -4029,17 +4218,23 @@ static int stac92xx_resume(struct hda_codec *codec) | |||
4029 | struct sigmatel_spec *spec = codec->spec; | 4218 | struct sigmatel_spec *spec = codec->spec; |
4030 | 4219 | ||
4031 | stac92xx_set_config_regs(codec); | 4220 | stac92xx_set_config_regs(codec); |
4032 | snd_hda_sequence_write(codec, spec->init); | 4221 | stac92xx_init(codec); |
4033 | stac_gpio_set(codec, spec->gpio_mask, | ||
4034 | spec->gpio_dir, spec->gpio_data); | ||
4035 | snd_hda_codec_resume_amp(codec); | 4222 | snd_hda_codec_resume_amp(codec); |
4036 | snd_hda_codec_resume_cache(codec); | 4223 | snd_hda_codec_resume_cache(codec); |
4037 | /* power down inactive DACs */ | 4224 | /* fake event to set up pins again to override cached values */ |
4038 | if (spec->dac_list) | ||
4039 | stac92xx_power_down(codec); | ||
4040 | /* invoke unsolicited event to reset the HP state */ | ||
4041 | if (spec->hp_detect) | 4225 | if (spec->hp_detect) |
4042 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | 4226 | codec->patch_ops.unsol_event(codec, |
4227 | (STAC_HP_EVENT | spec->autocfg.hp_pins[0]) << 26); | ||
4228 | return 0; | ||
4229 | } | ||
4230 | |||
4231 | static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state) | ||
4232 | { | ||
4233 | struct sigmatel_spec *spec = codec->spec; | ||
4234 | if (spec->eapd_mask) | ||
4235 | stac_gpio_set(codec, spec->gpio_mask, | ||
4236 | spec->gpio_dir, spec->gpio_data & | ||
4237 | ~spec->eapd_mask); | ||
4043 | return 0; | 4238 | return 0; |
4044 | } | 4239 | } |
4045 | #endif | 4240 | #endif |
@@ -4051,6 +4246,7 @@ static struct hda_codec_ops stac92xx_patch_ops = { | |||
4051 | .free = stac92xx_free, | 4246 | .free = stac92xx_free, |
4052 | .unsol_event = stac92xx_unsol_event, | 4247 | .unsol_event = stac92xx_unsol_event, |
4053 | #ifdef SND_HDA_NEEDS_RESUME | 4248 | #ifdef SND_HDA_NEEDS_RESUME |
4249 | .suspend = stac92xx_suspend, | ||
4054 | .resume = stac92xx_resume, | 4250 | .resume = stac92xx_resume, |
4055 | #endif | 4251 | #endif |
4056 | }; | 4252 | }; |
@@ -4073,14 +4269,12 @@ static int patch_stac9200(struct hda_codec *codec) | |||
4073 | if (spec->board_config < 0) { | 4269 | if (spec->board_config < 0) { |
4074 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9200, using BIOS defaults\n"); | 4270 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9200, using BIOS defaults\n"); |
4075 | err = stac92xx_save_bios_config_regs(codec); | 4271 | err = stac92xx_save_bios_config_regs(codec); |
4076 | if (err < 0) { | 4272 | } else |
4077 | stac92xx_free(codec); | 4273 | err = stac_save_pin_cfgs(codec, |
4078 | return err; | 4274 | stac9200_brd_tbl[spec->board_config]); |
4079 | } | 4275 | if (err < 0) { |
4080 | spec->pin_configs = spec->bios_pin_configs; | 4276 | stac92xx_free(codec); |
4081 | } else { | 4277 | return err; |
4082 | spec->pin_configs = stac9200_brd_tbl[spec->board_config]; | ||
4083 | stac92xx_set_config_regs(codec); | ||
4084 | } | 4278 | } |
4085 | 4279 | ||
4086 | spec->multiout.max_channels = 2; | 4280 | spec->multiout.max_channels = 2; |
@@ -4136,14 +4330,12 @@ static int patch_stac925x(struct hda_codec *codec) | |||
4136 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC925x," | 4330 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC925x," |
4137 | "using BIOS defaults\n"); | 4331 | "using BIOS defaults\n"); |
4138 | err = stac92xx_save_bios_config_regs(codec); | 4332 | err = stac92xx_save_bios_config_regs(codec); |
4139 | if (err < 0) { | 4333 | } else |
4140 | stac92xx_free(codec); | 4334 | err = stac_save_pin_cfgs(codec, |
4141 | return err; | 4335 | stac925x_brd_tbl[spec->board_config]); |
4142 | } | 4336 | if (err < 0) { |
4143 | spec->pin_configs = spec->bios_pin_configs; | 4337 | stac92xx_free(codec); |
4144 | } else if (stac925x_brd_tbl[spec->board_config] != NULL){ | 4338 | return err; |
4145 | spec->pin_configs = stac925x_brd_tbl[spec->board_config]; | ||
4146 | stac92xx_set_config_regs(codec); | ||
4147 | } | 4339 | } |
4148 | 4340 | ||
4149 | spec->multiout.max_channels = 2; | 4341 | spec->multiout.max_channels = 2; |
@@ -4225,14 +4417,12 @@ again: | |||
4225 | snd_printdd(KERN_INFO "hda_codec: Unknown model for" | 4417 | snd_printdd(KERN_INFO "hda_codec: Unknown model for" |
4226 | " STAC92HD73XX, using BIOS defaults\n"); | 4418 | " STAC92HD73XX, using BIOS defaults\n"); |
4227 | err = stac92xx_save_bios_config_regs(codec); | 4419 | err = stac92xx_save_bios_config_regs(codec); |
4228 | if (err < 0) { | 4420 | } else |
4229 | stac92xx_free(codec); | 4421 | err = stac_save_pin_cfgs(codec, |
4230 | return err; | 4422 | stac92hd73xx_brd_tbl[spec->board_config]); |
4231 | } | 4423 | if (err < 0) { |
4232 | spec->pin_configs = spec->bios_pin_configs; | 4424 | stac92xx_free(codec); |
4233 | } else { | 4425 | return err; |
4234 | spec->pin_configs = stac92hd73xx_brd_tbl[spec->board_config]; | ||
4235 | stac92xx_set_config_regs(codec); | ||
4236 | } | 4426 | } |
4237 | 4427 | ||
4238 | spec->multiout.num_dacs = snd_hda_get_connections(codec, 0x0a, | 4428 | spec->multiout.num_dacs = snd_hda_get_connections(codec, 0x0a, |
@@ -4408,14 +4598,12 @@ again: | |||
4408 | snd_printdd(KERN_INFO "hda_codec: Unknown model for" | 4598 | snd_printdd(KERN_INFO "hda_codec: Unknown model for" |
4409 | " STAC92HD83XXX, using BIOS defaults\n"); | 4599 | " STAC92HD83XXX, using BIOS defaults\n"); |
4410 | err = stac92xx_save_bios_config_regs(codec); | 4600 | err = stac92xx_save_bios_config_regs(codec); |
4411 | if (err < 0) { | 4601 | } else |
4412 | stac92xx_free(codec); | 4602 | err = stac_save_pin_cfgs(codec, |
4413 | return err; | 4603 | stac92hd83xxx_brd_tbl[spec->board_config]); |
4414 | } | 4604 | if (err < 0) { |
4415 | spec->pin_configs = spec->bios_pin_configs; | 4605 | stac92xx_free(codec); |
4416 | } else { | 4606 | return err; |
4417 | spec->pin_configs = stac92hd83xxx_brd_tbl[spec->board_config]; | ||
4418 | stac92xx_set_config_regs(codec); | ||
4419 | } | 4607 | } |
4420 | 4608 | ||
4421 | err = stac92xx_parse_auto_config(codec, 0x1d, 0); | 4609 | err = stac92xx_parse_auto_config(codec, 0x1d, 0); |
@@ -4463,14 +4651,8 @@ static int stac92hd71xx_resume(struct hda_codec *codec) | |||
4463 | 4651 | ||
4464 | static int stac92hd71xx_suspend(struct hda_codec *codec, pm_message_t state) | 4652 | static int stac92hd71xx_suspend(struct hda_codec *codec, pm_message_t state) |
4465 | { | 4653 | { |
4466 | struct sigmatel_spec *spec = codec->spec; | ||
4467 | |||
4468 | stac92hd71xx_set_power_state(codec, AC_PWRST_D3); | 4654 | stac92hd71xx_set_power_state(codec, AC_PWRST_D3); |
4469 | if (spec->eapd_mask) | 4655 | return stac92xx_suspend(codec, state); |
4470 | stac_gpio_set(codec, spec->gpio_mask, | ||
4471 | spec->gpio_dir, spec->gpio_data & | ||
4472 | ~spec->eapd_mask); | ||
4473 | return 0; | ||
4474 | }; | 4656 | }; |
4475 | 4657 | ||
4476 | #endif | 4658 | #endif |
@@ -4482,8 +4664,8 @@ static struct hda_codec_ops stac92hd71bxx_patch_ops = { | |||
4482 | .free = stac92xx_free, | 4664 | .free = stac92xx_free, |
4483 | .unsol_event = stac92xx_unsol_event, | 4665 | .unsol_event = stac92xx_unsol_event, |
4484 | #ifdef SND_HDA_NEEDS_RESUME | 4666 | #ifdef SND_HDA_NEEDS_RESUME |
4485 | .resume = stac92hd71xx_resume, | ||
4486 | .suspend = stac92hd71xx_suspend, | 4667 | .suspend = stac92hd71xx_suspend, |
4668 | .resume = stac92hd71xx_resume, | ||
4487 | #endif | 4669 | #endif |
4488 | }; | 4670 | }; |
4489 | 4671 | ||
@@ -4522,14 +4704,12 @@ again: | |||
4522 | snd_printdd(KERN_INFO "hda_codec: Unknown model for" | 4704 | snd_printdd(KERN_INFO "hda_codec: Unknown model for" |
4523 | " STAC92HD71BXX, using BIOS defaults\n"); | 4705 | " STAC92HD71BXX, using BIOS defaults\n"); |
4524 | err = stac92xx_save_bios_config_regs(codec); | 4706 | err = stac92xx_save_bios_config_regs(codec); |
4525 | if (err < 0) { | 4707 | } else |
4526 | stac92xx_free(codec); | 4708 | err = stac_save_pin_cfgs(codec, |
4527 | return err; | 4709 | stac92hd71bxx_brd_tbl[spec->board_config]); |
4528 | } | 4710 | if (err < 0) { |
4529 | spec->pin_configs = spec->bios_pin_configs; | 4711 | stac92xx_free(codec); |
4530 | } else { | 4712 | return err; |
4531 | spec->pin_configs = stac92hd71bxx_brd_tbl[spec->board_config]; | ||
4532 | stac92xx_set_config_regs(codec); | ||
4533 | } | 4713 | } |
4534 | 4714 | ||
4535 | if (spec->board_config > STAC_92HD71BXX_REF) { | 4715 | if (spec->board_config > STAC_92HD71BXX_REF) { |
@@ -4555,8 +4735,11 @@ again: | |||
4555 | snd_hda_codec_write_cache(codec, codec->afg, 0, | 4735 | snd_hda_codec_write_cache(codec, codec->afg, 0, |
4556 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02); | 4736 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02); |
4557 | snd_hda_codec_write_cache(codec, codec->afg, 0, | 4737 | snd_hda_codec_write_cache(codec, codec->afg, 0, |
4558 | AC_VERB_SET_UNSOLICITED_ENABLE, | 4738 | AC_VERB_SET_UNSOLICITED_ENABLE, |
4559 | (AC_USRSP_EN | STAC_VREF_EVENT | 0x01)); | 4739 | (AC_USRSP_EN | STAC_VREF_EVENT | codec->afg)); |
4740 | err = stac92xx_add_event(spec, codec->afg, 0x02); | ||
4741 | if (err < 0) | ||
4742 | return err; | ||
4560 | spec->gpio_mask |= 0x02; | 4743 | spec->gpio_mask |= 0x02; |
4561 | break; | 4744 | break; |
4562 | } | 4745 | } |
@@ -4575,7 +4758,7 @@ again: | |||
4575 | 4758 | ||
4576 | /* disable VSW */ | 4759 | /* disable VSW */ |
4577 | spec->init = &stac92hd71bxx_analog_core_init[HD_DISABLE_PORTF]; | 4760 | spec->init = &stac92hd71bxx_analog_core_init[HD_DISABLE_PORTF]; |
4578 | stac92xx_set_config_reg(codec, 0xf, 0x40f000f0); | 4761 | stac_change_pin_config(codec, 0xf, 0x40f000f0); |
4579 | break; | 4762 | break; |
4580 | case 0x111d7603: /* 6 Port with Analog Mixer */ | 4763 | case 0x111d7603: /* 6 Port with Analog Mixer */ |
4581 | if ((codec->revision_id & 0xf) == 1) { | 4764 | if ((codec->revision_id & 0xf) == 1) { |
@@ -4613,7 +4796,7 @@ again: | |||
4613 | switch (spec->board_config) { | 4796 | switch (spec->board_config) { |
4614 | case STAC_HP_M4: | 4797 | case STAC_HP_M4: |
4615 | /* enable internal microphone */ | 4798 | /* enable internal microphone */ |
4616 | stac92xx_set_config_reg(codec, 0x0e, 0x01813040); | 4799 | stac_change_pin_config(codec, 0x0e, 0x01813040); |
4617 | stac92xx_auto_set_pinctl(codec, 0x0e, | 4800 | stac92xx_auto_set_pinctl(codec, 0x0e, |
4618 | AC_PINCTL_IN_EN | AC_PINCTL_VREF_80); | 4801 | AC_PINCTL_IN_EN | AC_PINCTL_VREF_80); |
4619 | /* fallthru */ | 4802 | /* fallthru */ |
@@ -4719,14 +4902,12 @@ static int patch_stac922x(struct hda_codec *codec) | |||
4719 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, " | 4902 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, " |
4720 | "using BIOS defaults\n"); | 4903 | "using BIOS defaults\n"); |
4721 | err = stac92xx_save_bios_config_regs(codec); | 4904 | err = stac92xx_save_bios_config_regs(codec); |
4722 | if (err < 0) { | 4905 | } else |
4723 | stac92xx_free(codec); | 4906 | err = stac_save_pin_cfgs(codec, |
4724 | return err; | 4907 | stac922x_brd_tbl[spec->board_config]); |
4725 | } | 4908 | if (err < 0) { |
4726 | spec->pin_configs = spec->bios_pin_configs; | 4909 | stac92xx_free(codec); |
4727 | } else if (stac922x_brd_tbl[spec->board_config] != NULL) { | 4910 | return err; |
4728 | spec->pin_configs = stac922x_brd_tbl[spec->board_config]; | ||
4729 | stac92xx_set_config_regs(codec); | ||
4730 | } | 4911 | } |
4731 | 4912 | ||
4732 | spec->adc_nids = stac922x_adc_nids; | 4913 | spec->adc_nids = stac922x_adc_nids; |
@@ -4789,14 +4970,12 @@ static int patch_stac927x(struct hda_codec *codec) | |||
4789 | snd_printdd(KERN_INFO "hda_codec: Unknown model for" | 4970 | snd_printdd(KERN_INFO "hda_codec: Unknown model for" |
4790 | "STAC927x, using BIOS defaults\n"); | 4971 | "STAC927x, using BIOS defaults\n"); |
4791 | err = stac92xx_save_bios_config_regs(codec); | 4972 | err = stac92xx_save_bios_config_regs(codec); |
4792 | if (err < 0) { | 4973 | } else |
4793 | stac92xx_free(codec); | 4974 | err = stac_save_pin_cfgs(codec, |
4794 | return err; | 4975 | stac927x_brd_tbl[spec->board_config]); |
4795 | } | 4976 | if (err < 0) { |
4796 | spec->pin_configs = spec->bios_pin_configs; | 4977 | stac92xx_free(codec); |
4797 | } else { | 4978 | return err; |
4798 | spec->pin_configs = stac927x_brd_tbl[spec->board_config]; | ||
4799 | stac92xx_set_config_regs(codec); | ||
4800 | } | 4979 | } |
4801 | 4980 | ||
4802 | spec->digbeep_nid = 0x23; | 4981 | spec->digbeep_nid = 0x23; |
@@ -4826,15 +5005,15 @@ static int patch_stac927x(struct hda_codec *codec) | |||
4826 | case 0x10280209: | 5005 | case 0x10280209: |
4827 | case 0x1028022e: | 5006 | case 0x1028022e: |
4828 | /* correct the device field to SPDIF out */ | 5007 | /* correct the device field to SPDIF out */ |
4829 | stac92xx_set_config_reg(codec, 0x21, 0x01442070); | 5008 | stac_change_pin_config(codec, 0x21, 0x01442070); |
4830 | break; | 5009 | break; |
4831 | }; | 5010 | }; |
4832 | /* configure the analog microphone on some laptops */ | 5011 | /* configure the analog microphone on some laptops */ |
4833 | stac92xx_set_config_reg(codec, 0x0c, 0x90a79130); | 5012 | stac_change_pin_config(codec, 0x0c, 0x90a79130); |
4834 | /* correct the front output jack as a hp out */ | 5013 | /* correct the front output jack as a hp out */ |
4835 | stac92xx_set_config_reg(codec, 0x0f, 0x0227011f); | 5014 | stac_change_pin_config(codec, 0x0f, 0x0227011f); |
4836 | /* correct the front input jack as a mic */ | 5015 | /* correct the front input jack as a mic */ |
4837 | stac92xx_set_config_reg(codec, 0x0e, 0x02a79130); | 5016 | stac_change_pin_config(codec, 0x0e, 0x02a79130); |
4838 | /* fallthru */ | 5017 | /* fallthru */ |
4839 | case STAC_DELL_3ST: | 5018 | case STAC_DELL_3ST: |
4840 | /* GPIO2 High = Enable EAPD */ | 5019 | /* GPIO2 High = Enable EAPD */ |
@@ -4916,14 +5095,12 @@ static int patch_stac9205(struct hda_codec *codec) | |||
4916 | if (spec->board_config < 0) { | 5095 | if (spec->board_config < 0) { |
4917 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9205, using BIOS defaults\n"); | 5096 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9205, using BIOS defaults\n"); |
4918 | err = stac92xx_save_bios_config_regs(codec); | 5097 | err = stac92xx_save_bios_config_regs(codec); |
4919 | if (err < 0) { | 5098 | } else |
4920 | stac92xx_free(codec); | 5099 | err = stac_save_pin_cfgs(codec, |
4921 | return err; | 5100 | stac9205_brd_tbl[spec->board_config]); |
4922 | } | 5101 | if (err < 0) { |
4923 | spec->pin_configs = spec->bios_pin_configs; | 5102 | stac92xx_free(codec); |
4924 | } else { | 5103 | return err; |
4925 | spec->pin_configs = stac9205_brd_tbl[spec->board_config]; | ||
4926 | stac92xx_set_config_regs(codec); | ||
4927 | } | 5104 | } |
4928 | 5105 | ||
4929 | spec->digbeep_nid = 0x23; | 5106 | spec->digbeep_nid = 0x23; |
@@ -4950,15 +5127,18 @@ static int patch_stac9205(struct hda_codec *codec) | |||
4950 | switch (spec->board_config){ | 5127 | switch (spec->board_config){ |
4951 | case STAC_9205_DELL_M43: | 5128 | case STAC_9205_DELL_M43: |
4952 | /* Enable SPDIF in/out */ | 5129 | /* Enable SPDIF in/out */ |
4953 | stac92xx_set_config_reg(codec, 0x1f, 0x01441030); | 5130 | stac_change_pin_config(codec, 0x1f, 0x01441030); |
4954 | stac92xx_set_config_reg(codec, 0x20, 0x1c410030); | 5131 | stac_change_pin_config(codec, 0x20, 0x1c410030); |
4955 | 5132 | ||
4956 | /* Enable unsol response for GPIO4/Dock HP connection */ | 5133 | /* Enable unsol response for GPIO4/Dock HP connection */ |
4957 | snd_hda_codec_write_cache(codec, codec->afg, 0, | 5134 | snd_hda_codec_write_cache(codec, codec->afg, 0, |
4958 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10); | 5135 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10); |
4959 | snd_hda_codec_write_cache(codec, codec->afg, 0, | 5136 | snd_hda_codec_write_cache(codec, codec->afg, 0, |
4960 | AC_VERB_SET_UNSOLICITED_ENABLE, | 5137 | AC_VERB_SET_UNSOLICITED_ENABLE, |
4961 | (AC_USRSP_EN | STAC_HP_EVENT)); | 5138 | (AC_USRSP_EN | STAC_VREF_EVENT | codec->afg)); |
5139 | err = stac92xx_add_event(spec, codec->afg, 0x01); | ||
5140 | if (err < 0) | ||
5141 | return err; | ||
4962 | 5142 | ||
4963 | spec->gpio_dir = 0x0b; | 5143 | spec->gpio_dir = 0x0b; |
4964 | spec->eapd_mask = 0x01; | 5144 | spec->eapd_mask = 0x01; |
@@ -5052,29 +5232,11 @@ static struct hda_verb vaio_ar_init[] = { | |||
5052 | {} | 5232 | {} |
5053 | }; | 5233 | }; |
5054 | 5234 | ||
5055 | /* bind volumes of both NID 0x02 and 0x05 */ | ||
5056 | static struct hda_bind_ctls vaio_bind_master_vol = { | ||
5057 | .ops = &snd_hda_bind_vol, | ||
5058 | .values = { | ||
5059 | HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT), | ||
5060 | HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT), | ||
5061 | 0 | ||
5062 | }, | ||
5063 | }; | ||
5064 | |||
5065 | /* bind volumes of both NID 0x02 and 0x05 */ | ||
5066 | static struct hda_bind_ctls vaio_bind_master_sw = { | ||
5067 | .ops = &snd_hda_bind_sw, | ||
5068 | .values = { | ||
5069 | HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT), | ||
5070 | HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT), | ||
5071 | 0, | ||
5072 | }, | ||
5073 | }; | ||
5074 | |||
5075 | static struct snd_kcontrol_new vaio_mixer[] = { | 5235 | static struct snd_kcontrol_new vaio_mixer[] = { |
5076 | HDA_BIND_VOL("Master Playback Volume", &vaio_bind_master_vol), | 5236 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x02, 0, HDA_OUTPUT), |
5077 | HDA_BIND_SW("Master Playback Switch", &vaio_bind_master_sw), | 5237 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x02, 0, HDA_OUTPUT), |
5238 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x05, 0, HDA_OUTPUT), | ||
5239 | HDA_CODEC_MUTE("Speaker Playback Switch", 0x05, 0, HDA_OUTPUT), | ||
5078 | /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */ | 5240 | /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */ |
5079 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), | 5241 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), |
5080 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), | 5242 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), |
@@ -5090,8 +5252,10 @@ static struct snd_kcontrol_new vaio_mixer[] = { | |||
5090 | }; | 5252 | }; |
5091 | 5253 | ||
5092 | static struct snd_kcontrol_new vaio_ar_mixer[] = { | 5254 | static struct snd_kcontrol_new vaio_ar_mixer[] = { |
5093 | HDA_BIND_VOL("Master Playback Volume", &vaio_bind_master_vol), | 5255 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x02, 0, HDA_OUTPUT), |
5094 | HDA_BIND_SW("Master Playback Switch", &vaio_bind_master_sw), | 5256 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x02, 0, HDA_OUTPUT), |
5257 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x05, 0, HDA_OUTPUT), | ||
5258 | HDA_CODEC_MUTE("Speaker Playback Switch", 0x05, 0, HDA_OUTPUT), | ||
5095 | /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */ | 5259 | /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */ |
5096 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), | 5260 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), |
5097 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), | 5261 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), |
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 63e4871e5d8f..05182be1c9f0 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c | |||
@@ -53,9 +53,6 @@ | |||
53 | #define AMP_VAL_IDX_SHIFT 19 | 53 | #define AMP_VAL_IDX_SHIFT 19 |
54 | #define AMP_VAL_IDX_MASK (0x0f<<19) | 54 | #define AMP_VAL_IDX_MASK (0x0f<<19) |
55 | 55 | ||
56 | #define NUM_CONTROL_ALLOC 32 | ||
57 | #define NUM_VERB_ALLOC 32 | ||
58 | |||
59 | /* Pin Widget NID */ | 56 | /* Pin Widget NID */ |
60 | #define VT1708_HP_NID 0x13 | 57 | #define VT1708_HP_NID 0x13 |
61 | #define VT1708_DIGOUT_NID 0x14 | 58 | #define VT1708_DIGOUT_NID 0x14 |
@@ -145,8 +142,6 @@ enum { | |||
145 | AUTO_SEQ_SIDE | 142 | AUTO_SEQ_SIDE |
146 | }; | 143 | }; |
147 | 144 | ||
148 | #define get_amp_nid(kc) ((kc)->private_value & 0xffff) | ||
149 | |||
150 | /* Some VT1708S based boards gets the micboost setting wrong, so we have | 145 | /* Some VT1708S based boards gets the micboost setting wrong, so we have |
151 | * to apply some brute-force and re-write the TLV's by software. */ | 146 | * to apply some brute-force and re-write the TLV's by software. */ |
152 | static int mic_boost_tlv(struct snd_kcontrol *kcontrol, int op_flag, | 147 | static int mic_boost_tlv(struct snd_kcontrol *kcontrol, int op_flag, |
@@ -227,8 +222,7 @@ struct via_spec { | |||
227 | 222 | ||
228 | /* dynamic controls, init_verbs and input_mux */ | 223 | /* dynamic controls, init_verbs and input_mux */ |
229 | struct auto_pin_cfg autocfg; | 224 | struct auto_pin_cfg autocfg; |
230 | unsigned int num_kctl_alloc, num_kctl_used; | 225 | struct snd_array kctls; |
231 | struct snd_kcontrol_new *kctl_alloc; | ||
232 | struct hda_input_mux private_imux[2]; | 226 | struct hda_input_mux private_imux[2]; |
233 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; | 227 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; |
234 | 228 | ||
@@ -272,33 +266,31 @@ static int via_add_control(struct via_spec *spec, int type, const char *name, | |||
272 | { | 266 | { |
273 | struct snd_kcontrol_new *knew; | 267 | struct snd_kcontrol_new *knew; |
274 | 268 | ||
275 | if (spec->num_kctl_used >= spec->num_kctl_alloc) { | 269 | snd_array_init(&spec->kctls, sizeof(*knew), 32); |
276 | int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC; | 270 | knew = snd_array_new(&spec->kctls); |
277 | 271 | if (!knew) | |
278 | /* array + terminator */ | 272 | return -ENOMEM; |
279 | knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); | ||
280 | if (!knew) | ||
281 | return -ENOMEM; | ||
282 | if (spec->kctl_alloc) { | ||
283 | memcpy(knew, spec->kctl_alloc, | ||
284 | sizeof(*knew) * spec->num_kctl_alloc); | ||
285 | kfree(spec->kctl_alloc); | ||
286 | } | ||
287 | spec->kctl_alloc = knew; | ||
288 | spec->num_kctl_alloc = num; | ||
289 | } | ||
290 | |||
291 | knew = &spec->kctl_alloc[spec->num_kctl_used]; | ||
292 | *knew = vt1708_control_templates[type]; | 273 | *knew = vt1708_control_templates[type]; |
293 | knew->name = kstrdup(name, GFP_KERNEL); | 274 | knew->name = kstrdup(name, GFP_KERNEL); |
294 | |||
295 | if (!knew->name) | 275 | if (!knew->name) |
296 | return -ENOMEM; | 276 | return -ENOMEM; |
297 | knew->private_value = val; | 277 | knew->private_value = val; |
298 | spec->num_kctl_used++; | ||
299 | return 0; | 278 | return 0; |
300 | } | 279 | } |
301 | 280 | ||
281 | static void via_free_kctls(struct hda_codec *codec) | ||
282 | { | ||
283 | struct via_spec *spec = codec->spec; | ||
284 | |||
285 | if (spec->kctls.list) { | ||
286 | struct snd_kcontrol_new *kctl = spec->kctls.list; | ||
287 | int i; | ||
288 | for (i = 0; i < spec->kctls.used; i++) | ||
289 | kfree(kctl[i].name); | ||
290 | } | ||
291 | snd_array_free(&spec->kctls); | ||
292 | } | ||
293 | |||
302 | /* create input playback/capture controls for the given pin */ | 294 | /* create input playback/capture controls for the given pin */ |
303 | static int via_new_analog_input(struct via_spec *spec, hda_nid_t pin, | 295 | static int via_new_analog_input(struct via_spec *spec, hda_nid_t pin, |
304 | const char *ctlname, int idx, int mix_nid) | 296 | const char *ctlname, int idx, int mix_nid) |
@@ -896,6 +888,7 @@ static int via_build_controls(struct hda_codec *codec) | |||
896 | if (err < 0) | 888 | if (err < 0) |
897 | return err; | 889 | return err; |
898 | } | 890 | } |
891 | via_free_kctls(codec); /* no longer needed */ | ||
899 | return 0; | 892 | return 0; |
900 | } | 893 | } |
901 | 894 | ||
@@ -941,17 +934,11 @@ static int via_build_pcms(struct hda_codec *codec) | |||
941 | static void via_free(struct hda_codec *codec) | 934 | static void via_free(struct hda_codec *codec) |
942 | { | 935 | { |
943 | struct via_spec *spec = codec->spec; | 936 | struct via_spec *spec = codec->spec; |
944 | unsigned int i; | ||
945 | 937 | ||
946 | if (!spec) | 938 | if (!spec) |
947 | return; | 939 | return; |
948 | 940 | ||
949 | if (spec->kctl_alloc) { | 941 | via_free_kctls(codec); |
950 | for (i = 0; i < spec->num_kctl_used; i++) | ||
951 | kfree(spec->kctl_alloc[i].name); | ||
952 | kfree(spec->kctl_alloc); | ||
953 | } | ||
954 | |||
955 | kfree(codec->spec); | 942 | kfree(codec->spec); |
956 | } | 943 | } |
957 | 944 | ||
@@ -1373,8 +1360,8 @@ static int vt1708_parse_auto_config(struct hda_codec *codec) | |||
1373 | if (spec->autocfg.dig_in_pin) | 1360 | if (spec->autocfg.dig_in_pin) |
1374 | spec->dig_in_nid = VT1708_DIGIN_NID; | 1361 | spec->dig_in_nid = VT1708_DIGIN_NID; |
1375 | 1362 | ||
1376 | if (spec->kctl_alloc) | 1363 | if (spec->kctls.list) |
1377 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 1364 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
1378 | 1365 | ||
1379 | spec->init_verbs[spec->num_iverbs++] = vt1708_volume_init_verbs; | 1366 | spec->init_verbs[spec->num_iverbs++] = vt1708_volume_init_verbs; |
1380 | 1367 | ||
@@ -1846,8 +1833,8 @@ static int vt1709_parse_auto_config(struct hda_codec *codec) | |||
1846 | if (spec->autocfg.dig_in_pin) | 1833 | if (spec->autocfg.dig_in_pin) |
1847 | spec->dig_in_nid = VT1709_DIGIN_NID; | 1834 | spec->dig_in_nid = VT1709_DIGIN_NID; |
1848 | 1835 | ||
1849 | if (spec->kctl_alloc) | 1836 | if (spec->kctls.list) |
1850 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 1837 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
1851 | 1838 | ||
1852 | spec->input_mux = &spec->private_imux[0]; | 1839 | spec->input_mux = &spec->private_imux[0]; |
1853 | 1840 | ||
@@ -2390,8 +2377,8 @@ static int vt1708B_parse_auto_config(struct hda_codec *codec) | |||
2390 | if (spec->autocfg.dig_in_pin) | 2377 | if (spec->autocfg.dig_in_pin) |
2391 | spec->dig_in_nid = VT1708B_DIGIN_NID; | 2378 | spec->dig_in_nid = VT1708B_DIGIN_NID; |
2392 | 2379 | ||
2393 | if (spec->kctl_alloc) | 2380 | if (spec->kctls.list) |
2394 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 2381 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
2395 | 2382 | ||
2396 | spec->input_mux = &spec->private_imux[0]; | 2383 | spec->input_mux = &spec->private_imux[0]; |
2397 | 2384 | ||
@@ -2855,8 +2842,8 @@ static int vt1708S_parse_auto_config(struct hda_codec *codec) | |||
2855 | 2842 | ||
2856 | spec->extra_dig_out_nid = 0x15; | 2843 | spec->extra_dig_out_nid = 0x15; |
2857 | 2844 | ||
2858 | if (spec->kctl_alloc) | 2845 | if (spec->kctls.list) |
2859 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 2846 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
2860 | 2847 | ||
2861 | spec->input_mux = &spec->private_imux[0]; | 2848 | spec->input_mux = &spec->private_imux[0]; |
2862 | 2849 | ||
@@ -3174,8 +3161,8 @@ static int vt1702_parse_auto_config(struct hda_codec *codec) | |||
3174 | 3161 | ||
3175 | spec->extra_dig_out_nid = 0x1B; | 3162 | spec->extra_dig_out_nid = 0x1B; |
3176 | 3163 | ||
3177 | if (spec->kctl_alloc) | 3164 | if (spec->kctls.list) |
3178 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 3165 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
3179 | 3166 | ||
3180 | spec->input_mux = &spec->private_imux[0]; | 3167 | spec->input_mux = &spec->private_imux[0]; |
3181 | 3168 | ||