diff options
-rw-r--r-- | Documentation/sound/alsa/ALSA-Configuration.txt | 4 | ||||
-rw-r--r-- | include/linux/input.h | 1 | ||||
-rw-r--r-- | include/sound/jack.h | 1 | ||||
-rw-r--r-- | sound/core/jack.c | 9 | ||||
-rw-r--r-- | sound/pci/Kconfig | 9 | ||||
-rw-r--r-- | sound/pci/hda/Makefile | 1 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.c | 504 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 54 | ||||
-rw-r--r-- | sound/pci/hda/hda_generic.c | 20 | ||||
-rw-r--r-- | sound/pci/hda/hda_hwdep.c | 228 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.c | 264 | ||||
-rw-r--r-- | sound/pci/hda/hda_local.h | 24 | ||||
-rw-r--r-- | sound/pci/hda/hda_patch.h | 2 | ||||
-rw-r--r-- | sound/pci/hda/hda_proc.c | 44 | ||||
-rw-r--r-- | sound/pci/hda/patch_analog.c | 56 | ||||
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 11 | ||||
-rw-r--r-- | sound/pci/hda/patch_intelhdmi.c | 928 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 1302 | ||||
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 249 | ||||
-rw-r--r-- | sound/pci/hda/patch_via.c | 71 |
20 files changed, 2598 insertions, 1184 deletions
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index e0e54a27fc10..3ab5fb1357a2 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt | |||
@@ -844,6 +844,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. | |||
844 | 3stack 3-stack model | 844 | 3stack 3-stack model |
845 | toshiba Toshiba A205 | 845 | toshiba Toshiba A205 |
846 | acer Acer laptops | 846 | acer Acer laptops |
847 | acer-dmic Acer laptops with digital-mic | ||
847 | acer-aspire Acer Aspire One | 848 | acer-aspire Acer Aspire One |
848 | dell Dell OEM laptops (Vostro 1200) | 849 | dell Dell OEM laptops (Vostro 1200) |
849 | zepto Zepto laptops | 850 | zepto Zepto laptops |
@@ -857,6 +858,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. | |||
857 | quanta Quanta FL1 | 858 | quanta Quanta FL1 |
858 | eeepc-p703 ASUS Eeepc P703 P900A | 859 | eeepc-p703 ASUS Eeepc P703 P900A |
859 | eeepc-p901 ASUS Eeepc P901 S101 | 860 | eeepc-p901 ASUS Eeepc P901 S101 |
861 | fujitsu FSC Amilo | ||
862 | auto auto-config reading BIOS (default) | ||
860 | 863 | ||
861 | ALC662/663 | 864 | ALC662/663 |
862 | 3stack-dig 3-stack (2-channel) with SPDIF | 865 | 3stack-dig 3-stack (2-channel) with SPDIF |
@@ -938,6 +941,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. | |||
938 | lenovo Lenovo 3000 C200 | 941 | lenovo Lenovo 3000 C200 |
939 | dallas Dallas laptops | 942 | dallas Dallas laptops |
940 | hp HP TX1000 | 943 | hp HP TX1000 |
944 | asus-v1s ASUS V1Sn | ||
941 | auto auto-config reading BIOS (default) | 945 | auto auto-config reading BIOS (default) |
942 | 946 | ||
943 | CMI9880 | 947 | CMI9880 |
diff --git a/include/linux/input.h b/include/linux/input.h index a5802c9c81a4..7323d2ff5151 100644 --- a/include/linux/input.h +++ b/include/linux/input.h | |||
@@ -644,6 +644,7 @@ struct input_absinfo { | |||
644 | #define SW_RADIO SW_RFKILL_ALL /* deprecated */ | 644 | #define SW_RADIO SW_RFKILL_ALL /* deprecated */ |
645 | #define SW_MICROPHONE_INSERT 0x04 /* set = inserted */ | 645 | #define SW_MICROPHONE_INSERT 0x04 /* set = inserted */ |
646 | #define SW_DOCK 0x05 /* set = plugged into dock */ | 646 | #define SW_DOCK 0x05 /* set = plugged into dock */ |
647 | #define SW_LINEOUT_INSERT 0x06 /* set = inserted */ | ||
647 | #define SW_MAX 0x0f | 648 | #define SW_MAX 0x0f |
648 | #define SW_CNT (SW_MAX+1) | 649 | #define SW_CNT (SW_MAX+1) |
649 | 650 | ||
diff --git a/include/sound/jack.h b/include/sound/jack.h index b1b2b8b59adb..7cb25f4b50bb 100644 --- a/include/sound/jack.h +++ b/include/sound/jack.h | |||
@@ -35,6 +35,7 @@ enum snd_jack_types { | |||
35 | SND_JACK_HEADPHONE = 0x0001, | 35 | SND_JACK_HEADPHONE = 0x0001, |
36 | SND_JACK_MICROPHONE = 0x0002, | 36 | SND_JACK_MICROPHONE = 0x0002, |
37 | SND_JACK_HEADSET = SND_JACK_HEADPHONE | SND_JACK_MICROPHONE, | 37 | SND_JACK_HEADSET = SND_JACK_HEADPHONE | SND_JACK_MICROPHONE, |
38 | SND_JACK_LINEOUT = 0x0004, | ||
38 | }; | 39 | }; |
39 | 40 | ||
40 | struct snd_jack { | 41 | struct snd_jack { |
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..21e9327a0ef4 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig | |||
@@ -501,6 +501,7 @@ config SND_HDA_INTEL | |||
501 | tristate "Intel HD Audio" | 501 | tristate "Intel HD Audio" |
502 | select SND_PCM | 502 | select SND_PCM |
503 | select SND_VMASTER | 503 | select SND_VMASTER |
504 | select SND_JACK if INPUT=y || INPUT=SND | ||
504 | help | 505 | help |
505 | Say Y here to include support for Intel "High Definition | 506 | Say Y here to include support for Intel "High Definition |
506 | Audio" (Azalia) motherboard devices. | 507 | Audio" (Azalia) motherboard devices. |
@@ -573,6 +574,14 @@ config SND_HDA_CODEC_NVHDMI | |||
573 | Say Y here to include NVIDIA HDMI HD-audio codec support in | 574 | Say Y here to include NVIDIA HDMI HD-audio codec support in |
574 | snd-hda-intel driver, such as NVIDIA MCP78 HDMI. | 575 | snd-hda-intel driver, such as NVIDIA MCP78 HDMI. |
575 | 576 | ||
577 | config SND_HDA_CODEC_INTELHDMI | ||
578 | bool "Build INTEL HDMI HD-audio codec support" | ||
579 | depends on SND_HDA_INTEL | ||
580 | default y | ||
581 | help | ||
582 | Say Y here to include INTEL HDMI HD-audio codec support in | ||
583 | snd-hda-intel driver, such as Eaglelake integrated HDMI. | ||
584 | |||
576 | config SND_HDA_CODEC_CONEXANT | 585 | config SND_HDA_CODEC_CONEXANT |
577 | bool "Build Conexant HD-audio codec support" | 586 | bool "Build Conexant HD-audio codec support" |
578 | depends on SND_HDA_INTEL | 587 | depends on SND_HDA_INTEL |
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile index 1980c6d207e7..6fb5add1e39a 100644 --- a/sound/pci/hda/Makefile +++ b/sound/pci/hda/Makefile | |||
@@ -16,5 +16,6 @@ snd-hda-intel-$(CONFIG_SND_HDA_CODEC_ATIHDMI) += patch_atihdmi.o | |||
16 | snd-hda-intel-$(CONFIG_SND_HDA_CODEC_CONEXANT) += patch_conexant.o | 16 | snd-hda-intel-$(CONFIG_SND_HDA_CODEC_CONEXANT) += patch_conexant.o |
17 | snd-hda-intel-$(CONFIG_SND_HDA_CODEC_VIA) += patch_via.o | 17 | snd-hda-intel-$(CONFIG_SND_HDA_CODEC_VIA) += patch_via.o |
18 | snd-hda-intel-$(CONFIG_SND_HDA_CODEC_NVHDMI) += patch_nvhdmi.o | 18 | snd-hda-intel-$(CONFIG_SND_HDA_CODEC_NVHDMI) += patch_nvhdmi.o |
19 | snd-hda-intel-$(CONFIG_SND_HDA_CODEC_INTELHDMI) += patch_intelhdmi.o | ||
19 | 20 | ||
20 | obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-intel.o | 21 | 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 ba1ab737b55f..06e99c785155 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 | ||
@@ -394,6 +467,20 @@ static int snd_hda_bus_dev_free(struct snd_device *device) | |||
394 | return snd_hda_bus_free(bus); | 467 | return snd_hda_bus_free(bus); |
395 | } | 468 | } |
396 | 469 | ||
470 | #ifdef CONFIG_SND_HDA_HWDEP | ||
471 | static int snd_hda_bus_dev_register(struct snd_device *device) | ||
472 | { | ||
473 | struct hda_bus *bus = device->device_data; | ||
474 | struct hda_codec *codec; | ||
475 | list_for_each_entry(codec, &bus->codec_list, list) { | ||
476 | snd_hda_hwdep_add_sysfs(codec); | ||
477 | } | ||
478 | return 0; | ||
479 | } | ||
480 | #else | ||
481 | #define snd_hda_bus_dev_register NULL | ||
482 | #endif | ||
483 | |||
397 | /** | 484 | /** |
398 | * snd_hda_bus_new - create a HDA bus | 485 | * snd_hda_bus_new - create a HDA bus |
399 | * @card: the card entry | 486 | * @card: the card entry |
@@ -409,6 +496,7 @@ int __devinit snd_hda_bus_new(struct snd_card *card, | |||
409 | struct hda_bus *bus; | 496 | struct hda_bus *bus; |
410 | int err; | 497 | int err; |
411 | static struct snd_device_ops dev_ops = { | 498 | static struct snd_device_ops dev_ops = { |
499 | .dev_register = snd_hda_bus_dev_register, | ||
412 | .dev_free = snd_hda_bus_dev_free, | 500 | .dev_free = snd_hda_bus_dev_free, |
413 | }; | 501 | }; |
414 | 502 | ||
@@ -447,7 +535,7 @@ int __devinit snd_hda_bus_new(struct snd_card *card, | |||
447 | 535 | ||
448 | #ifdef CONFIG_SND_HDA_GENERIC | 536 | #ifdef CONFIG_SND_HDA_GENERIC |
449 | #define is_generic_config(codec) \ | 537 | #define is_generic_config(codec) \ |
450 | (codec->bus->modelname && !strcmp(codec->bus->modelname, "generic")) | 538 | (codec->modelname && !strcmp(codec->modelname, "generic")) |
451 | #else | 539 | #else |
452 | #define is_generic_config(codec) 0 | 540 | #define is_generic_config(codec) 0 |
453 | #endif | 541 | #endif |
@@ -455,7 +543,7 @@ int __devinit snd_hda_bus_new(struct snd_card *card, | |||
455 | /* | 543 | /* |
456 | * find a matching codec preset | 544 | * find a matching codec preset |
457 | */ | 545 | */ |
458 | static const struct hda_codec_preset __devinit * | 546 | static const struct hda_codec_preset * |
459 | find_codec_preset(struct hda_codec *codec) | 547 | find_codec_preset(struct hda_codec *codec) |
460 | { | 548 | { |
461 | const struct hda_codec_preset **tbl, *preset; | 549 | const struct hda_codec_preset **tbl, *preset; |
@@ -482,15 +570,14 @@ find_codec_preset(struct hda_codec *codec) | |||
482 | } | 570 | } |
483 | 571 | ||
484 | /* | 572 | /* |
485 | * snd_hda_get_codec_name - store the codec name | 573 | * get_codec_name - store the codec name |
486 | */ | 574 | */ |
487 | void snd_hda_get_codec_name(struct hda_codec *codec, | 575 | static int get_codec_name(struct hda_codec *codec) |
488 | char *name, int namelen) | ||
489 | { | 576 | { |
490 | const struct hda_vendor_id *c; | 577 | const struct hda_vendor_id *c; |
491 | const char *vendor = NULL; | 578 | const char *vendor = NULL; |
492 | u16 vendor_id = codec->vendor_id >> 16; | 579 | u16 vendor_id = codec->vendor_id >> 16; |
493 | char tmp[16]; | 580 | char tmp[16], name[32]; |
494 | 581 | ||
495 | for (c = hda_vendor_ids; c->id; c++) { | 582 | for (c = hda_vendor_ids; c->id; c++) { |
496 | if (c->id == vendor_id) { | 583 | if (c->id == vendor_id) { |
@@ -503,10 +590,15 @@ void snd_hda_get_codec_name(struct hda_codec *codec, | |||
503 | vendor = tmp; | 590 | vendor = tmp; |
504 | } | 591 | } |
505 | if (codec->preset && codec->preset->name) | 592 | if (codec->preset && codec->preset->name) |
506 | snprintf(name, namelen, "%s %s", vendor, codec->preset->name); | 593 | snprintf(name, sizeof(name), "%s %s", vendor, |
594 | codec->preset->name); | ||
507 | else | 595 | else |
508 | snprintf(name, namelen, "%s ID %x", vendor, | 596 | snprintf(name, sizeof(name), "%s ID %x", vendor, |
509 | codec->vendor_id & 0xffff); | 597 | codec->vendor_id & 0xffff); |
598 | codec->name = kstrdup(name, GFP_KERNEL); | ||
599 | if (!codec->name) | ||
600 | return -ENOMEM; | ||
601 | return 0; | ||
510 | } | 602 | } |
511 | 603 | ||
512 | /* | 604 | /* |
@@ -571,11 +663,14 @@ static void snd_hda_codec_free(struct hda_codec *codec) | |||
571 | flush_scheduled_work(); | 663 | flush_scheduled_work(); |
572 | #endif | 664 | #endif |
573 | list_del(&codec->list); | 665 | list_del(&codec->list); |
666 | snd_array_free(&codec->mixers); | ||
574 | codec->bus->caddr_tbl[codec->addr] = NULL; | 667 | codec->bus->caddr_tbl[codec->addr] = NULL; |
575 | if (codec->patch_ops.free) | 668 | if (codec->patch_ops.free) |
576 | codec->patch_ops.free(codec); | 669 | codec->patch_ops.free(codec); |
577 | free_hda_cache(&codec->amp_cache); | 670 | free_hda_cache(&codec->amp_cache); |
578 | free_hda_cache(&codec->cmd_cache); | 671 | free_hda_cache(&codec->cmd_cache); |
672 | kfree(codec->name); | ||
673 | kfree(codec->modelname); | ||
579 | kfree(codec->wcaps); | 674 | kfree(codec->wcaps); |
580 | kfree(codec); | 675 | kfree(codec); |
581 | } | 676 | } |
@@ -617,6 +712,14 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, | |||
617 | mutex_init(&codec->spdif_mutex); | 712 | mutex_init(&codec->spdif_mutex); |
618 | init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); | 713 | init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); |
619 | init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); | 714 | init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); |
715 | snd_array_init(&codec->mixers, sizeof(struct snd_kcontrol *), 32); | ||
716 | if (codec->bus->modelname) { | ||
717 | codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL); | ||
718 | if (!codec->modelname) { | ||
719 | snd_hda_codec_free(codec); | ||
720 | return -ENODEV; | ||
721 | } | ||
722 | } | ||
620 | 723 | ||
621 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 724 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
622 | INIT_DELAYED_WORK(&codec->power_work, hda_power_work); | 725 | INIT_DELAYED_WORK(&codec->power_work, hda_power_work); |
@@ -662,12 +765,41 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, | |||
662 | snd_hda_codec_read(codec, nid, 0, | 765 | snd_hda_codec_read(codec, nid, 0, |
663 | AC_VERB_GET_SUBSYSTEM_ID, 0); | 766 | AC_VERB_GET_SUBSYSTEM_ID, 0); |
664 | } | 767 | } |
768 | if (bus->modelname) | ||
769 | codec->modelname = kstrdup(bus->modelname, GFP_KERNEL); | ||
770 | |||
771 | err = snd_hda_codec_configure(codec); | ||
772 | if (err < 0) { | ||
773 | snd_hda_codec_free(codec); | ||
774 | return err; | ||
775 | } | ||
776 | snd_hda_codec_proc_new(codec); | ||
777 | |||
778 | snd_hda_create_hwdep(codec); | ||
779 | |||
780 | sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id, | ||
781 | codec->subsystem_id, codec->revision_id); | ||
782 | snd_component_add(codec->bus->card, component); | ||
783 | |||
784 | if (codecp) | ||
785 | *codecp = codec; | ||
786 | return 0; | ||
787 | } | ||
788 | |||
789 | int snd_hda_codec_configure(struct hda_codec *codec) | ||
790 | { | ||
791 | int err; | ||
665 | 792 | ||
666 | codec->preset = find_codec_preset(codec); | 793 | codec->preset = find_codec_preset(codec); |
794 | if (!codec->name) { | ||
795 | err = get_codec_name(codec); | ||
796 | if (err < 0) | ||
797 | return err; | ||
798 | } | ||
667 | /* audio codec should override the mixer name */ | 799 | /* audio codec should override the mixer name */ |
668 | if (codec->afg || !*bus->card->mixername) | 800 | if (codec->afg || !*codec->bus->card->mixername) |
669 | snd_hda_get_codec_name(codec, bus->card->mixername, | 801 | strlcpy(codec->bus->card->mixername, codec->name, |
670 | sizeof(bus->card->mixername)); | 802 | sizeof(codec->bus->card->mixername)); |
671 | 803 | ||
672 | if (is_generic_config(codec)) { | 804 | if (is_generic_config(codec)) { |
673 | err = snd_hda_parse_generic_codec(codec); | 805 | err = snd_hda_parse_generic_codec(codec); |
@@ -684,25 +816,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"); | 816 | printk(KERN_ERR "hda-codec: No codec parser is available\n"); |
685 | 817 | ||
686 | patched: | 818 | patched: |
687 | if (err < 0) { | 819 | if (!err && codec->patch_ops.unsol_event) |
688 | snd_hda_codec_free(codec); | 820 | err = init_unsol_queue(codec->bus); |
689 | return err; | 821 | 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 | } | 822 | } |
707 | 823 | ||
708 | /** | 824 | /** |
@@ -757,12 +873,12 @@ static void __devinit init_hda_cache(struct hda_cache_rec *cache, | |||
757 | { | 873 | { |
758 | memset(cache, 0, sizeof(*cache)); | 874 | memset(cache, 0, sizeof(*cache)); |
759 | memset(cache->hash, 0xff, sizeof(cache->hash)); | 875 | memset(cache->hash, 0xff, sizeof(cache->hash)); |
760 | cache->record_size = record_size; | 876 | snd_array_init(&cache->buf, record_size, 64); |
761 | } | 877 | } |
762 | 878 | ||
763 | static void free_hda_cache(struct hda_cache_rec *cache) | 879 | static void free_hda_cache(struct hda_cache_rec *cache) |
764 | { | 880 | { |
765 | kfree(cache->buffer); | 881 | snd_array_free(&cache->buf); |
766 | } | 882 | } |
767 | 883 | ||
768 | /* query the hash. allocate an entry if not found. */ | 884 | /* query the hash. allocate an entry if not found. */ |
@@ -771,38 +887,21 @@ static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache, | |||
771 | { | 887 | { |
772 | u16 idx = key % (u16)ARRAY_SIZE(cache->hash); | 888 | u16 idx = key % (u16)ARRAY_SIZE(cache->hash); |
773 | u16 cur = cache->hash[idx]; | 889 | u16 cur = cache->hash[idx]; |
890 | struct hda_cache_head *info_head = cache->buf.list; | ||
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 = &info_head[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 = cache->buf.used - 1; /* the last entry */ |
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"); | ||
2309 | continue; | 2533 | continue; |
2310 | err = set_pcm_default_values(codec, info); | 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]); | ||
2544 | continue; | ||
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,40 @@ 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 array->list + (array->used++ * array->elem_size); | ||
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 | } | ||
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 60468f562400..a73f0eb99283 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -520,6 +520,26 @@ 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 | /* | ||
523 | * Structures | 543 | * Structures |
524 | */ | 544 | */ |
525 | 545 | ||
@@ -536,15 +556,17 @@ typedef u16 hda_nid_t; | |||
536 | /* bus operators */ | 556 | /* bus operators */ |
537 | struct hda_bus_ops { | 557 | struct hda_bus_ops { |
538 | /* send a single command */ | 558 | /* send a single command */ |
539 | int (*command)(struct hda_codec *codec, hda_nid_t nid, int direct, | 559 | int (*command)(struct hda_bus *bus, unsigned int cmd); |
540 | unsigned int verb, unsigned int parm); | ||
541 | /* get a response from the last command */ | 560 | /* get a response from the last command */ |
542 | unsigned int (*get_response)(struct hda_codec *codec); | 561 | unsigned int (*get_response)(struct hda_bus *bus); |
543 | /* free the private data */ | 562 | /* free the private data */ |
544 | void (*private_free)(struct hda_bus *); | 563 | void (*private_free)(struct hda_bus *); |
564 | /* attach a PCM stream */ | ||
565 | int (*attach_pcm)(struct hda_bus *bus, struct hda_codec *codec, | ||
566 | struct hda_pcm *pcm); | ||
545 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 567 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
546 | /* notify power-up/down from codec to controller */ | 568 | /* notify power-up/down from codec to controller */ |
547 | void (*pm_notify)(struct hda_codec *codec); | 569 | void (*pm_notify)(struct hda_bus *bus); |
548 | #endif | 570 | #endif |
549 | }; | 571 | }; |
550 | 572 | ||
@@ -635,10 +657,7 @@ struct hda_amp_info { | |||
635 | 657 | ||
636 | struct hda_cache_rec { | 658 | struct hda_cache_rec { |
637 | u16 hash[64]; /* hash table for index */ | 659 | u16 hash[64]; /* hash table for index */ |
638 | unsigned int num_entries; /* number of assigned entries */ | 660 | 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 | }; | 661 | }; |
643 | 662 | ||
644 | /* PCM callbacks */ | 663 | /* PCM callbacks */ |
@@ -680,7 +699,8 @@ struct hda_pcm { | |||
680 | char *name; | 699 | char *name; |
681 | struct hda_pcm_stream stream[2]; | 700 | struct hda_pcm_stream stream[2]; |
682 | unsigned int pcm_type; /* HDA_PCM_TYPE_XXX */ | 701 | unsigned int pcm_type; /* HDA_PCM_TYPE_XXX */ |
683 | int device; /* assigned device number */ | 702 | int device; /* device number to assign */ |
703 | struct snd_pcm *pcm; /* assigned PCM instance */ | ||
684 | }; | 704 | }; |
685 | 705 | ||
686 | /* codec information */ | 706 | /* codec information */ |
@@ -699,6 +719,8 @@ struct hda_codec { | |||
699 | 719 | ||
700 | /* detected preset */ | 720 | /* detected preset */ |
701 | const struct hda_codec_preset *preset; | 721 | const struct hda_codec_preset *preset; |
722 | const char *name; /* codec name */ | ||
723 | const char *modelname; /* model name for preset */ | ||
702 | 724 | ||
703 | /* set by patch */ | 725 | /* set by patch */ |
704 | struct hda_codec_ops patch_ops; | 726 | struct hda_codec_ops patch_ops; |
@@ -718,6 +740,8 @@ struct hda_codec { | |||
718 | hda_nid_t start_nid; | 740 | hda_nid_t start_nid; |
719 | u32 *wcaps; | 741 | u32 *wcaps; |
720 | 742 | ||
743 | struct snd_array mixers; /* list of assigned mixer elements */ | ||
744 | |||
721 | struct hda_cache_rec amp_cache; /* cache for amp access */ | 745 | struct hda_cache_rec amp_cache; /* cache for amp access */ |
722 | struct hda_cache_rec cmd_cache; /* cache for other commands */ | 746 | struct hda_cache_rec cmd_cache; /* cache for other commands */ |
723 | 747 | ||
@@ -727,7 +751,11 @@ struct hda_codec { | |||
727 | unsigned int spdif_in_enable; /* SPDIF input enable? */ | 751 | unsigned int spdif_in_enable; /* SPDIF input enable? */ |
728 | hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */ | 752 | hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */ |
729 | 753 | ||
754 | #ifdef CONFIG_SND_HDA_HWDEP | ||
730 | struct snd_hwdep *hwdep; /* assigned hwdep device */ | 755 | struct snd_hwdep *hwdep; /* assigned hwdep device */ |
756 | struct snd_array init_verbs; /* additional init verbs */ | ||
757 | struct snd_array hints; /* additional hints */ | ||
758 | #endif | ||
731 | 759 | ||
732 | /* misc flags */ | 760 | /* misc flags */ |
733 | unsigned int spdif_status_reset :1; /* needs to toggle SPDIF for each | 761 | unsigned int spdif_status_reset :1; /* needs to toggle SPDIF for each |
@@ -799,6 +827,7 @@ void snd_hda_codec_resume_cache(struct hda_codec *codec); | |||
799 | * Mixer | 827 | * Mixer |
800 | */ | 828 | */ |
801 | int snd_hda_build_controls(struct hda_bus *bus); | 829 | int snd_hda_build_controls(struct hda_bus *bus); |
830 | int snd_hda_codec_build_controls(struct hda_codec *codec); | ||
802 | 831 | ||
803 | /* | 832 | /* |
804 | * PCM | 833 | * PCM |
@@ -831,6 +860,13 @@ int snd_hda_resume(struct hda_bus *bus); | |||
831 | #endif | 860 | #endif |
832 | 861 | ||
833 | /* | 862 | /* |
863 | * get widget information | ||
864 | */ | ||
865 | const char *snd_hda_get_jack_connectivity(u32 cfg); | ||
866 | const char *snd_hda_get_jack_type(u32 cfg); | ||
867 | const char *snd_hda_get_jack_location(u32 cfg); | ||
868 | |||
869 | /* | ||
834 | * power saving | 870 | * power saving |
835 | */ | 871 | */ |
836 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 872 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
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..653da1d3e4df 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,211 @@ 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 | |||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | /* | ||
149 | * sysfs interface | ||
150 | */ | ||
151 | |||
152 | static int clear_codec(struct hda_codec *codec) | ||
153 | { | ||
154 | snd_hda_codec_reset(codec); | ||
155 | clear_hwdep_elements(codec); | ||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | static int reconfig_codec(struct hda_codec *codec) | ||
160 | { | ||
161 | int err; | ||
162 | |||
163 | snd_printk(KERN_INFO "hda-codec: reconfiguring\n"); | ||
164 | snd_hda_codec_reset(codec); | ||
165 | err = snd_hda_codec_configure(codec); | ||
166 | if (err < 0) | ||
167 | return err; | ||
168 | /* rebuild PCMs */ | ||
169 | err = snd_hda_build_pcms(codec->bus); | ||
170 | if (err < 0) | ||
171 | return err; | ||
172 | /* rebuild mixers */ | ||
173 | err = snd_hda_codec_build_controls(codec); | ||
174 | if (err < 0) | ||
175 | return err; | ||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | /* | ||
180 | * allocate a string at most len chars, and remove the trailing EOL | ||
181 | */ | ||
182 | static char *kstrndup_noeol(const char *src, size_t len) | ||
183 | { | ||
184 | char *s = kstrndup(src, len, GFP_KERNEL); | ||
185 | char *p; | ||
186 | if (!s) | ||
187 | return NULL; | ||
188 | p = strchr(s, '\n'); | ||
189 | if (p) | ||
190 | *p = 0; | ||
191 | return s; | ||
192 | } | ||
193 | |||
194 | #define CODEC_INFO_SHOW(type) \ | ||
195 | static ssize_t type##_show(struct device *dev, \ | ||
196 | struct device_attribute *attr, \ | ||
197 | char *buf) \ | ||
198 | { \ | ||
199 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); \ | ||
200 | struct hda_codec *codec = hwdep->private_data; \ | ||
201 | return sprintf(buf, "0x%x\n", codec->type); \ | ||
202 | } | ||
203 | |||
204 | #define CODEC_INFO_STR_SHOW(type) \ | ||
205 | static ssize_t type##_show(struct device *dev, \ | ||
206 | struct device_attribute *attr, \ | ||
207 | char *buf) \ | ||
208 | { \ | ||
209 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); \ | ||
210 | struct hda_codec *codec = hwdep->private_data; \ | ||
211 | return sprintf(buf, "%s\n", \ | ||
212 | codec->type ? codec->type : ""); \ | ||
213 | } | ||
214 | |||
215 | CODEC_INFO_SHOW(vendor_id); | ||
216 | CODEC_INFO_SHOW(subsystem_id); | ||
217 | CODEC_INFO_SHOW(revision_id); | ||
218 | CODEC_INFO_SHOW(afg); | ||
219 | CODEC_INFO_SHOW(mfg); | ||
220 | CODEC_INFO_STR_SHOW(name); | ||
221 | CODEC_INFO_STR_SHOW(modelname); | ||
222 | |||
223 | #define CODEC_INFO_STORE(type) \ | ||
224 | static ssize_t type##_store(struct device *dev, \ | ||
225 | struct device_attribute *attr, \ | ||
226 | const char *buf, size_t count) \ | ||
227 | { \ | ||
228 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); \ | ||
229 | struct hda_codec *codec = hwdep->private_data; \ | ||
230 | char *after; \ | ||
231 | codec->type = simple_strtoul(buf, &after, 0); \ | ||
232 | return count; \ | ||
233 | } | ||
234 | |||
235 | #define CODEC_INFO_STR_STORE(type) \ | ||
236 | static ssize_t type##_store(struct device *dev, \ | ||
237 | struct device_attribute *attr, \ | ||
238 | const char *buf, size_t count) \ | ||
239 | { \ | ||
240 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); \ | ||
241 | struct hda_codec *codec = hwdep->private_data; \ | ||
242 | char *s = kstrndup_noeol(buf, 64); \ | ||
243 | if (!s) \ | ||
244 | return -ENOMEM; \ | ||
245 | kfree(codec->type); \ | ||
246 | codec->type = s; \ | ||
247 | return count; \ | ||
248 | } | ||
249 | |||
250 | CODEC_INFO_STORE(vendor_id); | ||
251 | CODEC_INFO_STORE(subsystem_id); | ||
252 | CODEC_INFO_STORE(revision_id); | ||
253 | CODEC_INFO_STR_STORE(name); | ||
254 | CODEC_INFO_STR_STORE(modelname); | ||
255 | |||
256 | #define CODEC_ACTION_STORE(type) \ | ||
257 | static ssize_t type##_store(struct device *dev, \ | ||
258 | struct device_attribute *attr, \ | ||
259 | const char *buf, size_t count) \ | ||
260 | { \ | ||
261 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); \ | ||
262 | struct hda_codec *codec = hwdep->private_data; \ | ||
263 | int err = 0; \ | ||
264 | if (*buf) \ | ||
265 | err = type##_codec(codec); \ | ||
266 | return err < 0 ? err : count; \ | ||
267 | } | ||
268 | |||
269 | CODEC_ACTION_STORE(reconfig); | ||
270 | CODEC_ACTION_STORE(clear); | ||
271 | |||
272 | static ssize_t init_verbs_store(struct device *dev, | ||
273 | struct device_attribute *attr, | ||
274 | const char *buf, size_t count) | ||
275 | { | ||
276 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); | ||
277 | struct hda_codec *codec = hwdep->private_data; | ||
278 | char *p; | ||
279 | struct hda_verb verb, *v; | ||
280 | |||
281 | verb.nid = simple_strtoul(buf, &p, 0); | ||
282 | verb.verb = simple_strtoul(p, &p, 0); | ||
283 | verb.param = simple_strtoul(p, &p, 0); | ||
284 | if (!verb.nid || !verb.verb || !verb.param) | ||
285 | return -EINVAL; | ||
286 | v = snd_array_new(&codec->init_verbs); | ||
287 | if (!v) | ||
288 | return -ENOMEM; | ||
289 | *v = verb; | ||
290 | return count; | ||
291 | } | ||
292 | |||
293 | static ssize_t hints_store(struct device *dev, | ||
294 | struct device_attribute *attr, | ||
295 | const char *buf, size_t count) | ||
296 | { | ||
297 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); | ||
298 | struct hda_codec *codec = hwdep->private_data; | ||
299 | char *p; | ||
300 | char **hint; | ||
301 | |||
302 | if (!*buf || isspace(*buf) || *buf == '#' || *buf == '\n') | ||
303 | return count; | ||
304 | p = kstrndup_noeol(buf, 1024); | ||
305 | if (!p) | ||
306 | return -ENOMEM; | ||
307 | hint = snd_array_new(&codec->hints); | ||
308 | if (!hint) { | ||
309 | kfree(p); | ||
310 | return -ENOMEM; | ||
311 | } | ||
312 | *hint = p; | ||
313 | return count; | ||
314 | } | ||
315 | |||
316 | #define CODEC_ATTR_RW(type) \ | ||
317 | __ATTR(type, 0644, type##_show, type##_store) | ||
318 | #define CODEC_ATTR_RO(type) \ | ||
319 | __ATTR_RO(type) | ||
320 | #define CODEC_ATTR_WO(type) \ | ||
321 | __ATTR(type, 0200, NULL, type##_store) | ||
322 | |||
323 | static struct device_attribute codec_attrs[] = { | ||
324 | CODEC_ATTR_RW(vendor_id), | ||
325 | CODEC_ATTR_RW(subsystem_id), | ||
326 | CODEC_ATTR_RW(revision_id), | ||
327 | CODEC_ATTR_RO(afg), | ||
328 | CODEC_ATTR_RO(mfg), | ||
329 | CODEC_ATTR_RW(name), | ||
330 | CODEC_ATTR_RW(modelname), | ||
331 | CODEC_ATTR_WO(init_verbs), | ||
332 | CODEC_ATTR_WO(hints), | ||
333 | CODEC_ATTR_WO(reconfig), | ||
334 | CODEC_ATTR_WO(clear), | ||
335 | }; | ||
336 | |||
337 | /* | ||
338 | * create sysfs files on hwdep directory | ||
339 | */ | ||
340 | int snd_hda_hwdep_add_sysfs(struct hda_codec *codec) | ||
341 | { | ||
342 | struct snd_hwdep *hwdep = codec->hwdep; | ||
343 | int i; | ||
344 | |||
345 | for (i = 0; i < ARRAY_SIZE(codec_attrs); i++) | ||
346 | snd_add_device_sysfs_file(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, | ||
347 | hwdep->device, &codec_attrs[i]); | ||
120 | return 0; | 348 | return 0; |
121 | } | 349 | } |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index c04ac38e2b2e..f3c447cf67f8 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -392,6 +392,7 @@ struct azx { | |||
392 | unsigned int msi :1; | 392 | unsigned int msi :1; |
393 | unsigned int irq_pending_warned :1; | 393 | unsigned int irq_pending_warned :1; |
394 | unsigned int via_dmapos_patch :1; /* enable DMA-position fix for VIA */ | 394 | unsigned int via_dmapos_patch :1; /* enable DMA-position fix for VIA */ |
395 | unsigned int probing :1; /* codec probing phase */ | ||
395 | 396 | ||
396 | /* for debugging */ | 397 | /* for debugging */ |
397 | unsigned int last_cmd; /* last issued command (to sync) */ | 398 | unsigned int last_cmd; /* last issued command (to sync) */ |
@@ -527,9 +528,9 @@ static void azx_free_cmd_io(struct azx *chip) | |||
527 | } | 528 | } |
528 | 529 | ||
529 | /* send a command */ | 530 | /* send a command */ |
530 | static int azx_corb_send_cmd(struct hda_codec *codec, u32 val) | 531 | static int azx_corb_send_cmd(struct hda_bus *bus, u32 val) |
531 | { | 532 | { |
532 | struct azx *chip = codec->bus->private_data; | 533 | struct azx *chip = bus->private_data; |
533 | unsigned int wp; | 534 | unsigned int wp; |
534 | 535 | ||
535 | /* add command to corb */ | 536 | /* add command to corb */ |
@@ -577,9 +578,9 @@ static void azx_update_rirb(struct azx *chip) | |||
577 | } | 578 | } |
578 | 579 | ||
579 | /* receive a response */ | 580 | /* receive a response */ |
580 | static unsigned int azx_rirb_get_response(struct hda_codec *codec) | 581 | static unsigned int azx_rirb_get_response(struct hda_bus *bus) |
581 | { | 582 | { |
582 | struct azx *chip = codec->bus->private_data; | 583 | struct azx *chip = bus->private_data; |
583 | unsigned long timeout; | 584 | unsigned long timeout; |
584 | 585 | ||
585 | again: | 586 | again: |
@@ -596,7 +597,7 @@ static unsigned int azx_rirb_get_response(struct hda_codec *codec) | |||
596 | } | 597 | } |
597 | if (time_after(jiffies, timeout)) | 598 | if (time_after(jiffies, timeout)) |
598 | break; | 599 | break; |
599 | if (codec->bus->needs_damn_long_delay) | 600 | if (bus->needs_damn_long_delay) |
600 | msleep(2); /* temporary workaround */ | 601 | msleep(2); /* temporary workaround */ |
601 | else { | 602 | else { |
602 | udelay(10); | 603 | udelay(10); |
@@ -624,6 +625,14 @@ static unsigned int azx_rirb_get_response(struct hda_codec *codec) | |||
624 | goto again; | 625 | goto again; |
625 | } | 626 | } |
626 | 627 | ||
628 | if (chip->probing) { | ||
629 | /* If this critical timeout happens during the codec probing | ||
630 | * phase, this is likely an access to a non-existing codec | ||
631 | * slot. Better to return an error and reset the system. | ||
632 | */ | ||
633 | return -1; | ||
634 | } | ||
635 | |||
627 | snd_printk(KERN_ERR "hda_intel: azx_get_response timeout, " | 636 | snd_printk(KERN_ERR "hda_intel: azx_get_response timeout, " |
628 | "switching to single_cmd mode: last cmd=0x%08x\n", | 637 | "switching to single_cmd mode: last cmd=0x%08x\n", |
629 | chip->last_cmd); | 638 | chip->last_cmd); |
@@ -646,9 +655,9 @@ static unsigned int azx_rirb_get_response(struct hda_codec *codec) | |||
646 | */ | 655 | */ |
647 | 656 | ||
648 | /* send a command */ | 657 | /* send a command */ |
649 | static int azx_single_send_cmd(struct hda_codec *codec, u32 val) | 658 | static int azx_single_send_cmd(struct hda_bus *bus, u32 val) |
650 | { | 659 | { |
651 | struct azx *chip = codec->bus->private_data; | 660 | struct azx *chip = bus->private_data; |
652 | int timeout = 50; | 661 | int timeout = 50; |
653 | 662 | ||
654 | while (timeout--) { | 663 | while (timeout--) { |
@@ -671,9 +680,9 @@ static int azx_single_send_cmd(struct hda_codec *codec, u32 val) | |||
671 | } | 680 | } |
672 | 681 | ||
673 | /* receive a response */ | 682 | /* receive a response */ |
674 | static unsigned int azx_single_get_response(struct hda_codec *codec) | 683 | static unsigned int azx_single_get_response(struct hda_bus *bus) |
675 | { | 684 | { |
676 | struct azx *chip = codec->bus->private_data; | 685 | struct azx *chip = bus->private_data; |
677 | int timeout = 50; | 686 | int timeout = 50; |
678 | 687 | ||
679 | while (timeout--) { | 688 | while (timeout--) { |
@@ -696,38 +705,29 @@ static unsigned int azx_single_get_response(struct hda_codec *codec) | |||
696 | */ | 705 | */ |
697 | 706 | ||
698 | /* send a command */ | 707 | /* send a command */ |
699 | static int azx_send_cmd(struct hda_codec *codec, hda_nid_t nid, | 708 | static int azx_send_cmd(struct hda_bus *bus, unsigned int val) |
700 | int direct, unsigned int verb, | ||
701 | unsigned int para) | ||
702 | { | 709 | { |
703 | struct azx *chip = codec->bus->private_data; | 710 | 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 | 711 | ||
712 | chip->last_cmd = val; | ||
713 | if (chip->single_cmd) | 713 | if (chip->single_cmd) |
714 | return azx_single_send_cmd(codec, val); | 714 | return azx_single_send_cmd(bus, val); |
715 | else | 715 | else |
716 | return azx_corb_send_cmd(codec, val); | 716 | return azx_corb_send_cmd(bus, val); |
717 | } | 717 | } |
718 | 718 | ||
719 | /* get a response */ | 719 | /* get a response */ |
720 | static unsigned int azx_get_response(struct hda_codec *codec) | 720 | static unsigned int azx_get_response(struct hda_bus *bus) |
721 | { | 721 | { |
722 | struct azx *chip = codec->bus->private_data; | 722 | struct azx *chip = bus->private_data; |
723 | if (chip->single_cmd) | 723 | if (chip->single_cmd) |
724 | return azx_single_get_response(codec); | 724 | return azx_single_get_response(bus); |
725 | else | 725 | else |
726 | return azx_rirb_get_response(codec); | 726 | return azx_rirb_get_response(bus); |
727 | } | 727 | } |
728 | 728 | ||
729 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 729 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
730 | static void azx_power_notify(struct hda_codec *codec); | 730 | static void azx_power_notify(struct hda_bus *bus); |
731 | #endif | 731 | #endif |
732 | 732 | ||
733 | /* reset codec link */ | 733 | /* reset codec link */ |
@@ -1184,6 +1184,28 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) | |||
1184 | return 0; | 1184 | return 0; |
1185 | } | 1185 | } |
1186 | 1186 | ||
1187 | /* | ||
1188 | * Probe the given codec address | ||
1189 | */ | ||
1190 | static int probe_codec(struct azx *chip, int addr) | ||
1191 | { | ||
1192 | unsigned int cmd = (addr << 28) | (AC_NODE_ROOT << 20) | | ||
1193 | (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID; | ||
1194 | unsigned int res; | ||
1195 | |||
1196 | chip->probing = 1; | ||
1197 | azx_send_cmd(chip->bus, cmd); | ||
1198 | res = azx_get_response(chip->bus); | ||
1199 | chip->probing = 0; | ||
1200 | if (res == -1) | ||
1201 | return -EIO; | ||
1202 | snd_printdd("hda_intel: codec #%d probed OK\n", addr); | ||
1203 | return 0; | ||
1204 | } | ||
1205 | |||
1206 | static int azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec, | ||
1207 | struct hda_pcm *cpcm); | ||
1208 | static void azx_stop_chip(struct azx *chip); | ||
1187 | 1209 | ||
1188 | /* | 1210 | /* |
1189 | * Codec initialization | 1211 | * Codec initialization |
@@ -1194,21 +1216,12 @@ static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] __devinitdata = { | |||
1194 | [AZX_DRIVER_TERA] = 1, | 1216 | [AZX_DRIVER_TERA] = 1, |
1195 | }; | 1217 | }; |
1196 | 1218 | ||
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, | 1219 | static int __devinit azx_codec_create(struct azx *chip, const char *model, |
1207 | unsigned int codec_probe_mask) | 1220 | unsigned int codec_probe_mask) |
1208 | { | 1221 | { |
1209 | struct hda_bus_template bus_temp; | 1222 | struct hda_bus_template bus_temp; |
1210 | int c, codecs, audio_codecs, err; | 1223 | int c, codecs, err; |
1211 | int def_slots, max_slots; | 1224 | int max_slots; |
1212 | 1225 | ||
1213 | memset(&bus_temp, 0, sizeof(bus_temp)); | 1226 | memset(&bus_temp, 0, sizeof(bus_temp)); |
1214 | bus_temp.private_data = chip; | 1227 | bus_temp.private_data = chip; |
@@ -1216,6 +1229,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model, | |||
1216 | bus_temp.pci = chip->pci; | 1229 | bus_temp.pci = chip->pci; |
1217 | bus_temp.ops.command = azx_send_cmd; | 1230 | bus_temp.ops.command = azx_send_cmd; |
1218 | bus_temp.ops.get_response = azx_get_response; | 1231 | bus_temp.ops.get_response = azx_get_response; |
1232 | bus_temp.ops.attach_pcm = azx_attach_pcm_stream; | ||
1219 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 1233 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
1220 | bus_temp.ops.pm_notify = azx_power_notify; | 1234 | bus_temp.ops.pm_notify = azx_power_notify; |
1221 | #endif | 1235 | #endif |
@@ -1227,33 +1241,43 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model, | |||
1227 | if (chip->driver_type == AZX_DRIVER_NVIDIA) | 1241 | if (chip->driver_type == AZX_DRIVER_NVIDIA) |
1228 | chip->bus->needs_damn_long_delay = 1; | 1242 | chip->bus->needs_damn_long_delay = 1; |
1229 | 1243 | ||
1230 | codecs = audio_codecs = 0; | 1244 | codecs = 0; |
1231 | max_slots = azx_max_codecs[chip->driver_type]; | 1245 | max_slots = azx_max_codecs[chip->driver_type]; |
1232 | if (!max_slots) | 1246 | if (!max_slots) |
1233 | max_slots = AZX_MAX_CODECS; | 1247 | max_slots = AZX_MAX_CODECS; |
1234 | def_slots = azx_default_codecs[chip->driver_type]; | 1248 | |
1235 | if (!def_slots) | 1249 | /* First try to probe all given codec slots */ |
1236 | def_slots = max_slots; | 1250 | for (c = 0; c < max_slots; c++) { |
1237 | for (c = 0; c < def_slots; c++) { | 1251 | if ((chip->codec_mask & (1 << c)) & codec_probe_mask) { |
1252 | if (probe_codec(chip, c) < 0) { | ||
1253 | /* Some BIOSen give you wrong codec addresses | ||
1254 | * that don't exist | ||
1255 | */ | ||
1256 | snd_printk(KERN_WARNING | ||
1257 | "hda_intel: Codec #%d probe error; " | ||
1258 | "disabling it...\n", c); | ||
1259 | chip->codec_mask &= ~(1 << c); | ||
1260 | /* More badly, accessing to a non-existing | ||
1261 | * codec often screws up the controller chip, | ||
1262 | * and distrubs the further communications. | ||
1263 | * Thus if an error occurs during probing, | ||
1264 | * better to reset the controller chip to | ||
1265 | * get back to the sanity state. | ||
1266 | */ | ||
1267 | azx_stop_chip(chip); | ||
1268 | azx_init_chip(chip); | ||
1269 | } | ||
1270 | } | ||
1271 | } | ||
1272 | |||
1273 | /* Then create codec instances */ | ||
1274 | for (c = 0; c < max_slots; c++) { | ||
1238 | if ((chip->codec_mask & (1 << c)) & codec_probe_mask) { | 1275 | if ((chip->codec_mask & (1 << c)) & codec_probe_mask) { |
1239 | struct hda_codec *codec; | 1276 | struct hda_codec *codec; |
1240 | err = snd_hda_codec_new(chip->bus, c, &codec); | 1277 | err = snd_hda_codec_new(chip->bus, c, &codec); |
1241 | if (err < 0) | 1278 | if (err < 0) |
1242 | continue; | 1279 | continue; |
1243 | codecs++; | 1280 | 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 | } | 1281 | } |
1258 | } | 1282 | } |
1259 | if (!codecs) { | 1283 | if (!codecs) { |
@@ -1722,111 +1746,59 @@ static struct snd_pcm_ops azx_pcm_ops = { | |||
1722 | 1746 | ||
1723 | static void azx_pcm_free(struct snd_pcm *pcm) | 1747 | static void azx_pcm_free(struct snd_pcm *pcm) |
1724 | { | 1748 | { |
1725 | kfree(pcm->private_data); | 1749 | struct azx_pcm *apcm = pcm->private_data; |
1750 | if (apcm) { | ||
1751 | apcm->chip->pcm[pcm->device] = NULL; | ||
1752 | kfree(apcm); | ||
1753 | } | ||
1726 | } | 1754 | } |
1727 | 1755 | ||
1728 | static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec, | 1756 | static int |
1729 | struct hda_pcm *cpcm) | 1757 | azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec, |
1758 | struct hda_pcm *cpcm) | ||
1730 | { | 1759 | { |
1731 | int err; | 1760 | struct azx *chip = bus->private_data; |
1732 | struct snd_pcm *pcm; | 1761 | struct snd_pcm *pcm; |
1733 | struct azx_pcm *apcm; | 1762 | struct azx_pcm *apcm; |
1763 | int pcm_dev = cpcm->device; | ||
1764 | int s, err; | ||
1734 | 1765 | ||
1735 | /* if no substreams are defined for both playback and capture, | 1766 | if (pcm_dev >= AZX_MAX_PCMS) { |
1736 | * it's just a placeholder. ignore it. | 1767 | snd_printk(KERN_ERR SFX "Invalid PCM device number %d\n", |
1737 | */ | 1768 | 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; | 1769 | return -EINVAL; |
1743 | 1770 | } | |
1744 | err = snd_pcm_new(chip->card, cpcm->name, cpcm->device, | 1771 | if (chip->pcm[pcm_dev]) { |
1745 | cpcm->stream[0].substreams, | 1772 | snd_printk(KERN_ERR SFX "PCM %d already exists\n", pcm_dev); |
1746 | cpcm->stream[1].substreams, | 1773 | return -EBUSY; |
1774 | } | ||
1775 | err = snd_pcm_new(chip->card, cpcm->name, pcm_dev, | ||
1776 | cpcm->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams, | ||
1777 | cpcm->stream[SNDRV_PCM_STREAM_CAPTURE].substreams, | ||
1747 | &pcm); | 1778 | &pcm); |
1748 | if (err < 0) | 1779 | if (err < 0) |
1749 | return err; | 1780 | return err; |
1750 | strcpy(pcm->name, cpcm->name); | 1781 | strcpy(pcm->name, cpcm->name); |
1751 | apcm = kmalloc(sizeof(*apcm), GFP_KERNEL); | 1782 | apcm = kzalloc(sizeof(*apcm), GFP_KERNEL); |
1752 | if (apcm == NULL) | 1783 | if (apcm == NULL) |
1753 | return -ENOMEM; | 1784 | return -ENOMEM; |
1754 | apcm->chip = chip; | 1785 | apcm->chip = chip; |
1755 | apcm->codec = codec; | 1786 | apcm->codec = codec; |
1756 | apcm->hinfo[0] = &cpcm->stream[0]; | ||
1757 | apcm->hinfo[1] = &cpcm->stream[1]; | ||
1758 | pcm->private_data = apcm; | 1787 | pcm->private_data = apcm; |
1759 | pcm->private_free = azx_pcm_free; | 1788 | pcm->private_free = azx_pcm_free; |
1760 | if (cpcm->stream[0].substreams) | 1789 | if (cpcm->pcm_type == HDA_PCM_TYPE_MODEM) |
1761 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &azx_pcm_ops); | 1790 | pcm->dev_class = SNDRV_PCM_CLASS_MODEM; |
1762 | if (cpcm->stream[1].substreams) | 1791 | chip->pcm[pcm_dev] = pcm; |
1763 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &azx_pcm_ops); | 1792 | cpcm->pcm = pcm; |
1793 | for (s = 0; s < 2; s++) { | ||
1794 | apcm->hinfo[s] = &cpcm->stream[s]; | ||
1795 | if (cpcm->stream[s].substreams) | ||
1796 | snd_pcm_set_ops(pcm, s, &azx_pcm_ops); | ||
1797 | } | ||
1798 | /* buffer pre-allocation */ | ||
1764 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, | 1799 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, |
1765 | snd_dma_pci_data(chip->pci), | 1800 | snd_dma_pci_data(chip->pci), |
1766 | 1024 * 64, 32 * 1024 * 1024); | 1801 | 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; | 1802 | return 0; |
1831 | } | 1803 | } |
1832 | 1804 | ||
@@ -1903,13 +1875,13 @@ static void azx_stop_chip(struct azx *chip) | |||
1903 | 1875 | ||
1904 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 1876 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
1905 | /* power-up/down the controller */ | 1877 | /* power-up/down the controller */ |
1906 | static void azx_power_notify(struct hda_codec *codec) | 1878 | static void azx_power_notify(struct hda_bus *bus) |
1907 | { | 1879 | { |
1908 | struct azx *chip = codec->bus->private_data; | 1880 | struct azx *chip = bus->private_data; |
1909 | struct hda_codec *c; | 1881 | struct hda_codec *c; |
1910 | int power_on = 0; | 1882 | int power_on = 0; |
1911 | 1883 | ||
1912 | list_for_each_entry(c, &codec->bus->codec_list, list) { | 1884 | list_for_each_entry(c, &bus->codec_list, list) { |
1913 | if (c->power_on) { | 1885 | if (c->power_on) { |
1914 | power_on = 1; | 1886 | power_on = 1; |
1915 | break; | 1887 | break; |
@@ -2352,7 +2324,7 @@ static int __devinit azx_probe(struct pci_dev *pci, | |||
2352 | } | 2324 | } |
2353 | 2325 | ||
2354 | /* create PCM streams */ | 2326 | /* create PCM streams */ |
2355 | err = azx_pcm_create(chip); | 2327 | err = snd_hda_build_pcms(chip->bus); |
2356 | if (err < 0) { | 2328 | if (err < 0) { |
2357 | snd_card_free(card); | 2329 | snd_card_free(card); |
2358 | return err; | 2330 | return err; |
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 7957fefda730..aac569b05599 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 |
@@ -364,17 +366,17 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
364 | /* amp values */ | 366 | /* amp values */ |
365 | #define AMP_IN_MUTE(idx) (0x7080 | ((idx)<<8)) | 367 | #define AMP_IN_MUTE(idx) (0x7080 | ((idx)<<8)) |
366 | #define AMP_IN_UNMUTE(idx) (0x7000 | ((idx)<<8)) | 368 | #define AMP_IN_UNMUTE(idx) (0x7000 | ((idx)<<8)) |
367 | #define AMP_OUT_MUTE 0xb080 | 369 | #define AMP_OUT_MUTE 0xb080 |
368 | #define AMP_OUT_UNMUTE 0xb000 | 370 | #define AMP_OUT_UNMUTE 0xb000 |
369 | #define AMP_OUT_ZERO 0xb000 | 371 | #define AMP_OUT_ZERO 0xb000 |
370 | /* pinctl values */ | 372 | /* pinctl values */ |
371 | #define PIN_IN (AC_PINCTL_IN_EN) | 373 | #define PIN_IN (AC_PINCTL_IN_EN) |
372 | #define PIN_VREFHIZ (AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ) | 374 | #define PIN_VREFHIZ (AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ) |
373 | #define PIN_VREF50 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_50) | 375 | #define PIN_VREF50 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_50) |
374 | #define PIN_VREFGRD (AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD) | 376 | #define PIN_VREFGRD (AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD) |
375 | #define PIN_VREF80 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_80) | 377 | #define PIN_VREF80 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_80) |
376 | #define PIN_VREF100 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_100) | 378 | #define PIN_VREF100 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_100) |
377 | #define PIN_OUT (AC_PINCTL_OUT_EN) | 379 | #define PIN_OUT (AC_PINCTL_OUT_EN) |
378 | #define PIN_HP (AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN) | 380 | #define PIN_HP (AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN) |
379 | #define PIN_HP_AMP (AC_PINCTL_HP_EN) | 381 | #define PIN_HP_AMP (AC_PINCTL_HP_EN) |
380 | 382 | ||
@@ -393,10 +395,18 @@ 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, | 395 | int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, |
394 | unsigned int caps); | 396 | unsigned int caps); |
395 | 397 | ||
398 | int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl); | ||
399 | void snd_hda_ctls_clear(struct hda_codec *codec); | ||
400 | |||
396 | /* | 401 | /* |
397 | * hwdep interface | 402 | * hwdep interface |
398 | */ | 403 | */ |
404 | #ifdef CONFIG_SND_HDA_HWDEP | ||
399 | int snd_hda_create_hwdep(struct hda_codec *codec); | 405 | int snd_hda_create_hwdep(struct hda_codec *codec); |
406 | int snd_hda_hwdep_add_sysfs(struct hda_codec *codec); | ||
407 | #else | ||
408 | static inline int snd_hda_create_hwdep(struct hda_codec *codec) { return 0; } | ||
409 | #endif | ||
400 | 410 | ||
401 | /* | 411 | /* |
402 | * power-management | 412 | * power-management |
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..64b6a38fa963 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c | |||
@@ -145,32 +145,6 @@ static void print_pcm_caps(struct snd_info_buffer *buffer, | |||
145 | print_pcm_formats(buffer, stream); | 145 | print_pcm_formats(buffer, stream); |
146 | } | 146 | } |
147 | 147 | ||
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) | 148 | static const char *get_jack_connection(u32 cfg) |
175 | { | 149 | { |
176 | static char *names[16] = { | 150 | static char *names[16] = { |
@@ -206,13 +180,6 @@ static void print_pin_caps(struct snd_info_buffer *buffer, | |||
206 | int *supports_vref) | 180 | int *supports_vref) |
207 | { | 181 | { |
208 | static char *jack_conns[4] = { "Jack", "N/A", "Fixed", "Both" }; | 182 | 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; | 183 | unsigned int caps, val; |
217 | 184 | ||
218 | caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); | 185 | caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); |
@@ -274,9 +241,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); | 241 | 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, | 242 | 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], | 243 | jack_conns[(caps & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT], |
277 | jack_types[(caps & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT], | 244 | snd_hda_get_jack_type(caps), |
278 | jack_locations[(caps >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3], | 245 | snd_hda_get_jack_connectivity(caps), |
279 | get_jack_location(caps)); | 246 | snd_hda_get_jack_location(caps)); |
280 | snd_iprintf(buffer, " Conn = %s, Color = %s\n", | 247 | snd_iprintf(buffer, " Conn = %s, Color = %s\n", |
281 | get_jack_connection(caps), | 248 | get_jack_connection(caps), |
282 | get_jack_color(caps)); | 249 | get_jack_color(caps)); |
@@ -513,12 +480,11 @@ static void print_codec_info(struct snd_info_entry *entry, | |||
513 | struct snd_info_buffer *buffer) | 480 | struct snd_info_buffer *buffer) |
514 | { | 481 | { |
515 | struct hda_codec *codec = entry->private_data; | 482 | struct hda_codec *codec = entry->private_data; |
516 | char buf[32]; | ||
517 | hda_nid_t nid; | 483 | hda_nid_t nid; |
518 | int i, nodes; | 484 | int i, nodes; |
519 | 485 | ||
520 | snd_hda_get_codec_name(codec, buf, sizeof(buf)); | 486 | snd_iprintf(buffer, "Codec: %s\n", |
521 | snd_iprintf(buffer, "Codec: %s\n", buf); | 487 | codec->name ? codec->name : "Not Set"); |
522 | snd_iprintf(buffer, "Address: %d\n", codec->addr); | 488 | snd_iprintf(buffer, "Address: %d\n", codec->addr); |
523 | snd_iprintf(buffer, "Vendor Id: 0x%x\n", codec->vendor_id); | 489 | snd_iprintf(buffer, "Vendor Id: 0x%x\n", codec->vendor_id); |
524 | snd_iprintf(buffer, "Subsystem Id: 0x%x\n", codec->subsystem_id); | 490 | 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 d3fd432cb3ea..d0d66f341cda 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 | ||
@@ -2452,9 +2465,6 @@ static struct hda_amp_list ad1988_loopbacks[] = { | |||
2452 | * Automatic parse of I/O pins from the BIOS configuration | 2465 | * Automatic parse of I/O pins from the BIOS configuration |
2453 | */ | 2466 | */ |
2454 | 2467 | ||
2455 | #define NUM_CONTROL_ALLOC 32 | ||
2456 | #define NUM_VERB_ALLOC 32 | ||
2457 | |||
2458 | enum { | 2468 | enum { |
2459 | AD_CTL_WIDGET_VOL, | 2469 | AD_CTL_WIDGET_VOL, |
2460 | AD_CTL_WIDGET_MUTE, | 2470 | AD_CTL_WIDGET_MUTE, |
@@ -2472,27 +2482,15 @@ static int add_control(struct ad198x_spec *spec, int type, const char *name, | |||
2472 | { | 2482 | { |
2473 | struct snd_kcontrol_new *knew; | 2483 | struct snd_kcontrol_new *knew; |
2474 | 2484 | ||
2475 | if (spec->num_kctl_used >= spec->num_kctl_alloc) { | 2485 | snd_array_init(&spec->kctls, sizeof(*knew), 32); |
2476 | int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC; | 2486 | knew = snd_array_new(&spec->kctls); |
2477 | 2487 | if (!knew) | |
2478 | knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */ | 2488 | 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]; | 2489 | *knew = ad1988_control_templates[type]; |
2491 | knew->name = kstrdup(name, GFP_KERNEL); | 2490 | knew->name = kstrdup(name, GFP_KERNEL); |
2492 | if (! knew->name) | 2491 | if (! knew->name) |
2493 | return -ENOMEM; | 2492 | return -ENOMEM; |
2494 | knew->private_value = val; | 2493 | knew->private_value = val; |
2495 | spec->num_kctl_used++; | ||
2496 | return 0; | 2494 | return 0; |
2497 | } | 2495 | } |
2498 | 2496 | ||
@@ -2846,8 +2844,8 @@ static int ad1988_parse_auto_config(struct hda_codec *codec) | |||
2846 | if (spec->autocfg.dig_in_pin) | 2844 | if (spec->autocfg.dig_in_pin) |
2847 | spec->dig_in_nid = AD1988_SPDIF_IN; | 2845 | spec->dig_in_nid = AD1988_SPDIF_IN; |
2848 | 2846 | ||
2849 | if (spec->kctl_alloc) | 2847 | if (spec->kctls.list) |
2850 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 2848 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
2851 | 2849 | ||
2852 | spec->init_verbs[spec->num_init_verbs++] = ad1988_6stack_init_verbs; | 2850 | spec->init_verbs[spec->num_init_verbs++] = ad1988_6stack_init_verbs; |
2853 | 2851 | ||
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..3beaf9c1090c --- /dev/null +++ b/sound/pci/hda/patch_intelhdmi.c | |||
@@ -0,0 +1,928 @@ | |||
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 <asm/unaligned.h> | ||
34 | #include "hda_codec.h" | ||
35 | #include "hda_local.h" | ||
36 | #include "hda_patch.h" | ||
37 | |||
38 | #define CVT_NID 0x02 /* audio converter */ | ||
39 | #define PIN_NID 0x03 /* HDMI output pin */ | ||
40 | |||
41 | #define INTEL_HDMI_EVENT_TAG 0x08 | ||
42 | |||
43 | /* | ||
44 | * CEA Short Audio Descriptor data | ||
45 | */ | ||
46 | struct cea_sad { | ||
47 | int channels; | ||
48 | int format; /* (format == 0) indicates invalid SAD */ | ||
49 | int rates; | ||
50 | int sample_bits; /* for LPCM */ | ||
51 | int max_bitrate; /* for AC3...ATRAC */ | ||
52 | int profile; /* for WMAPRO */ | ||
53 | }; | ||
54 | |||
55 | #define ELD_FIXED_BYTES 20 | ||
56 | #define ELD_MAX_MNL 16 | ||
57 | #define ELD_MAX_SAD 16 | ||
58 | |||
59 | /* | ||
60 | * ELD: EDID Like Data | ||
61 | */ | ||
62 | struct sink_eld { | ||
63 | int eld_size; | ||
64 | int baseline_len; | ||
65 | int eld_ver; /* (eld_ver == 0) indicates invalid ELD */ | ||
66 | int cea_edid_ver; | ||
67 | char monitor_name[ELD_MAX_MNL + 1]; | ||
68 | int manufacture_id; | ||
69 | int product_id; | ||
70 | u64 port_id; | ||
71 | int support_hdcp; | ||
72 | int support_ai; | ||
73 | int conn_type; | ||
74 | int aud_synch_delay; | ||
75 | int spk_alloc; | ||
76 | int sad_count; | ||
77 | struct cea_sad sad[ELD_MAX_SAD]; | ||
78 | }; | ||
79 | |||
80 | struct intel_hdmi_spec { | ||
81 | struct hda_multi_out multiout; | ||
82 | struct hda_pcm pcm_rec; | ||
83 | struct sink_eld sink; | ||
84 | }; | ||
85 | |||
86 | static struct hda_verb pinout_enable_verb[] = { | ||
87 | {PIN_NID, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
88 | {} /* terminator */ | ||
89 | }; | ||
90 | |||
91 | static struct hda_verb pinout_disable_verb[] = { | ||
92 | {PIN_NID, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00}, | ||
93 | {} | ||
94 | }; | ||
95 | |||
96 | static struct hda_verb unsolicited_response_verb[] = { | ||
97 | {PIN_NID, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | | ||
98 | INTEL_HDMI_EVENT_TAG}, | ||
99 | {} | ||
100 | }; | ||
101 | |||
102 | static struct hda_verb def_chan_map[] = { | ||
103 | {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x00}, | ||
104 | {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x11}, | ||
105 | {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x22}, | ||
106 | {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x33}, | ||
107 | {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x44}, | ||
108 | {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x55}, | ||
109 | {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x66}, | ||
110 | {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x77}, | ||
111 | {} | ||
112 | }; | ||
113 | |||
114 | |||
115 | struct hdmi_audio_infoframe { | ||
116 | u8 type; /* 0x84 */ | ||
117 | u8 ver; /* 0x01 */ | ||
118 | u8 len; /* 0x0a */ | ||
119 | |||
120 | u8 checksum; /* PB0 */ | ||
121 | u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */ | ||
122 | u8 SS01_SF24; | ||
123 | u8 CXT04; | ||
124 | u8 CA; | ||
125 | u8 LFEPBL01_LSV36_DM_INH7; | ||
126 | u8 reserved[5]; /* PB6 - PB10 */ | ||
127 | }; | ||
128 | |||
129 | /* | ||
130 | * SS1:SS0 index => sample size | ||
131 | */ | ||
132 | static int cea_sample_sizes[4] = { | ||
133 | 0, /* 0: Refer to Stream Header */ | ||
134 | AC_SUPPCM_BITS_16, /* 1: 16 bits */ | ||
135 | AC_SUPPCM_BITS_20, /* 2: 20 bits */ | ||
136 | AC_SUPPCM_BITS_24, /* 3: 24 bits */ | ||
137 | }; | ||
138 | |||
139 | /* | ||
140 | * SF2:SF1:SF0 index => sampling frequency | ||
141 | */ | ||
142 | static int cea_sampling_frequencies[8] = { | ||
143 | 0, /* 0: Refer to Stream Header */ | ||
144 | SNDRV_PCM_RATE_32000, /* 1: 32000Hz */ | ||
145 | SNDRV_PCM_RATE_44100, /* 2: 44100Hz */ | ||
146 | SNDRV_PCM_RATE_48000, /* 3: 48000Hz */ | ||
147 | SNDRV_PCM_RATE_88200, /* 4: 88200Hz */ | ||
148 | SNDRV_PCM_RATE_96000, /* 5: 96000Hz */ | ||
149 | SNDRV_PCM_RATE_176400, /* 6: 176400Hz */ | ||
150 | SNDRV_PCM_RATE_192000, /* 7: 192000Hz */ | ||
151 | }; | ||
152 | |||
153 | enum eld_versions { | ||
154 | ELD_VER_CEA_861D = 2, | ||
155 | ELD_VER_PARTIAL = 31, | ||
156 | }; | ||
157 | |||
158 | static char *eld_versoin_names[32] = { | ||
159 | "0-reserved", | ||
160 | "1-reserved", | ||
161 | "CEA-861D or below", | ||
162 | "3-reserved", | ||
163 | [4 ... 30] = "reserved", | ||
164 | [31] = "partial" | ||
165 | }; | ||
166 | |||
167 | enum cea_edid_versions { | ||
168 | CEA_EDID_VER_NONE = 0, | ||
169 | CEA_EDID_VER_CEA861 = 1, | ||
170 | CEA_EDID_VER_CEA861A = 2, | ||
171 | CEA_EDID_VER_CEA861BCD = 3, | ||
172 | CEA_EDID_VER_RESERVED = 4, | ||
173 | }; | ||
174 | |||
175 | static char *cea_edid_version_names[8] = { | ||
176 | "no CEA EDID Timing Extension block present", | ||
177 | "CEA-861", | ||
178 | "CEA-861-A", | ||
179 | "CEA-861-B, C or D", | ||
180 | "4-reserved", | ||
181 | [5 ... 7] = "reserved" | ||
182 | }; | ||
183 | |||
184 | /* | ||
185 | * CEA Speaker Allocation data block bits | ||
186 | */ | ||
187 | #define CEA_SA_FLR (0 << 0) | ||
188 | #define CEA_SA_LFE (1 << 1) | ||
189 | #define CEA_SA_FC (1 << 2) | ||
190 | #define CEA_SA_RLR (1 << 3) | ||
191 | #define CEA_SA_RC (1 << 4) | ||
192 | #define CEA_SA_FLRC (1 << 5) | ||
193 | #define CEA_SA_RLRC (1 << 6) | ||
194 | /* the following are not defined in ELD yet */ | ||
195 | #define CEA_SA_FLRW (1 << 7) | ||
196 | #define CEA_SA_FLRH (1 << 8) | ||
197 | #define CEA_SA_TC (1 << 9) | ||
198 | #define CEA_SA_FCH (1 << 10) | ||
199 | |||
200 | static char *cea_speaker_allocation_names[] = { | ||
201 | /* 0 */ "FL/FR", | ||
202 | /* 1 */ "LFE", | ||
203 | /* 2 */ "FC", | ||
204 | /* 3 */ "RL/RR", | ||
205 | /* 4 */ "RC", | ||
206 | /* 5 */ "FLC/FRC", | ||
207 | /* 6 */ "RLC/RRC", | ||
208 | /* 7 */ "FLW/FRW", | ||
209 | /* 8 */ "FLH/FRH", | ||
210 | /* 9 */ "TC", | ||
211 | /* 10 */ "FCH", | ||
212 | }; | ||
213 | |||
214 | static char *eld_connection_type_names[4] = { | ||
215 | "HDMI", | ||
216 | "Display Port", | ||
217 | "2-reserved", | ||
218 | "3-reserved" | ||
219 | }; | ||
220 | |||
221 | enum cea_audio_coding_types { | ||
222 | AUDIO_CODING_TYPE_REF_STREAM_HEADER = 0, | ||
223 | AUDIO_CODING_TYPE_LPCM = 1, | ||
224 | AUDIO_CODING_TYPE_AC3 = 2, | ||
225 | AUDIO_CODING_TYPE_MPEG1 = 3, | ||
226 | AUDIO_CODING_TYPE_MP3 = 4, | ||
227 | AUDIO_CODING_TYPE_MPEG2 = 5, | ||
228 | AUDIO_CODING_TYPE_AACLC = 6, | ||
229 | AUDIO_CODING_TYPE_DTS = 7, | ||
230 | AUDIO_CODING_TYPE_ATRAC = 8, | ||
231 | AUDIO_CODING_TYPE_SACD = 9, | ||
232 | AUDIO_CODING_TYPE_EAC3 = 10, | ||
233 | AUDIO_CODING_TYPE_DTS_HD = 11, | ||
234 | AUDIO_CODING_TYPE_MLP = 12, | ||
235 | AUDIO_CODING_TYPE_DST = 13, | ||
236 | AUDIO_CODING_TYPE_WMAPRO = 14, | ||
237 | AUDIO_CODING_TYPE_REF_CXT = 15, | ||
238 | /* also include valid xtypes below */ | ||
239 | AUDIO_CODING_TYPE_HE_AAC = 15, | ||
240 | AUDIO_CODING_TYPE_HE_AAC2 = 16, | ||
241 | AUDIO_CODING_TYPE_MPEG_SURROUND = 17, | ||
242 | }; | ||
243 | |||
244 | enum cea_audio_coding_xtypes { | ||
245 | AUDIO_CODING_XTYPE_HE_REF_CT = 0, | ||
246 | AUDIO_CODING_XTYPE_HE_AAC = 1, | ||
247 | AUDIO_CODING_XTYPE_HE_AAC2 = 2, | ||
248 | AUDIO_CODING_XTYPE_MPEG_SURROUND = 3, | ||
249 | AUDIO_CODING_XTYPE_FIRST_RESERVED = 4, | ||
250 | }; | ||
251 | |||
252 | static char *cea_audio_coding_type_names[] = { | ||
253 | /* 0 */ "undefined", | ||
254 | /* 1 */ "LPCM", | ||
255 | /* 2 */ "AC-3", | ||
256 | /* 3 */ "MPEG1", | ||
257 | /* 4 */ "MP3", | ||
258 | /* 5 */ "MPEG2", | ||
259 | /* 6 */ "AAC-LC", | ||
260 | /* 7 */ "DTS", | ||
261 | /* 8 */ "ATRAC", | ||
262 | /* 9 */ "DSD(1-bit audio)", | ||
263 | /* 10 */ "Dolby Digital Plus(E-AC-3/DD+)", | ||
264 | /* 11 */ "DTS-HD", | ||
265 | /* 12 */ "Dolby TrueHD(MLP)", | ||
266 | /* 13 */ "DST", | ||
267 | /* 14 */ "WMAPro", | ||
268 | /* 15 */ "HE-AAC", | ||
269 | /* 16 */ "HE-AACv2", | ||
270 | /* 17 */ "MPEG Surround", | ||
271 | }; | ||
272 | |||
273 | |||
274 | /* | ||
275 | * HDMI routines | ||
276 | */ | ||
277 | |||
278 | static int hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid) | ||
279 | { | ||
280 | return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE, | ||
281 | AC_DIPSIZE_ELD_BUF); | ||
282 | } | ||
283 | |||
284 | #ifdef BE_PARANOID | ||
285 | static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t nid, | ||
286 | int *packet_index, int *byte_index) | ||
287 | { | ||
288 | int val; | ||
289 | |||
290 | val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_INDEX, 0); | ||
291 | |||
292 | *packet_index = val >> 5; | ||
293 | *byte_index = val & 0x1f; | ||
294 | } | ||
295 | #endif | ||
296 | |||
297 | static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t nid, | ||
298 | int packet_index, int byte_index) | ||
299 | { | ||
300 | int val; | ||
301 | |||
302 | val = (packet_index << 5) | (byte_index & 0x1f); | ||
303 | |||
304 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val); | ||
305 | } | ||
306 | |||
307 | static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t nid, | ||
308 | unsigned char val) | ||
309 | { | ||
310 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val); | ||
311 | } | ||
312 | |||
313 | static void hdmi_enable_output(struct hda_codec *codec) | ||
314 | { | ||
315 | /* Enable pin out and unmute */ | ||
316 | snd_hda_sequence_write(codec, pinout_enable_verb); | ||
317 | if (get_wcaps(codec, PIN_NID) & AC_WCAP_OUT_AMP) | ||
318 | snd_hda_codec_write(codec, PIN_NID, 0, | ||
319 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); | ||
320 | |||
321 | /* Enable Audio InfoFrame Transmission */ | ||
322 | hdmi_set_dip_index(codec, PIN_NID, 0x0, 0x0); | ||
323 | snd_hda_codec_write(codec, PIN_NID, 0, AC_VERB_SET_HDMI_DIP_XMIT, | ||
324 | AC_DIPXMIT_BEST); | ||
325 | } | ||
326 | |||
327 | static void hdmi_disable_output(struct hda_codec *codec) | ||
328 | { | ||
329 | snd_hda_sequence_write(codec, pinout_disable_verb); | ||
330 | if (get_wcaps(codec, PIN_NID) & AC_WCAP_OUT_AMP) | ||
331 | snd_hda_codec_write(codec, PIN_NID, 0, | ||
332 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); | ||
333 | |||
334 | /* | ||
335 | * FIXME: noises may arise when playing music after reloading the | ||
336 | * kernel module, until the next X restart or monitor repower. | ||
337 | */ | ||
338 | } | ||
339 | |||
340 | static int hdmi_get_channel_count(struct hda_codec *codec) | ||
341 | { | ||
342 | return 1 + snd_hda_codec_read(codec, CVT_NID, 0, | ||
343 | AC_VERB_GET_CVT_CHAN_COUNT, 0); | ||
344 | } | ||
345 | |||
346 | static void hdmi_set_channel_count(struct hda_codec *codec, int chs) | ||
347 | { | ||
348 | snd_hda_codec_write(codec, CVT_NID, 0, | ||
349 | AC_VERB_SET_CVT_CHAN_COUNT, chs - 1); | ||
350 | |||
351 | if (chs != hdmi_get_channel_count(codec)) | ||
352 | snd_printd(KERN_INFO "Channel count expect=%d, real=%d\n", | ||
353 | chs, hdmi_get_channel_count(codec)); | ||
354 | } | ||
355 | |||
356 | static void hdmi_debug_slot_mapping(struct hda_codec *codec) | ||
357 | { | ||
358 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
359 | int i; | ||
360 | int slot; | ||
361 | |||
362 | for (i = 0; i < 8; i++) { | ||
363 | slot = snd_hda_codec_read(codec, CVT_NID, 0, | ||
364 | AC_VERB_GET_HDMI_CHAN_SLOT, i); | ||
365 | printk(KERN_DEBUG "ASP channel %d => slot %d\n", | ||
366 | slot >> 4, slot & 0x7); | ||
367 | } | ||
368 | #endif | ||
369 | } | ||
370 | |||
371 | static void hdmi_setup_channel_mapping(struct hda_codec *codec) | ||
372 | { | ||
373 | snd_hda_sequence_write(codec, def_chan_map); | ||
374 | hdmi_debug_slot_mapping(codec); | ||
375 | } | ||
376 | |||
377 | |||
378 | /* | ||
379 | * ELD(EDID Like Data) routines | ||
380 | */ | ||
381 | |||
382 | static int hdmi_present_sense(struct hda_codec *codec, hda_nid_t nid) | ||
383 | { | ||
384 | return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0); | ||
385 | } | ||
386 | |||
387 | static void hdmi_debug_present_sense(struct hda_codec *codec) | ||
388 | { | ||
389 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
390 | int eldv; | ||
391 | int present; | ||
392 | |||
393 | present = hdmi_present_sense(codec, PIN_NID); | ||
394 | eldv = (present & AC_PINSENSE_ELDV); | ||
395 | present = (present & AC_PINSENSE_PRESENCE); | ||
396 | |||
397 | printk(KERN_INFO "pinp = %d, eldv = %d\n", !!present, !!eldv); | ||
398 | #endif | ||
399 | } | ||
400 | |||
401 | static unsigned char hdmi_get_eld_byte(struct hda_codec *codec, int byte_index) | ||
402 | { | ||
403 | unsigned int val; | ||
404 | |||
405 | val = snd_hda_codec_read(codec, PIN_NID, 0, | ||
406 | AC_VERB_GET_HDMI_ELDD, byte_index); | ||
407 | |||
408 | #ifdef BE_PARANOID | ||
409 | printk(KERN_INFO "ELD data byte %d: 0x%x\n", byte_index, val); | ||
410 | #endif | ||
411 | |||
412 | if ((val & AC_ELDD_ELD_VALID) == 0) { | ||
413 | snd_printd(KERN_INFO "Invalid ELD data byte %d\n", | ||
414 | byte_index); | ||
415 | val = 0; | ||
416 | } | ||
417 | |||
418 | return val & AC_ELDD_ELD_DATA; | ||
419 | } | ||
420 | |||
421 | static inline unsigned char grab_bits(const unsigned char *buf, | ||
422 | int byte, int lowbit, int bits) | ||
423 | { | ||
424 | BUG_ON(lowbit > 7); | ||
425 | BUG_ON(bits > 8); | ||
426 | BUG_ON(bits <= 0); | ||
427 | |||
428 | return (buf[byte] >> lowbit) & ((1 << bits) - 1); | ||
429 | } | ||
430 | |||
431 | static void hdmi_update_short_audio_desc(struct cea_sad *a, | ||
432 | const unsigned char *buf) | ||
433 | { | ||
434 | int i; | ||
435 | int val; | ||
436 | |||
437 | val = grab_bits(buf, 1, 0, 7); | ||
438 | a->rates = 0; | ||
439 | for (i = 0; i < 7; i++) | ||
440 | if (val & (1 << i)) | ||
441 | a->rates |= cea_sampling_frequencies[i + 1]; | ||
442 | |||
443 | a->channels = grab_bits(buf, 0, 0, 3); | ||
444 | a->channels++; | ||
445 | |||
446 | a->format = grab_bits(buf, 0, 3, 4); | ||
447 | switch (a->format) { | ||
448 | case AUDIO_CODING_TYPE_REF_STREAM_HEADER: | ||
449 | snd_printd(KERN_INFO | ||
450 | "audio coding type 0 not expected in ELD\n"); | ||
451 | break; | ||
452 | |||
453 | case AUDIO_CODING_TYPE_LPCM: | ||
454 | val = grab_bits(buf, 2, 0, 3); | ||
455 | a->sample_bits = 0; | ||
456 | for (i = 0; i < 3; i++) | ||
457 | if (val & (1 << i)) | ||
458 | a->sample_bits |= cea_sample_sizes[i + 1]; | ||
459 | break; | ||
460 | |||
461 | case AUDIO_CODING_TYPE_AC3: | ||
462 | case AUDIO_CODING_TYPE_MPEG1: | ||
463 | case AUDIO_CODING_TYPE_MP3: | ||
464 | case AUDIO_CODING_TYPE_MPEG2: | ||
465 | case AUDIO_CODING_TYPE_AACLC: | ||
466 | case AUDIO_CODING_TYPE_DTS: | ||
467 | case AUDIO_CODING_TYPE_ATRAC: | ||
468 | a->max_bitrate = grab_bits(buf, 2, 0, 8); | ||
469 | a->max_bitrate *= 8000; | ||
470 | break; | ||
471 | |||
472 | case AUDIO_CODING_TYPE_SACD: | ||
473 | break; | ||
474 | |||
475 | case AUDIO_CODING_TYPE_EAC3: | ||
476 | break; | ||
477 | |||
478 | case AUDIO_CODING_TYPE_DTS_HD: | ||
479 | break; | ||
480 | |||
481 | case AUDIO_CODING_TYPE_MLP: | ||
482 | break; | ||
483 | |||
484 | case AUDIO_CODING_TYPE_DST: | ||
485 | break; | ||
486 | |||
487 | case AUDIO_CODING_TYPE_WMAPRO: | ||
488 | a->profile = grab_bits(buf, 2, 0, 3); | ||
489 | break; | ||
490 | |||
491 | case AUDIO_CODING_TYPE_REF_CXT: | ||
492 | a->format = grab_bits(buf, 2, 3, 5); | ||
493 | if (a->format == AUDIO_CODING_XTYPE_HE_REF_CT || | ||
494 | a->format >= AUDIO_CODING_XTYPE_FIRST_RESERVED) { | ||
495 | snd_printd(KERN_INFO | ||
496 | "audio coding xtype %d not expected in ELD\n", | ||
497 | a->format); | ||
498 | a->format = 0; | ||
499 | } else | ||
500 | a->format += AUDIO_CODING_TYPE_HE_AAC - | ||
501 | AUDIO_CODING_XTYPE_HE_AAC; | ||
502 | break; | ||
503 | } | ||
504 | } | ||
505 | |||
506 | static int hdmi_update_sink_eld(struct hda_codec *codec, | ||
507 | const unsigned char *buf, int size) | ||
508 | { | ||
509 | struct intel_hdmi_spec *spec = codec->spec; | ||
510 | struct sink_eld *e = &spec->sink; | ||
511 | int mnl; | ||
512 | int i; | ||
513 | |||
514 | e->eld_ver = grab_bits(buf, 0, 3, 5); | ||
515 | if (e->eld_ver != ELD_VER_CEA_861D && | ||
516 | e->eld_ver != ELD_VER_PARTIAL) { | ||
517 | snd_printd(KERN_INFO "Unknown ELD version %d\n", e->eld_ver); | ||
518 | goto out_fail; | ||
519 | } | ||
520 | |||
521 | e->eld_size = size; | ||
522 | e->baseline_len = grab_bits(buf, 2, 0, 8); | ||
523 | mnl = grab_bits(buf, 4, 0, 5); | ||
524 | e->cea_edid_ver = grab_bits(buf, 4, 5, 3); | ||
525 | |||
526 | e->support_hdcp = grab_bits(buf, 5, 0, 1); | ||
527 | e->support_ai = grab_bits(buf, 5, 1, 1); | ||
528 | e->conn_type = grab_bits(buf, 5, 2, 2); | ||
529 | e->sad_count = grab_bits(buf, 5, 4, 4); | ||
530 | |||
531 | e->aud_synch_delay = grab_bits(buf, 6, 0, 8); | ||
532 | e->spk_alloc = grab_bits(buf, 7, 0, 7); | ||
533 | |||
534 | e->port_id = get_unaligned_le64(buf + 8); | ||
535 | |||
536 | /* not specified, but the spec's tendency is little endian */ | ||
537 | e->manufacture_id = get_unaligned_le16(buf + 16); | ||
538 | e->product_id = get_unaligned_le16(buf + 18); | ||
539 | |||
540 | if (mnl > ELD_MAX_MNL) { | ||
541 | snd_printd(KERN_INFO "MNL is reserved value %d\n", mnl); | ||
542 | goto out_fail; | ||
543 | } else if (ELD_FIXED_BYTES + mnl > size) { | ||
544 | snd_printd(KERN_INFO "out of range MNL %d\n", mnl); | ||
545 | goto out_fail; | ||
546 | } else | ||
547 | strlcpy(e->monitor_name, buf + ELD_FIXED_BYTES, mnl); | ||
548 | |||
549 | for (i = 0; i < e->sad_count; i++) { | ||
550 | if (ELD_FIXED_BYTES + mnl + 3 * (i + 1) > size) { | ||
551 | snd_printd(KERN_INFO "out of range SAD %d\n", i); | ||
552 | goto out_fail; | ||
553 | } | ||
554 | hdmi_update_short_audio_desc(e->sad + i, | ||
555 | buf + ELD_FIXED_BYTES + mnl + 3 * i); | ||
556 | } | ||
557 | |||
558 | return 0; | ||
559 | |||
560 | out_fail: | ||
561 | e->eld_ver = 0; | ||
562 | return -EINVAL; | ||
563 | } | ||
564 | |||
565 | static int hdmi_get_eld(struct hda_codec *codec) | ||
566 | { | ||
567 | int i; | ||
568 | int ret; | ||
569 | int size; | ||
570 | unsigned char *buf; | ||
571 | |||
572 | i = hdmi_present_sense(codec, PIN_NID) & AC_PINSENSE_ELDV; | ||
573 | if (!i) | ||
574 | return -ENOENT; | ||
575 | |||
576 | size = hdmi_get_eld_size(codec, PIN_NID); | ||
577 | if (size == 0) { | ||
578 | /* wfg: workaround for ASUS P5E-VM HDMI board */ | ||
579 | snd_printd(KERN_INFO "ELD buf size is 0, force 128\n"); | ||
580 | size = 128; | ||
581 | } | ||
582 | if (size < ELD_FIXED_BYTES || size > PAGE_SIZE) { | ||
583 | snd_printd(KERN_INFO "Invalid ELD buf size %d\n", size); | ||
584 | return -ERANGE; | ||
585 | } | ||
586 | |||
587 | buf = kmalloc(size, GFP_KERNEL); | ||
588 | if (!buf) | ||
589 | return -ENOMEM; | ||
590 | |||
591 | for (i = 0; i < size; i++) | ||
592 | buf[i] = hdmi_get_eld_byte(codec, i); | ||
593 | |||
594 | ret = hdmi_update_sink_eld(codec, buf, size); | ||
595 | |||
596 | kfree(buf); | ||
597 | return ret; | ||
598 | } | ||
599 | |||
600 | static void hdmi_show_short_audio_desc(struct cea_sad *a) | ||
601 | { | ||
602 | printk(KERN_INFO "coding type: %s\n", | ||
603 | cea_audio_coding_type_names[a->format]); | ||
604 | printk(KERN_INFO "channels: %d\n", a->channels); | ||
605 | printk(KERN_INFO "sampling frequencies: 0x%x\n", a->rates); | ||
606 | |||
607 | if (a->format == AUDIO_CODING_TYPE_LPCM) | ||
608 | printk(KERN_INFO "sample bits: 0x%x\n", a->sample_bits); | ||
609 | |||
610 | if (a->max_bitrate) | ||
611 | printk(KERN_INFO "max bitrate: %d HZ\n", a->max_bitrate); | ||
612 | |||
613 | if (a->profile) | ||
614 | printk(KERN_INFO "profile: %d\n", a->profile); | ||
615 | } | ||
616 | |||
617 | static void hdmi_show_eld(struct hda_codec *codec) | ||
618 | { | ||
619 | int i; | ||
620 | int j; | ||
621 | struct intel_hdmi_spec *spec = codec->spec; | ||
622 | struct sink_eld *e = &spec->sink; | ||
623 | char buf[80]; | ||
624 | |||
625 | printk(KERN_INFO "ELD buffer size is %d\n", e->eld_size); | ||
626 | printk(KERN_INFO "ELD baseline len is %d*4\n", e->baseline_len); | ||
627 | printk(KERN_INFO "vendor block len is %d\n", | ||
628 | e->eld_size - e->baseline_len * 4 - 4); | ||
629 | printk(KERN_INFO "ELD version is %s\n", | ||
630 | eld_versoin_names[e->eld_ver]); | ||
631 | printk(KERN_INFO "CEA EDID version is %s\n", | ||
632 | cea_edid_version_names[e->cea_edid_ver]); | ||
633 | printk(KERN_INFO "manufacture id is 0x%x\n", e->manufacture_id); | ||
634 | printk(KERN_INFO "product id is 0x%x\n", e->product_id); | ||
635 | printk(KERN_INFO "port id is 0x%llx\n", (long long)e->port_id); | ||
636 | printk(KERN_INFO "HDCP support is %d\n", e->support_hdcp); | ||
637 | printk(KERN_INFO "AI support is %d\n", e->support_ai); | ||
638 | printk(KERN_INFO "SAD count is %d\n", e->sad_count); | ||
639 | printk(KERN_INFO "audio sync delay is %x\n", e->aud_synch_delay); | ||
640 | printk(KERN_INFO "connection type is %s\n", | ||
641 | eld_connection_type_names[e->conn_type]); | ||
642 | printk(KERN_INFO "monitor name is %s\n", e->monitor_name); | ||
643 | |||
644 | j = 0; | ||
645 | for (i = 0; i < ARRAY_SIZE(cea_speaker_allocation_names); i++) { | ||
646 | if (e->spk_alloc & (1 << i)) | ||
647 | j += snprintf(buf + j, sizeof(buf) - j, " %s", | ||
648 | cea_speaker_allocation_names[i]); | ||
649 | } | ||
650 | buf[j] = '\0'; /* necessary when j == 0 */ | ||
651 | printk(KERN_INFO "speaker allocations: (0x%x)%s\n", e->spk_alloc, buf); | ||
652 | |||
653 | for (i = 0; i < e->sad_count; i++) | ||
654 | hdmi_show_short_audio_desc(e->sad + i); | ||
655 | } | ||
656 | |||
657 | /* | ||
658 | * Be careful, ELD buf could be totally rubbish! | ||
659 | */ | ||
660 | static void hdmi_parse_eld(struct hda_codec *codec) | ||
661 | { | ||
662 | hdmi_debug_present_sense(codec); | ||
663 | |||
664 | if (!hdmi_get_eld(codec)) | ||
665 | hdmi_show_eld(codec); | ||
666 | } | ||
667 | |||
668 | |||
669 | /* | ||
670 | * Audio Infoframe routines | ||
671 | */ | ||
672 | |||
673 | static void hdmi_debug_dip_size(struct hda_codec *codec) | ||
674 | { | ||
675 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
676 | int i; | ||
677 | int size; | ||
678 | |||
679 | size = hdmi_get_eld_size(codec, PIN_NID); | ||
680 | printk(KERN_DEBUG "ELD buf size is %d\n", size); | ||
681 | |||
682 | for (i = 0; i < 8; i++) { | ||
683 | size = snd_hda_codec_read(codec, PIN_NID, 0, | ||
684 | AC_VERB_GET_HDMI_DIP_SIZE, i); | ||
685 | printk(KERN_DEBUG "DIP GP[%d] buf size is %d\n", i, size); | ||
686 | } | ||
687 | #endif | ||
688 | } | ||
689 | |||
690 | static void hdmi_clear_dip_buffers(struct hda_codec *codec) | ||
691 | { | ||
692 | #ifdef BE_PARANOID | ||
693 | int i, j; | ||
694 | int size; | ||
695 | int pi, bi; | ||
696 | for (i = 0; i < 8; i++) { | ||
697 | size = snd_hda_codec_read(codec, PIN_NID, 0, | ||
698 | AC_VERB_GET_HDMI_DIP_SIZE, i); | ||
699 | if (size == 0) | ||
700 | continue; | ||
701 | |||
702 | hdmi_set_dip_index(codec, PIN_NID, i, 0x0); | ||
703 | for (j = 1; j < 1000; j++) { | ||
704 | hdmi_write_dip_byte(codec, PIN_NID, 0x0); | ||
705 | hdmi_get_dip_index(codec, PIN_NID, &pi, &bi); | ||
706 | if (pi != i) | ||
707 | snd_printd(KERN_INFO "dip index %d: %d != %d\n", | ||
708 | bi, pi, i); | ||
709 | if (bi == 0) /* byte index wrapped around */ | ||
710 | break; | ||
711 | } | ||
712 | snd_printd(KERN_INFO | ||
713 | "DIP GP[%d] buf reported size=%d, written=%d\n", | ||
714 | i, size, j); | ||
715 | } | ||
716 | #endif | ||
717 | } | ||
718 | |||
719 | static void hdmi_setup_audio_infoframe(struct hda_codec *codec, | ||
720 | struct snd_pcm_substream *substream) | ||
721 | { | ||
722 | struct hdmi_audio_infoframe audio_infoframe = { | ||
723 | .type = 0x84, | ||
724 | .ver = 0x01, | ||
725 | .len = 0x0a, | ||
726 | .CC02_CT47 = substream->runtime->channels - 1, | ||
727 | }; | ||
728 | u8 *params = (u8 *)&audio_infoframe; | ||
729 | int i; | ||
730 | |||
731 | hdmi_debug_dip_size(codec); | ||
732 | hdmi_clear_dip_buffers(codec); /* be paranoid */ | ||
733 | |||
734 | hdmi_set_dip_index(codec, PIN_NID, 0x0, 0x0); | ||
735 | for (i = 0; i < sizeof(audio_infoframe); i++) | ||
736 | hdmi_write_dip_byte(codec, PIN_NID, params[i]); | ||
737 | } | ||
738 | |||
739 | |||
740 | /* | ||
741 | * Unsolicited events | ||
742 | */ | ||
743 | |||
744 | static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) | ||
745 | { | ||
746 | int pind = !!(res & AC_UNSOL_RES_PD); | ||
747 | int eldv = !!(res & AC_UNSOL_RES_ELDV); | ||
748 | |||
749 | printk(KERN_INFO "HDMI intrinsic event: PD=%d ELDV=%d\n", pind, eldv); | ||
750 | |||
751 | if (pind && eldv) { | ||
752 | hdmi_parse_eld(codec); | ||
753 | /* TODO: do real things about ELD */ | ||
754 | } | ||
755 | } | ||
756 | |||
757 | static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) | ||
758 | { | ||
759 | int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; | ||
760 | int cp_state = !!(res & AC_UNSOL_RES_CP_STATE); | ||
761 | int cp_ready = !!(res & AC_UNSOL_RES_CP_READY); | ||
762 | |||
763 | printk(KERN_INFO "HDMI non-intrinsic event: " | ||
764 | "SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n", | ||
765 | subtag, | ||
766 | cp_state, | ||
767 | cp_ready); | ||
768 | |||
769 | /* who cares? */ | ||
770 | if (cp_state) | ||
771 | ; | ||
772 | if (cp_ready) | ||
773 | ; | ||
774 | } | ||
775 | |||
776 | |||
777 | static void intel_hdmi_unsol_event(struct hda_codec *codec, unsigned int res) | ||
778 | { | ||
779 | int tag = res >> AC_UNSOL_RES_TAG_SHIFT; | ||
780 | int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; | ||
781 | |||
782 | if (tag != INTEL_HDMI_EVENT_TAG) { | ||
783 | snd_printd(KERN_INFO | ||
784 | "Unexpected HDMI unsolicited event tag 0x%x\n", | ||
785 | tag); | ||
786 | return; | ||
787 | } | ||
788 | |||
789 | if (subtag == 0) | ||
790 | hdmi_intrinsic_event(codec, res); | ||
791 | else | ||
792 | hdmi_non_intrinsic_event(codec, res); | ||
793 | } | ||
794 | |||
795 | /* | ||
796 | * Callbacks | ||
797 | */ | ||
798 | |||
799 | static int intel_hdmi_playback_pcm_open(struct hda_pcm_stream *hinfo, | ||
800 | struct hda_codec *codec, | ||
801 | struct snd_pcm_substream *substream) | ||
802 | { | ||
803 | struct intel_hdmi_spec *spec = codec->spec; | ||
804 | |||
805 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); | ||
806 | } | ||
807 | |||
808 | static int intel_hdmi_playback_pcm_close(struct hda_pcm_stream *hinfo, | ||
809 | struct hda_codec *codec, | ||
810 | struct snd_pcm_substream *substream) | ||
811 | { | ||
812 | struct intel_hdmi_spec *spec = codec->spec; | ||
813 | |||
814 | hdmi_disable_output(codec); | ||
815 | |||
816 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | ||
817 | } | ||
818 | |||
819 | static int intel_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
820 | struct hda_codec *codec, | ||
821 | unsigned int stream_tag, | ||
822 | unsigned int format, | ||
823 | struct snd_pcm_substream *substream) | ||
824 | { | ||
825 | struct intel_hdmi_spec *spec = codec->spec; | ||
826 | |||
827 | snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag, | ||
828 | format, substream); | ||
829 | |||
830 | hdmi_set_channel_count(codec, substream->runtime->channels); | ||
831 | |||
832 | /* wfg: channel mapping not supported by DEVCTG */ | ||
833 | hdmi_setup_channel_mapping(codec); | ||
834 | |||
835 | hdmi_setup_audio_infoframe(codec, substream); | ||
836 | |||
837 | hdmi_enable_output(codec); | ||
838 | |||
839 | return 0; | ||
840 | } | ||
841 | |||
842 | static struct hda_pcm_stream intel_hdmi_pcm_playback = { | ||
843 | .substreams = 1, | ||
844 | .channels_min = 2, | ||
845 | .channels_max = 8, | ||
846 | .nid = CVT_NID, /* NID to query formats and rates and setup streams */ | ||
847 | .ops = { | ||
848 | .open = intel_hdmi_playback_pcm_open, | ||
849 | .close = intel_hdmi_playback_pcm_close, | ||
850 | .prepare = intel_hdmi_playback_pcm_prepare | ||
851 | }, | ||
852 | }; | ||
853 | |||
854 | static int intel_hdmi_build_pcms(struct hda_codec *codec) | ||
855 | { | ||
856 | struct intel_hdmi_spec *spec = codec->spec; | ||
857 | struct hda_pcm *info = &spec->pcm_rec; | ||
858 | |||
859 | codec->num_pcms = 1; | ||
860 | codec->pcm_info = info; | ||
861 | |||
862 | info->name = "INTEL HDMI"; | ||
863 | info->pcm_type = HDA_PCM_TYPE_HDMI; | ||
864 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = intel_hdmi_pcm_playback; | ||
865 | |||
866 | return 0; | ||
867 | } | ||
868 | |||
869 | static int intel_hdmi_build_controls(struct hda_codec *codec) | ||
870 | { | ||
871 | struct intel_hdmi_spec *spec = codec->spec; | ||
872 | int err; | ||
873 | |||
874 | err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); | ||
875 | if (err < 0) | ||
876 | return err; | ||
877 | |||
878 | return 0; | ||
879 | } | ||
880 | |||
881 | static int intel_hdmi_init(struct hda_codec *codec) | ||
882 | { | ||
883 | /* disable audio output as early as possible */ | ||
884 | hdmi_disable_output(codec); | ||
885 | |||
886 | snd_hda_sequence_write(codec, unsolicited_response_verb); | ||
887 | |||
888 | return 0; | ||
889 | } | ||
890 | |||
891 | static void intel_hdmi_free(struct hda_codec *codec) | ||
892 | { | ||
893 | kfree(codec->spec); | ||
894 | } | ||
895 | |||
896 | static struct hda_codec_ops intel_hdmi_patch_ops = { | ||
897 | .init = intel_hdmi_init, | ||
898 | .free = intel_hdmi_free, | ||
899 | .build_pcms = intel_hdmi_build_pcms, | ||
900 | .build_controls = intel_hdmi_build_controls, | ||
901 | .unsol_event = intel_hdmi_unsol_event, | ||
902 | }; | ||
903 | |||
904 | static int patch_intel_hdmi(struct hda_codec *codec) | ||
905 | { | ||
906 | struct intel_hdmi_spec *spec; | ||
907 | |||
908 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
909 | if (spec == NULL) | ||
910 | return -ENOMEM; | ||
911 | |||
912 | spec->multiout.num_dacs = 0; /* no analog */ | ||
913 | spec->multiout.max_channels = 8; | ||
914 | spec->multiout.dig_out_nid = CVT_NID; | ||
915 | |||
916 | codec->spec = spec; | ||
917 | codec->patch_ops = intel_hdmi_patch_ops; | ||
918 | |||
919 | return 0; | ||
920 | } | ||
921 | |||
922 | struct hda_codec_preset snd_hda_preset_intelhdmi[] = { | ||
923 | { .id = 0x808629fb, .name = "INTEL G45 DEVCL", .patch = patch_intel_hdmi }, | ||
924 | { .id = 0x80862801, .name = "INTEL G45 DEVBLC", .patch = patch_intel_hdmi }, | ||
925 | { .id = 0x80862802, .name = "INTEL G45 DEVCTG", .patch = patch_intel_hdmi }, | ||
926 | { .id = 0x80862803, .name = "INTEL G45 DEVELK", .patch = patch_intel_hdmi }, | ||
927 | {} /* terminator */ | ||
928 | }; | ||
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index a378c0145125..0f1fa1dac448 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, |
@@ -239,6 +243,7 @@ struct alc_spec { | |||
239 | /* codec parameterization */ | 243 | /* codec parameterization */ |
240 | struct snd_kcontrol_new *mixers[5]; /* mixer arrays */ | 244 | struct snd_kcontrol_new *mixers[5]; /* mixer arrays */ |
241 | unsigned int num_mixers; | 245 | unsigned int num_mixers; |
246 | struct snd_kcontrol_new *cap_mixer; /* capture mixer */ | ||
242 | 247 | ||
243 | const struct hda_verb *init_verbs[5]; /* initialization verbs | 248 | const struct hda_verb *init_verbs[5]; /* initialization verbs |
244 | * don't forget NULL | 249 | * don't forget NULL |
@@ -268,6 +273,7 @@ struct alc_spec { | |||
268 | hda_nid_t *adc_nids; | 273 | hda_nid_t *adc_nids; |
269 | hda_nid_t *capsrc_nids; | 274 | hda_nid_t *capsrc_nids; |
270 | hda_nid_t dig_in_nid; /* digital-in NID; optional */ | 275 | hda_nid_t dig_in_nid; /* digital-in NID; optional */ |
276 | unsigned char is_mix_capture; /* matrix-style capture (non-mux) */ | ||
271 | 277 | ||
272 | /* capture source */ | 278 | /* capture source */ |
273 | unsigned int num_mux_defs; | 279 | unsigned int num_mux_defs; |
@@ -284,8 +290,7 @@ struct alc_spec { | |||
284 | 290 | ||
285 | /* dynamic controls, init_verbs and input_mux */ | 291 | /* dynamic controls, init_verbs and input_mux */ |
286 | struct auto_pin_cfg autocfg; | 292 | struct auto_pin_cfg autocfg; |
287 | unsigned int num_kctl_alloc, num_kctl_used; | 293 | struct snd_array kctls; |
288 | struct snd_kcontrol_new *kctl_alloc; | ||
289 | struct hda_input_mux private_imux; | 294 | struct hda_input_mux private_imux; |
290 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; | 295 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; |
291 | 296 | ||
@@ -323,6 +328,7 @@ struct alc_config_preset { | |||
323 | struct snd_kcontrol_new *mixers[5]; /* should be identical size | 328 | struct snd_kcontrol_new *mixers[5]; /* should be identical size |
324 | * with spec | 329 | * with spec |
325 | */ | 330 | */ |
331 | struct snd_kcontrol_new *cap_mixer; /* capture mixer */ | ||
326 | const struct hda_verb *init_verbs[5]; | 332 | const struct hda_verb *init_verbs[5]; |
327 | unsigned int num_dacs; | 333 | unsigned int num_dacs; |
328 | hda_nid_t *dac_nids; | 334 | hda_nid_t *dac_nids; |
@@ -375,14 +381,38 @@ static int alc_mux_enum_put(struct snd_kcontrol *kcontrol, | |||
375 | { | 381 | { |
376 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 382 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
377 | struct alc_spec *spec = codec->spec; | 383 | struct alc_spec *spec = codec->spec; |
384 | const struct hda_input_mux *imux = spec->input_mux; | ||
378 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | 385 | 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; | ||
380 | hda_nid_t nid = spec->capsrc_nids ? | 386 | hda_nid_t nid = spec->capsrc_nids ? |
381 | spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx]; | 387 | 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 | 388 | ||
389 | if (spec->is_mix_capture) { | ||
390 | /* Matrix-mixer style (e.g. ALC882) */ | ||
391 | unsigned int *cur_val = &spec->cur_mux[adc_idx]; | ||
392 | unsigned int i, idx; | ||
393 | |||
394 | idx = ucontrol->value.enumerated.item[0]; | ||
395 | if (idx >= imux->num_items) | ||
396 | idx = imux->num_items - 1; | ||
397 | if (*cur_val == idx) | ||
398 | return 0; | ||
399 | for (i = 0; i < imux->num_items; i++) { | ||
400 | unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE; | ||
401 | snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, | ||
402 | imux->items[i].index, | ||
403 | HDA_AMP_MUTE, v); | ||
404 | } | ||
405 | *cur_val = idx; | ||
406 | return 1; | ||
407 | } else { | ||
408 | /* MUX style (e.g. ALC880) */ | ||
409 | unsigned int mux_idx; | ||
410 | mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx; | ||
411 | return snd_hda_input_mux_put(codec, &spec->input_mux[mux_idx], | ||
412 | ucontrol, nid, | ||
413 | &spec->cur_mux[adc_idx]); | ||
414 | } | ||
415 | } | ||
386 | 416 | ||
387 | /* | 417 | /* |
388 | * channel mode setting | 418 | * channel mode setting |
@@ -717,6 +747,22 @@ static int alc_eapd_ctrl_put(struct snd_kcontrol *kcontrol, | |||
717 | #endif /* CONFIG_SND_DEBUG */ | 747 | #endif /* CONFIG_SND_DEBUG */ |
718 | 748 | ||
719 | /* | 749 | /* |
750 | */ | ||
751 | static void add_mixer(struct alc_spec *spec, struct snd_kcontrol_new *mix) | ||
752 | { | ||
753 | if (snd_BUG_ON(spec->num_mixers >= ARRAY_SIZE(spec->mixers))) | ||
754 | return; | ||
755 | spec->mixers[spec->num_mixers++] = mix; | ||
756 | } | ||
757 | |||
758 | static void add_verb(struct alc_spec *spec, const struct hda_verb *verb) | ||
759 | { | ||
760 | if (snd_BUG_ON(spec->num_init_verbs >= ARRAY_SIZE(spec->init_verbs))) | ||
761 | return; | ||
762 | spec->init_verbs[spec->num_init_verbs++] = verb; | ||
763 | } | ||
764 | |||
765 | /* | ||
720 | * set up from the preset table | 766 | * set up from the preset table |
721 | */ | 767 | */ |
722 | static void setup_preset(struct alc_spec *spec, | 768 | static void setup_preset(struct alc_spec *spec, |
@@ -725,11 +771,11 @@ static void setup_preset(struct alc_spec *spec, | |||
725 | int i; | 771 | int i; |
726 | 772 | ||
727 | for (i = 0; i < ARRAY_SIZE(preset->mixers) && preset->mixers[i]; i++) | 773 | for (i = 0; i < ARRAY_SIZE(preset->mixers) && preset->mixers[i]; i++) |
728 | spec->mixers[spec->num_mixers++] = preset->mixers[i]; | 774 | add_mixer(spec, preset->mixers[i]); |
775 | spec->cap_mixer = preset->cap_mixer; | ||
729 | for (i = 0; i < ARRAY_SIZE(preset->init_verbs) && preset->init_verbs[i]; | 776 | for (i = 0; i < ARRAY_SIZE(preset->init_verbs) && preset->init_verbs[i]; |
730 | i++) | 777 | i++) |
731 | spec->init_verbs[spec->num_init_verbs++] = | 778 | add_verb(spec, preset->init_verbs[i]); |
732 | preset->init_verbs[i]; | ||
733 | 779 | ||
734 | spec->channel_mode = preset->channel_mode; | 780 | spec->channel_mode = preset->channel_mode; |
735 | spec->num_channel_mode = preset->num_channel_mode; | 781 | spec->num_channel_mode = preset->num_channel_mode; |
@@ -1205,49 +1251,126 @@ static struct snd_kcontrol_new alc880_three_stack_mixer[] = { | |||
1205 | }; | 1251 | }; |
1206 | 1252 | ||
1207 | /* capture mixer elements */ | 1253 | /* capture mixer elements */ |
1208 | static struct snd_kcontrol_new alc880_capture_mixer[] = { | 1254 | static int alc_cap_vol_info(struct snd_kcontrol *kcontrol, |
1209 | HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT), | 1255 | struct snd_ctl_elem_info *uinfo) |
1210 | HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT), | 1256 | { |
1211 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT), | 1257 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
1212 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT), | 1258 | struct alc_spec *spec = codec->spec; |
1213 | HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT), | 1259 | 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 | 1260 | ||
1230 | /* capture mixer elements (in case NID 0x07 not available) */ | 1261 | mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */ |
1231 | static struct snd_kcontrol_new alc880_capture_alt_mixer[] = { | 1262 | kcontrol->private_value = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0, |
1232 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | 1263 | HDA_INPUT); |
1233 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | 1264 | err = snd_hda_mixer_amp_volume_info(kcontrol, uinfo); |
1234 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), | 1265 | mutex_unlock(&codec->spdif_mutex); /* reuse spdif_mutex */ |
1235 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), | 1266 | return err; |
1236 | { | 1267 | } |
1237 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1268 | |
1238 | /* The multiple "Capture Source" controls confuse alsamixer | 1269 | static int alc_cap_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag, |
1239 | * So call somewhat different.. | 1270 | unsigned int size, unsigned int __user *tlv) |
1240 | */ | 1271 | { |
1241 | /* .name = "Capture Source", */ | 1272 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
1242 | .name = "Input Source", | 1273 | struct alc_spec *spec = codec->spec; |
1243 | .count = 2, | 1274 | int err; |
1244 | .info = alc_mux_enum_info, | 1275 | |
1245 | .get = alc_mux_enum_get, | 1276 | mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */ |
1246 | .put = alc_mux_enum_put, | 1277 | kcontrol->private_value = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0, |
1247 | }, | 1278 | HDA_INPUT); |
1248 | { } /* end */ | 1279 | err = snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, tlv); |
1249 | }; | 1280 | mutex_unlock(&codec->spdif_mutex); /* reuse spdif_mutex */ |
1281 | return err; | ||
1282 | } | ||
1283 | |||
1284 | typedef int (*getput_call_t)(struct snd_kcontrol *kcontrol, | ||
1285 | struct snd_ctl_elem_value *ucontrol); | ||
1286 | |||
1287 | static int alc_cap_getput_caller(struct snd_kcontrol *kcontrol, | ||
1288 | struct snd_ctl_elem_value *ucontrol, | ||
1289 | getput_call_t func) | ||
1290 | { | ||
1291 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1292 | struct alc_spec *spec = codec->spec; | ||
1293 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | ||
1294 | int err; | ||
1295 | |||
1296 | mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */ | ||
1297 | kcontrol->private_value = HDA_COMPOSE_AMP_VAL(spec->adc_nids[adc_idx], | ||
1298 | 3, 0, HDA_INPUT); | ||
1299 | err = func(kcontrol, ucontrol); | ||
1300 | mutex_unlock(&codec->spdif_mutex); /* reuse spdif_mutex */ | ||
1301 | return err; | ||
1302 | } | ||
1303 | |||
1304 | static int alc_cap_vol_get(struct snd_kcontrol *kcontrol, | ||
1305 | struct snd_ctl_elem_value *ucontrol) | ||
1306 | { | ||
1307 | return alc_cap_getput_caller(kcontrol, ucontrol, | ||
1308 | snd_hda_mixer_amp_volume_get); | ||
1309 | } | ||
1310 | |||
1311 | static int alc_cap_vol_put(struct snd_kcontrol *kcontrol, | ||
1312 | struct snd_ctl_elem_value *ucontrol) | ||
1313 | { | ||
1314 | return alc_cap_getput_caller(kcontrol, ucontrol, | ||
1315 | snd_hda_mixer_amp_volume_put); | ||
1316 | } | ||
1250 | 1317 | ||
1318 | /* capture mixer elements */ | ||
1319 | #define alc_cap_sw_info snd_ctl_boolean_stereo_info | ||
1320 | |||
1321 | static int alc_cap_sw_get(struct snd_kcontrol *kcontrol, | ||
1322 | struct snd_ctl_elem_value *ucontrol) | ||
1323 | { | ||
1324 | return alc_cap_getput_caller(kcontrol, ucontrol, | ||
1325 | snd_hda_mixer_amp_switch_get); | ||
1326 | } | ||
1327 | |||
1328 | static int alc_cap_sw_put(struct snd_kcontrol *kcontrol, | ||
1329 | struct snd_ctl_elem_value *ucontrol) | ||
1330 | { | ||
1331 | return alc_cap_getput_caller(kcontrol, ucontrol, | ||
1332 | snd_hda_mixer_amp_switch_put); | ||
1333 | } | ||
1334 | |||
1335 | #define DEFINE_CAPMIX(num) \ | ||
1336 | static struct snd_kcontrol_new alc_capture_mixer ## num[] = { \ | ||
1337 | { \ | ||
1338 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
1339 | .name = "Capture Switch", \ | ||
1340 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ | ||
1341 | .count = num, \ | ||
1342 | .info = alc_cap_sw_info, \ | ||
1343 | .get = alc_cap_sw_get, \ | ||
1344 | .put = alc_cap_sw_put, \ | ||
1345 | }, \ | ||
1346 | { \ | ||
1347 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
1348 | .name = "Capture Volume", \ | ||
1349 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | \ | ||
1350 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ | ||
1351 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK), \ | ||
1352 | .count = num, \ | ||
1353 | .info = alc_cap_vol_info, \ | ||
1354 | .get = alc_cap_vol_get, \ | ||
1355 | .put = alc_cap_vol_put, \ | ||
1356 | .tlv = { .c = alc_cap_vol_tlv }, \ | ||
1357 | }, \ | ||
1358 | { \ | ||
1359 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
1360 | /* .name = "Capture Source", */ \ | ||
1361 | .name = "Input Source", \ | ||
1362 | .count = num, \ | ||
1363 | .info = alc_mux_enum_info, \ | ||
1364 | .get = alc_mux_enum_get, \ | ||
1365 | .put = alc_mux_enum_put, \ | ||
1366 | }, \ | ||
1367 | { } /* end */ \ | ||
1368 | } | ||
1369 | |||
1370 | /* up to three ADCs */ | ||
1371 | DEFINE_CAPMIX(1); | ||
1372 | DEFINE_CAPMIX(2); | ||
1373 | DEFINE_CAPMIX(3); | ||
1251 | 1374 | ||
1252 | 1375 | ||
1253 | /* | 1376 | /* |
@@ -1533,18 +1656,6 @@ static struct snd_kcontrol_new alc880_tcl_s700_mixer[] = { | |||
1533 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0B, 0x0, HDA_INPUT), | 1656 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0B, 0x0, HDA_INPUT), |
1534 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | 1657 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), |
1535 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | 1658 | 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 */ | 1659 | { } /* end */ |
1549 | }; | 1660 | }; |
1550 | 1661 | ||
@@ -1619,6 +1730,7 @@ static const char *alc_slave_vols[] = { | |||
1619 | "Speaker Playback Volume", | 1730 | "Speaker Playback Volume", |
1620 | "Mono Playback Volume", | 1731 | "Mono Playback Volume", |
1621 | "Line-Out Playback Volume", | 1732 | "Line-Out Playback Volume", |
1733 | "PCM Playback Volume", | ||
1622 | NULL, | 1734 | NULL, |
1623 | }; | 1735 | }; |
1624 | 1736 | ||
@@ -1638,6 +1750,9 @@ static const char *alc_slave_sws[] = { | |||
1638 | /* | 1750 | /* |
1639 | * build control elements | 1751 | * build control elements |
1640 | */ | 1752 | */ |
1753 | |||
1754 | static void alc_free_kctls(struct hda_codec *codec); | ||
1755 | |||
1641 | static int alc_build_controls(struct hda_codec *codec) | 1756 | static int alc_build_controls(struct hda_codec *codec) |
1642 | { | 1757 | { |
1643 | struct alc_spec *spec = codec->spec; | 1758 | struct alc_spec *spec = codec->spec; |
@@ -1649,7 +1764,11 @@ static int alc_build_controls(struct hda_codec *codec) | |||
1649 | if (err < 0) | 1764 | if (err < 0) |
1650 | return err; | 1765 | return err; |
1651 | } | 1766 | } |
1652 | 1767 | if (spec->cap_mixer) { | |
1768 | err = snd_hda_add_new_ctls(codec, spec->cap_mixer); | ||
1769 | if (err < 0) | ||
1770 | return err; | ||
1771 | } | ||
1653 | if (spec->multiout.dig_out_nid) { | 1772 | if (spec->multiout.dig_out_nid) { |
1654 | err = snd_hda_create_spdif_out_ctls(codec, | 1773 | err = snd_hda_create_spdif_out_ctls(codec, |
1655 | spec->multiout.dig_out_nid); | 1774 | spec->multiout.dig_out_nid); |
@@ -1684,6 +1803,7 @@ static int alc_build_controls(struct hda_codec *codec) | |||
1684 | return err; | 1803 | return err; |
1685 | } | 1804 | } |
1686 | 1805 | ||
1806 | alc_free_kctls(codec); /* no longer needed */ | ||
1687 | return 0; | 1807 | return 0; |
1688 | } | 1808 | } |
1689 | 1809 | ||
@@ -2774,19 +2894,27 @@ static int alc_build_pcms(struct hda_codec *codec) | |||
2774 | return 0; | 2894 | return 0; |
2775 | } | 2895 | } |
2776 | 2896 | ||
2897 | static void alc_free_kctls(struct hda_codec *codec) | ||
2898 | { | ||
2899 | struct alc_spec *spec = codec->spec; | ||
2900 | |||
2901 | if (spec->kctls.list) { | ||
2902 | struct snd_kcontrol_new *kctl = spec->kctls.list; | ||
2903 | int i; | ||
2904 | for (i = 0; i < spec->kctls.used; i++) | ||
2905 | kfree(kctl[i].name); | ||
2906 | } | ||
2907 | snd_array_free(&spec->kctls); | ||
2908 | } | ||
2909 | |||
2777 | static void alc_free(struct hda_codec *codec) | 2910 | static void alc_free(struct hda_codec *codec) |
2778 | { | 2911 | { |
2779 | struct alc_spec *spec = codec->spec; | 2912 | struct alc_spec *spec = codec->spec; |
2780 | unsigned int i; | ||
2781 | 2913 | ||
2782 | if (!spec) | 2914 | if (!spec) |
2783 | return; | 2915 | return; |
2784 | 2916 | ||
2785 | if (spec->kctl_alloc) { | 2917 | 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); | 2918 | kfree(spec); |
2791 | codec->spec = NULL; /* to be sure */ | 2919 | codec->spec = NULL; /* to be sure */ |
2792 | } | 2920 | } |
@@ -3268,6 +3396,8 @@ static struct alc_config_preset alc880_presets[] = { | |||
3268 | alc880_gpio2_init_verbs }, | 3396 | alc880_gpio2_init_verbs }, |
3269 | .num_dacs = ARRAY_SIZE(alc880_dac_nids), | 3397 | .num_dacs = ARRAY_SIZE(alc880_dac_nids), |
3270 | .dac_nids = alc880_dac_nids, | 3398 | .dac_nids = alc880_dac_nids, |
3399 | .adc_nids = alc880_adc_nids_alt, /* FIXME: correct? */ | ||
3400 | .num_adc_nids = 1, /* single ADC */ | ||
3271 | .hp_nid = 0x03, | 3401 | .hp_nid = 0x03, |
3272 | .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), | 3402 | .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), |
3273 | .channel_mode = alc880_2_jack_modes, | 3403 | .channel_mode = alc880_2_jack_modes, |
@@ -3532,9 +3662,6 @@ static struct alc_config_preset alc880_presets[] = { | |||
3532 | * Automatic parse of I/O pins from the BIOS configuration | 3662 | * Automatic parse of I/O pins from the BIOS configuration |
3533 | */ | 3663 | */ |
3534 | 3664 | ||
3535 | #define NUM_CONTROL_ALLOC 32 | ||
3536 | #define NUM_VERB_ALLOC 32 | ||
3537 | |||
3538 | enum { | 3665 | enum { |
3539 | ALC_CTL_WIDGET_VOL, | 3666 | ALC_CTL_WIDGET_VOL, |
3540 | ALC_CTL_WIDGET_MUTE, | 3667 | ALC_CTL_WIDGET_MUTE, |
@@ -3552,29 +3679,15 @@ static int add_control(struct alc_spec *spec, int type, const char *name, | |||
3552 | { | 3679 | { |
3553 | struct snd_kcontrol_new *knew; | 3680 | struct snd_kcontrol_new *knew; |
3554 | 3681 | ||
3555 | if (spec->num_kctl_used >= spec->num_kctl_alloc) { | 3682 | snd_array_init(&spec->kctls, sizeof(*knew), 32); |
3556 | int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC; | 3683 | knew = snd_array_new(&spec->kctls); |
3557 | 3684 | if (!knew) | |
3558 | /* array + terminator */ | 3685 | 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]; | 3686 | *knew = alc880_control_templates[type]; |
3573 | knew->name = kstrdup(name, GFP_KERNEL); | 3687 | knew->name = kstrdup(name, GFP_KERNEL); |
3574 | if (!knew->name) | 3688 | if (!knew->name) |
3575 | return -ENOMEM; | 3689 | return -ENOMEM; |
3576 | knew->private_value = val; | 3690 | knew->private_value = val; |
3577 | spec->num_kctl_used++; | ||
3578 | return 0; | 3691 | return 0; |
3579 | } | 3692 | } |
3580 | 3693 | ||
@@ -3898,10 +4011,10 @@ static int alc880_parse_auto_config(struct hda_codec *codec) | |||
3898 | if (spec->autocfg.dig_in_pin) | 4011 | if (spec->autocfg.dig_in_pin) |
3899 | spec->dig_in_nid = ALC880_DIGIN_NID; | 4012 | spec->dig_in_nid = ALC880_DIGIN_NID; |
3900 | 4013 | ||
3901 | if (spec->kctl_alloc) | 4014 | if (spec->kctls.list) |
3902 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 4015 | add_mixer(spec, spec->kctls.list); |
3903 | 4016 | ||
3904 | spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs; | 4017 | add_verb(spec, alc880_volume_init_verbs); |
3905 | 4018 | ||
3906 | spec->num_mux_defs = 1; | 4019 | spec->num_mux_defs = 1; |
3907 | spec->input_mux = &spec->private_imux; | 4020 | spec->input_mux = &spec->private_imux; |
@@ -3925,6 +4038,17 @@ static void alc880_auto_init(struct hda_codec *codec) | |||
3925 | * OK, here we have finally the patch for ALC880 | 4038 | * OK, here we have finally the patch for ALC880 |
3926 | */ | 4039 | */ |
3927 | 4040 | ||
4041 | static void set_capture_mixer(struct alc_spec *spec) | ||
4042 | { | ||
4043 | static struct snd_kcontrol_new *caps[3] = { | ||
4044 | alc_capture_mixer1, | ||
4045 | alc_capture_mixer2, | ||
4046 | alc_capture_mixer3, | ||
4047 | }; | ||
4048 | if (spec->num_adc_nids > 0 && spec->num_adc_nids < 3) | ||
4049 | spec->cap_mixer = caps[spec->num_adc_nids - 1]; | ||
4050 | } | ||
4051 | |||
3928 | static int patch_alc880(struct hda_codec *codec) | 4052 | static int patch_alc880(struct hda_codec *codec) |
3929 | { | 4053 | { |
3930 | struct alc_spec *spec; | 4054 | struct alc_spec *spec; |
@@ -3980,16 +4104,12 @@ static int patch_alc880(struct hda_codec *codec) | |||
3980 | if (wcap != AC_WID_AUD_IN) { | 4104 | if (wcap != AC_WID_AUD_IN) { |
3981 | spec->adc_nids = alc880_adc_nids_alt; | 4105 | spec->adc_nids = alc880_adc_nids_alt; |
3982 | spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids_alt); | 4106 | 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 { | 4107 | } else { |
3987 | spec->adc_nids = alc880_adc_nids; | 4108 | spec->adc_nids = alc880_adc_nids; |
3988 | spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids); | 4109 | spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids); |
3989 | spec->mixers[spec->num_mixers] = alc880_capture_mixer; | ||
3990 | spec->num_mixers++; | ||
3991 | } | 4110 | } |
3992 | } | 4111 | } |
4112 | set_capture_mixer(spec); | ||
3993 | 4113 | ||
3994 | spec->vmaster_nid = 0x0c; | 4114 | spec->vmaster_nid = 0x0c; |
3995 | 4115 | ||
@@ -4024,11 +4144,6 @@ static hda_nid_t alc260_adc_nids_alt[1] = { | |||
4024 | 0x05, | 4144 | 0x05, |
4025 | }; | 4145 | }; |
4026 | 4146 | ||
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 | 4147 | /* NIDs used when simultaneous access to both ADCs makes sense. Note that |
4033 | * alc260_capture_mixer assumes ADC0 (nid 0x04) is the first ADC. | 4148 | * alc260_capture_mixer assumes ADC0 (nid 0x04) is the first ADC. |
4034 | */ | 4149 | */ |
@@ -4427,45 +4542,6 @@ static struct snd_kcontrol_new alc260_replacer_672v_mixer[] = { | |||
4427 | { } /* end */ | 4542 | { } /* end */ |
4428 | }; | 4543 | }; |
4429 | 4544 | ||
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 | /* | 4545 | /* |
4470 | * initialization verbs | 4546 | * initialization verbs |
4471 | */ | 4547 | */ |
@@ -5282,7 +5358,6 @@ static struct hda_verb alc260_volume_init_verbs[] = { | |||
5282 | static int alc260_parse_auto_config(struct hda_codec *codec) | 5358 | static int alc260_parse_auto_config(struct hda_codec *codec) |
5283 | { | 5359 | { |
5284 | struct alc_spec *spec = codec->spec; | 5360 | struct alc_spec *spec = codec->spec; |
5285 | unsigned int wcap; | ||
5286 | int err; | 5361 | int err; |
5287 | static hda_nid_t alc260_ignore[] = { 0x17, 0 }; | 5362 | static hda_nid_t alc260_ignore[] = { 0x17, 0 }; |
5288 | 5363 | ||
@@ -5293,7 +5368,7 @@ static int alc260_parse_auto_config(struct hda_codec *codec) | |||
5293 | err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg); | 5368 | err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg); |
5294 | if (err < 0) | 5369 | if (err < 0) |
5295 | return err; | 5370 | return err; |
5296 | if (!spec->kctl_alloc) | 5371 | if (!spec->kctls.list) |
5297 | return 0; /* can't find valid BIOS pin config */ | 5372 | return 0; /* can't find valid BIOS pin config */ |
5298 | err = alc260_auto_create_analog_input_ctls(spec, &spec->autocfg); | 5373 | err = alc260_auto_create_analog_input_ctls(spec, &spec->autocfg); |
5299 | if (err < 0) | 5374 | if (err < 0) |
@@ -5303,28 +5378,14 @@ static int alc260_parse_auto_config(struct hda_codec *codec) | |||
5303 | 5378 | ||
5304 | if (spec->autocfg.dig_out_pin) | 5379 | if (spec->autocfg.dig_out_pin) |
5305 | spec->multiout.dig_out_nid = ALC260_DIGOUT_NID; | 5380 | spec->multiout.dig_out_nid = ALC260_DIGOUT_NID; |
5306 | if (spec->kctl_alloc) | 5381 | if (spec->kctls.list) |
5307 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 5382 | add_mixer(spec, spec->kctls.list); |
5308 | 5383 | ||
5309 | spec->init_verbs[spec->num_init_verbs++] = alc260_volume_init_verbs; | 5384 | add_verb(spec, alc260_volume_init_verbs); |
5310 | 5385 | ||
5311 | spec->num_mux_defs = 1; | 5386 | spec->num_mux_defs = 1; |
5312 | spec->input_mux = &spec->private_imux; | 5387 | spec->input_mux = &spec->private_imux; |
5313 | 5388 | ||
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); | 5389 | store_pin_configs(codec); |
5329 | return 1; | 5390 | return 1; |
5330 | } | 5391 | } |
@@ -5394,12 +5455,11 @@ static struct alc_config_preset alc260_presets[] = { | |||
5394 | [ALC260_BASIC] = { | 5455 | [ALC260_BASIC] = { |
5395 | .mixers = { alc260_base_output_mixer, | 5456 | .mixers = { alc260_base_output_mixer, |
5396 | alc260_input_mixer, | 5457 | alc260_input_mixer, |
5397 | alc260_pc_beep_mixer, | 5458 | alc260_pc_beep_mixer }, |
5398 | alc260_capture_mixer }, | ||
5399 | .init_verbs = { alc260_init_verbs }, | 5459 | .init_verbs = { alc260_init_verbs }, |
5400 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), | 5460 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), |
5401 | .dac_nids = alc260_dac_nids, | 5461 | .dac_nids = alc260_dac_nids, |
5402 | .num_adc_nids = ARRAY_SIZE(alc260_adc_nids), | 5462 | .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids), |
5403 | .adc_nids = alc260_adc_nids, | 5463 | .adc_nids = alc260_adc_nids, |
5404 | .num_channel_mode = ARRAY_SIZE(alc260_modes), | 5464 | .num_channel_mode = ARRAY_SIZE(alc260_modes), |
5405 | .channel_mode = alc260_modes, | 5465 | .channel_mode = alc260_modes, |
@@ -5407,14 +5467,13 @@ static struct alc_config_preset alc260_presets[] = { | |||
5407 | }, | 5467 | }, |
5408 | [ALC260_HP] = { | 5468 | [ALC260_HP] = { |
5409 | .mixers = { alc260_hp_output_mixer, | 5469 | .mixers = { alc260_hp_output_mixer, |
5410 | alc260_input_mixer, | 5470 | alc260_input_mixer }, |
5411 | alc260_capture_alt_mixer }, | ||
5412 | .init_verbs = { alc260_init_verbs, | 5471 | .init_verbs = { alc260_init_verbs, |
5413 | alc260_hp_unsol_verbs }, | 5472 | alc260_hp_unsol_verbs }, |
5414 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), | 5473 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), |
5415 | .dac_nids = alc260_dac_nids, | 5474 | .dac_nids = alc260_dac_nids, |
5416 | .num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids), | 5475 | .num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt), |
5417 | .adc_nids = alc260_hp_adc_nids, | 5476 | .adc_nids = alc260_adc_nids_alt, |
5418 | .num_channel_mode = ARRAY_SIZE(alc260_modes), | 5477 | .num_channel_mode = ARRAY_SIZE(alc260_modes), |
5419 | .channel_mode = alc260_modes, | 5478 | .channel_mode = alc260_modes, |
5420 | .input_mux = &alc260_capture_source, | 5479 | .input_mux = &alc260_capture_source, |
@@ -5423,14 +5482,13 @@ static struct alc_config_preset alc260_presets[] = { | |||
5423 | }, | 5482 | }, |
5424 | [ALC260_HP_DC7600] = { | 5483 | [ALC260_HP_DC7600] = { |
5425 | .mixers = { alc260_hp_dc7600_mixer, | 5484 | .mixers = { alc260_hp_dc7600_mixer, |
5426 | alc260_input_mixer, | 5485 | alc260_input_mixer }, |
5427 | alc260_capture_alt_mixer }, | ||
5428 | .init_verbs = { alc260_init_verbs, | 5486 | .init_verbs = { alc260_init_verbs, |
5429 | alc260_hp_dc7600_verbs }, | 5487 | alc260_hp_dc7600_verbs }, |
5430 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), | 5488 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), |
5431 | .dac_nids = alc260_dac_nids, | 5489 | .dac_nids = alc260_dac_nids, |
5432 | .num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids), | 5490 | .num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt), |
5433 | .adc_nids = alc260_hp_adc_nids, | 5491 | .adc_nids = alc260_adc_nids_alt, |
5434 | .num_channel_mode = ARRAY_SIZE(alc260_modes), | 5492 | .num_channel_mode = ARRAY_SIZE(alc260_modes), |
5435 | .channel_mode = alc260_modes, | 5493 | .channel_mode = alc260_modes, |
5436 | .input_mux = &alc260_capture_source, | 5494 | .input_mux = &alc260_capture_source, |
@@ -5439,14 +5497,13 @@ static struct alc_config_preset alc260_presets[] = { | |||
5439 | }, | 5497 | }, |
5440 | [ALC260_HP_3013] = { | 5498 | [ALC260_HP_3013] = { |
5441 | .mixers = { alc260_hp_3013_mixer, | 5499 | .mixers = { alc260_hp_3013_mixer, |
5442 | alc260_input_mixer, | 5500 | alc260_input_mixer }, |
5443 | alc260_capture_alt_mixer }, | ||
5444 | .init_verbs = { alc260_hp_3013_init_verbs, | 5501 | .init_verbs = { alc260_hp_3013_init_verbs, |
5445 | alc260_hp_3013_unsol_verbs }, | 5502 | alc260_hp_3013_unsol_verbs }, |
5446 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), | 5503 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), |
5447 | .dac_nids = alc260_dac_nids, | 5504 | .dac_nids = alc260_dac_nids, |
5448 | .num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids), | 5505 | .num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt), |
5449 | .adc_nids = alc260_hp_adc_nids, | 5506 | .adc_nids = alc260_adc_nids_alt, |
5450 | .num_channel_mode = ARRAY_SIZE(alc260_modes), | 5507 | .num_channel_mode = ARRAY_SIZE(alc260_modes), |
5451 | .channel_mode = alc260_modes, | 5508 | .channel_mode = alc260_modes, |
5452 | .input_mux = &alc260_capture_source, | 5509 | .input_mux = &alc260_capture_source, |
@@ -5454,8 +5511,7 @@ static struct alc_config_preset alc260_presets[] = { | |||
5454 | .init_hook = alc260_hp_3013_automute, | 5511 | .init_hook = alc260_hp_3013_automute, |
5455 | }, | 5512 | }, |
5456 | [ALC260_FUJITSU_S702X] = { | 5513 | [ALC260_FUJITSU_S702X] = { |
5457 | .mixers = { alc260_fujitsu_mixer, | 5514 | .mixers = { alc260_fujitsu_mixer }, |
5458 | alc260_capture_mixer }, | ||
5459 | .init_verbs = { alc260_fujitsu_init_verbs }, | 5515 | .init_verbs = { alc260_fujitsu_init_verbs }, |
5460 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), | 5516 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), |
5461 | .dac_nids = alc260_dac_nids, | 5517 | .dac_nids = alc260_dac_nids, |
@@ -5467,8 +5523,7 @@ static struct alc_config_preset alc260_presets[] = { | |||
5467 | .input_mux = alc260_fujitsu_capture_sources, | 5523 | .input_mux = alc260_fujitsu_capture_sources, |
5468 | }, | 5524 | }, |
5469 | [ALC260_ACER] = { | 5525 | [ALC260_ACER] = { |
5470 | .mixers = { alc260_acer_mixer, | 5526 | .mixers = { alc260_acer_mixer }, |
5471 | alc260_capture_mixer }, | ||
5472 | .init_verbs = { alc260_acer_init_verbs }, | 5527 | .init_verbs = { alc260_acer_init_verbs }, |
5473 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), | 5528 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), |
5474 | .dac_nids = alc260_dac_nids, | 5529 | .dac_nids = alc260_dac_nids, |
@@ -5480,8 +5535,7 @@ static struct alc_config_preset alc260_presets[] = { | |||
5480 | .input_mux = alc260_acer_capture_sources, | 5535 | .input_mux = alc260_acer_capture_sources, |
5481 | }, | 5536 | }, |
5482 | [ALC260_WILL] = { | 5537 | [ALC260_WILL] = { |
5483 | .mixers = { alc260_will_mixer, | 5538 | .mixers = { alc260_will_mixer }, |
5484 | alc260_capture_mixer }, | ||
5485 | .init_verbs = { alc260_init_verbs, alc260_will_verbs }, | 5539 | .init_verbs = { alc260_init_verbs, alc260_will_verbs }, |
5486 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), | 5540 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), |
5487 | .dac_nids = alc260_dac_nids, | 5541 | .dac_nids = alc260_dac_nids, |
@@ -5493,8 +5547,7 @@ static struct alc_config_preset alc260_presets[] = { | |||
5493 | .input_mux = &alc260_capture_source, | 5547 | .input_mux = &alc260_capture_source, |
5494 | }, | 5548 | }, |
5495 | [ALC260_REPLACER_672V] = { | 5549 | [ALC260_REPLACER_672V] = { |
5496 | .mixers = { alc260_replacer_672v_mixer, | 5550 | .mixers = { alc260_replacer_672v_mixer }, |
5497 | alc260_capture_mixer }, | ||
5498 | .init_verbs = { alc260_init_verbs, alc260_replacer_672v_verbs }, | 5551 | .init_verbs = { alc260_init_verbs, alc260_replacer_672v_verbs }, |
5499 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), | 5552 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), |
5500 | .dac_nids = alc260_dac_nids, | 5553 | .dac_nids = alc260_dac_nids, |
@@ -5509,8 +5562,7 @@ static struct alc_config_preset alc260_presets[] = { | |||
5509 | }, | 5562 | }, |
5510 | #ifdef CONFIG_SND_DEBUG | 5563 | #ifdef CONFIG_SND_DEBUG |
5511 | [ALC260_TEST] = { | 5564 | [ALC260_TEST] = { |
5512 | .mixers = { alc260_test_mixer, | 5565 | .mixers = { alc260_test_mixer }, |
5513 | alc260_capture_mixer }, | ||
5514 | .init_verbs = { alc260_test_init_verbs }, | 5566 | .init_verbs = { alc260_test_init_verbs }, |
5515 | .num_dacs = ARRAY_SIZE(alc260_test_dac_nids), | 5567 | .num_dacs = ARRAY_SIZE(alc260_test_dac_nids), |
5516 | .dac_nids = alc260_test_dac_nids, | 5568 | .dac_nids = alc260_test_dac_nids, |
@@ -5569,6 +5621,21 @@ static int patch_alc260(struct hda_codec *codec) | |||
5569 | spec->stream_digital_playback = &alc260_pcm_digital_playback; | 5621 | spec->stream_digital_playback = &alc260_pcm_digital_playback; |
5570 | spec->stream_digital_capture = &alc260_pcm_digital_capture; | 5622 | spec->stream_digital_capture = &alc260_pcm_digital_capture; |
5571 | 5623 | ||
5624 | if (!spec->adc_nids && spec->input_mux) { | ||
5625 | /* check whether NID 0x04 is valid */ | ||
5626 | unsigned int wcap = get_wcaps(codec, 0x04); | ||
5627 | wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; | ||
5628 | /* get type */ | ||
5629 | if (wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) { | ||
5630 | spec->adc_nids = alc260_adc_nids_alt; | ||
5631 | spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt); | ||
5632 | } else { | ||
5633 | spec->adc_nids = alc260_adc_nids; | ||
5634 | spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids); | ||
5635 | } | ||
5636 | } | ||
5637 | set_capture_mixer(spec); | ||
5638 | |||
5572 | spec->vmaster_nid = 0x08; | 5639 | spec->vmaster_nid = 0x08; |
5573 | 5640 | ||
5574 | codec->patch_ops = alc_patch_ops; | 5641 | codec->patch_ops = alc_patch_ops; |
@@ -5625,36 +5692,6 @@ static struct hda_input_mux alc882_capture_source = { | |||
5625 | { "CD", 0x4 }, | 5692 | { "CD", 0x4 }, |
5626 | }, | 5693 | }, |
5627 | }; | 5694 | }; |
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 | /* | 5695 | /* |
5659 | * 2ch mode | 5696 | * 2ch mode |
5660 | */ | 5697 | */ |
@@ -6337,49 +6374,6 @@ static struct hda_verb alc882_auto_init_verbs[] = { | |||
6337 | { } | 6374 | { } |
6338 | }; | 6375 | }; |
6339 | 6376 | ||
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 | 6377 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
6384 | #define alc882_loopbacks alc880_loopbacks | 6378 | #define alc882_loopbacks alc880_loopbacks |
6385 | #endif | 6379 | #endif |
@@ -6508,8 +6502,7 @@ static struct alc_config_preset alc882_presets[] = { | |||
6508 | .init_hook = alc885_imac24_init_hook, | 6502 | .init_hook = alc885_imac24_init_hook, |
6509 | }, | 6503 | }, |
6510 | [ALC882_TARGA] = { | 6504 | [ALC882_TARGA] = { |
6511 | .mixers = { alc882_targa_mixer, alc882_chmode_mixer, | 6505 | .mixers = { alc882_targa_mixer, alc882_chmode_mixer }, |
6512 | alc882_capture_mixer }, | ||
6513 | .init_verbs = { alc882_init_verbs, alc882_targa_verbs}, | 6506 | .init_verbs = { alc882_init_verbs, alc882_targa_verbs}, |
6514 | .num_dacs = ARRAY_SIZE(alc882_dac_nids), | 6507 | .num_dacs = ARRAY_SIZE(alc882_dac_nids), |
6515 | .dac_nids = alc882_dac_nids, | 6508 | .dac_nids = alc882_dac_nids, |
@@ -6525,8 +6518,7 @@ static struct alc_config_preset alc882_presets[] = { | |||
6525 | .init_hook = alc882_targa_automute, | 6518 | .init_hook = alc882_targa_automute, |
6526 | }, | 6519 | }, |
6527 | [ALC882_ASUS_A7J] = { | 6520 | [ALC882_ASUS_A7J] = { |
6528 | .mixers = { alc882_asus_a7j_mixer, alc882_chmode_mixer, | 6521 | .mixers = { alc882_asus_a7j_mixer, alc882_chmode_mixer }, |
6529 | alc882_capture_mixer }, | ||
6530 | .init_verbs = { alc882_init_verbs, alc882_asus_a7j_verbs}, | 6522 | .init_verbs = { alc882_init_verbs, alc882_asus_a7j_verbs}, |
6531 | .num_dacs = ARRAY_SIZE(alc882_dac_nids), | 6523 | .num_dacs = ARRAY_SIZE(alc882_dac_nids), |
6532 | .dac_nids = alc882_dac_nids, | 6524 | .dac_nids = alc882_dac_nids, |
@@ -6831,6 +6823,7 @@ static int patch_alc882(struct hda_codec *codec) | |||
6831 | spec->stream_digital_playback = &alc882_pcm_digital_playback; | 6823 | spec->stream_digital_playback = &alc882_pcm_digital_playback; |
6832 | spec->stream_digital_capture = &alc882_pcm_digital_capture; | 6824 | spec->stream_digital_capture = &alc882_pcm_digital_capture; |
6833 | 6825 | ||
6826 | spec->is_mix_capture = 1; /* matrix-style capture */ | ||
6834 | if (!spec->adc_nids && spec->input_mux) { | 6827 | if (!spec->adc_nids && spec->input_mux) { |
6835 | /* check whether NID 0x07 is valid */ | 6828 | /* check whether NID 0x07 is valid */ |
6836 | unsigned int wcap = get_wcaps(codec, 0x07); | 6829 | unsigned int wcap = get_wcaps(codec, 0x07); |
@@ -6840,17 +6833,13 @@ static int patch_alc882(struct hda_codec *codec) | |||
6840 | spec->adc_nids = alc882_adc_nids_alt; | 6833 | spec->adc_nids = alc882_adc_nids_alt; |
6841 | spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids_alt); | 6834 | spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids_alt); |
6842 | spec->capsrc_nids = alc882_capsrc_nids_alt; | 6835 | spec->capsrc_nids = alc882_capsrc_nids_alt; |
6843 | spec->mixers[spec->num_mixers] = | ||
6844 | alc882_capture_alt_mixer; | ||
6845 | spec->num_mixers++; | ||
6846 | } else { | 6836 | } else { |
6847 | spec->adc_nids = alc882_adc_nids; | 6837 | spec->adc_nids = alc882_adc_nids; |
6848 | spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids); | 6838 | spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids); |
6849 | spec->capsrc_nids = alc882_capsrc_nids; | 6839 | spec->capsrc_nids = alc882_capsrc_nids; |
6850 | spec->mixers[spec->num_mixers] = alc882_capture_mixer; | ||
6851 | spec->num_mixers++; | ||
6852 | } | 6840 | } |
6853 | } | 6841 | } |
6842 | set_capture_mixer(spec); | ||
6854 | 6843 | ||
6855 | spec->vmaster_nid = 0x0c; | 6844 | spec->vmaster_nid = 0x0c; |
6856 | 6845 | ||
@@ -6889,6 +6878,11 @@ static hda_nid_t alc883_adc_nids[2] = { | |||
6889 | 0x08, 0x09, | 6878 | 0x08, 0x09, |
6890 | }; | 6879 | }; |
6891 | 6880 | ||
6881 | static hda_nid_t alc883_adc_nids_alt[1] = { | ||
6882 | /* ADC1 */ | ||
6883 | 0x08, | ||
6884 | }; | ||
6885 | |||
6892 | static hda_nid_t alc883_capsrc_nids[2] = { 0x23, 0x22 }; | 6886 | static hda_nid_t alc883_capsrc_nids[2] = { 0x23, 0x22 }; |
6893 | 6887 | ||
6894 | /* input MUX */ | 6888 | /* input MUX */ |
@@ -6957,11 +6951,6 @@ static struct hda_input_mux alc883_asus_eee1601_capture_source = { | |||
6957 | }, | 6951 | }, |
6958 | }; | 6952 | }; |
6959 | 6953 | ||
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 | /* | 6954 | /* |
6966 | * 2ch mode | 6955 | * 2ch mode |
6967 | */ | 6956 | */ |
@@ -7115,19 +7104,6 @@ static struct snd_kcontrol_new alc883_base_mixer[] = { | |||
7115 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 7104 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
7116 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | 7105 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), |
7117 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | 7106 | 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 */ | 7107 | { } /* end */ |
7132 | }; | 7108 | }; |
7133 | 7109 | ||
@@ -7145,19 +7121,6 @@ static struct snd_kcontrol_new alc883_mitac_mixer[] = { | |||
7145 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 7121 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
7146 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | 7122 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), |
7147 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 7123 | 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 */ | 7124 | { } /* end */ |
7162 | }; | 7125 | }; |
7163 | 7126 | ||
@@ -7172,19 +7135,6 @@ static struct snd_kcontrol_new alc883_clevo_m720_mixer[] = { | |||
7172 | HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 7135 | HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
7173 | HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT), | 7136 | HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT), |
7174 | HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 7137 | 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 */ | 7138 | { } /* end */ |
7189 | }; | 7139 | }; |
7190 | 7140 | ||
@@ -7199,19 +7149,6 @@ static struct snd_kcontrol_new alc883_2ch_fujitsu_pi2515_mixer[] = { | |||
7199 | HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 7149 | HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
7200 | HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT), | 7150 | HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT), |
7201 | HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 7151 | 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 */ | 7152 | { } /* end */ |
7216 | }; | 7153 | }; |
7217 | 7154 | ||
@@ -7231,19 +7168,6 @@ static struct snd_kcontrol_new alc883_3ST_2ch_mixer[] = { | |||
7231 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 7168 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
7232 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | 7169 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), |
7233 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | 7170 | 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 */ | 7171 | { } /* end */ |
7248 | }; | 7172 | }; |
7249 | 7173 | ||
@@ -7269,17 +7193,6 @@ static struct snd_kcontrol_new alc883_3ST_6ch_mixer[] = { | |||
7269 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 7193 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
7270 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | 7194 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), |
7271 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | 7195 | 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 */ | 7196 | { } /* end */ |
7284 | }; | 7197 | }; |
7285 | 7198 | ||
@@ -7306,19 +7219,6 @@ static struct snd_kcontrol_new alc883_3ST_6ch_intel_mixer[] = { | |||
7306 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 7219 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
7307 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | 7220 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), |
7308 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | 7221 | 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 */ | 7222 | { } /* end */ |
7323 | }; | 7223 | }; |
7324 | 7224 | ||
@@ -7344,18 +7244,6 @@ static struct snd_kcontrol_new alc883_fivestack_mixer[] = { | |||
7344 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 7244 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
7345 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | 7245 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), |
7346 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | 7246 | 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 */ | 7247 | { } /* end */ |
7360 | }; | 7248 | }; |
7361 | 7249 | ||
@@ -7376,19 +7264,6 @@ static struct snd_kcontrol_new alc883_tagra_mixer[] = { | |||
7376 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 7264 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
7377 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 7265 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), |
7378 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 7266 | 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 */ | 7267 | { } /* end */ |
7393 | }; | 7268 | }; |
7394 | 7269 | ||
@@ -7404,19 +7279,6 @@ static struct snd_kcontrol_new alc883_tagra_2ch_mixer[] = { | |||
7404 | HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 7279 | HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
7405 | HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT), | 7280 | HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT), |
7406 | HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 7281 | 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 */ | 7282 | { } /* end */ |
7421 | }; | 7283 | }; |
7422 | 7284 | ||
@@ -7429,17 +7291,6 @@ static struct snd_kcontrol_new alc883_lenovo_101e_2ch_mixer[] = { | |||
7429 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 7291 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
7430 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 7292 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), |
7431 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 7293 | 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 */ | 7294 | { } /* end */ |
7444 | }; | 7295 | }; |
7445 | 7296 | ||
@@ -7453,19 +7304,6 @@ static struct snd_kcontrol_new alc883_lenovo_nb0763_mixer[] = { | |||
7453 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 7304 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
7454 | HDA_CODEC_VOLUME("iMic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 7305 | HDA_CODEC_VOLUME("iMic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
7455 | HDA_CODEC_MUTE("iMic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 7306 | 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 */ | 7307 | { } /* end */ |
7470 | }; | 7308 | }; |
7471 | 7309 | ||
@@ -7479,19 +7317,6 @@ static struct snd_kcontrol_new alc883_medion_md2_mixer[] = { | |||
7479 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 7317 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
7480 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | 7318 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), |
7481 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | 7319 | 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 */ | 7320 | { } /* end */ |
7496 | }; | 7321 | }; |
7497 | 7322 | ||
@@ -7504,19 +7329,6 @@ static struct snd_kcontrol_new alc883_acer_aspire_mixer[] = { | |||
7504 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 7329 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
7505 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 7330 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), |
7506 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 7331 | 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 */ | 7332 | { } /* end */ |
7521 | }; | 7333 | }; |
7522 | 7334 | ||
@@ -7544,19 +7356,6 @@ static struct snd_kcontrol_new alc888_lenovo_sky_mixer[] = { | |||
7544 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 7356 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
7545 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | 7357 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), |
7546 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 7358 | 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 */ | 7359 | { } /* end */ |
7561 | }; | 7360 | }; |
7562 | 7361 | ||
@@ -7587,6 +7386,10 @@ static struct snd_kcontrol_new alc883_asus_eee1601_mixer[] = { | |||
7587 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 7386 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
7588 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 7387 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), |
7589 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 7388 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
7389 | { } /* end */ | ||
7390 | }; | ||
7391 | |||
7392 | static struct snd_kcontrol_new alc883_asus_eee1601_cap_mixer[] = { | ||
7590 | HDA_BIND_VOL("Capture Volume", &alc883_bind_cap_vol), | 7393 | HDA_BIND_VOL("Capture Volume", &alc883_bind_cap_vol), |
7591 | HDA_BIND_SW("Capture Switch", &alc883_bind_cap_switch), | 7394 | HDA_BIND_SW("Capture Switch", &alc883_bind_cap_switch), |
7592 | { | 7395 | { |
@@ -7594,9 +7397,9 @@ static struct snd_kcontrol_new alc883_asus_eee1601_mixer[] = { | |||
7594 | /* .name = "Capture Source", */ | 7397 | /* .name = "Capture Source", */ |
7595 | .name = "Input Source", | 7398 | .name = "Input Source", |
7596 | .count = 1, | 7399 | .count = 1, |
7597 | .info = alc883_mux_enum_info, | 7400 | .info = alc_mux_enum_info, |
7598 | .get = alc883_mux_enum_get, | 7401 | .get = alc_mux_enum_get, |
7599 | .put = alc883_mux_enum_put, | 7402 | .put = alc_mux_enum_put, |
7600 | }, | 7403 | }, |
7601 | { } /* end */ | 7404 | { } /* end */ |
7602 | }; | 7405 | }; |
@@ -8251,27 +8054,6 @@ static struct hda_verb alc883_auto_init_verbs[] = { | |||
8251 | { } | 8054 | { } |
8252 | }; | 8055 | }; |
8253 | 8056 | ||
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[] = { | 8057 | static struct hda_verb alc888_asus_m90v_verbs[] = { |
8276 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | 8058 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
8277 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | 8059 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
@@ -8553,6 +8335,8 @@ static struct alc_config_preset alc883_presets[] = { | |||
8553 | .init_verbs = { alc883_init_verbs, alc883_tagra_verbs}, | 8335 | .init_verbs = { alc883_init_verbs, alc883_tagra_verbs}, |
8554 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), | 8336 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), |
8555 | .dac_nids = alc883_dac_nids, | 8337 | .dac_nids = alc883_dac_nids, |
8338 | .adc_nids = alc883_adc_nids_alt, | ||
8339 | .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt), | ||
8556 | .dig_out_nid = ALC883_DIGOUT_NID, | 8340 | .dig_out_nid = ALC883_DIGOUT_NID, |
8557 | .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), | 8341 | .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), |
8558 | .channel_mode = alc883_3ST_2ch_modes, | 8342 | .channel_mode = alc883_3ST_2ch_modes, |
@@ -8593,6 +8377,8 @@ static struct alc_config_preset alc883_presets[] = { | |||
8593 | alc883_medion_eapd_verbs }, | 8377 | alc883_medion_eapd_verbs }, |
8594 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), | 8378 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), |
8595 | .dac_nids = alc883_dac_nids, | 8379 | .dac_nids = alc883_dac_nids, |
8380 | .adc_nids = alc883_adc_nids_alt, | ||
8381 | .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt), | ||
8596 | .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes), | 8382 | .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes), |
8597 | .channel_mode = alc883_sixstack_modes, | 8383 | .channel_mode = alc883_sixstack_modes, |
8598 | .input_mux = &alc883_capture_source, | 8384 | .input_mux = &alc883_capture_source, |
@@ -8635,6 +8421,8 @@ static struct alc_config_preset alc883_presets[] = { | |||
8635 | .init_verbs = { alc883_init_verbs, alc883_lenovo_101e_verbs}, | 8421 | .init_verbs = { alc883_init_verbs, alc883_lenovo_101e_verbs}, |
8636 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), | 8422 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), |
8637 | .dac_nids = alc883_dac_nids, | 8423 | .dac_nids = alc883_dac_nids, |
8424 | .adc_nids = alc883_adc_nids_alt, | ||
8425 | .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt), | ||
8638 | .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), | 8426 | .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), |
8639 | .channel_mode = alc883_3ST_2ch_modes, | 8427 | .channel_mode = alc883_3ST_2ch_modes, |
8640 | .input_mux = &alc883_lenovo_101e_capture_source, | 8428 | .input_mux = &alc883_lenovo_101e_capture_source, |
@@ -8731,8 +8519,6 @@ static struct alc_config_preset alc883_presets[] = { | |||
8731 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), | 8519 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), |
8732 | .dac_nids = alc883_dac_nids, | 8520 | .dac_nids = alc883_dac_nids, |
8733 | .dig_out_nid = ALC883_DIGOUT_NID, | 8521 | .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), | 8522 | .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes), |
8737 | .channel_mode = alc883_sixstack_modes, | 8523 | .channel_mode = alc883_sixstack_modes, |
8738 | .need_dac_fix = 1, | 8524 | .need_dac_fix = 1, |
@@ -8756,6 +8542,7 @@ static struct alc_config_preset alc883_presets[] = { | |||
8756 | }, | 8542 | }, |
8757 | [ALC888_ASUS_EEE1601] = { | 8543 | [ALC888_ASUS_EEE1601] = { |
8758 | .mixers = { alc883_asus_eee1601_mixer }, | 8544 | .mixers = { alc883_asus_eee1601_mixer }, |
8545 | .cap_mixer = alc883_asus_eee1601_cap_mixer, | ||
8759 | .init_verbs = { alc883_init_verbs, alc888_asus_eee1601_verbs }, | 8546 | .init_verbs = { alc883_init_verbs, alc888_asus_eee1601_verbs }, |
8760 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), | 8547 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), |
8761 | .dac_nids = alc883_dac_nids, | 8548 | .dac_nids = alc883_dac_nids, |
@@ -8862,8 +8649,6 @@ static int alc883_parse_auto_config(struct hda_codec *codec) | |||
8862 | 8649 | ||
8863 | /* hack - override the init verbs */ | 8650 | /* hack - override the init verbs */ |
8864 | spec->init_verbs[0] = alc883_auto_init_verbs; | 8651 | spec->init_verbs[0] = alc883_auto_init_verbs; |
8865 | spec->mixers[spec->num_mixers] = alc883_capture_mixer; | ||
8866 | spec->num_mixers++; | ||
8867 | 8652 | ||
8868 | return 1; /* config found */ | 8653 | return 1; /* config found */ |
8869 | } | 8654 | } |
@@ -8946,9 +8731,15 @@ static int patch_alc883(struct hda_codec *codec) | |||
8946 | spec->stream_digital_playback = &alc883_pcm_digital_playback; | 8731 | spec->stream_digital_playback = &alc883_pcm_digital_playback; |
8947 | spec->stream_digital_capture = &alc883_pcm_digital_capture; | 8732 | spec->stream_digital_capture = &alc883_pcm_digital_capture; |
8948 | 8733 | ||
8949 | spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids); | 8734 | if (!spec->num_adc_nids) { |
8950 | spec->adc_nids = alc883_adc_nids; | 8735 | spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids); |
8951 | spec->capsrc_nids = alc883_capsrc_nids; | 8736 | spec->adc_nids = alc883_adc_nids; |
8737 | } | ||
8738 | if (!spec->capsrc_nids) | ||
8739 | spec->capsrc_nids = alc883_capsrc_nids; | ||
8740 | spec->is_mix_capture = 1; /* matrix-style capture */ | ||
8741 | if (!spec->cap_mixer) | ||
8742 | set_capture_mixer(spec); | ||
8952 | 8743 | ||
8953 | spec->vmaster_nid = 0x0c; | 8744 | spec->vmaster_nid = 0x0c; |
8954 | 8745 | ||
@@ -9439,20 +9230,6 @@ static struct snd_kcontrol_new alc262_toshiba_s06_mixer[] = { | |||
9439 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), | 9230 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), |
9440 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 9231 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
9441 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 9232 | 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 */ | 9233 | { } /* end */ |
9457 | }; | 9234 | }; |
9458 | 9235 | ||
@@ -9969,7 +9746,7 @@ static int alc262_ultra_mux_enum_put(struct snd_kcontrol *kcontrol, | |||
9969 | struct alc_spec *spec = codec->spec; | 9746 | struct alc_spec *spec = codec->spec; |
9970 | int ret; | 9747 | int ret; |
9971 | 9748 | ||
9972 | ret = alc882_mux_enum_put(kcontrol, ucontrol); | 9749 | ret = alc_mux_enum_put(kcontrol, ucontrol); |
9973 | if (!ret) | 9750 | if (!ret) |
9974 | return 0; | 9751 | return 0; |
9975 | /* reprogram the HP pin as mic or HP according to the input source */ | 9752 | /* reprogram the HP pin as mic or HP according to the input source */ |
@@ -9986,8 +9763,8 @@ static struct snd_kcontrol_new alc262_ultra_capture_mixer[] = { | |||
9986 | { | 9763 | { |
9987 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 9764 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
9988 | .name = "Capture Source", | 9765 | .name = "Capture Source", |
9989 | .info = alc882_mux_enum_info, | 9766 | .info = alc_mux_enum_info, |
9990 | .get = alc882_mux_enum_get, | 9767 | .get = alc_mux_enum_get, |
9991 | .put = alc262_ultra_mux_enum_put, | 9768 | .put = alc262_ultra_mux_enum_put, |
9992 | }, | 9769 | }, |
9993 | { } /* end */ | 9770 | { } /* end */ |
@@ -10380,10 +10157,10 @@ static int alc262_parse_auto_config(struct hda_codec *codec) | |||
10380 | if (spec->autocfg.dig_in_pin) | 10157 | if (spec->autocfg.dig_in_pin) |
10381 | spec->dig_in_nid = ALC262_DIGIN_NID; | 10158 | spec->dig_in_nid = ALC262_DIGIN_NID; |
10382 | 10159 | ||
10383 | if (spec->kctl_alloc) | 10160 | if (spec->kctls.list) |
10384 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 10161 | add_mixer(spec, spec->kctls.list); |
10385 | 10162 | ||
10386 | spec->init_verbs[spec->num_init_verbs++] = alc262_volume_init_verbs; | 10163 | add_verb(spec, alc262_volume_init_verbs); |
10387 | spec->num_mux_defs = 1; | 10164 | spec->num_mux_defs = 1; |
10388 | spec->input_mux = &spec->private_imux; | 10165 | spec->input_mux = &spec->private_imux; |
10389 | 10166 | ||
@@ -10624,7 +10401,8 @@ static struct alc_config_preset alc262_presets[] = { | |||
10624 | .init_hook = alc262_hippo_automute, | 10401 | .init_hook = alc262_hippo_automute, |
10625 | }, | 10402 | }, |
10626 | [ALC262_ULTRA] = { | 10403 | [ALC262_ULTRA] = { |
10627 | .mixers = { alc262_ultra_mixer, alc262_ultra_capture_mixer }, | 10404 | .mixers = { alc262_ultra_mixer }, |
10405 | .cap_mixer = alc262_ultra_capture_mixer, | ||
10628 | .init_verbs = { alc262_ultra_verbs }, | 10406 | .init_verbs = { alc262_ultra_verbs }, |
10629 | .num_dacs = ARRAY_SIZE(alc262_dac_nids), | 10407 | .num_dacs = ARRAY_SIZE(alc262_dac_nids), |
10630 | .dac_nids = alc262_dac_nids, | 10408 | .dac_nids = alc262_dac_nids, |
@@ -10750,6 +10528,7 @@ static int patch_alc262(struct hda_codec *codec) | |||
10750 | spec->stream_digital_playback = &alc262_pcm_digital_playback; | 10528 | spec->stream_digital_playback = &alc262_pcm_digital_playback; |
10751 | spec->stream_digital_capture = &alc262_pcm_digital_capture; | 10529 | spec->stream_digital_capture = &alc262_pcm_digital_capture; |
10752 | 10530 | ||
10531 | spec->is_mix_capture = 1; | ||
10753 | if (!spec->adc_nids && spec->input_mux) { | 10532 | if (!spec->adc_nids && spec->input_mux) { |
10754 | /* check whether NID 0x07 is valid */ | 10533 | /* check whether NID 0x07 is valid */ |
10755 | unsigned int wcap = get_wcaps(codec, 0x07); | 10534 | unsigned int wcap = get_wcaps(codec, 0x07); |
@@ -10760,17 +10539,14 @@ static int patch_alc262(struct hda_codec *codec) | |||
10760 | spec->adc_nids = alc262_adc_nids_alt; | 10539 | spec->adc_nids = alc262_adc_nids_alt; |
10761 | spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids_alt); | 10540 | spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids_alt); |
10762 | spec->capsrc_nids = alc262_capsrc_nids_alt; | 10541 | spec->capsrc_nids = alc262_capsrc_nids_alt; |
10763 | spec->mixers[spec->num_mixers] = | ||
10764 | alc262_capture_alt_mixer; | ||
10765 | spec->num_mixers++; | ||
10766 | } else { | 10542 | } else { |
10767 | spec->adc_nids = alc262_adc_nids; | 10543 | spec->adc_nids = alc262_adc_nids; |
10768 | spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids); | 10544 | spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids); |
10769 | spec->capsrc_nids = alc262_capsrc_nids; | 10545 | spec->capsrc_nids = alc262_capsrc_nids; |
10770 | spec->mixers[spec->num_mixers] = alc262_capture_mixer; | ||
10771 | spec->num_mixers++; | ||
10772 | } | 10546 | } |
10773 | } | 10547 | } |
10548 | if (!spec->cap_mixer) | ||
10549 | set_capture_mixer(spec); | ||
10774 | 10550 | ||
10775 | spec->vmaster_nid = 0x0c; | 10551 | spec->vmaster_nid = 0x0c; |
10776 | 10552 | ||
@@ -10942,6 +10718,22 @@ static struct snd_kcontrol_new alc268_acer_mixer[] = { | |||
10942 | { } | 10718 | { } |
10943 | }; | 10719 | }; |
10944 | 10720 | ||
10721 | static struct snd_kcontrol_new alc268_acer_dmic_mixer[] = { | ||
10722 | /* output mixer control */ | ||
10723 | HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol), | ||
10724 | { | ||
10725 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
10726 | .name = "Master Playback Switch", | ||
10727 | .info = snd_hda_mixer_amp_switch_info, | ||
10728 | .get = snd_hda_mixer_amp_switch_get, | ||
10729 | .put = alc268_acer_master_sw_put, | ||
10730 | .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT), | ||
10731 | }, | ||
10732 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | ||
10733 | HDA_CODEC_VOLUME("Line In Boost", 0x1a, 0, HDA_INPUT), | ||
10734 | { } | ||
10735 | }; | ||
10736 | |||
10945 | static struct hda_verb alc268_acer_aspire_one_verbs[] = { | 10737 | static struct hda_verb alc268_acer_aspire_one_verbs[] = { |
10946 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | 10738 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, |
10947 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | 10739 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, |
@@ -11218,10 +11010,6 @@ static struct hda_verb alc268_volume_init_verbs[] = { | |||
11218 | { } | 11010 | { } |
11219 | }; | 11011 | }; |
11220 | 11012 | ||
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[] = { | 11013 | static struct snd_kcontrol_new alc268_capture_alt_mixer[] = { |
11226 | HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT), | 11014 | HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT), |
11227 | HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT), | 11015 | HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT), |
@@ -11233,9 +11021,9 @@ static struct snd_kcontrol_new alc268_capture_alt_mixer[] = { | |||
11233 | /* .name = "Capture Source", */ | 11021 | /* .name = "Capture Source", */ |
11234 | .name = "Input Source", | 11022 | .name = "Input Source", |
11235 | .count = 1, | 11023 | .count = 1, |
11236 | .info = alc268_mux_enum_info, | 11024 | .info = alc_mux_enum_info, |
11237 | .get = alc268_mux_enum_get, | 11025 | .get = alc_mux_enum_get, |
11238 | .put = alc268_mux_enum_put, | 11026 | .put = alc_mux_enum_put, |
11239 | }, | 11027 | }, |
11240 | { } /* end */ | 11028 | { } /* end */ |
11241 | }; | 11029 | }; |
@@ -11253,9 +11041,9 @@ static struct snd_kcontrol_new alc268_capture_mixer[] = { | |||
11253 | /* .name = "Capture Source", */ | 11041 | /* .name = "Capture Source", */ |
11254 | .name = "Input Source", | 11042 | .name = "Input Source", |
11255 | .count = 2, | 11043 | .count = 2, |
11256 | .info = alc268_mux_enum_info, | 11044 | .info = alc_mux_enum_info, |
11257 | .get = alc268_mux_enum_get, | 11045 | .get = alc_mux_enum_get, |
11258 | .put = alc268_mux_enum_put, | 11046 | .put = alc_mux_enum_put, |
11259 | }, | 11047 | }, |
11260 | { } /* end */ | 11048 | { } /* end */ |
11261 | }; | 11049 | }; |
@@ -11274,6 +11062,15 @@ static struct hda_input_mux alc268_acer_capture_source = { | |||
11274 | .num_items = 3, | 11062 | .num_items = 3, |
11275 | .items = { | 11063 | .items = { |
11276 | { "Mic", 0x0 }, | 11064 | { "Mic", 0x0 }, |
11065 | { "Internal Mic", 0x1 }, | ||
11066 | { "Line", 0x2 }, | ||
11067 | }, | ||
11068 | }; | ||
11069 | |||
11070 | static struct hda_input_mux alc268_acer_dmic_capture_source = { | ||
11071 | .num_items = 3, | ||
11072 | .items = { | ||
11073 | { "Mic", 0x0 }, | ||
11277 | { "Internal Mic", 0x6 }, | 11074 | { "Internal Mic", 0x6 }, |
11278 | { "Line", 0x2 }, | 11075 | { "Line", 0x2 }, |
11279 | }, | 11076 | }, |
@@ -11512,13 +11309,13 @@ static int alc268_parse_auto_config(struct hda_codec *codec) | |||
11512 | if (spec->autocfg.dig_out_pin) | 11309 | if (spec->autocfg.dig_out_pin) |
11513 | spec->multiout.dig_out_nid = ALC268_DIGOUT_NID; | 11310 | spec->multiout.dig_out_nid = ALC268_DIGOUT_NID; |
11514 | 11311 | ||
11515 | if (spec->kctl_alloc) | 11312 | if (spec->kctls.list) |
11516 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 11313 | add_mixer(spec, spec->kctls.list); |
11517 | 11314 | ||
11518 | if (spec->autocfg.speaker_pins[0] != 0x1d) | 11315 | if (spec->autocfg.speaker_pins[0] != 0x1d) |
11519 | spec->mixers[spec->num_mixers++] = alc268_beep_mixer; | 11316 | add_mixer(spec, alc268_beep_mixer); |
11520 | 11317 | ||
11521 | spec->init_verbs[spec->num_init_verbs++] = alc268_volume_init_verbs; | 11318 | add_verb(spec, alc268_volume_init_verbs); |
11522 | spec->num_mux_defs = 1; | 11319 | spec->num_mux_defs = 1; |
11523 | spec->input_mux = &spec->private_imux; | 11320 | spec->input_mux = &spec->private_imux; |
11524 | 11321 | ||
@@ -11554,6 +11351,7 @@ static const char *alc268_models[ALC268_MODEL_LAST] = { | |||
11554 | [ALC268_3ST] = "3stack", | 11351 | [ALC268_3ST] = "3stack", |
11555 | [ALC268_TOSHIBA] = "toshiba", | 11352 | [ALC268_TOSHIBA] = "toshiba", |
11556 | [ALC268_ACER] = "acer", | 11353 | [ALC268_ACER] = "acer", |
11354 | [ALC268_ACER_DMIC] = "acer-dmic", | ||
11557 | [ALC268_ACER_ASPIRE_ONE] = "acer-aspire", | 11355 | [ALC268_ACER_ASPIRE_ONE] = "acer-aspire", |
11558 | [ALC268_DELL] = "dell", | 11356 | [ALC268_DELL] = "dell", |
11559 | [ALC268_ZEPTO] = "zepto", | 11357 | [ALC268_ZEPTO] = "zepto", |
@@ -11649,6 +11447,23 @@ static struct alc_config_preset alc268_presets[] = { | |||
11649 | .unsol_event = alc268_acer_unsol_event, | 11447 | .unsol_event = alc268_acer_unsol_event, |
11650 | .init_hook = alc268_acer_init_hook, | 11448 | .init_hook = alc268_acer_init_hook, |
11651 | }, | 11449 | }, |
11450 | [ALC268_ACER_DMIC] = { | ||
11451 | .mixers = { alc268_acer_dmic_mixer, alc268_capture_alt_mixer, | ||
11452 | alc268_beep_mixer }, | ||
11453 | .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, | ||
11454 | alc268_acer_verbs }, | ||
11455 | .num_dacs = ARRAY_SIZE(alc268_dac_nids), | ||
11456 | .dac_nids = alc268_dac_nids, | ||
11457 | .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt), | ||
11458 | .adc_nids = alc268_adc_nids_alt, | ||
11459 | .capsrc_nids = alc268_capsrc_nids, | ||
11460 | .hp_nid = 0x02, | ||
11461 | .num_channel_mode = ARRAY_SIZE(alc268_modes), | ||
11462 | .channel_mode = alc268_modes, | ||
11463 | .input_mux = &alc268_acer_dmic_capture_source, | ||
11464 | .unsol_event = alc268_acer_unsol_event, | ||
11465 | .init_hook = alc268_acer_init_hook, | ||
11466 | }, | ||
11652 | [ALC268_ACER_ASPIRE_ONE] = { | 11467 | [ALC268_ACER_ASPIRE_ONE] = { |
11653 | .mixers = { alc268_acer_aspire_one_mixer, | 11468 | .mixers = { alc268_acer_aspire_one_mixer, |
11654 | alc268_capture_alt_mixer }, | 11469 | alc268_capture_alt_mixer }, |
@@ -11787,15 +11602,11 @@ static int patch_alc268(struct hda_codec *codec) | |||
11787 | if (wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) { | 11602 | if (wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) { |
11788 | spec->adc_nids = alc268_adc_nids_alt; | 11603 | spec->adc_nids = alc268_adc_nids_alt; |
11789 | spec->num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt); | 11604 | spec->num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt); |
11790 | spec->mixers[spec->num_mixers] = | 11605 | add_mixer(spec, alc268_capture_alt_mixer); |
11791 | alc268_capture_alt_mixer; | ||
11792 | spec->num_mixers++; | ||
11793 | } else { | 11606 | } else { |
11794 | spec->adc_nids = alc268_adc_nids; | 11607 | spec->adc_nids = alc268_adc_nids; |
11795 | spec->num_adc_nids = ARRAY_SIZE(alc268_adc_nids); | 11608 | spec->num_adc_nids = ARRAY_SIZE(alc268_adc_nids); |
11796 | spec->mixers[spec->num_mixers] = | 11609 | add_mixer(spec, alc268_capture_mixer); |
11797 | alc268_capture_mixer; | ||
11798 | spec->num_mixers++; | ||
11799 | } | 11610 | } |
11800 | spec->capsrc_nids = alc268_capsrc_nids; | 11611 | spec->capsrc_nids = alc268_capsrc_nids; |
11801 | /* set default input source */ | 11612 | /* set default input source */ |
@@ -11893,6 +11704,31 @@ static struct snd_kcontrol_new alc269_quanta_fl1_mixer[] = { | |||
11893 | { } | 11704 | { } |
11894 | }; | 11705 | }; |
11895 | 11706 | ||
11707 | static struct snd_kcontrol_new alc269_lifebook_mixer[] = { | ||
11708 | /* output mixer control */ | ||
11709 | HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol), | ||
11710 | { | ||
11711 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
11712 | .name = "Master Playback Switch", | ||
11713 | .info = snd_hda_mixer_amp_switch_info, | ||
11714 | .get = snd_hda_mixer_amp_switch_get, | ||
11715 | .put = alc268_acer_master_sw_put, | ||
11716 | .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT), | ||
11717 | }, | ||
11718 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
11719 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
11720 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | ||
11721 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), | ||
11722 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), | ||
11723 | HDA_CODEC_VOLUME("Internal Mic Boost", 0x19, 0, HDA_INPUT), | ||
11724 | HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x0b, 0x03, HDA_INPUT), | ||
11725 | HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x0b, 0x03, HDA_INPUT), | ||
11726 | HDA_CODEC_VOLUME("Dock Mic Boost", 0x1b, 0, HDA_INPUT), | ||
11727 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
11728 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
11729 | { } | ||
11730 | }; | ||
11731 | |||
11896 | /* bind volumes of both NID 0x0c and 0x0d */ | 11732 | /* bind volumes of both NID 0x0c and 0x0d */ |
11897 | static struct hda_bind_ctls alc269_epc_bind_vol = { | 11733 | static struct hda_bind_ctls alc269_epc_bind_vol = { |
11898 | .ops = &snd_hda_bind_vol, | 11734 | .ops = &snd_hda_bind_vol, |
@@ -11911,28 +11747,18 @@ static struct snd_kcontrol_new alc269_eeepc_mixer[] = { | |||
11911 | }; | 11747 | }; |
11912 | 11748 | ||
11913 | /* capture mixer elements */ | 11749 | /* capture mixer elements */ |
11914 | static struct snd_kcontrol_new alc269_capture_mixer[] = { | 11750 | static struct snd_kcontrol_new alc269_epc_capture_mixer[] = { |
11915 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | 11751 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), |
11916 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | 11752 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), |
11917 | { | 11753 | 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 */ | 11754 | { } /* end */ |
11930 | }; | 11755 | }; |
11931 | 11756 | ||
11932 | /* capture mixer elements */ | 11757 | /* FSC amilo */ |
11933 | static struct snd_kcontrol_new alc269_epc_capture_mixer[] = { | 11758 | static struct snd_kcontrol_new alc269_fujitsu_mixer[] = { |
11934 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | 11759 | HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT), |
11935 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | 11760 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), |
11761 | HDA_BIND_VOL("PCM Playback Volume", &alc269_epc_bind_vol), | ||
11936 | { } /* end */ | 11762 | { } /* end */ |
11937 | }; | 11763 | }; |
11938 | 11764 | ||
@@ -11953,6 +11779,20 @@ static struct hda_verb alc269_quanta_fl1_verbs[] = { | |||
11953 | { } | 11779 | { } |
11954 | }; | 11780 | }; |
11955 | 11781 | ||
11782 | static struct hda_verb alc269_lifebook_verbs[] = { | ||
11783 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
11784 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
11785 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
11786 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
11787 | {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, | ||
11788 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
11789 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
11790 | {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, | ||
11791 | {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT}, | ||
11792 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
11793 | { } | ||
11794 | }; | ||
11795 | |||
11956 | /* toggle speaker-output according to the hp-jack state */ | 11796 | /* toggle speaker-output according to the hp-jack state */ |
11957 | static void alc269_quanta_fl1_speaker_automute(struct hda_codec *codec) | 11797 | static void alc269_quanta_fl1_speaker_automute(struct hda_codec *codec) |
11958 | { | 11798 | { |
@@ -11978,6 +11818,37 @@ static void alc269_quanta_fl1_speaker_automute(struct hda_codec *codec) | |||
11978 | AC_VERB_SET_PROC_COEF, 0x480); | 11818 | AC_VERB_SET_PROC_COEF, 0x480); |
11979 | } | 11819 | } |
11980 | 11820 | ||
11821 | /* toggle speaker-output according to the hp-jacks state */ | ||
11822 | static void alc269_lifebook_speaker_automute(struct hda_codec *codec) | ||
11823 | { | ||
11824 | unsigned int present; | ||
11825 | unsigned char bits; | ||
11826 | |||
11827 | /* Check laptop headphone socket */ | ||
11828 | present = snd_hda_codec_read(codec, 0x15, 0, | ||
11829 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
11830 | |||
11831 | /* Check port replicator headphone socket */ | ||
11832 | present |= snd_hda_codec_read(codec, 0x1a, 0, | ||
11833 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
11834 | |||
11835 | bits = present ? AMP_IN_MUTE(0) : 0; | ||
11836 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0, | ||
11837 | AMP_IN_MUTE(0), bits); | ||
11838 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1, | ||
11839 | AMP_IN_MUTE(0), bits); | ||
11840 | |||
11841 | snd_hda_codec_write(codec, 0x20, 0, | ||
11842 | AC_VERB_SET_COEF_INDEX, 0x0c); | ||
11843 | snd_hda_codec_write(codec, 0x20, 0, | ||
11844 | AC_VERB_SET_PROC_COEF, 0x680); | ||
11845 | |||
11846 | snd_hda_codec_write(codec, 0x20, 0, | ||
11847 | AC_VERB_SET_COEF_INDEX, 0x0c); | ||
11848 | snd_hda_codec_write(codec, 0x20, 0, | ||
11849 | AC_VERB_SET_PROC_COEF, 0x480); | ||
11850 | } | ||
11851 | |||
11981 | static void alc269_quanta_fl1_mic_automute(struct hda_codec *codec) | 11852 | static void alc269_quanta_fl1_mic_automute(struct hda_codec *codec) |
11982 | { | 11853 | { |
11983 | unsigned int present; | 11854 | unsigned int present; |
@@ -11988,6 +11859,29 @@ static void alc269_quanta_fl1_mic_automute(struct hda_codec *codec) | |||
11988 | AC_VERB_SET_CONNECT_SEL, present ? 0x0 : 0x1); | 11859 | AC_VERB_SET_CONNECT_SEL, present ? 0x0 : 0x1); |
11989 | } | 11860 | } |
11990 | 11861 | ||
11862 | static void alc269_lifebook_mic_autoswitch(struct hda_codec *codec) | ||
11863 | { | ||
11864 | unsigned int present_laptop; | ||
11865 | unsigned int present_dock; | ||
11866 | |||
11867 | present_laptop = snd_hda_codec_read(codec, 0x18, 0, | ||
11868 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
11869 | |||
11870 | present_dock = snd_hda_codec_read(codec, 0x1b, 0, | ||
11871 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
11872 | |||
11873 | /* Laptop mic port overrides dock mic port, design decision */ | ||
11874 | if (present_dock) | ||
11875 | snd_hda_codec_write(codec, 0x23, 0, | ||
11876 | AC_VERB_SET_CONNECT_SEL, 0x3); | ||
11877 | if (present_laptop) | ||
11878 | snd_hda_codec_write(codec, 0x23, 0, | ||
11879 | AC_VERB_SET_CONNECT_SEL, 0x0); | ||
11880 | if (!present_dock && !present_laptop) | ||
11881 | snd_hda_codec_write(codec, 0x23, 0, | ||
11882 | AC_VERB_SET_CONNECT_SEL, 0x1); | ||
11883 | } | ||
11884 | |||
11991 | static void alc269_quanta_fl1_unsol_event(struct hda_codec *codec, | 11885 | static void alc269_quanta_fl1_unsol_event(struct hda_codec *codec, |
11992 | unsigned int res) | 11886 | unsigned int res) |
11993 | { | 11887 | { |
@@ -11997,12 +11891,27 @@ static void alc269_quanta_fl1_unsol_event(struct hda_codec *codec, | |||
11997 | alc269_quanta_fl1_mic_automute(codec); | 11891 | alc269_quanta_fl1_mic_automute(codec); |
11998 | } | 11892 | } |
11999 | 11893 | ||
11894 | static void alc269_lifebook_unsol_event(struct hda_codec *codec, | ||
11895 | unsigned int res) | ||
11896 | { | ||
11897 | if ((res >> 26) == ALC880_HP_EVENT) | ||
11898 | alc269_lifebook_speaker_automute(codec); | ||
11899 | if ((res >> 26) == ALC880_MIC_EVENT) | ||
11900 | alc269_lifebook_mic_autoswitch(codec); | ||
11901 | } | ||
11902 | |||
12000 | static void alc269_quanta_fl1_init_hook(struct hda_codec *codec) | 11903 | static void alc269_quanta_fl1_init_hook(struct hda_codec *codec) |
12001 | { | 11904 | { |
12002 | alc269_quanta_fl1_speaker_automute(codec); | 11905 | alc269_quanta_fl1_speaker_automute(codec); |
12003 | alc269_quanta_fl1_mic_automute(codec); | 11906 | alc269_quanta_fl1_mic_automute(codec); |
12004 | } | 11907 | } |
12005 | 11908 | ||
11909 | static void alc269_lifebook_init_hook(struct hda_codec *codec) | ||
11910 | { | ||
11911 | alc269_lifebook_speaker_automute(codec); | ||
11912 | alc269_lifebook_mic_autoswitch(codec); | ||
11913 | } | ||
11914 | |||
12006 | static struct hda_verb alc269_eeepc_dmic_init_verbs[] = { | 11915 | static struct hda_verb alc269_eeepc_dmic_init_verbs[] = { |
12007 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, | 11916 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, |
12008 | {0x23, AC_VERB_SET_CONNECT_SEL, 0x05}, | 11917 | {0x23, AC_VERB_SET_CONNECT_SEL, 0x05}, |
@@ -12303,17 +12212,17 @@ static int alc269_parse_auto_config(struct hda_codec *codec) | |||
12303 | if (spec->autocfg.dig_out_pin) | 12212 | if (spec->autocfg.dig_out_pin) |
12304 | spec->multiout.dig_out_nid = ALC269_DIGOUT_NID; | 12213 | spec->multiout.dig_out_nid = ALC269_DIGOUT_NID; |
12305 | 12214 | ||
12306 | if (spec->kctl_alloc) | 12215 | if (spec->kctls.list) |
12307 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 12216 | add_mixer(spec, spec->kctls.list); |
12308 | 12217 | ||
12309 | /* create a beep mixer control if the pin 0x1d isn't assigned */ | 12218 | /* create a beep mixer control if the pin 0x1d isn't assigned */ |
12310 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.input_pins); i++) | 12219 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.input_pins); i++) |
12311 | if (spec->autocfg.input_pins[i] == 0x1d) | 12220 | if (spec->autocfg.input_pins[i] == 0x1d) |
12312 | break; | 12221 | break; |
12313 | if (i >= ARRAY_SIZE(spec->autocfg.input_pins)) | 12222 | if (i >= ARRAY_SIZE(spec->autocfg.input_pins)) |
12314 | spec->mixers[spec->num_mixers++] = alc269_beep_mixer; | 12223 | add_mixer(spec, alc269_beep_mixer); |
12315 | 12224 | ||
12316 | spec->init_verbs[spec->num_init_verbs++] = alc269_init_verbs; | 12225 | add_verb(spec, alc269_init_verbs); |
12317 | spec->num_mux_defs = 1; | 12226 | spec->num_mux_defs = 1; |
12318 | spec->input_mux = &spec->private_imux; | 12227 | spec->input_mux = &spec->private_imux; |
12319 | /* set default input source */ | 12228 | /* set default input source */ |
@@ -12325,8 +12234,8 @@ static int alc269_parse_auto_config(struct hda_codec *codec) | |||
12325 | if (err < 0) | 12234 | if (err < 0) |
12326 | return err; | 12235 | return err; |
12327 | 12236 | ||
12328 | spec->mixers[spec->num_mixers] = alc269_capture_mixer; | 12237 | if (!spec->cap_mixer) |
12329 | spec->num_mixers++; | 12238 | set_capture_mixer(spec); |
12330 | 12239 | ||
12331 | store_pin_configs(codec); | 12240 | store_pin_configs(codec); |
12332 | return 1; | 12241 | return 1; |
@@ -12355,7 +12264,9 @@ static const char *alc269_models[ALC269_MODEL_LAST] = { | |||
12355 | [ALC269_BASIC] = "basic", | 12264 | [ALC269_BASIC] = "basic", |
12356 | [ALC269_QUANTA_FL1] = "quanta", | 12265 | [ALC269_QUANTA_FL1] = "quanta", |
12357 | [ALC269_ASUS_EEEPC_P703] = "eeepc-p703", | 12266 | [ALC269_ASUS_EEEPC_P703] = "eeepc-p703", |
12358 | [ALC269_ASUS_EEEPC_P901] = "eeepc-p901" | 12267 | [ALC269_ASUS_EEEPC_P901] = "eeepc-p901", |
12268 | [ALC269_FUJITSU] = "fujitsu", | ||
12269 | [ALC269_LIFEBOOK] = "lifebook" | ||
12359 | }; | 12270 | }; |
12360 | 12271 | ||
12361 | static struct snd_pci_quirk alc269_cfg_tbl[] = { | 12272 | static struct snd_pci_quirk alc269_cfg_tbl[] = { |
@@ -12366,12 +12277,14 @@ static struct snd_pci_quirk alc269_cfg_tbl[] = { | |||
12366 | ALC269_ASUS_EEEPC_P901), | 12277 | ALC269_ASUS_EEEPC_P901), |
12367 | SND_PCI_QUIRK(0x1043, 0x834a, "ASUS Eeepc S101", | 12278 | SND_PCI_QUIRK(0x1043, 0x834a, "ASUS Eeepc S101", |
12368 | ALC269_ASUS_EEEPC_P901), | 12279 | ALC269_ASUS_EEEPC_P901), |
12280 | SND_PCI_QUIRK(0x1734, 0x115d, "FSC Amilo", ALC269_FUJITSU), | ||
12281 | SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook ICH9M-based", ALC269_LIFEBOOK), | ||
12369 | {} | 12282 | {} |
12370 | }; | 12283 | }; |
12371 | 12284 | ||
12372 | static struct alc_config_preset alc269_presets[] = { | 12285 | static struct alc_config_preset alc269_presets[] = { |
12373 | [ALC269_BASIC] = { | 12286 | [ALC269_BASIC] = { |
12374 | .mixers = { alc269_base_mixer, alc269_capture_mixer }, | 12287 | .mixers = { alc269_base_mixer }, |
12375 | .init_verbs = { alc269_init_verbs }, | 12288 | .init_verbs = { alc269_init_verbs }, |
12376 | .num_dacs = ARRAY_SIZE(alc269_dac_nids), | 12289 | .num_dacs = ARRAY_SIZE(alc269_dac_nids), |
12377 | .dac_nids = alc269_dac_nids, | 12290 | .dac_nids = alc269_dac_nids, |
@@ -12393,7 +12306,8 @@ static struct alc_config_preset alc269_presets[] = { | |||
12393 | .init_hook = alc269_quanta_fl1_init_hook, | 12306 | .init_hook = alc269_quanta_fl1_init_hook, |
12394 | }, | 12307 | }, |
12395 | [ALC269_ASUS_EEEPC_P703] = { | 12308 | [ALC269_ASUS_EEEPC_P703] = { |
12396 | .mixers = { alc269_eeepc_mixer, alc269_epc_capture_mixer }, | 12309 | .mixers = { alc269_eeepc_mixer }, |
12310 | .cap_mixer = alc269_epc_capture_mixer, | ||
12397 | .init_verbs = { alc269_init_verbs, | 12311 | .init_verbs = { alc269_init_verbs, |
12398 | alc269_eeepc_amic_init_verbs }, | 12312 | alc269_eeepc_amic_init_verbs }, |
12399 | .num_dacs = ARRAY_SIZE(alc269_dac_nids), | 12313 | .num_dacs = ARRAY_SIZE(alc269_dac_nids), |
@@ -12406,7 +12320,22 @@ static struct alc_config_preset alc269_presets[] = { | |||
12406 | .init_hook = alc269_eeepc_amic_inithook, | 12320 | .init_hook = alc269_eeepc_amic_inithook, |
12407 | }, | 12321 | }, |
12408 | [ALC269_ASUS_EEEPC_P901] = { | 12322 | [ALC269_ASUS_EEEPC_P901] = { |
12409 | .mixers = { alc269_eeepc_mixer, alc269_epc_capture_mixer}, | 12323 | .mixers = { alc269_eeepc_mixer }, |
12324 | .cap_mixer = alc269_epc_capture_mixer, | ||
12325 | .init_verbs = { alc269_init_verbs, | ||
12326 | alc269_eeepc_dmic_init_verbs }, | ||
12327 | .num_dacs = ARRAY_SIZE(alc269_dac_nids), | ||
12328 | .dac_nids = alc269_dac_nids, | ||
12329 | .hp_nid = 0x03, | ||
12330 | .num_channel_mode = ARRAY_SIZE(alc269_modes), | ||
12331 | .channel_mode = alc269_modes, | ||
12332 | .input_mux = &alc269_eeepc_dmic_capture_source, | ||
12333 | .unsol_event = alc269_eeepc_dmic_unsol_event, | ||
12334 | .init_hook = alc269_eeepc_dmic_inithook, | ||
12335 | }, | ||
12336 | [ALC269_FUJITSU] = { | ||
12337 | .mixers = { alc269_fujitsu_mixer, alc269_beep_mixer }, | ||
12338 | .cap_mixer = alc269_epc_capture_mixer, | ||
12410 | .init_verbs = { alc269_init_verbs, | 12339 | .init_verbs = { alc269_init_verbs, |
12411 | alc269_eeepc_dmic_init_verbs }, | 12340 | alc269_eeepc_dmic_init_verbs }, |
12412 | .num_dacs = ARRAY_SIZE(alc269_dac_nids), | 12341 | .num_dacs = ARRAY_SIZE(alc269_dac_nids), |
@@ -12418,6 +12347,18 @@ static struct alc_config_preset alc269_presets[] = { | |||
12418 | .unsol_event = alc269_eeepc_dmic_unsol_event, | 12347 | .unsol_event = alc269_eeepc_dmic_unsol_event, |
12419 | .init_hook = alc269_eeepc_dmic_inithook, | 12348 | .init_hook = alc269_eeepc_dmic_inithook, |
12420 | }, | 12349 | }, |
12350 | [ALC269_LIFEBOOK] = { | ||
12351 | .mixers = { alc269_lifebook_mixer }, | ||
12352 | .init_verbs = { alc269_init_verbs, alc269_lifebook_verbs }, | ||
12353 | .num_dacs = ARRAY_SIZE(alc269_dac_nids), | ||
12354 | .dac_nids = alc269_dac_nids, | ||
12355 | .hp_nid = 0x03, | ||
12356 | .num_channel_mode = ARRAY_SIZE(alc269_modes), | ||
12357 | .channel_mode = alc269_modes, | ||
12358 | .input_mux = &alc269_capture_source, | ||
12359 | .unsol_event = alc269_lifebook_unsol_event, | ||
12360 | .init_hook = alc269_lifebook_init_hook, | ||
12361 | }, | ||
12421 | }; | 12362 | }; |
12422 | 12363 | ||
12423 | static int patch_alc269(struct hda_codec *codec) | 12364 | static int patch_alc269(struct hda_codec *codec) |
@@ -12472,6 +12413,8 @@ static int patch_alc269(struct hda_codec *codec) | |||
12472 | spec->adc_nids = alc269_adc_nids; | 12413 | spec->adc_nids = alc269_adc_nids; |
12473 | spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids); | 12414 | spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids); |
12474 | spec->capsrc_nids = alc269_capsrc_nids; | 12415 | spec->capsrc_nids = alc269_capsrc_nids; |
12416 | if (!spec->cap_mixer) | ||
12417 | set_capture_mixer(spec); | ||
12475 | 12418 | ||
12476 | codec->patch_ops = alc_patch_ops; | 12419 | codec->patch_ops = alc_patch_ops; |
12477 | if (board_config == ALC269_AUTO) | 12420 | if (board_config == ALC269_AUTO) |
@@ -12612,17 +12555,6 @@ static struct snd_kcontrol_new alc861_base_mixer[] = { | |||
12612 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), | 12555 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), |
12613 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT), | 12556 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT), |
12614 | 12557 | ||
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 */ | 12558 | { } /* end */ |
12627 | }; | 12559 | }; |
12628 | 12560 | ||
@@ -12646,17 +12578,6 @@ static struct snd_kcontrol_new alc861_3ST_mixer[] = { | |||
12646 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), | 12578 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), |
12647 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT), | 12579 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT), |
12648 | 12580 | ||
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 | { | 12581 | { |
12661 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 12582 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
12662 | .name = "Channel Mode", | 12583 | .name = "Channel Mode", |
@@ -12674,18 +12595,6 @@ static struct snd_kcontrol_new alc861_toshiba_mixer[] = { | |||
12674 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT), | 12595 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT), |
12675 | HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT), | 12596 | HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT), |
12676 | 12597 | ||
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 */ | 12598 | { } /* end */ |
12690 | }; | 12599 | }; |
12691 | 12600 | ||
@@ -12709,17 +12618,6 @@ static struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = { | |||
12709 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), | 12618 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), |
12710 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT), | 12619 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT), |
12711 | 12620 | ||
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 | { | 12621 | { |
12724 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 12622 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
12725 | .name = "Channel Mode", | 12623 | .name = "Channel Mode", |
@@ -12751,17 +12649,6 @@ static struct snd_kcontrol_new alc861_asus_mixer[] = { | |||
12751 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), | 12649 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), |
12752 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_OUTPUT), | 12650 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_OUTPUT), |
12753 | 12651 | ||
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 | { | 12652 | { |
12766 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 12653 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
12767 | .name = "Channel Mode", | 12654 | .name = "Channel Mode", |
@@ -13293,25 +13180,6 @@ static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec, | |||
13293 | return 0; | 13180 | return 0; |
13294 | } | 13181 | } |
13295 | 13182 | ||
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, | 13183 | static void alc861_auto_set_output_and_unmute(struct hda_codec *codec, |
13316 | hda_nid_t nid, | 13184 | hda_nid_t nid, |
13317 | int pin_type, int dac_idx) | 13185 | int pin_type, int dac_idx) |
@@ -13402,18 +13270,17 @@ static int alc861_parse_auto_config(struct hda_codec *codec) | |||
13402 | if (spec->autocfg.dig_out_pin) | 13270 | if (spec->autocfg.dig_out_pin) |
13403 | spec->multiout.dig_out_nid = ALC861_DIGOUT_NID; | 13271 | spec->multiout.dig_out_nid = ALC861_DIGOUT_NID; |
13404 | 13272 | ||
13405 | if (spec->kctl_alloc) | 13273 | if (spec->kctls.list) |
13406 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 13274 | add_mixer(spec, spec->kctls.list); |
13407 | 13275 | ||
13408 | spec->init_verbs[spec->num_init_verbs++] = alc861_auto_init_verbs; | 13276 | add_verb(spec, alc861_auto_init_verbs); |
13409 | 13277 | ||
13410 | spec->num_mux_defs = 1; | 13278 | spec->num_mux_defs = 1; |
13411 | spec->input_mux = &spec->private_imux; | 13279 | spec->input_mux = &spec->private_imux; |
13412 | 13280 | ||
13413 | spec->adc_nids = alc861_adc_nids; | 13281 | spec->adc_nids = alc861_adc_nids; |
13414 | spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids); | 13282 | spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids); |
13415 | spec->mixers[spec->num_mixers] = alc861_capture_mixer; | 13283 | set_capture_mixer(spec); |
13416 | spec->num_mixers++; | ||
13417 | 13284 | ||
13418 | store_pin_configs(codec); | 13285 | store_pin_configs(codec); |
13419 | return 1; | 13286 | return 1; |
@@ -13709,11 +13576,6 @@ static struct hda_input_mux alc861vd_hp_capture_source = { | |||
13709 | }, | 13576 | }, |
13710 | }; | 13577 | }; |
13711 | 13578 | ||
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 | /* | 13579 | /* |
13718 | * 2ch mode | 13580 | * 2ch mode |
13719 | */ | 13581 | */ |
@@ -13759,25 +13621,6 @@ static struct snd_kcontrol_new alc861vd_chmode_mixer[] = { | |||
13759 | { } /* end */ | 13621 | { } /* end */ |
13760 | }; | 13622 | }; |
13761 | 13623 | ||
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 | 13624 | /* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17 |
13782 | * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b | 13625 | * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b |
13783 | */ | 13626 | */ |
@@ -14169,6 +14012,7 @@ static void alc861vd_dallas_unsol_event(struct hda_codec *codec, unsigned int re | |||
14169 | static const char *alc861vd_models[ALC861VD_MODEL_LAST] = { | 14012 | static const char *alc861vd_models[ALC861VD_MODEL_LAST] = { |
14170 | [ALC660VD_3ST] = "3stack-660", | 14013 | [ALC660VD_3ST] = "3stack-660", |
14171 | [ALC660VD_3ST_DIG] = "3stack-660-digout", | 14014 | [ALC660VD_3ST_DIG] = "3stack-660-digout", |
14015 | [ALC660VD_ASUS_V1S] = "asus-v1s", | ||
14172 | [ALC861VD_3ST] = "3stack", | 14016 | [ALC861VD_3ST] = "3stack", |
14173 | [ALC861VD_3ST_DIG] = "3stack-digout", | 14017 | [ALC861VD_3ST_DIG] = "3stack-digout", |
14174 | [ALC861VD_6ST_DIG] = "6stack-digout", | 14018 | [ALC861VD_6ST_DIG] = "6stack-digout", |
@@ -14183,7 +14027,7 @@ static struct snd_pci_quirk alc861vd_cfg_tbl[] = { | |||
14183 | SND_PCI_QUIRK(0x103c, 0x30bf, "HP TX1000", ALC861VD_HP), | 14027 | SND_PCI_QUIRK(0x103c, 0x30bf, "HP TX1000", ALC861VD_HP), |
14184 | SND_PCI_QUIRK(0x1043, 0x12e2, "Asus z35m", ALC660VD_3ST), | 14028 | SND_PCI_QUIRK(0x1043, 0x12e2, "Asus z35m", ALC660VD_3ST), |
14185 | SND_PCI_QUIRK(0x1043, 0x1339, "Asus G1", ALC660VD_3ST), | 14029 | SND_PCI_QUIRK(0x1043, 0x1339, "Asus G1", ALC660VD_3ST), |
14186 | SND_PCI_QUIRK(0x1043, 0x1633, "Asus V1Sn", ALC861VD_LENOVO), | 14030 | SND_PCI_QUIRK(0x1043, 0x1633, "Asus V1Sn", ALC660VD_ASUS_V1S), |
14187 | SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS", ALC660VD_3ST_DIG), | 14031 | SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS", ALC660VD_3ST_DIG), |
14188 | SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST), | 14032 | SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST), |
14189 | SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba A135", ALC861VD_LENOVO), | 14033 | SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba A135", ALC861VD_LENOVO), |
@@ -14290,6 +14134,21 @@ static struct alc_config_preset alc861vd_presets[] = { | |||
14290 | .unsol_event = alc861vd_dallas_unsol_event, | 14134 | .unsol_event = alc861vd_dallas_unsol_event, |
14291 | .init_hook = alc861vd_dallas_automute, | 14135 | .init_hook = alc861vd_dallas_automute, |
14292 | }, | 14136 | }, |
14137 | [ALC660VD_ASUS_V1S] = { | ||
14138 | .mixers = { alc861vd_lenovo_mixer }, | ||
14139 | .init_verbs = { alc861vd_volume_init_verbs, | ||
14140 | alc861vd_3stack_init_verbs, | ||
14141 | alc861vd_eapd_verbs, | ||
14142 | alc861vd_lenovo_unsol_verbs }, | ||
14143 | .num_dacs = ARRAY_SIZE(alc660vd_dac_nids), | ||
14144 | .dac_nids = alc660vd_dac_nids, | ||
14145 | .dig_out_nid = ALC861VD_DIGOUT_NID, | ||
14146 | .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes), | ||
14147 | .channel_mode = alc861vd_3stack_2ch_modes, | ||
14148 | .input_mux = &alc861vd_capture_source, | ||
14149 | .unsol_event = alc861vd_lenovo_unsol_event, | ||
14150 | .init_hook = alc861vd_lenovo_automute, | ||
14151 | }, | ||
14293 | }; | 14152 | }; |
14294 | 14153 | ||
14295 | /* | 14154 | /* |
@@ -14514,11 +14373,10 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec) | |||
14514 | if (spec->autocfg.dig_out_pin) | 14373 | if (spec->autocfg.dig_out_pin) |
14515 | spec->multiout.dig_out_nid = ALC861VD_DIGOUT_NID; | 14374 | spec->multiout.dig_out_nid = ALC861VD_DIGOUT_NID; |
14516 | 14375 | ||
14517 | if (spec->kctl_alloc) | 14376 | if (spec->kctls.list) |
14518 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 14377 | add_mixer(spec, spec->kctls.list); |
14519 | 14378 | ||
14520 | spec->init_verbs[spec->num_init_verbs++] | 14379 | add_verb(spec, alc861vd_volume_init_verbs); |
14521 | = alc861vd_volume_init_verbs; | ||
14522 | 14380 | ||
14523 | spec->num_mux_defs = 1; | 14381 | spec->num_mux_defs = 1; |
14524 | spec->input_mux = &spec->private_imux; | 14382 | spec->input_mux = &spec->private_imux; |
@@ -14585,7 +14443,7 @@ static int patch_alc861vd(struct hda_codec *codec) | |||
14585 | spec->stream_name_analog = "ALC660-VD Analog"; | 14443 | spec->stream_name_analog = "ALC660-VD Analog"; |
14586 | spec->stream_name_digital = "ALC660-VD Digital"; | 14444 | spec->stream_name_digital = "ALC660-VD Digital"; |
14587 | /* always turn on EAPD */ | 14445 | /* always turn on EAPD */ |
14588 | spec->init_verbs[spec->num_init_verbs++] = alc660vd_eapd_verbs; | 14446 | add_verb(spec, alc660vd_eapd_verbs); |
14589 | } else { | 14447 | } else { |
14590 | spec->stream_name_analog = "ALC861VD Analog"; | 14448 | spec->stream_name_analog = "ALC861VD Analog"; |
14591 | spec->stream_name_digital = "ALC861VD Digital"; | 14449 | spec->stream_name_digital = "ALC861VD Digital"; |
@@ -14600,9 +14458,9 @@ static int patch_alc861vd(struct hda_codec *codec) | |||
14600 | spec->adc_nids = alc861vd_adc_nids; | 14458 | spec->adc_nids = alc861vd_adc_nids; |
14601 | spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids); | 14459 | spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids); |
14602 | spec->capsrc_nids = alc861vd_capsrc_nids; | 14460 | spec->capsrc_nids = alc861vd_capsrc_nids; |
14461 | spec->is_mix_capture = 1; | ||
14603 | 14462 | ||
14604 | spec->mixers[spec->num_mixers] = alc861vd_capture_mixer; | 14463 | set_capture_mixer(spec); |
14605 | spec->num_mixers++; | ||
14606 | 14464 | ||
14607 | spec->vmaster_nid = 0x02; | 14465 | spec->vmaster_nid = 0x02; |
14608 | 14466 | ||
@@ -14689,10 +14547,6 @@ static struct hda_input_mux alc663_m51va_capture_source = { | |||
14689 | }, | 14547 | }, |
14690 | }; | 14548 | }; |
14691 | 14549 | ||
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 | /* | 14550 | /* |
14697 | * 2ch mode | 14551 | * 2ch mode |
14698 | */ | 14552 | */ |
@@ -15278,25 +15132,6 @@ static struct hda_verb alc662_ecs_init_verbs[] = { | |||
15278 | {} | 15132 | {} |
15279 | }; | 15133 | }; |
15280 | 15134 | ||
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[] = { | 15135 | static struct snd_kcontrol_new alc662_auto_capture_mixer[] = { |
15301 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), | 15136 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), |
15302 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), | 15137 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), |
@@ -15868,7 +15703,7 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = { | |||
15868 | 15703 | ||
15869 | static struct alc_config_preset alc662_presets[] = { | 15704 | static struct alc_config_preset alc662_presets[] = { |
15870 | [ALC662_3ST_2ch_DIG] = { | 15705 | [ALC662_3ST_2ch_DIG] = { |
15871 | .mixers = { alc662_3ST_2ch_mixer, alc662_capture_mixer }, | 15706 | .mixers = { alc662_3ST_2ch_mixer }, |
15872 | .init_verbs = { alc662_init_verbs }, | 15707 | .init_verbs = { alc662_init_verbs }, |
15873 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 15708 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
15874 | .dac_nids = alc662_dac_nids, | 15709 | .dac_nids = alc662_dac_nids, |
@@ -15879,8 +15714,7 @@ static struct alc_config_preset alc662_presets[] = { | |||
15879 | .input_mux = &alc662_capture_source, | 15714 | .input_mux = &alc662_capture_source, |
15880 | }, | 15715 | }, |
15881 | [ALC662_3ST_6ch_DIG] = { | 15716 | [ALC662_3ST_6ch_DIG] = { |
15882 | .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer, | 15717 | .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer }, |
15883 | alc662_capture_mixer }, | ||
15884 | .init_verbs = { alc662_init_verbs }, | 15718 | .init_verbs = { alc662_init_verbs }, |
15885 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 15719 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
15886 | .dac_nids = alc662_dac_nids, | 15720 | .dac_nids = alc662_dac_nids, |
@@ -15892,8 +15726,7 @@ static struct alc_config_preset alc662_presets[] = { | |||
15892 | .input_mux = &alc662_capture_source, | 15726 | .input_mux = &alc662_capture_source, |
15893 | }, | 15727 | }, |
15894 | [ALC662_3ST_6ch] = { | 15728 | [ALC662_3ST_6ch] = { |
15895 | .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer, | 15729 | .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer }, |
15896 | alc662_capture_mixer }, | ||
15897 | .init_verbs = { alc662_init_verbs }, | 15730 | .init_verbs = { alc662_init_verbs }, |
15898 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 15731 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
15899 | .dac_nids = alc662_dac_nids, | 15732 | .dac_nids = alc662_dac_nids, |
@@ -15903,8 +15736,7 @@ static struct alc_config_preset alc662_presets[] = { | |||
15903 | .input_mux = &alc662_capture_source, | 15736 | .input_mux = &alc662_capture_source, |
15904 | }, | 15737 | }, |
15905 | [ALC662_5ST_DIG] = { | 15738 | [ALC662_5ST_DIG] = { |
15906 | .mixers = { alc662_base_mixer, alc662_chmode_mixer, | 15739 | .mixers = { alc662_base_mixer, alc662_chmode_mixer }, |
15907 | alc662_capture_mixer }, | ||
15908 | .init_verbs = { alc662_init_verbs }, | 15740 | .init_verbs = { alc662_init_verbs }, |
15909 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 15741 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
15910 | .dac_nids = alc662_dac_nids, | 15742 | .dac_nids = alc662_dac_nids, |
@@ -15915,7 +15747,7 @@ static struct alc_config_preset alc662_presets[] = { | |||
15915 | .input_mux = &alc662_capture_source, | 15747 | .input_mux = &alc662_capture_source, |
15916 | }, | 15748 | }, |
15917 | [ALC662_LENOVO_101E] = { | 15749 | [ALC662_LENOVO_101E] = { |
15918 | .mixers = { alc662_lenovo_101e_mixer, alc662_capture_mixer }, | 15750 | .mixers = { alc662_lenovo_101e_mixer }, |
15919 | .init_verbs = { alc662_init_verbs, alc662_sue_init_verbs }, | 15751 | .init_verbs = { alc662_init_verbs, alc662_sue_init_verbs }, |
15920 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 15752 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
15921 | .dac_nids = alc662_dac_nids, | 15753 | .dac_nids = alc662_dac_nids, |
@@ -15926,7 +15758,7 @@ static struct alc_config_preset alc662_presets[] = { | |||
15926 | .init_hook = alc662_lenovo_101e_all_automute, | 15758 | .init_hook = alc662_lenovo_101e_all_automute, |
15927 | }, | 15759 | }, |
15928 | [ALC662_ASUS_EEEPC_P701] = { | 15760 | [ALC662_ASUS_EEEPC_P701] = { |
15929 | .mixers = { alc662_eeepc_p701_mixer, alc662_capture_mixer }, | 15761 | .mixers = { alc662_eeepc_p701_mixer }, |
15930 | .init_verbs = { alc662_init_verbs, | 15762 | .init_verbs = { alc662_init_verbs, |
15931 | alc662_eeepc_sue_init_verbs }, | 15763 | alc662_eeepc_sue_init_verbs }, |
15932 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 15764 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
@@ -15938,7 +15770,7 @@ static struct alc_config_preset alc662_presets[] = { | |||
15938 | .init_hook = alc662_eeepc_inithook, | 15770 | .init_hook = alc662_eeepc_inithook, |
15939 | }, | 15771 | }, |
15940 | [ALC662_ASUS_EEEPC_EP20] = { | 15772 | [ALC662_ASUS_EEEPC_EP20] = { |
15941 | .mixers = { alc662_eeepc_ep20_mixer, alc662_capture_mixer, | 15773 | .mixers = { alc662_eeepc_ep20_mixer, |
15942 | alc662_chmode_mixer }, | 15774 | alc662_chmode_mixer }, |
15943 | .init_verbs = { alc662_init_verbs, | 15775 | .init_verbs = { alc662_init_verbs, |
15944 | alc662_eeepc_ep20_sue_init_verbs }, | 15776 | alc662_eeepc_ep20_sue_init_verbs }, |
@@ -15951,7 +15783,7 @@ static struct alc_config_preset alc662_presets[] = { | |||
15951 | .init_hook = alc662_eeepc_ep20_inithook, | 15783 | .init_hook = alc662_eeepc_ep20_inithook, |
15952 | }, | 15784 | }, |
15953 | [ALC662_ECS] = { | 15785 | [ALC662_ECS] = { |
15954 | .mixers = { alc662_ecs_mixer, alc662_capture_mixer }, | 15786 | .mixers = { alc662_ecs_mixer }, |
15955 | .init_verbs = { alc662_init_verbs, | 15787 | .init_verbs = { alc662_init_verbs, |
15956 | alc662_ecs_init_verbs }, | 15788 | alc662_ecs_init_verbs }, |
15957 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 15789 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
@@ -15963,7 +15795,7 @@ static struct alc_config_preset alc662_presets[] = { | |||
15963 | .init_hook = alc662_eeepc_inithook, | 15795 | .init_hook = alc662_eeepc_inithook, |
15964 | }, | 15796 | }, |
15965 | [ALC663_ASUS_M51VA] = { | 15797 | [ALC663_ASUS_M51VA] = { |
15966 | .mixers = { alc663_m51va_mixer, alc662_capture_mixer}, | 15798 | .mixers = { alc663_m51va_mixer }, |
15967 | .init_verbs = { alc662_init_verbs, alc663_m51va_init_verbs }, | 15799 | .init_verbs = { alc662_init_verbs, alc663_m51va_init_verbs }, |
15968 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 15800 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
15969 | .dac_nids = alc662_dac_nids, | 15801 | .dac_nids = alc662_dac_nids, |
@@ -15975,7 +15807,7 @@ static struct alc_config_preset alc662_presets[] = { | |||
15975 | .init_hook = alc663_m51va_inithook, | 15807 | .init_hook = alc663_m51va_inithook, |
15976 | }, | 15808 | }, |
15977 | [ALC663_ASUS_G71V] = { | 15809 | [ALC663_ASUS_G71V] = { |
15978 | .mixers = { alc663_g71v_mixer, alc662_capture_mixer}, | 15810 | .mixers = { alc663_g71v_mixer }, |
15979 | .init_verbs = { alc662_init_verbs, alc663_g71v_init_verbs }, | 15811 | .init_verbs = { alc662_init_verbs, alc663_g71v_init_verbs }, |
15980 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 15812 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
15981 | .dac_nids = alc662_dac_nids, | 15813 | .dac_nids = alc662_dac_nids, |
@@ -15987,7 +15819,7 @@ static struct alc_config_preset alc662_presets[] = { | |||
15987 | .init_hook = alc663_g71v_inithook, | 15819 | .init_hook = alc663_g71v_inithook, |
15988 | }, | 15820 | }, |
15989 | [ALC663_ASUS_H13] = { | 15821 | [ALC663_ASUS_H13] = { |
15990 | .mixers = { alc663_m51va_mixer, alc662_capture_mixer}, | 15822 | .mixers = { alc663_m51va_mixer }, |
15991 | .init_verbs = { alc662_init_verbs, alc663_m51va_init_verbs }, | 15823 | .init_verbs = { alc662_init_verbs, alc663_m51va_init_verbs }, |
15992 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 15824 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
15993 | .dac_nids = alc662_dac_nids, | 15825 | .dac_nids = alc662_dac_nids, |
@@ -15998,7 +15830,7 @@ static struct alc_config_preset alc662_presets[] = { | |||
15998 | .init_hook = alc663_m51va_inithook, | 15830 | .init_hook = alc663_m51va_inithook, |
15999 | }, | 15831 | }, |
16000 | [ALC663_ASUS_G50V] = { | 15832 | [ALC663_ASUS_G50V] = { |
16001 | .mixers = { alc663_g50v_mixer, alc662_capture_mixer}, | 15833 | .mixers = { alc663_g50v_mixer }, |
16002 | .init_verbs = { alc662_init_verbs, alc663_g50v_init_verbs }, | 15834 | .init_verbs = { alc662_init_verbs, alc663_g50v_init_verbs }, |
16003 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 15835 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
16004 | .dac_nids = alc662_dac_nids, | 15836 | .dac_nids = alc662_dac_nids, |
@@ -16010,7 +15842,8 @@ static struct alc_config_preset alc662_presets[] = { | |||
16010 | .init_hook = alc663_g50v_inithook, | 15842 | .init_hook = alc663_g50v_inithook, |
16011 | }, | 15843 | }, |
16012 | [ALC663_ASUS_MODE1] = { | 15844 | [ALC663_ASUS_MODE1] = { |
16013 | .mixers = { alc663_m51va_mixer, alc662_auto_capture_mixer }, | 15845 | .mixers = { alc663_m51va_mixer }, |
15846 | .cap_mixer = alc662_auto_capture_mixer, | ||
16014 | .init_verbs = { alc662_init_verbs, | 15847 | .init_verbs = { alc662_init_verbs, |
16015 | alc663_21jd_amic_init_verbs }, | 15848 | alc663_21jd_amic_init_verbs }, |
16016 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 15849 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
@@ -16024,7 +15857,8 @@ static struct alc_config_preset alc662_presets[] = { | |||
16024 | .init_hook = alc663_mode1_inithook, | 15857 | .init_hook = alc663_mode1_inithook, |
16025 | }, | 15858 | }, |
16026 | [ALC662_ASUS_MODE2] = { | 15859 | [ALC662_ASUS_MODE2] = { |
16027 | .mixers = { alc662_1bjd_mixer, alc662_auto_capture_mixer }, | 15860 | .mixers = { alc662_1bjd_mixer }, |
15861 | .cap_mixer = alc662_auto_capture_mixer, | ||
16028 | .init_verbs = { alc662_init_verbs, | 15862 | .init_verbs = { alc662_init_verbs, |
16029 | alc662_1bjd_amic_init_verbs }, | 15863 | alc662_1bjd_amic_init_verbs }, |
16030 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 15864 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
@@ -16037,7 +15871,8 @@ static struct alc_config_preset alc662_presets[] = { | |||
16037 | .init_hook = alc662_mode2_inithook, | 15871 | .init_hook = alc662_mode2_inithook, |
16038 | }, | 15872 | }, |
16039 | [ALC663_ASUS_MODE3] = { | 15873 | [ALC663_ASUS_MODE3] = { |
16040 | .mixers = { alc663_two_hp_m1_mixer, alc662_auto_capture_mixer }, | 15874 | .mixers = { alc663_two_hp_m1_mixer }, |
15875 | .cap_mixer = alc662_auto_capture_mixer, | ||
16041 | .init_verbs = { alc662_init_verbs, | 15876 | .init_verbs = { alc662_init_verbs, |
16042 | alc663_two_hp_amic_m1_init_verbs }, | 15877 | alc663_two_hp_amic_m1_init_verbs }, |
16043 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 15878 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
@@ -16051,8 +15886,8 @@ static struct alc_config_preset alc662_presets[] = { | |||
16051 | .init_hook = alc663_mode3_inithook, | 15886 | .init_hook = alc663_mode3_inithook, |
16052 | }, | 15887 | }, |
16053 | [ALC663_ASUS_MODE4] = { | 15888 | [ALC663_ASUS_MODE4] = { |
16054 | .mixers = { alc663_asus_21jd_clfe_mixer, | 15889 | .mixers = { alc663_asus_21jd_clfe_mixer }, |
16055 | alc662_auto_capture_mixer}, | 15890 | .cap_mixer = alc662_auto_capture_mixer, |
16056 | .init_verbs = { alc662_init_verbs, | 15891 | .init_verbs = { alc662_init_verbs, |
16057 | alc663_21jd_amic_init_verbs}, | 15892 | alc663_21jd_amic_init_verbs}, |
16058 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 15893 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
@@ -16066,8 +15901,8 @@ static struct alc_config_preset alc662_presets[] = { | |||
16066 | .init_hook = alc663_mode4_inithook, | 15901 | .init_hook = alc663_mode4_inithook, |
16067 | }, | 15902 | }, |
16068 | [ALC663_ASUS_MODE5] = { | 15903 | [ALC663_ASUS_MODE5] = { |
16069 | .mixers = { alc663_asus_15jd_clfe_mixer, | 15904 | .mixers = { alc663_asus_15jd_clfe_mixer }, |
16070 | alc662_auto_capture_mixer }, | 15905 | .cap_mixer = alc662_auto_capture_mixer, |
16071 | .init_verbs = { alc662_init_verbs, | 15906 | .init_verbs = { alc662_init_verbs, |
16072 | alc663_15jd_amic_init_verbs }, | 15907 | alc663_15jd_amic_init_verbs }, |
16073 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 15908 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
@@ -16081,7 +15916,8 @@ static struct alc_config_preset alc662_presets[] = { | |||
16081 | .init_hook = alc663_mode5_inithook, | 15916 | .init_hook = alc663_mode5_inithook, |
16082 | }, | 15917 | }, |
16083 | [ALC663_ASUS_MODE6] = { | 15918 | [ALC663_ASUS_MODE6] = { |
16084 | .mixers = { alc663_two_hp_m2_mixer, alc662_auto_capture_mixer }, | 15919 | .mixers = { alc663_two_hp_m2_mixer }, |
15920 | .cap_mixer = alc662_auto_capture_mixer, | ||
16085 | .init_verbs = { alc662_init_verbs, | 15921 | .init_verbs = { alc662_init_verbs, |
16086 | alc663_two_hp_amic_m2_init_verbs }, | 15922 | alc663_two_hp_amic_m2_init_verbs }, |
16087 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 15923 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
@@ -16342,24 +16178,20 @@ static int alc662_parse_auto_config(struct hda_codec *codec) | |||
16342 | if (spec->autocfg.dig_out_pin) | 16178 | if (spec->autocfg.dig_out_pin) |
16343 | spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; | 16179 | spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; |
16344 | 16180 | ||
16345 | if (spec->kctl_alloc) | 16181 | if (spec->kctls.list) |
16346 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 16182 | add_mixer(spec, spec->kctls.list); |
16347 | 16183 | ||
16348 | spec->num_mux_defs = 1; | 16184 | spec->num_mux_defs = 1; |
16349 | spec->input_mux = &spec->private_imux; | 16185 | spec->input_mux = &spec->private_imux; |
16350 | 16186 | ||
16351 | spec->init_verbs[spec->num_init_verbs++] = alc662_auto_init_verbs; | 16187 | add_verb(spec, alc662_auto_init_verbs); |
16352 | if (codec->vendor_id == 0x10ec0663) | 16188 | if (codec->vendor_id == 0x10ec0663) |
16353 | spec->init_verbs[spec->num_init_verbs++] = | 16189 | add_verb(spec, alc663_auto_init_verbs); |
16354 | alc663_auto_init_verbs; | ||
16355 | 16190 | ||
16356 | err = alc_auto_add_mic_boost(codec); | 16191 | err = alc_auto_add_mic_boost(codec); |
16357 | if (err < 0) | 16192 | if (err < 0) |
16358 | return err; | 16193 | return err; |
16359 | 16194 | ||
16360 | spec->mixers[spec->num_mixers] = alc662_capture_mixer; | ||
16361 | spec->num_mixers++; | ||
16362 | |||
16363 | store_pin_configs(codec); | 16195 | store_pin_configs(codec); |
16364 | return 1; | 16196 | return 1; |
16365 | } | 16197 | } |
@@ -16435,6 +16267,10 @@ static int patch_alc662(struct hda_codec *codec) | |||
16435 | spec->adc_nids = alc662_adc_nids; | 16267 | spec->adc_nids = alc662_adc_nids; |
16436 | spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids); | 16268 | spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids); |
16437 | spec->capsrc_nids = alc662_capsrc_nids; | 16269 | spec->capsrc_nids = alc662_capsrc_nids; |
16270 | spec->is_mix_capture = 1; | ||
16271 | |||
16272 | if (!spec->cap_mixer) | ||
16273 | set_capture_mixer(spec); | ||
16438 | 16274 | ||
16439 | spec->vmaster_nid = 0x02; | 16275 | spec->vmaster_nid = 0x02; |
16440 | 16276 | ||
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index e6085915d86d..12c88c42d7f3 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -30,12 +30,13 @@ | |||
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 | #define STAC_INSERT_EVENT 0x10 |
39 | #define STAC_PWR_EVENT 0x20 | 40 | #define STAC_PWR_EVENT 0x20 |
40 | #define STAC_HP_EVENT 0x30 | 41 | #define STAC_HP_EVENT 0x30 |
41 | #define STAC_VREF_EVENT 0x40 | 42 | #define STAC_VREF_EVENT 0x40 |
@@ -130,6 +131,17 @@ enum { | |||
130 | STAC_927X_MODELS | 131 | STAC_927X_MODELS |
131 | }; | 132 | }; |
132 | 133 | ||
134 | struct sigmatel_event { | ||
135 | hda_nid_t nid; | ||
136 | int data; | ||
137 | }; | ||
138 | |||
139 | struct sigmatel_jack { | ||
140 | hda_nid_t nid; | ||
141 | int type; | ||
142 | struct snd_jack *jack; | ||
143 | }; | ||
144 | |||
133 | struct sigmatel_spec { | 145 | struct sigmatel_spec { |
134 | struct snd_kcontrol_new *mixers[4]; | 146 | struct snd_kcontrol_new *mixers[4]; |
135 | unsigned int num_mixers; | 147 | unsigned int num_mixers; |
@@ -162,6 +174,12 @@ struct sigmatel_spec { | |||
162 | hda_nid_t *pwr_nids; | 174 | hda_nid_t *pwr_nids; |
163 | hda_nid_t *dac_list; | 175 | hda_nid_t *dac_list; |
164 | 176 | ||
177 | /* jack detection */ | ||
178 | struct snd_array jacks; | ||
179 | |||
180 | /* events */ | ||
181 | struct snd_array events; | ||
182 | |||
165 | /* playback */ | 183 | /* playback */ |
166 | struct hda_input_mux *mono_mux; | 184 | struct hda_input_mux *mono_mux; |
167 | struct hda_input_mux *amp_mux; | 185 | struct hda_input_mux *amp_mux; |
@@ -219,8 +237,7 @@ struct sigmatel_spec { | |||
219 | 237 | ||
220 | /* dynamic controls and input_mux */ | 238 | /* dynamic controls and input_mux */ |
221 | struct auto_pin_cfg autocfg; | 239 | struct auto_pin_cfg autocfg; |
222 | unsigned int num_kctl_alloc, num_kctl_used; | 240 | struct snd_array kctls; |
223 | struct snd_kcontrol_new *kctl_alloc; | ||
224 | struct hda_input_mux private_dimux; | 241 | struct hda_input_mux private_dimux; |
225 | struct hda_input_mux private_imux; | 242 | struct hda_input_mux private_imux; |
226 | struct hda_input_mux private_smux; | 243 | struct hda_input_mux private_smux; |
@@ -1230,6 +1247,8 @@ static const char *slave_sws[] = { | |||
1230 | NULL | 1247 | NULL |
1231 | }; | 1248 | }; |
1232 | 1249 | ||
1250 | static void stac92xx_free_kctls(struct hda_codec *codec); | ||
1251 | |||
1233 | static int stac92xx_build_controls(struct hda_codec *codec) | 1252 | static int stac92xx_build_controls(struct hda_codec *codec) |
1234 | { | 1253 | { |
1235 | struct sigmatel_spec *spec = codec->spec; | 1254 | struct sigmatel_spec *spec = codec->spec; |
@@ -1247,7 +1266,7 @@ static int stac92xx_build_controls(struct hda_codec *codec) | |||
1247 | } | 1266 | } |
1248 | if (spec->num_dmuxes > 0) { | 1267 | if (spec->num_dmuxes > 0) { |
1249 | stac_dmux_mixer.count = spec->num_dmuxes; | 1268 | stac_dmux_mixer.count = spec->num_dmuxes; |
1250 | err = snd_ctl_add(codec->bus->card, | 1269 | err = snd_hda_ctl_add(codec, |
1251 | snd_ctl_new1(&stac_dmux_mixer, codec)); | 1270 | snd_ctl_new1(&stac_dmux_mixer, codec)); |
1252 | if (err < 0) | 1271 | if (err < 0) |
1253 | return err; | 1272 | return err; |
@@ -1302,6 +1321,7 @@ static int stac92xx_build_controls(struct hda_codec *codec) | |||
1302 | return err; | 1321 | return err; |
1303 | } | 1322 | } |
1304 | 1323 | ||
1324 | stac92xx_free_kctls(codec); /* no longer needed */ | ||
1305 | return 0; | 1325 | return 0; |
1306 | } | 1326 | } |
1307 | 1327 | ||
@@ -2452,13 +2472,15 @@ static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol, | |||
2452 | { | 2472 | { |
2453 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 2473 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
2454 | struct sigmatel_spec *spec = codec->spec; | 2474 | struct sigmatel_spec *spec = codec->spec; |
2475 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
2476 | int nid = cfg->hp_pins[cfg->hp_outs - 1]; | ||
2455 | 2477 | ||
2456 | spec->hp_switch = ucontrol->value.integer.value[0]; | 2478 | spec->hp_switch = ucontrol->value.integer.value[0]; |
2457 | 2479 | ||
2458 | /* check to be sure that the ports are upto date with | 2480 | /* check to be sure that the ports are upto date with |
2459 | * switch changes | 2481 | * switch changes |
2460 | */ | 2482 | */ |
2461 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | 2483 | codec->patch_ops.unsol_event(codec, (STAC_HP_EVENT | nid) << 26); |
2462 | 2484 | ||
2463 | return 1; | 2485 | return 1; |
2464 | } | 2486 | } |
@@ -2498,7 +2520,8 @@ static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
2498 | * appropriately according to the pin direction | 2520 | * appropriately according to the pin direction |
2499 | */ | 2521 | */ |
2500 | if (spec->hp_detect) | 2522 | if (spec->hp_detect) |
2501 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | 2523 | codec->patch_ops.unsol_event(codec, |
2524 | (STAC_HP_EVENT | nid) << 26); | ||
2502 | 2525 | ||
2503 | return 1; | 2526 | return 1; |
2504 | } | 2527 | } |
@@ -2591,28 +2614,16 @@ static int stac92xx_add_control_idx(struct sigmatel_spec *spec, int type, | |||
2591 | { | 2614 | { |
2592 | struct snd_kcontrol_new *knew; | 2615 | struct snd_kcontrol_new *knew; |
2593 | 2616 | ||
2594 | if (spec->num_kctl_used >= spec->num_kctl_alloc) { | 2617 | snd_array_init(&spec->kctls, sizeof(*knew), 32); |
2595 | int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC; | 2618 | knew = snd_array_new(&spec->kctls); |
2596 | 2619 | if (!knew) | |
2597 | knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */ | 2620 | return -ENOMEM; |
2598 | if (! knew) | ||
2599 | return -ENOMEM; | ||
2600 | if (spec->kctl_alloc) { | ||
2601 | memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc); | ||
2602 | kfree(spec->kctl_alloc); | ||
2603 | } | ||
2604 | spec->kctl_alloc = knew; | ||
2605 | spec->num_kctl_alloc = num; | ||
2606 | } | ||
2607 | |||
2608 | knew = &spec->kctl_alloc[spec->num_kctl_used]; | ||
2609 | *knew = stac92xx_control_templates[type]; | 2621 | *knew = stac92xx_control_templates[type]; |
2610 | knew->index = idx; | 2622 | knew->index = idx; |
2611 | knew->name = kstrdup(name, GFP_KERNEL); | 2623 | knew->name = kstrdup(name, GFP_KERNEL); |
2612 | if (! knew->name) | 2624 | if (! knew->name) |
2613 | return -ENOMEM; | 2625 | return -ENOMEM; |
2614 | knew->private_value = val; | 2626 | knew->private_value = val; |
2615 | spec->num_kctl_used++; | ||
2616 | return 0; | 2627 | return 0; |
2617 | } | 2628 | } |
2618 | 2629 | ||
@@ -3433,8 +3444,8 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
3433 | if (dig_in && spec->autocfg.dig_in_pin) | 3444 | if (dig_in && spec->autocfg.dig_in_pin) |
3434 | spec->dig_in_nid = dig_in; | 3445 | spec->dig_in_nid = dig_in; |
3435 | 3446 | ||
3436 | if (spec->kctl_alloc) | 3447 | if (spec->kctls.list) |
3437 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 3448 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
3438 | 3449 | ||
3439 | spec->input_mux = &spec->private_imux; | 3450 | spec->input_mux = &spec->private_imux; |
3440 | spec->dinput_mux = &spec->private_dimux; | 3451 | spec->dinput_mux = &spec->private_dimux; |
@@ -3535,8 +3546,8 @@ static int stac9200_parse_auto_config(struct hda_codec *codec) | |||
3535 | if (spec->autocfg.dig_in_pin) | 3546 | if (spec->autocfg.dig_in_pin) |
3536 | spec->dig_in_nid = 0x04; | 3547 | spec->dig_in_nid = 0x04; |
3537 | 3548 | ||
3538 | if (spec->kctl_alloc) | 3549 | if (spec->kctls.list) |
3539 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 3550 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
3540 | 3551 | ||
3541 | spec->input_mux = &spec->private_imux; | 3552 | spec->input_mux = &spec->private_imux; |
3542 | spec->dinput_mux = &spec->private_dimux; | 3553 | spec->dinput_mux = &spec->private_dimux; |
@@ -3580,13 +3591,70 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask, | |||
3580 | AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */ | 3591 | AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */ |
3581 | } | 3592 | } |
3582 | 3593 | ||
3594 | static int stac92xx_add_jack(struct hda_codec *codec, | ||
3595 | hda_nid_t nid, int type) | ||
3596 | { | ||
3597 | struct sigmatel_spec *spec = codec->spec; | ||
3598 | struct sigmatel_jack *jack; | ||
3599 | int def_conf = snd_hda_codec_read(codec, nid, | ||
3600 | 0, AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
3601 | int connectivity = get_defcfg_connect(def_conf); | ||
3602 | char name[32]; | ||
3603 | |||
3604 | if (connectivity && connectivity != AC_JACK_PORT_FIXED) | ||
3605 | return 0; | ||
3606 | |||
3607 | snd_array_init(&spec->jacks, sizeof(*jack), 32); | ||
3608 | jack = snd_array_new(&spec->jacks); | ||
3609 | if (!jack) | ||
3610 | return -ENOMEM; | ||
3611 | jack->nid = nid; | ||
3612 | jack->type = type; | ||
3613 | |||
3614 | sprintf(name, "%s at %s %s Jack", | ||
3615 | snd_hda_get_jack_type(def_conf), | ||
3616 | snd_hda_get_jack_connectivity(def_conf), | ||
3617 | snd_hda_get_jack_location(def_conf)); | ||
3618 | |||
3619 | return snd_jack_new(codec->bus->card, name, type, &jack->jack); | ||
3620 | } | ||
3621 | |||
3622 | static int stac92xx_add_event(struct sigmatel_spec *spec, hda_nid_t nid, | ||
3623 | int data) | ||
3624 | { | ||
3625 | struct sigmatel_event *event; | ||
3626 | |||
3627 | snd_array_init(&spec->events, sizeof(*event), 32); | ||
3628 | event = snd_array_new(&spec->events); | ||
3629 | if (!event) | ||
3630 | return -ENOMEM; | ||
3631 | event->nid = nid; | ||
3632 | event->data = data; | ||
3633 | |||
3634 | return 0; | ||
3635 | } | ||
3636 | |||
3637 | static int stac92xx_event_data(struct hda_codec *codec, hda_nid_t nid) | ||
3638 | { | ||
3639 | struct sigmatel_spec *spec = codec->spec; | ||
3640 | struct sigmatel_event *events = spec->events.list; | ||
3641 | if (events) { | ||
3642 | int i; | ||
3643 | for (i = 0; i < spec->events.used; i++) | ||
3644 | if (events[i].nid == nid) | ||
3645 | return events[i].data; | ||
3646 | } | ||
3647 | return 0; | ||
3648 | } | ||
3649 | |||
3583 | static void enable_pin_detect(struct hda_codec *codec, hda_nid_t nid, | 3650 | static void enable_pin_detect(struct hda_codec *codec, hda_nid_t nid, |
3584 | unsigned int event) | 3651 | unsigned int event) |
3585 | { | 3652 | { |
3586 | if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) | 3653 | if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) { |
3587 | snd_hda_codec_write_cache(codec, nid, 0, | 3654 | snd_hda_codec_write_cache(codec, nid, 0, |
3588 | AC_VERB_SET_UNSOLICITED_ENABLE, | 3655 | AC_VERB_SET_UNSOLICITED_ENABLE, |
3589 | (AC_USRSP_EN | event)); | 3656 | (AC_USRSP_EN | event | nid)); |
3657 | } | ||
3590 | } | 3658 | } |
3591 | 3659 | ||
3592 | static int is_nid_hp_pin(struct auto_pin_cfg *cfg, hda_nid_t nid) | 3660 | static int is_nid_hp_pin(struct auto_pin_cfg *cfg, hda_nid_t nid) |
@@ -3616,7 +3684,7 @@ static int stac92xx_init(struct hda_codec *codec) | |||
3616 | { | 3684 | { |
3617 | struct sigmatel_spec *spec = codec->spec; | 3685 | struct sigmatel_spec *spec = codec->spec; |
3618 | struct auto_pin_cfg *cfg = &spec->autocfg; | 3686 | struct auto_pin_cfg *cfg = &spec->autocfg; |
3619 | int i; | 3687 | int i, err; |
3620 | 3688 | ||
3621 | snd_hda_sequence_write(codec, spec->init); | 3689 | snd_hda_sequence_write(codec, spec->init); |
3622 | 3690 | ||
@@ -3629,21 +3697,36 @@ static int stac92xx_init(struct hda_codec *codec) | |||
3629 | /* set up pins */ | 3697 | /* set up pins */ |
3630 | if (spec->hp_detect) { | 3698 | if (spec->hp_detect) { |
3631 | /* Enable unsolicited responses on the HP widget */ | 3699 | /* Enable unsolicited responses on the HP widget */ |
3632 | for (i = 0; i < cfg->hp_outs; i++) | 3700 | for (i = 0; i < cfg->hp_outs; i++) { |
3633 | enable_pin_detect(codec, cfg->hp_pins[i], | 3701 | int type = SND_JACK_HEADPHONE; |
3634 | STAC_HP_EVENT); | 3702 | hda_nid_t nid = cfg->hp_pins[i]; |
3703 | enable_pin_detect(codec, nid, STAC_HP_EVENT | nid); | ||
3704 | /* jack detection */ | ||
3705 | if (cfg->hp_outs == i) | ||
3706 | type |= SND_JACK_LINEOUT; | ||
3707 | err = stac92xx_add_jack(codec, nid, type); | ||
3708 | if (err < 0) | ||
3709 | return err; | ||
3710 | |||
3711 | } | ||
3635 | /* force to enable the first line-out; the others are set up | 3712 | /* force to enable the first line-out; the others are set up |
3636 | * in unsol_event | 3713 | * in unsol_event |
3637 | */ | 3714 | */ |
3638 | stac92xx_auto_set_pinctl(codec, spec->autocfg.line_out_pins[0], | 3715 | stac92xx_auto_set_pinctl(codec, spec->autocfg.line_out_pins[0], |
3639 | AC_PINCTL_OUT_EN); | 3716 | AC_PINCTL_OUT_EN); |
3640 | stac92xx_auto_init_hp_out(codec); | ||
3641 | /* fake event to set up pins */ | 3717 | /* fake event to set up pins */ |
3642 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | 3718 | codec->patch_ops.unsol_event(codec, |
3719 | (STAC_HP_EVENT | spec->autocfg.hp_pins[0]) << 26); | ||
3643 | } else { | 3720 | } else { |
3644 | stac92xx_auto_init_multi_out(codec); | 3721 | stac92xx_auto_init_multi_out(codec); |
3645 | stac92xx_auto_init_hp_out(codec); | 3722 | stac92xx_auto_init_hp_out(codec); |
3646 | } | 3723 | } |
3724 | for (i = 0; i < cfg->line_outs; i++) { | ||
3725 | err = stac92xx_add_jack(codec, | ||
3726 | cfg->line_out_pins[i], SND_JACK_LINEOUT); | ||
3727 | if (err < 0) | ||
3728 | return err; | ||
3729 | } | ||
3647 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 3730 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
3648 | hda_nid_t nid = cfg->input_pins[i]; | 3731 | hda_nid_t nid = cfg->input_pins[i]; |
3649 | if (nid) { | 3732 | if (nid) { |
@@ -3656,6 +3739,11 @@ static int stac92xx_init(struct hda_codec *codec) | |||
3656 | if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC) | 3739 | if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC) |
3657 | pinctl |= stac92xx_get_vref(codec, nid); | 3740 | pinctl |= stac92xx_get_vref(codec, nid); |
3658 | stac92xx_auto_set_pinctl(codec, nid, pinctl); | 3741 | stac92xx_auto_set_pinctl(codec, nid, pinctl); |
3742 | err = stac92xx_add_jack(codec, nid, | ||
3743 | SND_JACK_MICROPHONE); | ||
3744 | if (err < 0) | ||
3745 | return err; | ||
3746 | enable_pin_detect(codec, nid, STAC_INSERT_EVENT | nid); | ||
3659 | } | 3747 | } |
3660 | } | 3748 | } |
3661 | for (i = 0; i < spec->num_dmics; i++) | 3749 | for (i = 0; i < spec->num_dmics; i++) |
@@ -3697,22 +3785,42 @@ static int stac92xx_init(struct hda_codec *codec) | |||
3697 | return 0; | 3785 | return 0; |
3698 | } | 3786 | } |
3699 | 3787 | ||
3788 | static void stac92xx_free_jacks(struct hda_codec *codec) | ||
3789 | { | ||
3790 | struct sigmatel_spec *spec = codec->spec; | ||
3791 | if (spec->jacks.list) { | ||
3792 | struct sigmatel_jack *jacks = spec->jacks.list; | ||
3793 | int i; | ||
3794 | for (i = 0; i < spec->jacks.used; i++) | ||
3795 | snd_device_free(codec->bus->card, &jacks[i].jack); | ||
3796 | } | ||
3797 | snd_array_free(&spec->jacks); | ||
3798 | } | ||
3799 | |||
3800 | static void stac92xx_free_kctls(struct hda_codec *codec) | ||
3801 | { | ||
3802 | struct sigmatel_spec *spec = codec->spec; | ||
3803 | |||
3804 | if (spec->kctls.list) { | ||
3805 | struct snd_kcontrol_new *kctl = spec->kctls.list; | ||
3806 | int i; | ||
3807 | for (i = 0; i < spec->kctls.used; i++) | ||
3808 | kfree(kctl[i].name); | ||
3809 | } | ||
3810 | snd_array_free(&spec->kctls); | ||
3811 | } | ||
3812 | |||
3700 | static void stac92xx_free(struct hda_codec *codec) | 3813 | static void stac92xx_free(struct hda_codec *codec) |
3701 | { | 3814 | { |
3702 | struct sigmatel_spec *spec = codec->spec; | 3815 | struct sigmatel_spec *spec = codec->spec; |
3703 | int i; | ||
3704 | 3816 | ||
3705 | if (! spec) | 3817 | if (! spec) |
3706 | return; | 3818 | return; |
3707 | 3819 | ||
3708 | if (spec->kctl_alloc) { | ||
3709 | for (i = 0; i < spec->num_kctl_used; i++) | ||
3710 | kfree(spec->kctl_alloc[i].name); | ||
3711 | kfree(spec->kctl_alloc); | ||
3712 | } | ||
3713 | |||
3714 | if (spec->bios_pin_configs) | 3820 | if (spec->bios_pin_configs) |
3715 | kfree(spec->bios_pin_configs); | 3821 | kfree(spec->bios_pin_configs); |
3822 | stac92xx_free_jacks(codec); | ||
3823 | snd_array_free(&spec->events); | ||
3716 | 3824 | ||
3717 | kfree(spec); | 3825 | kfree(spec); |
3718 | snd_hda_detach_beep_device(codec); | 3826 | snd_hda_detach_beep_device(codec); |
@@ -3851,24 +3959,57 @@ static void stac92xx_pin_sense(struct hda_codec *codec, int idx) | |||
3851 | 3959 | ||
3852 | /* power down unused output ports */ | 3960 | /* power down unused output ports */ |
3853 | snd_hda_codec_write(codec, codec->afg, 0, 0x7ec, val); | 3961 | snd_hda_codec_write(codec, codec->afg, 0, 0x7ec, val); |
3854 | }; | 3962 | } |
3963 | |||
3964 | static void stac92xx_report_jack(struct hda_codec *codec, hda_nid_t nid) | ||
3965 | { | ||
3966 | struct sigmatel_spec *spec = codec->spec; | ||
3967 | struct sigmatel_jack *jacks = spec->jacks.list; | ||
3968 | |||
3969 | if (jacks) { | ||
3970 | int i; | ||
3971 | for (i = 0; i < spec->jacks.used; i++) { | ||
3972 | if (jacks->nid == nid) { | ||
3973 | unsigned int pin_ctl = | ||
3974 | snd_hda_codec_read(codec, nid, | ||
3975 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, | ||
3976 | 0x00); | ||
3977 | int type = jacks->type; | ||
3978 | if (type == (SND_JACK_LINEOUT | ||
3979 | | SND_JACK_HEADPHONE)) | ||
3980 | type = (pin_ctl & AC_PINCTL_HP_EN) | ||
3981 | ? SND_JACK_HEADPHONE : SND_JACK_LINEOUT; | ||
3982 | snd_jack_report(jacks->jack, | ||
3983 | get_hp_pin_presence(codec, nid) | ||
3984 | ? type : 0); | ||
3985 | } | ||
3986 | jacks++; | ||
3987 | } | ||
3988 | } | ||
3989 | } | ||
3855 | 3990 | ||
3856 | static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) | 3991 | static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) |
3857 | { | 3992 | { |
3858 | struct sigmatel_spec *spec = codec->spec; | 3993 | struct sigmatel_spec *spec = codec->spec; |
3859 | int idx = res >> 26 & 0x0f; | 3994 | int event = (res >> 26) & 0x70; |
3995 | int nid = res >> 26 & 0x0f; | ||
3860 | 3996 | ||
3861 | switch ((res >> 26) & 0x70) { | 3997 | switch (event) { |
3862 | case STAC_HP_EVENT: | 3998 | case STAC_HP_EVENT: |
3863 | stac92xx_hp_detect(codec, res); | 3999 | stac92xx_hp_detect(codec, res); |
3864 | /* fallthru */ | 4000 | /* fallthru */ |
4001 | case STAC_INSERT_EVENT: | ||
3865 | case STAC_PWR_EVENT: | 4002 | case STAC_PWR_EVENT: |
3866 | if (spec->num_pwrs > 0) | 4003 | if (nid) { |
3867 | stac92xx_pin_sense(codec, idx); | 4004 | if (spec->num_pwrs > 0) |
4005 | stac92xx_pin_sense(codec, nid); | ||
4006 | stac92xx_report_jack(codec, nid); | ||
4007 | } | ||
3868 | break; | 4008 | break; |
3869 | case STAC_VREF_EVENT: { | 4009 | case STAC_VREF_EVENT: { |
3870 | int data = snd_hda_codec_read(codec, codec->afg, 0, | 4010 | int data = snd_hda_codec_read(codec, codec->afg, 0, |
3871 | AC_VERB_GET_GPIO_DATA, 0); | 4011 | AC_VERB_GET_GPIO_DATA, 0); |
4012 | int idx = stac92xx_event_data(codec, nid); | ||
3872 | /* toggle VREF state based on GPIOx status */ | 4013 | /* toggle VREF state based on GPIOx status */ |
3873 | snd_hda_codec_write(codec, codec->afg, 0, 0x7e0, | 4014 | snd_hda_codec_write(codec, codec->afg, 0, 0x7e0, |
3874 | !!(data & (1 << idx))); | 4015 | !!(data & (1 << idx))); |
@@ -4394,8 +4535,11 @@ again: | |||
4394 | snd_hda_codec_write(codec, codec->afg, 0, | 4535 | snd_hda_codec_write(codec, codec->afg, 0, |
4395 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02); | 4536 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02); |
4396 | snd_hda_codec_write_cache(codec, codec->afg, 0, | 4537 | snd_hda_codec_write_cache(codec, codec->afg, 0, |
4397 | AC_VERB_SET_UNSOLICITED_ENABLE, | 4538 | AC_VERB_SET_UNSOLICITED_ENABLE, |
4398 | (AC_USRSP_EN | STAC_VREF_EVENT | 0x01)); | 4539 | (AC_USRSP_EN | STAC_VREF_EVENT | codec->afg)); |
4540 | err = stac92xx_add_event(spec, codec->afg, 0x02); | ||
4541 | if (err < 0) | ||
4542 | return err; | ||
4399 | spec->gpio_mask |= 0x02; | 4543 | spec->gpio_mask |= 0x02; |
4400 | break; | 4544 | break; |
4401 | } | 4545 | } |
@@ -4794,8 +4938,11 @@ static int patch_stac9205(struct hda_codec *codec) | |||
4794 | snd_hda_codec_write(codec, codec->afg, 0, | 4938 | snd_hda_codec_write(codec, codec->afg, 0, |
4795 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10); | 4939 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10); |
4796 | snd_hda_codec_write_cache(codec, codec->afg, 0, | 4940 | snd_hda_codec_write_cache(codec, codec->afg, 0, |
4797 | AC_VERB_SET_UNSOLICITED_ENABLE, | 4941 | AC_VERB_SET_UNSOLICITED_ENABLE, |
4798 | (AC_USRSP_EN | STAC_HP_EVENT)); | 4942 | (AC_USRSP_EN | STAC_VREF_EVENT | codec->afg)); |
4943 | err = stac92xx_add_event(spec, codec->afg, 0x01); | ||
4944 | if (err < 0) | ||
4945 | return err; | ||
4799 | 4946 | ||
4800 | spec->gpio_dir = 0x0b; | 4947 | spec->gpio_dir = 0x0b; |
4801 | spec->eapd_mask = 0x01; | 4948 | spec->eapd_mask = 0x01; |
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 63e4871e5d8f..760e14ae3bff 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 |
@@ -227,8 +224,7 @@ struct via_spec { | |||
227 | 224 | ||
228 | /* dynamic controls, init_verbs and input_mux */ | 225 | /* dynamic controls, init_verbs and input_mux */ |
229 | struct auto_pin_cfg autocfg; | 226 | struct auto_pin_cfg autocfg; |
230 | unsigned int num_kctl_alloc, num_kctl_used; | 227 | struct snd_array kctls; |
231 | struct snd_kcontrol_new *kctl_alloc; | ||
232 | struct hda_input_mux private_imux[2]; | 228 | struct hda_input_mux private_imux[2]; |
233 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; | 229 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; |
234 | 230 | ||
@@ -272,33 +268,31 @@ static int via_add_control(struct via_spec *spec, int type, const char *name, | |||
272 | { | 268 | { |
273 | struct snd_kcontrol_new *knew; | 269 | struct snd_kcontrol_new *knew; |
274 | 270 | ||
275 | if (spec->num_kctl_used >= spec->num_kctl_alloc) { | 271 | snd_array_init(&spec->kctls, sizeof(*knew), 32); |
276 | int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC; | 272 | knew = snd_array_new(&spec->kctls); |
277 | 273 | if (!knew) | |
278 | /* array + terminator */ | 274 | 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]; | 275 | *knew = vt1708_control_templates[type]; |
293 | knew->name = kstrdup(name, GFP_KERNEL); | 276 | knew->name = kstrdup(name, GFP_KERNEL); |
294 | |||
295 | if (!knew->name) | 277 | if (!knew->name) |
296 | return -ENOMEM; | 278 | return -ENOMEM; |
297 | knew->private_value = val; | 279 | knew->private_value = val; |
298 | spec->num_kctl_used++; | ||
299 | return 0; | 280 | return 0; |
300 | } | 281 | } |
301 | 282 | ||
283 | static void via_free_kctls(struct hda_codec *codec) | ||
284 | { | ||
285 | struct via_spec *spec = codec->spec; | ||
286 | |||
287 | if (spec->kctls.list) { | ||
288 | struct snd_kcontrol_new *kctl = spec->kctls.list; | ||
289 | int i; | ||
290 | for (i = 0; i < spec->kctls.used; i++) | ||
291 | kfree(kctl[i].name); | ||
292 | } | ||
293 | snd_array_free(&spec->kctls); | ||
294 | } | ||
295 | |||
302 | /* create input playback/capture controls for the given pin */ | 296 | /* create input playback/capture controls for the given pin */ |
303 | static int via_new_analog_input(struct via_spec *spec, hda_nid_t pin, | 297 | static int via_new_analog_input(struct via_spec *spec, hda_nid_t pin, |
304 | const char *ctlname, int idx, int mix_nid) | 298 | const char *ctlname, int idx, int mix_nid) |
@@ -896,6 +890,7 @@ static int via_build_controls(struct hda_codec *codec) | |||
896 | if (err < 0) | 890 | if (err < 0) |
897 | return err; | 891 | return err; |
898 | } | 892 | } |
893 | via_free_kctls(codec); /* no longer needed */ | ||
899 | return 0; | 894 | return 0; |
900 | } | 895 | } |
901 | 896 | ||
@@ -941,17 +936,11 @@ static int via_build_pcms(struct hda_codec *codec) | |||
941 | static void via_free(struct hda_codec *codec) | 936 | static void via_free(struct hda_codec *codec) |
942 | { | 937 | { |
943 | struct via_spec *spec = codec->spec; | 938 | struct via_spec *spec = codec->spec; |
944 | unsigned int i; | ||
945 | 939 | ||
946 | if (!spec) | 940 | if (!spec) |
947 | return; | 941 | return; |
948 | 942 | ||
949 | if (spec->kctl_alloc) { | 943 | 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); | 944 | kfree(codec->spec); |
956 | } | 945 | } |
957 | 946 | ||
@@ -1373,8 +1362,8 @@ static int vt1708_parse_auto_config(struct hda_codec *codec) | |||
1373 | if (spec->autocfg.dig_in_pin) | 1362 | if (spec->autocfg.dig_in_pin) |
1374 | spec->dig_in_nid = VT1708_DIGIN_NID; | 1363 | spec->dig_in_nid = VT1708_DIGIN_NID; |
1375 | 1364 | ||
1376 | if (spec->kctl_alloc) | 1365 | if (spec->kctls.list) |
1377 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 1366 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
1378 | 1367 | ||
1379 | spec->init_verbs[spec->num_iverbs++] = vt1708_volume_init_verbs; | 1368 | spec->init_verbs[spec->num_iverbs++] = vt1708_volume_init_verbs; |
1380 | 1369 | ||
@@ -1846,8 +1835,8 @@ static int vt1709_parse_auto_config(struct hda_codec *codec) | |||
1846 | if (spec->autocfg.dig_in_pin) | 1835 | if (spec->autocfg.dig_in_pin) |
1847 | spec->dig_in_nid = VT1709_DIGIN_NID; | 1836 | spec->dig_in_nid = VT1709_DIGIN_NID; |
1848 | 1837 | ||
1849 | if (spec->kctl_alloc) | 1838 | if (spec->kctls.list) |
1850 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 1839 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
1851 | 1840 | ||
1852 | spec->input_mux = &spec->private_imux[0]; | 1841 | spec->input_mux = &spec->private_imux[0]; |
1853 | 1842 | ||
@@ -2390,8 +2379,8 @@ static int vt1708B_parse_auto_config(struct hda_codec *codec) | |||
2390 | if (spec->autocfg.dig_in_pin) | 2379 | if (spec->autocfg.dig_in_pin) |
2391 | spec->dig_in_nid = VT1708B_DIGIN_NID; | 2380 | spec->dig_in_nid = VT1708B_DIGIN_NID; |
2392 | 2381 | ||
2393 | if (spec->kctl_alloc) | 2382 | if (spec->kctls.list) |
2394 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 2383 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
2395 | 2384 | ||
2396 | spec->input_mux = &spec->private_imux[0]; | 2385 | spec->input_mux = &spec->private_imux[0]; |
2397 | 2386 | ||
@@ -2855,8 +2844,8 @@ static int vt1708S_parse_auto_config(struct hda_codec *codec) | |||
2855 | 2844 | ||
2856 | spec->extra_dig_out_nid = 0x15; | 2845 | spec->extra_dig_out_nid = 0x15; |
2857 | 2846 | ||
2858 | if (spec->kctl_alloc) | 2847 | if (spec->kctls.list) |
2859 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 2848 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
2860 | 2849 | ||
2861 | spec->input_mux = &spec->private_imux[0]; | 2850 | spec->input_mux = &spec->private_imux[0]; |
2862 | 2851 | ||
@@ -3174,8 +3163,8 @@ static int vt1702_parse_auto_config(struct hda_codec *codec) | |||
3174 | 3163 | ||
3175 | spec->extra_dig_out_nid = 0x1B; | 3164 | spec->extra_dig_out_nid = 0x1B; |
3176 | 3165 | ||
3177 | if (spec->kctl_alloc) | 3166 | if (spec->kctls.list) |
3178 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 3167 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
3179 | 3168 | ||
3180 | spec->input_mux = &spec->private_imux[0]; | 3169 | spec->input_mux = &spec->private_imux[0]; |
3181 | 3170 | ||