diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-11 15:58:37 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-11 15:58:37 -0400 |
commit | 0a3fd051c7036ef71b58863f8e5da7c3dabd9d3f (patch) | |
tree | 43388a81494ded94008afff66777f9f6e8cb5484 /sound/pci/hda | |
parent | 57a44415beee38d1afcd8e1b5fad66f3414d2dac (diff) | |
parent | c911d1e16dfc1f0338bbc245ff724322c0113395 (diff) |
Merge branch 'linus' of master.kernel.org:/pub/scm/linux/kernel/git/perex/alsa
* 'linus' of master.kernel.org:/pub/scm/linux/kernel/git/perex/alsa: (122 commits)
[ALSA] version 1.0.14rc4
[ALSA] Add speaker pin sequencing to hda_codec.c:snd_hda_parse_pin_def_config()
[ALSA] hda-codec - Add ALC861VD Lenovo support
[ALSA] hda-codec - Fix connection list in generic parser
[ALSA] usb-audio: work around wrong wMaxPacketSize on ESI M4U
[ALSA] usb-audio: work around broken M-Audio MidiSport Uno firmware
[ALSA] usb-audio: explicitly match Logitech QuickCam
[ALSA] hda-codec - Fix a typo
[ALSA] hda-codec - Fix ALC880 uniwill auto-mutes
[ALSA] hda-codec - Fix AD1988 SPDIF playback route control
[ALSA] wm8750 typo fix
[ALSA] wavefront: only declare isapnp on CONFIG_PNP
[ALSA] hda-codec - bug fixes for stac92xx HDA codecs.
[ALSA] add MODULE_FIRMWARE entries
[ALSA] do not depend on FW_LOADER when internal firmware images are used
[ALSA] hda-codec - Fix resume of STAC92xx codecs
[ALSA] usbaudio - Revert the minimal period size fix patch
[ALSA] hda-codec - Add support for new HP DV series laptops
[ALSA] usb-audio - Fix the minimum period size per transfer mode
[ALSA] sound/pcmcia/vx/vxpocket.c: fix an if() condition
...
Diffstat (limited to 'sound/pci/hda')
-rw-r--r-- | sound/pci/hda/Makefile | 9 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.c | 729 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 2 | ||||
-rw-r--r-- | sound/pci/hda/hda_generic.c | 2 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.c | 31 | ||||
-rw-r--r-- | sound/pci/hda/hda_local.h | 12 | ||||
-rw-r--r-- | sound/pci/hda/patch_analog.c | 85 | ||||
-rw-r--r-- | sound/pci/hda/patch_atihdmi.c | 17 | ||||
-rw-r--r-- | sound/pci/hda/patch_cmedia.c | 14 | ||||
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 310 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 2269 | ||||
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 178 | ||||
-rw-r--r-- | sound/pci/hda/patch_via.c | 14 |
13 files changed, 2707 insertions, 965 deletions
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile index 60d7b05a204a..b2484bbdcc1d 100644 --- a/sound/pci/hda/Makefile +++ b/sound/pci/hda/Makefile | |||
@@ -1,5 +1,8 @@ | |||
1 | snd-hda-intel-objs := hda_intel.o | 1 | snd-hda-intel-objs := hda_intel.o |
2 | snd-hda-codec-objs := hda_codec.o \ | 2 | # since snd-hda-intel is the only driver using hda-codec, |
3 | # merge it into a single module although it was originally | ||
4 | # designed to be individual modules | ||
5 | snd-hda-intel-objs += hda_codec.o \ | ||
3 | hda_generic.o \ | 6 | hda_generic.o \ |
4 | patch_realtek.o \ | 7 | patch_realtek.o \ |
5 | patch_cmedia.o \ | 8 | patch_cmedia.o \ |
@@ -10,7 +13,7 @@ snd-hda-codec-objs := hda_codec.o \ | |||
10 | patch_conexant.o \ | 13 | patch_conexant.o \ |
11 | patch_via.o | 14 | patch_via.o |
12 | ifdef CONFIG_PROC_FS | 15 | ifdef CONFIG_PROC_FS |
13 | snd-hda-codec-objs += hda_proc.o | 16 | snd-hda-intel-objs += hda_proc.o |
14 | endif | 17 | endif |
15 | 18 | ||
16 | obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-intel.o snd-hda-codec.o | 19 | 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 8f34fb447983..14649d54b493 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/pci.h> | 26 | #include <linux/pci.h> |
27 | #include <linux/moduleparam.h> | ||
28 | #include <linux/mutex.h> | 27 | #include <linux/mutex.h> |
29 | #include <sound/core.h> | 28 | #include <sound/core.h> |
30 | #include "hda_codec.h" | 29 | #include "hda_codec.h" |
@@ -34,11 +33,6 @@ | |||
34 | #include "hda_local.h" | 33 | #include "hda_local.h" |
35 | 34 | ||
36 | 35 | ||
37 | MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>"); | ||
38 | MODULE_DESCRIPTION("Universal interface for High Definition Audio Codec"); | ||
39 | MODULE_LICENSE("GPL"); | ||
40 | |||
41 | |||
42 | /* | 36 | /* |
43 | * vendor / preset table | 37 | * vendor / preset table |
44 | */ | 38 | */ |
@@ -77,12 +71,13 @@ static struct hda_vendor_id hda_vendor_ids[] = { | |||
77 | * | 71 | * |
78 | * Returns the obtained response value, or -1 for an error. | 72 | * Returns the obtained response value, or -1 for an error. |
79 | */ | 73 | */ |
80 | unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, int direct, | 74 | unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, |
75 | int direct, | ||
81 | unsigned int verb, unsigned int parm) | 76 | unsigned int verb, unsigned int parm) |
82 | { | 77 | { |
83 | unsigned int res; | 78 | unsigned int res; |
84 | mutex_lock(&codec->bus->cmd_mutex); | 79 | mutex_lock(&codec->bus->cmd_mutex); |
85 | if (! codec->bus->ops.command(codec, nid, direct, verb, parm)) | 80 | if (!codec->bus->ops.command(codec, nid, direct, verb, parm)) |
86 | res = codec->bus->ops.get_response(codec); | 81 | res = codec->bus->ops.get_response(codec); |
87 | else | 82 | else |
88 | res = (unsigned int)-1; | 83 | res = (unsigned int)-1; |
@@ -90,8 +85,6 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, int dire | |||
90 | return res; | 85 | return res; |
91 | } | 86 | } |
92 | 87 | ||
93 | EXPORT_SYMBOL(snd_hda_codec_read); | ||
94 | |||
95 | /** | 88 | /** |
96 | * snd_hda_codec_write - send a single command without waiting for response | 89 | * snd_hda_codec_write - send a single command without waiting for response |
97 | * @codec: the HDA codec | 90 | * @codec: the HDA codec |
@@ -114,8 +107,6 @@ int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct, | |||
114 | return err; | 107 | return err; |
115 | } | 108 | } |
116 | 109 | ||
117 | EXPORT_SYMBOL(snd_hda_codec_write); | ||
118 | |||
119 | /** | 110 | /** |
120 | * snd_hda_sequence_write - sequence writes | 111 | * snd_hda_sequence_write - sequence writes |
121 | * @codec: the HDA codec | 112 | * @codec: the HDA codec |
@@ -130,8 +121,6 @@ void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq) | |||
130 | snd_hda_codec_write(codec, seq->nid, 0, seq->verb, seq->param); | 121 | snd_hda_codec_write(codec, seq->nid, 0, seq->verb, seq->param); |
131 | } | 122 | } |
132 | 123 | ||
133 | EXPORT_SYMBOL(snd_hda_sequence_write); | ||
134 | |||
135 | /** | 124 | /** |
136 | * snd_hda_get_sub_nodes - get the range of sub nodes | 125 | * snd_hda_get_sub_nodes - get the range of sub nodes |
137 | * @codec: the HDA codec | 126 | * @codec: the HDA codec |
@@ -141,7 +130,8 @@ EXPORT_SYMBOL(snd_hda_sequence_write); | |||
141 | * Parse the NID and store the start NID of its sub-nodes. | 130 | * Parse the NID and store the start NID of its sub-nodes. |
142 | * Returns the number of sub-nodes. | 131 | * Returns the number of sub-nodes. |
143 | */ | 132 | */ |
144 | int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid, hda_nid_t *start_id) | 133 | int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid, |
134 | hda_nid_t *start_id) | ||
145 | { | 135 | { |
146 | unsigned int parm; | 136 | unsigned int parm; |
147 | 137 | ||
@@ -150,8 +140,6 @@ int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid, hda_nid_t *sta | |||
150 | return (int)(parm & 0x7fff); | 140 | return (int)(parm & 0x7fff); |
151 | } | 141 | } |
152 | 142 | ||
153 | EXPORT_SYMBOL(snd_hda_get_sub_nodes); | ||
154 | |||
155 | /** | 143 | /** |
156 | * snd_hda_get_connections - get connection list | 144 | * snd_hda_get_connections - get connection list |
157 | * @codec: the HDA codec | 145 | * @codec: the HDA codec |
@@ -187,12 +175,13 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid, | |||
187 | conn_len = parm & AC_CLIST_LENGTH; | 175 | conn_len = parm & AC_CLIST_LENGTH; |
188 | mask = (1 << (shift-1)) - 1; | 176 | mask = (1 << (shift-1)) - 1; |
189 | 177 | ||
190 | if (! conn_len) | 178 | if (!conn_len) |
191 | return 0; /* no connection */ | 179 | return 0; /* no connection */ |
192 | 180 | ||
193 | if (conn_len == 1) { | 181 | if (conn_len == 1) { |
194 | /* single connection */ | 182 | /* single connection */ |
195 | parm = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_LIST, 0); | 183 | parm = snd_hda_codec_read(codec, nid, 0, |
184 | AC_VERB_GET_CONNECT_LIST, 0); | ||
196 | conn_list[0] = parm & mask; | 185 | conn_list[0] = parm & mask; |
197 | return 1; | 186 | return 1; |
198 | } | 187 | } |
@@ -207,18 +196,21 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid, | |||
207 | if (i % num_elems == 0) | 196 | if (i % num_elems == 0) |
208 | parm = snd_hda_codec_read(codec, nid, 0, | 197 | parm = snd_hda_codec_read(codec, nid, 0, |
209 | AC_VERB_GET_CONNECT_LIST, i); | 198 | AC_VERB_GET_CONNECT_LIST, i); |
210 | range_val = !! (parm & (1 << (shift-1))); /* ranges */ | 199 | range_val = !!(parm & (1 << (shift-1))); /* ranges */ |
211 | val = parm & mask; | 200 | val = parm & mask; |
212 | parm >>= shift; | 201 | parm >>= shift; |
213 | if (range_val) { | 202 | if (range_val) { |
214 | /* ranges between the previous and this one */ | 203 | /* ranges between the previous and this one */ |
215 | if (! prev_nid || prev_nid >= val) { | 204 | if (!prev_nid || prev_nid >= val) { |
216 | snd_printk(KERN_WARNING "hda_codec: invalid dep_range_val %x:%x\n", prev_nid, val); | 205 | snd_printk(KERN_WARNING "hda_codec: " |
206 | "invalid dep_range_val %x:%x\n", | ||
207 | prev_nid, val); | ||
217 | continue; | 208 | continue; |
218 | } | 209 | } |
219 | for (n = prev_nid + 1; n <= val; n++) { | 210 | for (n = prev_nid + 1; n <= val; n++) { |
220 | if (conns >= max_conns) { | 211 | if (conns >= max_conns) { |
221 | snd_printk(KERN_ERR "Too many connections\n"); | 212 | snd_printk(KERN_ERR |
213 | "Too many connections\n"); | ||
222 | return -EINVAL; | 214 | return -EINVAL; |
223 | } | 215 | } |
224 | conn_list[conns++] = n; | 216 | conn_list[conns++] = n; |
@@ -253,7 +245,8 @@ int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex) | |||
253 | struct hda_bus_unsolicited *unsol; | 245 | struct hda_bus_unsolicited *unsol; |
254 | unsigned int wp; | 246 | unsigned int wp; |
255 | 247 | ||
256 | if ((unsol = bus->unsol) == NULL) | 248 | unsol = bus->unsol; |
249 | if (!unsol) | ||
257 | return 0; | 250 | return 0; |
258 | 251 | ||
259 | wp = (unsol->wp + 1) % HDA_UNSOL_QUEUE_SIZE; | 252 | wp = (unsol->wp + 1) % HDA_UNSOL_QUEUE_SIZE; |
@@ -268,8 +261,6 @@ int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex) | |||
268 | return 0; | 261 | return 0; |
269 | } | 262 | } |
270 | 263 | ||
271 | EXPORT_SYMBOL(snd_hda_queue_unsol_event); | ||
272 | |||
273 | /* | 264 | /* |
274 | * process queueud unsolicited events | 265 | * process queueud unsolicited events |
275 | */ | 266 | */ |
@@ -287,7 +278,7 @@ static void process_unsol_events(struct work_struct *work) | |||
287 | rp <<= 1; | 278 | rp <<= 1; |
288 | res = unsol->queue[rp]; | 279 | res = unsol->queue[rp]; |
289 | caddr = unsol->queue[rp + 1]; | 280 | caddr = unsol->queue[rp + 1]; |
290 | if (! (caddr & (1 << 4))) /* no unsolicited event? */ | 281 | if (!(caddr & (1 << 4))) /* no unsolicited event? */ |
291 | continue; | 282 | continue; |
292 | codec = bus->caddr_tbl[caddr & 0x0f]; | 283 | codec = bus->caddr_tbl[caddr & 0x0f]; |
293 | if (codec && codec->patch_ops.unsol_event) | 284 | if (codec && codec->patch_ops.unsol_event) |
@@ -298,7 +289,7 @@ static void process_unsol_events(struct work_struct *work) | |||
298 | /* | 289 | /* |
299 | * initialize unsolicited queue | 290 | * initialize unsolicited queue |
300 | */ | 291 | */ |
301 | static int init_unsol_queue(struct hda_bus *bus) | 292 | static int __devinit init_unsol_queue(struct hda_bus *bus) |
302 | { | 293 | { |
303 | struct hda_bus_unsolicited *unsol; | 294 | struct hda_bus_unsolicited *unsol; |
304 | 295 | ||
@@ -306,8 +297,9 @@ static int init_unsol_queue(struct hda_bus *bus) | |||
306 | return 0; | 297 | return 0; |
307 | 298 | ||
308 | unsol = kzalloc(sizeof(*unsol), GFP_KERNEL); | 299 | unsol = kzalloc(sizeof(*unsol), GFP_KERNEL); |
309 | if (! unsol) { | 300 | if (!unsol) { |
310 | snd_printk(KERN_ERR "hda_codec: can't allocate unsolicited queue\n"); | 301 | snd_printk(KERN_ERR "hda_codec: " |
302 | "can't allocate unsolicited queue\n"); | ||
311 | return -ENOMEM; | 303 | return -ENOMEM; |
312 | } | 304 | } |
313 | INIT_WORK(&unsol->work, process_unsol_events); | 305 | INIT_WORK(&unsol->work, process_unsol_events); |
@@ -323,16 +315,15 @@ static void snd_hda_codec_free(struct hda_codec *codec); | |||
323 | 315 | ||
324 | static int snd_hda_bus_free(struct hda_bus *bus) | 316 | static int snd_hda_bus_free(struct hda_bus *bus) |
325 | { | 317 | { |
326 | struct list_head *p, *n; | 318 | struct hda_codec *codec, *n; |
327 | 319 | ||
328 | if (! bus) | 320 | if (!bus) |
329 | return 0; | 321 | return 0; |
330 | if (bus->unsol) { | 322 | if (bus->unsol) { |
331 | flush_scheduled_work(); | 323 | flush_scheduled_work(); |
332 | kfree(bus->unsol); | 324 | kfree(bus->unsol); |
333 | } | 325 | } |
334 | list_for_each_safe(p, n, &bus->codec_list) { | 326 | list_for_each_entry_safe(codec, n, &bus->codec_list, list) { |
335 | struct hda_codec *codec = list_entry(p, struct hda_codec, list); | ||
336 | snd_hda_codec_free(codec); | 327 | snd_hda_codec_free(codec); |
337 | } | 328 | } |
338 | if (bus->ops.private_free) | 329 | if (bus->ops.private_free) |
@@ -355,8 +346,9 @@ static int snd_hda_bus_dev_free(struct snd_device *device) | |||
355 | * | 346 | * |
356 | * Returns 0 if successful, or a negative error code. | 347 | * Returns 0 if successful, or a negative error code. |
357 | */ | 348 | */ |
358 | int snd_hda_bus_new(struct snd_card *card, const struct hda_bus_template *temp, | 349 | int __devinit snd_hda_bus_new(struct snd_card *card, |
359 | struct hda_bus **busp) | 350 | const struct hda_bus_template *temp, |
351 | struct hda_bus **busp) | ||
360 | { | 352 | { |
361 | struct hda_bus *bus; | 353 | struct hda_bus *bus; |
362 | int err; | 354 | int err; |
@@ -385,7 +377,8 @@ int snd_hda_bus_new(struct snd_card *card, const struct hda_bus_template *temp, | |||
385 | mutex_init(&bus->cmd_mutex); | 377 | mutex_init(&bus->cmd_mutex); |
386 | INIT_LIST_HEAD(&bus->codec_list); | 378 | INIT_LIST_HEAD(&bus->codec_list); |
387 | 379 | ||
388 | if ((err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops)) < 0) { | 380 | err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops); |
381 | if (err < 0) { | ||
389 | snd_hda_bus_free(bus); | 382 | snd_hda_bus_free(bus); |
390 | return err; | 383 | return err; |
391 | } | 384 | } |
@@ -394,22 +387,24 @@ int snd_hda_bus_new(struct snd_card *card, const struct hda_bus_template *temp, | |||
394 | return 0; | 387 | return 0; |
395 | } | 388 | } |
396 | 389 | ||
397 | EXPORT_SYMBOL(snd_hda_bus_new); | ||
398 | |||
399 | /* | 390 | /* |
400 | * find a matching codec preset | 391 | * find a matching codec preset |
401 | */ | 392 | */ |
402 | static const struct hda_codec_preset *find_codec_preset(struct hda_codec *codec) | 393 | static const struct hda_codec_preset __devinit * |
394 | find_codec_preset(struct hda_codec *codec) | ||
403 | { | 395 | { |
404 | const struct hda_codec_preset **tbl, *preset; | 396 | const struct hda_codec_preset **tbl, *preset; |
405 | 397 | ||
398 | if (codec->bus->modelname && !strcmp(codec->bus->modelname, "generic")) | ||
399 | return NULL; /* use the generic parser */ | ||
400 | |||
406 | for (tbl = hda_preset_tables; *tbl; tbl++) { | 401 | for (tbl = hda_preset_tables; *tbl; tbl++) { |
407 | for (preset = *tbl; preset->id; preset++) { | 402 | for (preset = *tbl; preset->id; preset++) { |
408 | u32 mask = preset->mask; | 403 | u32 mask = preset->mask; |
409 | if (! mask) | 404 | if (!mask) |
410 | mask = ~0; | 405 | mask = ~0; |
411 | if (preset->id == (codec->vendor_id & mask) && | 406 | if (preset->id == (codec->vendor_id & mask) && |
412 | (! preset->rev || | 407 | (!preset->rev || |
413 | preset->rev == codec->revision_id)) | 408 | preset->rev == codec->revision_id)) |
414 | return preset; | 409 | return preset; |
415 | } | 410 | } |
@@ -434,27 +429,30 @@ void snd_hda_get_codec_name(struct hda_codec *codec, | |||
434 | break; | 429 | break; |
435 | } | 430 | } |
436 | } | 431 | } |
437 | if (! vendor) { | 432 | if (!vendor) { |
438 | sprintf(tmp, "Generic %04x", vendor_id); | 433 | sprintf(tmp, "Generic %04x", vendor_id); |
439 | vendor = tmp; | 434 | vendor = tmp; |
440 | } | 435 | } |
441 | if (codec->preset && codec->preset->name) | 436 | if (codec->preset && codec->preset->name) |
442 | snprintf(name, namelen, "%s %s", vendor, codec->preset->name); | 437 | snprintf(name, namelen, "%s %s", vendor, codec->preset->name); |
443 | else | 438 | else |
444 | snprintf(name, namelen, "%s ID %x", vendor, codec->vendor_id & 0xffff); | 439 | snprintf(name, namelen, "%s ID %x", vendor, |
440 | codec->vendor_id & 0xffff); | ||
445 | } | 441 | } |
446 | 442 | ||
447 | /* | 443 | /* |
448 | * look for an AFG and MFG nodes | 444 | * look for an AFG and MFG nodes |
449 | */ | 445 | */ |
450 | static void setup_fg_nodes(struct hda_codec *codec) | 446 | static void __devinit setup_fg_nodes(struct hda_codec *codec) |
451 | { | 447 | { |
452 | int i, total_nodes; | 448 | int i, total_nodes; |
453 | hda_nid_t nid; | 449 | hda_nid_t nid; |
454 | 450 | ||
455 | total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid); | 451 | total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid); |
456 | for (i = 0; i < total_nodes; i++, nid++) { | 452 | for (i = 0; i < total_nodes; i++, nid++) { |
457 | switch((snd_hda_param_read(codec, nid, AC_PAR_FUNCTION_TYPE) & 0xff)) { | 453 | unsigned int func; |
454 | func = snd_hda_param_read(codec, nid, AC_PAR_FUNCTION_TYPE); | ||
455 | switch (func & 0xff) { | ||
458 | case AC_GRP_AUDIO_FUNCTION: | 456 | case AC_GRP_AUDIO_FUNCTION: |
459 | codec->afg = nid; | 457 | codec->afg = nid; |
460 | break; | 458 | break; |
@@ -478,7 +476,7 @@ static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node) | |||
478 | codec->num_nodes = snd_hda_get_sub_nodes(codec, fg_node, | 476 | codec->num_nodes = snd_hda_get_sub_nodes(codec, fg_node, |
479 | &codec->start_nid); | 477 | &codec->start_nid); |
480 | codec->wcaps = kmalloc(codec->num_nodes * 4, GFP_KERNEL); | 478 | codec->wcaps = kmalloc(codec->num_nodes * 4, GFP_KERNEL); |
481 | if (! codec->wcaps) | 479 | if (!codec->wcaps) |
482 | return -ENOMEM; | 480 | return -ENOMEM; |
483 | nid = codec->start_nid; | 481 | nid = codec->start_nid; |
484 | for (i = 0; i < codec->num_nodes; i++, nid++) | 482 | for (i = 0; i < codec->num_nodes; i++, nid++) |
@@ -493,7 +491,7 @@ static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node) | |||
493 | */ | 491 | */ |
494 | static void snd_hda_codec_free(struct hda_codec *codec) | 492 | static void snd_hda_codec_free(struct hda_codec *codec) |
495 | { | 493 | { |
496 | if (! codec) | 494 | if (!codec) |
497 | return; | 495 | return; |
498 | list_del(&codec->list); | 496 | list_del(&codec->list); |
499 | codec->bus->caddr_tbl[codec->addr] = NULL; | 497 | codec->bus->caddr_tbl[codec->addr] = NULL; |
@@ -514,8 +512,8 @@ static void init_amp_hash(struct hda_codec *codec); | |||
514 | * | 512 | * |
515 | * Returns 0 if successful, or a negative error code. | 513 | * Returns 0 if successful, or a negative error code. |
516 | */ | 514 | */ |
517 | int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, | 515 | int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, |
518 | struct hda_codec **codecp) | 516 | struct hda_codec **codecp) |
519 | { | 517 | { |
520 | struct hda_codec *codec; | 518 | struct hda_codec *codec; |
521 | char component[13]; | 519 | char component[13]; |
@@ -525,7 +523,8 @@ int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, | |||
525 | snd_assert(codec_addr <= HDA_MAX_CODEC_ADDRESS, return -EINVAL); | 523 | snd_assert(codec_addr <= HDA_MAX_CODEC_ADDRESS, return -EINVAL); |
526 | 524 | ||
527 | if (bus->caddr_tbl[codec_addr]) { | 525 | if (bus->caddr_tbl[codec_addr]) { |
528 | snd_printk(KERN_ERR "hda_codec: address 0x%x is already occupied\n", codec_addr); | 526 | snd_printk(KERN_ERR "hda_codec: " |
527 | "address 0x%x is already occupied\n", codec_addr); | ||
529 | return -EBUSY; | 528 | return -EBUSY; |
530 | } | 529 | } |
531 | 530 | ||
@@ -543,18 +542,21 @@ int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, | |||
543 | list_add_tail(&codec->list, &bus->codec_list); | 542 | list_add_tail(&codec->list, &bus->codec_list); |
544 | bus->caddr_tbl[codec_addr] = codec; | 543 | bus->caddr_tbl[codec_addr] = codec; |
545 | 544 | ||
546 | codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT, AC_PAR_VENDOR_ID); | 545 | codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT, |
546 | AC_PAR_VENDOR_ID); | ||
547 | if (codec->vendor_id == -1) | 547 | if (codec->vendor_id == -1) |
548 | /* read again, hopefully the access method was corrected | 548 | /* read again, hopefully the access method was corrected |
549 | * in the last read... | 549 | * in the last read... |
550 | */ | 550 | */ |
551 | codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT, | 551 | codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT, |
552 | AC_PAR_VENDOR_ID); | 552 | AC_PAR_VENDOR_ID); |
553 | codec->subsystem_id = snd_hda_param_read(codec, AC_NODE_ROOT, AC_PAR_SUBSYSTEM_ID); | 553 | codec->subsystem_id = snd_hda_param_read(codec, AC_NODE_ROOT, |
554 | codec->revision_id = snd_hda_param_read(codec, AC_NODE_ROOT, AC_PAR_REV_ID); | 554 | AC_PAR_SUBSYSTEM_ID); |
555 | codec->revision_id = snd_hda_param_read(codec, AC_NODE_ROOT, | ||
556 | AC_PAR_REV_ID); | ||
555 | 557 | ||
556 | setup_fg_nodes(codec); | 558 | setup_fg_nodes(codec); |
557 | if (! codec->afg && ! codec->mfg) { | 559 | if (!codec->afg && !codec->mfg) { |
558 | snd_printdd("hda_codec: no AFG or MFG node found\n"); | 560 | snd_printdd("hda_codec: no AFG or MFG node found\n"); |
559 | snd_hda_codec_free(codec); | 561 | snd_hda_codec_free(codec); |
560 | return -ENODEV; | 562 | return -ENODEV; |
@@ -566,15 +568,16 @@ int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, | |||
566 | return -ENOMEM; | 568 | return -ENOMEM; |
567 | } | 569 | } |
568 | 570 | ||
569 | if (! codec->subsystem_id) { | 571 | if (!codec->subsystem_id) { |
570 | hda_nid_t nid = codec->afg ? codec->afg : codec->mfg; | 572 | hda_nid_t nid = codec->afg ? codec->afg : codec->mfg; |
571 | codec->subsystem_id = snd_hda_codec_read(codec, nid, 0, | 573 | codec->subsystem_id = |
572 | AC_VERB_GET_SUBSYSTEM_ID, | 574 | snd_hda_codec_read(codec, nid, 0, |
573 | 0); | 575 | AC_VERB_GET_SUBSYSTEM_ID, 0); |
574 | } | 576 | } |
575 | 577 | ||
576 | codec->preset = find_codec_preset(codec); | 578 | codec->preset = find_codec_preset(codec); |
577 | if (! *bus->card->mixername) | 579 | /* audio codec should override the mixer name */ |
580 | if (codec->afg || !*bus->card->mixername) | ||
578 | snd_hda_get_codec_name(codec, bus->card->mixername, | 581 | snd_hda_get_codec_name(codec, bus->card->mixername, |
579 | sizeof(bus->card->mixername)); | 582 | sizeof(bus->card->mixername)); |
580 | 583 | ||
@@ -600,8 +603,6 @@ int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, | |||
600 | return 0; | 603 | return 0; |
601 | } | 604 | } |
602 | 605 | ||
603 | EXPORT_SYMBOL(snd_hda_codec_new); | ||
604 | |||
605 | /** | 606 | /** |
606 | * snd_hda_codec_setup_stream - set up the codec for streaming | 607 | * snd_hda_codec_setup_stream - set up the codec for streaming |
607 | * @codec: the CODEC to set up | 608 | * @codec: the CODEC to set up |
@@ -610,13 +611,15 @@ EXPORT_SYMBOL(snd_hda_codec_new); | |||
610 | * @channel_id: channel id to pass, zero based. | 611 | * @channel_id: channel id to pass, zero based. |
611 | * @format: stream format. | 612 | * @format: stream format. |
612 | */ | 613 | */ |
613 | void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, u32 stream_tag, | 614 | void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, |
615 | u32 stream_tag, | ||
614 | int channel_id, int format) | 616 | int channel_id, int format) |
615 | { | 617 | { |
616 | if (! nid) | 618 | if (!nid) |
617 | return; | 619 | return; |
618 | 620 | ||
619 | snd_printdd("hda_codec_setup_stream: NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n", | 621 | snd_printdd("hda_codec_setup_stream: " |
622 | "NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n", | ||
620 | nid, stream_tag, channel_id, format); | 623 | nid, stream_tag, channel_id, format); |
621 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, | 624 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, |
622 | (stream_tag << 4) | channel_id); | 625 | (stream_tag << 4) | channel_id); |
@@ -624,8 +627,6 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, u32 stre | |||
624 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format); | 627 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format); |
625 | } | 628 | } |
626 | 629 | ||
627 | EXPORT_SYMBOL(snd_hda_codec_setup_stream); | ||
628 | |||
629 | /* | 630 | /* |
630 | * amp access functions | 631 | * amp access functions |
631 | */ | 632 | */ |
@@ -636,7 +637,7 @@ EXPORT_SYMBOL(snd_hda_codec_setup_stream); | |||
636 | #define INFO_AMP_VOL(ch) (1 << (1 + (ch))) | 637 | #define INFO_AMP_VOL(ch) (1 << (1 + (ch))) |
637 | 638 | ||
638 | /* initialize the hash table */ | 639 | /* initialize the hash table */ |
639 | static void init_amp_hash(struct hda_codec *codec) | 640 | static void __devinit init_amp_hash(struct hda_codec *codec) |
640 | { | 641 | { |
641 | memset(codec->amp_hash, 0xff, sizeof(codec->amp_hash)); | 642 | memset(codec->amp_hash, 0xff, sizeof(codec->amp_hash)); |
642 | codec->num_amp_entries = 0; | 643 | codec->num_amp_entries = 0; |
@@ -662,15 +663,18 @@ static struct hda_amp_info *get_alloc_amp_hash(struct hda_codec *codec, u32 key) | |||
662 | if (codec->num_amp_entries >= codec->amp_info_size) { | 663 | if (codec->num_amp_entries >= codec->amp_info_size) { |
663 | /* reallocate the array */ | 664 | /* reallocate the array */ |
664 | int new_size = codec->amp_info_size + 64; | 665 | int new_size = codec->amp_info_size + 64; |
665 | struct hda_amp_info *new_info = kcalloc(new_size, sizeof(struct hda_amp_info), | 666 | struct hda_amp_info *new_info; |
666 | GFP_KERNEL); | 667 | new_info = kcalloc(new_size, sizeof(struct hda_amp_info), |
667 | if (! new_info) { | 668 | GFP_KERNEL); |
668 | snd_printk(KERN_ERR "hda_codec: can't malloc amp_info\n"); | 669 | if (!new_info) { |
670 | snd_printk(KERN_ERR "hda_codec: " | ||
671 | "can't malloc amp_info\n"); | ||
669 | return NULL; | 672 | return NULL; |
670 | } | 673 | } |
671 | if (codec->amp_info) { | 674 | if (codec->amp_info) { |
672 | memcpy(new_info, codec->amp_info, | 675 | memcpy(new_info, codec->amp_info, |
673 | codec->amp_info_size * sizeof(struct hda_amp_info)); | 676 | codec->amp_info_size * |
677 | sizeof(struct hda_amp_info)); | ||
674 | kfree(codec->amp_info); | 678 | kfree(codec->amp_info); |
675 | } | 679 | } |
676 | codec->amp_info_size = new_size; | 680 | codec->amp_info_size = new_size; |
@@ -691,15 +695,18 @@ static struct hda_amp_info *get_alloc_amp_hash(struct hda_codec *codec, u32 key) | |||
691 | */ | 695 | */ |
692 | static u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction) | 696 | static u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction) |
693 | { | 697 | { |
694 | struct hda_amp_info *info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, 0)); | 698 | struct hda_amp_info *info; |
695 | 699 | ||
696 | if (! info) | 700 | info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, 0)); |
701 | if (!info) | ||
697 | return 0; | 702 | return 0; |
698 | if (! (info->status & INFO_AMP_CAPS)) { | 703 | if (!(info->status & INFO_AMP_CAPS)) { |
699 | if (! (get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD)) | 704 | if (!(get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD)) |
700 | nid = codec->afg; | 705 | nid = codec->afg; |
701 | info->amp_caps = snd_hda_param_read(codec, nid, direction == HDA_OUTPUT ? | 706 | info->amp_caps = snd_hda_param_read(codec, nid, |
702 | AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP); | 707 | direction == HDA_OUTPUT ? |
708 | AC_PAR_AMP_OUT_CAP : | ||
709 | AC_PAR_AMP_IN_CAP); | ||
703 | info->status |= INFO_AMP_CAPS; | 710 | info->status |= INFO_AMP_CAPS; |
704 | } | 711 | } |
705 | return info->amp_caps; | 712 | return info->amp_caps; |
@@ -709,8 +716,9 @@ static u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction) | |||
709 | * read the current volume to info | 716 | * read the current volume to info |
710 | * if the cache exists, read the cache value. | 717 | * if the cache exists, read the cache value. |
711 | */ | 718 | */ |
712 | static unsigned int get_vol_mute(struct hda_codec *codec, struct hda_amp_info *info, | 719 | static unsigned int get_vol_mute(struct hda_codec *codec, |
713 | hda_nid_t nid, int ch, int direction, int index) | 720 | struct hda_amp_info *info, hda_nid_t nid, |
721 | int ch, int direction, int index) | ||
714 | { | 722 | { |
715 | u32 val, parm; | 723 | u32 val, parm; |
716 | 724 | ||
@@ -720,7 +728,8 @@ static unsigned int get_vol_mute(struct hda_codec *codec, struct hda_amp_info *i | |||
720 | parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT; | 728 | parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT; |
721 | parm |= direction == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT; | 729 | parm |= direction == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT; |
722 | parm |= index; | 730 | parm |= index; |
723 | val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, parm); | 731 | val = snd_hda_codec_read(codec, nid, 0, |
732 | AC_VERB_GET_AMP_GAIN_MUTE, parm); | ||
724 | info->vol[ch] = val & 0xff; | 733 | info->vol[ch] = val & 0xff; |
725 | info->status |= INFO_AMP_VOL(ch); | 734 | info->status |= INFO_AMP_VOL(ch); |
726 | return info->vol[ch]; | 735 | return info->vol[ch]; |
@@ -730,7 +739,8 @@ static unsigned int get_vol_mute(struct hda_codec *codec, struct hda_amp_info *i | |||
730 | * write the current volume in info to the h/w and update the cache | 739 | * write the current volume in info to the h/w and update the cache |
731 | */ | 740 | */ |
732 | static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info, | 741 | static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info, |
733 | hda_nid_t nid, int ch, int direction, int index, int val) | 742 | hda_nid_t nid, int ch, int direction, int index, |
743 | int val) | ||
734 | { | 744 | { |
735 | u32 parm; | 745 | u32 parm; |
736 | 746 | ||
@@ -748,8 +758,9 @@ static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info, | |||
748 | int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, | 758 | int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, |
749 | int direction, int index) | 759 | int direction, int index) |
750 | { | 760 | { |
751 | struct hda_amp_info *info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index)); | 761 | struct hda_amp_info *info; |
752 | if (! info) | 762 | info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index)); |
763 | if (!info) | ||
753 | return 0; | 764 | return 0; |
754 | return get_vol_mute(codec, info, nid, ch, direction, index); | 765 | return get_vol_mute(codec, info, nid, ch, direction, index); |
755 | } | 766 | } |
@@ -760,13 +771,14 @@ int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, | |||
760 | int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, | 771 | int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, |
761 | int direction, int idx, int mask, int val) | 772 | int direction, int idx, int mask, int val) |
762 | { | 773 | { |
763 | struct hda_amp_info *info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx)); | 774 | struct hda_amp_info *info; |
764 | 775 | ||
765 | if (! info) | 776 | info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx)); |
777 | if (!info) | ||
766 | return 0; | 778 | return 0; |
767 | val &= mask; | 779 | val &= mask; |
768 | val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask; | 780 | val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask; |
769 | if (info->vol[ch] == val && ! codec->in_resume) | 781 | if (info->vol[ch] == val && !codec->in_resume) |
770 | return 0; | 782 | return 0; |
771 | put_vol_mute(codec, info, nid, ch, direction, idx, val); | 783 | put_vol_mute(codec, info, nid, ch, direction, idx, val); |
772 | return 1; | 784 | return 1; |
@@ -783,7 +795,8 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, | |||
783 | #define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf) | 795 | #define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf) |
784 | 796 | ||
785 | /* volume */ | 797 | /* volume */ |
786 | int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 798 | int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, |
799 | struct snd_ctl_elem_info *uinfo) | ||
787 | { | 800 | { |
788 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 801 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
789 | u16 nid = get_amp_nid(kcontrol); | 802 | u16 nid = get_amp_nid(kcontrol); |
@@ -792,9 +805,11 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
792 | u32 caps; | 805 | u32 caps; |
793 | 806 | ||
794 | caps = query_amp_caps(codec, nid, dir); | 807 | caps = query_amp_caps(codec, nid, dir); |
795 | caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT; /* num steps */ | 808 | /* num steps */ |
796 | if (! caps) { | 809 | caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT; |
797 | printk(KERN_WARNING "hda_codec: num_steps = 0 for NID=0x%x\n", nid); | 810 | if (!caps) { |
811 | printk(KERN_WARNING "hda_codec: " | ||
812 | "num_steps = 0 for NID=0x%x\n", nid); | ||
798 | return -EINVAL; | 813 | return -EINVAL; |
799 | } | 814 | } |
800 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | 815 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
@@ -804,7 +819,8 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
804 | return 0; | 819 | return 0; |
805 | } | 820 | } |
806 | 821 | ||
807 | int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 822 | int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, |
823 | struct snd_ctl_elem_value *ucontrol) | ||
808 | { | 824 | { |
809 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 825 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
810 | hda_nid_t nid = get_amp_nid(kcontrol); | 826 | hda_nid_t nid = get_amp_nid(kcontrol); |
@@ -820,7 +836,8 @@ int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
820 | return 0; | 836 | return 0; |
821 | } | 837 | } |
822 | 838 | ||
823 | int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 839 | int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, |
840 | struct snd_ctl_elem_value *ucontrol) | ||
824 | { | 841 | { |
825 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 842 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
826 | hda_nid_t nid = get_amp_nid(kcontrol); | 843 | hda_nid_t nid = get_amp_nid(kcontrol); |
@@ -852,7 +869,8 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, | |||
852 | if (size < 4 * sizeof(unsigned int)) | 869 | if (size < 4 * sizeof(unsigned int)) |
853 | return -ENOMEM; | 870 | return -ENOMEM; |
854 | caps = query_amp_caps(codec, nid, dir); | 871 | caps = query_amp_caps(codec, nid, dir); |
855 | val2 = (((caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT) + 1) * 25; | 872 | val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT; |
873 | val2 = (val2 + 1) * 25; | ||
856 | val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT); | 874 | val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT); |
857 | val1 = ((int)val1) * ((int)val2); | 875 | val1 = ((int)val1) * ((int)val2); |
858 | if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv)) | 876 | if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv)) |
@@ -867,7 +885,8 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, | |||
867 | } | 885 | } |
868 | 886 | ||
869 | /* switch */ | 887 | /* switch */ |
870 | int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 888 | int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, |
889 | struct snd_ctl_elem_info *uinfo) | ||
871 | { | 890 | { |
872 | int chs = get_amp_channels(kcontrol); | 891 | int chs = get_amp_channels(kcontrol); |
873 | 892 | ||
@@ -878,7 +897,8 @@ int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
878 | return 0; | 897 | return 0; |
879 | } | 898 | } |
880 | 899 | ||
881 | int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 900 | int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol, |
901 | struct snd_ctl_elem_value *ucontrol) | ||
882 | { | 902 | { |
883 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 903 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
884 | hda_nid_t nid = get_amp_nid(kcontrol); | 904 | hda_nid_t nid = get_amp_nid(kcontrol); |
@@ -888,13 +908,16 @@ int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
888 | long *valp = ucontrol->value.integer.value; | 908 | long *valp = ucontrol->value.integer.value; |
889 | 909 | ||
890 | if (chs & 1) | 910 | if (chs & 1) |
891 | *valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) & 0x80) ? 0 : 1; | 911 | *valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) & |
912 | 0x80) ? 0 : 1; | ||
892 | if (chs & 2) | 913 | if (chs & 2) |
893 | *valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) & 0x80) ? 0 : 1; | 914 | *valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) & |
915 | 0x80) ? 0 : 1; | ||
894 | return 0; | 916 | return 0; |
895 | } | 917 | } |
896 | 918 | ||
897 | int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 919 | int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, |
920 | struct snd_ctl_elem_value *ucontrol) | ||
898 | { | 921 | { |
899 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 922 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
900 | hda_nid_t nid = get_amp_nid(kcontrol); | 923 | hda_nid_t nid = get_amp_nid(kcontrol); |
@@ -925,7 +948,8 @@ int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
925 | #define AMP_VAL_IDX_SHIFT 19 | 948 | #define AMP_VAL_IDX_SHIFT 19 |
926 | #define AMP_VAL_IDX_MASK (0x0f<<19) | 949 | #define AMP_VAL_IDX_MASK (0x0f<<19) |
927 | 950 | ||
928 | int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 951 | int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol, |
952 | struct snd_ctl_elem_value *ucontrol) | ||
929 | { | 953 | { |
930 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 954 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
931 | unsigned long pval; | 955 | unsigned long pval; |
@@ -940,7 +964,8 @@ int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
940 | return err; | 964 | return err; |
941 | } | 965 | } |
942 | 966 | ||
943 | int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 967 | int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol, |
968 | struct snd_ctl_elem_value *ucontrol) | ||
944 | { | 969 | { |
945 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 970 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
946 | unsigned long pval; | 971 | unsigned long pval; |
@@ -950,7 +975,8 @@ int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
950 | pval = kcontrol->private_value; | 975 | pval = kcontrol->private_value; |
951 | indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT; | 976 | indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT; |
952 | for (i = 0; i < indices; i++) { | 977 | for (i = 0; i < indices; i++) { |
953 | kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) | (i << AMP_VAL_IDX_SHIFT); | 978 | kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) | |
979 | (i << AMP_VAL_IDX_SHIFT); | ||
954 | err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); | 980 | err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); |
955 | if (err < 0) | 981 | if (err < 0) |
956 | break; | 982 | break; |
@@ -965,14 +991,16 @@ int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
965 | * SPDIF out controls | 991 | * SPDIF out controls |
966 | */ | 992 | */ |
967 | 993 | ||
968 | static int snd_hda_spdif_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 994 | static int snd_hda_spdif_mask_info(struct snd_kcontrol *kcontrol, |
995 | struct snd_ctl_elem_info *uinfo) | ||
969 | { | 996 | { |
970 | uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; | 997 | uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; |
971 | uinfo->count = 1; | 998 | uinfo->count = 1; |
972 | return 0; | 999 | return 0; |
973 | } | 1000 | } |
974 | 1001 | ||
975 | static int snd_hda_spdif_cmask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1002 | static int snd_hda_spdif_cmask_get(struct snd_kcontrol *kcontrol, |
1003 | struct snd_ctl_elem_value *ucontrol) | ||
976 | { | 1004 | { |
977 | ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL | | 1005 | ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL | |
978 | IEC958_AES0_NONAUDIO | | 1006 | IEC958_AES0_NONAUDIO | |
@@ -983,7 +1011,8 @@ static int snd_hda_spdif_cmask_get(struct snd_kcontrol *kcontrol, struct snd_ctl | |||
983 | return 0; | 1011 | return 0; |
984 | } | 1012 | } |
985 | 1013 | ||
986 | static int snd_hda_spdif_pmask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1014 | static int snd_hda_spdif_pmask_get(struct snd_kcontrol *kcontrol, |
1015 | struct snd_ctl_elem_value *ucontrol) | ||
987 | { | 1016 | { |
988 | ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL | | 1017 | ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL | |
989 | IEC958_AES0_NONAUDIO | | 1018 | IEC958_AES0_NONAUDIO | |
@@ -991,7 +1020,8 @@ static int snd_hda_spdif_pmask_get(struct snd_kcontrol *kcontrol, struct snd_ctl | |||
991 | return 0; | 1020 | return 0; |
992 | } | 1021 | } |
993 | 1022 | ||
994 | static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1023 | static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol, |
1024 | struct snd_ctl_elem_value *ucontrol) | ||
995 | { | 1025 | { |
996 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 1026 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
997 | 1027 | ||
@@ -1011,19 +1041,21 @@ static unsigned short convert_from_spdif_status(unsigned int sbits) | |||
1011 | unsigned short val = 0; | 1041 | unsigned short val = 0; |
1012 | 1042 | ||
1013 | if (sbits & IEC958_AES0_PROFESSIONAL) | 1043 | if (sbits & IEC958_AES0_PROFESSIONAL) |
1014 | val |= 1 << 6; | 1044 | val |= AC_DIG1_PROFESSIONAL; |
1015 | if (sbits & IEC958_AES0_NONAUDIO) | 1045 | if (sbits & IEC958_AES0_NONAUDIO) |
1016 | val |= 1 << 5; | 1046 | val |= AC_DIG1_NONAUDIO; |
1017 | if (sbits & IEC958_AES0_PROFESSIONAL) { | 1047 | if (sbits & IEC958_AES0_PROFESSIONAL) { |
1018 | if ((sbits & IEC958_AES0_PRO_EMPHASIS) == IEC958_AES0_PRO_EMPHASIS_5015) | 1048 | if ((sbits & IEC958_AES0_PRO_EMPHASIS) == |
1019 | val |= 1 << 3; | 1049 | IEC958_AES0_PRO_EMPHASIS_5015) |
1050 | val |= AC_DIG1_EMPHASIS; | ||
1020 | } else { | 1051 | } else { |
1021 | if ((sbits & IEC958_AES0_CON_EMPHASIS) == IEC958_AES0_CON_EMPHASIS_5015) | 1052 | if ((sbits & IEC958_AES0_CON_EMPHASIS) == |
1022 | val |= 1 << 3; | 1053 | IEC958_AES0_CON_EMPHASIS_5015) |
1023 | if (! (sbits & IEC958_AES0_CON_NOT_COPYRIGHT)) | 1054 | val |= AC_DIG1_EMPHASIS; |
1024 | val |= 1 << 4; | 1055 | if (!(sbits & IEC958_AES0_CON_NOT_COPYRIGHT)) |
1056 | val |= AC_DIG1_COPYRIGHT; | ||
1025 | if (sbits & (IEC958_AES1_CON_ORIGINAL << 8)) | 1057 | if (sbits & (IEC958_AES1_CON_ORIGINAL << 8)) |
1026 | val |= 1 << 7; | 1058 | val |= AC_DIG1_LEVEL; |
1027 | val |= sbits & (IEC958_AES1_CON_CATEGORY << 8); | 1059 | val |= sbits & (IEC958_AES1_CON_CATEGORY << 8); |
1028 | } | 1060 | } |
1029 | return val; | 1061 | return val; |
@@ -1035,26 +1067,27 @@ static unsigned int convert_to_spdif_status(unsigned short val) | |||
1035 | { | 1067 | { |
1036 | unsigned int sbits = 0; | 1068 | unsigned int sbits = 0; |
1037 | 1069 | ||
1038 | if (val & (1 << 5)) | 1070 | if (val & AC_DIG1_NONAUDIO) |
1039 | sbits |= IEC958_AES0_NONAUDIO; | 1071 | sbits |= IEC958_AES0_NONAUDIO; |
1040 | if (val & (1 << 6)) | 1072 | if (val & AC_DIG1_PROFESSIONAL) |
1041 | sbits |= IEC958_AES0_PROFESSIONAL; | 1073 | sbits |= IEC958_AES0_PROFESSIONAL; |
1042 | if (sbits & IEC958_AES0_PROFESSIONAL) { | 1074 | if (sbits & IEC958_AES0_PROFESSIONAL) { |
1043 | if (sbits & (1 << 3)) | 1075 | if (sbits & AC_DIG1_EMPHASIS) |
1044 | sbits |= IEC958_AES0_PRO_EMPHASIS_5015; | 1076 | sbits |= IEC958_AES0_PRO_EMPHASIS_5015; |
1045 | } else { | 1077 | } else { |
1046 | if (val & (1 << 3)) | 1078 | if (val & AC_DIG1_EMPHASIS) |
1047 | sbits |= IEC958_AES0_CON_EMPHASIS_5015; | 1079 | sbits |= IEC958_AES0_CON_EMPHASIS_5015; |
1048 | if (! (val & (1 << 4))) | 1080 | if (!(val & AC_DIG1_COPYRIGHT)) |
1049 | sbits |= IEC958_AES0_CON_NOT_COPYRIGHT; | 1081 | sbits |= IEC958_AES0_CON_NOT_COPYRIGHT; |
1050 | if (val & (1 << 7)) | 1082 | if (val & AC_DIG1_LEVEL) |
1051 | sbits |= (IEC958_AES1_CON_ORIGINAL << 8); | 1083 | sbits |= (IEC958_AES1_CON_ORIGINAL << 8); |
1052 | sbits |= val & (0x7f << 8); | 1084 | sbits |= val & (0x7f << 8); |
1053 | } | 1085 | } |
1054 | return sbits; | 1086 | return sbits; |
1055 | } | 1087 | } |
1056 | 1088 | ||
1057 | static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1089 | static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol, |
1090 | struct snd_ctl_elem_value *ucontrol) | ||
1058 | { | 1091 | { |
1059 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 1092 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
1060 | hda_nid_t nid = kcontrol->private_value; | 1093 | hda_nid_t nid = kcontrol->private_value; |
@@ -1072,15 +1105,18 @@ static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol, struct snd_c | |||
1072 | codec->spdif_ctls = val; | 1105 | codec->spdif_ctls = val; |
1073 | 1106 | ||
1074 | if (change || codec->in_resume) { | 1107 | if (change || codec->in_resume) { |
1075 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, val & 0xff); | 1108 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, |
1076 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_2, val >> 8); | 1109 | val & 0xff); |
1110 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_2, | ||
1111 | val >> 8); | ||
1077 | } | 1112 | } |
1078 | 1113 | ||
1079 | mutex_unlock(&codec->spdif_mutex); | 1114 | mutex_unlock(&codec->spdif_mutex); |
1080 | return change; | 1115 | return change; |
1081 | } | 1116 | } |
1082 | 1117 | ||
1083 | static int snd_hda_spdif_out_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1118 | static int snd_hda_spdif_out_switch_info(struct snd_kcontrol *kcontrol, |
1119 | struct snd_ctl_elem_info *uinfo) | ||
1084 | { | 1120 | { |
1085 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | 1121 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; |
1086 | uinfo->count = 1; | 1122 | uinfo->count = 1; |
@@ -1089,15 +1125,17 @@ static int snd_hda_spdif_out_switch_info(struct snd_kcontrol *kcontrol, struct s | |||
1089 | return 0; | 1125 | return 0; |
1090 | } | 1126 | } |
1091 | 1127 | ||
1092 | static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1128 | static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol, |
1129 | struct snd_ctl_elem_value *ucontrol) | ||
1093 | { | 1130 | { |
1094 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 1131 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
1095 | 1132 | ||
1096 | ucontrol->value.integer.value[0] = codec->spdif_ctls & 1; | 1133 | ucontrol->value.integer.value[0] = codec->spdif_ctls & AC_DIG1_ENABLE; |
1097 | return 0; | 1134 | return 0; |
1098 | } | 1135 | } |
1099 | 1136 | ||
1100 | static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1137 | static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol, |
1138 | struct snd_ctl_elem_value *ucontrol) | ||
1101 | { | 1139 | { |
1102 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 1140 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
1103 | hda_nid_t nid = kcontrol->private_value; | 1141 | hda_nid_t nid = kcontrol->private_value; |
@@ -1105,16 +1143,21 @@ static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol, struct sn | |||
1105 | int change; | 1143 | int change; |
1106 | 1144 | ||
1107 | mutex_lock(&codec->spdif_mutex); | 1145 | mutex_lock(&codec->spdif_mutex); |
1108 | val = codec->spdif_ctls & ~1; | 1146 | val = codec->spdif_ctls & ~AC_DIG1_ENABLE; |
1109 | if (ucontrol->value.integer.value[0]) | 1147 | if (ucontrol->value.integer.value[0]) |
1110 | val |= 1; | 1148 | val |= AC_DIG1_ENABLE; |
1111 | change = codec->spdif_ctls != val; | 1149 | change = codec->spdif_ctls != val; |
1112 | if (change || codec->in_resume) { | 1150 | if (change || codec->in_resume) { |
1113 | codec->spdif_ctls = val; | 1151 | codec->spdif_ctls = val; |
1114 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, val & 0xff); | 1152 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, |
1115 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, | 1153 | val & 0xff); |
1116 | AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | | 1154 | /* unmute amp switch (if any) */ |
1117 | AC_AMP_SET_OUTPUT | ((val & 1) ? 0 : 0x80)); | 1155 | if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) && |
1156 | (val & AC_DIG1_ENABLE)) | ||
1157 | snd_hda_codec_write(codec, nid, 0, | ||
1158 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
1159 | AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | | ||
1160 | AC_AMP_SET_OUTPUT); | ||
1118 | } | 1161 | } |
1119 | mutex_unlock(&codec->spdif_mutex); | 1162 | mutex_unlock(&codec->spdif_mutex); |
1120 | return change; | 1163 | return change; |
@@ -1162,7 +1205,8 @@ static struct snd_kcontrol_new dig_mixes[] = { | |||
1162 | * | 1205 | * |
1163 | * Returns 0 if successful, or a negative error code. | 1206 | * Returns 0 if successful, or a negative error code. |
1164 | */ | 1207 | */ |
1165 | int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid) | 1208 | int __devinit snd_hda_create_spdif_out_ctls(struct hda_codec *codec, |
1209 | hda_nid_t nid) | ||
1166 | { | 1210 | { |
1167 | int err; | 1211 | int err; |
1168 | struct snd_kcontrol *kctl; | 1212 | struct snd_kcontrol *kctl; |
@@ -1171,10 +1215,12 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid) | |||
1171 | for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) { | 1215 | for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) { |
1172 | kctl = snd_ctl_new1(dig_mix, codec); | 1216 | kctl = snd_ctl_new1(dig_mix, codec); |
1173 | kctl->private_value = nid; | 1217 | kctl->private_value = nid; |
1174 | if ((err = snd_ctl_add(codec->bus->card, kctl)) < 0) | 1218 | err = snd_ctl_add(codec->bus->card, kctl); |
1219 | if (err < 0) | ||
1175 | return err; | 1220 | return err; |
1176 | } | 1221 | } |
1177 | codec->spdif_ctls = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT, 0); | 1222 | codec->spdif_ctls = |
1223 | snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT, 0); | ||
1178 | codec->spdif_status = convert_to_spdif_status(codec->spdif_ctls); | 1224 | codec->spdif_status = convert_to_spdif_status(codec->spdif_ctls); |
1179 | return 0; | 1225 | return 0; |
1180 | } | 1226 | } |
@@ -1185,7 +1231,8 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid) | |||
1185 | 1231 | ||
1186 | #define snd_hda_spdif_in_switch_info snd_hda_spdif_out_switch_info | 1232 | #define snd_hda_spdif_in_switch_info snd_hda_spdif_out_switch_info |
1187 | 1233 | ||
1188 | static int snd_hda_spdif_in_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1234 | static int snd_hda_spdif_in_switch_get(struct snd_kcontrol *kcontrol, |
1235 | struct snd_ctl_elem_value *ucontrol) | ||
1189 | { | 1236 | { |
1190 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 1237 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
1191 | 1238 | ||
@@ -1193,7 +1240,8 @@ static int snd_hda_spdif_in_switch_get(struct snd_kcontrol *kcontrol, struct snd | |||
1193 | return 0; | 1240 | return 0; |
1194 | } | 1241 | } |
1195 | 1242 | ||
1196 | static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1243 | static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol, |
1244 | struct snd_ctl_elem_value *ucontrol) | ||
1197 | { | 1245 | { |
1198 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 1246 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
1199 | hda_nid_t nid = kcontrol->private_value; | 1247 | hda_nid_t nid = kcontrol->private_value; |
@@ -1204,13 +1252,15 @@ static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol, struct snd | |||
1204 | change = codec->spdif_in_enable != val; | 1252 | change = codec->spdif_in_enable != val; |
1205 | if (change || codec->in_resume) { | 1253 | if (change || codec->in_resume) { |
1206 | codec->spdif_in_enable = val; | 1254 | codec->spdif_in_enable = val; |
1207 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, val); | 1255 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, |
1256 | val); | ||
1208 | } | 1257 | } |
1209 | mutex_unlock(&codec->spdif_mutex); | 1258 | mutex_unlock(&codec->spdif_mutex); |
1210 | return change; | 1259 | return change; |
1211 | } | 1260 | } |
1212 | 1261 | ||
1213 | static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1262 | static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol, |
1263 | struct snd_ctl_elem_value *ucontrol) | ||
1214 | { | 1264 | { |
1215 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 1265 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
1216 | hda_nid_t nid = kcontrol->private_value; | 1266 | hda_nid_t nid = kcontrol->private_value; |
@@ -1254,7 +1304,8 @@ static struct snd_kcontrol_new dig_in_ctls[] = { | |||
1254 | * | 1304 | * |
1255 | * Returns 0 if successful, or a negative error code. | 1305 | * Returns 0 if successful, or a negative error code. |
1256 | */ | 1306 | */ |
1257 | int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid) | 1307 | int __devinit snd_hda_create_spdif_in_ctls(struct hda_codec *codec, |
1308 | hda_nid_t nid) | ||
1258 | { | 1309 | { |
1259 | int err; | 1310 | int err; |
1260 | struct snd_kcontrol *kctl; | 1311 | struct snd_kcontrol *kctl; |
@@ -1263,10 +1314,13 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid) | |||
1263 | for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) { | 1314 | for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) { |
1264 | kctl = snd_ctl_new1(dig_mix, codec); | 1315 | kctl = snd_ctl_new1(dig_mix, codec); |
1265 | kctl->private_value = nid; | 1316 | kctl->private_value = nid; |
1266 | if ((err = snd_ctl_add(codec->bus->card, kctl)) < 0) | 1317 | err = snd_ctl_add(codec->bus->card, kctl); |
1318 | if (err < 0) | ||
1267 | return err; | 1319 | return err; |
1268 | } | 1320 | } |
1269 | codec->spdif_in_enable = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT, 0) & 1; | 1321 | codec->spdif_in_enable = |
1322 | snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT, 0) & | ||
1323 | AC_DIG1_ENABLE; | ||
1270 | return 0; | 1324 | return 0; |
1271 | } | 1325 | } |
1272 | 1326 | ||
@@ -1304,15 +1358,14 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, | |||
1304 | * | 1358 | * |
1305 | * Returns 0 if successful, otherwise a negative error code. | 1359 | * Returns 0 if successful, otherwise a negative error code. |
1306 | */ | 1360 | */ |
1307 | int snd_hda_build_controls(struct hda_bus *bus) | 1361 | int __devinit snd_hda_build_controls(struct hda_bus *bus) |
1308 | { | 1362 | { |
1309 | struct list_head *p; | 1363 | struct hda_codec *codec; |
1310 | 1364 | ||
1311 | /* build controls */ | 1365 | /* build controls */ |
1312 | list_for_each(p, &bus->codec_list) { | 1366 | list_for_each_entry(codec, &bus->codec_list, list) { |
1313 | struct hda_codec *codec = list_entry(p, struct hda_codec, list); | ||
1314 | int err; | 1367 | int err; |
1315 | if (! codec->patch_ops.build_controls) | 1368 | if (!codec->patch_ops.build_controls) |
1316 | continue; | 1369 | continue; |
1317 | err = codec->patch_ops.build_controls(codec); | 1370 | err = codec->patch_ops.build_controls(codec); |
1318 | if (err < 0) | 1371 | if (err < 0) |
@@ -1320,13 +1373,12 @@ int snd_hda_build_controls(struct hda_bus *bus) | |||
1320 | } | 1373 | } |
1321 | 1374 | ||
1322 | /* initialize */ | 1375 | /* initialize */ |
1323 | list_for_each(p, &bus->codec_list) { | 1376 | list_for_each_entry(codec, &bus->codec_list, list) { |
1324 | struct hda_codec *codec = list_entry(p, struct hda_codec, list); | ||
1325 | int err; | 1377 | int err; |
1326 | hda_set_power_state(codec, | 1378 | hda_set_power_state(codec, |
1327 | codec->afg ? codec->afg : codec->mfg, | 1379 | codec->afg ? codec->afg : codec->mfg, |
1328 | AC_PWRST_D0); | 1380 | AC_PWRST_D0); |
1329 | if (! codec->patch_ops.init) | 1381 | if (!codec->patch_ops.init) |
1330 | continue; | 1382 | continue; |
1331 | err = codec->patch_ops.init(codec); | 1383 | err = codec->patch_ops.init(codec); |
1332 | if (err < 0) | 1384 | if (err < 0) |
@@ -1335,8 +1387,6 @@ int snd_hda_build_controls(struct hda_bus *bus) | |||
1335 | return 0; | 1387 | return 0; |
1336 | } | 1388 | } |
1337 | 1389 | ||
1338 | EXPORT_SYMBOL(snd_hda_build_controls); | ||
1339 | |||
1340 | /* | 1390 | /* |
1341 | * stream formats | 1391 | * stream formats |
1342 | */ | 1392 | */ |
@@ -1361,6 +1411,11 @@ static struct hda_rate_tbl rate_bits[] = { | |||
1361 | { 96000, SNDRV_PCM_RATE_96000, 0x0800 }, /* 2 x 48 */ | 1411 | { 96000, SNDRV_PCM_RATE_96000, 0x0800 }, /* 2 x 48 */ |
1362 | { 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */ | 1412 | { 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */ |
1363 | { 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */ | 1413 | { 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */ |
1414 | #define AC_PAR_PCM_RATE_BITS 11 | ||
1415 | /* up to bits 10, 384kHZ isn't supported properly */ | ||
1416 | |||
1417 | /* not autodetected value */ | ||
1418 | { 9600, SNDRV_PCM_RATE_KNOT, 0x0400 }, /* 1/5 x 48 */ | ||
1364 | 1419 | ||
1365 | { 0 } /* terminator */ | 1420 | { 0 } /* terminator */ |
1366 | }; | 1421 | }; |
@@ -1389,7 +1444,7 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate, | |||
1389 | val = rate_bits[i].hda_fmt; | 1444 | val = rate_bits[i].hda_fmt; |
1390 | break; | 1445 | break; |
1391 | } | 1446 | } |
1392 | if (! rate_bits[i].hz) { | 1447 | if (!rate_bits[i].hz) { |
1393 | snd_printdd("invalid rate %d\n", rate); | 1448 | snd_printdd("invalid rate %d\n", rate); |
1394 | return 0; | 1449 | return 0; |
1395 | } | 1450 | } |
@@ -1414,15 +1469,14 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate, | |||
1414 | val |= 0x20; | 1469 | val |= 0x20; |
1415 | break; | 1470 | break; |
1416 | default: | 1471 | default: |
1417 | snd_printdd("invalid format width %d\n", snd_pcm_format_width(format)); | 1472 | snd_printdd("invalid format width %d\n", |
1473 | snd_pcm_format_width(format)); | ||
1418 | return 0; | 1474 | return 0; |
1419 | } | 1475 | } |
1420 | 1476 | ||
1421 | return val; | 1477 | return val; |
1422 | } | 1478 | } |
1423 | 1479 | ||
1424 | EXPORT_SYMBOL(snd_hda_calc_stream_format); | ||
1425 | |||
1426 | /** | 1480 | /** |
1427 | * snd_hda_query_supported_pcm - query the supported PCM rates and formats | 1481 | * snd_hda_query_supported_pcm - query the supported PCM rates and formats |
1428 | * @codec: the HDA codec | 1482 | * @codec: the HDA codec |
@@ -1449,12 +1503,12 @@ int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, | |||
1449 | if (val == -1) | 1503 | if (val == -1) |
1450 | return -EIO; | 1504 | return -EIO; |
1451 | } | 1505 | } |
1452 | if (! val) | 1506 | if (!val) |
1453 | val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM); | 1507 | val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM); |
1454 | 1508 | ||
1455 | if (ratesp) { | 1509 | if (ratesp) { |
1456 | u32 rates = 0; | 1510 | u32 rates = 0; |
1457 | for (i = 0; rate_bits[i].hz; i++) { | 1511 | for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) { |
1458 | if (val & (1 << i)) | 1512 | if (val & (1 << i)) |
1459 | rates |= rate_bits[i].alsa_bits; | 1513 | rates |= rate_bits[i].alsa_bits; |
1460 | } | 1514 | } |
@@ -1470,8 +1524,9 @@ int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, | |||
1470 | streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM); | 1524 | streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM); |
1471 | if (streams == -1) | 1525 | if (streams == -1) |
1472 | return -EIO; | 1526 | return -EIO; |
1473 | if (! streams) { | 1527 | if (!streams) { |
1474 | streams = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM); | 1528 | streams = snd_hda_param_read(codec, codec->afg, |
1529 | AC_PAR_STREAM); | ||
1475 | if (streams == -1) | 1530 | if (streams == -1) |
1476 | return -EIO; | 1531 | return -EIO; |
1477 | } | 1532 | } |
@@ -1495,7 +1550,8 @@ int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, | |||
1495 | bps = 24; | 1550 | bps = 24; |
1496 | else if (val & AC_SUPPCM_BITS_20) | 1551 | else if (val & AC_SUPPCM_BITS_20) |
1497 | bps = 20; | 1552 | bps = 20; |
1498 | } else if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24|AC_SUPPCM_BITS_32)) { | 1553 | } else if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24| |
1554 | AC_SUPPCM_BITS_32)) { | ||
1499 | formats |= SNDRV_PCM_FMTBIT_S32_LE; | 1555 | formats |= SNDRV_PCM_FMTBIT_S32_LE; |
1500 | if (val & AC_SUPPCM_BITS_32) | 1556 | if (val & AC_SUPPCM_BITS_32) |
1501 | bps = 32; | 1557 | bps = 32; |
@@ -1505,10 +1561,12 @@ int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, | |||
1505 | bps = 20; | 1561 | bps = 20; |
1506 | } | 1562 | } |
1507 | } | 1563 | } |
1508 | else if (streams == AC_SUPFMT_FLOAT32) { /* should be exclusive */ | 1564 | else if (streams == AC_SUPFMT_FLOAT32) { |
1565 | /* should be exclusive */ | ||
1509 | formats |= SNDRV_PCM_FMTBIT_FLOAT_LE; | 1566 | formats |= SNDRV_PCM_FMTBIT_FLOAT_LE; |
1510 | bps = 32; | 1567 | bps = 32; |
1511 | } else if (streams == AC_SUPFMT_AC3) { /* should be exclusive */ | 1568 | } else if (streams == AC_SUPFMT_AC3) { |
1569 | /* should be exclusive */ | ||
1512 | /* temporary hack: we have still no proper support | 1570 | /* temporary hack: we have still no proper support |
1513 | * for the direct AC3 stream... | 1571 | * for the direct AC3 stream... |
1514 | */ | 1572 | */ |
@@ -1525,7 +1583,8 @@ int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, | |||
1525 | } | 1583 | } |
1526 | 1584 | ||
1527 | /** | 1585 | /** |
1528 | * snd_hda_is_supported_format - check whether the given node supports the format val | 1586 | * snd_hda_is_supported_format - check whether the given node supports |
1587 | * the format val | ||
1529 | * | 1588 | * |
1530 | * Returns 1 if supported, 0 if not. | 1589 | * Returns 1 if supported, 0 if not. |
1531 | */ | 1590 | */ |
@@ -1541,50 +1600,50 @@ int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid, | |||
1541 | if (val == -1) | 1600 | if (val == -1) |
1542 | return 0; | 1601 | return 0; |
1543 | } | 1602 | } |
1544 | if (! val) { | 1603 | if (!val) { |
1545 | val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM); | 1604 | val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM); |
1546 | if (val == -1) | 1605 | if (val == -1) |
1547 | return 0; | 1606 | return 0; |
1548 | } | 1607 | } |
1549 | 1608 | ||
1550 | rate = format & 0xff00; | 1609 | rate = format & 0xff00; |
1551 | for (i = 0; rate_bits[i].hz; i++) | 1610 | for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) |
1552 | if (rate_bits[i].hda_fmt == rate) { | 1611 | if (rate_bits[i].hda_fmt == rate) { |
1553 | if (val & (1 << i)) | 1612 | if (val & (1 << i)) |
1554 | break; | 1613 | break; |
1555 | return 0; | 1614 | return 0; |
1556 | } | 1615 | } |
1557 | if (! rate_bits[i].hz) | 1616 | if (i >= AC_PAR_PCM_RATE_BITS) |
1558 | return 0; | 1617 | return 0; |
1559 | 1618 | ||
1560 | stream = snd_hda_param_read(codec, nid, AC_PAR_STREAM); | 1619 | stream = snd_hda_param_read(codec, nid, AC_PAR_STREAM); |
1561 | if (stream == -1) | 1620 | if (stream == -1) |
1562 | return 0; | 1621 | return 0; |
1563 | if (! stream && nid != codec->afg) | 1622 | if (!stream && nid != codec->afg) |
1564 | stream = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM); | 1623 | stream = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM); |
1565 | if (! stream || stream == -1) | 1624 | if (!stream || stream == -1) |
1566 | return 0; | 1625 | return 0; |
1567 | 1626 | ||
1568 | if (stream & AC_SUPFMT_PCM) { | 1627 | if (stream & AC_SUPFMT_PCM) { |
1569 | switch (format & 0xf0) { | 1628 | switch (format & 0xf0) { |
1570 | case 0x00: | 1629 | case 0x00: |
1571 | if (! (val & AC_SUPPCM_BITS_8)) | 1630 | if (!(val & AC_SUPPCM_BITS_8)) |
1572 | return 0; | 1631 | return 0; |
1573 | break; | 1632 | break; |
1574 | case 0x10: | 1633 | case 0x10: |
1575 | if (! (val & AC_SUPPCM_BITS_16)) | 1634 | if (!(val & AC_SUPPCM_BITS_16)) |
1576 | return 0; | 1635 | return 0; |
1577 | break; | 1636 | break; |
1578 | case 0x20: | 1637 | case 0x20: |
1579 | if (! (val & AC_SUPPCM_BITS_20)) | 1638 | if (!(val & AC_SUPPCM_BITS_20)) |
1580 | return 0; | 1639 | return 0; |
1581 | break; | 1640 | break; |
1582 | case 0x30: | 1641 | case 0x30: |
1583 | if (! (val & AC_SUPPCM_BITS_24)) | 1642 | if (!(val & AC_SUPPCM_BITS_24)) |
1584 | return 0; | 1643 | return 0; |
1585 | break; | 1644 | break; |
1586 | case 0x40: | 1645 | case 0x40: |
1587 | if (! (val & AC_SUPPCM_BITS_32)) | 1646 | if (!(val & AC_SUPPCM_BITS_32)) |
1588 | return 0; | 1647 | return 0; |
1589 | break; | 1648 | break; |
1590 | default: | 1649 | default: |
@@ -1625,15 +1684,15 @@ static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo, | |||
1625 | return 0; | 1684 | return 0; |
1626 | } | 1685 | } |
1627 | 1686 | ||
1628 | static int set_pcm_default_values(struct hda_codec *codec, struct hda_pcm_stream *info) | 1687 | static int __devinit set_pcm_default_values(struct hda_codec *codec, |
1688 | struct hda_pcm_stream *info) | ||
1629 | { | 1689 | { |
1630 | if (info->nid) { | 1690 | /* query support PCM information from the given NID */ |
1631 | /* query support PCM information from the given NID */ | 1691 | if (info->nid && (!info->rates || !info->formats)) { |
1632 | if (! info->rates || ! info->formats) | 1692 | snd_hda_query_supported_pcm(codec, info->nid, |
1633 | snd_hda_query_supported_pcm(codec, info->nid, | 1693 | info->rates ? NULL : &info->rates, |
1634 | info->rates ? NULL : &info->rates, | 1694 | info->formats ? NULL : &info->formats, |
1635 | info->formats ? NULL : &info->formats, | 1695 | info->maxbps ? NULL : &info->maxbps); |
1636 | info->maxbps ? NULL : &info->maxbps); | ||
1637 | } | 1696 | } |
1638 | if (info->ops.open == NULL) | 1697 | if (info->ops.open == NULL) |
1639 | info->ops.open = hda_pcm_default_open_close; | 1698 | info->ops.open = hda_pcm_default_open_close; |
@@ -1676,15 +1735,14 @@ static int set_pcm_default_values(struct hda_codec *codec, struct hda_pcm_stream | |||
1676 | * | 1735 | * |
1677 | * This function returns 0 if successfull, or a negative error code. | 1736 | * This function returns 0 if successfull, or a negative error code. |
1678 | */ | 1737 | */ |
1679 | int snd_hda_build_pcms(struct hda_bus *bus) | 1738 | int __devinit snd_hda_build_pcms(struct hda_bus *bus) |
1680 | { | 1739 | { |
1681 | struct list_head *p; | 1740 | struct hda_codec *codec; |
1682 | 1741 | ||
1683 | list_for_each(p, &bus->codec_list) { | 1742 | list_for_each_entry(codec, &bus->codec_list, list) { |
1684 | struct hda_codec *codec = list_entry(p, struct hda_codec, list); | ||
1685 | unsigned int pcm, s; | 1743 | unsigned int pcm, s; |
1686 | int err; | 1744 | int err; |
1687 | if (! codec->patch_ops.build_pcms) | 1745 | if (!codec->patch_ops.build_pcms) |
1688 | continue; | 1746 | continue; |
1689 | err = codec->patch_ops.build_pcms(codec); | 1747 | err = codec->patch_ops.build_pcms(codec); |
1690 | if (err < 0) | 1748 | if (err < 0) |
@@ -1693,7 +1751,7 @@ int snd_hda_build_pcms(struct hda_bus *bus) | |||
1693 | for (s = 0; s < 2; s++) { | 1751 | for (s = 0; s < 2; s++) { |
1694 | struct hda_pcm_stream *info; | 1752 | struct hda_pcm_stream *info; |
1695 | info = &codec->pcm_info[pcm].stream[s]; | 1753 | info = &codec->pcm_info[pcm].stream[s]; |
1696 | if (! info->substreams) | 1754 | if (!info->substreams) |
1697 | continue; | 1755 | continue; |
1698 | err = set_pcm_default_values(codec, info); | 1756 | err = set_pcm_default_values(codec, info); |
1699 | if (err < 0) | 1757 | if (err < 0) |
@@ -1704,8 +1762,6 @@ int snd_hda_build_pcms(struct hda_bus *bus) | |||
1704 | return 0; | 1762 | return 0; |
1705 | } | 1763 | } |
1706 | 1764 | ||
1707 | EXPORT_SYMBOL(snd_hda_build_pcms); | ||
1708 | |||
1709 | /** | 1765 | /** |
1710 | * snd_hda_check_board_config - compare the current codec with the config table | 1766 | * snd_hda_check_board_config - compare the current codec with the config table |
1711 | * @codec: the HDA codec | 1767 | * @codec: the HDA codec |
@@ -1719,9 +1775,9 @@ EXPORT_SYMBOL(snd_hda_build_pcms); | |||
1719 | * | 1775 | * |
1720 | * If no entries are matching, the function returns a negative value. | 1776 | * If no entries are matching, the function returns a negative value. |
1721 | */ | 1777 | */ |
1722 | int snd_hda_check_board_config(struct hda_codec *codec, | 1778 | int __devinit snd_hda_check_board_config(struct hda_codec *codec, |
1723 | int num_configs, const char **models, | 1779 | int num_configs, const char **models, |
1724 | const struct snd_pci_quirk *tbl) | 1780 | const struct snd_pci_quirk *tbl) |
1725 | { | 1781 | { |
1726 | if (codec->bus->modelname && models) { | 1782 | if (codec->bus->modelname && models) { |
1727 | int i; | 1783 | int i; |
@@ -1771,24 +1827,26 @@ int snd_hda_check_board_config(struct hda_codec *codec, | |||
1771 | * | 1827 | * |
1772 | * Returns 0 if successful, or a negative error code. | 1828 | * Returns 0 if successful, or a negative error code. |
1773 | */ | 1829 | */ |
1774 | int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew) | 1830 | int __devinit snd_hda_add_new_ctls(struct hda_codec *codec, |
1831 | struct snd_kcontrol_new *knew) | ||
1775 | { | 1832 | { |
1776 | int err; | 1833 | int err; |
1777 | 1834 | ||
1778 | for (; knew->name; knew++) { | 1835 | for (; knew->name; knew++) { |
1779 | struct snd_kcontrol *kctl; | 1836 | struct snd_kcontrol *kctl; |
1780 | kctl = snd_ctl_new1(knew, codec); | 1837 | kctl = snd_ctl_new1(knew, codec); |
1781 | if (! kctl) | 1838 | if (!kctl) |
1782 | return -ENOMEM; | 1839 | return -ENOMEM; |
1783 | err = snd_ctl_add(codec->bus->card, kctl); | 1840 | err = snd_ctl_add(codec->bus->card, kctl); |
1784 | if (err < 0) { | 1841 | if (err < 0) { |
1785 | if (! codec->addr) | 1842 | if (!codec->addr) |
1786 | return err; | 1843 | return err; |
1787 | kctl = snd_ctl_new1(knew, codec); | 1844 | kctl = snd_ctl_new1(knew, codec); |
1788 | if (! kctl) | 1845 | if (!kctl) |
1789 | return -ENOMEM; | 1846 | return -ENOMEM; |
1790 | kctl->id.device = codec->addr; | 1847 | kctl->id.device = codec->addr; |
1791 | if ((err = snd_ctl_add(codec->bus->card, kctl)) < 0) | 1848 | err = snd_ctl_add(codec->bus->card, kctl); |
1849 | if (err < 0) | ||
1792 | return err; | 1850 | return err; |
1793 | } | 1851 | } |
1794 | } | 1852 | } |
@@ -1799,8 +1857,10 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew) | |||
1799 | /* | 1857 | /* |
1800 | * Channel mode helper | 1858 | * Channel mode helper |
1801 | */ | 1859 | */ |
1802 | int snd_hda_ch_mode_info(struct hda_codec *codec, struct snd_ctl_elem_info *uinfo, | 1860 | int snd_hda_ch_mode_info(struct hda_codec *codec, |
1803 | const struct hda_channel_mode *chmode, int num_chmodes) | 1861 | struct snd_ctl_elem_info *uinfo, |
1862 | const struct hda_channel_mode *chmode, | ||
1863 | int num_chmodes) | ||
1804 | { | 1864 | { |
1805 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 1865 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
1806 | uinfo->count = 1; | 1866 | uinfo->count = 1; |
@@ -1812,8 +1872,10 @@ int snd_hda_ch_mode_info(struct hda_codec *codec, struct snd_ctl_elem_info *uinf | |||
1812 | return 0; | 1872 | return 0; |
1813 | } | 1873 | } |
1814 | 1874 | ||
1815 | int snd_hda_ch_mode_get(struct hda_codec *codec, struct snd_ctl_elem_value *ucontrol, | 1875 | int snd_hda_ch_mode_get(struct hda_codec *codec, |
1816 | const struct hda_channel_mode *chmode, int num_chmodes, | 1876 | struct snd_ctl_elem_value *ucontrol, |
1877 | const struct hda_channel_mode *chmode, | ||
1878 | int num_chmodes, | ||
1817 | int max_channels) | 1879 | int max_channels) |
1818 | { | 1880 | { |
1819 | int i; | 1881 | int i; |
@@ -1827,15 +1889,17 @@ int snd_hda_ch_mode_get(struct hda_codec *codec, struct snd_ctl_elem_value *ucon | |||
1827 | return 0; | 1889 | return 0; |
1828 | } | 1890 | } |
1829 | 1891 | ||
1830 | int snd_hda_ch_mode_put(struct hda_codec *codec, struct snd_ctl_elem_value *ucontrol, | 1892 | int snd_hda_ch_mode_put(struct hda_codec *codec, |
1831 | const struct hda_channel_mode *chmode, int num_chmodes, | 1893 | struct snd_ctl_elem_value *ucontrol, |
1894 | const struct hda_channel_mode *chmode, | ||
1895 | int num_chmodes, | ||
1832 | int *max_channelsp) | 1896 | int *max_channelsp) |
1833 | { | 1897 | { |
1834 | unsigned int mode; | 1898 | unsigned int mode; |
1835 | 1899 | ||
1836 | mode = ucontrol->value.enumerated.item[0]; | 1900 | mode = ucontrol->value.enumerated.item[0]; |
1837 | snd_assert(mode < num_chmodes, return -EINVAL); | 1901 | snd_assert(mode < num_chmodes, return -EINVAL); |
1838 | if (*max_channelsp == chmode[mode].channels && ! codec->in_resume) | 1902 | if (*max_channelsp == chmode[mode].channels && !codec->in_resume) |
1839 | return 0; | 1903 | return 0; |
1840 | /* change the current channel setting */ | 1904 | /* change the current channel setting */ |
1841 | *max_channelsp = chmode[mode].channels; | 1905 | *max_channelsp = chmode[mode].channels; |
@@ -1847,7 +1911,8 @@ int snd_hda_ch_mode_put(struct hda_codec *codec, struct snd_ctl_elem_value *ucon | |||
1847 | /* | 1911 | /* |
1848 | * input MUX helper | 1912 | * input MUX helper |
1849 | */ | 1913 | */ |
1850 | int snd_hda_input_mux_info(const struct hda_input_mux *imux, struct snd_ctl_elem_info *uinfo) | 1914 | int snd_hda_input_mux_info(const struct hda_input_mux *imux, |
1915 | struct snd_ctl_elem_info *uinfo) | ||
1851 | { | 1916 | { |
1852 | unsigned int index; | 1917 | unsigned int index; |
1853 | 1918 | ||
@@ -1861,8 +1926,10 @@ int snd_hda_input_mux_info(const struct hda_input_mux *imux, struct snd_ctl_elem | |||
1861 | return 0; | 1926 | return 0; |
1862 | } | 1927 | } |
1863 | 1928 | ||
1864 | int snd_hda_input_mux_put(struct hda_codec *codec, const struct hda_input_mux *imux, | 1929 | int snd_hda_input_mux_put(struct hda_codec *codec, |
1865 | struct snd_ctl_elem_value *ucontrol, hda_nid_t nid, | 1930 | const struct hda_input_mux *imux, |
1931 | struct snd_ctl_elem_value *ucontrol, | ||
1932 | hda_nid_t nid, | ||
1866 | unsigned int *cur_val) | 1933 | unsigned int *cur_val) |
1867 | { | 1934 | { |
1868 | unsigned int idx; | 1935 | unsigned int idx; |
@@ -1870,7 +1937,7 @@ int snd_hda_input_mux_put(struct hda_codec *codec, const struct hda_input_mux *i | |||
1870 | idx = ucontrol->value.enumerated.item[0]; | 1937 | idx = ucontrol->value.enumerated.item[0]; |
1871 | if (idx >= imux->num_items) | 1938 | if (idx >= imux->num_items) |
1872 | idx = imux->num_items - 1; | 1939 | idx = imux->num_items - 1; |
1873 | if (*cur_val == idx && ! codec->in_resume) | 1940 | if (*cur_val == idx && !codec->in_resume) |
1874 | return 0; | 1941 | return 0; |
1875 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, | 1942 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, |
1876 | imux->items[idx].index); | 1943 | imux->items[idx].index); |
@@ -1883,25 +1950,53 @@ int snd_hda_input_mux_put(struct hda_codec *codec, const struct hda_input_mux *i | |||
1883 | * Multi-channel / digital-out PCM helper functions | 1950 | * Multi-channel / digital-out PCM helper functions |
1884 | */ | 1951 | */ |
1885 | 1952 | ||
1953 | /* setup SPDIF output stream */ | ||
1954 | static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid, | ||
1955 | unsigned int stream_tag, unsigned int format) | ||
1956 | { | ||
1957 | /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ | ||
1958 | if (codec->spdif_ctls & AC_DIG1_ENABLE) | ||
1959 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, | ||
1960 | codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); | ||
1961 | snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format); | ||
1962 | /* turn on again (if needed) */ | ||
1963 | if (codec->spdif_ctls & AC_DIG1_ENABLE) | ||
1964 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, | ||
1965 | codec->spdif_ctls & 0xff); | ||
1966 | } | ||
1967 | |||
1886 | /* | 1968 | /* |
1887 | * open the digital out in the exclusive mode | 1969 | * open the digital out in the exclusive mode |
1888 | */ | 1970 | */ |
1889 | int snd_hda_multi_out_dig_open(struct hda_codec *codec, struct hda_multi_out *mout) | 1971 | int snd_hda_multi_out_dig_open(struct hda_codec *codec, |
1972 | struct hda_multi_out *mout) | ||
1890 | { | 1973 | { |
1891 | mutex_lock(&codec->spdif_mutex); | 1974 | mutex_lock(&codec->spdif_mutex); |
1892 | if (mout->dig_out_used) { | 1975 | if (mout->dig_out_used == HDA_DIG_ANALOG_DUP) |
1893 | mutex_unlock(&codec->spdif_mutex); | 1976 | /* already opened as analog dup; reset it once */ |
1894 | return -EBUSY; /* already being used */ | 1977 | snd_hda_codec_setup_stream(codec, mout->dig_out_nid, 0, 0, 0); |
1895 | } | ||
1896 | mout->dig_out_used = HDA_DIG_EXCLUSIVE; | 1978 | mout->dig_out_used = HDA_DIG_EXCLUSIVE; |
1897 | mutex_unlock(&codec->spdif_mutex); | 1979 | mutex_unlock(&codec->spdif_mutex); |
1898 | return 0; | 1980 | return 0; |
1899 | } | 1981 | } |
1900 | 1982 | ||
1983 | int snd_hda_multi_out_dig_prepare(struct hda_codec *codec, | ||
1984 | struct hda_multi_out *mout, | ||
1985 | unsigned int stream_tag, | ||
1986 | unsigned int format, | ||
1987 | struct snd_pcm_substream *substream) | ||
1988 | { | ||
1989 | mutex_lock(&codec->spdif_mutex); | ||
1990 | setup_dig_out_stream(codec, mout->dig_out_nid, stream_tag, format); | ||
1991 | mutex_unlock(&codec->spdif_mutex); | ||
1992 | return 0; | ||
1993 | } | ||
1994 | |||
1901 | /* | 1995 | /* |
1902 | * release the digital out | 1996 | * release the digital out |
1903 | */ | 1997 | */ |
1904 | int snd_hda_multi_out_dig_close(struct hda_codec *codec, struct hda_multi_out *mout) | 1998 | int snd_hda_multi_out_dig_close(struct hda_codec *codec, |
1999 | struct hda_multi_out *mout) | ||
1905 | { | 2000 | { |
1906 | mutex_lock(&codec->spdif_mutex); | 2001 | mutex_lock(&codec->spdif_mutex); |
1907 | mout->dig_out_used = 0; | 2002 | mout->dig_out_used = 0; |
@@ -1912,7 +2007,8 @@ int snd_hda_multi_out_dig_close(struct hda_codec *codec, struct hda_multi_out *m | |||
1912 | /* | 2007 | /* |
1913 | * set up more restrictions for analog out | 2008 | * set up more restrictions for analog out |
1914 | */ | 2009 | */ |
1915 | int snd_hda_multi_out_analog_open(struct hda_codec *codec, struct hda_multi_out *mout, | 2010 | int snd_hda_multi_out_analog_open(struct hda_codec *codec, |
2011 | struct hda_multi_out *mout, | ||
1916 | struct snd_pcm_substream *substream) | 2012 | struct snd_pcm_substream *substream) |
1917 | { | 2013 | { |
1918 | substream->runtime->hw.channels_max = mout->max_channels; | 2014 | substream->runtime->hw.channels_max = mout->max_channels; |
@@ -1924,7 +2020,8 @@ int snd_hda_multi_out_analog_open(struct hda_codec *codec, struct hda_multi_out | |||
1924 | * set up the i/o for analog out | 2020 | * set up the i/o for analog out |
1925 | * when the digital out is available, copy the front out to digital out, too. | 2021 | * when the digital out is available, copy the front out to digital out, too. |
1926 | */ | 2022 | */ |
1927 | int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_out *mout, | 2023 | int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, |
2024 | struct hda_multi_out *mout, | ||
1928 | unsigned int stream_tag, | 2025 | unsigned int stream_tag, |
1929 | unsigned int format, | 2026 | unsigned int format, |
1930 | struct snd_pcm_substream *substream) | 2027 | struct snd_pcm_substream *substream) |
@@ -1936,24 +2033,27 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_o | |||
1936 | mutex_lock(&codec->spdif_mutex); | 2033 | mutex_lock(&codec->spdif_mutex); |
1937 | if (mout->dig_out_nid && mout->dig_out_used != HDA_DIG_EXCLUSIVE) { | 2034 | if (mout->dig_out_nid && mout->dig_out_used != HDA_DIG_EXCLUSIVE) { |
1938 | if (chs == 2 && | 2035 | if (chs == 2 && |
1939 | snd_hda_is_supported_format(codec, mout->dig_out_nid, format) && | 2036 | snd_hda_is_supported_format(codec, mout->dig_out_nid, |
1940 | ! (codec->spdif_status & IEC958_AES0_NONAUDIO)) { | 2037 | format) && |
2038 | !(codec->spdif_status & IEC958_AES0_NONAUDIO)) { | ||
1941 | mout->dig_out_used = HDA_DIG_ANALOG_DUP; | 2039 | mout->dig_out_used = HDA_DIG_ANALOG_DUP; |
1942 | /* setup digital receiver */ | 2040 | setup_dig_out_stream(codec, mout->dig_out_nid, |
1943 | snd_hda_codec_setup_stream(codec, mout->dig_out_nid, | 2041 | stream_tag, format); |
1944 | stream_tag, 0, format); | ||
1945 | } else { | 2042 | } else { |
1946 | mout->dig_out_used = 0; | 2043 | mout->dig_out_used = 0; |
1947 | snd_hda_codec_setup_stream(codec, mout->dig_out_nid, 0, 0, 0); | 2044 | snd_hda_codec_setup_stream(codec, mout->dig_out_nid, |
2045 | 0, 0, 0); | ||
1948 | } | 2046 | } |
1949 | } | 2047 | } |
1950 | mutex_unlock(&codec->spdif_mutex); | 2048 | mutex_unlock(&codec->spdif_mutex); |
1951 | 2049 | ||
1952 | /* front */ | 2050 | /* front */ |
1953 | snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag, 0, format); | 2051 | snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag, |
2052 | 0, format); | ||
1954 | if (mout->hp_nid && mout->hp_nid != nids[HDA_FRONT]) | 2053 | if (mout->hp_nid && mout->hp_nid != nids[HDA_FRONT]) |
1955 | /* headphone out will just decode front left/right (stereo) */ | 2054 | /* headphone out will just decode front left/right (stereo) */ |
1956 | snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 0, format); | 2055 | snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, |
2056 | 0, format); | ||
1957 | /* extra outputs copied from front */ | 2057 | /* extra outputs copied from front */ |
1958 | for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++) | 2058 | for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++) |
1959 | if (mout->extra_out_nid[i]) | 2059 | if (mout->extra_out_nid[i]) |
@@ -1964,11 +2064,11 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_o | |||
1964 | /* surrounds */ | 2064 | /* surrounds */ |
1965 | for (i = 1; i < mout->num_dacs; i++) { | 2065 | for (i = 1; i < mout->num_dacs; i++) { |
1966 | if (chs >= (i + 1) * 2) /* independent out */ | 2066 | if (chs >= (i + 1) * 2) /* independent out */ |
1967 | snd_hda_codec_setup_stream(codec, nids[i], stream_tag, i * 2, | 2067 | snd_hda_codec_setup_stream(codec, nids[i], stream_tag, |
1968 | format); | 2068 | i * 2, format); |
1969 | else /* copy front */ | 2069 | else /* copy front */ |
1970 | snd_hda_codec_setup_stream(codec, nids[i], stream_tag, 0, | 2070 | snd_hda_codec_setup_stream(codec, nids[i], stream_tag, |
1971 | format); | 2071 | 0, format); |
1972 | } | 2072 | } |
1973 | return 0; | 2073 | return 0; |
1974 | } | 2074 | } |
@@ -1976,7 +2076,8 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_o | |||
1976 | /* | 2076 | /* |
1977 | * clean up the setting for analog out | 2077 | * clean up the setting for analog out |
1978 | */ | 2078 | */ |
1979 | int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, struct hda_multi_out *mout) | 2079 | int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, |
2080 | struct hda_multi_out *mout) | ||
1980 | { | 2081 | { |
1981 | hda_nid_t *nids = mout->dac_nids; | 2082 | hda_nid_t *nids = mout->dac_nids; |
1982 | int i; | 2083 | int i; |
@@ -2003,7 +2104,7 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, struct hda_multi_o | |||
2003 | * Helper for automatic ping configuration | 2104 | * Helper for automatic ping configuration |
2004 | */ | 2105 | */ |
2005 | 2106 | ||
2006 | static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list) | 2107 | static int __devinit is_in_nid_list(hda_nid_t nid, hda_nid_t *list) |
2007 | { | 2108 | { |
2008 | for (; *list; list++) | 2109 | for (; *list; list++) |
2009 | if (*list == nid) | 2110 | if (*list == nid) |
@@ -2011,6 +2112,32 @@ static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list) | |||
2011 | return 0; | 2112 | return 0; |
2012 | } | 2113 | } |
2013 | 2114 | ||
2115 | |||
2116 | /* | ||
2117 | * Sort an associated group of pins according to their sequence numbers. | ||
2118 | */ | ||
2119 | static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences, | ||
2120 | int num_pins) | ||
2121 | { | ||
2122 | int i, j; | ||
2123 | short seq; | ||
2124 | hda_nid_t nid; | ||
2125 | |||
2126 | for (i = 0; i < num_pins; i++) { | ||
2127 | for (j = i + 1; j < num_pins; j++) { | ||
2128 | if (sequences[i] > sequences[j]) { | ||
2129 | seq = sequences[i]; | ||
2130 | sequences[i] = sequences[j]; | ||
2131 | sequences[j] = seq; | ||
2132 | nid = pins[i]; | ||
2133 | pins[i] = pins[j]; | ||
2134 | pins[j] = nid; | ||
2135 | } | ||
2136 | } | ||
2137 | } | ||
2138 | } | ||
2139 | |||
2140 | |||
2014 | /* | 2141 | /* |
2015 | * Parse all pin widgets and store the useful pin nids to cfg | 2142 | * Parse all pin widgets and store the useful pin nids to cfg |
2016 | * | 2143 | * |
@@ -2028,22 +2155,27 @@ static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list) | |||
2028 | * The digital input/output pins are assigned to dig_in_pin and dig_out_pin, | 2155 | * The digital input/output pins are assigned to dig_in_pin and dig_out_pin, |
2029 | * respectively. | 2156 | * respectively. |
2030 | */ | 2157 | */ |
2031 | int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *cfg, | 2158 | int __devinit snd_hda_parse_pin_def_config(struct hda_codec *codec, |
2032 | hda_nid_t *ignore_nids) | 2159 | struct auto_pin_cfg *cfg, |
2160 | hda_nid_t *ignore_nids) | ||
2033 | { | 2161 | { |
2034 | hda_nid_t nid, nid_start; | 2162 | hda_nid_t nid, nid_start; |
2035 | int i, j, nodes; | 2163 | int nodes; |
2036 | short seq, assoc_line_out, sequences[ARRAY_SIZE(cfg->line_out_pins)]; | 2164 | short seq, assoc_line_out, assoc_speaker; |
2165 | short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)]; | ||
2166 | short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)]; | ||
2037 | 2167 | ||
2038 | memset(cfg, 0, sizeof(*cfg)); | 2168 | memset(cfg, 0, sizeof(*cfg)); |
2039 | 2169 | ||
2040 | memset(sequences, 0, sizeof(sequences)); | 2170 | memset(sequences_line_out, 0, sizeof(sequences_line_out)); |
2041 | assoc_line_out = 0; | 2171 | memset(sequences_speaker, 0, sizeof(sequences_speaker)); |
2172 | assoc_line_out = assoc_speaker = 0; | ||
2042 | 2173 | ||
2043 | nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid_start); | 2174 | nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid_start); |
2044 | for (nid = nid_start; nid < nodes + nid_start; nid++) { | 2175 | for (nid = nid_start; nid < nodes + nid_start; nid++) { |
2045 | unsigned int wid_caps = get_wcaps(codec, nid); | 2176 | unsigned int wid_caps = get_wcaps(codec, nid); |
2046 | unsigned int wid_type = (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; | 2177 | unsigned int wid_type = |
2178 | (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; | ||
2047 | unsigned int def_conf; | 2179 | unsigned int def_conf; |
2048 | short assoc, loc; | 2180 | short assoc, loc; |
2049 | 2181 | ||
@@ -2054,7 +2186,8 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c | |||
2054 | if (ignore_nids && is_in_nid_list(nid, ignore_nids)) | 2186 | if (ignore_nids && is_in_nid_list(nid, ignore_nids)) |
2055 | continue; | 2187 | continue; |
2056 | 2188 | ||
2057 | def_conf = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); | 2189 | def_conf = snd_hda_codec_read(codec, nid, 0, |
2190 | AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
2058 | if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE) | 2191 | if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE) |
2059 | continue; | 2192 | continue; |
2060 | loc = get_defcfg_location(def_conf); | 2193 | loc = get_defcfg_location(def_conf); |
@@ -2062,22 +2195,31 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c | |||
2062 | case AC_JACK_LINE_OUT: | 2195 | case AC_JACK_LINE_OUT: |
2063 | seq = get_defcfg_sequence(def_conf); | 2196 | seq = get_defcfg_sequence(def_conf); |
2064 | assoc = get_defcfg_association(def_conf); | 2197 | assoc = get_defcfg_association(def_conf); |
2065 | if (! assoc) | 2198 | if (!assoc) |
2066 | continue; | 2199 | continue; |
2067 | if (! assoc_line_out) | 2200 | if (!assoc_line_out) |
2068 | assoc_line_out = assoc; | 2201 | assoc_line_out = assoc; |
2069 | else if (assoc_line_out != assoc) | 2202 | else if (assoc_line_out != assoc) |
2070 | continue; | 2203 | continue; |
2071 | if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins)) | 2204 | if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins)) |
2072 | continue; | 2205 | continue; |
2073 | cfg->line_out_pins[cfg->line_outs] = nid; | 2206 | cfg->line_out_pins[cfg->line_outs] = nid; |
2074 | sequences[cfg->line_outs] = seq; | 2207 | sequences_line_out[cfg->line_outs] = seq; |
2075 | cfg->line_outs++; | 2208 | cfg->line_outs++; |
2076 | break; | 2209 | break; |
2077 | case AC_JACK_SPEAKER: | 2210 | case AC_JACK_SPEAKER: |
2211 | seq = get_defcfg_sequence(def_conf); | ||
2212 | assoc = get_defcfg_association(def_conf); | ||
2213 | if (! assoc) | ||
2214 | continue; | ||
2215 | if (! assoc_speaker) | ||
2216 | assoc_speaker = assoc; | ||
2217 | else if (assoc_speaker != assoc) | ||
2218 | continue; | ||
2078 | if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins)) | 2219 | if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins)) |
2079 | continue; | 2220 | continue; |
2080 | cfg->speaker_pins[cfg->speaker_outs] = nid; | 2221 | cfg->speaker_pins[cfg->speaker_outs] = nid; |
2222 | sequences_speaker[cfg->speaker_outs] = seq; | ||
2081 | cfg->speaker_outs++; | 2223 | cfg->speaker_outs++; |
2082 | break; | 2224 | break; |
2083 | case AC_JACK_HP_OUT: | 2225 | case AC_JACK_HP_OUT: |
@@ -2123,34 +2265,45 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c | |||
2123 | } | 2265 | } |
2124 | 2266 | ||
2125 | /* sort by sequence */ | 2267 | /* sort by sequence */ |
2126 | for (i = 0; i < cfg->line_outs; i++) | 2268 | sort_pins_by_sequence(cfg->line_out_pins, sequences_line_out, |
2127 | for (j = i + 1; j < cfg->line_outs; j++) | 2269 | cfg->line_outs); |
2128 | if (sequences[i] > sequences[j]) { | 2270 | sort_pins_by_sequence(cfg->speaker_pins, sequences_speaker, |
2129 | seq = sequences[i]; | 2271 | cfg->speaker_outs); |
2130 | sequences[i] = sequences[j]; | 2272 | |
2131 | sequences[j] = seq; | 2273 | /* |
2132 | nid = cfg->line_out_pins[i]; | 2274 | * FIX-UP: if no line-outs are detected, try to use speaker or HP pin |
2133 | cfg->line_out_pins[i] = cfg->line_out_pins[j]; | 2275 | * as a primary output |
2134 | cfg->line_out_pins[j] = nid; | 2276 | */ |
2135 | } | 2277 | if (!cfg->line_outs) { |
2278 | if (cfg->speaker_outs) { | ||
2279 | cfg->line_outs = cfg->speaker_outs; | ||
2280 | memcpy(cfg->line_out_pins, cfg->speaker_pins, | ||
2281 | sizeof(cfg->speaker_pins)); | ||
2282 | cfg->speaker_outs = 0; | ||
2283 | memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins)); | ||
2284 | cfg->line_out_type = AUTO_PIN_SPEAKER_OUT; | ||
2285 | } else if (cfg->hp_outs) { | ||
2286 | cfg->line_outs = cfg->hp_outs; | ||
2287 | memcpy(cfg->line_out_pins, cfg->hp_pins, | ||
2288 | sizeof(cfg->hp_pins)); | ||
2289 | cfg->hp_outs = 0; | ||
2290 | memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins)); | ||
2291 | cfg->line_out_type = AUTO_PIN_HP_OUT; | ||
2292 | } | ||
2293 | } | ||
2136 | 2294 | ||
2137 | /* Reorder the surround channels | 2295 | /* Reorder the surround channels |
2138 | * ALSA sequence is front/surr/clfe/side | 2296 | * ALSA sequence is front/surr/clfe/side |
2139 | * HDA sequence is: | 2297 | * HDA sequence is: |
2140 | * 4-ch: front/surr => OK as it is | 2298 | * 4-ch: front/surr => OK as it is |
2141 | * 6-ch: front/clfe/surr | 2299 | * 6-ch: front/clfe/surr |
2142 | * 8-ch: front/clfe/side/surr | 2300 | * 8-ch: front/clfe/rear/side|fc |
2143 | */ | 2301 | */ |
2144 | switch (cfg->line_outs) { | 2302 | switch (cfg->line_outs) { |
2145 | case 3: | 2303 | case 3: |
2146 | nid = cfg->line_out_pins[1]; | ||
2147 | cfg->line_out_pins[1] = cfg->line_out_pins[2]; | ||
2148 | cfg->line_out_pins[2] = nid; | ||
2149 | break; | ||
2150 | case 4: | 2304 | case 4: |
2151 | nid = cfg->line_out_pins[1]; | 2305 | nid = cfg->line_out_pins[1]; |
2152 | cfg->line_out_pins[1] = cfg->line_out_pins[3]; | 2306 | cfg->line_out_pins[1] = cfg->line_out_pins[2]; |
2153 | cfg->line_out_pins[3] = cfg->line_out_pins[2]; | ||
2154 | cfg->line_out_pins[2] = nid; | 2307 | cfg->line_out_pins[2] = nid; |
2155 | break; | 2308 | break; |
2156 | } | 2309 | } |
@@ -2179,26 +2332,6 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c | |||
2179 | cfg->input_pins[AUTO_PIN_CD], | 2332 | cfg->input_pins[AUTO_PIN_CD], |
2180 | cfg->input_pins[AUTO_PIN_AUX]); | 2333 | cfg->input_pins[AUTO_PIN_AUX]); |
2181 | 2334 | ||
2182 | /* | ||
2183 | * FIX-UP: if no line-outs are detected, try to use speaker or HP pin | ||
2184 | * as a primary output | ||
2185 | */ | ||
2186 | if (! cfg->line_outs) { | ||
2187 | if (cfg->speaker_outs) { | ||
2188 | cfg->line_outs = cfg->speaker_outs; | ||
2189 | memcpy(cfg->line_out_pins, cfg->speaker_pins, | ||
2190 | sizeof(cfg->speaker_pins)); | ||
2191 | cfg->speaker_outs = 0; | ||
2192 | memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins)); | ||
2193 | } else if (cfg->hp_outs) { | ||
2194 | cfg->line_outs = cfg->hp_outs; | ||
2195 | memcpy(cfg->line_out_pins, cfg->hp_pins, | ||
2196 | sizeof(cfg->hp_pins)); | ||
2197 | cfg->hp_outs = 0; | ||
2198 | memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins)); | ||
2199 | } | ||
2200 | } | ||
2201 | |||
2202 | return 0; | 2335 | return 0; |
2203 | } | 2336 | } |
2204 | 2337 | ||
@@ -2222,11 +2355,10 @@ const char *auto_pin_cfg_labels[AUTO_PIN_LAST] = { | |||
2222 | */ | 2355 | */ |
2223 | int snd_hda_suspend(struct hda_bus *bus, pm_message_t state) | 2356 | int snd_hda_suspend(struct hda_bus *bus, pm_message_t state) |
2224 | { | 2357 | { |
2225 | struct list_head *p; | 2358 | struct hda_codec *codec; |
2226 | 2359 | ||
2227 | /* FIXME: should handle power widget capabilities */ | 2360 | /* FIXME: should handle power widget capabilities */ |
2228 | list_for_each(p, &bus->codec_list) { | 2361 | list_for_each_entry(codec, &bus->codec_list, list) { |
2229 | struct hda_codec *codec = list_entry(p, struct hda_codec, list); | ||
2230 | if (codec->patch_ops.suspend) | 2362 | if (codec->patch_ops.suspend) |
2231 | codec->patch_ops.suspend(codec, state); | 2363 | codec->patch_ops.suspend(codec, state); |
2232 | hda_set_power_state(codec, | 2364 | hda_set_power_state(codec, |
@@ -2236,8 +2368,6 @@ int snd_hda_suspend(struct hda_bus *bus, pm_message_t state) | |||
2236 | return 0; | 2368 | return 0; |
2237 | } | 2369 | } |
2238 | 2370 | ||
2239 | EXPORT_SYMBOL(snd_hda_suspend); | ||
2240 | |||
2241 | /** | 2371 | /** |
2242 | * snd_hda_resume - resume the codecs | 2372 | * snd_hda_resume - resume the codecs |
2243 | * @bus: the HDA bus | 2373 | * @bus: the HDA bus |
@@ -2247,10 +2377,9 @@ EXPORT_SYMBOL(snd_hda_suspend); | |||
2247 | */ | 2377 | */ |
2248 | int snd_hda_resume(struct hda_bus *bus) | 2378 | int snd_hda_resume(struct hda_bus *bus) |
2249 | { | 2379 | { |
2250 | struct list_head *p; | 2380 | struct hda_codec *codec; |
2251 | 2381 | ||
2252 | list_for_each(p, &bus->codec_list) { | 2382 | list_for_each_entry(codec, &bus->codec_list, list) { |
2253 | struct hda_codec *codec = list_entry(p, struct hda_codec, list); | ||
2254 | hda_set_power_state(codec, | 2383 | hda_set_power_state(codec, |
2255 | codec->afg ? codec->afg : codec->mfg, | 2384 | codec->afg ? codec->afg : codec->mfg, |
2256 | AC_PWRST_D0); | 2385 | AC_PWRST_D0); |
@@ -2260,8 +2389,6 @@ int snd_hda_resume(struct hda_bus *bus) | |||
2260 | return 0; | 2389 | return 0; |
2261 | } | 2390 | } |
2262 | 2391 | ||
2263 | EXPORT_SYMBOL(snd_hda_resume); | ||
2264 | |||
2265 | /** | 2392 | /** |
2266 | * snd_hda_resume_ctls - resume controls in the new control list | 2393 | * snd_hda_resume_ctls - resume controls in the new control list |
2267 | * @codec: the HDA codec | 2394 | * @codec: the HDA codec |
@@ -2276,7 +2403,7 @@ int snd_hda_resume_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew) | |||
2276 | struct snd_ctl_elem_value *val; | 2403 | struct snd_ctl_elem_value *val; |
2277 | 2404 | ||
2278 | val = kmalloc(sizeof(*val), GFP_KERNEL); | 2405 | val = kmalloc(sizeof(*val), GFP_KERNEL); |
2279 | if (! val) | 2406 | if (!val) |
2280 | return -ENOMEM; | 2407 | return -ENOMEM; |
2281 | codec->in_resume = 1; | 2408 | codec->in_resume = 1; |
2282 | for (; knew->name; knew++) { | 2409 | for (; knew->name; knew++) { |
@@ -2320,19 +2447,3 @@ int snd_hda_resume_spdif_in(struct hda_codec *codec) | |||
2320 | return snd_hda_resume_ctls(codec, dig_in_ctls); | 2447 | return snd_hda_resume_ctls(codec, dig_in_ctls); |
2321 | } | 2448 | } |
2322 | #endif | 2449 | #endif |
2323 | |||
2324 | /* | ||
2325 | * INIT part | ||
2326 | */ | ||
2327 | |||
2328 | static int __init alsa_hda_init(void) | ||
2329 | { | ||
2330 | return 0; | ||
2331 | } | ||
2332 | |||
2333 | static void __exit alsa_hda_exit(void) | ||
2334 | { | ||
2335 | } | ||
2336 | |||
2337 | module_init(alsa_hda_init) | ||
2338 | module_exit(alsa_hda_exit) | ||
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index c12bc4e8840f..56c26e7ccdf1 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -233,7 +233,7 @@ enum { | |||
233 | */ | 233 | */ |
234 | 234 | ||
235 | /* Amp gain/mute */ | 235 | /* Amp gain/mute */ |
236 | #define AC_AMP_MUTE (1<<8) | 236 | #define AC_AMP_MUTE (1<<7) |
237 | #define AC_AMP_GAIN (0x7f) | 237 | #define AC_AMP_GAIN (0x7f) |
238 | #define AC_AMP_GET_INDEX (0xf<<0) | 238 | #define AC_AMP_GET_INDEX (0xf<<0) |
239 | 239 | ||
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 1e5ff0cd3709..000287f7da43 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c | |||
@@ -133,7 +133,7 @@ static int add_new_node(struct hda_codec *codec, struct hda_gspec *spec, hda_nid | |||
133 | return -ENOMEM; | 133 | return -ENOMEM; |
134 | } | 134 | } |
135 | } | 135 | } |
136 | memcpy(node->conn_list, conn_list, nconns); | 136 | memcpy(node->conn_list, conn_list, nconns * sizeof(hda_nid_t)); |
137 | node->nconns = nconns; | 137 | node->nconns = nconns; |
138 | node->wid_caps = get_wcaps(codec, nid); | 138 | node->wid_caps = get_wcaps(codec, nid); |
139 | node->type = (node->wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; | 139 | node->type = (node->wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 1672cace1ae7..2fa281cbef91 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -88,6 +88,8 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6}," | |||
88 | "{ATI, SB600}," | 88 | "{ATI, SB600}," |
89 | "{ATI, RS600}," | 89 | "{ATI, RS600}," |
90 | "{ATI, RS690}," | 90 | "{ATI, RS690}," |
91 | "{ATI, RS780}," | ||
92 | "{ATI, R600}," | ||
91 | "{VIA, VT8251}," | 93 | "{VIA, VT8251}," |
92 | "{VIA, VT8237A}," | 94 | "{VIA, VT8237A}," |
93 | "{SiS, SIS966}," | 95 | "{SiS, SIS966}," |
@@ -198,6 +200,7 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; | |||
198 | #define RIRB_INT_MASK 0x05 | 200 | #define RIRB_INT_MASK 0x05 |
199 | 201 | ||
200 | /* STATESTS int mask: SD2,SD1,SD0 */ | 202 | /* STATESTS int mask: SD2,SD1,SD0 */ |
203 | #define AZX_MAX_CODECS 3 | ||
201 | #define STATESTS_INT_MASK 0x07 | 204 | #define STATESTS_INT_MASK 0x07 |
202 | 205 | ||
203 | /* SD_CTL bits */ | 206 | /* SD_CTL bits */ |
@@ -978,7 +981,7 @@ static unsigned int azx_max_codecs[] __devinitdata = { | |||
978 | static int __devinit azx_codec_create(struct azx *chip, const char *model) | 981 | static int __devinit azx_codec_create(struct azx *chip, const char *model) |
979 | { | 982 | { |
980 | struct hda_bus_template bus_temp; | 983 | struct hda_bus_template bus_temp; |
981 | int c, codecs, err; | 984 | int c, codecs, audio_codecs, err; |
982 | 985 | ||
983 | memset(&bus_temp, 0, sizeof(bus_temp)); | 986 | memset(&bus_temp, 0, sizeof(bus_temp)); |
984 | bus_temp.private_data = chip; | 987 | bus_temp.private_data = chip; |
@@ -990,16 +993,30 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model) | |||
990 | if ((err = snd_hda_bus_new(chip->card, &bus_temp, &chip->bus)) < 0) | 993 | if ((err = snd_hda_bus_new(chip->card, &bus_temp, &chip->bus)) < 0) |
991 | return err; | 994 | return err; |
992 | 995 | ||
993 | codecs = 0; | 996 | codecs = audio_codecs = 0; |
994 | for (c = 0; c < azx_max_codecs[chip->driver_type]; c++) { | 997 | for (c = 0; c < AZX_MAX_CODECS; c++) { |
995 | if ((chip->codec_mask & (1 << c)) & probe_mask) { | 998 | if ((chip->codec_mask & (1 << c)) & probe_mask) { |
996 | err = snd_hda_codec_new(chip->bus, c, NULL); | 999 | struct hda_codec *codec; |
1000 | err = snd_hda_codec_new(chip->bus, c, &codec); | ||
997 | if (err < 0) | 1001 | if (err < 0) |
998 | continue; | 1002 | continue; |
999 | codecs++; | 1003 | codecs++; |
1004 | if (codec->afg) | ||
1005 | audio_codecs++; | ||
1000 | } | 1006 | } |
1001 | } | 1007 | } |
1002 | if (! codecs) { | 1008 | if (!audio_codecs) { |
1009 | /* probe additional slots if no codec is found */ | ||
1010 | for (; c < azx_max_codecs[chip->driver_type]; c++) { | ||
1011 | if ((chip->codec_mask & (1 << c)) & probe_mask) { | ||
1012 | err = snd_hda_codec_new(chip->bus, c, NULL); | ||
1013 | if (err < 0) | ||
1014 | continue; | ||
1015 | codecs++; | ||
1016 | } | ||
1017 | } | ||
1018 | } | ||
1019 | if (!codecs) { | ||
1003 | snd_printk(KERN_ERR SFX "no codecs initialized\n"); | 1020 | snd_printk(KERN_ERR SFX "no codecs initialized\n"); |
1004 | return -ENXIO; | 1021 | return -ENXIO; |
1005 | } | 1022 | } |
@@ -1518,7 +1535,7 @@ static int azx_dev_free(struct snd_device *device) | |||
1518 | /* | 1535 | /* |
1519 | * white/black-listing for position_fix | 1536 | * white/black-listing for position_fix |
1520 | */ | 1537 | */ |
1521 | static const struct snd_pci_quirk position_fix_list[] __devinitdata = { | 1538 | static struct snd_pci_quirk position_fix_list[] __devinitdata = { |
1522 | SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_NONE), | 1539 | SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_NONE), |
1523 | {} | 1540 | {} |
1524 | }; | 1541 | }; |
@@ -1758,6 +1775,8 @@ static struct pci_device_id azx_ids[] = { | |||
1758 | { 0x1002, 0x4383, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB600 */ | 1775 | { 0x1002, 0x4383, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB600 */ |
1759 | { 0x1002, 0x793b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RS600 HDMI */ | 1776 | { 0x1002, 0x793b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RS600 HDMI */ |
1760 | { 0x1002, 0x7919, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RS690 HDMI */ | 1777 | { 0x1002, 0x7919, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RS690 HDMI */ |
1778 | { 0x1002, 0x960c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RS780 HDMI */ | ||
1779 | { 0x1002, 0xaa00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI R600 HDMI */ | ||
1761 | { 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_VIA }, /* VIA VT8251/VT8237A */ | 1780 | { 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_VIA }, /* VIA VT8251/VT8237A */ |
1762 | { 0x1039, 0x7502, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_SIS }, /* SIS966 */ | 1781 | { 0x1039, 0x7502, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_SIS }, /* SIS966 */ |
1763 | { 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ULI }, /* ULI M5461 */ | 1782 | { 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ULI }, /* ULI M5461 */ |
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 39718d6cdadd..be12b8814c39 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -148,6 +148,11 @@ struct hda_multi_out { | |||
148 | 148 | ||
149 | int snd_hda_multi_out_dig_open(struct hda_codec *codec, struct hda_multi_out *mout); | 149 | int snd_hda_multi_out_dig_open(struct hda_codec *codec, struct hda_multi_out *mout); |
150 | int snd_hda_multi_out_dig_close(struct hda_codec *codec, struct hda_multi_out *mout); | 150 | int snd_hda_multi_out_dig_close(struct hda_codec *codec, struct hda_multi_out *mout); |
151 | int snd_hda_multi_out_dig_prepare(struct hda_codec *codec, | ||
152 | struct hda_multi_out *mout, | ||
153 | unsigned int stream_tag, | ||
154 | unsigned int format, | ||
155 | struct snd_pcm_substream *substream); | ||
151 | int snd_hda_multi_out_analog_open(struct hda_codec *codec, struct hda_multi_out *mout, | 156 | int snd_hda_multi_out_analog_open(struct hda_codec *codec, struct hda_multi_out *mout, |
152 | struct snd_pcm_substream *substream); | 157 | struct snd_pcm_substream *substream); |
153 | int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_out *mout, | 158 | int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_out *mout, |
@@ -217,6 +222,12 @@ enum { | |||
217 | AUTO_PIN_LAST | 222 | AUTO_PIN_LAST |
218 | }; | 223 | }; |
219 | 224 | ||
225 | enum { | ||
226 | AUTO_PIN_LINE_OUT, | ||
227 | AUTO_PIN_SPEAKER_OUT, | ||
228 | AUTO_PIN_HP_OUT | ||
229 | }; | ||
230 | |||
220 | extern const char *auto_pin_cfg_labels[AUTO_PIN_LAST]; | 231 | extern const char *auto_pin_cfg_labels[AUTO_PIN_LAST]; |
221 | 232 | ||
222 | struct auto_pin_cfg { | 233 | struct auto_pin_cfg { |
@@ -225,6 +236,7 @@ struct auto_pin_cfg { | |||
225 | int speaker_outs; | 236 | int speaker_outs; |
226 | hda_nid_t speaker_pins[5]; | 237 | hda_nid_t speaker_pins[5]; |
227 | int hp_outs; | 238 | int hp_outs; |
239 | int line_out_type; /* AUTO_PIN_XXX_OUT */ | ||
228 | hda_nid_t hp_pins[5]; | 240 | hda_nid_t hp_pins[5]; |
229 | hda_nid_t input_pins[AUTO_PIN_LAST]; | 241 | hda_nid_t input_pins[AUTO_PIN_LAST]; |
230 | hda_nid_t dig_out_pin; | 242 | hda_nid_t dig_out_pin; |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index f94f1f22889e..0e1a879663fa 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -192,6 +192,17 @@ static int ad198x_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, | |||
192 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | 192 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); |
193 | } | 193 | } |
194 | 194 | ||
195 | static int ad198x_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
196 | struct hda_codec *codec, | ||
197 | unsigned int stream_tag, | ||
198 | unsigned int format, | ||
199 | struct snd_pcm_substream *substream) | ||
200 | { | ||
201 | struct ad198x_spec *spec = codec->spec; | ||
202 | return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag, | ||
203 | format, substream); | ||
204 | } | ||
205 | |||
195 | /* | 206 | /* |
196 | * Analog capture | 207 | * Analog capture |
197 | */ | 208 | */ |
@@ -250,7 +261,8 @@ static struct hda_pcm_stream ad198x_pcm_digital_playback = { | |||
250 | .nid = 0, /* fill later */ | 261 | .nid = 0, /* fill later */ |
251 | .ops = { | 262 | .ops = { |
252 | .open = ad198x_dig_playback_pcm_open, | 263 | .open = ad198x_dig_playback_pcm_open, |
253 | .close = ad198x_dig_playback_pcm_close | 264 | .close = ad198x_dig_playback_pcm_close, |
265 | .prepare = ad198x_dig_playback_pcm_prepare | ||
254 | }, | 266 | }, |
255 | }; | 267 | }; |
256 | 268 | ||
@@ -739,41 +751,35 @@ static struct hda_verb ad1986a_init_verbs[] = { | |||
739 | { } /* end */ | 751 | { } /* end */ |
740 | }; | 752 | }; |
741 | 753 | ||
742 | /* additional verbs for 3-stack model */ | ||
743 | static struct hda_verb ad1986a_3st_init_verbs[] = { | ||
744 | /* Mic and line-in selectors */ | ||
745 | {0x0f, AC_VERB_SET_CONNECT_SEL, 0x2}, | ||
746 | {0x10, AC_VERB_SET_CONNECT_SEL, 0x1}, | ||
747 | { } /* end */ | ||
748 | }; | ||
749 | |||
750 | static struct hda_verb ad1986a_ch2_init[] = { | 754 | static struct hda_verb ad1986a_ch2_init[] = { |
751 | /* Surround out -> Line In */ | 755 | /* Surround out -> Line In */ |
752 | { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, | 756 | { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, |
753 | { 0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | 757 | /* Line-in selectors */ |
758 | { 0x10, AC_VERB_SET_CONNECT_SEL, 0x1 }, | ||
754 | /* CLFE -> Mic in */ | 759 | /* CLFE -> Mic in */ |
755 | { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, | 760 | { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, |
756 | { 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | 761 | /* Mic selector, mix C/LFE (backmic) and Mic (frontmic) */ |
762 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 }, | ||
757 | { } /* end */ | 763 | { } /* end */ |
758 | }; | 764 | }; |
759 | 765 | ||
760 | static struct hda_verb ad1986a_ch4_init[] = { | 766 | static struct hda_verb ad1986a_ch4_init[] = { |
761 | /* Surround out -> Surround */ | 767 | /* Surround out -> Surround */ |
762 | { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | 768 | { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, |
763 | { 0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 769 | { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 }, |
764 | /* CLFE -> Mic in */ | 770 | /* CLFE -> Mic in */ |
765 | { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, | 771 | { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, |
766 | { 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | 772 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 }, |
767 | { } /* end */ | 773 | { } /* end */ |
768 | }; | 774 | }; |
769 | 775 | ||
770 | static struct hda_verb ad1986a_ch6_init[] = { | 776 | static struct hda_verb ad1986a_ch6_init[] = { |
771 | /* Surround out -> Surround out */ | 777 | /* Surround out -> Surround out */ |
772 | { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | 778 | { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, |
773 | { 0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 779 | { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 }, |
774 | /* CLFE -> CLFE */ | 780 | /* CLFE -> CLFE */ |
775 | { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | 781 | { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, |
776 | { 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 782 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x0 }, |
777 | { } /* end */ | 783 | { } /* end */ |
778 | }; | 784 | }; |
779 | 785 | ||
@@ -828,6 +834,7 @@ static struct snd_pci_quirk ad1986a_cfg_tbl[] = { | |||
828 | SND_PCI_QUIRK(0x1043, 0x1297, "ASUS Z62F", AD1986A_LAPTOP_EAPD), | 834 | SND_PCI_QUIRK(0x1043, 0x1297, "ASUS Z62F", AD1986A_LAPTOP_EAPD), |
829 | SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS V1j", AD1986A_LAPTOP_EAPD), | 835 | SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS V1j", AD1986A_LAPTOP_EAPD), |
830 | SND_PCI_QUIRK(0x1043, 0x1302, "ASUS W3j", AD1986A_LAPTOP_EAPD), | 836 | SND_PCI_QUIRK(0x1043, 0x1302, "ASUS W3j", AD1986A_LAPTOP_EAPD), |
837 | SND_PCI_QUIRK(0x1043, 0x1447, "ASUS A8J", AD1986A_3STACK), | ||
831 | SND_PCI_QUIRK(0x1043, 0x817f, "ASUS P5", AD1986A_3STACK), | 838 | SND_PCI_QUIRK(0x1043, 0x817f, "ASUS P5", AD1986A_3STACK), |
832 | SND_PCI_QUIRK(0x1043, 0x818f, "ASUS P5", AD1986A_LAPTOP), | 839 | SND_PCI_QUIRK(0x1043, 0x818f, "ASUS P5", AD1986A_LAPTOP), |
833 | SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS P5", AD1986A_3STACK), | 840 | SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS P5", AD1986A_3STACK), |
@@ -882,9 +889,8 @@ static int patch_ad1986a(struct hda_codec *codec) | |||
882 | case AD1986A_3STACK: | 889 | case AD1986A_3STACK: |
883 | spec->num_mixers = 2; | 890 | spec->num_mixers = 2; |
884 | spec->mixers[1] = ad1986a_3st_mixers; | 891 | spec->mixers[1] = ad1986a_3st_mixers; |
885 | spec->num_init_verbs = 3; | 892 | spec->num_init_verbs = 2; |
886 | spec->init_verbs[1] = ad1986a_3st_init_verbs; | 893 | spec->init_verbs[1] = ad1986a_ch2_init; |
887 | spec->init_verbs[2] = ad1986a_ch2_init; | ||
888 | spec->channel_mode = ad1986a_modes; | 894 | spec->channel_mode = ad1986a_modes; |
889 | spec->num_channel_mode = ARRAY_SIZE(ad1986a_modes); | 895 | spec->num_channel_mode = ARRAY_SIZE(ad1986a_modes); |
890 | spec->need_dac_fix = 1; | 896 | spec->need_dac_fix = 1; |
@@ -1892,8 +1898,9 @@ static int ad1988_spdif_playback_source_get(struct snd_kcontrol *kcontrol, | |||
1892 | 1898 | ||
1893 | sel = snd_hda_codec_read(codec, 0x02, 0, AC_VERB_GET_CONNECT_SEL, 0); | 1899 | sel = snd_hda_codec_read(codec, 0x02, 0, AC_VERB_GET_CONNECT_SEL, 0); |
1894 | if (sel > 0) { | 1900 | if (sel > 0) { |
1895 | sel = snd_hda_codec_read(codec, 0x0b, 0, AC_VERB_GET_CONNECT_SEL, 0); | 1901 | sel = snd_hda_codec_read(codec, 0x0b, 0, |
1896 | if (sel <= 3) | 1902 | AC_VERB_GET_CONNECT_SEL, 0); |
1903 | if (sel < 3) | ||
1897 | sel++; | 1904 | sel++; |
1898 | else | 1905 | else |
1899 | sel = 0; | 1906 | sel = 0; |
@@ -1906,23 +1913,27 @@ static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol, | |||
1906 | struct snd_ctl_elem_value *ucontrol) | 1913 | struct snd_ctl_elem_value *ucontrol) |
1907 | { | 1914 | { |
1908 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 1915 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
1909 | unsigned int sel; | 1916 | unsigned int val, sel; |
1910 | int change; | 1917 | int change; |
1911 | 1918 | ||
1919 | val = ucontrol->value.enumerated.item[0]; | ||
1912 | sel = snd_hda_codec_read(codec, 0x02, 0, AC_VERB_GET_CONNECT_SEL, 0); | 1920 | sel = snd_hda_codec_read(codec, 0x02, 0, AC_VERB_GET_CONNECT_SEL, 0); |
1913 | if (! ucontrol->value.enumerated.item[0]) { | 1921 | if (!val) { |
1914 | change = sel != 0; | 1922 | change = sel != 0; |
1915 | if (change) | 1923 | if (change || codec->in_resume) |
1916 | snd_hda_codec_write(codec, 0x02, 0, AC_VERB_SET_CONNECT_SEL, 0); | 1924 | snd_hda_codec_write(codec, 0x02, 0, |
1925 | AC_VERB_SET_CONNECT_SEL, 0); | ||
1917 | } else { | 1926 | } else { |
1918 | change = sel == 0; | 1927 | change = sel == 0; |
1919 | if (change) | 1928 | if (change || codec->in_resume) |
1920 | snd_hda_codec_write(codec, 0x02, 0, AC_VERB_SET_CONNECT_SEL, 1); | 1929 | snd_hda_codec_write(codec, 0x02, 0, |
1921 | sel = snd_hda_codec_read(codec, 0x0b, 0, AC_VERB_GET_CONNECT_SEL, 0) + 1; | 1930 | AC_VERB_SET_CONNECT_SEL, 1); |
1922 | change |= sel == ucontrol->value.enumerated.item[0]; | 1931 | sel = snd_hda_codec_read(codec, 0x0b, 0, |
1923 | if (change) | 1932 | AC_VERB_GET_CONNECT_SEL, 0) + 1; |
1924 | snd_hda_codec_write(codec, 0x02, 0, AC_VERB_SET_CONNECT_SEL, | 1933 | change |= sel != val; |
1925 | ucontrol->value.enumerated.item[0] - 1); | 1934 | if (change || codec->in_resume) |
1935 | snd_hda_codec_write(codec, 0x0b, 0, | ||
1936 | AC_VERB_SET_CONNECT_SEL, val - 1); | ||
1926 | } | 1937 | } |
1927 | return change; | 1938 | return change; |
1928 | } | 1939 | } |
diff --git a/sound/pci/hda/patch_atihdmi.c b/sound/pci/hda/patch_atihdmi.c index 831469d3a923..f8eb4c90f801 100644 --- a/sound/pci/hda/patch_atihdmi.c +++ b/sound/pci/hda/patch_atihdmi.c | |||
@@ -94,6 +94,17 @@ static int atihdmi_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, | |||
94 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | 94 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); |
95 | } | 95 | } |
96 | 96 | ||
97 | static int atihdmi_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
98 | struct hda_codec *codec, | ||
99 | unsigned int stream_tag, | ||
100 | unsigned int format, | ||
101 | struct snd_pcm_substream *substream) | ||
102 | { | ||
103 | struct atihdmi_spec *spec = codec->spec; | ||
104 | return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag, | ||
105 | format, substream); | ||
106 | } | ||
107 | |||
97 | static struct hda_pcm_stream atihdmi_pcm_digital_playback = { | 108 | static struct hda_pcm_stream atihdmi_pcm_digital_playback = { |
98 | .substreams = 1, | 109 | .substreams = 1, |
99 | .channels_min = 2, | 110 | .channels_min = 2, |
@@ -101,7 +112,8 @@ static struct hda_pcm_stream atihdmi_pcm_digital_playback = { | |||
101 | .nid = 0x2, /* NID to query formats and rates and setup streams */ | 112 | .nid = 0x2, /* NID to query formats and rates and setup streams */ |
102 | .ops = { | 113 | .ops = { |
103 | .open = atihdmi_dig_playback_pcm_open, | 114 | .open = atihdmi_dig_playback_pcm_open, |
104 | .close = atihdmi_dig_playback_pcm_close | 115 | .close = atihdmi_dig_playback_pcm_close, |
116 | .prepare = atihdmi_dig_playback_pcm_prepare | ||
105 | }, | 117 | }, |
106 | }; | 118 | }; |
107 | 119 | ||
@@ -160,6 +172,7 @@ static int patch_atihdmi(struct hda_codec *codec) | |||
160 | */ | 172 | */ |
161 | struct hda_codec_preset snd_hda_preset_atihdmi[] = { | 173 | struct hda_codec_preset snd_hda_preset_atihdmi[] = { |
162 | { .id = 0x1002793c, .name = "ATI RS600 HDMI", .patch = patch_atihdmi }, | 174 | { .id = 0x1002793c, .name = "ATI RS600 HDMI", .patch = patch_atihdmi }, |
163 | { .id = 0x1002791a, .name = "ATI RS690 HDMI", .patch = patch_atihdmi }, | 175 | { .id = 0x1002791a, .name = "ATI RS690/780 HDMI", .patch = patch_atihdmi }, |
176 | { .id = 0x1002aa01, .name = "ATI R600 HDMI", .patch = patch_atihdmi }, | ||
164 | {} /* terminator */ | 177 | {} /* terminator */ |
165 | }; | 178 | }; |
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c index 5b9d3a31a1ae..3c722e667bc8 100644 --- a/sound/pci/hda/patch_cmedia.c +++ b/sound/pci/hda/patch_cmedia.c | |||
@@ -497,6 +497,17 @@ static int cmi9880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, | |||
497 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | 497 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); |
498 | } | 498 | } |
499 | 499 | ||
500 | static int cmi9880_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
501 | struct hda_codec *codec, | ||
502 | unsigned int stream_tag, | ||
503 | unsigned int format, | ||
504 | struct snd_pcm_substream *substream) | ||
505 | { | ||
506 | struct cmi_spec *spec = codec->spec; | ||
507 | return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag, | ||
508 | format, substream); | ||
509 | } | ||
510 | |||
500 | /* | 511 | /* |
501 | * Analog capture | 512 | * Analog capture |
502 | */ | 513 | */ |
@@ -556,7 +567,8 @@ static struct hda_pcm_stream cmi9880_pcm_digital_playback = { | |||
556 | /* NID is set in cmi9880_build_pcms */ | 567 | /* NID is set in cmi9880_build_pcms */ |
557 | .ops = { | 568 | .ops = { |
558 | .open = cmi9880_dig_playback_pcm_open, | 569 | .open = cmi9880_dig_playback_pcm_open, |
559 | .close = cmi9880_dig_playback_pcm_close | 570 | .close = cmi9880_dig_playback_pcm_close, |
571 | .prepare = cmi9880_dig_playback_pcm_prepare | ||
560 | }, | 572 | }, |
561 | }; | 573 | }; |
562 | 574 | ||
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 46e93c6b9a42..a5a4b2bddf20 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -136,6 +136,18 @@ static int conexant_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, | |||
136 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | 136 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); |
137 | } | 137 | } |
138 | 138 | ||
139 | static int conexant_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
140 | struct hda_codec *codec, | ||
141 | unsigned int stream_tag, | ||
142 | unsigned int format, | ||
143 | struct snd_pcm_substream *substream) | ||
144 | { | ||
145 | struct conexant_spec *spec = codec->spec; | ||
146 | return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, | ||
147 | stream_tag, | ||
148 | format, substream); | ||
149 | } | ||
150 | |||
139 | /* | 151 | /* |
140 | * Analog capture | 152 | * Analog capture |
141 | */ | 153 | */ |
@@ -194,7 +206,8 @@ static struct hda_pcm_stream conexant_pcm_digital_playback = { | |||
194 | .nid = 0, /* fill later */ | 206 | .nid = 0, /* fill later */ |
195 | .ops = { | 207 | .ops = { |
196 | .open = conexant_dig_playback_pcm_open, | 208 | .open = conexant_dig_playback_pcm_open, |
197 | .close = conexant_dig_playback_pcm_close | 209 | .close = conexant_dig_playback_pcm_close, |
210 | .prepare = conexant_dig_playback_pcm_prepare | ||
198 | }, | 211 | }, |
199 | }; | 212 | }; |
200 | 213 | ||
@@ -452,115 +465,6 @@ static int conexant_ch_mode_put(struct snd_kcontrol *kcontrol, | |||
452 | .put = conexant_ch_mode_put, \ | 465 | .put = conexant_ch_mode_put, \ |
453 | .private_value = nid | (dir<<16) } | 466 | .private_value = nid | (dir<<16) } |
454 | 467 | ||
455 | static int cxt_gpio_data_info(struct snd_kcontrol *kcontrol, | ||
456 | struct snd_ctl_elem_info *uinfo) | ||
457 | { | ||
458 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
459 | uinfo->count = 1; | ||
460 | uinfo->value.integer.min = 0; | ||
461 | uinfo->value.integer.max = 1; | ||
462 | return 0; | ||
463 | } | ||
464 | |||
465 | static int cxt_gpio_data_get(struct snd_kcontrol *kcontrol, | ||
466 | struct snd_ctl_elem_value *ucontrol) | ||
467 | { | ||
468 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
469 | hda_nid_t nid = kcontrol->private_value & 0xffff; | ||
470 | unsigned char mask = (kcontrol->private_value >> 16) & 0xff; | ||
471 | long *valp = ucontrol->value.integer.value; | ||
472 | unsigned int val = snd_hda_codec_read(codec, nid, 0, | ||
473 | AC_VERB_GET_GPIO_DATA, 0x00); | ||
474 | |||
475 | *valp = (val & mask) != 0; | ||
476 | return 0; | ||
477 | } | ||
478 | |||
479 | static int cxt_gpio_data_put(struct snd_kcontrol *kcontrol, | ||
480 | struct snd_ctl_elem_value *ucontrol) | ||
481 | { | ||
482 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
483 | hda_nid_t nid = kcontrol->private_value & 0xffff; | ||
484 | unsigned char mask = (kcontrol->private_value >> 16) & 0xff; | ||
485 | long val = *ucontrol->value.integer.value; | ||
486 | unsigned int gpio_data = snd_hda_codec_read(codec, nid, 0, | ||
487 | AC_VERB_GET_GPIO_DATA, | ||
488 | 0x00); | ||
489 | unsigned int old_data = gpio_data; | ||
490 | |||
491 | /* Set/unset the masked GPIO bit(s) as needed */ | ||
492 | if (val == 0) | ||
493 | gpio_data &= ~mask; | ||
494 | else | ||
495 | gpio_data |= mask; | ||
496 | if (gpio_data == old_data && !codec->in_resume) | ||
497 | return 0; | ||
498 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_GPIO_DATA, gpio_data); | ||
499 | return 1; | ||
500 | } | ||
501 | |||
502 | #define CXT_GPIO_DATA_SWITCH(xname, nid, mask) \ | ||
503 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ | ||
504 | .info = cxt_gpio_data_info, \ | ||
505 | .get = cxt_gpio_data_get, \ | ||
506 | .put = cxt_gpio_data_put, \ | ||
507 | .private_value = nid | (mask<<16) } | ||
508 | #if 0 | ||
509 | static int cxt_spdif_ctrl_info(struct snd_kcontrol *kcontrol, | ||
510 | struct snd_ctl_elem_info *uinfo) | ||
511 | { | ||
512 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
513 | uinfo->count = 1; | ||
514 | uinfo->value.integer.min = 0; | ||
515 | uinfo->value.integer.max = 1; | ||
516 | return 0; | ||
517 | } | ||
518 | |||
519 | static int cxt_spdif_ctrl_get(struct snd_kcontrol *kcontrol, | ||
520 | struct snd_ctl_elem_value *ucontrol) | ||
521 | { | ||
522 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
523 | hda_nid_t nid = kcontrol->private_value & 0xffff; | ||
524 | unsigned char mask = (kcontrol->private_value >> 16) & 0xff; | ||
525 | long *valp = ucontrol->value.integer.value; | ||
526 | unsigned int val = snd_hda_codec_read(codec, nid, 0, | ||
527 | AC_VERB_GET_DIGI_CONVERT, 0x00); | ||
528 | |||
529 | *valp = (val & mask) != 0; | ||
530 | return 0; | ||
531 | } | ||
532 | |||
533 | static int cxt_spdif_ctrl_put(struct snd_kcontrol *kcontrol, | ||
534 | struct snd_ctl_elem_value *ucontrol) | ||
535 | { | ||
536 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
537 | hda_nid_t nid = kcontrol->private_value & 0xffff; | ||
538 | unsigned char mask = (kcontrol->private_value >> 16) & 0xff; | ||
539 | long val = *ucontrol->value.integer.value; | ||
540 | unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0, | ||
541 | AC_VERB_GET_DIGI_CONVERT, | ||
542 | 0x00); | ||
543 | unsigned int old_data = ctrl_data; | ||
544 | |||
545 | /* Set/unset the masked control bit(s) as needed */ | ||
546 | if (val == 0) | ||
547 | ctrl_data &= ~mask; | ||
548 | else | ||
549 | ctrl_data |= mask; | ||
550 | if (ctrl_data == old_data && !codec->in_resume) | ||
551 | return 0; | ||
552 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, | ||
553 | ctrl_data); | ||
554 | return 1; | ||
555 | } | ||
556 | |||
557 | #define CXT_SPDIF_CTRL_SWITCH(xname, nid, mask) \ | ||
558 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ | ||
559 | .info = cxt_spdif_ctrl_info, \ | ||
560 | .get = cxt_spdif_ctrl_get, \ | ||
561 | .put = cxt_spdif_ctrl_put, \ | ||
562 | .private_value = nid | (mask<<16) } | ||
563 | #endif | ||
564 | #endif /* CONFIG_SND_DEBUG */ | 468 | #endif /* CONFIG_SND_DEBUG */ |
565 | 469 | ||
566 | /* Conexant 5045 specific */ | 470 | /* Conexant 5045 specific */ |
@@ -599,6 +503,7 @@ static int cxt5045_hp_master_sw_put(struct snd_kcontrol *kcontrol, | |||
599 | bits = (!spec->hp_present && spec->cur_eapd) ? 0 : 0x80; | 503 | bits = (!spec->hp_present && spec->cur_eapd) ? 0 : 0x80; |
600 | snd_hda_codec_amp_update(codec, 0x10, 0, HDA_OUTPUT, 0, 0x80, bits); | 504 | snd_hda_codec_amp_update(codec, 0x10, 0, HDA_OUTPUT, 0, 0x80, bits); |
601 | snd_hda_codec_amp_update(codec, 0x10, 1, HDA_OUTPUT, 0, 0x80, bits); | 505 | snd_hda_codec_amp_update(codec, 0x10, 1, HDA_OUTPUT, 0, 0x80, bits); |
506 | |||
602 | bits = spec->cur_eapd ? 0 : 0x80; | 507 | bits = spec->cur_eapd ? 0 : 0x80; |
603 | snd_hda_codec_amp_update(codec, 0x11, 0, HDA_OUTPUT, 0, 0x80, bits); | 508 | snd_hda_codec_amp_update(codec, 0x11, 0, HDA_OUTPUT, 0, 0x80, bits); |
604 | snd_hda_codec_amp_update(codec, 0x11, 1, HDA_OUTPUT, 0, 0x80, bits); | 509 | snd_hda_codec_amp_update(codec, 0x11, 1, HDA_OUTPUT, 0, 0x80, bits); |
@@ -624,6 +529,29 @@ static int cxt5045_hp_master_vol_put(struct snd_kcontrol *kcontrol, | |||
624 | return change; | 529 | return change; |
625 | } | 530 | } |
626 | 531 | ||
532 | /* toggle input of built-in and mic jack appropriately */ | ||
533 | static void cxt5045_hp_automic(struct hda_codec *codec) | ||
534 | { | ||
535 | static struct hda_verb mic_jack_on[] = { | ||
536 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
537 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
538 | {} | ||
539 | }; | ||
540 | static struct hda_verb mic_jack_off[] = { | ||
541 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
542 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
543 | {} | ||
544 | }; | ||
545 | unsigned int present; | ||
546 | |||
547 | present = snd_hda_codec_read(codec, 0x12, 0, | ||
548 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
549 | if (present) | ||
550 | snd_hda_sequence_write(codec, mic_jack_on); | ||
551 | else | ||
552 | snd_hda_sequence_write(codec, mic_jack_off); | ||
553 | } | ||
554 | |||
627 | 555 | ||
628 | /* mute internal speaker if HP is plugged */ | 556 | /* mute internal speaker if HP is plugged */ |
629 | static void cxt5045_hp_automute(struct hda_codec *codec) | 557 | static void cxt5045_hp_automute(struct hda_codec *codec) |
@@ -634,7 +562,7 @@ static void cxt5045_hp_automute(struct hda_codec *codec) | |||
634 | spec->hp_present = snd_hda_codec_read(codec, 0x11, 0, | 562 | spec->hp_present = snd_hda_codec_read(codec, 0x11, 0, |
635 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 563 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
636 | 564 | ||
637 | bits = (spec->hp_present || !spec->cur_eapd) ? 0x80 : 0; | 565 | bits = (spec->hp_present || !spec->cur_eapd) ? 0x80 : 0; |
638 | snd_hda_codec_amp_update(codec, 0x10, 0, HDA_OUTPUT, 0, 0x80, bits); | 566 | snd_hda_codec_amp_update(codec, 0x10, 0, HDA_OUTPUT, 0, 0x80, bits); |
639 | snd_hda_codec_amp_update(codec, 0x10, 1, HDA_OUTPUT, 0, 0x80, bits); | 567 | snd_hda_codec_amp_update(codec, 0x10, 1, HDA_OUTPUT, 0, 0x80, bits); |
640 | } | 568 | } |
@@ -648,6 +576,10 @@ static void cxt5045_hp_unsol_event(struct hda_codec *codec, | |||
648 | case CONEXANT_HP_EVENT: | 576 | case CONEXANT_HP_EVENT: |
649 | cxt5045_hp_automute(codec); | 577 | cxt5045_hp_automute(codec); |
650 | break; | 578 | break; |
579 | case CONEXANT_MIC_EVENT: | ||
580 | cxt5045_hp_automic(codec); | ||
581 | break; | ||
582 | |||
651 | } | 583 | } |
652 | } | 584 | } |
653 | 585 | ||
@@ -659,12 +591,10 @@ static struct snd_kcontrol_new cxt5045_mixers[] = { | |||
659 | .get = conexant_mux_enum_get, | 591 | .get = conexant_mux_enum_get, |
660 | .put = conexant_mux_enum_put | 592 | .put = conexant_mux_enum_put |
661 | }, | 593 | }, |
662 | HDA_CODEC_VOLUME("Int Mic Volume", 0x17, 0x01, HDA_INPUT), | 594 | HDA_CODEC_VOLUME("Int Mic Volume", 0x1a, 0x01, HDA_INPUT), |
663 | HDA_CODEC_MUTE("Int Mic Switch", 0x17, 0x01, HDA_INPUT), | 595 | HDA_CODEC_MUTE("Int Mic Switch", 0x1a, 0x01, HDA_INPUT), |
664 | HDA_CODEC_VOLUME("Ext Mic Volume", 0x17, 0x02, HDA_INPUT), | 596 | HDA_CODEC_VOLUME("Ext Mic Volume", 0x1a, 0x02, HDA_INPUT), |
665 | HDA_CODEC_MUTE("Ext Mic Switch", 0x17, 0x02, HDA_INPUT), | 597 | HDA_CODEC_MUTE("Ext Mic Switch", 0x1a, 0x02, HDA_INPUT), |
666 | HDA_CODEC_VOLUME("Capture Volume", 0x1a, 0x0, HDA_INPUT), | ||
667 | HDA_CODEC_MUTE("Capture Switch", 0x1a, 0x0, HDA_INPUT), | ||
668 | { | 598 | { |
669 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 599 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
670 | .name = "Master Playback Volume", | 600 | .name = "Master Playback Volume", |
@@ -688,7 +618,7 @@ static struct snd_kcontrol_new cxt5045_mixers[] = { | |||
688 | static struct hda_verb cxt5045_init_verbs[] = { | 618 | static struct hda_verb cxt5045_init_verbs[] = { |
689 | /* Line in, Mic */ | 619 | /* Line in, Mic */ |
690 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | 620 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, |
691 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 }, | 621 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 }, |
692 | /* HP, Amp */ | 622 | /* HP, Amp */ |
693 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | 623 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, |
694 | {0x17, AC_VERB_SET_CONNECT_SEL,0x01}, | 624 | {0x17, AC_VERB_SET_CONNECT_SEL,0x01}, |
@@ -701,18 +631,29 @@ static struct hda_verb cxt5045_init_verbs[] = { | |||
701 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, | 631 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, |
702 | AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x04}, | 632 | AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x04}, |
703 | /* Record selector: Int mic */ | 633 | /* Record selector: Int mic */ |
704 | {0x1a, AC_VERB_SET_CONNECT_SEL,0x0}, | 634 | {0x1a, AC_VERB_SET_CONNECT_SEL,0x1}, |
705 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, | 635 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, |
706 | AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, | 636 | AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, |
707 | /* SPDIF route: PCM */ | 637 | /* SPDIF route: PCM */ |
708 | { 0x13, AC_VERB_SET_CONNECT_SEL, 0x0 }, | 638 | { 0x13, AC_VERB_SET_CONNECT_SEL, 0x0 }, |
709 | /* pin sensing on HP and Mic jacks */ | ||
710 | {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, | ||
711 | /* EAPD */ | 639 | /* EAPD */ |
712 | {0x10, AC_VERB_SET_EAPD_BTLENABLE, 0x2 }, /* default on */ | 640 | {0x10, AC_VERB_SET_EAPD_BTLENABLE, 0x2 }, /* default on */ |
713 | { } /* end */ | 641 | { } /* end */ |
714 | }; | 642 | }; |
715 | 643 | ||
644 | |||
645 | static struct hda_verb cxt5045_hp_sense_init_verbs[] = { | ||
646 | /* pin sensing on HP jack */ | ||
647 | {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, | ||
648 | { } /* end */ | ||
649 | }; | ||
650 | |||
651 | static struct hda_verb cxt5045_mic_sense_init_verbs[] = { | ||
652 | /* pin sensing on HP jack */ | ||
653 | {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, | ||
654 | { } /* end */ | ||
655 | }; | ||
656 | |||
716 | #ifdef CONFIG_SND_DEBUG | 657 | #ifdef CONFIG_SND_DEBUG |
717 | /* Test configuration for debugging, modelled after the ALC260 test | 658 | /* Test configuration for debugging, modelled after the ALC260 test |
718 | * configuration. | 659 | * configuration. |
@@ -733,6 +674,10 @@ static struct snd_kcontrol_new cxt5045_test_mixer[] = { | |||
733 | /* Output controls */ | 674 | /* Output controls */ |
734 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x10, 0x0, HDA_OUTPUT), | 675 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x10, 0x0, HDA_OUTPUT), |
735 | HDA_CODEC_MUTE("Speaker Playback Switch", 0x10, 0x0, HDA_OUTPUT), | 676 | HDA_CODEC_MUTE("Speaker Playback Switch", 0x10, 0x0, HDA_OUTPUT), |
677 | HDA_CODEC_VOLUME("Node 11 Playback Volume", 0x11, 0x0, HDA_OUTPUT), | ||
678 | HDA_CODEC_MUTE("Node 11 Playback Switch", 0x11, 0x0, HDA_OUTPUT), | ||
679 | HDA_CODEC_VOLUME("Node 12 Playback Volume", 0x12, 0x0, HDA_OUTPUT), | ||
680 | HDA_CODEC_MUTE("Node 12 Playback Switch", 0x12, 0x0, HDA_OUTPUT), | ||
736 | 681 | ||
737 | /* Modes for retasking pin widgets */ | 682 | /* Modes for retasking pin widgets */ |
738 | CXT_PIN_MODE("HP-OUT pin mode", 0x11, CXT_PIN_DIR_INOUT), | 683 | CXT_PIN_MODE("HP-OUT pin mode", 0x11, CXT_PIN_DIR_INOUT), |
@@ -742,25 +687,17 @@ static struct snd_kcontrol_new cxt5045_test_mixer[] = { | |||
742 | CXT_EAPD_SWITCH("External Amplifier", 0x10, 0x0), | 687 | CXT_EAPD_SWITCH("External Amplifier", 0x10, 0x0), |
743 | 688 | ||
744 | /* Loopback mixer controls */ | 689 | /* Loopback mixer controls */ |
745 | HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x17, 0x01, HDA_INPUT), | 690 | |
746 | HDA_CODEC_MUTE("MIC1 Playback Switch", 0x17, 0x01, HDA_INPUT), | 691 | HDA_CODEC_VOLUME("Mixer-1 Volume", 0x17, 0x0, HDA_INPUT), |
747 | HDA_CODEC_VOLUME("LINE loopback Playback Volume", 0x17, 0x02, HDA_INPUT), | 692 | HDA_CODEC_MUTE("Mixer-1 Switch", 0x17, 0x0, HDA_INPUT), |
748 | HDA_CODEC_MUTE("LINE loopback Playback Switch", 0x17, 0x02, HDA_INPUT), | 693 | HDA_CODEC_VOLUME("Mixer-2 Volume", 0x17, 0x1, HDA_INPUT), |
749 | HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x17, 0x03, HDA_INPUT), | 694 | HDA_CODEC_MUTE("Mixer-2 Switch", 0x17, 0x1, HDA_INPUT), |
750 | HDA_CODEC_MUTE("HP-OUT loopback Playback Switch", 0x17, 0x03, HDA_INPUT), | 695 | HDA_CODEC_VOLUME("Mixer-3 Volume", 0x17, 0x2, HDA_INPUT), |
751 | HDA_CODEC_VOLUME("CD Playback Volume", 0x17, 0x04, HDA_INPUT), | 696 | HDA_CODEC_MUTE("Mixer-3 Switch", 0x17, 0x2, HDA_INPUT), |
752 | HDA_CODEC_MUTE("CD Playback Switch", 0x17, 0x04, HDA_INPUT), | 697 | HDA_CODEC_VOLUME("Mixer-4 Volume", 0x17, 0x3, HDA_INPUT), |
753 | 698 | HDA_CODEC_MUTE("Mixer-4 Switch", 0x17, 0x3, HDA_INPUT), | |
754 | HDA_CODEC_VOLUME("Capture-1 Volume", 0x17, 0x0, HDA_INPUT), | 699 | HDA_CODEC_VOLUME("Mixer-5 Volume", 0x17, 0x4, HDA_INPUT), |
755 | HDA_CODEC_MUTE("Capture-1 Switch", 0x17, 0x0, HDA_INPUT), | 700 | HDA_CODEC_MUTE("Mixer-5 Switch", 0x17, 0x4, HDA_INPUT), |
756 | HDA_CODEC_VOLUME("Capture-2 Volume", 0x17, 0x1, HDA_INPUT), | ||
757 | HDA_CODEC_MUTE("Capture-2 Switch", 0x17, 0x1, HDA_INPUT), | ||
758 | HDA_CODEC_VOLUME("Capture-3 Volume", 0x17, 0x2, HDA_INPUT), | ||
759 | HDA_CODEC_MUTE("Capture-3 Switch", 0x17, 0x2, HDA_INPUT), | ||
760 | HDA_CODEC_VOLUME("Capture-4 Volume", 0x17, 0x3, HDA_INPUT), | ||
761 | HDA_CODEC_MUTE("Capture-4 Switch", 0x17, 0x3, HDA_INPUT), | ||
762 | HDA_CODEC_VOLUME("Capture-5 Volume", 0x17, 0x4, HDA_INPUT), | ||
763 | HDA_CODEC_MUTE("Capture-5 Switch", 0x17, 0x4, HDA_INPUT), | ||
764 | { | 701 | { |
765 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 702 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
766 | .name = "Input Source", | 703 | .name = "Input Source", |
@@ -768,14 +705,17 @@ static struct snd_kcontrol_new cxt5045_test_mixer[] = { | |||
768 | .get = conexant_mux_enum_get, | 705 | .get = conexant_mux_enum_get, |
769 | .put = conexant_mux_enum_put, | 706 | .put = conexant_mux_enum_put, |
770 | }, | 707 | }, |
771 | |||
772 | { } /* end */ | 708 | { } /* end */ |
773 | }; | 709 | }; |
774 | 710 | ||
775 | static struct hda_verb cxt5045_test_init_verbs[] = { | 711 | static struct hda_verb cxt5045_test_init_verbs[] = { |
712 | /* Set connections */ | ||
713 | { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 }, | ||
714 | { 0x11, AC_VERB_SET_CONNECT_SEL, 0x0 }, | ||
715 | { 0x12, AC_VERB_SET_CONNECT_SEL, 0x0 }, | ||
776 | /* Enable retasking pins as output, initially without power amp */ | 716 | /* Enable retasking pins as output, initially without power amp */ |
777 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | 717 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
778 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | 718 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
779 | 719 | ||
780 | /* Disable digital (SPDIF) pins initially, but users can enable | 720 | /* Disable digital (SPDIF) pins initially, but users can enable |
781 | * them via a mixer switch. In the case of SPDIF-out, this initverb | 721 | * them via a mixer switch. In the case of SPDIF-out, this initverb |
@@ -804,6 +744,7 @@ static struct hda_verb cxt5045_test_init_verbs[] = { | |||
804 | * pin) | 744 | * pin) |
805 | */ | 745 | */ |
806 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, | 746 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, |
747 | {0x17, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
807 | 748 | ||
808 | /* Mute all inputs to mixer widget (even unconnected ones) */ | 749 | /* Mute all inputs to mixer widget (even unconnected ones) */ |
809 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* Mixer pin */ | 750 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* Mixer pin */ |
@@ -827,7 +768,8 @@ static int cxt5045_init(struct hda_codec *codec) | |||
827 | 768 | ||
828 | 769 | ||
829 | enum { | 770 | enum { |
830 | CXT5045_LAPTOP, /* Laptops w/ EAPD support */ | 771 | CXT5045_LAPTOP, /* Laptops w/ EAPD support */ |
772 | CXT5045_FUJITSU, /* Laptops w/ EAPD support */ | ||
831 | #ifdef CONFIG_SND_DEBUG | 773 | #ifdef CONFIG_SND_DEBUG |
832 | CXT5045_TEST, | 774 | CXT5045_TEST, |
833 | #endif | 775 | #endif |
@@ -836,6 +778,7 @@ enum { | |||
836 | 778 | ||
837 | static const char *cxt5045_models[CXT5045_MODELS] = { | 779 | static const char *cxt5045_models[CXT5045_MODELS] = { |
838 | [CXT5045_LAPTOP] = "laptop", | 780 | [CXT5045_LAPTOP] = "laptop", |
781 | [CXT5045_FUJITSU] = "fujitsu", | ||
839 | #ifdef CONFIG_SND_DEBUG | 782 | #ifdef CONFIG_SND_DEBUG |
840 | [CXT5045_TEST] = "test", | 783 | [CXT5045_TEST] = "test", |
841 | #endif | 784 | #endif |
@@ -844,7 +787,11 @@ static const char *cxt5045_models[CXT5045_MODELS] = { | |||
844 | static struct snd_pci_quirk cxt5045_cfg_tbl[] = { | 787 | static struct snd_pci_quirk cxt5045_cfg_tbl[] = { |
845 | SND_PCI_QUIRK(0x103c, 0x30b7, "HP DV6000Z", CXT5045_LAPTOP), | 788 | SND_PCI_QUIRK(0x103c, 0x30b7, "HP DV6000Z", CXT5045_LAPTOP), |
846 | SND_PCI_QUIRK(0x103c, 0x30bb, "HP DV8000", CXT5045_LAPTOP), | 789 | SND_PCI_QUIRK(0x103c, 0x30bb, "HP DV8000", CXT5045_LAPTOP), |
847 | SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_LAPTOP), | 790 | SND_PCI_QUIRK(0x103c, 0x30b2, "HP DV Series", CXT5045_LAPTOP), |
791 | SND_PCI_QUIRK(0x103c, 0x30b5, "HP DV2120", CXT5045_LAPTOP), | ||
792 | SND_PCI_QUIRK(0x103c, 0x30cd, "HP DV Series", CXT5045_LAPTOP), | ||
793 | SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_FUJITSU), | ||
794 | SND_PCI_QUIRK(0x8086, 0x2111, "Conexant Reference board", CXT5045_LAPTOP), | ||
848 | {} | 795 | {} |
849 | }; | 796 | }; |
850 | 797 | ||
@@ -877,16 +824,23 @@ static int patch_cxt5045(struct hda_codec *codec) | |||
877 | 824 | ||
878 | 825 | ||
879 | codec->patch_ops = conexant_patch_ops; | 826 | codec->patch_ops = conexant_patch_ops; |
880 | codec->patch_ops.unsol_event = cxt5045_hp_unsol_event; | ||
881 | 827 | ||
882 | board_config = snd_hda_check_board_config(codec, CXT5045_MODELS, | 828 | board_config = snd_hda_check_board_config(codec, CXT5045_MODELS, |
883 | cxt5045_models, | 829 | cxt5045_models, |
884 | cxt5045_cfg_tbl); | 830 | cxt5045_cfg_tbl); |
885 | switch (board_config) { | 831 | switch (board_config) { |
886 | case CXT5045_LAPTOP: | 832 | case CXT5045_LAPTOP: |
833 | codec->patch_ops.unsol_event = cxt5045_hp_unsol_event; | ||
834 | spec->input_mux = &cxt5045_capture_source; | ||
835 | spec->num_init_verbs = 2; | ||
836 | spec->init_verbs[1] = cxt5045_hp_sense_init_verbs; | ||
837 | spec->mixers[0] = cxt5045_mixers; | ||
838 | codec->patch_ops.init = cxt5045_init; | ||
839 | break; | ||
840 | case CXT5045_FUJITSU: | ||
887 | spec->input_mux = &cxt5045_capture_source; | 841 | spec->input_mux = &cxt5045_capture_source; |
888 | spec->num_init_verbs = 2; | 842 | spec->num_init_verbs = 2; |
889 | spec->init_verbs[1] = cxt5045_init_verbs; | 843 | spec->init_verbs[1] = cxt5045_mic_sense_init_verbs; |
890 | spec->mixers[0] = cxt5045_mixers; | 844 | spec->mixers[0] = cxt5045_mixers; |
891 | codec->patch_ops.init = cxt5045_init; | 845 | codec->patch_ops.init = cxt5045_init; |
892 | break; | 846 | break; |
@@ -913,10 +867,9 @@ static struct hda_channel_mode cxt5047_modes[1] = { | |||
913 | }; | 867 | }; |
914 | 868 | ||
915 | static struct hda_input_mux cxt5047_capture_source = { | 869 | static struct hda_input_mux cxt5047_capture_source = { |
916 | .num_items = 2, | 870 | .num_items = 1, |
917 | .items = { | 871 | .items = { |
918 | { "ExtMic", 0x0 }, | 872 | { "Mic", 0x2 }, |
919 | { "IntMic", 0x1 }, | ||
920 | } | 873 | } |
921 | }; | 874 | }; |
922 | 875 | ||
@@ -1009,7 +962,7 @@ static void cxt5047_hp_automic(struct hda_codec *codec) | |||
1009 | }; | 962 | }; |
1010 | unsigned int present; | 963 | unsigned int present; |
1011 | 964 | ||
1012 | present = snd_hda_codec_read(codec, 0x08, 0, | 965 | present = snd_hda_codec_read(codec, 0x15, 0, |
1013 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 966 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
1014 | if (present) | 967 | if (present) |
1015 | snd_hda_sequence_write(codec, mic_jack_on); | 968 | snd_hda_sequence_write(codec, mic_jack_on); |
@@ -1033,37 +986,20 @@ static void cxt5047_hp_unsol_event(struct hda_codec *codec, | |||
1033 | } | 986 | } |
1034 | 987 | ||
1035 | static struct snd_kcontrol_new cxt5047_mixers[] = { | 988 | static struct snd_kcontrol_new cxt5047_mixers[] = { |
1036 | { | ||
1037 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1038 | .name = "Capture Source", | ||
1039 | .info = conexant_mux_enum_info, | ||
1040 | .get = conexant_mux_enum_get, | ||
1041 | .put = conexant_mux_enum_put | ||
1042 | }, | ||
1043 | HDA_CODEC_VOLUME("Mic Bypass Capture Volume", 0x19, 0x02, HDA_INPUT), | 989 | HDA_CODEC_VOLUME("Mic Bypass Capture Volume", 0x19, 0x02, HDA_INPUT), |
1044 | HDA_CODEC_MUTE("Mic Bypass Capture Switch", 0x19, 0x02, HDA_INPUT), | 990 | HDA_CODEC_MUTE("Mic Bypass Capture Switch", 0x19, 0x02, HDA_INPUT), |
991 | HDA_CODEC_VOLUME("Mic Gain Volume", 0x1a, 0x0, HDA_OUTPUT), | ||
992 | HDA_CODEC_MUTE("Mic Gain Switch", 0x1a, 0x0, HDA_OUTPUT), | ||
1045 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT), | 993 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT), |
1046 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT), | 994 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT), |
1047 | HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT), | 995 | HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT), |
1048 | HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT), | 996 | HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT), |
1049 | HDA_CODEC_VOLUME("PCM-2 Volume", 0x1c, 0x00, HDA_OUTPUT), | 997 | HDA_CODEC_VOLUME("PCM-2 Volume", 0x1c, 0x00, HDA_OUTPUT), |
1050 | HDA_CODEC_MUTE("PCM-2 Switch", 0x1c, 0x00, HDA_OUTPUT), | 998 | HDA_CODEC_MUTE("PCM-2 Switch", 0x1c, 0x00, HDA_OUTPUT), |
1051 | { | 999 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x00, HDA_OUTPUT), |
1052 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1000 | HDA_CODEC_MUTE("Speaker Playback Switch", 0x1d, 0x00, HDA_OUTPUT), |
1053 | .name = "Master Playback Volume", | 1001 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x13, 0x00, HDA_OUTPUT), |
1054 | .info = snd_hda_mixer_amp_volume_info, | 1002 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x13, 0x00, HDA_OUTPUT), |
1055 | .get = snd_hda_mixer_amp_volume_get, | ||
1056 | .put = cxt5047_hp_master_vol_put, | ||
1057 | .private_value = HDA_COMPOSE_AMP_VAL(0x13, 3, 0, HDA_OUTPUT), | ||
1058 | }, | ||
1059 | { | ||
1060 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1061 | .name = "Master Playback Switch", | ||
1062 | .info = cxt_eapd_info, | ||
1063 | .get = cxt_eapd_get, | ||
1064 | .put = cxt5047_hp_master_sw_put, | ||
1065 | .private_value = 0x13, | ||
1066 | }, | ||
1067 | 1003 | ||
1068 | {} | 1004 | {} |
1069 | }; | 1005 | }; |
@@ -1133,18 +1069,19 @@ static struct hda_verb cxt5047_init_verbs[] = { | |||
1133 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | 1069 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, |
1134 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 }, | 1070 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 }, |
1135 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 }, | 1071 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 }, |
1136 | /* HP, Amp, Speaker */ | 1072 | /* HP, Speaker */ |
1137 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | 1073 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, |
1138 | {0x1A, AC_VERB_SET_CONNECT_SEL,0x00}, | 1074 | {0x13, AC_VERB_SET_CONNECT_SEL,0x1}, |
1139 | {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, | ||
1140 | AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x00}, | ||
1141 | {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, | ||
1142 | AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x03}, | ||
1143 | {0x1d, AC_VERB_SET_CONNECT_SEL,0x0}, | 1075 | {0x1d, AC_VERB_SET_CONNECT_SEL,0x0}, |
1144 | /* Record selector: Front mic */ | 1076 | /* Record selector: Mic */ |
1145 | {0x12, AC_VERB_SET_CONNECT_SEL,0x03}, | 1077 | {0x12, AC_VERB_SET_CONNECT_SEL,0x03}, |
1146 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, | 1078 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, |
1147 | AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, | 1079 | AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, |
1080 | {0x1A, AC_VERB_SET_CONNECT_SEL,0x02}, | ||
1081 | {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, | ||
1082 | AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x00}, | ||
1083 | {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, | ||
1084 | AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x03}, | ||
1148 | /* SPDIF route: PCM */ | 1085 | /* SPDIF route: PCM */ |
1149 | { 0x18, AC_VERB_SET_CONNECT_SEL, 0x0 }, | 1086 | { 0x18, AC_VERB_SET_CONNECT_SEL, 0x0 }, |
1150 | /* Enable unsolicited events */ | 1087 | /* Enable unsolicited events */ |
@@ -1161,8 +1098,6 @@ static struct hda_verb cxt5047_toshiba_init_verbs[] = { | |||
1161 | {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, | 1098 | {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, |
1162 | /* Speaker routing */ | 1099 | /* Speaker routing */ |
1163 | {0x1d, AC_VERB_SET_CONNECT_SEL,0x1}, | 1100 | {0x1d, AC_VERB_SET_CONNECT_SEL,0x1}, |
1164 | /* Change default to ExtMic for recording */ | ||
1165 | {0x1a, AC_VERB_SET_CONNECT_SEL,0x2}, | ||
1166 | {} | 1101 | {} |
1167 | }; | 1102 | }; |
1168 | 1103 | ||
@@ -1172,7 +1107,6 @@ static struct hda_verb cxt5047_hp_init_verbs[] = { | |||
1172 | {0x13, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, | 1107 | {0x13, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, |
1173 | /* Record selector: Ext Mic */ | 1108 | /* Record selector: Ext Mic */ |
1174 | {0x12, AC_VERB_SET_CONNECT_SEL,0x03}, | 1109 | {0x12, AC_VERB_SET_CONNECT_SEL,0x03}, |
1175 | {0x1a, AC_VERB_SET_CONNECT_SEL,0x02}, | ||
1176 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, | 1110 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, |
1177 | AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, | 1111 | AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, |
1178 | /* Speaker routing */ | 1112 | /* Speaker routing */ |
@@ -1242,14 +1176,6 @@ static struct snd_kcontrol_new cxt5047_test_mixer[] = { | |||
1242 | .get = conexant_mux_enum_get, | 1176 | .get = conexant_mux_enum_get, |
1243 | .put = conexant_mux_enum_put, | 1177 | .put = conexant_mux_enum_put, |
1244 | }, | 1178 | }, |
1245 | /* Controls for GPIO pins, assuming they exist and are configured | ||
1246 | * as outputs | ||
1247 | */ | ||
1248 | CXT_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01), | ||
1249 | CXT_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02), | ||
1250 | CXT_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04), | ||
1251 | CXT_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08), | ||
1252 | |||
1253 | { } /* end */ | 1179 | { } /* end */ |
1254 | }; | 1180 | }; |
1255 | 1181 | ||
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index fba3cb11bc2a..a4ede27af021 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -74,6 +74,8 @@ enum { | |||
74 | ALC260_HP_3013, | 74 | ALC260_HP_3013, |
75 | ALC260_FUJITSU_S702X, | 75 | ALC260_FUJITSU_S702X, |
76 | ALC260_ACER, | 76 | ALC260_ACER, |
77 | ALC260_WILL, | ||
78 | ALC260_REPLACER_672V, | ||
77 | #ifdef CONFIG_SND_DEBUG | 79 | #ifdef CONFIG_SND_DEBUG |
78 | ALC260_TEST, | 80 | ALC260_TEST, |
79 | #endif | 81 | #endif |
@@ -115,15 +117,28 @@ enum { | |||
115 | ALC861VD_3ST, | 117 | ALC861VD_3ST, |
116 | ALC861VD_3ST_DIG, | 118 | ALC861VD_3ST_DIG, |
117 | ALC861VD_6ST_DIG, | 119 | ALC861VD_6ST_DIG, |
120 | ALC861VD_LENOVO, | ||
118 | ALC861VD_AUTO, | 121 | ALC861VD_AUTO, |
119 | ALC861VD_MODEL_LAST, | 122 | ALC861VD_MODEL_LAST, |
120 | }; | 123 | }; |
121 | 124 | ||
125 | /* ALC662 models */ | ||
126 | enum { | ||
127 | ALC662_3ST_2ch_DIG, | ||
128 | ALC662_3ST_6ch_DIG, | ||
129 | ALC662_3ST_6ch, | ||
130 | ALC662_5ST_DIG, | ||
131 | ALC662_LENOVO_101E, | ||
132 | ALC662_AUTO, | ||
133 | ALC662_MODEL_LAST, | ||
134 | }; | ||
135 | |||
122 | /* ALC882 models */ | 136 | /* ALC882 models */ |
123 | enum { | 137 | enum { |
124 | ALC882_3ST_DIG, | 138 | ALC882_3ST_DIG, |
125 | ALC882_6ST_DIG, | 139 | ALC882_6ST_DIG, |
126 | ALC882_ARIMA, | 140 | ALC882_ARIMA, |
141 | ALC882_W2JC, | ||
127 | ALC882_AUTO, | 142 | ALC882_AUTO, |
128 | ALC885_MACPRO, | 143 | ALC885_MACPRO, |
129 | ALC882_MODEL_LAST, | 144 | ALC882_MODEL_LAST, |
@@ -141,6 +156,7 @@ enum { | |||
141 | ALC883_ACER, | 156 | ALC883_ACER, |
142 | ALC883_MEDION, | 157 | ALC883_MEDION, |
143 | ALC883_LAPTOP_EAPD, | 158 | ALC883_LAPTOP_EAPD, |
159 | ALC883_LENOVO_101E_2ch, | ||
144 | ALC883_AUTO, | 160 | ALC883_AUTO, |
145 | ALC883_MODEL_LAST, | 161 | ALC883_MODEL_LAST, |
146 | }; | 162 | }; |
@@ -163,7 +179,7 @@ struct alc_spec { | |||
163 | struct hda_pcm_stream *stream_analog_playback; | 179 | struct hda_pcm_stream *stream_analog_playback; |
164 | struct hda_pcm_stream *stream_analog_capture; | 180 | struct hda_pcm_stream *stream_analog_capture; |
165 | 181 | ||
166 | char *stream_name_digital; /* digital PCM stream */ | 182 | char *stream_name_digital; /* digital PCM stream */ |
167 | struct hda_pcm_stream *stream_digital_playback; | 183 | struct hda_pcm_stream *stream_digital_playback; |
168 | struct hda_pcm_stream *stream_digital_capture; | 184 | struct hda_pcm_stream *stream_digital_capture; |
169 | 185 | ||
@@ -401,7 +417,7 @@ static int alc_pin_mode_put(struct snd_kcontrol *kcontrol, | |||
401 | AC_VERB_GET_PIN_WIDGET_CONTROL, | 417 | AC_VERB_GET_PIN_WIDGET_CONTROL, |
402 | 0x00); | 418 | 0x00); |
403 | 419 | ||
404 | if (val < alc_pin_mode_min(dir) || val > alc_pin_mode_max(dir)) | 420 | if (val < alc_pin_mode_min(dir) || val > alc_pin_mode_max(dir)) |
405 | val = alc_pin_mode_min(dir); | 421 | val = alc_pin_mode_min(dir); |
406 | 422 | ||
407 | change = pinctl != alc_pin_mode_values[val]; | 423 | change = pinctl != alc_pin_mode_values[val]; |
@@ -460,7 +476,8 @@ static int alc_gpio_data_info(struct snd_kcontrol *kcontrol, | |||
460 | uinfo->value.integer.min = 0; | 476 | uinfo->value.integer.min = 0; |
461 | uinfo->value.integer.max = 1; | 477 | uinfo->value.integer.max = 1; |
462 | return 0; | 478 | return 0; |
463 | } | 479 | } |
480 | |||
464 | static int alc_gpio_data_get(struct snd_kcontrol *kcontrol, | 481 | static int alc_gpio_data_get(struct snd_kcontrol *kcontrol, |
465 | struct snd_ctl_elem_value *ucontrol) | 482 | struct snd_ctl_elem_value *ucontrol) |
466 | { | 483 | { |
@@ -520,7 +537,8 @@ static int alc_spdif_ctrl_info(struct snd_kcontrol *kcontrol, | |||
520 | uinfo->value.integer.min = 0; | 537 | uinfo->value.integer.min = 0; |
521 | uinfo->value.integer.max = 1; | 538 | uinfo->value.integer.max = 1; |
522 | return 0; | 539 | return 0; |
523 | } | 540 | } |
541 | |||
524 | static int alc_spdif_ctrl_get(struct snd_kcontrol *kcontrol, | 542 | static int alc_spdif_ctrl_get(struct snd_kcontrol *kcontrol, |
525 | struct snd_ctl_elem_value *ucontrol) | 543 | struct snd_ctl_elem_value *ucontrol) |
526 | { | 544 | { |
@@ -592,7 +610,7 @@ static void setup_preset(struct alc_spec *spec, | |||
592 | spec->multiout.hp_nid = preset->hp_nid; | 610 | spec->multiout.hp_nid = preset->hp_nid; |
593 | 611 | ||
594 | spec->num_mux_defs = preset->num_mux_defs; | 612 | spec->num_mux_defs = preset->num_mux_defs; |
595 | if (! spec->num_mux_defs) | 613 | if (!spec->num_mux_defs) |
596 | spec->num_mux_defs = 1; | 614 | spec->num_mux_defs = 1; |
597 | spec->input_mux = preset->input_mux; | 615 | spec->input_mux = preset->input_mux; |
598 | 616 | ||
@@ -604,6 +622,90 @@ static void setup_preset(struct alc_spec *spec, | |||
604 | spec->init_hook = preset->init_hook; | 622 | spec->init_hook = preset->init_hook; |
605 | } | 623 | } |
606 | 624 | ||
625 | /* Enable GPIO mask and set output */ | ||
626 | static struct hda_verb alc_gpio1_init_verbs[] = { | ||
627 | {0x01, AC_VERB_SET_GPIO_MASK, 0x01}, | ||
628 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, | ||
629 | {0x01, AC_VERB_SET_GPIO_DATA, 0x01}, | ||
630 | { } | ||
631 | }; | ||
632 | |||
633 | static struct hda_verb alc_gpio2_init_verbs[] = { | ||
634 | {0x01, AC_VERB_SET_GPIO_MASK, 0x02}, | ||
635 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02}, | ||
636 | {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, | ||
637 | { } | ||
638 | }; | ||
639 | |||
640 | static struct hda_verb alc_gpio3_init_verbs[] = { | ||
641 | {0x01, AC_VERB_SET_GPIO_MASK, 0x03}, | ||
642 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03}, | ||
643 | {0x01, AC_VERB_SET_GPIO_DATA, 0x03}, | ||
644 | { } | ||
645 | }; | ||
646 | |||
647 | /* 32-bit subsystem ID for BIOS loading in HD Audio codec. | ||
648 | * 31 ~ 16 : Manufacture ID | ||
649 | * 15 ~ 8 : SKU ID | ||
650 | * 7 ~ 0 : Assembly ID | ||
651 | * port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36 | ||
652 | */ | ||
653 | static void alc_subsystem_id(struct hda_codec *codec, | ||
654 | unsigned int porta, unsigned int porte, | ||
655 | unsigned int portd) | ||
656 | { | ||
657 | unsigned int ass, tmp; | ||
658 | |||
659 | ass = codec->subsystem_id; | ||
660 | if (!(ass & 1)) | ||
661 | return; | ||
662 | |||
663 | /* Override */ | ||
664 | tmp = (ass & 0x38) >> 3; /* external Amp control */ | ||
665 | switch (tmp) { | ||
666 | case 1: | ||
667 | snd_hda_sequence_write(codec, alc_gpio1_init_verbs); | ||
668 | break; | ||
669 | case 3: | ||
670 | snd_hda_sequence_write(codec, alc_gpio2_init_verbs); | ||
671 | break; | ||
672 | case 7: | ||
673 | snd_hda_sequence_write(codec, alc_gpio3_init_verbs); | ||
674 | break; | ||
675 | case 5: | ||
676 | switch (codec->vendor_id) { | ||
677 | case 0x10ec0862: | ||
678 | case 0x10ec0660: | ||
679 | case 0x10ec0662: | ||
680 | case 0x10ec0267: | ||
681 | case 0x10ec0268: | ||
682 | snd_hda_codec_write(codec, 0x14, 0, | ||
683 | AC_VERB_SET_EAPD_BTLENABLE, 2); | ||
684 | snd_hda_codec_write(codec, 0x15, 0, | ||
685 | AC_VERB_SET_EAPD_BTLENABLE, 2); | ||
686 | return; | ||
687 | } | ||
688 | case 6: | ||
689 | if (ass & 4) { /* bit 2 : 0 = Desktop, 1 = Laptop */ | ||
690 | hda_nid_t port = 0; | ||
691 | tmp = (ass & 0x1800) >> 11; | ||
692 | switch (tmp) { | ||
693 | case 0: port = porta; break; | ||
694 | case 1: port = porte; break; | ||
695 | case 2: port = portd; break; | ||
696 | } | ||
697 | if (port) | ||
698 | snd_hda_codec_write(codec, port, 0, | ||
699 | AC_VERB_SET_EAPD_BTLENABLE, | ||
700 | 2); | ||
701 | } | ||
702 | snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7); | ||
703 | snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, | ||
704 | (tmp == 5 ? 0x3040 : 0x3050)); | ||
705 | break; | ||
706 | } | ||
707 | } | ||
708 | |||
607 | /* | 709 | /* |
608 | * ALC880 3-stack model | 710 | * ALC880 3-stack model |
609 | * | 711 | * |
@@ -801,7 +903,7 @@ static struct hda_channel_mode alc880_fivestack_modes[2] = { | |||
801 | static hda_nid_t alc880_6st_dac_nids[4] = { | 903 | static hda_nid_t alc880_6st_dac_nids[4] = { |
802 | /* front, rear, clfe, rear_surr */ | 904 | /* front, rear, clfe, rear_surr */ |
803 | 0x02, 0x03, 0x04, 0x05 | 905 | 0x02, 0x03, 0x04, 0x05 |
804 | }; | 906 | }; |
805 | 907 | ||
806 | static struct hda_input_mux alc880_6stack_capture_source = { | 908 | static struct hda_input_mux alc880_6stack_capture_source = { |
807 | .num_items = 4, | 909 | .num_items = 4, |
@@ -1409,25 +1511,43 @@ static struct hda_verb alc880_beep_init_verbs[] = { | |||
1409 | }; | 1511 | }; |
1410 | 1512 | ||
1411 | /* toggle speaker-output according to the hp-jack state */ | 1513 | /* toggle speaker-output according to the hp-jack state */ |
1412 | static void alc880_uniwill_automute(struct hda_codec *codec) | 1514 | static void alc880_uniwill_hp_automute(struct hda_codec *codec) |
1413 | { | 1515 | { |
1414 | unsigned int present; | 1516 | unsigned int present; |
1517 | unsigned char bits; | ||
1415 | 1518 | ||
1416 | present = snd_hda_codec_read(codec, 0x14, 0, | 1519 | present = snd_hda_codec_read(codec, 0x14, 0, |
1417 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 1520 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
1521 | bits = present ? 0x80 : 0; | ||
1418 | snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, | 1522 | snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, |
1419 | 0x80, present ? 0x80 : 0); | 1523 | 0x80, bits); |
1420 | snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, | 1524 | snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, |
1421 | 0x80, present ? 0x80 : 0); | 1525 | 0x80, bits); |
1422 | snd_hda_codec_amp_update(codec, 0x16, 0, HDA_OUTPUT, 0, | 1526 | snd_hda_codec_amp_update(codec, 0x16, 0, HDA_OUTPUT, 0, |
1423 | 0x80, present ? 0x80 : 0); | 1527 | 0x80, bits); |
1424 | snd_hda_codec_amp_update(codec, 0x16, 1, HDA_OUTPUT, 0, | 1528 | snd_hda_codec_amp_update(codec, 0x16, 1, HDA_OUTPUT, 0, |
1425 | 0x80, present ? 0x80 : 0); | 1529 | 0x80, bits); |
1530 | } | ||
1531 | |||
1532 | /* auto-toggle front mic */ | ||
1533 | static void alc880_uniwill_mic_automute(struct hda_codec *codec) | ||
1534 | { | ||
1535 | unsigned int present; | ||
1536 | unsigned char bits; | ||
1426 | 1537 | ||
1427 | present = snd_hda_codec_read(codec, 0x18, 0, | 1538 | present = snd_hda_codec_read(codec, 0x18, 0, |
1428 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 1539 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
1429 | snd_hda_codec_write(codec, 0x0b, 0, AC_VERB_SET_AMP_GAIN_MUTE, | 1540 | bits = present ? 0x80 : 0; |
1430 | 0x7000 | (0x01 << 8) | (present ? 0x80 : 0)); | 1541 | snd_hda_codec_amp_update(codec, 0x0b, 0, HDA_INPUT, 1, |
1542 | 0x80, bits); | ||
1543 | snd_hda_codec_amp_update(codec, 0x0b, 1, HDA_INPUT, 1, | ||
1544 | 0x80, bits); | ||
1545 | } | ||
1546 | |||
1547 | static void alc880_uniwill_automute(struct hda_codec *codec) | ||
1548 | { | ||
1549 | alc880_uniwill_hp_automute(codec); | ||
1550 | alc880_uniwill_mic_automute(codec); | ||
1431 | } | 1551 | } |
1432 | 1552 | ||
1433 | static void alc880_uniwill_unsol_event(struct hda_codec *codec, | 1553 | static void alc880_uniwill_unsol_event(struct hda_codec *codec, |
@@ -1436,22 +1556,28 @@ static void alc880_uniwill_unsol_event(struct hda_codec *codec, | |||
1436 | /* Looks like the unsol event is incompatible with the standard | 1556 | /* Looks like the unsol event is incompatible with the standard |
1437 | * definition. 4bit tag is placed at 28 bit! | 1557 | * definition. 4bit tag is placed at 28 bit! |
1438 | */ | 1558 | */ |
1439 | if ((res >> 28) == ALC880_HP_EVENT || | 1559 | switch (res >> 28) { |
1440 | (res >> 28) == ALC880_MIC_EVENT) | 1560 | case ALC880_HP_EVENT: |
1441 | alc880_uniwill_automute(codec); | 1561 | alc880_uniwill_hp_automute(codec); |
1562 | break; | ||
1563 | case ALC880_MIC_EVENT: | ||
1564 | alc880_uniwill_mic_automute(codec); | ||
1565 | break; | ||
1566 | } | ||
1442 | } | 1567 | } |
1443 | 1568 | ||
1444 | static void alc880_uniwill_p53_hp_automute(struct hda_codec *codec) | 1569 | static void alc880_uniwill_p53_hp_automute(struct hda_codec *codec) |
1445 | { | 1570 | { |
1446 | unsigned int present; | 1571 | unsigned int present; |
1572 | unsigned char bits; | ||
1447 | 1573 | ||
1448 | present = snd_hda_codec_read(codec, 0x14, 0, | 1574 | present = snd_hda_codec_read(codec, 0x14, 0, |
1449 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 1575 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
1450 | 1576 | bits = present ? 0x80 : 0; | |
1451 | snd_hda_codec_amp_update(codec, 0x15, 0, HDA_INPUT, 0, | 1577 | snd_hda_codec_amp_update(codec, 0x15, 0, HDA_INPUT, 0, |
1452 | 0x80, present ? 0x80 : 0); | 1578 | 0x80, bits); |
1453 | snd_hda_codec_amp_update(codec, 0x15, 1, HDA_INPUT, 0, | 1579 | snd_hda_codec_amp_update(codec, 0x15, 1, HDA_INPUT, 0, |
1454 | 0x80, present ? 0x80 : 0); | 1580 | 0x80, bits); |
1455 | } | 1581 | } |
1456 | 1582 | ||
1457 | static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec) | 1583 | static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec) |
@@ -1480,7 +1606,7 @@ static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec, | |||
1480 | */ | 1606 | */ |
1481 | if ((res >> 28) == ALC880_HP_EVENT) | 1607 | if ((res >> 28) == ALC880_HP_EVENT) |
1482 | alc880_uniwill_p53_hp_automute(codec); | 1608 | alc880_uniwill_p53_hp_automute(codec); |
1483 | if ((res >> 28) == ALC880_DCVOL_EVENT) | 1609 | if ((res >> 28) == ALC880_DCVOL_EVENT) |
1484 | alc880_uniwill_p53_dcvol_automute(codec); | 1610 | alc880_uniwill_p53_dcvol_automute(codec); |
1485 | } | 1611 | } |
1486 | 1612 | ||
@@ -1547,22 +1673,8 @@ static struct hda_verb alc880_pin_asus_init_verbs[] = { | |||
1547 | }; | 1673 | }; |
1548 | 1674 | ||
1549 | /* Enable GPIO mask and set output */ | 1675 | /* Enable GPIO mask and set output */ |
1550 | static struct hda_verb alc880_gpio1_init_verbs[] = { | 1676 | #define alc880_gpio1_init_verbs alc_gpio1_init_verbs |
1551 | {0x01, AC_VERB_SET_GPIO_MASK, 0x01}, | 1677 | #define alc880_gpio2_init_verbs alc_gpio2_init_verbs |
1552 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, | ||
1553 | {0x01, AC_VERB_SET_GPIO_DATA, 0x01}, | ||
1554 | |||
1555 | { } | ||
1556 | }; | ||
1557 | |||
1558 | /* Enable GPIO mask and set output */ | ||
1559 | static struct hda_verb alc880_gpio2_init_verbs[] = { | ||
1560 | {0x01, AC_VERB_SET_GPIO_MASK, 0x02}, | ||
1561 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02}, | ||
1562 | {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, | ||
1563 | |||
1564 | { } | ||
1565 | }; | ||
1566 | 1678 | ||
1567 | /* Clevo m520g init */ | 1679 | /* Clevo m520g init */ |
1568 | static struct hda_verb alc880_pin_clevo_init_verbs[] = { | 1680 | static struct hda_verb alc880_pin_clevo_init_verbs[] = { |
@@ -1734,13 +1846,15 @@ static struct hda_verb alc880_lg_init_verbs[] = { | |||
1734 | static void alc880_lg_automute(struct hda_codec *codec) | 1846 | static void alc880_lg_automute(struct hda_codec *codec) |
1735 | { | 1847 | { |
1736 | unsigned int present; | 1848 | unsigned int present; |
1849 | unsigned char bits; | ||
1737 | 1850 | ||
1738 | present = snd_hda_codec_read(codec, 0x1b, 0, | 1851 | present = snd_hda_codec_read(codec, 0x1b, 0, |
1739 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 1852 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
1853 | bits = present ? 0x80 : 0; | ||
1740 | snd_hda_codec_amp_update(codec, 0x17, 0, HDA_OUTPUT, 0, | 1854 | snd_hda_codec_amp_update(codec, 0x17, 0, HDA_OUTPUT, 0, |
1741 | 0x80, present ? 0x80 : 0); | 1855 | 0x80, bits); |
1742 | snd_hda_codec_amp_update(codec, 0x17, 1, HDA_OUTPUT, 0, | 1856 | snd_hda_codec_amp_update(codec, 0x17, 1, HDA_OUTPUT, 0, |
1743 | 0x80, present ? 0x80 : 0); | 1857 | 0x80, bits); |
1744 | } | 1858 | } |
1745 | 1859 | ||
1746 | static void alc880_lg_unsol_event(struct hda_codec *codec, unsigned int res) | 1860 | static void alc880_lg_unsol_event(struct hda_codec *codec, unsigned int res) |
@@ -1810,13 +1924,15 @@ static struct hda_verb alc880_lg_lw_init_verbs[] = { | |||
1810 | static void alc880_lg_lw_automute(struct hda_codec *codec) | 1924 | static void alc880_lg_lw_automute(struct hda_codec *codec) |
1811 | { | 1925 | { |
1812 | unsigned int present; | 1926 | unsigned int present; |
1927 | unsigned char bits; | ||
1813 | 1928 | ||
1814 | present = snd_hda_codec_read(codec, 0x1b, 0, | 1929 | present = snd_hda_codec_read(codec, 0x1b, 0, |
1815 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 1930 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
1931 | bits = present ? 0x80 : 0; | ||
1816 | snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, | 1932 | snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, |
1817 | 0x80, present ? 0x80 : 0); | 1933 | 0x80, bits); |
1818 | snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, | 1934 | snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, |
1819 | 0x80, present ? 0x80 : 0); | 1935 | 0x80, bits); |
1820 | } | 1936 | } |
1821 | 1937 | ||
1822 | static void alc880_lg_lw_unsol_event(struct hda_codec *codec, unsigned int res) | 1938 | static void alc880_lg_lw_unsol_event(struct hda_codec *codec, unsigned int res) |
@@ -1916,6 +2032,17 @@ static int alc880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, | |||
1916 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); | 2032 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); |
1917 | } | 2033 | } |
1918 | 2034 | ||
2035 | static int alc880_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
2036 | struct hda_codec *codec, | ||
2037 | unsigned int stream_tag, | ||
2038 | unsigned int format, | ||
2039 | struct snd_pcm_substream *substream) | ||
2040 | { | ||
2041 | struct alc_spec *spec = codec->spec; | ||
2042 | return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, | ||
2043 | stream_tag, format, substream); | ||
2044 | } | ||
2045 | |||
1919 | static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, | 2046 | static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, |
1920 | struct hda_codec *codec, | 2047 | struct hda_codec *codec, |
1921 | struct snd_pcm_substream *substream) | 2048 | struct snd_pcm_substream *substream) |
@@ -1984,7 +2111,8 @@ static struct hda_pcm_stream alc880_pcm_digital_playback = { | |||
1984 | /* NID is set in alc_build_pcms */ | 2111 | /* NID is set in alc_build_pcms */ |
1985 | .ops = { | 2112 | .ops = { |
1986 | .open = alc880_dig_playback_pcm_open, | 2113 | .open = alc880_dig_playback_pcm_open, |
1987 | .close = alc880_dig_playback_pcm_close | 2114 | .close = alc880_dig_playback_pcm_close, |
2115 | .prepare = alc880_dig_playback_pcm_prepare | ||
1988 | }, | 2116 | }, |
1989 | }; | 2117 | }; |
1990 | 2118 | ||
@@ -2075,7 +2203,7 @@ static void alc_free(struct hda_codec *codec) | |||
2075 | struct alc_spec *spec = codec->spec; | 2203 | struct alc_spec *spec = codec->spec; |
2076 | unsigned int i; | 2204 | unsigned int i; |
2077 | 2205 | ||
2078 | if (! spec) | 2206 | if (!spec) |
2079 | return; | 2207 | return; |
2080 | 2208 | ||
2081 | if (spec->kctl_alloc) { | 2209 | if (spec->kctl_alloc) { |
@@ -2477,7 +2605,8 @@ static struct snd_pci_quirk alc880_cfg_tbl[] = { | |||
2477 | static struct alc_config_preset alc880_presets[] = { | 2605 | static struct alc_config_preset alc880_presets[] = { |
2478 | [ALC880_3ST] = { | 2606 | [ALC880_3ST] = { |
2479 | .mixers = { alc880_three_stack_mixer }, | 2607 | .mixers = { alc880_three_stack_mixer }, |
2480 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_3stack_init_verbs }, | 2608 | .init_verbs = { alc880_volume_init_verbs, |
2609 | alc880_pin_3stack_init_verbs }, | ||
2481 | .num_dacs = ARRAY_SIZE(alc880_dac_nids), | 2610 | .num_dacs = ARRAY_SIZE(alc880_dac_nids), |
2482 | .dac_nids = alc880_dac_nids, | 2611 | .dac_nids = alc880_dac_nids, |
2483 | .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), | 2612 | .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), |
@@ -2487,7 +2616,8 @@ static struct alc_config_preset alc880_presets[] = { | |||
2487 | }, | 2616 | }, |
2488 | [ALC880_3ST_DIG] = { | 2617 | [ALC880_3ST_DIG] = { |
2489 | .mixers = { alc880_three_stack_mixer }, | 2618 | .mixers = { alc880_three_stack_mixer }, |
2490 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_3stack_init_verbs }, | 2619 | .init_verbs = { alc880_volume_init_verbs, |
2620 | alc880_pin_3stack_init_verbs }, | ||
2491 | .num_dacs = ARRAY_SIZE(alc880_dac_nids), | 2621 | .num_dacs = ARRAY_SIZE(alc880_dac_nids), |
2492 | .dac_nids = alc880_dac_nids, | 2622 | .dac_nids = alc880_dac_nids, |
2493 | .dig_out_nid = ALC880_DIGOUT_NID, | 2623 | .dig_out_nid = ALC880_DIGOUT_NID, |
@@ -2509,8 +2639,10 @@ static struct alc_config_preset alc880_presets[] = { | |||
2509 | .input_mux = &alc880_capture_source, | 2639 | .input_mux = &alc880_capture_source, |
2510 | }, | 2640 | }, |
2511 | [ALC880_5ST] = { | 2641 | [ALC880_5ST] = { |
2512 | .mixers = { alc880_three_stack_mixer, alc880_five_stack_mixer}, | 2642 | .mixers = { alc880_three_stack_mixer, |
2513 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_5stack_init_verbs }, | 2643 | alc880_five_stack_mixer}, |
2644 | .init_verbs = { alc880_volume_init_verbs, | ||
2645 | alc880_pin_5stack_init_verbs }, | ||
2514 | .num_dacs = ARRAY_SIZE(alc880_dac_nids), | 2646 | .num_dacs = ARRAY_SIZE(alc880_dac_nids), |
2515 | .dac_nids = alc880_dac_nids, | 2647 | .dac_nids = alc880_dac_nids, |
2516 | .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes), | 2648 | .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes), |
@@ -2518,8 +2650,10 @@ static struct alc_config_preset alc880_presets[] = { | |||
2518 | .input_mux = &alc880_capture_source, | 2650 | .input_mux = &alc880_capture_source, |
2519 | }, | 2651 | }, |
2520 | [ALC880_5ST_DIG] = { | 2652 | [ALC880_5ST_DIG] = { |
2521 | .mixers = { alc880_three_stack_mixer, alc880_five_stack_mixer }, | 2653 | .mixers = { alc880_three_stack_mixer, |
2522 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_5stack_init_verbs }, | 2654 | alc880_five_stack_mixer }, |
2655 | .init_verbs = { alc880_volume_init_verbs, | ||
2656 | alc880_pin_5stack_init_verbs }, | ||
2523 | .num_dacs = ARRAY_SIZE(alc880_dac_nids), | 2657 | .num_dacs = ARRAY_SIZE(alc880_dac_nids), |
2524 | .dac_nids = alc880_dac_nids, | 2658 | .dac_nids = alc880_dac_nids, |
2525 | .dig_out_nid = ALC880_DIGOUT_NID, | 2659 | .dig_out_nid = ALC880_DIGOUT_NID, |
@@ -2529,7 +2663,8 @@ static struct alc_config_preset alc880_presets[] = { | |||
2529 | }, | 2663 | }, |
2530 | [ALC880_6ST] = { | 2664 | [ALC880_6ST] = { |
2531 | .mixers = { alc880_six_stack_mixer }, | 2665 | .mixers = { alc880_six_stack_mixer }, |
2532 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_6stack_init_verbs }, | 2666 | .init_verbs = { alc880_volume_init_verbs, |
2667 | alc880_pin_6stack_init_verbs }, | ||
2533 | .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids), | 2668 | .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids), |
2534 | .dac_nids = alc880_6st_dac_nids, | 2669 | .dac_nids = alc880_6st_dac_nids, |
2535 | .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes), | 2670 | .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes), |
@@ -2538,7 +2673,8 @@ static struct alc_config_preset alc880_presets[] = { | |||
2538 | }, | 2673 | }, |
2539 | [ALC880_6ST_DIG] = { | 2674 | [ALC880_6ST_DIG] = { |
2540 | .mixers = { alc880_six_stack_mixer }, | 2675 | .mixers = { alc880_six_stack_mixer }, |
2541 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_6stack_init_verbs }, | 2676 | .init_verbs = { alc880_volume_init_verbs, |
2677 | alc880_pin_6stack_init_verbs }, | ||
2542 | .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids), | 2678 | .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids), |
2543 | .dac_nids = alc880_6st_dac_nids, | 2679 | .dac_nids = alc880_6st_dac_nids, |
2544 | .dig_out_nid = ALC880_DIGOUT_NID, | 2680 | .dig_out_nid = ALC880_DIGOUT_NID, |
@@ -2548,7 +2684,8 @@ static struct alc_config_preset alc880_presets[] = { | |||
2548 | }, | 2684 | }, |
2549 | [ALC880_W810] = { | 2685 | [ALC880_W810] = { |
2550 | .mixers = { alc880_w810_base_mixer }, | 2686 | .mixers = { alc880_w810_base_mixer }, |
2551 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_w810_init_verbs, | 2687 | .init_verbs = { alc880_volume_init_verbs, |
2688 | alc880_pin_w810_init_verbs, | ||
2552 | alc880_gpio2_init_verbs }, | 2689 | alc880_gpio2_init_verbs }, |
2553 | .num_dacs = ARRAY_SIZE(alc880_w810_dac_nids), | 2690 | .num_dacs = ARRAY_SIZE(alc880_w810_dac_nids), |
2554 | .dac_nids = alc880_w810_dac_nids, | 2691 | .dac_nids = alc880_w810_dac_nids, |
@@ -2559,7 +2696,8 @@ static struct alc_config_preset alc880_presets[] = { | |||
2559 | }, | 2696 | }, |
2560 | [ALC880_Z71V] = { | 2697 | [ALC880_Z71V] = { |
2561 | .mixers = { alc880_z71v_mixer }, | 2698 | .mixers = { alc880_z71v_mixer }, |
2562 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_z71v_init_verbs }, | 2699 | .init_verbs = { alc880_volume_init_verbs, |
2700 | alc880_pin_z71v_init_verbs }, | ||
2563 | .num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids), | 2701 | .num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids), |
2564 | .dac_nids = alc880_z71v_dac_nids, | 2702 | .dac_nids = alc880_z71v_dac_nids, |
2565 | .dig_out_nid = ALC880_DIGOUT_NID, | 2703 | .dig_out_nid = ALC880_DIGOUT_NID, |
@@ -2570,7 +2708,8 @@ static struct alc_config_preset alc880_presets[] = { | |||
2570 | }, | 2708 | }, |
2571 | [ALC880_F1734] = { | 2709 | [ALC880_F1734] = { |
2572 | .mixers = { alc880_f1734_mixer }, | 2710 | .mixers = { alc880_f1734_mixer }, |
2573 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_f1734_init_verbs }, | 2711 | .init_verbs = { alc880_volume_init_verbs, |
2712 | alc880_pin_f1734_init_verbs }, | ||
2574 | .num_dacs = ARRAY_SIZE(alc880_f1734_dac_nids), | 2713 | .num_dacs = ARRAY_SIZE(alc880_f1734_dac_nids), |
2575 | .dac_nids = alc880_f1734_dac_nids, | 2714 | .dac_nids = alc880_f1734_dac_nids, |
2576 | .hp_nid = 0x02, | 2715 | .hp_nid = 0x02, |
@@ -2580,7 +2719,8 @@ static struct alc_config_preset alc880_presets[] = { | |||
2580 | }, | 2719 | }, |
2581 | [ALC880_ASUS] = { | 2720 | [ALC880_ASUS] = { |
2582 | .mixers = { alc880_asus_mixer }, | 2721 | .mixers = { alc880_asus_mixer }, |
2583 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs, | 2722 | .init_verbs = { alc880_volume_init_verbs, |
2723 | alc880_pin_asus_init_verbs, | ||
2584 | alc880_gpio1_init_verbs }, | 2724 | alc880_gpio1_init_verbs }, |
2585 | .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), | 2725 | .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), |
2586 | .dac_nids = alc880_asus_dac_nids, | 2726 | .dac_nids = alc880_asus_dac_nids, |
@@ -2591,7 +2731,8 @@ static struct alc_config_preset alc880_presets[] = { | |||
2591 | }, | 2731 | }, |
2592 | [ALC880_ASUS_DIG] = { | 2732 | [ALC880_ASUS_DIG] = { |
2593 | .mixers = { alc880_asus_mixer }, | 2733 | .mixers = { alc880_asus_mixer }, |
2594 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs, | 2734 | .init_verbs = { alc880_volume_init_verbs, |
2735 | alc880_pin_asus_init_verbs, | ||
2595 | alc880_gpio1_init_verbs }, | 2736 | alc880_gpio1_init_verbs }, |
2596 | .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), | 2737 | .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), |
2597 | .dac_nids = alc880_asus_dac_nids, | 2738 | .dac_nids = alc880_asus_dac_nids, |
@@ -2603,7 +2744,8 @@ static struct alc_config_preset alc880_presets[] = { | |||
2603 | }, | 2744 | }, |
2604 | [ALC880_ASUS_DIG2] = { | 2745 | [ALC880_ASUS_DIG2] = { |
2605 | .mixers = { alc880_asus_mixer }, | 2746 | .mixers = { alc880_asus_mixer }, |
2606 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs, | 2747 | .init_verbs = { alc880_volume_init_verbs, |
2748 | alc880_pin_asus_init_verbs, | ||
2607 | alc880_gpio2_init_verbs }, /* use GPIO2 */ | 2749 | alc880_gpio2_init_verbs }, /* use GPIO2 */ |
2608 | .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), | 2750 | .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), |
2609 | .dac_nids = alc880_asus_dac_nids, | 2751 | .dac_nids = alc880_asus_dac_nids, |
@@ -2615,7 +2757,8 @@ static struct alc_config_preset alc880_presets[] = { | |||
2615 | }, | 2757 | }, |
2616 | [ALC880_ASUS_W1V] = { | 2758 | [ALC880_ASUS_W1V] = { |
2617 | .mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer }, | 2759 | .mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer }, |
2618 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs, | 2760 | .init_verbs = { alc880_volume_init_verbs, |
2761 | alc880_pin_asus_init_verbs, | ||
2619 | alc880_gpio1_init_verbs }, | 2762 | alc880_gpio1_init_verbs }, |
2620 | .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), | 2763 | .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), |
2621 | .dac_nids = alc880_asus_dac_nids, | 2764 | .dac_nids = alc880_asus_dac_nids, |
@@ -2664,7 +2807,7 @@ static struct alc_config_preset alc880_presets[] = { | |||
2664 | .init_hook = alc880_uniwill_p53_hp_automute, | 2807 | .init_hook = alc880_uniwill_p53_hp_automute, |
2665 | }, | 2808 | }, |
2666 | [ALC880_FUJITSU] = { | 2809 | [ALC880_FUJITSU] = { |
2667 | .mixers = { alc880_fujitsu_mixer, | 2810 | .mixers = { alc880_fujitsu_mixer, |
2668 | alc880_pcbeep_mixer, }, | 2811 | alc880_pcbeep_mixer, }, |
2669 | .init_verbs = { alc880_volume_init_verbs, | 2812 | .init_verbs = { alc880_volume_init_verbs, |
2670 | alc880_uniwill_p53_init_verbs, | 2813 | alc880_uniwill_p53_init_verbs, |
@@ -2707,7 +2850,7 @@ static struct alc_config_preset alc880_presets[] = { | |||
2707 | .mixers = { alc880_lg_lw_mixer }, | 2850 | .mixers = { alc880_lg_lw_mixer }, |
2708 | .init_verbs = { alc880_volume_init_verbs, | 2851 | .init_verbs = { alc880_volume_init_verbs, |
2709 | alc880_lg_lw_init_verbs }, | 2852 | alc880_lg_lw_init_verbs }, |
2710 | .num_dacs = 1, | 2853 | .num_dacs = 1, |
2711 | .dac_nids = alc880_dac_nids, | 2854 | .dac_nids = alc880_dac_nids, |
2712 | .dig_out_nid = ALC880_DIGOUT_NID, | 2855 | .dig_out_nid = ALC880_DIGOUT_NID, |
2713 | .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), | 2856 | .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), |
@@ -2749,18 +2892,21 @@ static struct snd_kcontrol_new alc880_control_templates[] = { | |||
2749 | }; | 2892 | }; |
2750 | 2893 | ||
2751 | /* add dynamic controls */ | 2894 | /* add dynamic controls */ |
2752 | static int add_control(struct alc_spec *spec, int type, const char *name, unsigned long val) | 2895 | static int add_control(struct alc_spec *spec, int type, const char *name, |
2896 | unsigned long val) | ||
2753 | { | 2897 | { |
2754 | struct snd_kcontrol_new *knew; | 2898 | struct snd_kcontrol_new *knew; |
2755 | 2899 | ||
2756 | if (spec->num_kctl_used >= spec->num_kctl_alloc) { | 2900 | if (spec->num_kctl_used >= spec->num_kctl_alloc) { |
2757 | int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC; | 2901 | int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC; |
2758 | 2902 | ||
2759 | knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */ | 2903 | /* array + terminator */ |
2760 | if (! knew) | 2904 | knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); |
2905 | if (!knew) | ||
2761 | return -ENOMEM; | 2906 | return -ENOMEM; |
2762 | if (spec->kctl_alloc) { | 2907 | if (spec->kctl_alloc) { |
2763 | memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc); | 2908 | memcpy(knew, spec->kctl_alloc, |
2909 | sizeof(*knew) * spec->num_kctl_alloc); | ||
2764 | kfree(spec->kctl_alloc); | 2910 | kfree(spec->kctl_alloc); |
2765 | } | 2911 | } |
2766 | spec->kctl_alloc = knew; | 2912 | spec->kctl_alloc = knew; |
@@ -2770,7 +2916,7 @@ static int add_control(struct alc_spec *spec, int type, const char *name, unsign | |||
2770 | knew = &spec->kctl_alloc[spec->num_kctl_used]; | 2916 | knew = &spec->kctl_alloc[spec->num_kctl_used]; |
2771 | *knew = alc880_control_templates[type]; | 2917 | *knew = alc880_control_templates[type]; |
2772 | knew->name = kstrdup(name, GFP_KERNEL); | 2918 | knew->name = kstrdup(name, GFP_KERNEL); |
2773 | if (! knew->name) | 2919 | if (!knew->name) |
2774 | return -ENOMEM; | 2920 | return -ENOMEM; |
2775 | knew->private_value = val; | 2921 | knew->private_value = val; |
2776 | spec->num_kctl_used++; | 2922 | spec->num_kctl_used++; |
@@ -2790,7 +2936,8 @@ static int add_control(struct alc_spec *spec, int type, const char *name, unsign | |||
2790 | #define ALC880_PIN_CD_NID 0x1c | 2936 | #define ALC880_PIN_CD_NID 0x1c |
2791 | 2937 | ||
2792 | /* fill in the dac_nids table from the parsed pin configuration */ | 2938 | /* fill in the dac_nids table from the parsed pin configuration */ |
2793 | static int alc880_auto_fill_dac_nids(struct alc_spec *spec, const struct auto_pin_cfg *cfg) | 2939 | static int alc880_auto_fill_dac_nids(struct alc_spec *spec, |
2940 | const struct auto_pin_cfg *cfg) | ||
2794 | { | 2941 | { |
2795 | hda_nid_t nid; | 2942 | hda_nid_t nid; |
2796 | int assigned[4]; | 2943 | int assigned[4]; |
@@ -2815,8 +2962,9 @@ static int alc880_auto_fill_dac_nids(struct alc_spec *spec, const struct auto_pi | |||
2815 | continue; | 2962 | continue; |
2816 | /* search for an empty channel */ | 2963 | /* search for an empty channel */ |
2817 | for (j = 0; j < cfg->line_outs; j++) { | 2964 | for (j = 0; j < cfg->line_outs; j++) { |
2818 | if (! assigned[j]) { | 2965 | if (!assigned[j]) { |
2819 | spec->multiout.dac_nids[i] = alc880_idx_to_dac(j); | 2966 | spec->multiout.dac_nids[i] = |
2967 | alc880_idx_to_dac(j); | ||
2820 | assigned[j] = 1; | 2968 | assigned[j] = 1; |
2821 | break; | 2969 | break; |
2822 | } | 2970 | } |
@@ -2831,36 +2979,54 @@ static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
2831 | const struct auto_pin_cfg *cfg) | 2979 | const struct auto_pin_cfg *cfg) |
2832 | { | 2980 | { |
2833 | char name[32]; | 2981 | char name[32]; |
2834 | static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" }; | 2982 | static const char *chname[4] = { |
2983 | "Front", "Surround", NULL /*CLFE*/, "Side" | ||
2984 | }; | ||
2835 | hda_nid_t nid; | 2985 | hda_nid_t nid; |
2836 | int i, err; | 2986 | int i, err; |
2837 | 2987 | ||
2838 | for (i = 0; i < cfg->line_outs; i++) { | 2988 | for (i = 0; i < cfg->line_outs; i++) { |
2839 | if (! spec->multiout.dac_nids[i]) | 2989 | if (!spec->multiout.dac_nids[i]) |
2840 | continue; | 2990 | continue; |
2841 | nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i])); | 2991 | nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i])); |
2842 | if (i == 2) { | 2992 | if (i == 2) { |
2843 | /* Center/LFE */ | 2993 | /* Center/LFE */ |
2844 | if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Center Playback Volume", | 2994 | err = add_control(spec, ALC_CTL_WIDGET_VOL, |
2845 | HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0) | 2995 | "Center Playback Volume", |
2996 | HDA_COMPOSE_AMP_VAL(nid, 1, 0, | ||
2997 | HDA_OUTPUT)); | ||
2998 | if (err < 0) | ||
2846 | return err; | 2999 | return err; |
2847 | if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "LFE Playback Volume", | 3000 | err = add_control(spec, ALC_CTL_WIDGET_VOL, |
2848 | HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0) | 3001 | "LFE Playback Volume", |
3002 | HDA_COMPOSE_AMP_VAL(nid, 2, 0, | ||
3003 | HDA_OUTPUT)); | ||
3004 | if (err < 0) | ||
2849 | return err; | 3005 | return err; |
2850 | if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "Center Playback Switch", | 3006 | err = add_control(spec, ALC_CTL_BIND_MUTE, |
2851 | HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT))) < 0) | 3007 | "Center Playback Switch", |
3008 | HDA_COMPOSE_AMP_VAL(nid, 1, 2, | ||
3009 | HDA_INPUT)); | ||
3010 | if (err < 0) | ||
2852 | return err; | 3011 | return err; |
2853 | if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "LFE Playback Switch", | 3012 | err = add_control(spec, ALC_CTL_BIND_MUTE, |
2854 | HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT))) < 0) | 3013 | "LFE Playback Switch", |
3014 | HDA_COMPOSE_AMP_VAL(nid, 2, 2, | ||
3015 | HDA_INPUT)); | ||
3016 | if (err < 0) | ||
2855 | return err; | 3017 | return err; |
2856 | } else { | 3018 | } else { |
2857 | sprintf(name, "%s Playback Volume", chname[i]); | 3019 | sprintf(name, "%s Playback Volume", chname[i]); |
2858 | if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name, | 3020 | err = add_control(spec, ALC_CTL_WIDGET_VOL, name, |
2859 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) | 3021 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, |
3022 | HDA_OUTPUT)); | ||
3023 | if (err < 0) | ||
2860 | return err; | 3024 | return err; |
2861 | sprintf(name, "%s Playback Switch", chname[i]); | 3025 | sprintf(name, "%s Playback Switch", chname[i]); |
2862 | if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name, | 3026 | err = add_control(spec, ALC_CTL_BIND_MUTE, name, |
2863 | HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0) | 3027 | HDA_COMPOSE_AMP_VAL(nid, 3, 2, |
3028 | HDA_INPUT)); | ||
3029 | if (err < 0) | ||
2864 | return err; | 3030 | return err; |
2865 | } | 3031 | } |
2866 | } | 3032 | } |
@@ -2875,51 +3041,57 @@ static int alc880_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin, | |||
2875 | int err; | 3041 | int err; |
2876 | char name[32]; | 3042 | char name[32]; |
2877 | 3043 | ||
2878 | if (! pin) | 3044 | if (!pin) |
2879 | return 0; | 3045 | return 0; |
2880 | 3046 | ||
2881 | if (alc880_is_fixed_pin(pin)) { | 3047 | if (alc880_is_fixed_pin(pin)) { |
2882 | nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); | 3048 | nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); |
2883 | /* specify the DAC as the extra output */ | 3049 | /* specify the DAC as the extra output */ |
2884 | if (! spec->multiout.hp_nid) | 3050 | if (!spec->multiout.hp_nid) |
2885 | spec->multiout.hp_nid = nid; | 3051 | spec->multiout.hp_nid = nid; |
2886 | else | 3052 | else |
2887 | spec->multiout.extra_out_nid[0] = nid; | 3053 | spec->multiout.extra_out_nid[0] = nid; |
2888 | /* control HP volume/switch on the output mixer amp */ | 3054 | /* control HP volume/switch on the output mixer amp */ |
2889 | nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin)); | 3055 | nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin)); |
2890 | sprintf(name, "%s Playback Volume", pfx); | 3056 | sprintf(name, "%s Playback Volume", pfx); |
2891 | if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name, | 3057 | err = add_control(spec, ALC_CTL_WIDGET_VOL, name, |
2892 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) | 3058 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); |
3059 | if (err < 0) | ||
2893 | return err; | 3060 | return err; |
2894 | sprintf(name, "%s Playback Switch", pfx); | 3061 | sprintf(name, "%s Playback Switch", pfx); |
2895 | if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name, | 3062 | err = add_control(spec, ALC_CTL_BIND_MUTE, name, |
2896 | HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0) | 3063 | HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT)); |
3064 | if (err < 0) | ||
2897 | return err; | 3065 | return err; |
2898 | } else if (alc880_is_multi_pin(pin)) { | 3066 | } else if (alc880_is_multi_pin(pin)) { |
2899 | /* set manual connection */ | 3067 | /* set manual connection */ |
2900 | /* we have only a switch on HP-out PIN */ | 3068 | /* we have only a switch on HP-out PIN */ |
2901 | sprintf(name, "%s Playback Switch", pfx); | 3069 | sprintf(name, "%s Playback Switch", pfx); |
2902 | if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, | 3070 | err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, |
2903 | HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT))) < 0) | 3071 | HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT)); |
3072 | if (err < 0) | ||
2904 | return err; | 3073 | return err; |
2905 | } | 3074 | } |
2906 | return 0; | 3075 | return 0; |
2907 | } | 3076 | } |
2908 | 3077 | ||
2909 | /* create input playback/capture controls for the given pin */ | 3078 | /* create input playback/capture controls for the given pin */ |
2910 | static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, const char *ctlname, | 3079 | static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, |
3080 | const char *ctlname, | ||
2911 | int idx, hda_nid_t mix_nid) | 3081 | int idx, hda_nid_t mix_nid) |
2912 | { | 3082 | { |
2913 | char name[32]; | 3083 | char name[32]; |
2914 | int err; | 3084 | int err; |
2915 | 3085 | ||
2916 | sprintf(name, "%s Playback Volume", ctlname); | 3086 | sprintf(name, "%s Playback Volume", ctlname); |
2917 | if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name, | 3087 | err = add_control(spec, ALC_CTL_WIDGET_VOL, name, |
2918 | HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT))) < 0) | 3088 | HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); |
3089 | if (err < 0) | ||
2919 | return err; | 3090 | return err; |
2920 | sprintf(name, "%s Playback Switch", ctlname); | 3091 | sprintf(name, "%s Playback Switch", ctlname); |
2921 | if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, | 3092 | err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, |
2922 | HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT))) < 0) | 3093 | HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); |
3094 | if (err < 0) | ||
2923 | return err; | 3095 | return err; |
2924 | return 0; | 3096 | return 0; |
2925 | } | 3097 | } |
@@ -2939,8 +3111,10 @@ static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec, | |||
2939 | idx, 0x0b); | 3111 | idx, 0x0b); |
2940 | if (err < 0) | 3112 | if (err < 0) |
2941 | return err; | 3113 | return err; |
2942 | imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; | 3114 | imux->items[imux->num_items].label = |
2943 | imux->items[imux->num_items].index = alc880_input_pin_idx(cfg->input_pins[i]); | 3115 | auto_pin_cfg_labels[i]; |
3116 | imux->items[imux->num_items].index = | ||
3117 | alc880_input_pin_idx(cfg->input_pins[i]); | ||
2944 | imux->num_items++; | 3118 | imux->num_items++; |
2945 | } | 3119 | } |
2946 | } | 3120 | } |
@@ -2952,8 +3126,10 @@ static void alc880_auto_set_output_and_unmute(struct hda_codec *codec, | |||
2952 | int dac_idx) | 3126 | int dac_idx) |
2953 | { | 3127 | { |
2954 | /* set as output */ | 3128 | /* set as output */ |
2955 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type); | 3129 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, |
2956 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); | 3130 | pin_type); |
3131 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, | ||
3132 | AMP_OUT_UNMUTE); | ||
2957 | /* need the manual connection? */ | 3133 | /* need the manual connection? */ |
2958 | if (alc880_is_multi_pin(nid)) { | 3134 | if (alc880_is_multi_pin(nid)) { |
2959 | struct alc_spec *spec = codec->spec; | 3135 | struct alc_spec *spec = codec->spec; |
@@ -2964,14 +3140,24 @@ static void alc880_auto_set_output_and_unmute(struct hda_codec *codec, | |||
2964 | } | 3140 | } |
2965 | } | 3141 | } |
2966 | 3142 | ||
3143 | static int get_pin_type(int line_out_type) | ||
3144 | { | ||
3145 | if (line_out_type == AUTO_PIN_HP_OUT) | ||
3146 | return PIN_HP; | ||
3147 | else | ||
3148 | return PIN_OUT; | ||
3149 | } | ||
3150 | |||
2967 | static void alc880_auto_init_multi_out(struct hda_codec *codec) | 3151 | static void alc880_auto_init_multi_out(struct hda_codec *codec) |
2968 | { | 3152 | { |
2969 | struct alc_spec *spec = codec->spec; | 3153 | struct alc_spec *spec = codec->spec; |
2970 | int i; | 3154 | int i; |
2971 | 3155 | ||
3156 | alc_subsystem_id(codec, 0x15, 0x1b, 0x14); | ||
2972 | for (i = 0; i < spec->autocfg.line_outs; i++) { | 3157 | for (i = 0; i < spec->autocfg.line_outs; i++) { |
2973 | hda_nid_t nid = spec->autocfg.line_out_pins[i]; | 3158 | hda_nid_t nid = spec->autocfg.line_out_pins[i]; |
2974 | alc880_auto_set_output_and_unmute(codec, nid, PIN_OUT, i); | 3159 | int pin_type = get_pin_type(spec->autocfg.line_out_type); |
3160 | alc880_auto_set_output_and_unmute(codec, nid, pin_type, i); | ||
2975 | } | 3161 | } |
2976 | } | 3162 | } |
2977 | 3163 | ||
@@ -2996,37 +3182,52 @@ static void alc880_auto_init_analog_input(struct hda_codec *codec) | |||
2996 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 3182 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
2997 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 3183 | hda_nid_t nid = spec->autocfg.input_pins[i]; |
2998 | if (alc880_is_input_pin(nid)) { | 3184 | if (alc880_is_input_pin(nid)) { |
2999 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | 3185 | snd_hda_codec_write(codec, nid, 0, |
3000 | i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN); | 3186 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
3187 | i <= AUTO_PIN_FRONT_MIC ? | ||
3188 | PIN_VREF80 : PIN_IN); | ||
3001 | if (nid != ALC880_PIN_CD_NID) | 3189 | if (nid != ALC880_PIN_CD_NID) |
3002 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, | 3190 | snd_hda_codec_write(codec, nid, 0, |
3191 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
3003 | AMP_OUT_MUTE); | 3192 | AMP_OUT_MUTE); |
3004 | } | 3193 | } |
3005 | } | 3194 | } |
3006 | } | 3195 | } |
3007 | 3196 | ||
3008 | /* parse the BIOS configuration and set up the alc_spec */ | 3197 | /* parse the BIOS configuration and set up the alc_spec */ |
3009 | /* return 1 if successful, 0 if the proper config is not found, or a negative error code */ | 3198 | /* return 1 if successful, 0 if the proper config is not found, |
3199 | * or a negative error code | ||
3200 | */ | ||
3010 | static int alc880_parse_auto_config(struct hda_codec *codec) | 3201 | static int alc880_parse_auto_config(struct hda_codec *codec) |
3011 | { | 3202 | { |
3012 | struct alc_spec *spec = codec->spec; | 3203 | struct alc_spec *spec = codec->spec; |
3013 | int err; | 3204 | int err; |
3014 | static hda_nid_t alc880_ignore[] = { 0x1d, 0 }; | 3205 | static hda_nid_t alc880_ignore[] = { 0x1d, 0 }; |
3015 | 3206 | ||
3016 | if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, | 3207 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, |
3017 | alc880_ignore)) < 0) | 3208 | alc880_ignore); |
3209 | if (err < 0) | ||
3018 | return err; | 3210 | return err; |
3019 | if (! spec->autocfg.line_outs) | 3211 | if (!spec->autocfg.line_outs) |
3020 | return 0; /* can't find valid BIOS pin config */ | 3212 | return 0; /* can't find valid BIOS pin config */ |
3021 | 3213 | ||
3022 | if ((err = alc880_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 || | 3214 | err = alc880_auto_fill_dac_nids(spec, &spec->autocfg); |
3023 | (err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || | 3215 | if (err < 0) |
3024 | (err = alc880_auto_create_extra_out(spec, | 3216 | return err; |
3025 | spec->autocfg.speaker_pins[0], | 3217 | err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg); |
3026 | "Speaker")) < 0 || | 3218 | if (err < 0) |
3027 | (err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0], | 3219 | return err; |
3028 | "Headphone")) < 0 || | 3220 | err = alc880_auto_create_extra_out(spec, |
3029 | (err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) | 3221 | spec->autocfg.speaker_pins[0], |
3222 | "Speaker"); | ||
3223 | if (err < 0) | ||
3224 | return err; | ||
3225 | err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0], | ||
3226 | "Headphone"); | ||
3227 | if (err < 0) | ||
3228 | return err; | ||
3229 | err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg); | ||
3230 | if (err < 0) | ||
3030 | return err; | 3231 | return err; |
3031 | 3232 | ||
3032 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 3233 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
@@ -3086,7 +3287,7 @@ static int patch_alc880(struct hda_codec *codec) | |||
3086 | if (err < 0) { | 3287 | if (err < 0) { |
3087 | alc_free(codec); | 3288 | alc_free(codec); |
3088 | return err; | 3289 | return err; |
3089 | } else if (! err) { | 3290 | } else if (!err) { |
3090 | printk(KERN_INFO | 3291 | printk(KERN_INFO |
3091 | "hda_codec: Cannot set up configuration " | 3292 | "hda_codec: Cannot set up configuration " |
3092 | "from BIOS. Using 3-stack mode...\n"); | 3293 | "from BIOS. Using 3-stack mode...\n"); |
@@ -3105,14 +3306,16 @@ static int patch_alc880(struct hda_codec *codec) | |||
3105 | spec->stream_digital_playback = &alc880_pcm_digital_playback; | 3306 | spec->stream_digital_playback = &alc880_pcm_digital_playback; |
3106 | spec->stream_digital_capture = &alc880_pcm_digital_capture; | 3307 | spec->stream_digital_capture = &alc880_pcm_digital_capture; |
3107 | 3308 | ||
3108 | if (! spec->adc_nids && spec->input_mux) { | 3309 | if (!spec->adc_nids && spec->input_mux) { |
3109 | /* check whether NID 0x07 is valid */ | 3310 | /* check whether NID 0x07 is valid */ |
3110 | unsigned int wcap = get_wcaps(codec, alc880_adc_nids[0]); | 3311 | unsigned int wcap = get_wcaps(codec, alc880_adc_nids[0]); |
3111 | wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */ | 3312 | /* get type */ |
3313 | wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; | ||
3112 | if (wcap != AC_WID_AUD_IN) { | 3314 | if (wcap != AC_WID_AUD_IN) { |
3113 | spec->adc_nids = alc880_adc_nids_alt; | 3315 | spec->adc_nids = alc880_adc_nids_alt; |
3114 | spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids_alt); | 3316 | spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids_alt); |
3115 | spec->mixers[spec->num_mixers] = alc880_capture_alt_mixer; | 3317 | spec->mixers[spec->num_mixers] = |
3318 | alc880_capture_alt_mixer; | ||
3116 | spec->num_mixers++; | 3319 | spec->num_mixers++; |
3117 | } else { | 3320 | } else { |
3118 | spec->adc_nids = alc880_adc_nids; | 3321 | spec->adc_nids = alc880_adc_nids; |
@@ -3254,7 +3457,7 @@ static struct snd_kcontrol_new alc260_base_output_mixer[] = { | |||
3254 | HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), | 3457 | HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), |
3255 | HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT), | 3458 | HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT), |
3256 | { } /* end */ | 3459 | { } /* end */ |
3257 | }; | 3460 | }; |
3258 | 3461 | ||
3259 | static struct snd_kcontrol_new alc260_input_mixer[] = { | 3462 | static struct snd_kcontrol_new alc260_input_mixer[] = { |
3260 | HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), | 3463 | HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), |
@@ -3349,6 +3552,42 @@ static struct snd_kcontrol_new alc260_acer_mixer[] = { | |||
3349 | { } /* end */ | 3552 | { } /* end */ |
3350 | }; | 3553 | }; |
3351 | 3554 | ||
3555 | /* Packard bell V7900 ALC260 pin usage: HP = 0x0f, Mic jack = 0x12, | ||
3556 | * Line In jack = 0x14, CD audio = 0x16, pc beep = 0x17. | ||
3557 | */ | ||
3558 | static struct snd_kcontrol_new alc260_will_mixer[] = { | ||
3559 | HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT), | ||
3560 | HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT), | ||
3561 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT), | ||
3562 | HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT), | ||
3563 | ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN), | ||
3564 | HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), | ||
3565 | HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT), | ||
3566 | ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT), | ||
3567 | HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), | ||
3568 | HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), | ||
3569 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT), | ||
3570 | HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT), | ||
3571 | { } /* end */ | ||
3572 | }; | ||
3573 | |||
3574 | /* Replacer 672V ALC260 pin usage: Mic jack = 0x12, | ||
3575 | * Line In jack = 0x14, ATAPI Mic = 0x13, speaker = 0x0f. | ||
3576 | */ | ||
3577 | static struct snd_kcontrol_new alc260_replacer_672v_mixer[] = { | ||
3578 | HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT), | ||
3579 | HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT), | ||
3580 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT), | ||
3581 | HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT), | ||
3582 | ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN), | ||
3583 | HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x07, 0x1, HDA_INPUT), | ||
3584 | HDA_CODEC_MUTE("ATATI Mic Playback Switch", 0x07, 0x1, HDA_INPUT), | ||
3585 | HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), | ||
3586 | HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT), | ||
3587 | ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT), | ||
3588 | { } /* end */ | ||
3589 | }; | ||
3590 | |||
3352 | /* capture mixer elements */ | 3591 | /* capture mixer elements */ |
3353 | static struct snd_kcontrol_new alc260_capture_mixer[] = { | 3592 | static struct snd_kcontrol_new alc260_capture_mixer[] = { |
3354 | HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT), | 3593 | HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT), |
@@ -3434,7 +3673,9 @@ static struct hda_verb alc260_init_verbs[] = { | |||
3434 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | 3673 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
3435 | /* unmute LINE-2 out pin */ | 3674 | /* unmute LINE-2 out pin */ |
3436 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | 3675 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
3437 | /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */ | 3676 | /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & |
3677 | * Line In 2 = 0x03 | ||
3678 | */ | ||
3438 | /* mute CD */ | 3679 | /* mute CD */ |
3439 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 3680 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, |
3440 | /* mute Line In */ | 3681 | /* mute Line In */ |
@@ -3482,7 +3723,9 @@ static struct hda_verb alc260_hp_init_verbs[] = { | |||
3482 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 3723 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, |
3483 | /* mute pin widget amp left and right (no gain on this amp) */ | 3724 | /* mute pin widget amp left and right (no gain on this amp) */ |
3484 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, | 3725 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, |
3485 | /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */ | 3726 | /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & |
3727 | * Line In 2 = 0x03 | ||
3728 | */ | ||
3486 | /* unmute CD */ | 3729 | /* unmute CD */ |
3487 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, | 3730 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, |
3488 | /* unmute Line In */ | 3731 | /* unmute Line In */ |
@@ -3530,7 +3773,9 @@ static struct hda_verb alc260_hp_3013_init_verbs[] = { | |||
3530 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 3773 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, |
3531 | /* mute pin widget amp left and right (no gain on this amp) */ | 3774 | /* mute pin widget amp left and right (no gain on this amp) */ |
3532 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, | 3775 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, |
3533 | /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */ | 3776 | /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & |
3777 | * Line In 2 = 0x03 | ||
3778 | */ | ||
3534 | /* unmute CD */ | 3779 | /* unmute CD */ |
3535 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, | 3780 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, |
3536 | /* unmute Line In */ | 3781 | /* unmute Line In */ |
@@ -3680,7 +3925,9 @@ static struct hda_verb alc260_acer_init_verbs[] = { | |||
3680 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | 3925 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
3681 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | 3926 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, |
3682 | 3927 | ||
3683 | /* Unmute Line-out pin widget amp left and right (no equiv mixer ctrl) */ | 3928 | /* Unmute Line-out pin widget amp left and right |
3929 | * (no equiv mixer ctrl) | ||
3930 | */ | ||
3684 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | 3931 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
3685 | /* Unmute mono pin widget amp output (no equiv mixer ctrl) */ | 3932 | /* Unmute mono pin widget amp output (no equiv mixer ctrl) */ |
3686 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | 3933 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
@@ -3719,6 +3966,55 @@ static struct hda_verb alc260_acer_init_verbs[] = { | |||
3719 | { } | 3966 | { } |
3720 | }; | 3967 | }; |
3721 | 3968 | ||
3969 | static struct hda_verb alc260_will_verbs[] = { | ||
3970 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
3971 | {0x0b, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
3972 | {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
3973 | {0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, | ||
3974 | {0x1a, AC_VERB_SET_COEF_INDEX, 0x07}, | ||
3975 | {0x1a, AC_VERB_SET_PROC_COEF, 0x3040}, | ||
3976 | {} | ||
3977 | }; | ||
3978 | |||
3979 | static struct hda_verb alc260_replacer_672v_verbs[] = { | ||
3980 | {0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, | ||
3981 | {0x1a, AC_VERB_SET_COEF_INDEX, 0x07}, | ||
3982 | {0x1a, AC_VERB_SET_PROC_COEF, 0x3050}, | ||
3983 | |||
3984 | {0x01, AC_VERB_SET_GPIO_MASK, 0x01}, | ||
3985 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, | ||
3986 | {0x01, AC_VERB_SET_GPIO_DATA, 0x00}, | ||
3987 | |||
3988 | {0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, | ||
3989 | {} | ||
3990 | }; | ||
3991 | |||
3992 | /* toggle speaker-output according to the hp-jack state */ | ||
3993 | static void alc260_replacer_672v_automute(struct hda_codec *codec) | ||
3994 | { | ||
3995 | unsigned int present; | ||
3996 | |||
3997 | /* speaker --> GPIO Data 0, hp or spdif --> GPIO data 1 */ | ||
3998 | present = snd_hda_codec_read(codec, 0x0f, 0, | ||
3999 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
4000 | if (present) { | ||
4001 | snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 1); | ||
4002 | snd_hda_codec_write(codec, 0x0f, 0, | ||
4003 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP); | ||
4004 | } else { | ||
4005 | snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 0); | ||
4006 | snd_hda_codec_write(codec, 0x0f, 0, | ||
4007 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); | ||
4008 | } | ||
4009 | } | ||
4010 | |||
4011 | static void alc260_replacer_672v_unsol_event(struct hda_codec *codec, | ||
4012 | unsigned int res) | ||
4013 | { | ||
4014 | if ((res >> 26) == ALC880_HP_EVENT) | ||
4015 | alc260_replacer_672v_automute(codec); | ||
4016 | } | ||
4017 | |||
3722 | /* Test configuration for debugging, modelled after the ALC880 test | 4018 | /* Test configuration for debugging, modelled after the ALC880 test |
3723 | * configuration. | 4019 | * configuration. |
3724 | */ | 4020 | */ |
@@ -3946,10 +4242,12 @@ static int alc260_add_playback_controls(struct alc_spec *spec, hda_nid_t nid, | |||
3946 | return 0; /* N/A */ | 4242 | return 0; /* N/A */ |
3947 | 4243 | ||
3948 | snprintf(name, sizeof(name), "%s Playback Volume", pfx); | 4244 | snprintf(name, sizeof(name), "%s Playback Volume", pfx); |
3949 | if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name, vol_val)) < 0) | 4245 | err = add_control(spec, ALC_CTL_WIDGET_VOL, name, vol_val); |
4246 | if (err < 0) | ||
3950 | return err; | 4247 | return err; |
3951 | snprintf(name, sizeof(name), "%s Playback Switch", pfx); | 4248 | snprintf(name, sizeof(name), "%s Playback Switch", pfx); |
3952 | if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, sw_val)) < 0) | 4249 | err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, sw_val); |
4250 | if (err < 0) | ||
3953 | return err; | 4251 | return err; |
3954 | return 1; | 4252 | return 1; |
3955 | } | 4253 | } |
@@ -3985,7 +4283,7 @@ static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
3985 | if (err < 0) | 4283 | if (err < 0) |
3986 | return err; | 4284 | return err; |
3987 | } | 4285 | } |
3988 | return 0; | 4286 | return 0; |
3989 | } | 4287 | } |
3990 | 4288 | ||
3991 | /* create playback/capture controls for input pins */ | 4289 | /* create playback/capture controls for input pins */ |
@@ -3999,20 +4297,24 @@ static int alc260_auto_create_analog_input_ctls(struct alc_spec *spec, | |||
3999 | if (cfg->input_pins[i] >= 0x12) { | 4297 | if (cfg->input_pins[i] >= 0x12) { |
4000 | idx = cfg->input_pins[i] - 0x12; | 4298 | idx = cfg->input_pins[i] - 0x12; |
4001 | err = new_analog_input(spec, cfg->input_pins[i], | 4299 | err = new_analog_input(spec, cfg->input_pins[i], |
4002 | auto_pin_cfg_labels[i], idx, 0x07); | 4300 | auto_pin_cfg_labels[i], idx, |
4301 | 0x07); | ||
4003 | if (err < 0) | 4302 | if (err < 0) |
4004 | return err; | 4303 | return err; |
4005 | imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; | 4304 | imux->items[imux->num_items].label = |
4305 | auto_pin_cfg_labels[i]; | ||
4006 | imux->items[imux->num_items].index = idx; | 4306 | imux->items[imux->num_items].index = idx; |
4007 | imux->num_items++; | 4307 | imux->num_items++; |
4008 | } | 4308 | } |
4009 | if ((cfg->input_pins[i] >= 0x0f) && (cfg->input_pins[i] <= 0x10)){ | 4309 | if (cfg->input_pins[i] >= 0x0f && cfg->input_pins[i] <= 0x10){ |
4010 | idx = cfg->input_pins[i] - 0x09; | 4310 | idx = cfg->input_pins[i] - 0x09; |
4011 | err = new_analog_input(spec, cfg->input_pins[i], | 4311 | err = new_analog_input(spec, cfg->input_pins[i], |
4012 | auto_pin_cfg_labels[i], idx, 0x07); | 4312 | auto_pin_cfg_labels[i], idx, |
4313 | 0x07); | ||
4013 | if (err < 0) | 4314 | if (err < 0) |
4014 | return err; | 4315 | return err; |
4015 | imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; | 4316 | imux->items[imux->num_items].label = |
4317 | auto_pin_cfg_labels[i]; | ||
4016 | imux->items[imux->num_items].index = idx; | 4318 | imux->items[imux->num_items].index = idx; |
4017 | imux->num_items++; | 4319 | imux->num_items++; |
4018 | } | 4320 | } |
@@ -4025,14 +4327,15 @@ static void alc260_auto_set_output_and_unmute(struct hda_codec *codec, | |||
4025 | int sel_idx) | 4327 | int sel_idx) |
4026 | { | 4328 | { |
4027 | /* set as output */ | 4329 | /* set as output */ |
4028 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type); | 4330 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, |
4029 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); | 4331 | pin_type); |
4332 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, | ||
4333 | AMP_OUT_UNMUTE); | ||
4030 | /* need the manual connection? */ | 4334 | /* need the manual connection? */ |
4031 | if (nid >= 0x12) { | 4335 | if (nid >= 0x12) { |
4032 | int idx = nid - 0x12; | 4336 | int idx = nid - 0x12; |
4033 | snd_hda_codec_write(codec, idx + 0x0b, 0, | 4337 | snd_hda_codec_write(codec, idx + 0x0b, 0, |
4034 | AC_VERB_SET_CONNECT_SEL, sel_idx); | 4338 | AC_VERB_SET_CONNECT_SEL, sel_idx); |
4035 | |||
4036 | } | 4339 | } |
4037 | } | 4340 | } |
4038 | 4341 | ||
@@ -4041,9 +4344,12 @@ static void alc260_auto_init_multi_out(struct hda_codec *codec) | |||
4041 | struct alc_spec *spec = codec->spec; | 4344 | struct alc_spec *spec = codec->spec; |
4042 | hda_nid_t nid; | 4345 | hda_nid_t nid; |
4043 | 4346 | ||
4044 | nid = spec->autocfg.line_out_pins[0]; | 4347 | alc_subsystem_id(codec, 0x10, 0x15, 0x0f); |
4045 | if (nid) | 4348 | nid = spec->autocfg.line_out_pins[0]; |
4046 | alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0); | 4349 | if (nid) { |
4350 | int pin_type = get_pin_type(spec->autocfg.line_out_type); | ||
4351 | alc260_auto_set_output_and_unmute(codec, nid, pin_type, 0); | ||
4352 | } | ||
4047 | 4353 | ||
4048 | nid = spec->autocfg.speaker_pins[0]; | 4354 | nid = spec->autocfg.speaker_pins[0]; |
4049 | if (nid) | 4355 | if (nid) |
@@ -4051,8 +4357,8 @@ static void alc260_auto_init_multi_out(struct hda_codec *codec) | |||
4051 | 4357 | ||
4052 | nid = spec->autocfg.hp_pins[0]; | 4358 | nid = spec->autocfg.hp_pins[0]; |
4053 | if (nid) | 4359 | if (nid) |
4054 | alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0); | 4360 | alc260_auto_set_output_and_unmute(codec, nid, PIN_HP, 0); |
4055 | } | 4361 | } |
4056 | 4362 | ||
4057 | #define ALC260_PIN_CD_NID 0x16 | 4363 | #define ALC260_PIN_CD_NID 0x16 |
4058 | static void alc260_auto_init_analog_input(struct hda_codec *codec) | 4364 | static void alc260_auto_init_analog_input(struct hda_codec *codec) |
@@ -4063,10 +4369,13 @@ static void alc260_auto_init_analog_input(struct hda_codec *codec) | |||
4063 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 4369 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
4064 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 4370 | hda_nid_t nid = spec->autocfg.input_pins[i]; |
4065 | if (nid >= 0x12) { | 4371 | if (nid >= 0x12) { |
4066 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | 4372 | snd_hda_codec_write(codec, nid, 0, |
4067 | i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN); | 4373 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
4374 | i <= AUTO_PIN_FRONT_MIC ? | ||
4375 | PIN_VREF80 : PIN_IN); | ||
4068 | if (nid != ALC260_PIN_CD_NID) | 4376 | if (nid != ALC260_PIN_CD_NID) |
4069 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, | 4377 | snd_hda_codec_write(codec, nid, 0, |
4378 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
4070 | AMP_OUT_MUTE); | 4379 | AMP_OUT_MUTE); |
4071 | } | 4380 | } |
4072 | } | 4381 | } |
@@ -4086,8 +4395,8 @@ static struct hda_verb alc260_volume_init_verbs[] = { | |||
4086 | 4395 | ||
4087 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | 4396 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback |
4088 | * mixer widget | 4397 | * mixer widget |
4089 | * Note: PASD motherboards uses the Line In 2 as the input for front panel | 4398 | * Note: PASD motherboards uses the Line In 2 as the input for |
4090 | * mic (mic 2) | 4399 | * front panel mic (mic 2) |
4091 | */ | 4400 | */ |
4092 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | 4401 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ |
4093 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 4402 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
@@ -4122,14 +4431,17 @@ static int alc260_parse_auto_config(struct hda_codec *codec) | |||
4122 | int err; | 4431 | int err; |
4123 | static hda_nid_t alc260_ignore[] = { 0x17, 0 }; | 4432 | static hda_nid_t alc260_ignore[] = { 0x17, 0 }; |
4124 | 4433 | ||
4125 | if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, | 4434 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, |
4126 | alc260_ignore)) < 0) | 4435 | alc260_ignore); |
4436 | if (err < 0) | ||
4127 | return err; | 4437 | return err; |
4128 | if ((err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0) | 4438 | err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg); |
4439 | if (err < 0) | ||
4129 | return err; | 4440 | return err; |
4130 | if (! spec->kctl_alloc) | 4441 | if (!spec->kctl_alloc) |
4131 | return 0; /* can't find valid BIOS pin config */ | 4442 | return 0; /* can't find valid BIOS pin config */ |
4132 | if ((err = alc260_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) | 4443 | err = alc260_auto_create_analog_input_ctls(spec, &spec->autocfg); |
4444 | if (err < 0) | ||
4133 | return err; | 4445 | return err; |
4134 | 4446 | ||
4135 | spec->multiout.max_channels = 2; | 4447 | spec->multiout.max_channels = 2; |
@@ -4177,6 +4489,8 @@ static const char *alc260_models[ALC260_MODEL_LAST] = { | |||
4177 | [ALC260_HP_3013] = "hp-3013", | 4489 | [ALC260_HP_3013] = "hp-3013", |
4178 | [ALC260_FUJITSU_S702X] = "fujitsu", | 4490 | [ALC260_FUJITSU_S702X] = "fujitsu", |
4179 | [ALC260_ACER] = "acer", | 4491 | [ALC260_ACER] = "acer", |
4492 | [ALC260_WILL] = "will", | ||
4493 | [ALC260_REPLACER_672V] = "replacer", | ||
4180 | #ifdef CONFIG_SND_DEBUG | 4494 | #ifdef CONFIG_SND_DEBUG |
4181 | [ALC260_TEST] = "test", | 4495 | [ALC260_TEST] = "test", |
4182 | #endif | 4496 | #endif |
@@ -4200,6 +4514,8 @@ static struct snd_pci_quirk alc260_cfg_tbl[] = { | |||
4200 | SND_PCI_QUIRK(0x104d, 0x81cd, "Sony VAIO", ALC260_BASIC), | 4514 | SND_PCI_QUIRK(0x104d, 0x81cd, "Sony VAIO", ALC260_BASIC), |
4201 | SND_PCI_QUIRK(0x10cf, 0x1326, "Fujitsu S702X", ALC260_FUJITSU_S702X), | 4515 | SND_PCI_QUIRK(0x10cf, 0x1326, "Fujitsu S702X", ALC260_FUJITSU_S702X), |
4202 | SND_PCI_QUIRK(0x152d, 0x0729, "CTL U553W", ALC260_BASIC), | 4516 | SND_PCI_QUIRK(0x152d, 0x0729, "CTL U553W", ALC260_BASIC), |
4517 | SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_WILL), | ||
4518 | SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_REPLACER_672V), | ||
4203 | {} | 4519 | {} |
4204 | }; | 4520 | }; |
4205 | 4521 | ||
@@ -4270,6 +4586,34 @@ static struct alc_config_preset alc260_presets[] = { | |||
4270 | .num_mux_defs = ARRAY_SIZE(alc260_acer_capture_sources), | 4586 | .num_mux_defs = ARRAY_SIZE(alc260_acer_capture_sources), |
4271 | .input_mux = alc260_acer_capture_sources, | 4587 | .input_mux = alc260_acer_capture_sources, |
4272 | }, | 4588 | }, |
4589 | [ALC260_WILL] = { | ||
4590 | .mixers = { alc260_will_mixer, | ||
4591 | alc260_capture_mixer }, | ||
4592 | .init_verbs = { alc260_init_verbs, alc260_will_verbs }, | ||
4593 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), | ||
4594 | .dac_nids = alc260_dac_nids, | ||
4595 | .num_adc_nids = ARRAY_SIZE(alc260_adc_nids), | ||
4596 | .adc_nids = alc260_adc_nids, | ||
4597 | .dig_out_nid = ALC260_DIGOUT_NID, | ||
4598 | .num_channel_mode = ARRAY_SIZE(alc260_modes), | ||
4599 | .channel_mode = alc260_modes, | ||
4600 | .input_mux = &alc260_capture_source, | ||
4601 | }, | ||
4602 | [ALC260_REPLACER_672V] = { | ||
4603 | .mixers = { alc260_replacer_672v_mixer, | ||
4604 | alc260_capture_mixer }, | ||
4605 | .init_verbs = { alc260_init_verbs, alc260_replacer_672v_verbs }, | ||
4606 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), | ||
4607 | .dac_nids = alc260_dac_nids, | ||
4608 | .num_adc_nids = ARRAY_SIZE(alc260_adc_nids), | ||
4609 | .adc_nids = alc260_adc_nids, | ||
4610 | .dig_out_nid = ALC260_DIGOUT_NID, | ||
4611 | .num_channel_mode = ARRAY_SIZE(alc260_modes), | ||
4612 | .channel_mode = alc260_modes, | ||
4613 | .input_mux = &alc260_capture_source, | ||
4614 | .unsol_event = alc260_replacer_672v_unsol_event, | ||
4615 | .init_hook = alc260_replacer_672v_automute, | ||
4616 | }, | ||
4273 | #ifdef CONFIG_SND_DEBUG | 4617 | #ifdef CONFIG_SND_DEBUG |
4274 | [ALC260_TEST] = { | 4618 | [ALC260_TEST] = { |
4275 | .mixers = { alc260_test_mixer, | 4619 | .mixers = { alc260_test_mixer, |
@@ -4313,7 +4657,7 @@ static int patch_alc260(struct hda_codec *codec) | |||
4313 | if (err < 0) { | 4657 | if (err < 0) { |
4314 | alc_free(codec); | 4658 | alc_free(codec); |
4315 | return err; | 4659 | return err; |
4316 | } else if (! err) { | 4660 | } else if (!err) { |
4317 | printk(KERN_INFO | 4661 | printk(KERN_INFO |
4318 | "hda_codec: Cannot set up configuration " | 4662 | "hda_codec: Cannot set up configuration " |
4319 | "from BIOS. Using base mode...\n"); | 4663 | "from BIOS. Using base mode...\n"); |
@@ -4382,7 +4726,8 @@ static struct hda_input_mux alc882_capture_source = { | |||
4382 | #define alc882_mux_enum_info alc_mux_enum_info | 4726 | #define alc882_mux_enum_info alc_mux_enum_info |
4383 | #define alc882_mux_enum_get alc_mux_enum_get | 4727 | #define alc882_mux_enum_get alc_mux_enum_get |
4384 | 4728 | ||
4385 | static int alc882_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 4729 | static int alc882_mux_enum_put(struct snd_kcontrol *kcontrol, |
4730 | struct snd_ctl_elem_value *ucontrol) | ||
4386 | { | 4731 | { |
4387 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 4732 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
4388 | struct alc_spec *spec = codec->spec; | 4733 | struct alc_spec *spec = codec->spec; |
@@ -4396,7 +4741,7 @@ static int alc882_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ele | |||
4396 | idx = ucontrol->value.enumerated.item[0]; | 4741 | idx = ucontrol->value.enumerated.item[0]; |
4397 | if (idx >= imux->num_items) | 4742 | if (idx >= imux->num_items) |
4398 | idx = imux->num_items - 1; | 4743 | idx = imux->num_items - 1; |
4399 | if (*cur_val == idx && ! codec->in_resume) | 4744 | if (*cur_val == idx && !codec->in_resume) |
4400 | return 0; | 4745 | return 0; |
4401 | for (i = 0; i < imux->num_items; i++) { | 4746 | for (i = 0; i < imux->num_items; i++) { |
4402 | unsigned int v = (i == idx) ? 0x7000 : 0x7080; | 4747 | unsigned int v = (i == idx) ? 0x7000 : 0x7080; |
@@ -4464,6 +4809,21 @@ static struct snd_kcontrol_new alc882_base_mixer[] = { | |||
4464 | { } /* end */ | 4809 | { } /* end */ |
4465 | }; | 4810 | }; |
4466 | 4811 | ||
4812 | static struct snd_kcontrol_new alc882_w2jc_mixer[] = { | ||
4813 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
4814 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | ||
4815 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
4816 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
4817 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | ||
4818 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | ||
4819 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
4820 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | ||
4821 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
4822 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
4823 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
4824 | { } /* end */ | ||
4825 | }; | ||
4826 | |||
4467 | static struct snd_kcontrol_new alc882_chmode_mixer[] = { | 4827 | static struct snd_kcontrol_new alc882_chmode_mixer[] = { |
4468 | { | 4828 | { |
4469 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 4829 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -4559,7 +4919,7 @@ static struct hda_verb alc882_eapd_verbs[] = { | |||
4559 | /* change to EAPD mode */ | 4919 | /* change to EAPD mode */ |
4560 | {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, | 4920 | {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, |
4561 | {0x20, AC_VERB_SET_PROC_COEF, 0x3060}, | 4921 | {0x20, AC_VERB_SET_PROC_COEF, 0x3060}, |
4562 | { } | 4922 | { } |
4563 | }; | 4923 | }; |
4564 | 4924 | ||
4565 | /* Mac Pro test */ | 4925 | /* Mac Pro test */ |
@@ -4624,6 +4984,7 @@ static struct hda_verb alc882_macpro_init_verbs[] = { | |||
4624 | 4984 | ||
4625 | { } | 4985 | { } |
4626 | }; | 4986 | }; |
4987 | |||
4627 | static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted) | 4988 | static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted) |
4628 | { | 4989 | { |
4629 | unsigned int gpiostate, gpiomask, gpiodir; | 4990 | unsigned int gpiostate, gpiomask, gpiodir; |
@@ -4672,8 +5033,8 @@ static struct hda_verb alc882_auto_init_verbs[] = { | |||
4672 | 5033 | ||
4673 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | 5034 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback |
4674 | * mixer widget | 5035 | * mixer widget |
4675 | * Note: PASD motherboards uses the Line In 2 as the input for front panel | 5036 | * Note: PASD motherboards uses the Line In 2 as the input for |
4676 | * mic (mic 2) | 5037 | * front panel mic (mic 2) |
4677 | */ | 5038 | */ |
4678 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | 5039 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ |
4679 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 5040 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
@@ -4782,6 +5143,7 @@ static const char *alc882_models[ALC882_MODEL_LAST] = { | |||
4782 | [ALC882_3ST_DIG] = "3stack-dig", | 5143 | [ALC882_3ST_DIG] = "3stack-dig", |
4783 | [ALC882_6ST_DIG] = "6stack-dig", | 5144 | [ALC882_6ST_DIG] = "6stack-dig", |
4784 | [ALC882_ARIMA] = "arima", | 5145 | [ALC882_ARIMA] = "arima", |
5146 | [ALC882_W2JC] = "w2jc", | ||
4785 | [ALC885_MACPRO] = "macpro", | 5147 | [ALC885_MACPRO] = "macpro", |
4786 | [ALC882_AUTO] = "auto", | 5148 | [ALC882_AUTO] = "auto", |
4787 | }; | 5149 | }; |
@@ -4792,6 +5154,7 @@ static struct snd_pci_quirk alc882_cfg_tbl[] = { | |||
4792 | SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC882_6ST_DIG), | 5154 | SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC882_6ST_DIG), |
4793 | SND_PCI_QUIRK(0x161f, 0x2054, "Arima W820", ALC882_ARIMA), | 5155 | SND_PCI_QUIRK(0x161f, 0x2054, "Arima W820", ALC882_ARIMA), |
4794 | SND_PCI_QUIRK(0x1043, 0x81d8, "Asus P5WD", ALC882_6ST_DIG), | 5156 | SND_PCI_QUIRK(0x1043, 0x81d8, "Asus P5WD", ALC882_6ST_DIG), |
5157 | SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_W2JC), | ||
4795 | {} | 5158 | {} |
4796 | }; | 5159 | }; |
4797 | 5160 | ||
@@ -4828,6 +5191,18 @@ static struct alc_config_preset alc882_presets[] = { | |||
4828 | .channel_mode = alc882_sixstack_modes, | 5191 | .channel_mode = alc882_sixstack_modes, |
4829 | .input_mux = &alc882_capture_source, | 5192 | .input_mux = &alc882_capture_source, |
4830 | }, | 5193 | }, |
5194 | [ALC882_W2JC] = { | ||
5195 | .mixers = { alc882_w2jc_mixer, alc882_chmode_mixer }, | ||
5196 | .init_verbs = { alc882_init_verbs, alc882_eapd_verbs, | ||
5197 | alc880_gpio1_init_verbs }, | ||
5198 | .num_dacs = ARRAY_SIZE(alc882_dac_nids), | ||
5199 | .dac_nids = alc882_dac_nids, | ||
5200 | .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), | ||
5201 | .channel_mode = alc880_threestack_modes, | ||
5202 | .need_dac_fix = 1, | ||
5203 | .input_mux = &alc882_capture_source, | ||
5204 | .dig_out_nid = ALC882_DIGOUT_NID, | ||
5205 | }, | ||
4831 | [ALC885_MACPRO] = { | 5206 | [ALC885_MACPRO] = { |
4832 | .mixers = { alc882_macpro_mixer }, | 5207 | .mixers = { alc882_macpro_mixer }, |
4833 | .init_verbs = { alc882_macpro_init_verbs }, | 5208 | .init_verbs = { alc882_macpro_init_verbs }, |
@@ -4851,15 +5226,17 @@ static void alc882_auto_set_output_and_unmute(struct hda_codec *codec, | |||
4851 | { | 5226 | { |
4852 | /* set as output */ | 5227 | /* set as output */ |
4853 | struct alc_spec *spec = codec->spec; | 5228 | struct alc_spec *spec = codec->spec; |
4854 | int idx; | 5229 | int idx; |
4855 | 5230 | ||
4856 | if (spec->multiout.dac_nids[dac_idx] == 0x25) | 5231 | if (spec->multiout.dac_nids[dac_idx] == 0x25) |
4857 | idx = 4; | 5232 | idx = 4; |
4858 | else | 5233 | else |
4859 | idx = spec->multiout.dac_nids[dac_idx] - 2; | 5234 | idx = spec->multiout.dac_nids[dac_idx] - 2; |
4860 | 5235 | ||
4861 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type); | 5236 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, |
4862 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); | 5237 | pin_type); |
5238 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, | ||
5239 | AMP_OUT_UNMUTE); | ||
4863 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx); | 5240 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx); |
4864 | 5241 | ||
4865 | } | 5242 | } |
@@ -4869,10 +5246,13 @@ static void alc882_auto_init_multi_out(struct hda_codec *codec) | |||
4869 | struct alc_spec *spec = codec->spec; | 5246 | struct alc_spec *spec = codec->spec; |
4870 | int i; | 5247 | int i; |
4871 | 5248 | ||
5249 | alc_subsystem_id(codec, 0x15, 0x1b, 0x14); | ||
4872 | for (i = 0; i <= HDA_SIDE; i++) { | 5250 | for (i = 0; i <= HDA_SIDE; i++) { |
4873 | hda_nid_t nid = spec->autocfg.line_out_pins[i]; | 5251 | hda_nid_t nid = spec->autocfg.line_out_pins[i]; |
5252 | int pin_type = get_pin_type(spec->autocfg.line_out_type); | ||
4874 | if (nid) | 5253 | if (nid) |
4875 | alc882_auto_set_output_and_unmute(codec, nid, PIN_OUT, i); | 5254 | alc882_auto_set_output_and_unmute(codec, nid, pin_type, |
5255 | i); | ||
4876 | } | 5256 | } |
4877 | } | 5257 | } |
4878 | 5258 | ||
@@ -4883,7 +5263,8 @@ static void alc882_auto_init_hp_out(struct hda_codec *codec) | |||
4883 | 5263 | ||
4884 | pin = spec->autocfg.hp_pins[0]; | 5264 | pin = spec->autocfg.hp_pins[0]; |
4885 | if (pin) /* connect to front */ | 5265 | if (pin) /* connect to front */ |
4886 | alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); /* use dac 0 */ | 5266 | /* use dac 0 */ |
5267 | alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); | ||
4887 | } | 5268 | } |
4888 | 5269 | ||
4889 | #define alc882_is_input_pin(nid) alc880_is_input_pin(nid) | 5270 | #define alc882_is_input_pin(nid) alc880_is_input_pin(nid) |
@@ -4897,10 +5278,13 @@ static void alc882_auto_init_analog_input(struct hda_codec *codec) | |||
4897 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 5278 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
4898 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 5279 | hda_nid_t nid = spec->autocfg.input_pins[i]; |
4899 | if (alc882_is_input_pin(nid)) { | 5280 | if (alc882_is_input_pin(nid)) { |
4900 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | 5281 | snd_hda_codec_write(codec, nid, 0, |
4901 | i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN); | 5282 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
5283 | i <= AUTO_PIN_FRONT_MIC ? | ||
5284 | PIN_VREF80 : PIN_IN); | ||
4902 | if (nid != ALC882_PIN_CD_NID) | 5285 | if (nid != ALC882_PIN_CD_NID) |
4903 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, | 5286 | snd_hda_codec_write(codec, nid, 0, |
5287 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
4904 | AMP_OUT_MUTE); | 5288 | AMP_OUT_MUTE); |
4905 | } | 5289 | } |
4906 | } | 5290 | } |
@@ -4962,7 +5346,7 @@ static int patch_alc882(struct hda_codec *codec) | |||
4962 | if (err < 0) { | 5346 | if (err < 0) { |
4963 | alc_free(codec); | 5347 | alc_free(codec); |
4964 | return err; | 5348 | return err; |
4965 | } else if (! err) { | 5349 | } else if (!err) { |
4966 | printk(KERN_INFO | 5350 | printk(KERN_INFO |
4967 | "hda_codec: Cannot set up configuration " | 5351 | "hda_codec: Cannot set up configuration " |
4968 | "from BIOS. Using base mode...\n"); | 5352 | "from BIOS. Using base mode...\n"); |
@@ -4986,14 +5370,16 @@ static int patch_alc882(struct hda_codec *codec) | |||
4986 | spec->stream_digital_playback = &alc882_pcm_digital_playback; | 5370 | spec->stream_digital_playback = &alc882_pcm_digital_playback; |
4987 | spec->stream_digital_capture = &alc882_pcm_digital_capture; | 5371 | spec->stream_digital_capture = &alc882_pcm_digital_capture; |
4988 | 5372 | ||
4989 | if (! spec->adc_nids && spec->input_mux) { | 5373 | if (!spec->adc_nids && spec->input_mux) { |
4990 | /* check whether NID 0x07 is valid */ | 5374 | /* check whether NID 0x07 is valid */ |
4991 | unsigned int wcap = get_wcaps(codec, 0x07); | 5375 | unsigned int wcap = get_wcaps(codec, 0x07); |
4992 | wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */ | 5376 | /* get type */ |
5377 | wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; | ||
4993 | if (wcap != AC_WID_AUD_IN) { | 5378 | if (wcap != AC_WID_AUD_IN) { |
4994 | spec->adc_nids = alc882_adc_nids_alt; | 5379 | spec->adc_nids = alc882_adc_nids_alt; |
4995 | spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids_alt); | 5380 | spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids_alt); |
4996 | spec->mixers[spec->num_mixers] = alc882_capture_alt_mixer; | 5381 | spec->mixers[spec->num_mixers] = |
5382 | alc882_capture_alt_mixer; | ||
4997 | spec->num_mixers++; | 5383 | spec->num_mixers++; |
4998 | } else { | 5384 | } else { |
4999 | spec->adc_nids = alc882_adc_nids; | 5385 | spec->adc_nids = alc882_adc_nids; |
@@ -5033,6 +5419,7 @@ static hda_nid_t alc883_adc_nids[2] = { | |||
5033 | /* ADC1-2 */ | 5419 | /* ADC1-2 */ |
5034 | 0x08, 0x09, | 5420 | 0x08, 0x09, |
5035 | }; | 5421 | }; |
5422 | |||
5036 | /* input MUX */ | 5423 | /* input MUX */ |
5037 | /* FIXME: should be a matrix-type input source selection */ | 5424 | /* FIXME: should be a matrix-type input source selection */ |
5038 | 5425 | ||
@@ -5045,6 +5432,15 @@ static struct hda_input_mux alc883_capture_source = { | |||
5045 | { "CD", 0x4 }, | 5432 | { "CD", 0x4 }, |
5046 | }, | 5433 | }, |
5047 | }; | 5434 | }; |
5435 | |||
5436 | static struct hda_input_mux alc883_lenovo_101e_capture_source = { | ||
5437 | .num_items = 2, | ||
5438 | .items = { | ||
5439 | { "Mic", 0x1 }, | ||
5440 | { "Line", 0x2 }, | ||
5441 | }, | ||
5442 | }; | ||
5443 | |||
5048 | #define alc883_mux_enum_info alc_mux_enum_info | 5444 | #define alc883_mux_enum_info alc_mux_enum_info |
5049 | #define alc883_mux_enum_get alc_mux_enum_get | 5445 | #define alc883_mux_enum_get alc_mux_enum_get |
5050 | 5446 | ||
@@ -5063,7 +5459,7 @@ static int alc883_mux_enum_put(struct snd_kcontrol *kcontrol, | |||
5063 | idx = ucontrol->value.enumerated.item[0]; | 5459 | idx = ucontrol->value.enumerated.item[0]; |
5064 | if (idx >= imux->num_items) | 5460 | if (idx >= imux->num_items) |
5065 | idx = imux->num_items - 1; | 5461 | idx = imux->num_items - 1; |
5066 | if (*cur_val == idx && ! codec->in_resume) | 5462 | if (*cur_val == idx && !codec->in_resume) |
5067 | return 0; | 5463 | return 0; |
5068 | for (i = 0; i < imux->num_items; i++) { | 5464 | for (i = 0; i < imux->num_items; i++) { |
5069 | unsigned int v = (i == idx) ? 0x7000 : 0x7080; | 5465 | unsigned int v = (i == idx) ? 0x7000 : 0x7080; |
@@ -5073,6 +5469,7 @@ static int alc883_mux_enum_put(struct snd_kcontrol *kcontrol, | |||
5073 | *cur_val = idx; | 5469 | *cur_val = idx; |
5074 | return 1; | 5470 | return 1; |
5075 | } | 5471 | } |
5472 | |||
5076 | /* | 5473 | /* |
5077 | * 2ch mode | 5474 | * 2ch mode |
5078 | */ | 5475 | */ |
@@ -5325,7 +5722,7 @@ static struct snd_kcontrol_new alc883_tagra_mixer[] = { | |||
5325 | .put = alc883_mux_enum_put, | 5722 | .put = alc883_mux_enum_put, |
5326 | }, | 5723 | }, |
5327 | { } /* end */ | 5724 | { } /* end */ |
5328 | }; | 5725 | }; |
5329 | 5726 | ||
5330 | static struct snd_kcontrol_new alc883_tagra_2ch_mixer[] = { | 5727 | static struct snd_kcontrol_new alc883_tagra_2ch_mixer[] = { |
5331 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | 5728 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), |
@@ -5350,7 +5747,30 @@ static struct snd_kcontrol_new alc883_tagra_2ch_mixer[] = { | |||
5350 | .put = alc883_mux_enum_put, | 5747 | .put = alc883_mux_enum_put, |
5351 | }, | 5748 | }, |
5352 | { } /* end */ | 5749 | { } /* end */ |
5353 | }; | 5750 | }; |
5751 | |||
5752 | static struct snd_kcontrol_new alc883_lenovo_101e_2ch_mixer[] = { | ||
5753 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
5754 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | ||
5755 | HDA_CODEC_VOLUME("iSpeaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
5756 | HDA_BIND_MUTE("iSpeaker Playback Switch", 0x0d, 2, HDA_INPUT), | ||
5757 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | ||
5758 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | ||
5759 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | ||
5760 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | ||
5761 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
5762 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
5763 | { | ||
5764 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
5765 | /* .name = "Capture Source", */ | ||
5766 | .name = "Input Source", | ||
5767 | .count = 1, | ||
5768 | .info = alc883_mux_enum_info, | ||
5769 | .get = alc883_mux_enum_get, | ||
5770 | .put = alc883_mux_enum_put, | ||
5771 | }, | ||
5772 | { } /* end */ | ||
5773 | }; | ||
5354 | 5774 | ||
5355 | static struct snd_kcontrol_new alc883_chmode_mixer[] = { | 5775 | static struct snd_kcontrol_new alc883_chmode_mixer[] = { |
5356 | { | 5776 | { |
@@ -5452,10 +5872,17 @@ static struct hda_verb alc883_tagra_verbs[] = { | |||
5452 | {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ | 5872 | {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ |
5453 | 5873 | ||
5454 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, | 5874 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, |
5455 | {0x01, AC_VERB_SET_GPIO_MASK, 0x03}, | 5875 | {0x01, AC_VERB_SET_GPIO_MASK, 0x03}, |
5456 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03}, | 5876 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03}, |
5457 | {0x01, AC_VERB_SET_GPIO_DATA, 0x03}, | 5877 | {0x01, AC_VERB_SET_GPIO_DATA, 0x03}, |
5878 | |||
5879 | { } /* end */ | ||
5880 | }; | ||
5458 | 5881 | ||
5882 | static struct hda_verb alc883_lenovo_101e_verbs[] = { | ||
5883 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
5884 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_FRONT_EVENT|AC_USRSP_EN}, | ||
5885 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT|AC_USRSP_EN}, | ||
5459 | { } /* end */ | 5886 | { } /* end */ |
5460 | }; | 5887 | }; |
5461 | 5888 | ||
@@ -5463,14 +5890,17 @@ static struct hda_verb alc883_tagra_verbs[] = { | |||
5463 | static void alc883_tagra_automute(struct hda_codec *codec) | 5890 | static void alc883_tagra_automute(struct hda_codec *codec) |
5464 | { | 5891 | { |
5465 | unsigned int present; | 5892 | unsigned int present; |
5893 | unsigned char bits; | ||
5466 | 5894 | ||
5467 | present = snd_hda_codec_read(codec, 0x14, 0, | 5895 | present = snd_hda_codec_read(codec, 0x14, 0, |
5468 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 5896 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
5897 | bits = present ? 0x80 : 0; | ||
5469 | snd_hda_codec_amp_update(codec, 0x1b, 0, HDA_OUTPUT, 0, | 5898 | snd_hda_codec_amp_update(codec, 0x1b, 0, HDA_OUTPUT, 0, |
5470 | 0x80, present ? 0x80 : 0); | 5899 | 0x80, bits); |
5471 | snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0, | 5900 | snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0, |
5472 | 0x80, present ? 0x80 : 0); | 5901 | 0x80, bits); |
5473 | snd_hda_codec_write(codec, 1, 0, AC_VERB_SET_GPIO_DATA, present ? 1 : 3); | 5902 | snd_hda_codec_write(codec, 1, 0, AC_VERB_SET_GPIO_DATA, |
5903 | present ? 1 : 3); | ||
5474 | } | 5904 | } |
5475 | 5905 | ||
5476 | static void alc883_tagra_unsol_event(struct hda_codec *codec, unsigned int res) | 5906 | static void alc883_tagra_unsol_event(struct hda_codec *codec, unsigned int res) |
@@ -5479,6 +5909,47 @@ static void alc883_tagra_unsol_event(struct hda_codec *codec, unsigned int res) | |||
5479 | alc883_tagra_automute(codec); | 5909 | alc883_tagra_automute(codec); |
5480 | } | 5910 | } |
5481 | 5911 | ||
5912 | static void alc883_lenovo_101e_ispeaker_automute(struct hda_codec *codec) | ||
5913 | { | ||
5914 | unsigned int present; | ||
5915 | unsigned char bits; | ||
5916 | |||
5917 | present = snd_hda_codec_read(codec, 0x14, 0, | ||
5918 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
5919 | bits = present ? 0x80 : 0; | ||
5920 | snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, | ||
5921 | 0x80, bits); | ||
5922 | snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, | ||
5923 | 0x80, bits); | ||
5924 | } | ||
5925 | |||
5926 | static void alc883_lenovo_101e_all_automute(struct hda_codec *codec) | ||
5927 | { | ||
5928 | unsigned int present; | ||
5929 | unsigned char bits; | ||
5930 | |||
5931 | present = snd_hda_codec_read(codec, 0x1b, 0, | ||
5932 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
5933 | bits = present ? 0x80 : 0; | ||
5934 | snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, | ||
5935 | 0x80, bits); | ||
5936 | snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, | ||
5937 | 0x80, bits); | ||
5938 | snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, | ||
5939 | 0x80, bits); | ||
5940 | snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, | ||
5941 | 0x80, bits); | ||
5942 | } | ||
5943 | |||
5944 | static void alc883_lenovo_101e_unsol_event(struct hda_codec *codec, | ||
5945 | unsigned int res) | ||
5946 | { | ||
5947 | if ((res >> 26) == ALC880_HP_EVENT) | ||
5948 | alc883_lenovo_101e_all_automute(codec); | ||
5949 | if ((res >> 26) == ALC880_FRONT_EVENT) | ||
5950 | alc883_lenovo_101e_ispeaker_automute(codec); | ||
5951 | } | ||
5952 | |||
5482 | /* | 5953 | /* |
5483 | * generic initialization of ADC, input mixers and output mixers | 5954 | * generic initialization of ADC, input mixers and output mixers |
5484 | */ | 5955 | */ |
@@ -5493,8 +5964,8 @@ static struct hda_verb alc883_auto_init_verbs[] = { | |||
5493 | 5964 | ||
5494 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | 5965 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback |
5495 | * mixer widget | 5966 | * mixer widget |
5496 | * Note: PASD motherboards uses the Line In 2 as the input for front panel | 5967 | * Note: PASD motherboards uses the Line In 2 as the input for |
5497 | * mic (mic 2) | 5968 | * front panel mic (mic 2) |
5498 | */ | 5969 | */ |
5499 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | 5970 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ |
5500 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 5971 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
@@ -5530,13 +6001,13 @@ static struct hda_verb alc883_auto_init_verbs[] = { | |||
5530 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 6001 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
5531 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 6002 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
5532 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 6003 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, |
5533 | //{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 6004 | /* {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, */ |
5534 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 6005 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, |
5535 | /* Input mixer2 */ | 6006 | /* Input mixer2 */ |
5536 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 6007 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
5537 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 6008 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
5538 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 6009 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, |
5539 | //{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 6010 | /* {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, */ |
5540 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 6011 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, |
5541 | 6012 | ||
5542 | { } | 6013 | { } |
@@ -5584,6 +6055,7 @@ static const char *alc883_models[ALC883_MODEL_LAST] = { | |||
5584 | [ALC883_ACER] = "acer", | 6055 | [ALC883_ACER] = "acer", |
5585 | [ALC883_MEDION] = "medion", | 6056 | [ALC883_MEDION] = "medion", |
5586 | [ALC883_LAPTOP_EAPD] = "laptop-eapd", | 6057 | [ALC883_LAPTOP_EAPD] = "laptop-eapd", |
6058 | [ALC883_LENOVO_101E_2ch] = "lenovo-101e", | ||
5587 | [ALC883_AUTO] = "auto", | 6059 | [ALC883_AUTO] = "auto", |
5588 | }; | 6060 | }; |
5589 | 6061 | ||
@@ -5592,6 +6064,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { | |||
5592 | SND_PCI_QUIRK(0x108e, 0x534d, NULL, ALC883_3ST_6ch), | 6064 | SND_PCI_QUIRK(0x108e, 0x534d, NULL, ALC883_3ST_6ch), |
5593 | SND_PCI_QUIRK(0x1558, 0, "Clevo laptop", ALC883_LAPTOP_EAPD), | 6065 | SND_PCI_QUIRK(0x1558, 0, "Clevo laptop", ALC883_LAPTOP_EAPD), |
5594 | SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC883_6ST_DIG), | 6066 | SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC883_6ST_DIG), |
6067 | SND_PCI_QUIRK(0x1458, 0xa002, "MSI", ALC883_6ST_DIG), | ||
5595 | SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC883_6ST_DIG), | 6068 | SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC883_6ST_DIG), |
5596 | SND_PCI_QUIRK(0x1462, 0x7187, "MSI", ALC883_6ST_DIG), | 6069 | SND_PCI_QUIRK(0x1462, 0x7187, "MSI", ALC883_6ST_DIG), |
5597 | SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG), | 6070 | SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG), |
@@ -5609,6 +6082,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { | |||
5609 | SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION), | 6082 | SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION), |
5610 | SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC883_LAPTOP_EAPD), | 6083 | SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC883_LAPTOP_EAPD), |
5611 | SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC883_3ST_6ch), | 6084 | SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC883_3ST_6ch), |
6085 | SND_PCI_QUIRK(0x17aa, 0x101e, "lenovo 101e", ALC883_LENOVO_101E_2ch), | ||
5612 | {} | 6086 | {} |
5613 | }; | 6087 | }; |
5614 | 6088 | ||
@@ -5639,7 +6113,7 @@ static struct alc_config_preset alc883_presets[] = { | |||
5639 | .channel_mode = alc883_3ST_6ch_modes, | 6113 | .channel_mode = alc883_3ST_6ch_modes, |
5640 | .need_dac_fix = 1, | 6114 | .need_dac_fix = 1, |
5641 | .input_mux = &alc883_capture_source, | 6115 | .input_mux = &alc883_capture_source, |
5642 | }, | 6116 | }, |
5643 | [ALC883_3ST_6ch] = { | 6117 | [ALC883_3ST_6ch] = { |
5644 | .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer }, | 6118 | .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer }, |
5645 | .init_verbs = { alc883_init_verbs }, | 6119 | .init_verbs = { alc883_init_verbs }, |
@@ -5651,7 +6125,7 @@ static struct alc_config_preset alc883_presets[] = { | |||
5651 | .channel_mode = alc883_3ST_6ch_modes, | 6125 | .channel_mode = alc883_3ST_6ch_modes, |
5652 | .need_dac_fix = 1, | 6126 | .need_dac_fix = 1, |
5653 | .input_mux = &alc883_capture_source, | 6127 | .input_mux = &alc883_capture_source, |
5654 | }, | 6128 | }, |
5655 | [ALC883_6ST_DIG] = { | 6129 | [ALC883_6ST_DIG] = { |
5656 | .mixers = { alc883_base_mixer, alc883_chmode_mixer }, | 6130 | .mixers = { alc883_base_mixer, alc883_chmode_mixer }, |
5657 | .init_verbs = { alc883_init_verbs }, | 6131 | .init_verbs = { alc883_init_verbs }, |
@@ -5749,6 +6223,19 @@ static struct alc_config_preset alc883_presets[] = { | |||
5749 | .channel_mode = alc883_3ST_2ch_modes, | 6223 | .channel_mode = alc883_3ST_2ch_modes, |
5750 | .input_mux = &alc883_capture_source, | 6224 | .input_mux = &alc883_capture_source, |
5751 | }, | 6225 | }, |
6226 | [ALC883_LENOVO_101E_2ch] = { | ||
6227 | .mixers = { alc883_lenovo_101e_2ch_mixer}, | ||
6228 | .init_verbs = { alc883_init_verbs, alc883_lenovo_101e_verbs}, | ||
6229 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), | ||
6230 | .dac_nids = alc883_dac_nids, | ||
6231 | .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), | ||
6232 | .adc_nids = alc883_adc_nids, | ||
6233 | .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), | ||
6234 | .channel_mode = alc883_3ST_2ch_modes, | ||
6235 | .input_mux = &alc883_lenovo_101e_capture_source, | ||
6236 | .unsol_event = alc883_lenovo_101e_unsol_event, | ||
6237 | .init_hook = alc883_lenovo_101e_all_automute, | ||
6238 | }, | ||
5752 | }; | 6239 | }; |
5753 | 6240 | ||
5754 | 6241 | ||
@@ -5761,8 +6248,8 @@ static void alc883_auto_set_output_and_unmute(struct hda_codec *codec, | |||
5761 | { | 6248 | { |
5762 | /* set as output */ | 6249 | /* set as output */ |
5763 | struct alc_spec *spec = codec->spec; | 6250 | struct alc_spec *spec = codec->spec; |
5764 | int idx; | 6251 | int idx; |
5765 | 6252 | ||
5766 | if (spec->multiout.dac_nids[dac_idx] == 0x25) | 6253 | if (spec->multiout.dac_nids[dac_idx] == 0x25) |
5767 | idx = 4; | 6254 | idx = 4; |
5768 | else | 6255 | else |
@@ -5781,10 +6268,13 @@ static void alc883_auto_init_multi_out(struct hda_codec *codec) | |||
5781 | struct alc_spec *spec = codec->spec; | 6268 | struct alc_spec *spec = codec->spec; |
5782 | int i; | 6269 | int i; |
5783 | 6270 | ||
6271 | alc_subsystem_id(codec, 0x15, 0x1b, 0x14); | ||
5784 | for (i = 0; i <= HDA_SIDE; i++) { | 6272 | for (i = 0; i <= HDA_SIDE; i++) { |
5785 | hda_nid_t nid = spec->autocfg.line_out_pins[i]; | 6273 | hda_nid_t nid = spec->autocfg.line_out_pins[i]; |
6274 | int pin_type = get_pin_type(spec->autocfg.line_out_type); | ||
5786 | if (nid) | 6275 | if (nid) |
5787 | alc883_auto_set_output_and_unmute(codec, nid, PIN_OUT, i); | 6276 | alc883_auto_set_output_and_unmute(codec, nid, pin_type, |
6277 | i); | ||
5788 | } | 6278 | } |
5789 | } | 6279 | } |
5790 | 6280 | ||
@@ -5833,8 +6323,8 @@ static int alc883_parse_auto_config(struct hda_codec *codec) | |||
5833 | else if (err > 0) | 6323 | else if (err > 0) |
5834 | /* hack - override the init verbs */ | 6324 | /* hack - override the init verbs */ |
5835 | spec->init_verbs[0] = alc883_auto_init_verbs; | 6325 | spec->init_verbs[0] = alc883_auto_init_verbs; |
5836 | spec->mixers[spec->num_mixers] = alc883_capture_mixer; | 6326 | spec->mixers[spec->num_mixers] = alc883_capture_mixer; |
5837 | spec->num_mixers++; | 6327 | spec->num_mixers++; |
5838 | return err; | 6328 | return err; |
5839 | } | 6329 | } |
5840 | 6330 | ||
@@ -5872,7 +6362,7 @@ static int patch_alc883(struct hda_codec *codec) | |||
5872 | if (err < 0) { | 6362 | if (err < 0) { |
5873 | alc_free(codec); | 6363 | alc_free(codec); |
5874 | return err; | 6364 | return err; |
5875 | } else if (! err) { | 6365 | } else if (!err) { |
5876 | printk(KERN_INFO | 6366 | printk(KERN_INFO |
5877 | "hda_codec: Cannot set up configuration " | 6367 | "hda_codec: Cannot set up configuration " |
5878 | "from BIOS. Using base mode...\n"); | 6368 | "from BIOS. Using base mode...\n"); |
@@ -5891,7 +6381,7 @@ static int patch_alc883(struct hda_codec *codec) | |||
5891 | spec->stream_digital_playback = &alc883_pcm_digital_playback; | 6381 | spec->stream_digital_playback = &alc883_pcm_digital_playback; |
5892 | spec->stream_digital_capture = &alc883_pcm_digital_capture; | 6382 | spec->stream_digital_capture = &alc883_pcm_digital_capture; |
5893 | 6383 | ||
5894 | if (! spec->adc_nids && spec->input_mux) { | 6384 | if (!spec->adc_nids && spec->input_mux) { |
5895 | spec->adc_nids = alc883_adc_nids; | 6385 | spec->adc_nids = alc883_adc_nids; |
5896 | spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids); | 6386 | spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids); |
5897 | } | 6387 | } |
@@ -6028,8 +6518,8 @@ static struct hda_verb alc262_init_verbs[] = { | |||
6028 | 6518 | ||
6029 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | 6519 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback |
6030 | * mixer widget | 6520 | * mixer widget |
6031 | * Note: PASD motherboards uses the Line In 2 as the input for front panel | 6521 | * Note: PASD motherboards uses the Line In 2 as the input for |
6032 | * mic (mic 2) | 6522 | * front panel mic (mic 2) |
6033 | */ | 6523 | */ |
6034 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | 6524 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ |
6035 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 6525 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
@@ -6086,7 +6576,7 @@ static struct hda_verb alc262_init_verbs[] = { | |||
6086 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 6576 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, |
6087 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, | 6577 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, |
6088 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, | 6578 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, |
6089 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, | 6579 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, |
6090 | 6580 | ||
6091 | { } | 6581 | { } |
6092 | }; | 6582 | }; |
@@ -6113,7 +6603,7 @@ static void alc262_hippo_automute(struct hda_codec *codec, int force) | |||
6113 | struct alc_spec *spec = codec->spec; | 6603 | struct alc_spec *spec = codec->spec; |
6114 | unsigned int mute; | 6604 | unsigned int mute; |
6115 | 6605 | ||
6116 | if (force || ! spec->sense_updated) { | 6606 | if (force || !spec->sense_updated) { |
6117 | unsigned int present; | 6607 | unsigned int present; |
6118 | /* need to execute and sync at first */ | 6608 | /* need to execute and sync at first */ |
6119 | snd_hda_codec_read(codec, 0x15, 0, AC_VERB_SET_PIN_SENSE, 0); | 6609 | snd_hda_codec_read(codec, 0x15, 0, AC_VERB_SET_PIN_SENSE, 0); |
@@ -6153,7 +6643,7 @@ static void alc262_hippo1_automute(struct hda_codec *codec, int force) | |||
6153 | struct alc_spec *spec = codec->spec; | 6643 | struct alc_spec *spec = codec->spec; |
6154 | unsigned int mute; | 6644 | unsigned int mute; |
6155 | 6645 | ||
6156 | if (force || ! spec->sense_updated) { | 6646 | if (force || !spec->sense_updated) { |
6157 | unsigned int present; | 6647 | unsigned int present; |
6158 | /* need to execute and sync at first */ | 6648 | /* need to execute and sync at first */ |
6159 | snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0); | 6649 | snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0); |
@@ -6226,7 +6716,7 @@ static void alc262_fujitsu_automute(struct hda_codec *codec, int force) | |||
6226 | struct alc_spec *spec = codec->spec; | 6716 | struct alc_spec *spec = codec->spec; |
6227 | unsigned int mute; | 6717 | unsigned int mute; |
6228 | 6718 | ||
6229 | if (force || ! spec->sense_updated) { | 6719 | if (force || !spec->sense_updated) { |
6230 | unsigned int present; | 6720 | unsigned int present; |
6231 | /* need to execute and sync at first */ | 6721 | /* need to execute and sync at first */ |
6232 | snd_hda_codec_read(codec, 0x14, 0, AC_VERB_SET_PIN_SENSE, 0); | 6722 | snd_hda_codec_read(codec, 0x14, 0, AC_VERB_SET_PIN_SENSE, 0); |
@@ -6331,7 +6821,8 @@ static struct hda_verb alc262_EAPD_verbs[] = { | |||
6331 | }; | 6821 | }; |
6332 | 6822 | ||
6333 | /* add playback controls from the parsed DAC table */ | 6823 | /* add playback controls from the parsed DAC table */ |
6334 | static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg) | 6824 | static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, |
6825 | const struct auto_pin_cfg *cfg) | ||
6335 | { | 6826 | { |
6336 | hda_nid_t nid; | 6827 | hda_nid_t nid; |
6337 | int err; | 6828 | int err; |
@@ -6342,26 +6833,39 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, const struct | |||
6342 | 6833 | ||
6343 | nid = cfg->line_out_pins[0]; | 6834 | nid = cfg->line_out_pins[0]; |
6344 | if (nid) { | 6835 | if (nid) { |
6345 | if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Front Playback Volume", | 6836 | err = add_control(spec, ALC_CTL_WIDGET_VOL, |
6346 | HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT))) < 0) | 6837 | "Front Playback Volume", |
6838 | HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT)); | ||
6839 | if (err < 0) | ||
6347 | return err; | 6840 | return err; |
6348 | if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Front Playback Switch", | 6841 | err = add_control(spec, ALC_CTL_WIDGET_MUTE, |
6349 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) | 6842 | "Front Playback Switch", |
6843 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); | ||
6844 | if (err < 0) | ||
6350 | return err; | 6845 | return err; |
6351 | } | 6846 | } |
6352 | 6847 | ||
6353 | nid = cfg->speaker_pins[0]; | 6848 | nid = cfg->speaker_pins[0]; |
6354 | if (nid) { | 6849 | if (nid) { |
6355 | if (nid == 0x16) { | 6850 | if (nid == 0x16) { |
6356 | if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Speaker Playback Volume", | 6851 | err = add_control(spec, ALC_CTL_WIDGET_VOL, |
6357 | HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT))) < 0) | 6852 | "Speaker Playback Volume", |
6853 | HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, | ||
6854 | HDA_OUTPUT)); | ||
6855 | if (err < 0) | ||
6358 | return err; | 6856 | return err; |
6359 | if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Speaker Playback Switch", | 6857 | err = add_control(spec, ALC_CTL_WIDGET_MUTE, |
6360 | HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0) | 6858 | "Speaker Playback Switch", |
6859 | HDA_COMPOSE_AMP_VAL(nid, 2, 0, | ||
6860 | HDA_OUTPUT)); | ||
6861 | if (err < 0) | ||
6361 | return err; | 6862 | return err; |
6362 | } else { | 6863 | } else { |
6363 | if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Speaker Playback Switch", | 6864 | err = add_control(spec, ALC_CTL_WIDGET_MUTE, |
6364 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) | 6865 | "Speaker Playback Switch", |
6866 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, | ||
6867 | HDA_OUTPUT)); | ||
6868 | if (err < 0) | ||
6365 | return err; | 6869 | return err; |
6366 | } | 6870 | } |
6367 | } | 6871 | } |
@@ -6369,23 +6873,33 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, const struct | |||
6369 | if (nid) { | 6873 | if (nid) { |
6370 | /* spec->multiout.hp_nid = 2; */ | 6874 | /* spec->multiout.hp_nid = 2; */ |
6371 | if (nid == 0x16) { | 6875 | if (nid == 0x16) { |
6372 | if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Headphone Playback Volume", | 6876 | err = add_control(spec, ALC_CTL_WIDGET_VOL, |
6373 | HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT))) < 0) | 6877 | "Headphone Playback Volume", |
6878 | HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, | ||
6879 | HDA_OUTPUT)); | ||
6880 | if (err < 0) | ||
6374 | return err; | 6881 | return err; |
6375 | if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch", | 6882 | err = add_control(spec, ALC_CTL_WIDGET_MUTE, |
6376 | HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0) | 6883 | "Headphone Playback Switch", |
6884 | HDA_COMPOSE_AMP_VAL(nid, 2, 0, | ||
6885 | HDA_OUTPUT)); | ||
6886 | if (err < 0) | ||
6377 | return err; | 6887 | return err; |
6378 | } else { | 6888 | } else { |
6379 | if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch", | 6889 | err = add_control(spec, ALC_CTL_WIDGET_MUTE, |
6380 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) | 6890 | "Headphone Playback Switch", |
6891 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, | ||
6892 | HDA_OUTPUT)); | ||
6893 | if (err < 0) | ||
6381 | return err; | 6894 | return err; |
6382 | } | 6895 | } |
6383 | } | 6896 | } |
6384 | return 0; | 6897 | return 0; |
6385 | } | 6898 | } |
6386 | 6899 | ||
6387 | /* identical with ALC880 */ | 6900 | /* identical with ALC880 */ |
6388 | #define alc262_auto_create_analog_input_ctls alc880_auto_create_analog_input_ctls | 6901 | #define alc262_auto_create_analog_input_ctls \ |
6902 | alc880_auto_create_analog_input_ctls | ||
6389 | 6903 | ||
6390 | /* | 6904 | /* |
6391 | * generic initialization of ADC, input mixers and output mixers | 6905 | * generic initialization of ADC, input mixers and output mixers |
@@ -6403,8 +6917,8 @@ static struct hda_verb alc262_volume_init_verbs[] = { | |||
6403 | 6917 | ||
6404 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | 6918 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback |
6405 | * mixer widget | 6919 | * mixer widget |
6406 | * Note: PASD motherboards uses the Line In 2 as the input for front panel | 6920 | * Note: PASD motherboards uses the Line In 2 as the input for |
6407 | * mic (mic 2) | 6921 | * front panel mic (mic 2) |
6408 | */ | 6922 | */ |
6409 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | 6923 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ |
6410 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 6924 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
@@ -6464,8 +6978,8 @@ static struct hda_verb alc262_HP_BPC_init_verbs[] = { | |||
6464 | 6978 | ||
6465 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | 6979 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback |
6466 | * mixer widget | 6980 | * mixer widget |
6467 | * Note: PASD motherboards uses the Line In 2 as the input for front panel | 6981 | * Note: PASD motherboards uses the Line In 2 as the input for |
6468 | * mic (mic 2) | 6982 | * front panel mic (mic 2) |
6469 | */ | 6983 | */ |
6470 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | 6984 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ |
6471 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 6985 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
@@ -6647,13 +7161,17 @@ static int alc262_parse_auto_config(struct hda_codec *codec) | |||
6647 | int err; | 7161 | int err; |
6648 | static hda_nid_t alc262_ignore[] = { 0x1d, 0 }; | 7162 | static hda_nid_t alc262_ignore[] = { 0x1d, 0 }; |
6649 | 7163 | ||
6650 | if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, | 7164 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, |
6651 | alc262_ignore)) < 0) | 7165 | alc262_ignore); |
7166 | if (err < 0) | ||
6652 | return err; | 7167 | return err; |
6653 | if (! spec->autocfg.line_outs) | 7168 | if (!spec->autocfg.line_outs) |
6654 | return 0; /* can't find valid BIOS pin config */ | 7169 | return 0; /* can't find valid BIOS pin config */ |
6655 | if ((err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || | 7170 | err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg); |
6656 | (err = alc262_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) | 7171 | if (err < 0) |
7172 | return err; | ||
7173 | err = alc262_auto_create_analog_input_ctls(spec, &spec->autocfg); | ||
7174 | if (err < 0) | ||
6657 | return err; | 7175 | return err; |
6658 | 7176 | ||
6659 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 7177 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
@@ -6777,7 +7295,7 @@ static struct alc_config_preset alc262_presets[] = { | |||
6777 | .num_channel_mode = ARRAY_SIZE(alc262_modes), | 7295 | .num_channel_mode = ARRAY_SIZE(alc262_modes), |
6778 | .channel_mode = alc262_modes, | 7296 | .channel_mode = alc262_modes, |
6779 | .input_mux = &alc262_HP_capture_source, | 7297 | .input_mux = &alc262_HP_capture_source, |
6780 | }, | 7298 | }, |
6781 | [ALC262_HP_BPC_D7000_WF] = { | 7299 | [ALC262_HP_BPC_D7000_WF] = { |
6782 | .mixers = { alc262_HP_BPC_WildWest_mixer }, | 7300 | .mixers = { alc262_HP_BPC_WildWest_mixer }, |
6783 | .init_verbs = { alc262_HP_BPC_WildWest_init_verbs }, | 7301 | .init_verbs = { alc262_HP_BPC_WildWest_init_verbs }, |
@@ -6787,7 +7305,7 @@ static struct alc_config_preset alc262_presets[] = { | |||
6787 | .num_channel_mode = ARRAY_SIZE(alc262_modes), | 7305 | .num_channel_mode = ARRAY_SIZE(alc262_modes), |
6788 | .channel_mode = alc262_modes, | 7306 | .channel_mode = alc262_modes, |
6789 | .input_mux = &alc262_HP_capture_source, | 7307 | .input_mux = &alc262_HP_capture_source, |
6790 | }, | 7308 | }, |
6791 | [ALC262_HP_BPC_D7000_WL] = { | 7309 | [ALC262_HP_BPC_D7000_WL] = { |
6792 | .mixers = { alc262_HP_BPC_WildWest_mixer, | 7310 | .mixers = { alc262_HP_BPC_WildWest_mixer, |
6793 | alc262_HP_BPC_WildWest_option_mixer }, | 7311 | alc262_HP_BPC_WildWest_option_mixer }, |
@@ -6798,7 +7316,7 @@ static struct alc_config_preset alc262_presets[] = { | |||
6798 | .num_channel_mode = ARRAY_SIZE(alc262_modes), | 7316 | .num_channel_mode = ARRAY_SIZE(alc262_modes), |
6799 | .channel_mode = alc262_modes, | 7317 | .channel_mode = alc262_modes, |
6800 | .input_mux = &alc262_HP_capture_source, | 7318 | .input_mux = &alc262_HP_capture_source, |
6801 | }, | 7319 | }, |
6802 | [ALC262_BENQ_ED8] = { | 7320 | [ALC262_BENQ_ED8] = { |
6803 | .mixers = { alc262_base_mixer }, | 7321 | .mixers = { alc262_base_mixer }, |
6804 | .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs }, | 7322 | .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs }, |
@@ -6808,7 +7326,7 @@ static struct alc_config_preset alc262_presets[] = { | |||
6808 | .num_channel_mode = ARRAY_SIZE(alc262_modes), | 7326 | .num_channel_mode = ARRAY_SIZE(alc262_modes), |
6809 | .channel_mode = alc262_modes, | 7327 | .channel_mode = alc262_modes, |
6810 | .input_mux = &alc262_capture_source, | 7328 | .input_mux = &alc262_capture_source, |
6811 | }, | 7329 | }, |
6812 | }; | 7330 | }; |
6813 | 7331 | ||
6814 | static int patch_alc262(struct hda_codec *codec) | 7332 | static int patch_alc262(struct hda_codec *codec) |
@@ -6823,7 +7341,9 @@ static int patch_alc262(struct hda_codec *codec) | |||
6823 | 7341 | ||
6824 | codec->spec = spec; | 7342 | codec->spec = spec; |
6825 | #if 0 | 7343 | #if 0 |
6826 | /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is under-run */ | 7344 | /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is |
7345 | * under-run | ||
7346 | */ | ||
6827 | { | 7347 | { |
6828 | int tmp; | 7348 | int tmp; |
6829 | snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7); | 7349 | snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7); |
@@ -6849,7 +7369,7 @@ static int patch_alc262(struct hda_codec *codec) | |||
6849 | if (err < 0) { | 7369 | if (err < 0) { |
6850 | alc_free(codec); | 7370 | alc_free(codec); |
6851 | return err; | 7371 | return err; |
6852 | } else if (! err) { | 7372 | } else if (!err) { |
6853 | printk(KERN_INFO | 7373 | printk(KERN_INFO |
6854 | "hda_codec: Cannot set up configuration " | 7374 | "hda_codec: Cannot set up configuration " |
6855 | "from BIOS. Using base mode...\n"); | 7375 | "from BIOS. Using base mode...\n"); |
@@ -6868,15 +7388,17 @@ static int patch_alc262(struct hda_codec *codec) | |||
6868 | spec->stream_digital_playback = &alc262_pcm_digital_playback; | 7388 | spec->stream_digital_playback = &alc262_pcm_digital_playback; |
6869 | spec->stream_digital_capture = &alc262_pcm_digital_capture; | 7389 | spec->stream_digital_capture = &alc262_pcm_digital_capture; |
6870 | 7390 | ||
6871 | if (! spec->adc_nids && spec->input_mux) { | 7391 | if (!spec->adc_nids && spec->input_mux) { |
6872 | /* check whether NID 0x07 is valid */ | 7392 | /* check whether NID 0x07 is valid */ |
6873 | unsigned int wcap = get_wcaps(codec, 0x07); | 7393 | unsigned int wcap = get_wcaps(codec, 0x07); |
6874 | 7394 | ||
6875 | wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */ | 7395 | /* get type */ |
7396 | wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; | ||
6876 | if (wcap != AC_WID_AUD_IN) { | 7397 | if (wcap != AC_WID_AUD_IN) { |
6877 | spec->adc_nids = alc262_adc_nids_alt; | 7398 | spec->adc_nids = alc262_adc_nids_alt; |
6878 | spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids_alt); | 7399 | spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids_alt); |
6879 | spec->mixers[spec->num_mixers] = alc262_capture_alt_mixer; | 7400 | spec->mixers[spec->num_mixers] = |
7401 | alc262_capture_alt_mixer; | ||
6880 | spec->num_mixers++; | 7402 | spec->num_mixers++; |
6881 | } else { | 7403 | } else { |
6882 | spec->adc_nids = alc262_adc_nids; | 7404 | spec->adc_nids = alc262_adc_nids; |
@@ -6904,7 +7426,9 @@ static int patch_alc262(struct hda_codec *codec) | |||
6904 | static struct hda_verb alc861_threestack_ch2_init[] = { | 7426 | static struct hda_verb alc861_threestack_ch2_init[] = { |
6905 | /* set pin widget 1Ah (line in) for input */ | 7427 | /* set pin widget 1Ah (line in) for input */ |
6906 | { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, | 7428 | { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, |
6907 | /* set pin widget 18h (mic1/2) for input, for mic also enable the vref */ | 7429 | /* set pin widget 18h (mic1/2) for input, for mic also enable |
7430 | * the vref | ||
7431 | */ | ||
6908 | { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, | 7432 | { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, |
6909 | 7433 | ||
6910 | { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c }, | 7434 | { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c }, |
@@ -6961,7 +7485,9 @@ static struct hda_channel_mode alc861_uniwill_m31_modes[2] = { | |||
6961 | static struct hda_verb alc861_asus_ch2_init[] = { | 7485 | static struct hda_verb alc861_asus_ch2_init[] = { |
6962 | /* set pin widget 1Ah (line in) for input */ | 7486 | /* set pin widget 1Ah (line in) for input */ |
6963 | { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, | 7487 | { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, |
6964 | /* set pin widget 18h (mic1/2) for input, for mic also enable the vref */ | 7488 | /* set pin widget 18h (mic1/2) for input, for mic also enable |
7489 | * the vref | ||
7490 | */ | ||
6965 | { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, | 7491 | { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, |
6966 | 7492 | ||
6967 | { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c }, | 7493 | { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c }, |
@@ -7016,7 +7542,7 @@ static struct snd_kcontrol_new alc861_base_mixer[] = { | |||
7016 | HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT), | 7542 | HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT), |
7017 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), | 7543 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), |
7018 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT), | 7544 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT), |
7019 | 7545 | ||
7020 | /* Capture mixer control */ | 7546 | /* Capture mixer control */ |
7021 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | 7547 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), |
7022 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | 7548 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), |
@@ -7050,7 +7576,7 @@ static struct snd_kcontrol_new alc861_3ST_mixer[] = { | |||
7050 | HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT), | 7576 | HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT), |
7051 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), | 7577 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), |
7052 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT), | 7578 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT), |
7053 | 7579 | ||
7054 | /* Capture mixer control */ | 7580 | /* Capture mixer control */ |
7055 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | 7581 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), |
7056 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | 7582 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), |
@@ -7092,7 +7618,7 @@ static struct snd_kcontrol_new alc861_toshiba_mixer[] = { | |||
7092 | }, | 7618 | }, |
7093 | 7619 | ||
7094 | { } /* end */ | 7620 | { } /* end */ |
7095 | }; | 7621 | }; |
7096 | 7622 | ||
7097 | static struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = { | 7623 | static struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = { |
7098 | /* output mixer control */ | 7624 | /* output mixer control */ |
@@ -7113,7 +7639,7 @@ static struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = { | |||
7113 | HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT), | 7639 | HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT), |
7114 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), | 7640 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), |
7115 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT), | 7641 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT), |
7116 | 7642 | ||
7117 | /* Capture mixer control */ | 7643 | /* Capture mixer control */ |
7118 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | 7644 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), |
7119 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | 7645 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), |
@@ -7134,7 +7660,7 @@ static struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = { | |||
7134 | .private_value = ARRAY_SIZE(alc861_uniwill_m31_modes), | 7660 | .private_value = ARRAY_SIZE(alc861_uniwill_m31_modes), |
7135 | }, | 7661 | }, |
7136 | { } /* end */ | 7662 | { } /* end */ |
7137 | }; | 7663 | }; |
7138 | 7664 | ||
7139 | static struct snd_kcontrol_new alc861_asus_mixer[] = { | 7665 | static struct snd_kcontrol_new alc861_asus_mixer[] = { |
7140 | /* output mixer control */ | 7666 | /* output mixer control */ |
@@ -7154,8 +7680,8 @@ static struct snd_kcontrol_new alc861_asus_mixer[] = { | |||
7154 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT), | 7680 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT), |
7155 | HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT), | 7681 | HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT), |
7156 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), | 7682 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), |
7157 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_OUTPUT), /* was HDA_INPUT (why?) */ | 7683 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_OUTPUT), |
7158 | 7684 | ||
7159 | /* Capture mixer control */ | 7685 | /* Capture mixer control */ |
7160 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | 7686 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), |
7161 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | 7687 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), |
@@ -7239,7 +7765,7 @@ static struct hda_verb alc861_base_init_verbs[] = { | |||
7239 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 7765 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
7240 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 7766 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
7241 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 7767 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, |
7242 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c }, //Output 0~12 step | 7768 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */ |
7243 | 7769 | ||
7244 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 7770 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
7245 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 7771 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
@@ -7249,7 +7775,8 @@ static struct hda_verb alc861_base_init_verbs[] = { | |||
7249 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 7775 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
7250 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 7776 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
7251 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 7777 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
7252 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, // hp used DAC 3 (Front) | 7778 | /* hp used DAC 3 (Front) */ |
7779 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | ||
7253 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 7780 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, |
7254 | 7781 | ||
7255 | { } | 7782 | { } |
@@ -7300,7 +7827,7 @@ static struct hda_verb alc861_threestack_init_verbs[] = { | |||
7300 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 7827 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
7301 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 7828 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
7302 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 7829 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, |
7303 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c }, //Output 0~12 step | 7830 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */ |
7304 | 7831 | ||
7305 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 7832 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
7306 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 7833 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
@@ -7310,7 +7837,8 @@ static struct hda_verb alc861_threestack_init_verbs[] = { | |||
7310 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 7837 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
7311 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 7838 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
7312 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 7839 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
7313 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, // hp used DAC 3 (Front) | 7840 | /* hp used DAC 3 (Front) */ |
7841 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | ||
7314 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 7842 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, |
7315 | { } | 7843 | { } |
7316 | }; | 7844 | }; |
@@ -7329,7 +7857,8 @@ static struct hda_verb alc861_uniwill_m31_init_verbs[] = { | |||
7329 | { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | 7857 | { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, |
7330 | { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 }, | 7858 | { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 }, |
7331 | /* port-E for HP out (front panel) */ | 7859 | /* port-E for HP out (front panel) */ |
7332 | { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, // this has to be set to VREF80 | 7860 | /* this has to be set to VREF80 */ |
7861 | { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, | ||
7333 | /* route front PCM to HP */ | 7862 | /* route front PCM to HP */ |
7334 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, | 7863 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, |
7335 | /* port-F for mic-in (front panel) with vref */ | 7864 | /* port-F for mic-in (front panel) with vref */ |
@@ -7360,7 +7889,7 @@ static struct hda_verb alc861_uniwill_m31_init_verbs[] = { | |||
7360 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 7889 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
7361 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 7890 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
7362 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 7891 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, |
7363 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c }, //Output 0~12 step | 7892 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */ |
7364 | 7893 | ||
7365 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 7894 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
7366 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 7895 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
@@ -7370,7 +7899,8 @@ static struct hda_verb alc861_uniwill_m31_init_verbs[] = { | |||
7370 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 7899 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
7371 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 7900 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
7372 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 7901 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
7373 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, // hp used DAC 3 (Front) | 7902 | /* hp used DAC 3 (Front) */ |
7903 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | ||
7374 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 7904 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, |
7375 | { } | 7905 | { } |
7376 | }; | 7906 | }; |
@@ -7379,7 +7909,9 @@ static struct hda_verb alc861_asus_init_verbs[] = { | |||
7379 | /* | 7909 | /* |
7380 | * Unmute ADC0 and set the default input to mic-in | 7910 | * Unmute ADC0 and set the default input to mic-in |
7381 | */ | 7911 | */ |
7382 | /* port-A for surround (rear panel) | according to codec#0 this is the HP jack*/ | 7912 | /* port-A for surround (rear panel) |
7913 | * according to codec#0 this is the HP jack | ||
7914 | */ | ||
7383 | { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, /* was 0x00 */ | 7915 | { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, /* was 0x00 */ |
7384 | /* route front PCM to HP */ | 7916 | /* route front PCM to HP */ |
7385 | { 0x0e, AC_VERB_SET_CONNECT_SEL, 0x01 }, | 7917 | { 0x0e, AC_VERB_SET_CONNECT_SEL, 0x01 }, |
@@ -7391,7 +7923,8 @@ static struct hda_verb alc861_asus_init_verbs[] = { | |||
7391 | { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | 7923 | { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, |
7392 | { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 }, | 7924 | { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 }, |
7393 | /* port-E for HP out (front panel) */ | 7925 | /* port-E for HP out (front panel) */ |
7394 | { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, /* this has to be set to VREF80 */ | 7926 | /* this has to be set to VREF80 */ |
7927 | { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, | ||
7395 | /* route front PCM to HP */ | 7928 | /* route front PCM to HP */ |
7396 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, | 7929 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, |
7397 | /* port-F for mic-in (front panel) with vref */ | 7930 | /* port-F for mic-in (front panel) with vref */ |
@@ -7421,7 +7954,7 @@ static struct hda_verb alc861_asus_init_verbs[] = { | |||
7421 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 7954 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
7422 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 7955 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
7423 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 7956 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, |
7424 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c }, /* Output 0~12 step */ | 7957 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */ |
7425 | 7958 | ||
7426 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 7959 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
7427 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 7960 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
@@ -7431,7 +7964,8 @@ static struct hda_verb alc861_asus_init_verbs[] = { | |||
7431 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 7964 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
7432 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 7965 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
7433 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 7966 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
7434 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, /* hp used DAC 3 (Front) */ | 7967 | /* hp used DAC 3 (Front) */ |
7968 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | ||
7435 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 7969 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, |
7436 | { } | 7970 | { } |
7437 | }; | 7971 | }; |
@@ -7450,7 +7984,7 @@ static struct hda_verb alc861_auto_init_verbs[] = { | |||
7450 | /* | 7984 | /* |
7451 | * Unmute ADC0 and set the default input to mic-in | 7985 | * Unmute ADC0 and set the default input to mic-in |
7452 | */ | 7986 | */ |
7453 | // {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, | 7987 | /* {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, */ |
7454 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 7988 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
7455 | 7989 | ||
7456 | /* Unmute DAC0~3 & spdif out*/ | 7990 | /* Unmute DAC0~3 & spdif out*/ |
@@ -7483,21 +8017,21 @@ static struct hda_verb alc861_auto_init_verbs[] = { | |||
7483 | 8017 | ||
7484 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | 8018 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
7485 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | 8019 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
7486 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 8020 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, |
7487 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 8021 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, |
7488 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | 8022 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
7489 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | 8023 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
7490 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 8024 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, |
7491 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 8025 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, |
7492 | 8026 | ||
7493 | {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, // set Mic 1 | 8027 | {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, /* set Mic 1 */ |
7494 | 8028 | ||
7495 | { } | 8029 | { } |
7496 | }; | 8030 | }; |
7497 | 8031 | ||
7498 | static struct hda_verb alc861_toshiba_init_verbs[] = { | 8032 | static struct hda_verb alc861_toshiba_init_verbs[] = { |
7499 | {0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, | 8033 | {0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, |
7500 | 8034 | ||
7501 | { } | 8035 | { } |
7502 | }; | 8036 | }; |
7503 | 8037 | ||
@@ -7521,9 +8055,6 @@ static void alc861_toshiba_automute(struct hda_codec *codec) | |||
7521 | static void alc861_toshiba_unsol_event(struct hda_codec *codec, | 8055 | static void alc861_toshiba_unsol_event(struct hda_codec *codec, |
7522 | unsigned int res) | 8056 | unsigned int res) |
7523 | { | 8057 | { |
7524 | /* Looks like the unsol event is incompatible with the standard | ||
7525 | * definition. 6bit tag is placed at 26 bit! | ||
7526 | */ | ||
7527 | if ((res >> 26) == ALC880_HP_EVENT) | 8058 | if ((res >> 26) == ALC880_HP_EVENT) |
7528 | alc861_toshiba_automute(codec); | 8059 | alc861_toshiba_automute(codec); |
7529 | } | 8060 | } |
@@ -7568,7 +8099,8 @@ static struct hda_input_mux alc861_capture_source = { | |||
7568 | }; | 8099 | }; |
7569 | 8100 | ||
7570 | /* fill in the dac_nids table from the parsed pin configuration */ | 8101 | /* fill in the dac_nids table from the parsed pin configuration */ |
7571 | static int alc861_auto_fill_dac_nids(struct alc_spec *spec, const struct auto_pin_cfg *cfg) | 8102 | static int alc861_auto_fill_dac_nids(struct alc_spec *spec, |
8103 | const struct auto_pin_cfg *cfg) | ||
7572 | { | 8104 | { |
7573 | int i; | 8105 | int i; |
7574 | hda_nid_t nid; | 8106 | hda_nid_t nid; |
@@ -7591,29 +8123,40 @@ static int alc861_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
7591 | const struct auto_pin_cfg *cfg) | 8123 | const struct auto_pin_cfg *cfg) |
7592 | { | 8124 | { |
7593 | char name[32]; | 8125 | char name[32]; |
7594 | static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" }; | 8126 | static const char *chname[4] = { |
8127 | "Front", "Surround", NULL /*CLFE*/, "Side" | ||
8128 | }; | ||
7595 | hda_nid_t nid; | 8129 | hda_nid_t nid; |
7596 | int i, idx, err; | 8130 | int i, idx, err; |
7597 | 8131 | ||
7598 | for (i = 0; i < cfg->line_outs; i++) { | 8132 | for (i = 0; i < cfg->line_outs; i++) { |
7599 | nid = spec->multiout.dac_nids[i]; | 8133 | nid = spec->multiout.dac_nids[i]; |
7600 | if (! nid) | 8134 | if (!nid) |
7601 | continue; | 8135 | continue; |
7602 | if (nid == 0x05) { | 8136 | if (nid == 0x05) { |
7603 | /* Center/LFE */ | 8137 | /* Center/LFE */ |
7604 | if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "Center Playback Switch", | 8138 | err = add_control(spec, ALC_CTL_BIND_MUTE, |
7605 | HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0) | 8139 | "Center Playback Switch", |
8140 | HDA_COMPOSE_AMP_VAL(nid, 1, 0, | ||
8141 | HDA_OUTPUT)); | ||
8142 | if (err < 0) | ||
7606 | return err; | 8143 | return err; |
7607 | if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "LFE Playback Switch", | 8144 | err = add_control(spec, ALC_CTL_BIND_MUTE, |
7608 | HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0) | 8145 | "LFE Playback Switch", |
8146 | HDA_COMPOSE_AMP_VAL(nid, 2, 0, | ||
8147 | HDA_OUTPUT)); | ||
8148 | if (err < 0) | ||
7609 | return err; | 8149 | return err; |
7610 | } else { | 8150 | } else { |
7611 | for (idx = 0; idx < ARRAY_SIZE(alc861_dac_nids) - 1; idx++) | 8151 | for (idx = 0; idx < ARRAY_SIZE(alc861_dac_nids) - 1; |
8152 | idx++) | ||
7612 | if (nid == alc861_dac_nids[idx]) | 8153 | if (nid == alc861_dac_nids[idx]) |
7613 | break; | 8154 | break; |
7614 | sprintf(name, "%s Playback Switch", chname[idx]); | 8155 | sprintf(name, "%s Playback Switch", chname[idx]); |
7615 | if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name, | 8156 | err = add_control(spec, ALC_CTL_BIND_MUTE, name, |
7616 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) | 8157 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, |
8158 | HDA_OUTPUT)); | ||
8159 | if (err < 0) | ||
7617 | return err; | 8160 | return err; |
7618 | } | 8161 | } |
7619 | } | 8162 | } |
@@ -7625,13 +8168,15 @@ static int alc861_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin) | |||
7625 | int err; | 8168 | int err; |
7626 | hda_nid_t nid; | 8169 | hda_nid_t nid; |
7627 | 8170 | ||
7628 | if (! pin) | 8171 | if (!pin) |
7629 | return 0; | 8172 | return 0; |
7630 | 8173 | ||
7631 | if ((pin >= 0x0b && pin <= 0x10) || pin == 0x1f || pin == 0x20) { | 8174 | if ((pin >= 0x0b && pin <= 0x10) || pin == 0x1f || pin == 0x20) { |
7632 | nid = 0x03; | 8175 | nid = 0x03; |
7633 | if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch", | 8176 | err = add_control(spec, ALC_CTL_WIDGET_MUTE, |
7634 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) | 8177 | "Headphone Playback Switch", |
8178 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); | ||
8179 | if (err < 0) | ||
7635 | return err; | 8180 | return err; |
7636 | spec->multiout.hp_nid = nid; | 8181 | spec->multiout.hp_nid = nid; |
7637 | } | 8182 | } |
@@ -7639,32 +8184,33 @@ static int alc861_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin) | |||
7639 | } | 8184 | } |
7640 | 8185 | ||
7641 | /* create playback/capture controls for input pins */ | 8186 | /* create playback/capture controls for input pins */ |
7642 | static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg) | 8187 | static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec, |
8188 | const struct auto_pin_cfg *cfg) | ||
7643 | { | 8189 | { |
7644 | struct hda_input_mux *imux = &spec->private_imux; | 8190 | struct hda_input_mux *imux = &spec->private_imux; |
7645 | int i, err, idx, idx1; | 8191 | int i, err, idx, idx1; |
7646 | 8192 | ||
7647 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 8193 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
7648 | switch(cfg->input_pins[i]) { | 8194 | switch (cfg->input_pins[i]) { |
7649 | case 0x0c: | 8195 | case 0x0c: |
7650 | idx1 = 1; | 8196 | idx1 = 1; |
7651 | idx = 2; // Line In | 8197 | idx = 2; /* Line In */ |
7652 | break; | 8198 | break; |
7653 | case 0x0f: | 8199 | case 0x0f: |
7654 | idx1 = 2; | 8200 | idx1 = 2; |
7655 | idx = 2; // Line In | 8201 | idx = 2; /* Line In */ |
7656 | break; | 8202 | break; |
7657 | case 0x0d: | 8203 | case 0x0d: |
7658 | idx1 = 0; | 8204 | idx1 = 0; |
7659 | idx = 1; // Mic In | 8205 | idx = 1; /* Mic In */ |
7660 | break; | 8206 | break; |
7661 | case 0x10: | 8207 | case 0x10: |
7662 | idx1 = 3; | 8208 | idx1 = 3; |
7663 | idx = 1; // Mic In | 8209 | idx = 1; /* Mic In */ |
7664 | break; | 8210 | break; |
7665 | case 0x11: | 8211 | case 0x11: |
7666 | idx1 = 4; | 8212 | idx1 = 4; |
7667 | idx = 0; // CD | 8213 | idx = 0; /* CD */ |
7668 | break; | 8214 | break; |
7669 | default: | 8215 | default: |
7670 | continue; | 8216 | continue; |
@@ -7677,7 +8223,7 @@ static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec, const str | |||
7677 | 8223 | ||
7678 | imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; | 8224 | imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; |
7679 | imux->items[imux->num_items].index = idx1; | 8225 | imux->items[imux->num_items].index = idx1; |
7680 | imux->num_items++; | 8226 | imux->num_items++; |
7681 | } | 8227 | } |
7682 | return 0; | 8228 | return 0; |
7683 | } | 8229 | } |
@@ -7702,13 +8248,16 @@ static struct snd_kcontrol_new alc861_capture_mixer[] = { | |||
7702 | { } /* end */ | 8248 | { } /* end */ |
7703 | }; | 8249 | }; |
7704 | 8250 | ||
7705 | static void alc861_auto_set_output_and_unmute(struct hda_codec *codec, hda_nid_t nid, | 8251 | static void alc861_auto_set_output_and_unmute(struct hda_codec *codec, |
8252 | hda_nid_t nid, | ||
7706 | int pin_type, int dac_idx) | 8253 | int pin_type, int dac_idx) |
7707 | { | 8254 | { |
7708 | /* set as output */ | 8255 | /* set as output */ |
7709 | 8256 | ||
7710 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type); | 8257 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, |
7711 | snd_hda_codec_write(codec, dac_idx, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); | 8258 | pin_type); |
8259 | snd_hda_codec_write(codec, dac_idx, 0, AC_VERB_SET_AMP_GAIN_MUTE, | ||
8260 | AMP_OUT_UNMUTE); | ||
7712 | 8261 | ||
7713 | } | 8262 | } |
7714 | 8263 | ||
@@ -7717,10 +8266,13 @@ static void alc861_auto_init_multi_out(struct hda_codec *codec) | |||
7717 | struct alc_spec *spec = codec->spec; | 8266 | struct alc_spec *spec = codec->spec; |
7718 | int i; | 8267 | int i; |
7719 | 8268 | ||
8269 | alc_subsystem_id(codec, 0x0e, 0x0f, 0x0b); | ||
7720 | for (i = 0; i < spec->autocfg.line_outs; i++) { | 8270 | for (i = 0; i < spec->autocfg.line_outs; i++) { |
7721 | hda_nid_t nid = spec->autocfg.line_out_pins[i]; | 8271 | hda_nid_t nid = spec->autocfg.line_out_pins[i]; |
8272 | int pin_type = get_pin_type(spec->autocfg.line_out_type); | ||
7722 | if (nid) | 8273 | if (nid) |
7723 | alc861_auto_set_output_and_unmute(codec, nid, PIN_OUT, spec->multiout.dac_nids[i]); | 8274 | alc861_auto_set_output_and_unmute(codec, nid, pin_type, |
8275 | spec->multiout.dac_nids[i]); | ||
7724 | } | 8276 | } |
7725 | } | 8277 | } |
7726 | 8278 | ||
@@ -7731,7 +8283,8 @@ static void alc861_auto_init_hp_out(struct hda_codec *codec) | |||
7731 | 8283 | ||
7732 | pin = spec->autocfg.hp_pins[0]; | 8284 | pin = spec->autocfg.hp_pins[0]; |
7733 | if (pin) /* connect to front */ | 8285 | if (pin) /* connect to front */ |
7734 | alc861_auto_set_output_and_unmute(codec, pin, PIN_HP, spec->multiout.dac_nids[0]); | 8286 | alc861_auto_set_output_and_unmute(codec, pin, PIN_HP, |
8287 | spec->multiout.dac_nids[0]); | ||
7735 | } | 8288 | } |
7736 | 8289 | ||
7737 | static void alc861_auto_init_analog_input(struct hda_codec *codec) | 8290 | static void alc861_auto_init_analog_input(struct hda_codec *codec) |
@@ -7741,31 +8294,43 @@ static void alc861_auto_init_analog_input(struct hda_codec *codec) | |||
7741 | 8294 | ||
7742 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 8295 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
7743 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 8296 | hda_nid_t nid = spec->autocfg.input_pins[i]; |
7744 | if ((nid>=0x0c) && (nid <=0x11)) { | 8297 | if (nid >= 0x0c && nid <= 0x11) { |
7745 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | 8298 | snd_hda_codec_write(codec, nid, 0, |
7746 | i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN); | 8299 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
8300 | i <= AUTO_PIN_FRONT_MIC ? | ||
8301 | PIN_VREF80 : PIN_IN); | ||
7747 | } | 8302 | } |
7748 | } | 8303 | } |
7749 | } | 8304 | } |
7750 | 8305 | ||
7751 | /* parse the BIOS configuration and set up the alc_spec */ | 8306 | /* parse the BIOS configuration and set up the alc_spec */ |
7752 | /* return 1 if successful, 0 if the proper config is not found, or a negative error code */ | 8307 | /* return 1 if successful, 0 if the proper config is not found, |
8308 | * or a negative error code | ||
8309 | */ | ||
7753 | static int alc861_parse_auto_config(struct hda_codec *codec) | 8310 | static int alc861_parse_auto_config(struct hda_codec *codec) |
7754 | { | 8311 | { |
7755 | struct alc_spec *spec = codec->spec; | 8312 | struct alc_spec *spec = codec->spec; |
7756 | int err; | 8313 | int err; |
7757 | static hda_nid_t alc861_ignore[] = { 0x1d, 0 }; | 8314 | static hda_nid_t alc861_ignore[] = { 0x1d, 0 }; |
7758 | 8315 | ||
7759 | if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, | 8316 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, |
7760 | alc861_ignore)) < 0) | 8317 | alc861_ignore); |
8318 | if (err < 0) | ||
7761 | return err; | 8319 | return err; |
7762 | if (! spec->autocfg.line_outs) | 8320 | if (!spec->autocfg.line_outs) |
7763 | return 0; /* can't find valid BIOS pin config */ | 8321 | return 0; /* can't find valid BIOS pin config */ |
7764 | 8322 | ||
7765 | if ((err = alc861_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 || | 8323 | err = alc861_auto_fill_dac_nids(spec, &spec->autocfg); |
7766 | (err = alc861_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || | 8324 | if (err < 0) |
7767 | (err = alc861_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0])) < 0 || | 8325 | return err; |
7768 | (err = alc861_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) | 8326 | err = alc861_auto_create_multi_out_ctls(spec, &spec->autocfg); |
8327 | if (err < 0) | ||
8328 | return err; | ||
8329 | err = alc861_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); | ||
8330 | if (err < 0) | ||
8331 | return err; | ||
8332 | err = alc861_auto_create_analog_input_ctls(spec, &spec->autocfg); | ||
8333 | if (err < 0) | ||
7769 | return err; | 8334 | return err; |
7770 | 8335 | ||
7771 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 8336 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
@@ -7817,12 +8382,14 @@ static struct snd_pci_quirk alc861_cfg_tbl[] = { | |||
7817 | SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC861_3ST), | 8382 | SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC861_3ST), |
7818 | SND_PCI_QUIRK(0x1043, 0x1335, "ASUS F2/3", ALC861_ASUS_LAPTOP), | 8383 | SND_PCI_QUIRK(0x1043, 0x1335, "ASUS F2/3", ALC861_ASUS_LAPTOP), |
7819 | SND_PCI_QUIRK(0x1043, 0x1338, "ASUS F2/3", ALC861_ASUS_LAPTOP), | 8384 | SND_PCI_QUIRK(0x1043, 0x1338, "ASUS F2/3", ALC861_ASUS_LAPTOP), |
8385 | SND_PCI_QUIRK(0x1043, 0x13d7, "ASUS A9rp", ALC861_ASUS_LAPTOP), | ||
7820 | SND_PCI_QUIRK(0x1043, 0x1393, "ASUS", ALC861_ASUS), | 8386 | SND_PCI_QUIRK(0x1043, 0x1393, "ASUS", ALC861_ASUS), |
7821 | SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS", ALC660_3ST), | 8387 | SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS", ALC660_3ST), |
7822 | SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba", ALC861_TOSHIBA), | 8388 | SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba", ALC861_TOSHIBA), |
7823 | SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba", ALC861_TOSHIBA), | 8389 | SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba", ALC861_TOSHIBA), |
7824 | SND_PCI_QUIRK(0x1584, 0x9072, "Uniwill m31", ALC861_UNIWILL_M31), | 8390 | SND_PCI_QUIRK(0x1584, 0x9072, "Uniwill m31", ALC861_UNIWILL_M31), |
7825 | SND_PCI_QUIRK(0x1584, 0x2b01, "Uniwill X40AIx", ALC861_UNIWILL_M31), | 8391 | SND_PCI_QUIRK(0x1584, 0x2b01, "Uniwill X40AIx", ALC861_UNIWILL_M31), |
8392 | SND_PCI_QUIRK(0x1849, 0x0660, "Asrock 939SLI32", ALC660_3ST), | ||
7826 | SND_PCI_QUIRK(0x8086, 0xd600, "Intel", ALC861_3ST), | 8393 | SND_PCI_QUIRK(0x8086, 0xd600, "Intel", ALC861_3ST), |
7827 | {} | 8394 | {} |
7828 | }; | 8395 | }; |
@@ -7892,7 +8459,8 @@ static struct alc_config_preset alc861_presets[] = { | |||
7892 | }, | 8459 | }, |
7893 | [ALC861_TOSHIBA] = { | 8460 | [ALC861_TOSHIBA] = { |
7894 | .mixers = { alc861_toshiba_mixer }, | 8461 | .mixers = { alc861_toshiba_mixer }, |
7895 | .init_verbs = { alc861_base_init_verbs, alc861_toshiba_init_verbs }, | 8462 | .init_verbs = { alc861_base_init_verbs, |
8463 | alc861_toshiba_init_verbs }, | ||
7896 | .num_dacs = ARRAY_SIZE(alc861_dac_nids), | 8464 | .num_dacs = ARRAY_SIZE(alc861_dac_nids), |
7897 | .dac_nids = alc861_dac_nids, | 8465 | .dac_nids = alc861_dac_nids, |
7898 | .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), | 8466 | .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), |
@@ -7944,7 +8512,7 @@ static int patch_alc861(struct hda_codec *codec) | |||
7944 | if (spec == NULL) | 8512 | if (spec == NULL) |
7945 | return -ENOMEM; | 8513 | return -ENOMEM; |
7946 | 8514 | ||
7947 | codec->spec = spec; | 8515 | codec->spec = spec; |
7948 | 8516 | ||
7949 | board_config = snd_hda_check_board_config(codec, ALC861_MODEL_LAST, | 8517 | board_config = snd_hda_check_board_config(codec, ALC861_MODEL_LAST, |
7950 | alc861_models, | 8518 | alc861_models, |
@@ -7962,7 +8530,7 @@ static int patch_alc861(struct hda_codec *codec) | |||
7962 | if (err < 0) { | 8530 | if (err < 0) { |
7963 | alc_free(codec); | 8531 | alc_free(codec); |
7964 | return err; | 8532 | return err; |
7965 | } else if (! err) { | 8533 | } else if (!err) { |
7966 | printk(KERN_INFO | 8534 | printk(KERN_INFO |
7967 | "hda_codec: Cannot set up configuration " | 8535 | "hda_codec: Cannot set up configuration " |
7968 | "from BIOS. Using base mode...\n"); | 8536 | "from BIOS. Using base mode...\n"); |
@@ -8049,7 +8617,7 @@ static int alc861vd_mux_enum_put(struct snd_kcontrol *kcontrol, | |||
8049 | idx = ucontrol->value.enumerated.item[0]; | 8617 | idx = ucontrol->value.enumerated.item[0]; |
8050 | if (idx >= imux->num_items) | 8618 | if (idx >= imux->num_items) |
8051 | idx = imux->num_items - 1; | 8619 | idx = imux->num_items - 1; |
8052 | if (*cur_val == idx && ! codec->in_resume) | 8620 | if (*cur_val == idx && !codec->in_resume) |
8053 | return 0; | 8621 | return 0; |
8054 | for (i = 0; i < imux->num_items; i++) { | 8622 | for (i = 0; i < imux->num_items; i++) { |
8055 | unsigned int v = (i == idx) ? 0x7000 : 0x7080; | 8623 | unsigned int v = (i == idx) ? 0x7000 : 0x7080; |
@@ -8193,6 +8761,27 @@ static struct snd_kcontrol_new alc861vd_3st_mixer[] = { | |||
8193 | { } /* end */ | 8761 | { } /* end */ |
8194 | }; | 8762 | }; |
8195 | 8763 | ||
8764 | static struct snd_kcontrol_new alc861vd_lenovo_mixer[] = { | ||
8765 | HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT), | ||
8766 | /*HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),*/ | ||
8767 | HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), | ||
8768 | |||
8769 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | ||
8770 | |||
8771 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | ||
8772 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
8773 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
8774 | |||
8775 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | ||
8776 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | ||
8777 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | ||
8778 | |||
8779 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
8780 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
8781 | |||
8782 | { } /* end */ | ||
8783 | }; | ||
8784 | |||
8196 | /* | 8785 | /* |
8197 | * generic initialization of ADC, input mixers and output mixers | 8786 | * generic initialization of ADC, input mixers and output mixers |
8198 | */ | 8787 | */ |
@@ -8214,10 +8803,10 @@ static struct hda_verb alc861vd_volume_init_verbs[] = { | |||
8214 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 8803 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, |
8215 | 8804 | ||
8216 | /* Capture mixer: unmute Mic, F-Mic, Line, CD inputs */ | 8805 | /* Capture mixer: unmute Mic, F-Mic, Line, CD inputs */ |
8806 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
8807 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
8808 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | ||
8217 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 8809 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, |
8218 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)}, | ||
8219 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)}, | ||
8220 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(8)}, | ||
8221 | 8810 | ||
8222 | /* | 8811 | /* |
8223 | * Set up output mixers (0x02 - 0x05) | 8812 | * Set up output mixers (0x02 - 0x05) |
@@ -8318,6 +8907,68 @@ static struct hda_verb alc861vd_6stack_init_verbs[] = { | |||
8318 | { } | 8907 | { } |
8319 | }; | 8908 | }; |
8320 | 8909 | ||
8910 | static struct hda_verb alc861vd_eapd_verbs[] = { | ||
8911 | {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2}, | ||
8912 | { } | ||
8913 | }; | ||
8914 | |||
8915 | static struct hda_verb alc861vd_lenovo_unsol_verbs[] = { | ||
8916 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
8917 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
8918 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, | ||
8919 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, | ||
8920 | {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT}, | ||
8921 | {} | ||
8922 | }; | ||
8923 | |||
8924 | /* toggle speaker-output according to the hp-jack state */ | ||
8925 | static void alc861vd_lenovo_hp_automute(struct hda_codec *codec) | ||
8926 | { | ||
8927 | unsigned int present; | ||
8928 | unsigned char bits; | ||
8929 | |||
8930 | present = snd_hda_codec_read(codec, 0x1b, 0, | ||
8931 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
8932 | bits = present ? 0x80 : 0; | ||
8933 | snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, | ||
8934 | 0x80, bits); | ||
8935 | snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, | ||
8936 | 0x80, bits); | ||
8937 | } | ||
8938 | |||
8939 | static void alc861vd_lenovo_mic_automute(struct hda_codec *codec) | ||
8940 | { | ||
8941 | unsigned int present; | ||
8942 | unsigned char bits; | ||
8943 | |||
8944 | present = snd_hda_codec_read(codec, 0x18, 0, | ||
8945 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
8946 | bits = present ? 0x80 : 0; | ||
8947 | snd_hda_codec_amp_update(codec, 0x0b, 0, HDA_INPUT, 1, | ||
8948 | 0x80, bits); | ||
8949 | snd_hda_codec_amp_update(codec, 0x0b, 1, HDA_INPUT, 1, | ||
8950 | 0x80, bits); | ||
8951 | } | ||
8952 | |||
8953 | static void alc861vd_lenovo_automute(struct hda_codec *codec) | ||
8954 | { | ||
8955 | alc861vd_lenovo_hp_automute(codec); | ||
8956 | alc861vd_lenovo_mic_automute(codec); | ||
8957 | } | ||
8958 | |||
8959 | static void alc861vd_lenovo_unsol_event(struct hda_codec *codec, | ||
8960 | unsigned int res) | ||
8961 | { | ||
8962 | switch (res >> 26) { | ||
8963 | case ALC880_HP_EVENT: | ||
8964 | alc861vd_lenovo_hp_automute(codec); | ||
8965 | break; | ||
8966 | case ALC880_MIC_EVENT: | ||
8967 | alc861vd_lenovo_mic_automute(codec); | ||
8968 | break; | ||
8969 | } | ||
8970 | } | ||
8971 | |||
8321 | /* pcm configuration: identiacal with ALC880 */ | 8972 | /* pcm configuration: identiacal with ALC880 */ |
8322 | #define alc861vd_pcm_analog_playback alc880_pcm_analog_playback | 8973 | #define alc861vd_pcm_analog_playback alc880_pcm_analog_playback |
8323 | #define alc861vd_pcm_analog_capture alc880_pcm_analog_capture | 8974 | #define alc861vd_pcm_analog_capture alc880_pcm_analog_capture |
@@ -8332,15 +8983,18 @@ static const char *alc861vd_models[ALC861VD_MODEL_LAST] = { | |||
8332 | [ALC861VD_3ST] = "3stack", | 8983 | [ALC861VD_3ST] = "3stack", |
8333 | [ALC861VD_3ST_DIG] = "3stack-digout", | 8984 | [ALC861VD_3ST_DIG] = "3stack-digout", |
8334 | [ALC861VD_6ST_DIG] = "6stack-digout", | 8985 | [ALC861VD_6ST_DIG] = "6stack-digout", |
8986 | [ALC861VD_LENOVO] = "lenovo", | ||
8335 | [ALC861VD_AUTO] = "auto", | 8987 | [ALC861VD_AUTO] = "auto", |
8336 | }; | 8988 | }; |
8337 | 8989 | ||
8338 | static struct snd_pci_quirk alc861vd_cfg_tbl[] = { | 8990 | static struct snd_pci_quirk alc861vd_cfg_tbl[] = { |
8991 | SND_PCI_QUIRK(0x1043, 0x12e2, "Asus z35m", ALC660VD_3ST), | ||
8339 | SND_PCI_QUIRK(0x1043, 0x1339, "Asus G1", ALC660VD_3ST), | 8992 | SND_PCI_QUIRK(0x1043, 0x1339, "Asus G1", ALC660VD_3ST), |
8340 | SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST), | 8993 | SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST), |
8341 | SND_PCI_QUIRK(0x1019, 0xa88d, "Realtek ALC660 demo", ALC660VD_3ST), | 8994 | SND_PCI_QUIRK(0x1019, 0xa88d, "Realtek ALC660 demo", ALC660VD_3ST), |
8342 | 8995 | ||
8343 | SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo 3000 C200", ALC861VD_3ST), | 8996 | SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo 3000 C200", ALC861VD_LENOVO), |
8997 | SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo", ALC861VD_LENOVO), | ||
8344 | {} | 8998 | {} |
8345 | }; | 8999 | }; |
8346 | 9000 | ||
@@ -8389,6 +9043,22 @@ static struct alc_config_preset alc861vd_presets[] = { | |||
8389 | .channel_mode = alc861vd_6stack_modes, | 9043 | .channel_mode = alc861vd_6stack_modes, |
8390 | .input_mux = &alc861vd_capture_source, | 9044 | .input_mux = &alc861vd_capture_source, |
8391 | }, | 9045 | }, |
9046 | [ALC861VD_LENOVO] = { | ||
9047 | .mixers = { alc861vd_lenovo_mixer }, | ||
9048 | .init_verbs = { alc861vd_volume_init_verbs, | ||
9049 | alc861vd_3stack_init_verbs, | ||
9050 | alc861vd_eapd_verbs, | ||
9051 | alc861vd_lenovo_unsol_verbs }, | ||
9052 | .num_dacs = ARRAY_SIZE(alc660vd_dac_nids), | ||
9053 | .dac_nids = alc660vd_dac_nids, | ||
9054 | .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids), | ||
9055 | .adc_nids = alc861vd_adc_nids, | ||
9056 | .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes), | ||
9057 | .channel_mode = alc861vd_3stack_2ch_modes, | ||
9058 | .input_mux = &alc861vd_capture_source, | ||
9059 | .unsol_event = alc861vd_lenovo_unsol_event, | ||
9060 | .init_hook = alc861vd_lenovo_automute, | ||
9061 | }, | ||
8392 | }; | 9062 | }; |
8393 | 9063 | ||
8394 | /* | 9064 | /* |
@@ -8409,11 +9079,13 @@ static void alc861vd_auto_init_multi_out(struct hda_codec *codec) | |||
8409 | struct alc_spec *spec = codec->spec; | 9079 | struct alc_spec *spec = codec->spec; |
8410 | int i; | 9080 | int i; |
8411 | 9081 | ||
9082 | alc_subsystem_id(codec, 0x15, 0x1b, 0x14); | ||
8412 | for (i = 0; i <= HDA_SIDE; i++) { | 9083 | for (i = 0; i <= HDA_SIDE; i++) { |
8413 | hda_nid_t nid = spec->autocfg.line_out_pins[i]; | 9084 | hda_nid_t nid = spec->autocfg.line_out_pins[i]; |
9085 | int pin_type = get_pin_type(spec->autocfg.line_out_type); | ||
8414 | if (nid) | 9086 | if (nid) |
8415 | alc861vd_auto_set_output_and_unmute(codec, nid, | 9087 | alc861vd_auto_set_output_and_unmute(codec, nid, |
8416 | PIN_OUT, i); | 9088 | pin_type, i); |
8417 | } | 9089 | } |
8418 | } | 9090 | } |
8419 | 9091 | ||
@@ -8466,7 +9138,7 @@ static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
8466 | int i, err; | 9138 | int i, err; |
8467 | 9139 | ||
8468 | for (i = 0; i < cfg->line_outs; i++) { | 9140 | for (i = 0; i < cfg->line_outs; i++) { |
8469 | if (! spec->multiout.dac_nids[i]) | 9141 | if (!spec->multiout.dac_nids[i]) |
8470 | continue; | 9142 | continue; |
8471 | nid_v = alc861vd_idx_to_mixer_vol( | 9143 | nid_v = alc861vd_idx_to_mixer_vol( |
8472 | alc880_dac_to_idx( | 9144 | alc880_dac_to_idx( |
@@ -8477,36 +9149,42 @@ static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
8477 | 9149 | ||
8478 | if (i == 2) { | 9150 | if (i == 2) { |
8479 | /* Center/LFE */ | 9151 | /* Center/LFE */ |
8480 | if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, | 9152 | err = add_control(spec, ALC_CTL_WIDGET_VOL, |
8481 | "Center Playback Volume", | 9153 | "Center Playback Volume", |
8482 | HDA_COMPOSE_AMP_VAL(nid_v, 1, | 9154 | HDA_COMPOSE_AMP_VAL(nid_v, 1, 0, |
8483 | 0, HDA_OUTPUT))) < 0) | 9155 | HDA_OUTPUT)); |
9156 | if (err < 0) | ||
8484 | return err; | 9157 | return err; |
8485 | if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, | 9158 | err = add_control(spec, ALC_CTL_WIDGET_VOL, |
8486 | "LFE Playback Volume", | 9159 | "LFE Playback Volume", |
8487 | HDA_COMPOSE_AMP_VAL(nid_v, 2, | 9160 | HDA_COMPOSE_AMP_VAL(nid_v, 2, 0, |
8488 | 0, HDA_OUTPUT))) < 0) | 9161 | HDA_OUTPUT)); |
9162 | if (err < 0) | ||
8489 | return err; | 9163 | return err; |
8490 | if ((err = add_control(spec, ALC_CTL_BIND_MUTE, | 9164 | err = add_control(spec, ALC_CTL_BIND_MUTE, |
8491 | "Center Playback Switch", | 9165 | "Center Playback Switch", |
8492 | HDA_COMPOSE_AMP_VAL(nid_s, 1, | 9166 | HDA_COMPOSE_AMP_VAL(nid_s, 1, 2, |
8493 | 2, HDA_INPUT))) < 0) | 9167 | HDA_INPUT)); |
9168 | if (err < 0) | ||
8494 | return err; | 9169 | return err; |
8495 | if ((err = add_control(spec, ALC_CTL_BIND_MUTE, | 9170 | err = add_control(spec, ALC_CTL_BIND_MUTE, |
8496 | "LFE Playback Switch", | 9171 | "LFE Playback Switch", |
8497 | HDA_COMPOSE_AMP_VAL(nid_s, 2, | 9172 | HDA_COMPOSE_AMP_VAL(nid_s, 2, 2, |
8498 | 2, HDA_INPUT))) < 0) | 9173 | HDA_INPUT)); |
9174 | if (err < 0) | ||
8499 | return err; | 9175 | return err; |
8500 | } else { | 9176 | } else { |
8501 | sprintf(name, "%s Playback Volume", chname[i]); | 9177 | sprintf(name, "%s Playback Volume", chname[i]); |
8502 | if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name, | 9178 | err = add_control(spec, ALC_CTL_WIDGET_VOL, name, |
8503 | HDA_COMPOSE_AMP_VAL(nid_v, 3, | 9179 | HDA_COMPOSE_AMP_VAL(nid_v, 3, 0, |
8504 | 0, HDA_OUTPUT))) < 0) | 9180 | HDA_OUTPUT)); |
9181 | if (err < 0) | ||
8505 | return err; | 9182 | return err; |
8506 | sprintf(name, "%s Playback Switch", chname[i]); | 9183 | sprintf(name, "%s Playback Switch", chname[i]); |
8507 | if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name, | 9184 | err = add_control(spec, ALC_CTL_BIND_MUTE, name, |
8508 | HDA_COMPOSE_AMP_VAL(nid_v, 3, | 9185 | HDA_COMPOSE_AMP_VAL(nid_s, 3, 2, |
8509 | 2, HDA_INPUT))) < 0) | 9186 | HDA_INPUT)); |
9187 | if (err < 0) | ||
8510 | return err; | 9188 | return err; |
8511 | } | 9189 | } |
8512 | } | 9190 | } |
@@ -8523,13 +9201,13 @@ static int alc861vd_auto_create_extra_out(struct alc_spec *spec, | |||
8523 | int err; | 9201 | int err; |
8524 | char name[32]; | 9202 | char name[32]; |
8525 | 9203 | ||
8526 | if (! pin) | 9204 | if (!pin) |
8527 | return 0; | 9205 | return 0; |
8528 | 9206 | ||
8529 | if (alc880_is_fixed_pin(pin)) { | 9207 | if (alc880_is_fixed_pin(pin)) { |
8530 | nid_v = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); | 9208 | nid_v = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); |
8531 | /* specify the DAC as the extra output */ | 9209 | /* specify the DAC as the extra output */ |
8532 | if (! spec->multiout.hp_nid) | 9210 | if (!spec->multiout.hp_nid) |
8533 | spec->multiout.hp_nid = nid_v; | 9211 | spec->multiout.hp_nid = nid_v; |
8534 | else | 9212 | else |
8535 | spec->multiout.extra_out_nid[0] = nid_v; | 9213 | spec->multiout.extra_out_nid[0] = nid_v; |
@@ -8540,22 +9218,22 @@ static int alc861vd_auto_create_extra_out(struct alc_spec *spec, | |||
8540 | alc880_fixed_pin_idx(pin)); | 9218 | alc880_fixed_pin_idx(pin)); |
8541 | 9219 | ||
8542 | sprintf(name, "%s Playback Volume", pfx); | 9220 | sprintf(name, "%s Playback Volume", pfx); |
8543 | if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name, | 9221 | err = add_control(spec, ALC_CTL_WIDGET_VOL, name, |
8544 | HDA_COMPOSE_AMP_VAL(nid_v, 3, 0, | 9222 | HDA_COMPOSE_AMP_VAL(nid_v, 3, 0, HDA_OUTPUT)); |
8545 | HDA_OUTPUT))) < 0) | 9223 | if (err < 0) |
8546 | return err; | 9224 | return err; |
8547 | sprintf(name, "%s Playback Switch", pfx); | 9225 | sprintf(name, "%s Playback Switch", pfx); |
8548 | if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name, | 9226 | err = add_control(spec, ALC_CTL_BIND_MUTE, name, |
8549 | HDA_COMPOSE_AMP_VAL(nid_s, 3, 2, | 9227 | HDA_COMPOSE_AMP_VAL(nid_s, 3, 2, HDA_INPUT)); |
8550 | HDA_INPUT))) < 0) | 9228 | if (err < 0) |
8551 | return err; | 9229 | return err; |
8552 | } else if (alc880_is_multi_pin(pin)) { | 9230 | } else if (alc880_is_multi_pin(pin)) { |
8553 | /* set manual connection */ | 9231 | /* set manual connection */ |
8554 | /* we have only a switch on HP-out PIN */ | 9232 | /* we have only a switch on HP-out PIN */ |
8555 | sprintf(name, "%s Playback Switch", pfx); | 9233 | sprintf(name, "%s Playback Switch", pfx); |
8556 | if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, | 9234 | err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, |
8557 | HDA_COMPOSE_AMP_VAL(pin, 3, 0, | 9235 | HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT)); |
8558 | HDA_OUTPUT))) < 0) | 9236 | if (err < 0) |
8559 | return err; | 9237 | return err; |
8560 | } | 9238 | } |
8561 | return 0; | 9239 | return 0; |
@@ -8572,21 +9250,31 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec) | |||
8572 | int err; | 9250 | int err; |
8573 | static hda_nid_t alc861vd_ignore[] = { 0x1d, 0 }; | 9251 | static hda_nid_t alc861vd_ignore[] = { 0x1d, 0 }; |
8574 | 9252 | ||
8575 | if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, | 9253 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, |
8576 | alc861vd_ignore)) < 0) | 9254 | alc861vd_ignore); |
9255 | if (err < 0) | ||
8577 | return err; | 9256 | return err; |
8578 | if (! spec->autocfg.line_outs) | 9257 | if (!spec->autocfg.line_outs) |
8579 | return 0; /* can't find valid BIOS pin config */ | 9258 | return 0; /* can't find valid BIOS pin config */ |
8580 | 9259 | ||
8581 | if ((err = alc880_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 || | 9260 | err = alc880_auto_fill_dac_nids(spec, &spec->autocfg); |
8582 | (err = alc861vd_auto_create_multi_out_ctls(spec, | 9261 | if (err < 0) |
8583 | &spec->autocfg)) < 0 || | 9262 | return err; |
8584 | (err = alc861vd_auto_create_extra_out(spec, | 9263 | err = alc861vd_auto_create_multi_out_ctls(spec, &spec->autocfg); |
8585 | spec->autocfg.speaker_pins[0], "Speaker")) < 0 || | 9264 | if (err < 0) |
8586 | (err = alc861vd_auto_create_extra_out(spec, | 9265 | return err; |
8587 | spec->autocfg.hp_pins[0], "Headphone")) < 0 || | 9266 | err = alc861vd_auto_create_extra_out(spec, |
8588 | (err = alc880_auto_create_analog_input_ctls(spec, | 9267 | spec->autocfg.speaker_pins[0], |
8589 | &spec->autocfg)) < 0) | 9268 | "Speaker"); |
9269 | if (err < 0) | ||
9270 | return err; | ||
9271 | err = alc861vd_auto_create_extra_out(spec, | ||
9272 | spec->autocfg.hp_pins[0], | ||
9273 | "Headphone"); | ||
9274 | if (err < 0) | ||
9275 | return err; | ||
9276 | err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg); | ||
9277 | if (err < 0) | ||
8590 | return err; | 9278 | return err; |
8591 | 9279 | ||
8592 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 9280 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
@@ -8641,7 +9329,7 @@ static int patch_alc861vd(struct hda_codec *codec) | |||
8641 | if (err < 0) { | 9329 | if (err < 0) { |
8642 | alc_free(codec); | 9330 | alc_free(codec); |
8643 | return err; | 9331 | return err; |
8644 | } else if (! err) { | 9332 | } else if (!err) { |
8645 | printk(KERN_INFO | 9333 | printk(KERN_INFO |
8646 | "hda_codec: Cannot set up configuration " | 9334 | "hda_codec: Cannot set up configuration " |
8647 | "from BIOS. Using base mode...\n"); | 9335 | "from BIOS. Using base mode...\n"); |
@@ -8675,16 +9363,875 @@ static int patch_alc861vd(struct hda_codec *codec) | |||
8675 | } | 9363 | } |
8676 | 9364 | ||
8677 | /* | 9365 | /* |
9366 | * ALC662 support | ||
9367 | * | ||
9368 | * ALC662 is almost identical with ALC880 but has cleaner and more flexible | ||
9369 | * configuration. Each pin widget can choose any input DACs and a mixer. | ||
9370 | * Each ADC is connected from a mixer of all inputs. This makes possible | ||
9371 | * 6-channel independent captures. | ||
9372 | * | ||
9373 | * In addition, an independent DAC for the multi-playback (not used in this | ||
9374 | * driver yet). | ||
9375 | */ | ||
9376 | #define ALC662_DIGOUT_NID 0x06 | ||
9377 | #define ALC662_DIGIN_NID 0x0a | ||
9378 | |||
9379 | static hda_nid_t alc662_dac_nids[4] = { | ||
9380 | /* front, rear, clfe, rear_surr */ | ||
9381 | 0x02, 0x03, 0x04 | ||
9382 | }; | ||
9383 | |||
9384 | static hda_nid_t alc662_adc_nids[1] = { | ||
9385 | /* ADC1-2 */ | ||
9386 | 0x09, | ||
9387 | }; | ||
9388 | /* input MUX */ | ||
9389 | /* FIXME: should be a matrix-type input source selection */ | ||
9390 | |||
9391 | static struct hda_input_mux alc662_capture_source = { | ||
9392 | .num_items = 4, | ||
9393 | .items = { | ||
9394 | { "Mic", 0x0 }, | ||
9395 | { "Front Mic", 0x1 }, | ||
9396 | { "Line", 0x2 }, | ||
9397 | { "CD", 0x4 }, | ||
9398 | }, | ||
9399 | }; | ||
9400 | |||
9401 | static struct hda_input_mux alc662_lenovo_101e_capture_source = { | ||
9402 | .num_items = 2, | ||
9403 | .items = { | ||
9404 | { "Mic", 0x1 }, | ||
9405 | { "Line", 0x2 }, | ||
9406 | }, | ||
9407 | }; | ||
9408 | #define alc662_mux_enum_info alc_mux_enum_info | ||
9409 | #define alc662_mux_enum_get alc_mux_enum_get | ||
9410 | |||
9411 | static int alc662_mux_enum_put(struct snd_kcontrol *kcontrol, | ||
9412 | struct snd_ctl_elem_value *ucontrol) | ||
9413 | { | ||
9414 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
9415 | struct alc_spec *spec = codec->spec; | ||
9416 | const struct hda_input_mux *imux = spec->input_mux; | ||
9417 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | ||
9418 | static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 }; | ||
9419 | hda_nid_t nid = capture_mixers[adc_idx]; | ||
9420 | unsigned int *cur_val = &spec->cur_mux[adc_idx]; | ||
9421 | unsigned int i, idx; | ||
9422 | |||
9423 | idx = ucontrol->value.enumerated.item[0]; | ||
9424 | if (idx >= imux->num_items) | ||
9425 | idx = imux->num_items - 1; | ||
9426 | if (*cur_val == idx && !codec->in_resume) | ||
9427 | return 0; | ||
9428 | for (i = 0; i < imux->num_items; i++) { | ||
9429 | unsigned int v = (i == idx) ? 0x7000 : 0x7080; | ||
9430 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, | ||
9431 | v | (imux->items[i].index << 8)); | ||
9432 | } | ||
9433 | *cur_val = idx; | ||
9434 | return 1; | ||
9435 | } | ||
9436 | /* | ||
9437 | * 2ch mode | ||
9438 | */ | ||
9439 | static struct hda_channel_mode alc662_3ST_2ch_modes[1] = { | ||
9440 | { 2, NULL } | ||
9441 | }; | ||
9442 | |||
9443 | /* | ||
9444 | * 2ch mode | ||
9445 | */ | ||
9446 | static struct hda_verb alc662_3ST_ch2_init[] = { | ||
9447 | { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, | ||
9448 | { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, | ||
9449 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | ||
9450 | { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, | ||
9451 | { } /* end */ | ||
9452 | }; | ||
9453 | |||
9454 | /* | ||
9455 | * 6ch mode | ||
9456 | */ | ||
9457 | static struct hda_verb alc662_3ST_ch6_init[] = { | ||
9458 | { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
9459 | { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, | ||
9460 | { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 }, | ||
9461 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
9462 | { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, | ||
9463 | { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 }, | ||
9464 | { } /* end */ | ||
9465 | }; | ||
9466 | |||
9467 | static struct hda_channel_mode alc662_3ST_6ch_modes[2] = { | ||
9468 | { 2, alc662_3ST_ch2_init }, | ||
9469 | { 6, alc662_3ST_ch6_init }, | ||
9470 | }; | ||
9471 | |||
9472 | /* | ||
9473 | * 2ch mode | ||
9474 | */ | ||
9475 | static struct hda_verb alc662_sixstack_ch6_init[] = { | ||
9476 | { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, | ||
9477 | { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, | ||
9478 | { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
9479 | { } /* end */ | ||
9480 | }; | ||
9481 | |||
9482 | /* | ||
9483 | * 6ch mode | ||
9484 | */ | ||
9485 | static struct hda_verb alc662_sixstack_ch8_init[] = { | ||
9486 | { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
9487 | { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
9488 | { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
9489 | { } /* end */ | ||
9490 | }; | ||
9491 | |||
9492 | static struct hda_channel_mode alc662_5stack_modes[2] = { | ||
9493 | { 2, alc662_sixstack_ch6_init }, | ||
9494 | { 6, alc662_sixstack_ch8_init }, | ||
9495 | }; | ||
9496 | |||
9497 | /* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17 | ||
9498 | * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b | ||
9499 | */ | ||
9500 | |||
9501 | static struct snd_kcontrol_new alc662_base_mixer[] = { | ||
9502 | /* output mixer control */ | ||
9503 | HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT), | ||
9504 | HDA_CODEC_MUTE("Front Playback Switch", 0x02, 0x0, HDA_OUTPUT), | ||
9505 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x3, 0x0, HDA_OUTPUT), | ||
9506 | HDA_CODEC_MUTE("Surround Playback Switch", 0x03, 0x0, HDA_OUTPUT), | ||
9507 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT), | ||
9508 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT), | ||
9509 | HDA_BIND_MUTE_MONO("Center Playback Switch", 0x04, 1, 2, HDA_INPUT), | ||
9510 | HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x04, 2, 2, HDA_INPUT), | ||
9511 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | ||
9512 | |||
9513 | /*Input mixer control */ | ||
9514 | HDA_CODEC_VOLUME("CD Playback Volume", 0xb, 0x4, HDA_INPUT), | ||
9515 | HDA_CODEC_MUTE("CD Playback Switch", 0xb, 0x4, HDA_INPUT), | ||
9516 | HDA_CODEC_VOLUME("Line Playback Volume", 0xb, 0x02, HDA_INPUT), | ||
9517 | HDA_CODEC_MUTE("Line Playback Switch", 0xb, 0x02, HDA_INPUT), | ||
9518 | HDA_CODEC_VOLUME("Mic Playback Volume", 0xb, 0x0, HDA_INPUT), | ||
9519 | HDA_CODEC_MUTE("Mic Playback Switch", 0xb, 0x0, HDA_INPUT), | ||
9520 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0xb, 0x01, HDA_INPUT), | ||
9521 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0xb, 0x01, HDA_INPUT), | ||
9522 | |||
9523 | /* Capture mixer control */ | ||
9524 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), | ||
9525 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), | ||
9526 | { | ||
9527 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
9528 | .name = "Capture Source", | ||
9529 | .count = 1, | ||
9530 | .info = alc_mux_enum_info, | ||
9531 | .get = alc_mux_enum_get, | ||
9532 | .put = alc_mux_enum_put, | ||
9533 | }, | ||
9534 | { } /* end */ | ||
9535 | }; | ||
9536 | |||
9537 | static struct snd_kcontrol_new alc662_3ST_2ch_mixer[] = { | ||
9538 | HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT), | ||
9539 | HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT), | ||
9540 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | ||
9541 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
9542 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
9543 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | ||
9544 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | ||
9545 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
9546 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
9547 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | ||
9548 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | ||
9549 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
9550 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
9551 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), | ||
9552 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), | ||
9553 | { | ||
9554 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
9555 | /* .name = "Capture Source", */ | ||
9556 | .name = "Input Source", | ||
9557 | .count = 1, | ||
9558 | .info = alc662_mux_enum_info, | ||
9559 | .get = alc662_mux_enum_get, | ||
9560 | .put = alc662_mux_enum_put, | ||
9561 | }, | ||
9562 | { } /* end */ | ||
9563 | }; | ||
9564 | |||
9565 | static struct snd_kcontrol_new alc662_3ST_6ch_mixer[] = { | ||
9566 | HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT), | ||
9567 | HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT), | ||
9568 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT), | ||
9569 | HDA_BIND_MUTE("Surround Playback Switch", 0x03, 2, HDA_INPUT), | ||
9570 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT), | ||
9571 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT), | ||
9572 | HDA_BIND_MUTE_MONO("Center Playback Switch", 0x04, 1, 2, HDA_INPUT), | ||
9573 | HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x04, 2, 2, HDA_INPUT), | ||
9574 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | ||
9575 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
9576 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
9577 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | ||
9578 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | ||
9579 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
9580 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
9581 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | ||
9582 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | ||
9583 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
9584 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
9585 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), | ||
9586 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), | ||
9587 | { | ||
9588 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
9589 | /* .name = "Capture Source", */ | ||
9590 | .name = "Input Source", | ||
9591 | .count = 1, | ||
9592 | .info = alc662_mux_enum_info, | ||
9593 | .get = alc662_mux_enum_get, | ||
9594 | .put = alc662_mux_enum_put, | ||
9595 | }, | ||
9596 | { } /* end */ | ||
9597 | }; | ||
9598 | |||
9599 | static struct snd_kcontrol_new alc662_lenovo_101e_mixer[] = { | ||
9600 | HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT), | ||
9601 | HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT), | ||
9602 | HDA_CODEC_VOLUME("iSpeaker Playback Volume", 0x03, 0x0, HDA_OUTPUT), | ||
9603 | HDA_BIND_MUTE("iSpeaker Playback Switch", 0x03, 2, HDA_INPUT), | ||
9604 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | ||
9605 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | ||
9606 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | ||
9607 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | ||
9608 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | ||
9609 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), | ||
9610 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), | ||
9611 | { | ||
9612 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
9613 | /* .name = "Capture Source", */ | ||
9614 | .name = "Input Source", | ||
9615 | .count = 1, | ||
9616 | .info = alc662_mux_enum_info, | ||
9617 | .get = alc662_mux_enum_get, | ||
9618 | .put = alc662_mux_enum_put, | ||
9619 | }, | ||
9620 | { } /* end */ | ||
9621 | }; | ||
9622 | |||
9623 | static struct snd_kcontrol_new alc662_chmode_mixer[] = { | ||
9624 | { | ||
9625 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
9626 | .name = "Channel Mode", | ||
9627 | .info = alc_ch_mode_info, | ||
9628 | .get = alc_ch_mode_get, | ||
9629 | .put = alc_ch_mode_put, | ||
9630 | }, | ||
9631 | { } /* end */ | ||
9632 | }; | ||
9633 | |||
9634 | static struct hda_verb alc662_init_verbs[] = { | ||
9635 | /* ADC: mute amp left and right */ | ||
9636 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
9637 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
9638 | /* Front mixer: unmute input/output amp left and right (volume = 0) */ | ||
9639 | |||
9640 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
9641 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
9642 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | ||
9643 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | ||
9644 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | ||
9645 | |||
9646 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
9647 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
9648 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
9649 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
9650 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
9651 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
9652 | |||
9653 | /* Front Pin: output 0 (0x0c) */ | ||
9654 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
9655 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
9656 | |||
9657 | /* Rear Pin: output 1 (0x0d) */ | ||
9658 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
9659 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
9660 | |||
9661 | /* CLFE Pin: output 2 (0x0e) */ | ||
9662 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
9663 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
9664 | |||
9665 | /* Mic (rear) pin: input vref at 80% */ | ||
9666 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
9667 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
9668 | /* Front Mic pin: input vref at 80% */ | ||
9669 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
9670 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
9671 | /* Line In pin: input */ | ||
9672 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
9673 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
9674 | /* Line-2 In: Headphone output (output 0 - 0x0c) */ | ||
9675 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
9676 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
9677 | {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
9678 | /* CD pin widget for input */ | ||
9679 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
9680 | |||
9681 | /* FIXME: use matrix-type input source selection */ | ||
9682 | /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ | ||
9683 | /* Input mixer */ | ||
9684 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
9685 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
9686 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | ||
9687 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | ||
9688 | { } | ||
9689 | }; | ||
9690 | |||
9691 | static struct hda_verb alc662_sue_init_verbs[] = { | ||
9692 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_FRONT_EVENT}, | ||
9693 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT}, | ||
9694 | {} | ||
9695 | }; | ||
9696 | |||
9697 | /* | ||
9698 | * generic initialization of ADC, input mixers and output mixers | ||
9699 | */ | ||
9700 | static struct hda_verb alc662_auto_init_verbs[] = { | ||
9701 | /* | ||
9702 | * Unmute ADC and set the default input to mic-in | ||
9703 | */ | ||
9704 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
9705 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
9706 | |||
9707 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | ||
9708 | * mixer widget | ||
9709 | * Note: PASD motherboards uses the Line In 2 as the input for front | ||
9710 | * panel mic (mic 2) | ||
9711 | */ | ||
9712 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | ||
9713 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
9714 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
9715 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | ||
9716 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | ||
9717 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | ||
9718 | |||
9719 | /* | ||
9720 | * Set up output mixers (0x0c - 0x0f) | ||
9721 | */ | ||
9722 | /* set vol=0 to output mixers */ | ||
9723 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
9724 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
9725 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
9726 | |||
9727 | /* set up input amps for analog loopback */ | ||
9728 | /* Amp Indices: DAC = 0, mixer = 1 */ | ||
9729 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
9730 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
9731 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
9732 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
9733 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
9734 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
9735 | |||
9736 | |||
9737 | /* FIXME: use matrix-type input source selection */ | ||
9738 | /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ | ||
9739 | /* Input mixer */ | ||
9740 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
9741 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
9742 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | ||
9743 | /*{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},*/ | ||
9744 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | ||
9745 | |||
9746 | { } | ||
9747 | }; | ||
9748 | |||
9749 | /* capture mixer elements */ | ||
9750 | static struct snd_kcontrol_new alc662_capture_mixer[] = { | ||
9751 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), | ||
9752 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), | ||
9753 | { | ||
9754 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
9755 | /* The multiple "Capture Source" controls confuse alsamixer | ||
9756 | * So call somewhat different.. | ||
9757 | * FIXME: the controls appear in the "playback" view! | ||
9758 | */ | ||
9759 | /* .name = "Capture Source", */ | ||
9760 | .name = "Input Source", | ||
9761 | .count = 1, | ||
9762 | .info = alc882_mux_enum_info, | ||
9763 | .get = alc882_mux_enum_get, | ||
9764 | .put = alc882_mux_enum_put, | ||
9765 | }, | ||
9766 | { } /* end */ | ||
9767 | }; | ||
9768 | |||
9769 | static void alc662_lenovo_101e_ispeaker_automute(struct hda_codec *codec) | ||
9770 | { | ||
9771 | unsigned int present; | ||
9772 | unsigned char bits; | ||
9773 | |||
9774 | present = snd_hda_codec_read(codec, 0x14, 0, | ||
9775 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
9776 | bits = present ? 0x80 : 0; | ||
9777 | snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, | ||
9778 | 0x80, bits); | ||
9779 | snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, | ||
9780 | 0x80, bits); | ||
9781 | } | ||
9782 | |||
9783 | static void alc662_lenovo_101e_all_automute(struct hda_codec *codec) | ||
9784 | { | ||
9785 | unsigned int present; | ||
9786 | unsigned char bits; | ||
9787 | |||
9788 | present = snd_hda_codec_read(codec, 0x1b, 0, | ||
9789 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
9790 | bits = present ? 0x80 : 0; | ||
9791 | snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, | ||
9792 | 0x80, bits); | ||
9793 | snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, | ||
9794 | 0x80, bits); | ||
9795 | snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, | ||
9796 | 0x80, bits); | ||
9797 | snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, | ||
9798 | 0x80, bits); | ||
9799 | } | ||
9800 | |||
9801 | static void alc662_lenovo_101e_unsol_event(struct hda_codec *codec, | ||
9802 | unsigned int res) | ||
9803 | { | ||
9804 | if ((res >> 26) == ALC880_HP_EVENT) | ||
9805 | alc662_lenovo_101e_all_automute(codec); | ||
9806 | if ((res >> 26) == ALC880_FRONT_EVENT) | ||
9807 | alc662_lenovo_101e_ispeaker_automute(codec); | ||
9808 | } | ||
9809 | |||
9810 | |||
9811 | /* pcm configuration: identiacal with ALC880 */ | ||
9812 | #define alc662_pcm_analog_playback alc880_pcm_analog_playback | ||
9813 | #define alc662_pcm_analog_capture alc880_pcm_analog_capture | ||
9814 | #define alc662_pcm_digital_playback alc880_pcm_digital_playback | ||
9815 | #define alc662_pcm_digital_capture alc880_pcm_digital_capture | ||
9816 | |||
9817 | /* | ||
9818 | * configuration and preset | ||
9819 | */ | ||
9820 | static const char *alc662_models[ALC662_MODEL_LAST] = { | ||
9821 | [ALC662_3ST_2ch_DIG] = "3stack-dig", | ||
9822 | [ALC662_3ST_6ch_DIG] = "3stack-6ch-dig", | ||
9823 | [ALC662_3ST_6ch] = "3stack-6ch", | ||
9824 | [ALC662_5ST_DIG] = "6stack-dig", | ||
9825 | [ALC662_LENOVO_101E] = "lenovo-101e", | ||
9826 | [ALC662_AUTO] = "auto", | ||
9827 | }; | ||
9828 | |||
9829 | static struct snd_pci_quirk alc662_cfg_tbl[] = { | ||
9830 | SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E), | ||
9831 | {} | ||
9832 | }; | ||
9833 | |||
9834 | static struct alc_config_preset alc662_presets[] = { | ||
9835 | [ALC662_3ST_2ch_DIG] = { | ||
9836 | .mixers = { alc662_3ST_2ch_mixer }, | ||
9837 | .init_verbs = { alc662_init_verbs }, | ||
9838 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | ||
9839 | .dac_nids = alc662_dac_nids, | ||
9840 | .dig_out_nid = ALC662_DIGOUT_NID, | ||
9841 | .num_adc_nids = ARRAY_SIZE(alc662_adc_nids), | ||
9842 | .adc_nids = alc662_adc_nids, | ||
9843 | .dig_in_nid = ALC662_DIGIN_NID, | ||
9844 | .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes), | ||
9845 | .channel_mode = alc662_3ST_2ch_modes, | ||
9846 | .input_mux = &alc662_capture_source, | ||
9847 | }, | ||
9848 | [ALC662_3ST_6ch_DIG] = { | ||
9849 | .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer }, | ||
9850 | .init_verbs = { alc662_init_verbs }, | ||
9851 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | ||
9852 | .dac_nids = alc662_dac_nids, | ||
9853 | .dig_out_nid = ALC662_DIGOUT_NID, | ||
9854 | .num_adc_nids = ARRAY_SIZE(alc662_adc_nids), | ||
9855 | .adc_nids = alc662_adc_nids, | ||
9856 | .dig_in_nid = ALC662_DIGIN_NID, | ||
9857 | .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes), | ||
9858 | .channel_mode = alc662_3ST_6ch_modes, | ||
9859 | .need_dac_fix = 1, | ||
9860 | .input_mux = &alc662_capture_source, | ||
9861 | }, | ||
9862 | [ALC662_3ST_6ch] = { | ||
9863 | .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer }, | ||
9864 | .init_verbs = { alc662_init_verbs }, | ||
9865 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | ||
9866 | .dac_nids = alc662_dac_nids, | ||
9867 | .num_adc_nids = ARRAY_SIZE(alc662_adc_nids), | ||
9868 | .adc_nids = alc662_adc_nids, | ||
9869 | .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes), | ||
9870 | .channel_mode = alc662_3ST_6ch_modes, | ||
9871 | .need_dac_fix = 1, | ||
9872 | .input_mux = &alc662_capture_source, | ||
9873 | }, | ||
9874 | [ALC662_5ST_DIG] = { | ||
9875 | .mixers = { alc662_base_mixer, alc662_chmode_mixer }, | ||
9876 | .init_verbs = { alc662_init_verbs }, | ||
9877 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | ||
9878 | .dac_nids = alc662_dac_nids, | ||
9879 | .dig_out_nid = ALC662_DIGOUT_NID, | ||
9880 | .num_adc_nids = ARRAY_SIZE(alc662_adc_nids), | ||
9881 | .adc_nids = alc662_adc_nids, | ||
9882 | .dig_in_nid = ALC662_DIGIN_NID, | ||
9883 | .num_channel_mode = ARRAY_SIZE(alc662_5stack_modes), | ||
9884 | .channel_mode = alc662_5stack_modes, | ||
9885 | .input_mux = &alc662_capture_source, | ||
9886 | }, | ||
9887 | [ALC662_LENOVO_101E] = { | ||
9888 | .mixers = { alc662_lenovo_101e_mixer }, | ||
9889 | .init_verbs = { alc662_init_verbs, alc662_sue_init_verbs }, | ||
9890 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | ||
9891 | .dac_nids = alc662_dac_nids, | ||
9892 | .num_adc_nids = ARRAY_SIZE(alc662_adc_nids), | ||
9893 | .adc_nids = alc662_adc_nids, | ||
9894 | .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes), | ||
9895 | .channel_mode = alc662_3ST_2ch_modes, | ||
9896 | .input_mux = &alc662_lenovo_101e_capture_source, | ||
9897 | .unsol_event = alc662_lenovo_101e_unsol_event, | ||
9898 | .init_hook = alc662_lenovo_101e_all_automute, | ||
9899 | }, | ||
9900 | |||
9901 | }; | ||
9902 | |||
9903 | |||
9904 | /* | ||
9905 | * BIOS auto configuration | ||
9906 | */ | ||
9907 | |||
9908 | /* add playback controls from the parsed DAC table */ | ||
9909 | static int alc662_auto_create_multi_out_ctls(struct alc_spec *spec, | ||
9910 | const struct auto_pin_cfg *cfg) | ||
9911 | { | ||
9912 | char name[32]; | ||
9913 | static const char *chname[4] = { | ||
9914 | "Front", "Surround", NULL /*CLFE*/, "Side" | ||
9915 | }; | ||
9916 | hda_nid_t nid; | ||
9917 | int i, err; | ||
9918 | |||
9919 | for (i = 0; i < cfg->line_outs; i++) { | ||
9920 | if (!spec->multiout.dac_nids[i]) | ||
9921 | continue; | ||
9922 | nid = alc880_idx_to_dac(i); | ||
9923 | if (i == 2) { | ||
9924 | /* Center/LFE */ | ||
9925 | err = add_control(spec, ALC_CTL_WIDGET_VOL, | ||
9926 | "Center Playback Volume", | ||
9927 | HDA_COMPOSE_AMP_VAL(nid, 1, 0, | ||
9928 | HDA_OUTPUT)); | ||
9929 | if (err < 0) | ||
9930 | return err; | ||
9931 | err = add_control(spec, ALC_CTL_WIDGET_VOL, | ||
9932 | "LFE Playback Volume", | ||
9933 | HDA_COMPOSE_AMP_VAL(nid, 2, 0, | ||
9934 | HDA_OUTPUT)); | ||
9935 | if (err < 0) | ||
9936 | return err; | ||
9937 | err = add_control(spec, ALC_CTL_BIND_MUTE, | ||
9938 | "Center Playback Switch", | ||
9939 | HDA_COMPOSE_AMP_VAL(nid, 1, 2, | ||
9940 | HDA_INPUT)); | ||
9941 | if (err < 0) | ||
9942 | return err; | ||
9943 | err = add_control(spec, ALC_CTL_BIND_MUTE, | ||
9944 | "LFE Playback Switch", | ||
9945 | HDA_COMPOSE_AMP_VAL(nid, 2, 2, | ||
9946 | HDA_INPUT)); | ||
9947 | if (err < 0) | ||
9948 | return err; | ||
9949 | } else { | ||
9950 | sprintf(name, "%s Playback Volume", chname[i]); | ||
9951 | err = add_control(spec, ALC_CTL_WIDGET_VOL, name, | ||
9952 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, | ||
9953 | HDA_OUTPUT)); | ||
9954 | if (err < 0) | ||
9955 | return err; | ||
9956 | sprintf(name, "%s Playback Switch", chname[i]); | ||
9957 | err = add_control(spec, ALC_CTL_BIND_MUTE, name, | ||
9958 | HDA_COMPOSE_AMP_VAL(nid, 3, 2, | ||
9959 | HDA_INPUT)); | ||
9960 | if (err < 0) | ||
9961 | return err; | ||
9962 | } | ||
9963 | } | ||
9964 | return 0; | ||
9965 | } | ||
9966 | |||
9967 | /* add playback controls for speaker and HP outputs */ | ||
9968 | static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin, | ||
9969 | const char *pfx) | ||
9970 | { | ||
9971 | hda_nid_t nid; | ||
9972 | int err; | ||
9973 | char name[32]; | ||
9974 | |||
9975 | if (!pin) | ||
9976 | return 0; | ||
9977 | |||
9978 | if (alc880_is_fixed_pin(pin)) { | ||
9979 | nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); | ||
9980 | /* printk("DAC nid=%x\n",nid); */ | ||
9981 | /* specify the DAC as the extra output */ | ||
9982 | if (!spec->multiout.hp_nid) | ||
9983 | spec->multiout.hp_nid = nid; | ||
9984 | else | ||
9985 | spec->multiout.extra_out_nid[0] = nid; | ||
9986 | /* control HP volume/switch on the output mixer amp */ | ||
9987 | nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); | ||
9988 | sprintf(name, "%s Playback Volume", pfx); | ||
9989 | err = add_control(spec, ALC_CTL_WIDGET_VOL, name, | ||
9990 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); | ||
9991 | if (err < 0) | ||
9992 | return err; | ||
9993 | sprintf(name, "%s Playback Switch", pfx); | ||
9994 | err = add_control(spec, ALC_CTL_BIND_MUTE, name, | ||
9995 | HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT)); | ||
9996 | if (err < 0) | ||
9997 | return err; | ||
9998 | } else if (alc880_is_multi_pin(pin)) { | ||
9999 | /* set manual connection */ | ||
10000 | /* we have only a switch on HP-out PIN */ | ||
10001 | sprintf(name, "%s Playback Switch", pfx); | ||
10002 | err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, | ||
10003 | HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT)); | ||
10004 | if (err < 0) | ||
10005 | return err; | ||
10006 | } | ||
10007 | return 0; | ||
10008 | } | ||
10009 | |||
10010 | /* create playback/capture controls for input pins */ | ||
10011 | static int alc662_auto_create_analog_input_ctls(struct alc_spec *spec, | ||
10012 | const struct auto_pin_cfg *cfg) | ||
10013 | { | ||
10014 | struct hda_input_mux *imux = &spec->private_imux; | ||
10015 | int i, err, idx; | ||
10016 | |||
10017 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
10018 | if (alc880_is_input_pin(cfg->input_pins[i])) { | ||
10019 | idx = alc880_input_pin_idx(cfg->input_pins[i]); | ||
10020 | err = new_analog_input(spec, cfg->input_pins[i], | ||
10021 | auto_pin_cfg_labels[i], | ||
10022 | idx, 0x0b); | ||
10023 | if (err < 0) | ||
10024 | return err; | ||
10025 | imux->items[imux->num_items].label = | ||
10026 | auto_pin_cfg_labels[i]; | ||
10027 | imux->items[imux->num_items].index = | ||
10028 | alc880_input_pin_idx(cfg->input_pins[i]); | ||
10029 | imux->num_items++; | ||
10030 | } | ||
10031 | } | ||
10032 | return 0; | ||
10033 | } | ||
10034 | |||
10035 | static void alc662_auto_set_output_and_unmute(struct hda_codec *codec, | ||
10036 | hda_nid_t nid, int pin_type, | ||
10037 | int dac_idx) | ||
10038 | { | ||
10039 | /* set as output */ | ||
10040 | snd_hda_codec_write(codec, nid, 0, | ||
10041 | AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type); | ||
10042 | snd_hda_codec_write(codec, nid, 0, | ||
10043 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); | ||
10044 | /* need the manual connection? */ | ||
10045 | if (alc880_is_multi_pin(nid)) { | ||
10046 | struct alc_spec *spec = codec->spec; | ||
10047 | int idx = alc880_multi_pin_idx(nid); | ||
10048 | snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0, | ||
10049 | AC_VERB_SET_CONNECT_SEL, | ||
10050 | alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx])); | ||
10051 | } | ||
10052 | } | ||
10053 | |||
10054 | static void alc662_auto_init_multi_out(struct hda_codec *codec) | ||
10055 | { | ||
10056 | struct alc_spec *spec = codec->spec; | ||
10057 | int i; | ||
10058 | |||
10059 | for (i = 0; i <= HDA_SIDE; i++) { | ||
10060 | hda_nid_t nid = spec->autocfg.line_out_pins[i]; | ||
10061 | int pin_type = get_pin_type(spec->autocfg.line_out_type); | ||
10062 | if (nid) | ||
10063 | alc662_auto_set_output_and_unmute(codec, nid, pin_type, | ||
10064 | i); | ||
10065 | } | ||
10066 | } | ||
10067 | |||
10068 | static void alc662_auto_init_hp_out(struct hda_codec *codec) | ||
10069 | { | ||
10070 | struct alc_spec *spec = codec->spec; | ||
10071 | hda_nid_t pin; | ||
10072 | |||
10073 | pin = spec->autocfg.hp_pins[0]; | ||
10074 | if (pin) /* connect to front */ | ||
10075 | /* use dac 0 */ | ||
10076 | alc662_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); | ||
10077 | } | ||
10078 | |||
10079 | #define alc662_is_input_pin(nid) alc880_is_input_pin(nid) | ||
10080 | #define ALC662_PIN_CD_NID ALC880_PIN_CD_NID | ||
10081 | |||
10082 | static void alc662_auto_init_analog_input(struct hda_codec *codec) | ||
10083 | { | ||
10084 | struct alc_spec *spec = codec->spec; | ||
10085 | int i; | ||
10086 | |||
10087 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
10088 | hda_nid_t nid = spec->autocfg.input_pins[i]; | ||
10089 | if (alc662_is_input_pin(nid)) { | ||
10090 | snd_hda_codec_write(codec, nid, 0, | ||
10091 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
10092 | (i <= AUTO_PIN_FRONT_MIC ? | ||
10093 | PIN_VREF80 : PIN_IN)); | ||
10094 | if (nid != ALC662_PIN_CD_NID) | ||
10095 | snd_hda_codec_write(codec, nid, 0, | ||
10096 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
10097 | AMP_OUT_MUTE); | ||
10098 | } | ||
10099 | } | ||
10100 | } | ||
10101 | |||
10102 | static int alc662_parse_auto_config(struct hda_codec *codec) | ||
10103 | { | ||
10104 | struct alc_spec *spec = codec->spec; | ||
10105 | int err; | ||
10106 | static hda_nid_t alc662_ignore[] = { 0x1d, 0 }; | ||
10107 | |||
10108 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, | ||
10109 | alc662_ignore); | ||
10110 | if (err < 0) | ||
10111 | return err; | ||
10112 | if (!spec->autocfg.line_outs) | ||
10113 | return 0; /* can't find valid BIOS pin config */ | ||
10114 | |||
10115 | err = alc880_auto_fill_dac_nids(spec, &spec->autocfg); | ||
10116 | if (err < 0) | ||
10117 | return err; | ||
10118 | err = alc662_auto_create_multi_out_ctls(spec, &spec->autocfg); | ||
10119 | if (err < 0) | ||
10120 | return err; | ||
10121 | err = alc662_auto_create_extra_out(spec, | ||
10122 | spec->autocfg.speaker_pins[0], | ||
10123 | "Speaker"); | ||
10124 | if (err < 0) | ||
10125 | return err; | ||
10126 | err = alc662_auto_create_extra_out(spec, spec->autocfg.hp_pins[0], | ||
10127 | "Headphone"); | ||
10128 | if (err < 0) | ||
10129 | return err; | ||
10130 | err = alc662_auto_create_analog_input_ctls(spec, &spec->autocfg); | ||
10131 | if (err < 0) | ||
10132 | return err; | ||
10133 | |||
10134 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | ||
10135 | |||
10136 | if (spec->autocfg.dig_out_pin) | ||
10137 | spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; | ||
10138 | |||
10139 | if (spec->kctl_alloc) | ||
10140 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | ||
10141 | |||
10142 | spec->num_mux_defs = 1; | ||
10143 | spec->input_mux = &spec->private_imux; | ||
10144 | |||
10145 | if (err < 0) | ||
10146 | return err; | ||
10147 | else if (err > 0) | ||
10148 | /* hack - override the init verbs */ | ||
10149 | spec->init_verbs[0] = alc662_auto_init_verbs; | ||
10150 | spec->mixers[spec->num_mixers] = alc662_capture_mixer; | ||
10151 | spec->num_mixers++; | ||
10152 | return err; | ||
10153 | } | ||
10154 | |||
10155 | /* additional initialization for auto-configuration model */ | ||
10156 | static void alc662_auto_init(struct hda_codec *codec) | ||
10157 | { | ||
10158 | alc662_auto_init_multi_out(codec); | ||
10159 | alc662_auto_init_hp_out(codec); | ||
10160 | alc662_auto_init_analog_input(codec); | ||
10161 | } | ||
10162 | |||
10163 | static int patch_alc662(struct hda_codec *codec) | ||
10164 | { | ||
10165 | struct alc_spec *spec; | ||
10166 | int err, board_config; | ||
10167 | |||
10168 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
10169 | if (!spec) | ||
10170 | return -ENOMEM; | ||
10171 | |||
10172 | codec->spec = spec; | ||
10173 | |||
10174 | board_config = snd_hda_check_board_config(codec, ALC662_MODEL_LAST, | ||
10175 | alc662_models, | ||
10176 | alc662_cfg_tbl); | ||
10177 | if (board_config < 0) { | ||
10178 | printk(KERN_INFO "hda_codec: Unknown model for ALC662, " | ||
10179 | "trying auto-probe from BIOS...\n"); | ||
10180 | board_config = ALC662_AUTO; | ||
10181 | } | ||
10182 | |||
10183 | if (board_config == ALC662_AUTO) { | ||
10184 | /* automatic parse from the BIOS config */ | ||
10185 | err = alc662_parse_auto_config(codec); | ||
10186 | if (err < 0) { | ||
10187 | alc_free(codec); | ||
10188 | return err; | ||
10189 | } else if (err) { | ||
10190 | printk(KERN_INFO | ||
10191 | "hda_codec: Cannot set up configuration " | ||
10192 | "from BIOS. Using base mode...\n"); | ||
10193 | board_config = ALC662_3ST_2ch_DIG; | ||
10194 | } | ||
10195 | } | ||
10196 | |||
10197 | if (board_config != ALC662_AUTO) | ||
10198 | setup_preset(spec, &alc662_presets[board_config]); | ||
10199 | |||
10200 | spec->stream_name_analog = "ALC662 Analog"; | ||
10201 | spec->stream_analog_playback = &alc662_pcm_analog_playback; | ||
10202 | spec->stream_analog_capture = &alc662_pcm_analog_capture; | ||
10203 | |||
10204 | spec->stream_name_digital = "ALC662 Digital"; | ||
10205 | spec->stream_digital_playback = &alc662_pcm_digital_playback; | ||
10206 | spec->stream_digital_capture = &alc662_pcm_digital_capture; | ||
10207 | |||
10208 | if (!spec->adc_nids && spec->input_mux) { | ||
10209 | spec->adc_nids = alc662_adc_nids; | ||
10210 | spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids); | ||
10211 | } | ||
10212 | |||
10213 | codec->patch_ops = alc_patch_ops; | ||
10214 | if (board_config == ALC662_AUTO) | ||
10215 | spec->init_hook = alc662_auto_init; | ||
10216 | |||
10217 | return 0; | ||
10218 | } | ||
10219 | |||
10220 | /* | ||
8678 | * patch entries | 10221 | * patch entries |
8679 | */ | 10222 | */ |
8680 | struct hda_codec_preset snd_hda_preset_realtek[] = { | 10223 | struct hda_codec_preset snd_hda_preset_realtek[] = { |
8681 | { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 }, | 10224 | { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 }, |
8682 | { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 }, | 10225 | { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 }, |
8683 | { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660", | 10226 | { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660", |
8684 | .patch = patch_alc861 }, | 10227 | .patch = patch_alc861 }, |
8685 | { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd }, | 10228 | { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd }, |
8686 | { .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 }, | 10229 | { .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 }, |
8687 | { .id = 0x10ec0862, .name = "ALC861-VD", .patch = patch_alc861vd }, | 10230 | { .id = 0x10ec0862, .name = "ALC861-VD", .patch = patch_alc861vd }, |
10231 | { .id = 0x10ec0662, .rev = 0x100002, .name = "ALC662 rev2", | ||
10232 | .patch = patch_alc883 }, | ||
10233 | { .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1", | ||
10234 | .patch = patch_alc662 }, | ||
8688 | { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, | 10235 | { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, |
8689 | { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 }, | 10236 | { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 }, |
8690 | { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc883 }, | 10237 | { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc883 }, |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index c94291bc5367..93ae9c250767 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -62,6 +62,7 @@ enum { | |||
62 | STAC_MACBOOK, | 62 | STAC_MACBOOK, |
63 | STAC_MACBOOK_PRO_V1, | 63 | STAC_MACBOOK_PRO_V1, |
64 | STAC_MACBOOK_PRO_V2, | 64 | STAC_MACBOOK_PRO_V2, |
65 | STAC_IMAC_INTEL, | ||
65 | STAC_922X_MODELS | 66 | STAC_922X_MODELS |
66 | }; | 67 | }; |
67 | 68 | ||
@@ -175,8 +176,8 @@ static hda_nid_t stac9205_mux_nids[2] = { | |||
175 | 0x19, 0x1a | 176 | 0x19, 0x1a |
176 | }; | 177 | }; |
177 | 178 | ||
178 | static hda_nid_t stac9205_dmic_nids[3] = { | 179 | static hda_nid_t stac9205_dmic_nids[2] = { |
179 | 0x17, 0x18, 0 | 180 | 0x17, 0x18, |
180 | }; | 181 | }; |
181 | 182 | ||
182 | static hda_nid_t stac9200_pin_nids[8] = { | 183 | static hda_nid_t stac9200_pin_nids[8] = { |
@@ -524,12 +525,6 @@ static unsigned int d945gtp5_pin_configs[10] = { | |||
524 | 0x02a19320, 0x40000100, | 525 | 0x02a19320, 0x40000100, |
525 | }; | 526 | }; |
526 | 527 | ||
527 | static unsigned int macbook_pin_configs[10] = { | ||
528 | 0x0321e230, 0x03a1e020, 0x400000fd, 0x9017e110, | ||
529 | 0x400000fe, 0x0381e021, 0x1345e240, 0x13c5e22e, | ||
530 | 0x400000fc, 0x400000fb, | ||
531 | }; | ||
532 | |||
533 | static unsigned int macbook_pro_v1_pin_configs[10] = { | 528 | static unsigned int macbook_pro_v1_pin_configs[10] = { |
534 | 0x0321e230, 0x03a1e020, 0x9017e110, 0x01014010, | 529 | 0x0321e230, 0x03a1e020, 0x9017e110, 0x01014010, |
535 | 0x01a19021, 0x0381e021, 0x1345e240, 0x13c5e22e, | 530 | 0x01a19021, 0x0381e021, 0x1345e240, 0x13c5e22e, |
@@ -542,14 +537,21 @@ static unsigned int macbook_pro_v2_pin_configs[10] = { | |||
542 | 0x400000fc, 0x400000fb, | 537 | 0x400000fc, 0x400000fb, |
543 | }; | 538 | }; |
544 | 539 | ||
540 | static unsigned int imac_intel_pin_configs[10] = { | ||
541 | 0x0121e230, 0x90a70120, 0x9017e110, 0x400000fe, | ||
542 | 0x400000fd, 0x0181e021, 0x1145e040, 0x400000fa, | ||
543 | 0x400000fc, 0x400000fb, | ||
544 | }; | ||
545 | |||
545 | static unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = { | 546 | static unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = { |
546 | [STAC_D945_REF] = ref922x_pin_configs, | 547 | [STAC_D945_REF] = ref922x_pin_configs, |
547 | [STAC_D945GTP3] = d945gtp3_pin_configs, | 548 | [STAC_D945GTP3] = d945gtp3_pin_configs, |
548 | [STAC_D945GTP5] = d945gtp5_pin_configs, | 549 | [STAC_D945GTP5] = d945gtp5_pin_configs, |
549 | [STAC_MACMINI] = d945gtp5_pin_configs, | 550 | [STAC_MACMINI] = macbook_pro_v1_pin_configs, |
550 | [STAC_MACBOOK] = macbook_pin_configs, | 551 | [STAC_MACBOOK] = macbook_pro_v1_pin_configs, |
551 | [STAC_MACBOOK_PRO_V1] = macbook_pro_v1_pin_configs, | 552 | [STAC_MACBOOK_PRO_V1] = macbook_pro_v1_pin_configs, |
552 | [STAC_MACBOOK_PRO_V2] = macbook_pro_v2_pin_configs, | 553 | [STAC_MACBOOK_PRO_V2] = macbook_pro_v2_pin_configs, |
554 | [STAC_IMAC_INTEL] = imac_intel_pin_configs, | ||
553 | }; | 555 | }; |
554 | 556 | ||
555 | static const char *stac922x_models[STAC_922X_MODELS] = { | 557 | static const char *stac922x_models[STAC_922X_MODELS] = { |
@@ -560,6 +562,7 @@ static const char *stac922x_models[STAC_922X_MODELS] = { | |||
560 | [STAC_MACBOOK] = "macbook", | 562 | [STAC_MACBOOK] = "macbook", |
561 | [STAC_MACBOOK_PRO_V1] = "macbook-pro-v1", | 563 | [STAC_MACBOOK_PRO_V1] = "macbook-pro-v1", |
562 | [STAC_MACBOOK_PRO_V2] = "macbook-pro", | 564 | [STAC_MACBOOK_PRO_V2] = "macbook-pro", |
565 | [STAC_IMAC_INTEL] = "imac-intel", | ||
563 | }; | 566 | }; |
564 | 567 | ||
565 | static struct snd_pci_quirk stac922x_cfg_tbl[] = { | 568 | static struct snd_pci_quirk stac922x_cfg_tbl[] = { |
@@ -820,6 +823,17 @@ static int stac92xx_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, | |||
820 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | 823 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); |
821 | } | 824 | } |
822 | 825 | ||
826 | static int stac92xx_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
827 | struct hda_codec *codec, | ||
828 | unsigned int stream_tag, | ||
829 | unsigned int format, | ||
830 | struct snd_pcm_substream *substream) | ||
831 | { | ||
832 | struct sigmatel_spec *spec = codec->spec; | ||
833 | return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, | ||
834 | stream_tag, format, substream); | ||
835 | } | ||
836 | |||
823 | 837 | ||
824 | /* | 838 | /* |
825 | * Analog capture callbacks | 839 | * Analog capture callbacks |
@@ -854,7 +868,8 @@ static struct hda_pcm_stream stac92xx_pcm_digital_playback = { | |||
854 | /* NID is set in stac92xx_build_pcms */ | 868 | /* NID is set in stac92xx_build_pcms */ |
855 | .ops = { | 869 | .ops = { |
856 | .open = stac92xx_dig_playback_pcm_open, | 870 | .open = stac92xx_dig_playback_pcm_open, |
857 | .close = stac92xx_dig_playback_pcm_close | 871 | .close = stac92xx_dig_playback_pcm_close, |
872 | .prepare = stac92xx_dig_playback_pcm_prepare | ||
858 | }, | 873 | }, |
859 | }; | 874 | }; |
860 | 875 | ||
@@ -1055,11 +1070,23 @@ static int stac92xx_add_control(struct sigmatel_spec *spec, int type, const char | |||
1055 | static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cfg *cfg) | 1070 | static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cfg *cfg) |
1056 | { | 1071 | { |
1057 | struct sigmatel_spec *spec = codec->spec; | 1072 | struct sigmatel_spec *spec = codec->spec; |
1073 | unsigned int wcaps, wtype; | ||
1074 | int i, num_dacs = 0; | ||
1075 | |||
1076 | /* use the wcaps cache to count all DACs available for line-outs */ | ||
1077 | for (i = 0; i < codec->num_nodes; i++) { | ||
1078 | wcaps = codec->wcaps[i]; | ||
1079 | wtype = (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; | ||
1080 | if (wtype == AC_WID_AUD_OUT && !(wcaps & AC_WCAP_DIGITAL)) | ||
1081 | num_dacs++; | ||
1082 | } | ||
1058 | 1083 | ||
1084 | snd_printdd("%s: total dac count=%d\n", __func__, num_dacs); | ||
1085 | |||
1059 | switch (cfg->line_outs) { | 1086 | switch (cfg->line_outs) { |
1060 | case 3: | 1087 | case 3: |
1061 | /* add line-in as side */ | 1088 | /* add line-in as side */ |
1062 | if (cfg->input_pins[AUTO_PIN_LINE]) { | 1089 | if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 3) { |
1063 | cfg->line_out_pins[3] = cfg->input_pins[AUTO_PIN_LINE]; | 1090 | cfg->line_out_pins[3] = cfg->input_pins[AUTO_PIN_LINE]; |
1064 | spec->line_switch = 1; | 1091 | spec->line_switch = 1; |
1065 | cfg->line_outs++; | 1092 | cfg->line_outs++; |
@@ -1067,12 +1094,12 @@ static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cf | |||
1067 | break; | 1094 | break; |
1068 | case 2: | 1095 | case 2: |
1069 | /* add line-in as clfe and mic as side */ | 1096 | /* add line-in as clfe and mic as side */ |
1070 | if (cfg->input_pins[AUTO_PIN_LINE]) { | 1097 | if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 2) { |
1071 | cfg->line_out_pins[2] = cfg->input_pins[AUTO_PIN_LINE]; | 1098 | cfg->line_out_pins[2] = cfg->input_pins[AUTO_PIN_LINE]; |
1072 | spec->line_switch = 1; | 1099 | spec->line_switch = 1; |
1073 | cfg->line_outs++; | 1100 | cfg->line_outs++; |
1074 | } | 1101 | } |
1075 | if (cfg->input_pins[AUTO_PIN_MIC]) { | 1102 | if (cfg->input_pins[AUTO_PIN_MIC] && num_dacs > 3) { |
1076 | cfg->line_out_pins[3] = cfg->input_pins[AUTO_PIN_MIC]; | 1103 | cfg->line_out_pins[3] = cfg->input_pins[AUTO_PIN_MIC]; |
1077 | spec->mic_switch = 1; | 1104 | spec->mic_switch = 1; |
1078 | cfg->line_outs++; | 1105 | cfg->line_outs++; |
@@ -1080,12 +1107,12 @@ static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cf | |||
1080 | break; | 1107 | break; |
1081 | case 1: | 1108 | case 1: |
1082 | /* add line-in as surr and mic as clfe */ | 1109 | /* add line-in as surr and mic as clfe */ |
1083 | if (cfg->input_pins[AUTO_PIN_LINE]) { | 1110 | if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 1) { |
1084 | cfg->line_out_pins[1] = cfg->input_pins[AUTO_PIN_LINE]; | 1111 | cfg->line_out_pins[1] = cfg->input_pins[AUTO_PIN_LINE]; |
1085 | spec->line_switch = 1; | 1112 | spec->line_switch = 1; |
1086 | cfg->line_outs++; | 1113 | cfg->line_outs++; |
1087 | } | 1114 | } |
1088 | if (cfg->input_pins[AUTO_PIN_MIC]) { | 1115 | if (cfg->input_pins[AUTO_PIN_MIC] && num_dacs > 2) { |
1089 | cfg->line_out_pins[2] = cfg->input_pins[AUTO_PIN_MIC]; | 1116 | cfg->line_out_pins[2] = cfg->input_pins[AUTO_PIN_MIC]; |
1090 | spec->mic_switch = 1; | 1117 | spec->mic_switch = 1; |
1091 | cfg->line_outs++; | 1118 | cfg->line_outs++; |
@@ -1096,33 +1123,76 @@ static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cf | |||
1096 | return 0; | 1123 | return 0; |
1097 | } | 1124 | } |
1098 | 1125 | ||
1126 | |||
1127 | static int is_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid) | ||
1128 | { | ||
1129 | int i; | ||
1130 | |||
1131 | for (i = 0; i < spec->multiout.num_dacs; i++) { | ||
1132 | if (spec->multiout.dac_nids[i] == nid) | ||
1133 | return 1; | ||
1134 | } | ||
1135 | |||
1136 | return 0; | ||
1137 | } | ||
1138 | |||
1099 | /* | 1139 | /* |
1100 | * XXX The line_out pin widget connection list may not be set to the | 1140 | * Fill in the dac_nids table from the parsed pin configuration |
1101 | * desired DAC nid. This is the case on 927x where ports A and B can | 1141 | * This function only works when every pin in line_out_pins[] |
1102 | * be routed to several DACs. | 1142 | * contains atleast one DAC in its connection list. Some 92xx |
1103 | * | 1143 | * codecs are not connected directly to a DAC, such as the 9200 |
1104 | * This requires an analysis of the line-out/hp pin configuration | 1144 | * and 9202/925x. For those, dac_nids[] must be hard-coded. |
1105 | * to provide a best fit for pin/DAC configurations that are routable. | ||
1106 | * For now, 927x DAC4 is not supported and 927x DAC1 output to ports | ||
1107 | * A and B is not supported. | ||
1108 | */ | 1145 | */ |
1109 | /* fill in the dac_nids table from the parsed pin configuration */ | ||
1110 | static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec, | 1146 | static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec, |
1111 | const struct auto_pin_cfg *cfg) | 1147 | const struct auto_pin_cfg *cfg) |
1112 | { | 1148 | { |
1113 | struct sigmatel_spec *spec = codec->spec; | 1149 | struct sigmatel_spec *spec = codec->spec; |
1114 | hda_nid_t nid; | 1150 | int i, j, conn_len = 0; |
1115 | int i; | 1151 | hda_nid_t nid, conn[HDA_MAX_CONNECTIONS]; |
1116 | 1152 | unsigned int wcaps, wtype; | |
1117 | /* check the pins hardwired to audio widget */ | 1153 | |
1118 | for (i = 0; i < cfg->line_outs; i++) { | 1154 | for (i = 0; i < cfg->line_outs; i++) { |
1119 | nid = cfg->line_out_pins[i]; | 1155 | nid = cfg->line_out_pins[i]; |
1120 | spec->multiout.dac_nids[i] = snd_hda_codec_read(codec, nid, 0, | 1156 | conn_len = snd_hda_get_connections(codec, nid, conn, |
1121 | AC_VERB_GET_CONNECT_LIST, 0) & 0xff; | 1157 | HDA_MAX_CONNECTIONS); |
1122 | } | 1158 | for (j = 0; j < conn_len; j++) { |
1159 | wcaps = snd_hda_param_read(codec, conn[j], | ||
1160 | AC_PAR_AUDIO_WIDGET_CAP); | ||
1161 | wtype = (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; | ||
1162 | |||
1163 | if (wtype != AC_WID_AUD_OUT || | ||
1164 | (wcaps & AC_WCAP_DIGITAL)) | ||
1165 | continue; | ||
1166 | /* conn[j] is a DAC routed to this line-out */ | ||
1167 | if (!is_in_dac_nids(spec, conn[j])) | ||
1168 | break; | ||
1169 | } | ||
1170 | |||
1171 | if (j == conn_len) { | ||
1172 | /* error out, no available DAC found */ | ||
1173 | snd_printk(KERN_ERR | ||
1174 | "%s: No available DAC for pin 0x%x\n", | ||
1175 | __func__, nid); | ||
1176 | return -ENODEV; | ||
1177 | } | ||
1123 | 1178 | ||
1124 | spec->multiout.num_dacs = cfg->line_outs; | 1179 | spec->multiout.dac_nids[i] = conn[j]; |
1180 | spec->multiout.num_dacs++; | ||
1181 | if (conn_len > 1) { | ||
1182 | /* select this DAC in the pin's input mux */ | ||
1183 | snd_hda_codec_write(codec, nid, 0, | ||
1184 | AC_VERB_SET_CONNECT_SEL, j); | ||
1185 | |||
1186 | } | ||
1187 | } | ||
1125 | 1188 | ||
1189 | snd_printd("dac_nids=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", | ||
1190 | spec->multiout.num_dacs, | ||
1191 | spec->multiout.dac_nids[0], | ||
1192 | spec->multiout.dac_nids[1], | ||
1193 | spec->multiout.dac_nids[2], | ||
1194 | spec->multiout.dac_nids[3], | ||
1195 | spec->multiout.dac_nids[4]); | ||
1126 | return 0; | 1196 | return 0; |
1127 | } | 1197 | } |
1128 | 1198 | ||
@@ -1189,12 +1259,8 @@ static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec, | |||
1189 | 1259 | ||
1190 | static int check_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid) | 1260 | static int check_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid) |
1191 | { | 1261 | { |
1192 | int i; | 1262 | if (is_in_dac_nids(spec, nid)) |
1193 | 1263 | return 1; | |
1194 | for (i = 0; i < spec->multiout.num_dacs; i++) { | ||
1195 | if (spec->multiout.dac_nids[i] == nid) | ||
1196 | return 1; | ||
1197 | } | ||
1198 | if (spec->multiout.hp_nid == nid) | 1264 | if (spec->multiout.hp_nid == nid) |
1199 | return 1; | 1265 | return 1; |
1200 | return 0; | 1266 | return 0; |
@@ -1236,12 +1302,10 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, | |||
1236 | add_spec_dacs(spec, nid); | 1302 | add_spec_dacs(spec, nid); |
1237 | } | 1303 | } |
1238 | for (i = 0; i < cfg->speaker_outs; i++) { | 1304 | for (i = 0; i < cfg->speaker_outs; i++) { |
1239 | nid = snd_hda_codec_read(codec, cfg->speaker_pins[0], 0, | 1305 | nid = snd_hda_codec_read(codec, cfg->speaker_pins[i], 0, |
1240 | AC_VERB_GET_CONNECT_LIST, 0) & 0xff; | 1306 | AC_VERB_GET_CONNECT_LIST, 0) & 0xff; |
1241 | if (check_in_dac_nids(spec, nid)) | 1307 | if (check_in_dac_nids(spec, nid)) |
1242 | nid = 0; | 1308 | nid = 0; |
1243 | if (check_in_dac_nids(spec, nid)) | ||
1244 | nid = 0; | ||
1245 | if (! nid) | 1309 | if (! nid) |
1246 | continue; | 1310 | continue; |
1247 | add_spec_dacs(spec, nid); | 1311 | add_spec_dacs(spec, nid); |
@@ -1355,7 +1419,7 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const | |||
1355 | imux->num_items++; | 1419 | imux->num_items++; |
1356 | } | 1420 | } |
1357 | 1421 | ||
1358 | if (imux->num_items == 1) { | 1422 | if (imux->num_items) { |
1359 | /* | 1423 | /* |
1360 | * Set the current input for the muxes. | 1424 | * Set the current input for the muxes. |
1361 | * The STAC9221 has two input muxes with identical source | 1425 | * The STAC9221 has two input muxes with identical source |
@@ -1675,8 +1739,12 @@ static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid, | |||
1675 | { | 1739 | { |
1676 | unsigned int pin_ctl = snd_hda_codec_read(codec, nid, | 1740 | unsigned int pin_ctl = snd_hda_codec_read(codec, nid, |
1677 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); | 1741 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); |
1678 | if (flag == AC_PINCTL_OUT_EN && (pin_ctl & AC_PINCTL_IN_EN)) | 1742 | |
1679 | return; | 1743 | /* if setting pin direction bits, clear the current |
1744 | direction bits first */ | ||
1745 | if (flag & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN)) | ||
1746 | pin_ctl &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN); | ||
1747 | |||
1680 | snd_hda_codec_write(codec, nid, 0, | 1748 | snd_hda_codec_write(codec, nid, 0, |
1681 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 1749 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
1682 | pin_ctl | flag); | 1750 | pin_ctl | flag); |
@@ -1751,6 +1819,7 @@ static int stac92xx_resume(struct hda_codec *codec) | |||
1751 | 1819 | ||
1752 | stac92xx_init(codec); | 1820 | stac92xx_init(codec); |
1753 | stac92xx_set_config_regs(codec); | 1821 | stac92xx_set_config_regs(codec); |
1822 | snd_hda_resume_ctls(codec, spec->mixer); | ||
1754 | for (i = 0; i < spec->num_mixers; i++) | 1823 | for (i = 0; i < spec->num_mixers; i++) |
1755 | snd_hda_resume_ctls(codec, spec->mixers[i]); | 1824 | snd_hda_resume_ctls(codec, spec->mixers[i]); |
1756 | if (spec->multiout.dig_out_nid) | 1825 | if (spec->multiout.dig_out_nid) |
@@ -1905,12 +1974,18 @@ static int patch_stac922x(struct hda_codec *codec) | |||
1905 | */ | 1974 | */ |
1906 | printk(KERN_INFO "hda_codec: STAC922x, Apple subsys_id=%x\n", codec->subsystem_id); | 1975 | printk(KERN_INFO "hda_codec: STAC922x, Apple subsys_id=%x\n", codec->subsystem_id); |
1907 | switch (codec->subsystem_id) { | 1976 | switch (codec->subsystem_id) { |
1977 | case 0x106b0a00: /* MacBook First generatoin */ | ||
1978 | spec->board_config = STAC_MACBOOK; | ||
1979 | break; | ||
1908 | case 0x106b0200: /* MacBook Pro first generation */ | 1980 | case 0x106b0200: /* MacBook Pro first generation */ |
1909 | spec->board_config = STAC_MACBOOK_PRO_V1; | 1981 | spec->board_config = STAC_MACBOOK_PRO_V1; |
1910 | break; | 1982 | break; |
1911 | case 0x106b1e00: /* MacBook Pro second generation */ | 1983 | case 0x106b1e00: /* MacBook Pro second generation */ |
1912 | spec->board_config = STAC_MACBOOK_PRO_V2; | 1984 | spec->board_config = STAC_MACBOOK_PRO_V2; |
1913 | break; | 1985 | break; |
1986 | case 0x106b0700: /* Intel-based iMac */ | ||
1987 | spec->board_config = STAC_IMAC_INTEL; | ||
1988 | break; | ||
1914 | } | 1989 | } |
1915 | } | 1990 | } |
1916 | 1991 | ||
@@ -1931,7 +2006,7 @@ static int patch_stac922x(struct hda_codec *codec) | |||
1931 | 2006 | ||
1932 | spec->adc_nids = stac922x_adc_nids; | 2007 | spec->adc_nids = stac922x_adc_nids; |
1933 | spec->mux_nids = stac922x_mux_nids; | 2008 | spec->mux_nids = stac922x_mux_nids; |
1934 | spec->num_muxes = 2; | 2009 | spec->num_muxes = ARRAY_SIZE(stac922x_mux_nids); |
1935 | spec->num_dmics = 0; | 2010 | spec->num_dmics = 0; |
1936 | 2011 | ||
1937 | spec->init = stac922x_core_init; | 2012 | spec->init = stac922x_core_init; |
@@ -1992,7 +2067,7 @@ static int patch_stac927x(struct hda_codec *codec) | |||
1992 | case STAC_D965_3ST: | 2067 | case STAC_D965_3ST: |
1993 | spec->adc_nids = stac927x_adc_nids; | 2068 | spec->adc_nids = stac927x_adc_nids; |
1994 | spec->mux_nids = stac927x_mux_nids; | 2069 | spec->mux_nids = stac927x_mux_nids; |
1995 | spec->num_muxes = 3; | 2070 | spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids); |
1996 | spec->num_dmics = 0; | 2071 | spec->num_dmics = 0; |
1997 | spec->init = d965_core_init; | 2072 | spec->init = d965_core_init; |
1998 | spec->mixer = stac9227_mixer; | 2073 | spec->mixer = stac9227_mixer; |
@@ -2000,7 +2075,7 @@ static int patch_stac927x(struct hda_codec *codec) | |||
2000 | case STAC_D965_5ST: | 2075 | case STAC_D965_5ST: |
2001 | spec->adc_nids = stac927x_adc_nids; | 2076 | spec->adc_nids = stac927x_adc_nids; |
2002 | spec->mux_nids = stac927x_mux_nids; | 2077 | spec->mux_nids = stac927x_mux_nids; |
2003 | spec->num_muxes = 3; | 2078 | spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids); |
2004 | spec->num_dmics = 0; | 2079 | spec->num_dmics = 0; |
2005 | spec->init = d965_core_init; | 2080 | spec->init = d965_core_init; |
2006 | spec->mixer = stac9227_mixer; | 2081 | spec->mixer = stac9227_mixer; |
@@ -2008,7 +2083,7 @@ static int patch_stac927x(struct hda_codec *codec) | |||
2008 | default: | 2083 | default: |
2009 | spec->adc_nids = stac927x_adc_nids; | 2084 | spec->adc_nids = stac927x_adc_nids; |
2010 | spec->mux_nids = stac927x_mux_nids; | 2085 | spec->mux_nids = stac927x_mux_nids; |
2011 | spec->num_muxes = 3; | 2086 | spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids); |
2012 | spec->num_dmics = 0; | 2087 | spec->num_dmics = 0; |
2013 | spec->init = stac927x_core_init; | 2088 | spec->init = stac927x_core_init; |
2014 | spec->mixer = stac927x_mixer; | 2089 | spec->mixer = stac927x_mixer; |
@@ -2067,9 +2142,9 @@ static int patch_stac9205(struct hda_codec *codec) | |||
2067 | 2142 | ||
2068 | spec->adc_nids = stac9205_adc_nids; | 2143 | spec->adc_nids = stac9205_adc_nids; |
2069 | spec->mux_nids = stac9205_mux_nids; | 2144 | spec->mux_nids = stac9205_mux_nids; |
2070 | spec->num_muxes = 2; | 2145 | spec->num_muxes = ARRAY_SIZE(stac9205_mux_nids); |
2071 | spec->dmic_nids = stac9205_dmic_nids; | 2146 | spec->dmic_nids = stac9205_dmic_nids; |
2072 | spec->num_dmics = 2; | 2147 | spec->num_dmics = ARRAY_SIZE(stac9205_dmic_nids); |
2073 | spec->dmux_nid = 0x1d; | 2148 | spec->dmux_nid = 0x1d; |
2074 | 2149 | ||
2075 | spec->init = stac9205_core_init; | 2150 | spec->init = stac9205_core_init; |
@@ -2294,6 +2369,7 @@ static struct snd_pci_quirk stac9872_cfg_tbl[] = { | |||
2294 | SND_PCI_QUIRK(0x104d, 0x81e6, "Sony VAIO F/S", CXD9872RD_VAIO), | 2369 | SND_PCI_QUIRK(0x104d, 0x81e6, "Sony VAIO F/S", CXD9872RD_VAIO), |
2295 | SND_PCI_QUIRK(0x104d, 0x81ef, "Sony VAIO F/S", CXD9872RD_VAIO), | 2370 | SND_PCI_QUIRK(0x104d, 0x81ef, "Sony VAIO F/S", CXD9872RD_VAIO), |
2296 | SND_PCI_QUIRK(0x104d, 0x81fd, "Sony VAIO AR", CXD9872AKD_VAIO), | 2371 | SND_PCI_QUIRK(0x104d, 0x81fd, "Sony VAIO AR", CXD9872AKD_VAIO), |
2372 | SND_PCI_QUIRK(0x104d, 0x8205, "Sony VAIO AR", CXD9872AKD_VAIO), | ||
2297 | {} | 2373 | {} |
2298 | }; | 2374 | }; |
2299 | 2375 | ||
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 2b11ac8689b9..ba32d1e52cb8 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c | |||
@@ -377,6 +377,17 @@ static int via_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, | |||
377 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | 377 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); |
378 | } | 378 | } |
379 | 379 | ||
380 | static int via_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
381 | struct hda_codec *codec, | ||
382 | unsigned int stream_tag, | ||
383 | unsigned int format, | ||
384 | struct snd_pcm_substream *substream) | ||
385 | { | ||
386 | struct via_spec *spec = codec->spec; | ||
387 | return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, | ||
388 | stream_tag, format, substream); | ||
389 | } | ||
390 | |||
380 | /* | 391 | /* |
381 | * Analog capture | 392 | * Analog capture |
382 | */ | 393 | */ |
@@ -433,7 +444,8 @@ static struct hda_pcm_stream vt1708_pcm_digital_playback = { | |||
433 | /* NID is set in via_build_pcms */ | 444 | /* NID is set in via_build_pcms */ |
434 | .ops = { | 445 | .ops = { |
435 | .open = via_dig_playback_pcm_open, | 446 | .open = via_dig_playback_pcm_open, |
436 | .close = via_dig_playback_pcm_close | 447 | .close = via_dig_playback_pcm_close, |
448 | .prepare = via_dig_playback_pcm_prepare | ||
437 | }, | 449 | }, |
438 | }; | 450 | }; |
439 | 451 | ||