diff options
Diffstat (limited to 'sound/pci/hda/patch_hdmi.c')
-rw-r--r-- | sound/pci/hda/patch_hdmi.c | 987 |
1 files changed, 903 insertions, 84 deletions
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index afd6022a96a7..bd0ae697f9c4 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
@@ -3,6 +3,9 @@ | |||
3 | * patch_hdmi.c - routines for HDMI/DisplayPort codecs | 3 | * patch_hdmi.c - routines for HDMI/DisplayPort codecs |
4 | * | 4 | * |
5 | * Copyright(c) 2008-2010 Intel Corporation. All rights reserved. | 5 | * Copyright(c) 2008-2010 Intel Corporation. All rights reserved. |
6 | * Copyright (c) 2006 ATI Technologies Inc. | ||
7 | * Copyright (c) 2008 NVIDIA Corp. All rights reserved. | ||
8 | * Copyright (c) 2008 Wei Ni <wni@nvidia.com> | ||
6 | * | 9 | * |
7 | * Authors: | 10 | * Authors: |
8 | * Wu Fengguang <wfg@linux.intel.com> | 11 | * Wu Fengguang <wfg@linux.intel.com> |
@@ -25,6 +28,28 @@ | |||
25 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 28 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
26 | */ | 29 | */ |
27 | 30 | ||
31 | #include <linux/init.h> | ||
32 | #include <linux/delay.h> | ||
33 | #include <linux/slab.h> | ||
34 | #include <linux/moduleparam.h> | ||
35 | #include <sound/core.h> | ||
36 | #include <sound/jack.h> | ||
37 | #include "hda_codec.h" | ||
38 | #include "hda_local.h" | ||
39 | |||
40 | static bool static_hdmi_pcm; | ||
41 | module_param(static_hdmi_pcm, bool, 0644); | ||
42 | MODULE_PARM_DESC(static_hdmi_pcm, "Don't restrict PCM parameters per ELD info"); | ||
43 | |||
44 | /* | ||
45 | * The HDMI/DisplayPort configuration can be highly dynamic. A graphics device | ||
46 | * could support two independent pipes, each of them can be connected to one or | ||
47 | * more ports (DVI, HDMI or DisplayPort). | ||
48 | * | ||
49 | * The HDA correspondence of pipes/ports are converter/pin nodes. | ||
50 | */ | ||
51 | #define MAX_HDMI_CVTS 4 | ||
52 | #define MAX_HDMI_PINS 4 | ||
28 | 53 | ||
29 | struct hdmi_spec { | 54 | struct hdmi_spec { |
30 | int num_cvts; | 55 | int num_cvts; |
@@ -49,14 +74,10 @@ struct hdmi_spec { | |||
49 | struct hda_pcm_stream codec_pcm_pars[MAX_HDMI_CVTS]; | 74 | struct hda_pcm_stream codec_pcm_pars[MAX_HDMI_CVTS]; |
50 | 75 | ||
51 | /* | 76 | /* |
52 | * nvhdmi specific | 77 | * ati/nvhdmi specific |
53 | */ | 78 | */ |
54 | struct hda_multi_out multiout; | 79 | struct hda_multi_out multiout; |
55 | unsigned int codec_type; | 80 | const struct hda_pcm_stream *pcm_playback; |
56 | |||
57 | /* misc flags */ | ||
58 | /* PD bit indicates only the update, not the current state */ | ||
59 | unsigned int old_pin_detect:1; | ||
60 | }; | 81 | }; |
61 | 82 | ||
62 | 83 | ||
@@ -65,13 +86,31 @@ struct hdmi_audio_infoframe { | |||
65 | u8 ver; /* 0x01 */ | 86 | u8 ver; /* 0x01 */ |
66 | u8 len; /* 0x0a */ | 87 | u8 len; /* 0x0a */ |
67 | 88 | ||
68 | u8 checksum; /* PB0 */ | 89 | u8 checksum; |
90 | |||
69 | u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */ | 91 | u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */ |
70 | u8 SS01_SF24; | 92 | u8 SS01_SF24; |
71 | u8 CXT04; | 93 | u8 CXT04; |
72 | u8 CA; | 94 | u8 CA; |
73 | u8 LFEPBL01_LSV36_DM_INH7; | 95 | u8 LFEPBL01_LSV36_DM_INH7; |
74 | u8 reserved[5]; /* PB6 - PB10 */ | 96 | }; |
97 | |||
98 | struct dp_audio_infoframe { | ||
99 | u8 type; /* 0x84 */ | ||
100 | u8 len; /* 0x1b */ | ||
101 | u8 ver; /* 0x11 << 2 */ | ||
102 | |||
103 | u8 CC02_CT47; /* match with HDMI infoframe from this on */ | ||
104 | u8 SS01_SF24; | ||
105 | u8 CXT04; | ||
106 | u8 CA; | ||
107 | u8 LFEPBL01_LSV36_DM_INH7; | ||
108 | }; | ||
109 | |||
110 | union audio_infoframe { | ||
111 | struct hdmi_audio_infoframe hdmi; | ||
112 | struct dp_audio_infoframe dp; | ||
113 | u8 bytes[0]; | ||
75 | }; | 114 | }; |
76 | 115 | ||
77 | /* | 116 | /* |
@@ -162,7 +201,7 @@ static int hdmi_channel_mapping[0x32][8] = { | |||
162 | /* 4ch */ | 201 | /* 4ch */ |
163 | [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 }, | 202 | [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 }, |
164 | /* surround41 */ | 203 | /* surround41 */ |
165 | [0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 }, | 204 | [0x09] = { 0x00, 0x11, 0x24, 0x35, 0x42, 0xf3, 0xf6, 0xf7 }, |
166 | /* surround50 */ | 205 | /* surround50 */ |
167 | [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 }, | 206 | [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 }, |
168 | /* surround51 */ | 207 | /* surround51 */ |
@@ -175,7 +214,7 @@ static int hdmi_channel_mapping[0x32][8] = { | |||
175 | * This is an ordered list! | 214 | * This is an ordered list! |
176 | * | 215 | * |
177 | * The preceding ones have better chances to be selected by | 216 | * The preceding ones have better chances to be selected by |
178 | * hdmi_setup_channel_allocation(). | 217 | * hdmi_channel_allocation(). |
179 | */ | 218 | */ |
180 | static struct cea_channel_speaker_allocation channel_allocations[] = { | 219 | static struct cea_channel_speaker_allocation channel_allocations[] = { |
181 | /* channel: 7 6 5 4 3 2 1 0 */ | 220 | /* channel: 7 6 5 4 3 2 1 0 */ |
@@ -257,13 +296,6 @@ static int hda_node_index(hda_nid_t *nids, hda_nid_t nid) | |||
257 | return -EINVAL; | 296 | return -EINVAL; |
258 | } | 297 | } |
259 | 298 | ||
260 | static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid, | ||
261 | struct hdmi_eld *eld) | ||
262 | { | ||
263 | if (!snd_hdmi_get_eld(eld, codec, pin_nid)) | ||
264 | snd_hdmi_show_eld(eld); | ||
265 | } | ||
266 | |||
267 | #ifdef BE_PARANOID | 299 | #ifdef BE_PARANOID |
268 | static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, | 300 | static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, |
269 | int *packet_index, int *byte_index) | 301 | int *packet_index, int *byte_index) |
@@ -352,14 +384,14 @@ static void init_channel_allocations(void) | |||
352 | * | 384 | * |
353 | * TODO: it could select the wrong CA from multiple candidates. | 385 | * TODO: it could select the wrong CA from multiple candidates. |
354 | */ | 386 | */ |
355 | static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid, | 387 | static int hdmi_channel_allocation(struct hda_codec *codec, hda_nid_t nid, |
356 | struct hdmi_audio_infoframe *ai) | 388 | int channels) |
357 | { | 389 | { |
358 | struct hdmi_spec *spec = codec->spec; | 390 | struct hdmi_spec *spec = codec->spec; |
359 | struct hdmi_eld *eld; | 391 | struct hdmi_eld *eld; |
360 | int i; | 392 | int i; |
393 | int ca = 0; | ||
361 | int spk_mask = 0; | 394 | int spk_mask = 0; |
362 | int channels = 1 + (ai->CC02_CT47 & 0x7); | ||
363 | char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; | 395 | char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; |
364 | 396 | ||
365 | /* | 397 | /* |
@@ -397,16 +429,16 @@ static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid, | |||
397 | if (channels == channel_allocations[i].channels && | 429 | if (channels == channel_allocations[i].channels && |
398 | (spk_mask & channel_allocations[i].spk_mask) == | 430 | (spk_mask & channel_allocations[i].spk_mask) == |
399 | channel_allocations[i].spk_mask) { | 431 | channel_allocations[i].spk_mask) { |
400 | ai->CA = channel_allocations[i].ca_index; | 432 | ca = channel_allocations[i].ca_index; |
401 | break; | 433 | break; |
402 | } | 434 | } |
403 | } | 435 | } |
404 | 436 | ||
405 | snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf)); | 437 | snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf)); |
406 | snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n", | 438 | snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n", |
407 | ai->CA, channels, buf); | 439 | ca, channels, buf); |
408 | 440 | ||
409 | return ai->CA; | 441 | return ca; |
410 | } | 442 | } |
411 | 443 | ||
412 | static void hdmi_debug_channel_mapping(struct hda_codec *codec, | 444 | static void hdmi_debug_channel_mapping(struct hda_codec *codec, |
@@ -428,10 +460,9 @@ static void hdmi_debug_channel_mapping(struct hda_codec *codec, | |||
428 | 460 | ||
429 | static void hdmi_setup_channel_mapping(struct hda_codec *codec, | 461 | static void hdmi_setup_channel_mapping(struct hda_codec *codec, |
430 | hda_nid_t pin_nid, | 462 | hda_nid_t pin_nid, |
431 | struct hdmi_audio_infoframe *ai) | 463 | int ca) |
432 | { | 464 | { |
433 | int i; | 465 | int i; |
434 | int ca = ai->CA; | ||
435 | int err; | 466 | int err; |
436 | 467 | ||
437 | if (hdmi_channel_mapping[ca][1] == 0) { | 468 | if (hdmi_channel_mapping[ca][1] == 0) { |
@@ -528,41 +559,37 @@ static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid) | |||
528 | #endif | 559 | #endif |
529 | } | 560 | } |
530 | 561 | ||
531 | static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai) | 562 | static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *hdmi_ai) |
532 | { | 563 | { |
533 | u8 *bytes = (u8 *)ai; | 564 | u8 *bytes = (u8 *)hdmi_ai; |
534 | u8 sum = 0; | 565 | u8 sum = 0; |
535 | int i; | 566 | int i; |
536 | 567 | ||
537 | ai->checksum = 0; | 568 | hdmi_ai->checksum = 0; |
538 | 569 | ||
539 | for (i = 0; i < sizeof(*ai); i++) | 570 | for (i = 0; i < sizeof(*hdmi_ai); i++) |
540 | sum += bytes[i]; | 571 | sum += bytes[i]; |
541 | 572 | ||
542 | ai->checksum = -sum; | 573 | hdmi_ai->checksum = -sum; |
543 | } | 574 | } |
544 | 575 | ||
545 | static void hdmi_fill_audio_infoframe(struct hda_codec *codec, | 576 | static void hdmi_fill_audio_infoframe(struct hda_codec *codec, |
546 | hda_nid_t pin_nid, | 577 | hda_nid_t pin_nid, |
547 | struct hdmi_audio_infoframe *ai) | 578 | u8 *dip, int size) |
548 | { | 579 | { |
549 | u8 *bytes = (u8 *)ai; | ||
550 | int i; | 580 | int i; |
551 | 581 | ||
552 | hdmi_debug_dip_size(codec, pin_nid); | 582 | hdmi_debug_dip_size(codec, pin_nid); |
553 | hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */ | 583 | hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */ |
554 | 584 | ||
555 | hdmi_checksum_audio_infoframe(ai); | ||
556 | |||
557 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); | 585 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); |
558 | for (i = 0; i < sizeof(*ai); i++) | 586 | for (i = 0; i < size; i++) |
559 | hdmi_write_dip_byte(codec, pin_nid, bytes[i]); | 587 | hdmi_write_dip_byte(codec, pin_nid, dip[i]); |
560 | } | 588 | } |
561 | 589 | ||
562 | static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, | 590 | static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, |
563 | struct hdmi_audio_infoframe *ai) | 591 | u8 *dip, int size) |
564 | { | 592 | { |
565 | u8 *bytes = (u8 *)ai; | ||
566 | u8 val; | 593 | u8 val; |
567 | int i; | 594 | int i; |
568 | 595 | ||
@@ -571,10 +598,10 @@ static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, | |||
571 | return false; | 598 | return false; |
572 | 599 | ||
573 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); | 600 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); |
574 | for (i = 0; i < sizeof(*ai); i++) { | 601 | for (i = 0; i < size; i++) { |
575 | val = snd_hda_codec_read(codec, pin_nid, 0, | 602 | val = snd_hda_codec_read(codec, pin_nid, 0, |
576 | AC_VERB_GET_HDMI_DIP_DATA, 0); | 603 | AC_VERB_GET_HDMI_DIP_DATA, 0); |
577 | if (val != bytes[i]) | 604 | if (val != dip[i]) |
578 | return false; | 605 | return false; |
579 | } | 606 | } |
580 | 607 | ||
@@ -586,15 +613,12 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid, | |||
586 | { | 613 | { |
587 | struct hdmi_spec *spec = codec->spec; | 614 | struct hdmi_spec *spec = codec->spec; |
588 | hda_nid_t pin_nid; | 615 | hda_nid_t pin_nid; |
616 | int channels = substream->runtime->channels; | ||
617 | int ca; | ||
589 | int i; | 618 | int i; |
590 | struct hdmi_audio_infoframe ai = { | 619 | union audio_infoframe ai; |
591 | .type = 0x84, | ||
592 | .ver = 0x01, | ||
593 | .len = 0x0a, | ||
594 | .CC02_CT47 = substream->runtime->channels - 1, | ||
595 | }; | ||
596 | 620 | ||
597 | hdmi_setup_channel_allocation(codec, nid, &ai); | 621 | ca = hdmi_channel_allocation(codec, nid, channels); |
598 | 622 | ||
599 | for (i = 0; i < spec->num_pins; i++) { | 623 | for (i = 0; i < spec->num_pins; i++) { |
600 | if (spec->pin_cvt[i] != nid) | 624 | if (spec->pin_cvt[i] != nid) |
@@ -603,14 +627,46 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid, | |||
603 | continue; | 627 | continue; |
604 | 628 | ||
605 | pin_nid = spec->pin[i]; | 629 | pin_nid = spec->pin[i]; |
606 | if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) { | 630 | |
631 | memset(&ai, 0, sizeof(ai)); | ||
632 | if (spec->sink_eld[i].conn_type == 0) { /* HDMI */ | ||
633 | struct hdmi_audio_infoframe *hdmi_ai = &ai.hdmi; | ||
634 | |||
635 | hdmi_ai->type = 0x84; | ||
636 | hdmi_ai->ver = 0x01; | ||
637 | hdmi_ai->len = 0x0a; | ||
638 | hdmi_ai->CC02_CT47 = channels - 1; | ||
639 | hdmi_ai->CA = ca; | ||
640 | hdmi_checksum_audio_infoframe(hdmi_ai); | ||
641 | } else if (spec->sink_eld[i].conn_type == 1) { /* DisplayPort */ | ||
642 | struct dp_audio_infoframe *dp_ai = &ai.dp; | ||
643 | |||
644 | dp_ai->type = 0x84; | ||
645 | dp_ai->len = 0x1b; | ||
646 | dp_ai->ver = 0x11 << 2; | ||
647 | dp_ai->CC02_CT47 = channels - 1; | ||
648 | dp_ai->CA = ca; | ||
649 | } else { | ||
650 | snd_printd("HDMI: unknown connection type at pin %d\n", | ||
651 | pin_nid); | ||
652 | continue; | ||
653 | } | ||
654 | |||
655 | /* | ||
656 | * sizeof(ai) is used instead of sizeof(*hdmi_ai) or | ||
657 | * sizeof(*dp_ai) to avoid partial match/update problems when | ||
658 | * the user switches between HDMI/DP monitors. | ||
659 | */ | ||
660 | if (!hdmi_infoframe_uptodate(codec, pin_nid, ai.bytes, | ||
661 | sizeof(ai))) { | ||
607 | snd_printdd("hdmi_setup_audio_infoframe: " | 662 | snd_printdd("hdmi_setup_audio_infoframe: " |
608 | "cvt=%d pin=%d channels=%d\n", | 663 | "cvt=%d pin=%d channels=%d\n", |
609 | nid, pin_nid, | 664 | nid, pin_nid, |
610 | substream->runtime->channels); | 665 | channels); |
611 | hdmi_setup_channel_mapping(codec, pin_nid, &ai); | 666 | hdmi_setup_channel_mapping(codec, pin_nid, ca); |
612 | hdmi_stop_infoframe_trans(codec, pin_nid); | 667 | hdmi_stop_infoframe_trans(codec, pin_nid); |
613 | hdmi_fill_audio_infoframe(codec, pin_nid, &ai); | 668 | hdmi_fill_audio_infoframe(codec, pin_nid, |
669 | ai.bytes, sizeof(ai)); | ||
614 | hdmi_start_infoframe_trans(codec, pin_nid); | 670 | hdmi_start_infoframe_trans(codec, pin_nid); |
615 | } | 671 | } |
616 | } | 672 | } |
@@ -627,33 +683,20 @@ static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid, | |||
627 | static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) | 683 | static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) |
628 | { | 684 | { |
629 | struct hdmi_spec *spec = codec->spec; | 685 | struct hdmi_spec *spec = codec->spec; |
630 | int tag = res >> AC_UNSOL_RES_TAG_SHIFT; | 686 | int pin_nid = res >> AC_UNSOL_RES_TAG_SHIFT; |
631 | int pind = !!(res & AC_UNSOL_RES_PD); | 687 | int pd = !!(res & AC_UNSOL_RES_PD); |
632 | int eldv = !!(res & AC_UNSOL_RES_ELDV); | 688 | int eldv = !!(res & AC_UNSOL_RES_ELDV); |
633 | int index; | 689 | int index; |
634 | 690 | ||
635 | printk(KERN_INFO | 691 | printk(KERN_INFO |
636 | "HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n", | 692 | "HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n", |
637 | tag, pind, eldv); | 693 | pin_nid, pd, eldv); |
638 | 694 | ||
639 | index = hda_node_index(spec->pin, tag); | 695 | index = hda_node_index(spec->pin, pin_nid); |
640 | if (index < 0) | 696 | if (index < 0) |
641 | return; | 697 | return; |
642 | 698 | ||
643 | if (spec->old_pin_detect) { | 699 | hdmi_present_sense(codec, pin_nid, &spec->sink_eld[index]); |
644 | if (pind) | ||
645 | hdmi_present_sense(codec, tag, &spec->sink_eld[index]); | ||
646 | pind = spec->sink_eld[index].monitor_present; | ||
647 | } | ||
648 | |||
649 | spec->sink_eld[index].monitor_present = pind; | ||
650 | spec->sink_eld[index].eld_valid = eldv; | ||
651 | |||
652 | if (pind && eldv) { | ||
653 | hdmi_get_show_eld(codec, spec->pin[index], | ||
654 | &spec->sink_eld[index]); | ||
655 | /* TODO: do real things about ELD */ | ||
656 | } | ||
657 | } | 700 | } |
658 | 701 | ||
659 | static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) | 702 | static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) |
@@ -757,6 +800,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, | |||
757 | struct hdmi_spec *spec = codec->spec; | 800 | struct hdmi_spec *spec = codec->spec; |
758 | struct hdmi_eld *eld; | 801 | struct hdmi_eld *eld; |
759 | struct hda_pcm_stream *codec_pars; | 802 | struct hda_pcm_stream *codec_pars; |
803 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
760 | unsigned int idx; | 804 | unsigned int idx; |
761 | 805 | ||
762 | for (idx = 0; idx < spec->num_cvts; idx++) | 806 | for (idx = 0; idx < spec->num_cvts; idx++) |
@@ -772,26 +816,32 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, | |||
772 | *codec_pars = *hinfo; | 816 | *codec_pars = *hinfo; |
773 | 817 | ||
774 | eld = &spec->sink_eld[idx]; | 818 | eld = &spec->sink_eld[idx]; |
775 | if (eld->sad_count > 0) { | 819 | if (!static_hdmi_pcm && eld->eld_valid && eld->sad_count > 0) { |
776 | hdmi_eld_update_pcm_info(eld, hinfo, codec_pars); | 820 | hdmi_eld_update_pcm_info(eld, hinfo, codec_pars); |
777 | if (hinfo->channels_min > hinfo->channels_max || | 821 | if (hinfo->channels_min > hinfo->channels_max || |
778 | !hinfo->rates || !hinfo->formats) | 822 | !hinfo->rates || !hinfo->formats) |
779 | return -ENODEV; | 823 | return -ENODEV; |
780 | } else { | 824 | } else { |
781 | /* fallback to the codec default */ | 825 | /* fallback to the codec default */ |
782 | hinfo->channels_min = codec_pars->channels_min; | ||
783 | hinfo->channels_max = codec_pars->channels_max; | 826 | hinfo->channels_max = codec_pars->channels_max; |
784 | hinfo->rates = codec_pars->rates; | 827 | hinfo->rates = codec_pars->rates; |
785 | hinfo->formats = codec_pars->formats; | 828 | hinfo->formats = codec_pars->formats; |
786 | hinfo->maxbps = codec_pars->maxbps; | 829 | hinfo->maxbps = codec_pars->maxbps; |
787 | } | 830 | } |
831 | /* store the updated parameters */ | ||
832 | runtime->hw.channels_min = hinfo->channels_min; | ||
833 | runtime->hw.channels_max = hinfo->channels_max; | ||
834 | runtime->hw.formats = hinfo->formats; | ||
835 | runtime->hw.rates = hinfo->rates; | ||
836 | |||
837 | snd_pcm_hw_constraint_step(substream->runtime, 0, | ||
838 | SNDRV_PCM_HW_PARAM_CHANNELS, 2); | ||
788 | return 0; | 839 | return 0; |
789 | } | 840 | } |
790 | 841 | ||
791 | /* | 842 | /* |
792 | * HDA/HDMI auto parsing | 843 | * HDA/HDMI auto parsing |
793 | */ | 844 | */ |
794 | |||
795 | static int hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid) | 845 | static int hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid) |
796 | { | 846 | { |
797 | struct hdmi_spec *spec = codec->spec; | 847 | struct hdmi_spec *spec = codec->spec; |
@@ -827,18 +877,39 @@ static int hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid) | |||
827 | static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid, | 877 | static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid, |
828 | struct hdmi_eld *eld) | 878 | struct hdmi_eld *eld) |
829 | { | 879 | { |
880 | /* | ||
881 | * Always execute a GetPinSense verb here, even when called from | ||
882 | * hdmi_intrinsic_event; for some NVIDIA HW, the unsolicited | ||
883 | * response's PD bit is not the real PD value, but indicates that | ||
884 | * the real PD value changed. An older version of the HD-audio | ||
885 | * specification worked this way. Hence, we just ignore the data in | ||
886 | * the unsolicited response to avoid custom WARs. | ||
887 | */ | ||
830 | int present = snd_hda_pin_sense(codec, pin_nid); | 888 | int present = snd_hda_pin_sense(codec, pin_nid); |
831 | 889 | ||
890 | memset(eld, 0, sizeof(*eld)); | ||
891 | |||
832 | eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE); | 892 | eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE); |
833 | eld->eld_valid = !!(present & AC_PINSENSE_ELDV); | 893 | if (eld->monitor_present) |
894 | eld->eld_valid = !!(present & AC_PINSENSE_ELDV); | ||
895 | else | ||
896 | eld->eld_valid = 0; | ||
897 | |||
898 | printk(KERN_INFO | ||
899 | "HDMI status: Pin=%d Presence_Detect=%d ELD_Valid=%d\n", | ||
900 | pin_nid, eld->monitor_present, eld->eld_valid); | ||
834 | 901 | ||
835 | if (present & AC_PINSENSE_ELDV) | 902 | if (eld->eld_valid) |
836 | hdmi_get_show_eld(codec, pin_nid, eld); | 903 | if (!snd_hdmi_get_eld(eld, codec, pin_nid)) |
904 | snd_hdmi_show_eld(eld); | ||
905 | |||
906 | snd_hda_input_jack_report(codec, pin_nid); | ||
837 | } | 907 | } |
838 | 908 | ||
839 | static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) | 909 | static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) |
840 | { | 910 | { |
841 | struct hdmi_spec *spec = codec->spec; | 911 | struct hdmi_spec *spec = codec->spec; |
912 | int err; | ||
842 | 913 | ||
843 | if (spec->num_pins >= MAX_HDMI_PINS) { | 914 | if (spec->num_pins >= MAX_HDMI_PINS) { |
844 | snd_printk(KERN_WARNING | 915 | snd_printk(KERN_WARNING |
@@ -846,28 +917,38 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) | |||
846 | return -E2BIG; | 917 | return -E2BIG; |
847 | } | 918 | } |
848 | 919 | ||
920 | err = snd_hda_input_jack_add(codec, pin_nid, | ||
921 | SND_JACK_VIDEOOUT, NULL); | ||
922 | if (err < 0) | ||
923 | return err; | ||
924 | |||
849 | hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]); | 925 | hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]); |
850 | 926 | ||
851 | spec->pin[spec->num_pins] = pin_nid; | 927 | spec->pin[spec->num_pins] = pin_nid; |
852 | spec->num_pins++; | 928 | spec->num_pins++; |
853 | 929 | ||
854 | /* | ||
855 | * It is assumed that converter nodes come first in the node list and | ||
856 | * hence have been registered and usable now. | ||
857 | */ | ||
858 | return hdmi_read_pin_conn(codec, pin_nid); | 930 | return hdmi_read_pin_conn(codec, pin_nid); |
859 | } | 931 | } |
860 | 932 | ||
861 | static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid) | 933 | static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid) |
862 | { | 934 | { |
935 | int i, found_pin = 0; | ||
863 | struct hdmi_spec *spec = codec->spec; | 936 | struct hdmi_spec *spec = codec->spec; |
864 | 937 | ||
865 | if (spec->num_cvts >= MAX_HDMI_CVTS) { | 938 | for (i = 0; i < spec->num_pins; i++) |
866 | snd_printk(KERN_WARNING | 939 | if (nid == spec->pin_cvt[i]) { |
867 | "HDMI: no space for converter %d\n", nid); | 940 | found_pin = 1; |
868 | return -E2BIG; | 941 | break; |
942 | } | ||
943 | |||
944 | if (!found_pin) { | ||
945 | snd_printdd("HDMI: Skipping node %d (no connection)\n", nid); | ||
946 | return -EINVAL; | ||
869 | } | 947 | } |
870 | 948 | ||
949 | if (snd_BUG_ON(spec->num_cvts >= MAX_HDMI_CVTS)) | ||
950 | return -E2BIG; | ||
951 | |||
871 | spec->cvt[spec->num_cvts] = nid; | 952 | spec->cvt[spec->num_cvts] = nid; |
872 | spec->num_cvts++; | 953 | spec->num_cvts++; |
873 | 954 | ||
@@ -878,6 +959,8 @@ static int hdmi_parse_codec(struct hda_codec *codec) | |||
878 | { | 959 | { |
879 | hda_nid_t nid; | 960 | hda_nid_t nid; |
880 | int i, nodes; | 961 | int i, nodes; |
962 | int num_tmp_cvts = 0; | ||
963 | hda_nid_t tmp_cvt[MAX_HDMI_CVTS]; | ||
881 | 964 | ||
882 | nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid); | 965 | nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid); |
883 | if (!nid || nodes < 0) { | 966 | if (!nid || nodes < 0) { |
@@ -888,6 +971,7 @@ static int hdmi_parse_codec(struct hda_codec *codec) | |||
888 | for (i = 0; i < nodes; i++, nid++) { | 971 | for (i = 0; i < nodes; i++, nid++) { |
889 | unsigned int caps; | 972 | unsigned int caps; |
890 | unsigned int type; | 973 | unsigned int type; |
974 | unsigned int config; | ||
891 | 975 | ||
892 | caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP); | 976 | caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP); |
893 | type = get_wcaps_type(caps); | 977 | type = get_wcaps_type(caps); |
@@ -897,17 +981,32 @@ static int hdmi_parse_codec(struct hda_codec *codec) | |||
897 | 981 | ||
898 | switch (type) { | 982 | switch (type) { |
899 | case AC_WID_AUD_OUT: | 983 | case AC_WID_AUD_OUT: |
900 | hdmi_add_cvt(codec, nid); | 984 | if (num_tmp_cvts >= MAX_HDMI_CVTS) { |
985 | snd_printk(KERN_WARNING | ||
986 | "HDMI: no space for converter %d\n", nid); | ||
987 | continue; | ||
988 | } | ||
989 | tmp_cvt[num_tmp_cvts] = nid; | ||
990 | num_tmp_cvts++; | ||
901 | break; | 991 | break; |
902 | case AC_WID_PIN: | 992 | case AC_WID_PIN: |
903 | caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); | 993 | caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); |
904 | if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP))) | 994 | if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP))) |
905 | continue; | 995 | continue; |
996 | |||
997 | config = snd_hda_codec_read(codec, nid, 0, | ||
998 | AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
999 | if (get_defcfg_connect(config) == AC_JACK_PORT_NONE) | ||
1000 | continue; | ||
1001 | |||
906 | hdmi_add_pin(codec, nid); | 1002 | hdmi_add_pin(codec, nid); |
907 | break; | 1003 | break; |
908 | } | 1004 | } |
909 | } | 1005 | } |
910 | 1006 | ||
1007 | for (i = 0; i < num_tmp_cvts; i++) | ||
1008 | hdmi_add_cvt(codec, tmp_cvt[i]); | ||
1009 | |||
911 | /* | 1010 | /* |
912 | * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event | 1011 | * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event |
913 | * can be lost and presence sense verb will become inaccurate if the | 1012 | * can be lost and presence sense verb will become inaccurate if the |
@@ -922,3 +1021,723 @@ static int hdmi_parse_codec(struct hda_codec *codec) | |||
922 | return 0; | 1021 | return 0; |
923 | } | 1022 | } |
924 | 1023 | ||
1024 | /* | ||
1025 | */ | ||
1026 | static char *generic_hdmi_pcm_names[MAX_HDMI_CVTS] = { | ||
1027 | "HDMI 0", | ||
1028 | "HDMI 1", | ||
1029 | "HDMI 2", | ||
1030 | "HDMI 3", | ||
1031 | }; | ||
1032 | |||
1033 | /* | ||
1034 | * HDMI callbacks | ||
1035 | */ | ||
1036 | |||
1037 | static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
1038 | struct hda_codec *codec, | ||
1039 | unsigned int stream_tag, | ||
1040 | unsigned int format, | ||
1041 | struct snd_pcm_substream *substream) | ||
1042 | { | ||
1043 | hdmi_set_channel_count(codec, hinfo->nid, | ||
1044 | substream->runtime->channels); | ||
1045 | |||
1046 | hdmi_setup_audio_infoframe(codec, hinfo->nid, substream); | ||
1047 | |||
1048 | return hdmi_setup_stream(codec, hinfo->nid, stream_tag, format); | ||
1049 | } | ||
1050 | |||
1051 | static const struct hda_pcm_stream generic_hdmi_pcm_playback = { | ||
1052 | .substreams = 1, | ||
1053 | .channels_min = 2, | ||
1054 | .ops = { | ||
1055 | .open = hdmi_pcm_open, | ||
1056 | .prepare = generic_hdmi_playback_pcm_prepare, | ||
1057 | }, | ||
1058 | }; | ||
1059 | |||
1060 | static int generic_hdmi_build_pcms(struct hda_codec *codec) | ||
1061 | { | ||
1062 | struct hdmi_spec *spec = codec->spec; | ||
1063 | struct hda_pcm *info = spec->pcm_rec; | ||
1064 | int i; | ||
1065 | |||
1066 | codec->num_pcms = spec->num_cvts; | ||
1067 | codec->pcm_info = info; | ||
1068 | |||
1069 | for (i = 0; i < codec->num_pcms; i++, info++) { | ||
1070 | unsigned int chans; | ||
1071 | struct hda_pcm_stream *pstr; | ||
1072 | |||
1073 | chans = get_wcaps(codec, spec->cvt[i]); | ||
1074 | chans = get_wcaps_channels(chans); | ||
1075 | |||
1076 | info->name = generic_hdmi_pcm_names[i]; | ||
1077 | info->pcm_type = HDA_PCM_TYPE_HDMI; | ||
1078 | pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK]; | ||
1079 | if (spec->pcm_playback) | ||
1080 | *pstr = *spec->pcm_playback; | ||
1081 | else | ||
1082 | *pstr = generic_hdmi_pcm_playback; | ||
1083 | pstr->nid = spec->cvt[i]; | ||
1084 | if (pstr->channels_max <= 2 && chans && chans <= 16) | ||
1085 | pstr->channels_max = chans; | ||
1086 | } | ||
1087 | |||
1088 | return 0; | ||
1089 | } | ||
1090 | |||
1091 | static int generic_hdmi_build_controls(struct hda_codec *codec) | ||
1092 | { | ||
1093 | struct hdmi_spec *spec = codec->spec; | ||
1094 | int err; | ||
1095 | int i; | ||
1096 | |||
1097 | for (i = 0; i < codec->num_pcms; i++) { | ||
1098 | err = snd_hda_create_spdif_out_ctls(codec, spec->cvt[i]); | ||
1099 | if (err < 0) | ||
1100 | return err; | ||
1101 | } | ||
1102 | |||
1103 | return 0; | ||
1104 | } | ||
1105 | |||
1106 | static int generic_hdmi_init(struct hda_codec *codec) | ||
1107 | { | ||
1108 | struct hdmi_spec *spec = codec->spec; | ||
1109 | int i; | ||
1110 | |||
1111 | for (i = 0; spec->pin[i]; i++) { | ||
1112 | hdmi_enable_output(codec, spec->pin[i]); | ||
1113 | snd_hda_codec_write(codec, spec->pin[i], 0, | ||
1114 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
1115 | AC_USRSP_EN | spec->pin[i]); | ||
1116 | } | ||
1117 | return 0; | ||
1118 | } | ||
1119 | |||
1120 | static void generic_hdmi_free(struct hda_codec *codec) | ||
1121 | { | ||
1122 | struct hdmi_spec *spec = codec->spec; | ||
1123 | int i; | ||
1124 | |||
1125 | for (i = 0; i < spec->num_pins; i++) | ||
1126 | snd_hda_eld_proc_free(codec, &spec->sink_eld[i]); | ||
1127 | snd_hda_input_jack_free(codec); | ||
1128 | |||
1129 | kfree(spec); | ||
1130 | } | ||
1131 | |||
1132 | static const struct hda_codec_ops generic_hdmi_patch_ops = { | ||
1133 | .init = generic_hdmi_init, | ||
1134 | .free = generic_hdmi_free, | ||
1135 | .build_pcms = generic_hdmi_build_pcms, | ||
1136 | .build_controls = generic_hdmi_build_controls, | ||
1137 | .unsol_event = hdmi_unsol_event, | ||
1138 | }; | ||
1139 | |||
1140 | static int patch_generic_hdmi(struct hda_codec *codec) | ||
1141 | { | ||
1142 | struct hdmi_spec *spec; | ||
1143 | int i; | ||
1144 | |||
1145 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
1146 | if (spec == NULL) | ||
1147 | return -ENOMEM; | ||
1148 | |||
1149 | codec->spec = spec; | ||
1150 | if (hdmi_parse_codec(codec) < 0) { | ||
1151 | codec->spec = NULL; | ||
1152 | kfree(spec); | ||
1153 | return -EINVAL; | ||
1154 | } | ||
1155 | codec->patch_ops = generic_hdmi_patch_ops; | ||
1156 | |||
1157 | for (i = 0; i < spec->num_pins; i++) | ||
1158 | snd_hda_eld_proc_new(codec, &spec->sink_eld[i], i); | ||
1159 | |||
1160 | init_channel_allocations(); | ||
1161 | |||
1162 | return 0; | ||
1163 | } | ||
1164 | |||
1165 | /* | ||
1166 | * Nvidia specific implementations | ||
1167 | */ | ||
1168 | |||
1169 | #define Nv_VERB_SET_Channel_Allocation 0xF79 | ||
1170 | #define Nv_VERB_SET_Info_Frame_Checksum 0xF7A | ||
1171 | #define Nv_VERB_SET_Audio_Protection_On 0xF98 | ||
1172 | #define Nv_VERB_SET_Audio_Protection_Off 0xF99 | ||
1173 | |||
1174 | #define nvhdmi_master_con_nid_7x 0x04 | ||
1175 | #define nvhdmi_master_pin_nid_7x 0x05 | ||
1176 | |||
1177 | static const hda_nid_t nvhdmi_con_nids_7x[4] = { | ||
1178 | /*front, rear, clfe, rear_surr */ | ||
1179 | 0x6, 0x8, 0xa, 0xc, | ||
1180 | }; | ||
1181 | |||
1182 | static const struct hda_verb nvhdmi_basic_init_7x[] = { | ||
1183 | /* set audio protect on */ | ||
1184 | { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1}, | ||
1185 | /* enable digital output on pin widget */ | ||
1186 | { 0x5, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | ||
1187 | { 0x7, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | ||
1188 | { 0x9, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | ||
1189 | { 0xb, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | ||
1190 | { 0xd, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | ||
1191 | {} /* terminator */ | ||
1192 | }; | ||
1193 | |||
1194 | #ifdef LIMITED_RATE_FMT_SUPPORT | ||
1195 | /* support only the safe format and rate */ | ||
1196 | #define SUPPORTED_RATES SNDRV_PCM_RATE_48000 | ||
1197 | #define SUPPORTED_MAXBPS 16 | ||
1198 | #define SUPPORTED_FORMATS SNDRV_PCM_FMTBIT_S16_LE | ||
1199 | #else | ||
1200 | /* support all rates and formats */ | ||
1201 | #define SUPPORTED_RATES \ | ||
1202 | (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ | ||
1203 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |\ | ||
1204 | SNDRV_PCM_RATE_192000) | ||
1205 | #define SUPPORTED_MAXBPS 24 | ||
1206 | #define SUPPORTED_FORMATS \ | ||
1207 | (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE) | ||
1208 | #endif | ||
1209 | |||
1210 | static int nvhdmi_7x_init(struct hda_codec *codec) | ||
1211 | { | ||
1212 | snd_hda_sequence_write(codec, nvhdmi_basic_init_7x); | ||
1213 | return 0; | ||
1214 | } | ||
1215 | |||
1216 | static unsigned int channels_2_6_8[] = { | ||
1217 | 2, 6, 8 | ||
1218 | }; | ||
1219 | |||
1220 | static unsigned int channels_2_8[] = { | ||
1221 | 2, 8 | ||
1222 | }; | ||
1223 | |||
1224 | static struct snd_pcm_hw_constraint_list hw_constraints_2_6_8_channels = { | ||
1225 | .count = ARRAY_SIZE(channels_2_6_8), | ||
1226 | .list = channels_2_6_8, | ||
1227 | .mask = 0, | ||
1228 | }; | ||
1229 | |||
1230 | static struct snd_pcm_hw_constraint_list hw_constraints_2_8_channels = { | ||
1231 | .count = ARRAY_SIZE(channels_2_8), | ||
1232 | .list = channels_2_8, | ||
1233 | .mask = 0, | ||
1234 | }; | ||
1235 | |||
1236 | static int simple_playback_pcm_open(struct hda_pcm_stream *hinfo, | ||
1237 | struct hda_codec *codec, | ||
1238 | struct snd_pcm_substream *substream) | ||
1239 | { | ||
1240 | struct hdmi_spec *spec = codec->spec; | ||
1241 | struct snd_pcm_hw_constraint_list *hw_constraints_channels = NULL; | ||
1242 | |||
1243 | switch (codec->preset->id) { | ||
1244 | case 0x10de0002: | ||
1245 | case 0x10de0003: | ||
1246 | case 0x10de0005: | ||
1247 | case 0x10de0006: | ||
1248 | hw_constraints_channels = &hw_constraints_2_8_channels; | ||
1249 | break; | ||
1250 | case 0x10de0007: | ||
1251 | hw_constraints_channels = &hw_constraints_2_6_8_channels; | ||
1252 | break; | ||
1253 | default: | ||
1254 | break; | ||
1255 | } | ||
1256 | |||
1257 | if (hw_constraints_channels != NULL) { | ||
1258 | snd_pcm_hw_constraint_list(substream->runtime, 0, | ||
1259 | SNDRV_PCM_HW_PARAM_CHANNELS, | ||
1260 | hw_constraints_channels); | ||
1261 | } else { | ||
1262 | snd_pcm_hw_constraint_step(substream->runtime, 0, | ||
1263 | SNDRV_PCM_HW_PARAM_CHANNELS, 2); | ||
1264 | } | ||
1265 | |||
1266 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); | ||
1267 | } | ||
1268 | |||
1269 | static int simple_playback_pcm_close(struct hda_pcm_stream *hinfo, | ||
1270 | struct hda_codec *codec, | ||
1271 | struct snd_pcm_substream *substream) | ||
1272 | { | ||
1273 | struct hdmi_spec *spec = codec->spec; | ||
1274 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | ||
1275 | } | ||
1276 | |||
1277 | static int simple_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
1278 | struct hda_codec *codec, | ||
1279 | unsigned int stream_tag, | ||
1280 | unsigned int format, | ||
1281 | struct snd_pcm_substream *substream) | ||
1282 | { | ||
1283 | struct hdmi_spec *spec = codec->spec; | ||
1284 | return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, | ||
1285 | stream_tag, format, substream); | ||
1286 | } | ||
1287 | |||
1288 | static void nvhdmi_8ch_7x_set_info_frame_parameters(struct hda_codec *codec, | ||
1289 | int channels) | ||
1290 | { | ||
1291 | unsigned int chanmask; | ||
1292 | int chan = channels ? (channels - 1) : 1; | ||
1293 | |||
1294 | switch (channels) { | ||
1295 | default: | ||
1296 | case 0: | ||
1297 | case 2: | ||
1298 | chanmask = 0x00; | ||
1299 | break; | ||
1300 | case 4: | ||
1301 | chanmask = 0x08; | ||
1302 | break; | ||
1303 | case 6: | ||
1304 | chanmask = 0x0b; | ||
1305 | break; | ||
1306 | case 8: | ||
1307 | chanmask = 0x13; | ||
1308 | break; | ||
1309 | } | ||
1310 | |||
1311 | /* Set the audio infoframe channel allocation and checksum fields. The | ||
1312 | * channel count is computed implicitly by the hardware. */ | ||
1313 | snd_hda_codec_write(codec, 0x1, 0, | ||
1314 | Nv_VERB_SET_Channel_Allocation, chanmask); | ||
1315 | |||
1316 | snd_hda_codec_write(codec, 0x1, 0, | ||
1317 | Nv_VERB_SET_Info_Frame_Checksum, | ||
1318 | (0x71 - chan - chanmask)); | ||
1319 | } | ||
1320 | |||
1321 | static int nvhdmi_8ch_7x_pcm_close(struct hda_pcm_stream *hinfo, | ||
1322 | struct hda_codec *codec, | ||
1323 | struct snd_pcm_substream *substream) | ||
1324 | { | ||
1325 | struct hdmi_spec *spec = codec->spec; | ||
1326 | int i; | ||
1327 | |||
1328 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, | ||
1329 | 0, AC_VERB_SET_CHANNEL_STREAMID, 0); | ||
1330 | for (i = 0; i < 4; i++) { | ||
1331 | /* set the stream id */ | ||
1332 | snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0, | ||
1333 | AC_VERB_SET_CHANNEL_STREAMID, 0); | ||
1334 | /* set the stream format */ | ||
1335 | snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0, | ||
1336 | AC_VERB_SET_STREAM_FORMAT, 0); | ||
1337 | } | ||
1338 | |||
1339 | /* The audio hardware sends a channel count of 0x7 (8ch) when all the | ||
1340 | * streams are disabled. */ | ||
1341 | nvhdmi_8ch_7x_set_info_frame_parameters(codec, 8); | ||
1342 | |||
1343 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | ||
1344 | } | ||
1345 | |||
1346 | static int nvhdmi_8ch_7x_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
1347 | struct hda_codec *codec, | ||
1348 | unsigned int stream_tag, | ||
1349 | unsigned int format, | ||
1350 | struct snd_pcm_substream *substream) | ||
1351 | { | ||
1352 | int chs; | ||
1353 | unsigned int dataDCC1, dataDCC2, channel_id; | ||
1354 | int i; | ||
1355 | |||
1356 | mutex_lock(&codec->spdif_mutex); | ||
1357 | |||
1358 | chs = substream->runtime->channels; | ||
1359 | |||
1360 | dataDCC1 = AC_DIG1_ENABLE | AC_DIG1_COPYRIGHT; | ||
1361 | dataDCC2 = 0x2; | ||
1362 | |||
1363 | /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ | ||
1364 | if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) | ||
1365 | snd_hda_codec_write(codec, | ||
1366 | nvhdmi_master_con_nid_7x, | ||
1367 | 0, | ||
1368 | AC_VERB_SET_DIGI_CONVERT_1, | ||
1369 | codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); | ||
1370 | |||
1371 | /* set the stream id */ | ||
1372 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0, | ||
1373 | AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0); | ||
1374 | |||
1375 | /* set the stream format */ | ||
1376 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0, | ||
1377 | AC_VERB_SET_STREAM_FORMAT, format); | ||
1378 | |||
1379 | /* turn on again (if needed) */ | ||
1380 | /* enable and set the channel status audio/data flag */ | ||
1381 | if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) { | ||
1382 | snd_hda_codec_write(codec, | ||
1383 | nvhdmi_master_con_nid_7x, | ||
1384 | 0, | ||
1385 | AC_VERB_SET_DIGI_CONVERT_1, | ||
1386 | codec->spdif_ctls & 0xff); | ||
1387 | snd_hda_codec_write(codec, | ||
1388 | nvhdmi_master_con_nid_7x, | ||
1389 | 0, | ||
1390 | AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); | ||
1391 | } | ||
1392 | |||
1393 | for (i = 0; i < 4; i++) { | ||
1394 | if (chs == 2) | ||
1395 | channel_id = 0; | ||
1396 | else | ||
1397 | channel_id = i * 2; | ||
1398 | |||
1399 | /* turn off SPDIF once; | ||
1400 | *otherwise the IEC958 bits won't be updated | ||
1401 | */ | ||
1402 | if (codec->spdif_status_reset && | ||
1403 | (codec->spdif_ctls & AC_DIG1_ENABLE)) | ||
1404 | snd_hda_codec_write(codec, | ||
1405 | nvhdmi_con_nids_7x[i], | ||
1406 | 0, | ||
1407 | AC_VERB_SET_DIGI_CONVERT_1, | ||
1408 | codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); | ||
1409 | /* set the stream id */ | ||
1410 | snd_hda_codec_write(codec, | ||
1411 | nvhdmi_con_nids_7x[i], | ||
1412 | 0, | ||
1413 | AC_VERB_SET_CHANNEL_STREAMID, | ||
1414 | (stream_tag << 4) | channel_id); | ||
1415 | /* set the stream format */ | ||
1416 | snd_hda_codec_write(codec, | ||
1417 | nvhdmi_con_nids_7x[i], | ||
1418 | 0, | ||
1419 | AC_VERB_SET_STREAM_FORMAT, | ||
1420 | format); | ||
1421 | /* turn on again (if needed) */ | ||
1422 | /* enable and set the channel status audio/data flag */ | ||
1423 | if (codec->spdif_status_reset && | ||
1424 | (codec->spdif_ctls & AC_DIG1_ENABLE)) { | ||
1425 | snd_hda_codec_write(codec, | ||
1426 | nvhdmi_con_nids_7x[i], | ||
1427 | 0, | ||
1428 | AC_VERB_SET_DIGI_CONVERT_1, | ||
1429 | codec->spdif_ctls & 0xff); | ||
1430 | snd_hda_codec_write(codec, | ||
1431 | nvhdmi_con_nids_7x[i], | ||
1432 | 0, | ||
1433 | AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); | ||
1434 | } | ||
1435 | } | ||
1436 | |||
1437 | nvhdmi_8ch_7x_set_info_frame_parameters(codec, chs); | ||
1438 | |||
1439 | mutex_unlock(&codec->spdif_mutex); | ||
1440 | return 0; | ||
1441 | } | ||
1442 | |||
1443 | static const struct hda_pcm_stream nvhdmi_pcm_playback_8ch_7x = { | ||
1444 | .substreams = 1, | ||
1445 | .channels_min = 2, | ||
1446 | .channels_max = 8, | ||
1447 | .nid = nvhdmi_master_con_nid_7x, | ||
1448 | .rates = SUPPORTED_RATES, | ||
1449 | .maxbps = SUPPORTED_MAXBPS, | ||
1450 | .formats = SUPPORTED_FORMATS, | ||
1451 | .ops = { | ||
1452 | .open = simple_playback_pcm_open, | ||
1453 | .close = nvhdmi_8ch_7x_pcm_close, | ||
1454 | .prepare = nvhdmi_8ch_7x_pcm_prepare | ||
1455 | }, | ||
1456 | }; | ||
1457 | |||
1458 | static const struct hda_pcm_stream nvhdmi_pcm_playback_2ch = { | ||
1459 | .substreams = 1, | ||
1460 | .channels_min = 2, | ||
1461 | .channels_max = 2, | ||
1462 | .nid = nvhdmi_master_con_nid_7x, | ||
1463 | .rates = SUPPORTED_RATES, | ||
1464 | .maxbps = SUPPORTED_MAXBPS, | ||
1465 | .formats = SUPPORTED_FORMATS, | ||
1466 | .ops = { | ||
1467 | .open = simple_playback_pcm_open, | ||
1468 | .close = simple_playback_pcm_close, | ||
1469 | .prepare = simple_playback_pcm_prepare | ||
1470 | }, | ||
1471 | }; | ||
1472 | |||
1473 | static const struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = { | ||
1474 | .build_controls = generic_hdmi_build_controls, | ||
1475 | .build_pcms = generic_hdmi_build_pcms, | ||
1476 | .init = nvhdmi_7x_init, | ||
1477 | .free = generic_hdmi_free, | ||
1478 | }; | ||
1479 | |||
1480 | static const struct hda_codec_ops nvhdmi_patch_ops_2ch = { | ||
1481 | .build_controls = generic_hdmi_build_controls, | ||
1482 | .build_pcms = generic_hdmi_build_pcms, | ||
1483 | .init = nvhdmi_7x_init, | ||
1484 | .free = generic_hdmi_free, | ||
1485 | }; | ||
1486 | |||
1487 | static int patch_nvhdmi_2ch(struct hda_codec *codec) | ||
1488 | { | ||
1489 | struct hdmi_spec *spec; | ||
1490 | |||
1491 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
1492 | if (spec == NULL) | ||
1493 | return -ENOMEM; | ||
1494 | |||
1495 | codec->spec = spec; | ||
1496 | |||
1497 | spec->multiout.num_dacs = 0; /* no analog */ | ||
1498 | spec->multiout.max_channels = 2; | ||
1499 | spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x; | ||
1500 | spec->num_cvts = 1; | ||
1501 | spec->cvt[0] = nvhdmi_master_con_nid_7x; | ||
1502 | spec->pcm_playback = &nvhdmi_pcm_playback_2ch; | ||
1503 | |||
1504 | codec->patch_ops = nvhdmi_patch_ops_2ch; | ||
1505 | |||
1506 | return 0; | ||
1507 | } | ||
1508 | |||
1509 | static int patch_nvhdmi_8ch_7x(struct hda_codec *codec) | ||
1510 | { | ||
1511 | struct hdmi_spec *spec; | ||
1512 | int err = patch_nvhdmi_2ch(codec); | ||
1513 | |||
1514 | if (err < 0) | ||
1515 | return err; | ||
1516 | spec = codec->spec; | ||
1517 | spec->multiout.max_channels = 8; | ||
1518 | spec->pcm_playback = &nvhdmi_pcm_playback_8ch_7x; | ||
1519 | codec->patch_ops = nvhdmi_patch_ops_8ch_7x; | ||
1520 | |||
1521 | /* Initialize the audio infoframe channel mask and checksum to something | ||
1522 | * valid */ | ||
1523 | nvhdmi_8ch_7x_set_info_frame_parameters(codec, 8); | ||
1524 | |||
1525 | return 0; | ||
1526 | } | ||
1527 | |||
1528 | /* | ||
1529 | * ATI-specific implementations | ||
1530 | * | ||
1531 | * FIXME: we may omit the whole this and use the generic code once after | ||
1532 | * it's confirmed to work. | ||
1533 | */ | ||
1534 | |||
1535 | #define ATIHDMI_CVT_NID 0x02 /* audio converter */ | ||
1536 | #define ATIHDMI_PIN_NID 0x03 /* HDMI output pin */ | ||
1537 | |||
1538 | static int atihdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
1539 | struct hda_codec *codec, | ||
1540 | unsigned int stream_tag, | ||
1541 | unsigned int format, | ||
1542 | struct snd_pcm_substream *substream) | ||
1543 | { | ||
1544 | struct hdmi_spec *spec = codec->spec; | ||
1545 | int chans = substream->runtime->channels; | ||
1546 | int i, err; | ||
1547 | |||
1548 | err = simple_playback_pcm_prepare(hinfo, codec, stream_tag, format, | ||
1549 | substream); | ||
1550 | if (err < 0) | ||
1551 | return err; | ||
1552 | snd_hda_codec_write(codec, spec->cvt[0], 0, AC_VERB_SET_CVT_CHAN_COUNT, | ||
1553 | chans - 1); | ||
1554 | /* FIXME: XXX */ | ||
1555 | for (i = 0; i < chans; i++) { | ||
1556 | snd_hda_codec_write(codec, spec->cvt[0], 0, | ||
1557 | AC_VERB_SET_HDMI_CHAN_SLOT, | ||
1558 | (i << 4) | i); | ||
1559 | } | ||
1560 | return 0; | ||
1561 | } | ||
1562 | |||
1563 | static const struct hda_pcm_stream atihdmi_pcm_digital_playback = { | ||
1564 | .substreams = 1, | ||
1565 | .channels_min = 2, | ||
1566 | .channels_max = 2, | ||
1567 | .nid = ATIHDMI_CVT_NID, | ||
1568 | .ops = { | ||
1569 | .open = simple_playback_pcm_open, | ||
1570 | .close = simple_playback_pcm_close, | ||
1571 | .prepare = atihdmi_playback_pcm_prepare | ||
1572 | }, | ||
1573 | }; | ||
1574 | |||
1575 | static const struct hda_verb atihdmi_basic_init[] = { | ||
1576 | /* enable digital output on pin widget */ | ||
1577 | { 0x03, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
1578 | {} /* terminator */ | ||
1579 | }; | ||
1580 | |||
1581 | static int atihdmi_init(struct hda_codec *codec) | ||
1582 | { | ||
1583 | struct hdmi_spec *spec = codec->spec; | ||
1584 | |||
1585 | snd_hda_sequence_write(codec, atihdmi_basic_init); | ||
1586 | /* SI codec requires to unmute the pin */ | ||
1587 | if (get_wcaps(codec, spec->pin[0]) & AC_WCAP_OUT_AMP) | ||
1588 | snd_hda_codec_write(codec, spec->pin[0], 0, | ||
1589 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
1590 | AMP_OUT_UNMUTE); | ||
1591 | return 0; | ||
1592 | } | ||
1593 | |||
1594 | static const struct hda_codec_ops atihdmi_patch_ops = { | ||
1595 | .build_controls = generic_hdmi_build_controls, | ||
1596 | .build_pcms = generic_hdmi_build_pcms, | ||
1597 | .init = atihdmi_init, | ||
1598 | .free = generic_hdmi_free, | ||
1599 | }; | ||
1600 | |||
1601 | |||
1602 | static int patch_atihdmi(struct hda_codec *codec) | ||
1603 | { | ||
1604 | struct hdmi_spec *spec; | ||
1605 | |||
1606 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
1607 | if (spec == NULL) | ||
1608 | return -ENOMEM; | ||
1609 | |||
1610 | codec->spec = spec; | ||
1611 | |||
1612 | spec->multiout.num_dacs = 0; /* no analog */ | ||
1613 | spec->multiout.max_channels = 2; | ||
1614 | spec->multiout.dig_out_nid = ATIHDMI_CVT_NID; | ||
1615 | spec->num_cvts = 1; | ||
1616 | spec->cvt[0] = ATIHDMI_CVT_NID; | ||
1617 | spec->pin[0] = ATIHDMI_PIN_NID; | ||
1618 | spec->pcm_playback = &atihdmi_pcm_digital_playback; | ||
1619 | |||
1620 | codec->patch_ops = atihdmi_patch_ops; | ||
1621 | |||
1622 | return 0; | ||
1623 | } | ||
1624 | |||
1625 | |||
1626 | /* | ||
1627 | * patch entries | ||
1628 | */ | ||
1629 | static const struct hda_codec_preset snd_hda_preset_hdmi[] = { | ||
1630 | { .id = 0x1002793c, .name = "RS600 HDMI", .patch = patch_atihdmi }, | ||
1631 | { .id = 0x10027919, .name = "RS600 HDMI", .patch = patch_atihdmi }, | ||
1632 | { .id = 0x1002791a, .name = "RS690/780 HDMI", .patch = patch_atihdmi }, | ||
1633 | { .id = 0x1002aa01, .name = "R6xx HDMI", .patch = patch_generic_hdmi }, | ||
1634 | { .id = 0x10951390, .name = "SiI1390 HDMI", .patch = patch_generic_hdmi }, | ||
1635 | { .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_generic_hdmi }, | ||
1636 | { .id = 0x17e80047, .name = "Chrontel HDMI", .patch = patch_generic_hdmi }, | ||
1637 | { .id = 0x10de0002, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, | ||
1638 | { .id = 0x10de0003, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, | ||
1639 | { .id = 0x10de0005, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, | ||
1640 | { .id = 0x10de0006, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, | ||
1641 | { .id = 0x10de0007, .name = "MCP79/7A HDMI", .patch = patch_nvhdmi_8ch_7x }, | ||
1642 | { .id = 0x10de000a, .name = "GPU 0a HDMI/DP", .patch = patch_generic_hdmi }, | ||
1643 | { .id = 0x10de000b, .name = "GPU 0b HDMI/DP", .patch = patch_generic_hdmi }, | ||
1644 | { .id = 0x10de000c, .name = "MCP89 HDMI", .patch = patch_generic_hdmi }, | ||
1645 | { .id = 0x10de000d, .name = "GPU 0d HDMI/DP", .patch = patch_generic_hdmi }, | ||
1646 | { .id = 0x10de0010, .name = "GPU 10 HDMI/DP", .patch = patch_generic_hdmi }, | ||
1647 | { .id = 0x10de0011, .name = "GPU 11 HDMI/DP", .patch = patch_generic_hdmi }, | ||
1648 | { .id = 0x10de0012, .name = "GPU 12 HDMI/DP", .patch = patch_generic_hdmi }, | ||
1649 | { .id = 0x10de0013, .name = "GPU 13 HDMI/DP", .patch = patch_generic_hdmi }, | ||
1650 | { .id = 0x10de0014, .name = "GPU 14 HDMI/DP", .patch = patch_generic_hdmi }, | ||
1651 | { .id = 0x10de0015, .name = "GPU 15 HDMI/DP", .patch = patch_generic_hdmi }, | ||
1652 | { .id = 0x10de0016, .name = "GPU 16 HDMI/DP", .patch = patch_generic_hdmi }, | ||
1653 | /* 17 is known to be absent */ | ||
1654 | { .id = 0x10de0018, .name = "GPU 18 HDMI/DP", .patch = patch_generic_hdmi }, | ||
1655 | { .id = 0x10de0019, .name = "GPU 19 HDMI/DP", .patch = patch_generic_hdmi }, | ||
1656 | { .id = 0x10de001a, .name = "GPU 1a HDMI/DP", .patch = patch_generic_hdmi }, | ||
1657 | { .id = 0x10de001b, .name = "GPU 1b HDMI/DP", .patch = patch_generic_hdmi }, | ||
1658 | { .id = 0x10de001c, .name = "GPU 1c HDMI/DP", .patch = patch_generic_hdmi }, | ||
1659 | { .id = 0x10de0040, .name = "GPU 40 HDMI/DP", .patch = patch_generic_hdmi }, | ||
1660 | { .id = 0x10de0041, .name = "GPU 41 HDMI/DP", .patch = patch_generic_hdmi }, | ||
1661 | { .id = 0x10de0042, .name = "GPU 42 HDMI/DP", .patch = patch_generic_hdmi }, | ||
1662 | { .id = 0x10de0043, .name = "GPU 43 HDMI/DP", .patch = patch_generic_hdmi }, | ||
1663 | { .id = 0x10de0044, .name = "GPU 44 HDMI/DP", .patch = patch_generic_hdmi }, | ||
1664 | { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, | ||
1665 | { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, | ||
1666 | { .id = 0x80860054, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi }, | ||
1667 | { .id = 0x80862801, .name = "Bearlake HDMI", .patch = patch_generic_hdmi }, | ||
1668 | { .id = 0x80862802, .name = "Cantiga HDMI", .patch = patch_generic_hdmi }, | ||
1669 | { .id = 0x80862803, .name = "Eaglelake HDMI", .patch = patch_generic_hdmi }, | ||
1670 | { .id = 0x80862804, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi }, | ||
1671 | { .id = 0x80862805, .name = "CougarPoint HDMI", .patch = patch_generic_hdmi }, | ||
1672 | { .id = 0x80862806, .name = "PantherPoint HDMI", .patch = patch_generic_hdmi }, | ||
1673 | { .id = 0x808629fb, .name = "Crestline HDMI", .patch = patch_generic_hdmi }, | ||
1674 | {} /* terminator */ | ||
1675 | }; | ||
1676 | |||
1677 | MODULE_ALIAS("snd-hda-codec-id:1002793c"); | ||
1678 | MODULE_ALIAS("snd-hda-codec-id:10027919"); | ||
1679 | MODULE_ALIAS("snd-hda-codec-id:1002791a"); | ||
1680 | MODULE_ALIAS("snd-hda-codec-id:1002aa01"); | ||
1681 | MODULE_ALIAS("snd-hda-codec-id:10951390"); | ||
1682 | MODULE_ALIAS("snd-hda-codec-id:10951392"); | ||
1683 | MODULE_ALIAS("snd-hda-codec-id:10de0002"); | ||
1684 | MODULE_ALIAS("snd-hda-codec-id:10de0003"); | ||
1685 | MODULE_ALIAS("snd-hda-codec-id:10de0005"); | ||
1686 | MODULE_ALIAS("snd-hda-codec-id:10de0006"); | ||
1687 | MODULE_ALIAS("snd-hda-codec-id:10de0007"); | ||
1688 | MODULE_ALIAS("snd-hda-codec-id:10de000a"); | ||
1689 | MODULE_ALIAS("snd-hda-codec-id:10de000b"); | ||
1690 | MODULE_ALIAS("snd-hda-codec-id:10de000c"); | ||
1691 | MODULE_ALIAS("snd-hda-codec-id:10de000d"); | ||
1692 | MODULE_ALIAS("snd-hda-codec-id:10de0010"); | ||
1693 | MODULE_ALIAS("snd-hda-codec-id:10de0011"); | ||
1694 | MODULE_ALIAS("snd-hda-codec-id:10de0012"); | ||
1695 | MODULE_ALIAS("snd-hda-codec-id:10de0013"); | ||
1696 | MODULE_ALIAS("snd-hda-codec-id:10de0014"); | ||
1697 | MODULE_ALIAS("snd-hda-codec-id:10de0015"); | ||
1698 | MODULE_ALIAS("snd-hda-codec-id:10de0016"); | ||
1699 | MODULE_ALIAS("snd-hda-codec-id:10de0018"); | ||
1700 | MODULE_ALIAS("snd-hda-codec-id:10de0019"); | ||
1701 | MODULE_ALIAS("snd-hda-codec-id:10de001a"); | ||
1702 | MODULE_ALIAS("snd-hda-codec-id:10de001b"); | ||
1703 | MODULE_ALIAS("snd-hda-codec-id:10de001c"); | ||
1704 | MODULE_ALIAS("snd-hda-codec-id:10de0040"); | ||
1705 | MODULE_ALIAS("snd-hda-codec-id:10de0041"); | ||
1706 | MODULE_ALIAS("snd-hda-codec-id:10de0042"); | ||
1707 | MODULE_ALIAS("snd-hda-codec-id:10de0043"); | ||
1708 | MODULE_ALIAS("snd-hda-codec-id:10de0044"); | ||
1709 | MODULE_ALIAS("snd-hda-codec-id:10de0067"); | ||
1710 | MODULE_ALIAS("snd-hda-codec-id:10de8001"); | ||
1711 | MODULE_ALIAS("snd-hda-codec-id:17e80047"); | ||
1712 | MODULE_ALIAS("snd-hda-codec-id:80860054"); | ||
1713 | MODULE_ALIAS("snd-hda-codec-id:80862801"); | ||
1714 | MODULE_ALIAS("snd-hda-codec-id:80862802"); | ||
1715 | MODULE_ALIAS("snd-hda-codec-id:80862803"); | ||
1716 | MODULE_ALIAS("snd-hda-codec-id:80862804"); | ||
1717 | MODULE_ALIAS("snd-hda-codec-id:80862805"); | ||
1718 | MODULE_ALIAS("snd-hda-codec-id:80862806"); | ||
1719 | MODULE_ALIAS("snd-hda-codec-id:808629fb"); | ||
1720 | |||
1721 | MODULE_LICENSE("GPL"); | ||
1722 | MODULE_DESCRIPTION("HDMI HD-audio codec"); | ||
1723 | MODULE_ALIAS("snd-hda-codec-intelhdmi"); | ||
1724 | MODULE_ALIAS("snd-hda-codec-nvhdmi"); | ||
1725 | MODULE_ALIAS("snd-hda-codec-atihdmi"); | ||
1726 | |||
1727 | static struct hda_codec_preset_list intel_list = { | ||
1728 | .preset = snd_hda_preset_hdmi, | ||
1729 | .owner = THIS_MODULE, | ||
1730 | }; | ||
1731 | |||
1732 | static int __init patch_hdmi_init(void) | ||
1733 | { | ||
1734 | return snd_hda_add_codec_preset(&intel_list); | ||
1735 | } | ||
1736 | |||
1737 | static void __exit patch_hdmi_exit(void) | ||
1738 | { | ||
1739 | snd_hda_delete_codec_preset(&intel_list); | ||
1740 | } | ||
1741 | |||
1742 | module_init(patch_hdmi_init) | ||
1743 | module_exit(patch_hdmi_exit) | ||