diff options
author | Takashi Iwai <tiwai@suse.de> | 2010-10-25 04:40:05 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2010-10-25 04:40:05 -0400 |
commit | 506ecbca71d07fa327dd986be1682e90885678ee (patch) | |
tree | eba675a57b0201c8f30436d08cab03c5dcd235ba /sound/pci/hda/patch_hdmi.c | |
parent | aa5c14d5c0d3e4c587db4a1b220b9c86415c538f (diff) | |
parent | 0e7adbe263f89ea2ef15b5af5e80a812b2a85025 (diff) |
Merge branch 'topic/hda' into for-linus
Diffstat (limited to 'sound/pci/hda/patch_hdmi.c')
-rw-r--r-- | sound/pci/hda/patch_hdmi.c | 797 |
1 files changed, 756 insertions, 41 deletions
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index afd6022a96a7..d3e49aa5b9ec 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,22 @@ | |||
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 <sound/core.h> | ||
35 | #include "hda_codec.h" | ||
36 | #include "hda_local.h" | ||
37 | |||
38 | /* | ||
39 | * The HDMI/DisplayPort configuration can be highly dynamic. A graphics device | ||
40 | * could support two independent pipes, each of them can be connected to one or | ||
41 | * more ports (DVI, HDMI or DisplayPort). | ||
42 | * | ||
43 | * The HDA correspondence of pipes/ports are converter/pin nodes. | ||
44 | */ | ||
45 | #define MAX_HDMI_CVTS 3 | ||
46 | #define MAX_HDMI_PINS 3 | ||
28 | 47 | ||
29 | struct hdmi_spec { | 48 | struct hdmi_spec { |
30 | int num_cvts; | 49 | int num_cvts; |
@@ -49,10 +68,10 @@ struct hdmi_spec { | |||
49 | struct hda_pcm_stream codec_pcm_pars[MAX_HDMI_CVTS]; | 68 | struct hda_pcm_stream codec_pcm_pars[MAX_HDMI_CVTS]; |
50 | 69 | ||
51 | /* | 70 | /* |
52 | * nvhdmi specific | 71 | * ati/nvhdmi specific |
53 | */ | 72 | */ |
54 | struct hda_multi_out multiout; | 73 | struct hda_multi_out multiout; |
55 | unsigned int codec_type; | 74 | struct hda_pcm_stream *pcm_playback; |
56 | 75 | ||
57 | /* misc flags */ | 76 | /* misc flags */ |
58 | /* PD bit indicates only the update, not the current state */ | 77 | /* PD bit indicates only the update, not the current state */ |
@@ -65,13 +84,25 @@ struct hdmi_audio_infoframe { | |||
65 | u8 ver; /* 0x01 */ | 84 | u8 ver; /* 0x01 */ |
66 | u8 len; /* 0x0a */ | 85 | u8 len; /* 0x0a */ |
67 | 86 | ||
68 | u8 checksum; /* PB0 */ | 87 | u8 checksum; |
88 | |||
69 | u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */ | 89 | u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */ |
70 | u8 SS01_SF24; | 90 | u8 SS01_SF24; |
71 | u8 CXT04; | 91 | u8 CXT04; |
72 | u8 CA; | 92 | u8 CA; |
73 | u8 LFEPBL01_LSV36_DM_INH7; | 93 | u8 LFEPBL01_LSV36_DM_INH7; |
74 | u8 reserved[5]; /* PB6 - PB10 */ | 94 | }; |
95 | |||
96 | struct dp_audio_infoframe { | ||
97 | u8 type; /* 0x84 */ | ||
98 | u8 len; /* 0x1b */ | ||
99 | u8 ver; /* 0x11 << 2 */ | ||
100 | |||
101 | u8 CC02_CT47; /* match with HDMI infoframe from this on */ | ||
102 | u8 SS01_SF24; | ||
103 | u8 CXT04; | ||
104 | u8 CA; | ||
105 | u8 LFEPBL01_LSV36_DM_INH7; | ||
75 | }; | 106 | }; |
76 | 107 | ||
77 | /* | 108 | /* |
@@ -162,7 +193,7 @@ static int hdmi_channel_mapping[0x32][8] = { | |||
162 | /* 4ch */ | 193 | /* 4ch */ |
163 | [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 }, | 194 | [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 }, |
164 | /* surround41 */ | 195 | /* surround41 */ |
165 | [0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 }, | 196 | [0x09] = { 0x00, 0x11, 0x24, 0x35, 0x42, 0xf3, 0xf6, 0xf7 }, |
166 | /* surround50 */ | 197 | /* surround50 */ |
167 | [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 }, | 198 | [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 }, |
168 | /* surround51 */ | 199 | /* surround51 */ |
@@ -175,7 +206,7 @@ static int hdmi_channel_mapping[0x32][8] = { | |||
175 | * This is an ordered list! | 206 | * This is an ordered list! |
176 | * | 207 | * |
177 | * The preceding ones have better chances to be selected by | 208 | * The preceding ones have better chances to be selected by |
178 | * hdmi_setup_channel_allocation(). | 209 | * hdmi_channel_allocation(). |
179 | */ | 210 | */ |
180 | static struct cea_channel_speaker_allocation channel_allocations[] = { | 211 | static struct cea_channel_speaker_allocation channel_allocations[] = { |
181 | /* channel: 7 6 5 4 3 2 1 0 */ | 212 | /* channel: 7 6 5 4 3 2 1 0 */ |
@@ -352,14 +383,14 @@ static void init_channel_allocations(void) | |||
352 | * | 383 | * |
353 | * TODO: it could select the wrong CA from multiple candidates. | 384 | * TODO: it could select the wrong CA from multiple candidates. |
354 | */ | 385 | */ |
355 | static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid, | 386 | static int hdmi_channel_allocation(struct hda_codec *codec, hda_nid_t nid, |
356 | struct hdmi_audio_infoframe *ai) | 387 | int channels) |
357 | { | 388 | { |
358 | struct hdmi_spec *spec = codec->spec; | 389 | struct hdmi_spec *spec = codec->spec; |
359 | struct hdmi_eld *eld; | 390 | struct hdmi_eld *eld; |
360 | int i; | 391 | int i; |
392 | int ca = 0; | ||
361 | int spk_mask = 0; | 393 | int spk_mask = 0; |
362 | int channels = 1 + (ai->CC02_CT47 & 0x7); | ||
363 | char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; | 394 | char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; |
364 | 395 | ||
365 | /* | 396 | /* |
@@ -397,16 +428,16 @@ static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid, | |||
397 | if (channels == channel_allocations[i].channels && | 428 | if (channels == channel_allocations[i].channels && |
398 | (spk_mask & channel_allocations[i].spk_mask) == | 429 | (spk_mask & channel_allocations[i].spk_mask) == |
399 | channel_allocations[i].spk_mask) { | 430 | channel_allocations[i].spk_mask) { |
400 | ai->CA = channel_allocations[i].ca_index; | 431 | ca = channel_allocations[i].ca_index; |
401 | break; | 432 | break; |
402 | } | 433 | } |
403 | } | 434 | } |
404 | 435 | ||
405 | snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf)); | 436 | snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf)); |
406 | snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n", | 437 | snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n", |
407 | ai->CA, channels, buf); | 438 | ca, channels, buf); |
408 | 439 | ||
409 | return ai->CA; | 440 | return ca; |
410 | } | 441 | } |
411 | 442 | ||
412 | static void hdmi_debug_channel_mapping(struct hda_codec *codec, | 443 | static void hdmi_debug_channel_mapping(struct hda_codec *codec, |
@@ -428,10 +459,9 @@ static void hdmi_debug_channel_mapping(struct hda_codec *codec, | |||
428 | 459 | ||
429 | static void hdmi_setup_channel_mapping(struct hda_codec *codec, | 460 | static void hdmi_setup_channel_mapping(struct hda_codec *codec, |
430 | hda_nid_t pin_nid, | 461 | hda_nid_t pin_nid, |
431 | struct hdmi_audio_infoframe *ai) | 462 | int ca) |
432 | { | 463 | { |
433 | int i; | 464 | int i; |
434 | int ca = ai->CA; | ||
435 | int err; | 465 | int err; |
436 | 466 | ||
437 | if (hdmi_channel_mapping[ca][1] == 0) { | 467 | if (hdmi_channel_mapping[ca][1] == 0) { |
@@ -528,41 +558,37 @@ static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid) | |||
528 | #endif | 558 | #endif |
529 | } | 559 | } |
530 | 560 | ||
531 | static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai) | 561 | static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *hdmi_ai) |
532 | { | 562 | { |
533 | u8 *bytes = (u8 *)ai; | 563 | u8 *bytes = (u8 *)hdmi_ai; |
534 | u8 sum = 0; | 564 | u8 sum = 0; |
535 | int i; | 565 | int i; |
536 | 566 | ||
537 | ai->checksum = 0; | 567 | hdmi_ai->checksum = 0; |
538 | 568 | ||
539 | for (i = 0; i < sizeof(*ai); i++) | 569 | for (i = 0; i < sizeof(*hdmi_ai); i++) |
540 | sum += bytes[i]; | 570 | sum += bytes[i]; |
541 | 571 | ||
542 | ai->checksum = -sum; | 572 | hdmi_ai->checksum = -sum; |
543 | } | 573 | } |
544 | 574 | ||
545 | static void hdmi_fill_audio_infoframe(struct hda_codec *codec, | 575 | static void hdmi_fill_audio_infoframe(struct hda_codec *codec, |
546 | hda_nid_t pin_nid, | 576 | hda_nid_t pin_nid, |
547 | struct hdmi_audio_infoframe *ai) | 577 | u8 *dip, int size) |
548 | { | 578 | { |
549 | u8 *bytes = (u8 *)ai; | ||
550 | int i; | 579 | int i; |
551 | 580 | ||
552 | hdmi_debug_dip_size(codec, pin_nid); | 581 | hdmi_debug_dip_size(codec, pin_nid); |
553 | hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */ | 582 | hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */ |
554 | 583 | ||
555 | hdmi_checksum_audio_infoframe(ai); | ||
556 | |||
557 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); | 584 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); |
558 | for (i = 0; i < sizeof(*ai); i++) | 585 | for (i = 0; i < size; i++) |
559 | hdmi_write_dip_byte(codec, pin_nid, bytes[i]); | 586 | hdmi_write_dip_byte(codec, pin_nid, dip[i]); |
560 | } | 587 | } |
561 | 588 | ||
562 | static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, | 589 | static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, |
563 | struct hdmi_audio_infoframe *ai) | 590 | u8 *dip, int size) |
564 | { | 591 | { |
565 | u8 *bytes = (u8 *)ai; | ||
566 | u8 val; | 592 | u8 val; |
567 | int i; | 593 | int i; |
568 | 594 | ||
@@ -571,10 +597,10 @@ static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, | |||
571 | return false; | 597 | return false; |
572 | 598 | ||
573 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); | 599 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); |
574 | for (i = 0; i < sizeof(*ai); i++) { | 600 | for (i = 0; i < size; i++) { |
575 | val = snd_hda_codec_read(codec, pin_nid, 0, | 601 | val = snd_hda_codec_read(codec, pin_nid, 0, |
576 | AC_VERB_GET_HDMI_DIP_DATA, 0); | 602 | AC_VERB_GET_HDMI_DIP_DATA, 0); |
577 | if (val != bytes[i]) | 603 | if (val != dip[i]) |
578 | return false; | 604 | return false; |
579 | } | 605 | } |
580 | 606 | ||
@@ -586,15 +612,13 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid, | |||
586 | { | 612 | { |
587 | struct hdmi_spec *spec = codec->spec; | 613 | struct hdmi_spec *spec = codec->spec; |
588 | hda_nid_t pin_nid; | 614 | hda_nid_t pin_nid; |
615 | int channels = substream->runtime->channels; | ||
616 | int ca; | ||
589 | int i; | 617 | int i; |
590 | struct hdmi_audio_infoframe ai = { | 618 | u8 ai[max(sizeof(struct hdmi_audio_infoframe), |
591 | .type = 0x84, | 619 | sizeof(struct dp_audio_infoframe))]; |
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,45 @@ 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; | ||
634 | |||
635 | hdmi_ai = (struct hdmi_audio_infoframe *)ai; | ||
636 | hdmi_ai->type = 0x84; | ||
637 | hdmi_ai->ver = 0x01; | ||
638 | hdmi_ai->len = 0x0a; | ||
639 | hdmi_ai->CC02_CT47 = channels - 1; | ||
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; | ||
643 | |||
644 | dp_ai = (struct dp_audio_infoframe *)ai; | ||
645 | dp_ai->type = 0x84; | ||
646 | dp_ai->len = 0x1b; | ||
647 | dp_ai->ver = 0x11 << 2; | ||
648 | dp_ai->CC02_CT47 = channels - 1; | ||
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, sizeof(ai))) { | ||
607 | snd_printdd("hdmi_setup_audio_infoframe: " | 661 | snd_printdd("hdmi_setup_audio_infoframe: " |
608 | "cvt=%d pin=%d channels=%d\n", | 662 | "cvt=%d pin=%d channels=%d\n", |
609 | nid, pin_nid, | 663 | nid, pin_nid, |
610 | substream->runtime->channels); | 664 | channels); |
611 | hdmi_setup_channel_mapping(codec, pin_nid, &ai); | 665 | hdmi_setup_channel_mapping(codec, pin_nid, ca); |
612 | hdmi_stop_infoframe_trans(codec, pin_nid); | 666 | hdmi_stop_infoframe_trans(codec, pin_nid); |
613 | hdmi_fill_audio_infoframe(codec, pin_nid, &ai); | 667 | hdmi_fill_audio_infoframe(codec, pin_nid, |
668 | ai, sizeof(ai)); | ||
614 | hdmi_start_infoframe_trans(codec, pin_nid); | 669 | hdmi_start_infoframe_trans(codec, pin_nid); |
615 | } | 670 | } |
616 | } | 671 | } |
@@ -791,7 +846,6 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, | |||
791 | /* | 846 | /* |
792 | * HDA/HDMI auto parsing | 847 | * HDA/HDMI auto parsing |
793 | */ | 848 | */ |
794 | |||
795 | static int hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid) | 849 | static int hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid) |
796 | { | 850 | { |
797 | struct hdmi_spec *spec = codec->spec; | 851 | struct hdmi_spec *spec = codec->spec; |
@@ -922,3 +976,664 @@ static int hdmi_parse_codec(struct hda_codec *codec) | |||
922 | return 0; | 976 | return 0; |
923 | } | 977 | } |
924 | 978 | ||
979 | /* | ||
980 | */ | ||
981 | static char *generic_hdmi_pcm_names[MAX_HDMI_CVTS] = { | ||
982 | "HDMI 0", | ||
983 | "HDMI 1", | ||
984 | "HDMI 2", | ||
985 | }; | ||
986 | |||
987 | /* | ||
988 | * HDMI callbacks | ||
989 | */ | ||
990 | |||
991 | static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
992 | struct hda_codec *codec, | ||
993 | unsigned int stream_tag, | ||
994 | unsigned int format, | ||
995 | struct snd_pcm_substream *substream) | ||
996 | { | ||
997 | hdmi_set_channel_count(codec, hinfo->nid, | ||
998 | substream->runtime->channels); | ||
999 | |||
1000 | hdmi_setup_audio_infoframe(codec, hinfo->nid, substream); | ||
1001 | |||
1002 | return hdmi_setup_stream(codec, hinfo->nid, stream_tag, format); | ||
1003 | } | ||
1004 | |||
1005 | static struct hda_pcm_stream generic_hdmi_pcm_playback = { | ||
1006 | .substreams = 1, | ||
1007 | .channels_min = 2, | ||
1008 | .ops = { | ||
1009 | .open = hdmi_pcm_open, | ||
1010 | .prepare = generic_hdmi_playback_pcm_prepare, | ||
1011 | }, | ||
1012 | }; | ||
1013 | |||
1014 | static int generic_hdmi_build_pcms(struct hda_codec *codec) | ||
1015 | { | ||
1016 | struct hdmi_spec *spec = codec->spec; | ||
1017 | struct hda_pcm *info = spec->pcm_rec; | ||
1018 | int i; | ||
1019 | |||
1020 | codec->num_pcms = spec->num_cvts; | ||
1021 | codec->pcm_info = info; | ||
1022 | |||
1023 | for (i = 0; i < codec->num_pcms; i++, info++) { | ||
1024 | unsigned int chans; | ||
1025 | struct hda_pcm_stream *pstr; | ||
1026 | |||
1027 | chans = get_wcaps(codec, spec->cvt[i]); | ||
1028 | chans = get_wcaps_channels(chans); | ||
1029 | |||
1030 | info->name = generic_hdmi_pcm_names[i]; | ||
1031 | info->pcm_type = HDA_PCM_TYPE_HDMI; | ||
1032 | pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK]; | ||
1033 | if (spec->pcm_playback) | ||
1034 | *pstr = *spec->pcm_playback; | ||
1035 | else | ||
1036 | *pstr = generic_hdmi_pcm_playback; | ||
1037 | pstr->nid = spec->cvt[i]; | ||
1038 | if (pstr->channels_max <= 2 && chans && chans <= 16) | ||
1039 | pstr->channels_max = chans; | ||
1040 | } | ||
1041 | |||
1042 | return 0; | ||
1043 | } | ||
1044 | |||
1045 | static int generic_hdmi_build_controls(struct hda_codec *codec) | ||
1046 | { | ||
1047 | struct hdmi_spec *spec = codec->spec; | ||
1048 | int err; | ||
1049 | int i; | ||
1050 | |||
1051 | for (i = 0; i < codec->num_pcms; i++) { | ||
1052 | err = snd_hda_create_spdif_out_ctls(codec, spec->cvt[i]); | ||
1053 | if (err < 0) | ||
1054 | return err; | ||
1055 | } | ||
1056 | |||
1057 | return 0; | ||
1058 | } | ||
1059 | |||
1060 | static int generic_hdmi_init(struct hda_codec *codec) | ||
1061 | { | ||
1062 | struct hdmi_spec *spec = codec->spec; | ||
1063 | int i; | ||
1064 | |||
1065 | for (i = 0; spec->pin[i]; i++) { | ||
1066 | hdmi_enable_output(codec, spec->pin[i]); | ||
1067 | snd_hda_codec_write(codec, spec->pin[i], 0, | ||
1068 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
1069 | AC_USRSP_EN | spec->pin[i]); | ||
1070 | } | ||
1071 | return 0; | ||
1072 | } | ||
1073 | |||
1074 | static void generic_hdmi_free(struct hda_codec *codec) | ||
1075 | { | ||
1076 | struct hdmi_spec *spec = codec->spec; | ||
1077 | int i; | ||
1078 | |||
1079 | for (i = 0; i < spec->num_pins; i++) | ||
1080 | snd_hda_eld_proc_free(codec, &spec->sink_eld[i]); | ||
1081 | |||
1082 | kfree(spec); | ||
1083 | } | ||
1084 | |||
1085 | static struct hda_codec_ops generic_hdmi_patch_ops = { | ||
1086 | .init = generic_hdmi_init, | ||
1087 | .free = generic_hdmi_free, | ||
1088 | .build_pcms = generic_hdmi_build_pcms, | ||
1089 | .build_controls = generic_hdmi_build_controls, | ||
1090 | .unsol_event = hdmi_unsol_event, | ||
1091 | }; | ||
1092 | |||
1093 | static int patch_generic_hdmi(struct hda_codec *codec) | ||
1094 | { | ||
1095 | struct hdmi_spec *spec; | ||
1096 | int i; | ||
1097 | |||
1098 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
1099 | if (spec == NULL) | ||
1100 | return -ENOMEM; | ||
1101 | |||
1102 | codec->spec = spec; | ||
1103 | if (hdmi_parse_codec(codec) < 0) { | ||
1104 | codec->spec = NULL; | ||
1105 | kfree(spec); | ||
1106 | return -EINVAL; | ||
1107 | } | ||
1108 | codec->patch_ops = generic_hdmi_patch_ops; | ||
1109 | |||
1110 | for (i = 0; i < spec->num_pins; i++) | ||
1111 | snd_hda_eld_proc_new(codec, &spec->sink_eld[i], i); | ||
1112 | |||
1113 | init_channel_allocations(); | ||
1114 | |||
1115 | return 0; | ||
1116 | } | ||
1117 | |||
1118 | /* | ||
1119 | * Nvidia specific implementations | ||
1120 | */ | ||
1121 | |||
1122 | #define Nv_VERB_SET_Channel_Allocation 0xF79 | ||
1123 | #define Nv_VERB_SET_Info_Frame_Checksum 0xF7A | ||
1124 | #define Nv_VERB_SET_Audio_Protection_On 0xF98 | ||
1125 | #define Nv_VERB_SET_Audio_Protection_Off 0xF99 | ||
1126 | |||
1127 | #define nvhdmi_master_con_nid_7x 0x04 | ||
1128 | #define nvhdmi_master_pin_nid_7x 0x05 | ||
1129 | |||
1130 | static hda_nid_t nvhdmi_con_nids_7x[4] = { | ||
1131 | /*front, rear, clfe, rear_surr */ | ||
1132 | 0x6, 0x8, 0xa, 0xc, | ||
1133 | }; | ||
1134 | |||
1135 | static struct hda_verb nvhdmi_basic_init_7x[] = { | ||
1136 | /* set audio protect on */ | ||
1137 | { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1}, | ||
1138 | /* enable digital output on pin widget */ | ||
1139 | { 0x5, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | ||
1140 | { 0x7, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | ||
1141 | { 0x9, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | ||
1142 | { 0xb, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | ||
1143 | { 0xd, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | ||
1144 | {} /* terminator */ | ||
1145 | }; | ||
1146 | |||
1147 | #ifdef LIMITED_RATE_FMT_SUPPORT | ||
1148 | /* support only the safe format and rate */ | ||
1149 | #define SUPPORTED_RATES SNDRV_PCM_RATE_48000 | ||
1150 | #define SUPPORTED_MAXBPS 16 | ||
1151 | #define SUPPORTED_FORMATS SNDRV_PCM_FMTBIT_S16_LE | ||
1152 | #else | ||
1153 | /* support all rates and formats */ | ||
1154 | #define SUPPORTED_RATES \ | ||
1155 | (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ | ||
1156 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |\ | ||
1157 | SNDRV_PCM_RATE_192000) | ||
1158 | #define SUPPORTED_MAXBPS 24 | ||
1159 | #define SUPPORTED_FORMATS \ | ||
1160 | (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE) | ||
1161 | #endif | ||
1162 | |||
1163 | static int nvhdmi_7x_init(struct hda_codec *codec) | ||
1164 | { | ||
1165 | snd_hda_sequence_write(codec, nvhdmi_basic_init_7x); | ||
1166 | return 0; | ||
1167 | } | ||
1168 | |||
1169 | static int simple_playback_pcm_open(struct hda_pcm_stream *hinfo, | ||
1170 | struct hda_codec *codec, | ||
1171 | struct snd_pcm_substream *substream) | ||
1172 | { | ||
1173 | struct hdmi_spec *spec = codec->spec; | ||
1174 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); | ||
1175 | } | ||
1176 | |||
1177 | static int simple_playback_pcm_close(struct hda_pcm_stream *hinfo, | ||
1178 | struct hda_codec *codec, | ||
1179 | struct snd_pcm_substream *substream) | ||
1180 | { | ||
1181 | struct hdmi_spec *spec = codec->spec; | ||
1182 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | ||
1183 | } | ||
1184 | |||
1185 | static int simple_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
1186 | struct hda_codec *codec, | ||
1187 | unsigned int stream_tag, | ||
1188 | unsigned int format, | ||
1189 | struct snd_pcm_substream *substream) | ||
1190 | { | ||
1191 | struct hdmi_spec *spec = codec->spec; | ||
1192 | return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, | ||
1193 | stream_tag, format, substream); | ||
1194 | } | ||
1195 | |||
1196 | static int nvhdmi_8ch_7x_pcm_close(struct hda_pcm_stream *hinfo, | ||
1197 | struct hda_codec *codec, | ||
1198 | struct snd_pcm_substream *substream) | ||
1199 | { | ||
1200 | struct hdmi_spec *spec = codec->spec; | ||
1201 | int i; | ||
1202 | |||
1203 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, | ||
1204 | 0, AC_VERB_SET_CHANNEL_STREAMID, 0); | ||
1205 | for (i = 0; i < 4; i++) { | ||
1206 | /* set the stream id */ | ||
1207 | snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0, | ||
1208 | AC_VERB_SET_CHANNEL_STREAMID, 0); | ||
1209 | /* set the stream format */ | ||
1210 | snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0, | ||
1211 | AC_VERB_SET_STREAM_FORMAT, 0); | ||
1212 | } | ||
1213 | |||
1214 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | ||
1215 | } | ||
1216 | |||
1217 | static int nvhdmi_8ch_7x_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
1218 | struct hda_codec *codec, | ||
1219 | unsigned int stream_tag, | ||
1220 | unsigned int format, | ||
1221 | struct snd_pcm_substream *substream) | ||
1222 | { | ||
1223 | int chs; | ||
1224 | unsigned int dataDCC1, dataDCC2, chan, chanmask, channel_id; | ||
1225 | int i; | ||
1226 | |||
1227 | mutex_lock(&codec->spdif_mutex); | ||
1228 | |||
1229 | chs = substream->runtime->channels; | ||
1230 | chan = chs ? (chs - 1) : 1; | ||
1231 | |||
1232 | switch (chs) { | ||
1233 | default: | ||
1234 | case 0: | ||
1235 | case 2: | ||
1236 | chanmask = 0x00; | ||
1237 | break; | ||
1238 | case 4: | ||
1239 | chanmask = 0x08; | ||
1240 | break; | ||
1241 | case 6: | ||
1242 | chanmask = 0x0b; | ||
1243 | break; | ||
1244 | case 8: | ||
1245 | chanmask = 0x13; | ||
1246 | break; | ||
1247 | } | ||
1248 | dataDCC1 = AC_DIG1_ENABLE | AC_DIG1_COPYRIGHT; | ||
1249 | dataDCC2 = 0x2; | ||
1250 | |||
1251 | /* set the Audio InforFrame Channel Allocation */ | ||
1252 | snd_hda_codec_write(codec, 0x1, 0, | ||
1253 | Nv_VERB_SET_Channel_Allocation, chanmask); | ||
1254 | |||
1255 | /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ | ||
1256 | if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) | ||
1257 | snd_hda_codec_write(codec, | ||
1258 | nvhdmi_master_con_nid_7x, | ||
1259 | 0, | ||
1260 | AC_VERB_SET_DIGI_CONVERT_1, | ||
1261 | codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); | ||
1262 | |||
1263 | /* set the stream id */ | ||
1264 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0, | ||
1265 | AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0); | ||
1266 | |||
1267 | /* set the stream format */ | ||
1268 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0, | ||
1269 | AC_VERB_SET_STREAM_FORMAT, format); | ||
1270 | |||
1271 | /* turn on again (if needed) */ | ||
1272 | /* enable and set the channel status audio/data flag */ | ||
1273 | if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) { | ||
1274 | snd_hda_codec_write(codec, | ||
1275 | nvhdmi_master_con_nid_7x, | ||
1276 | 0, | ||
1277 | AC_VERB_SET_DIGI_CONVERT_1, | ||
1278 | codec->spdif_ctls & 0xff); | ||
1279 | snd_hda_codec_write(codec, | ||
1280 | nvhdmi_master_con_nid_7x, | ||
1281 | 0, | ||
1282 | AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); | ||
1283 | } | ||
1284 | |||
1285 | for (i = 0; i < 4; i++) { | ||
1286 | if (chs == 2) | ||
1287 | channel_id = 0; | ||
1288 | else | ||
1289 | channel_id = i * 2; | ||
1290 | |||
1291 | /* turn off SPDIF once; | ||
1292 | *otherwise the IEC958 bits won't be updated | ||
1293 | */ | ||
1294 | if (codec->spdif_status_reset && | ||
1295 | (codec->spdif_ctls & AC_DIG1_ENABLE)) | ||
1296 | snd_hda_codec_write(codec, | ||
1297 | nvhdmi_con_nids_7x[i], | ||
1298 | 0, | ||
1299 | AC_VERB_SET_DIGI_CONVERT_1, | ||
1300 | codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); | ||
1301 | /* set the stream id */ | ||
1302 | snd_hda_codec_write(codec, | ||
1303 | nvhdmi_con_nids_7x[i], | ||
1304 | 0, | ||
1305 | AC_VERB_SET_CHANNEL_STREAMID, | ||
1306 | (stream_tag << 4) | channel_id); | ||
1307 | /* set the stream format */ | ||
1308 | snd_hda_codec_write(codec, | ||
1309 | nvhdmi_con_nids_7x[i], | ||
1310 | 0, | ||
1311 | AC_VERB_SET_STREAM_FORMAT, | ||
1312 | format); | ||
1313 | /* turn on again (if needed) */ | ||
1314 | /* enable and set the channel status audio/data flag */ | ||
1315 | if (codec->spdif_status_reset && | ||
1316 | (codec->spdif_ctls & AC_DIG1_ENABLE)) { | ||
1317 | snd_hda_codec_write(codec, | ||
1318 | nvhdmi_con_nids_7x[i], | ||
1319 | 0, | ||
1320 | AC_VERB_SET_DIGI_CONVERT_1, | ||
1321 | codec->spdif_ctls & 0xff); | ||
1322 | snd_hda_codec_write(codec, | ||
1323 | nvhdmi_con_nids_7x[i], | ||
1324 | 0, | ||
1325 | AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); | ||
1326 | } | ||
1327 | } | ||
1328 | |||
1329 | /* set the Audio Info Frame Checksum */ | ||
1330 | snd_hda_codec_write(codec, 0x1, 0, | ||
1331 | Nv_VERB_SET_Info_Frame_Checksum, | ||
1332 | (0x71 - chan - chanmask)); | ||
1333 | |||
1334 | mutex_unlock(&codec->spdif_mutex); | ||
1335 | return 0; | ||
1336 | } | ||
1337 | |||
1338 | static struct hda_pcm_stream nvhdmi_pcm_playback_8ch_7x = { | ||
1339 | .substreams = 1, | ||
1340 | .channels_min = 2, | ||
1341 | .channels_max = 8, | ||
1342 | .nid = nvhdmi_master_con_nid_7x, | ||
1343 | .rates = SUPPORTED_RATES, | ||
1344 | .maxbps = SUPPORTED_MAXBPS, | ||
1345 | .formats = SUPPORTED_FORMATS, | ||
1346 | .ops = { | ||
1347 | .open = simple_playback_pcm_open, | ||
1348 | .close = nvhdmi_8ch_7x_pcm_close, | ||
1349 | .prepare = nvhdmi_8ch_7x_pcm_prepare | ||
1350 | }, | ||
1351 | }; | ||
1352 | |||
1353 | static struct hda_pcm_stream nvhdmi_pcm_playback_2ch = { | ||
1354 | .substreams = 1, | ||
1355 | .channels_min = 2, | ||
1356 | .channels_max = 2, | ||
1357 | .nid = nvhdmi_master_con_nid_7x, | ||
1358 | .rates = SUPPORTED_RATES, | ||
1359 | .maxbps = SUPPORTED_MAXBPS, | ||
1360 | .formats = SUPPORTED_FORMATS, | ||
1361 | .ops = { | ||
1362 | .open = simple_playback_pcm_open, | ||
1363 | .close = simple_playback_pcm_close, | ||
1364 | .prepare = simple_playback_pcm_prepare | ||
1365 | }, | ||
1366 | }; | ||
1367 | |||
1368 | static struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = { | ||
1369 | .build_controls = generic_hdmi_build_controls, | ||
1370 | .build_pcms = generic_hdmi_build_pcms, | ||
1371 | .init = nvhdmi_7x_init, | ||
1372 | .free = generic_hdmi_free, | ||
1373 | }; | ||
1374 | |||
1375 | static struct hda_codec_ops nvhdmi_patch_ops_2ch = { | ||
1376 | .build_controls = generic_hdmi_build_controls, | ||
1377 | .build_pcms = generic_hdmi_build_pcms, | ||
1378 | .init = nvhdmi_7x_init, | ||
1379 | .free = generic_hdmi_free, | ||
1380 | }; | ||
1381 | |||
1382 | static int patch_nvhdmi_8ch_89(struct hda_codec *codec) | ||
1383 | { | ||
1384 | struct hdmi_spec *spec; | ||
1385 | int err = patch_generic_hdmi(codec); | ||
1386 | |||
1387 | if (err < 0) | ||
1388 | return err; | ||
1389 | spec = codec->spec; | ||
1390 | spec->old_pin_detect = 1; | ||
1391 | return 0; | ||
1392 | } | ||
1393 | |||
1394 | static int patch_nvhdmi_2ch(struct hda_codec *codec) | ||
1395 | { | ||
1396 | struct hdmi_spec *spec; | ||
1397 | |||
1398 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
1399 | if (spec == NULL) | ||
1400 | return -ENOMEM; | ||
1401 | |||
1402 | codec->spec = spec; | ||
1403 | |||
1404 | spec->multiout.num_dacs = 0; /* no analog */ | ||
1405 | spec->multiout.max_channels = 2; | ||
1406 | spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x; | ||
1407 | spec->old_pin_detect = 1; | ||
1408 | spec->num_cvts = 1; | ||
1409 | spec->cvt[0] = nvhdmi_master_con_nid_7x; | ||
1410 | spec->pcm_playback = &nvhdmi_pcm_playback_2ch; | ||
1411 | |||
1412 | codec->patch_ops = nvhdmi_patch_ops_2ch; | ||
1413 | |||
1414 | return 0; | ||
1415 | } | ||
1416 | |||
1417 | static int patch_nvhdmi_8ch_7x(struct hda_codec *codec) | ||
1418 | { | ||
1419 | struct hdmi_spec *spec; | ||
1420 | int err = patch_nvhdmi_2ch(codec); | ||
1421 | |||
1422 | if (err < 0) | ||
1423 | return err; | ||
1424 | spec = codec->spec; | ||
1425 | spec->multiout.max_channels = 8; | ||
1426 | spec->pcm_playback = &nvhdmi_pcm_playback_8ch_7x; | ||
1427 | codec->patch_ops = nvhdmi_patch_ops_8ch_7x; | ||
1428 | return 0; | ||
1429 | } | ||
1430 | |||
1431 | /* | ||
1432 | * ATI-specific implementations | ||
1433 | * | ||
1434 | * FIXME: we may omit the whole this and use the generic code once after | ||
1435 | * it's confirmed to work. | ||
1436 | */ | ||
1437 | |||
1438 | #define ATIHDMI_CVT_NID 0x02 /* audio converter */ | ||
1439 | #define ATIHDMI_PIN_NID 0x03 /* HDMI output pin */ | ||
1440 | |||
1441 | static int atihdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
1442 | struct hda_codec *codec, | ||
1443 | unsigned int stream_tag, | ||
1444 | unsigned int format, | ||
1445 | struct snd_pcm_substream *substream) | ||
1446 | { | ||
1447 | struct hdmi_spec *spec = codec->spec; | ||
1448 | int chans = substream->runtime->channels; | ||
1449 | int i, err; | ||
1450 | |||
1451 | err = simple_playback_pcm_prepare(hinfo, codec, stream_tag, format, | ||
1452 | substream); | ||
1453 | if (err < 0) | ||
1454 | return err; | ||
1455 | snd_hda_codec_write(codec, spec->cvt[0], 0, AC_VERB_SET_CVT_CHAN_COUNT, | ||
1456 | chans - 1); | ||
1457 | /* FIXME: XXX */ | ||
1458 | for (i = 0; i < chans; i++) { | ||
1459 | snd_hda_codec_write(codec, spec->cvt[0], 0, | ||
1460 | AC_VERB_SET_HDMI_CHAN_SLOT, | ||
1461 | (i << 4) | i); | ||
1462 | } | ||
1463 | return 0; | ||
1464 | } | ||
1465 | |||
1466 | static struct hda_pcm_stream atihdmi_pcm_digital_playback = { | ||
1467 | .substreams = 1, | ||
1468 | .channels_min = 2, | ||
1469 | .channels_max = 2, | ||
1470 | .nid = ATIHDMI_CVT_NID, | ||
1471 | .ops = { | ||
1472 | .open = simple_playback_pcm_open, | ||
1473 | .close = simple_playback_pcm_close, | ||
1474 | .prepare = atihdmi_playback_pcm_prepare | ||
1475 | }, | ||
1476 | }; | ||
1477 | |||
1478 | static struct hda_verb atihdmi_basic_init[] = { | ||
1479 | /* enable digital output on pin widget */ | ||
1480 | { 0x03, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
1481 | {} /* terminator */ | ||
1482 | }; | ||
1483 | |||
1484 | static int atihdmi_init(struct hda_codec *codec) | ||
1485 | { | ||
1486 | struct hdmi_spec *spec = codec->spec; | ||
1487 | |||
1488 | snd_hda_sequence_write(codec, atihdmi_basic_init); | ||
1489 | /* SI codec requires to unmute the pin */ | ||
1490 | if (get_wcaps(codec, spec->pin[0]) & AC_WCAP_OUT_AMP) | ||
1491 | snd_hda_codec_write(codec, spec->pin[0], 0, | ||
1492 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
1493 | AMP_OUT_UNMUTE); | ||
1494 | return 0; | ||
1495 | } | ||
1496 | |||
1497 | static struct hda_codec_ops atihdmi_patch_ops = { | ||
1498 | .build_controls = generic_hdmi_build_controls, | ||
1499 | .build_pcms = generic_hdmi_build_pcms, | ||
1500 | .init = atihdmi_init, | ||
1501 | .free = generic_hdmi_free, | ||
1502 | }; | ||
1503 | |||
1504 | |||
1505 | static int patch_atihdmi(struct hda_codec *codec) | ||
1506 | { | ||
1507 | struct hdmi_spec *spec; | ||
1508 | |||
1509 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
1510 | if (spec == NULL) | ||
1511 | return -ENOMEM; | ||
1512 | |||
1513 | codec->spec = spec; | ||
1514 | |||
1515 | spec->multiout.num_dacs = 0; /* no analog */ | ||
1516 | spec->multiout.max_channels = 2; | ||
1517 | spec->multiout.dig_out_nid = ATIHDMI_CVT_NID; | ||
1518 | spec->num_cvts = 1; | ||
1519 | spec->cvt[0] = ATIHDMI_CVT_NID; | ||
1520 | spec->pin[0] = ATIHDMI_PIN_NID; | ||
1521 | spec->pcm_playback = &atihdmi_pcm_digital_playback; | ||
1522 | |||
1523 | codec->patch_ops = atihdmi_patch_ops; | ||
1524 | |||
1525 | return 0; | ||
1526 | } | ||
1527 | |||
1528 | |||
1529 | /* | ||
1530 | * patch entries | ||
1531 | */ | ||
1532 | static struct hda_codec_preset snd_hda_preset_hdmi[] = { | ||
1533 | { .id = 0x1002793c, .name = "RS600 HDMI", .patch = patch_atihdmi }, | ||
1534 | { .id = 0x10027919, .name = "RS600 HDMI", .patch = patch_atihdmi }, | ||
1535 | { .id = 0x1002791a, .name = "RS690/780 HDMI", .patch = patch_atihdmi }, | ||
1536 | { .id = 0x1002aa01, .name = "R6xx HDMI", .patch = patch_atihdmi }, | ||
1537 | { .id = 0x10951390, .name = "SiI1390 HDMI", .patch = patch_generic_hdmi }, | ||
1538 | { .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_generic_hdmi }, | ||
1539 | { .id = 0x17e80047, .name = "Chrontel HDMI", .patch = patch_generic_hdmi }, | ||
1540 | { .id = 0x10de0002, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, | ||
1541 | { .id = 0x10de0003, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, | ||
1542 | { .id = 0x10de0005, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, | ||
1543 | { .id = 0x10de0006, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, | ||
1544 | { .id = 0x10de0007, .name = "MCP79/7A HDMI", .patch = patch_nvhdmi_8ch_7x }, | ||
1545 | { .id = 0x10de000a, .name = "GPU 0a HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
1546 | { .id = 0x10de000b, .name = "GPU 0b HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
1547 | { .id = 0x10de000c, .name = "MCP89 HDMI", .patch = patch_nvhdmi_8ch_89 }, | ||
1548 | { .id = 0x10de000d, .name = "GPU 0d HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
1549 | { .id = 0x10de0010, .name = "GPU 10 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
1550 | { .id = 0x10de0011, .name = "GPU 11 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
1551 | { .id = 0x10de0012, .name = "GPU 12 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
1552 | { .id = 0x10de0013, .name = "GPU 13 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
1553 | { .id = 0x10de0014, .name = "GPU 14 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
1554 | { .id = 0x10de0018, .name = "GPU 18 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
1555 | { .id = 0x10de0019, .name = "GPU 19 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
1556 | { .id = 0x10de001a, .name = "GPU 1a HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
1557 | { .id = 0x10de001b, .name = "GPU 1b HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
1558 | { .id = 0x10de001c, .name = "GPU 1c HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
1559 | { .id = 0x10de0040, .name = "GPU 40 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
1560 | { .id = 0x10de0041, .name = "GPU 41 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
1561 | { .id = 0x10de0042, .name = "GPU 42 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
1562 | { .id = 0x10de0043, .name = "GPU 43 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
1563 | { .id = 0x10de0044, .name = "GPU 44 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
1564 | { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, | ||
1565 | { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, | ||
1566 | { .id = 0x80860054, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi }, | ||
1567 | { .id = 0x80862801, .name = "Bearlake HDMI", .patch = patch_generic_hdmi }, | ||
1568 | { .id = 0x80862802, .name = "Cantiga HDMI", .patch = patch_generic_hdmi }, | ||
1569 | { .id = 0x80862803, .name = "Eaglelake HDMI", .patch = patch_generic_hdmi }, | ||
1570 | { .id = 0x80862804, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi }, | ||
1571 | { .id = 0x80862805, .name = "CougarPoint HDMI", .patch = patch_generic_hdmi }, | ||
1572 | { .id = 0x808629fb, .name = "Crestline HDMI", .patch = patch_generic_hdmi }, | ||
1573 | {} /* terminator */ | ||
1574 | }; | ||
1575 | |||
1576 | MODULE_ALIAS("snd-hda-codec-id:1002793c"); | ||
1577 | MODULE_ALIAS("snd-hda-codec-id:10027919"); | ||
1578 | MODULE_ALIAS("snd-hda-codec-id:1002791a"); | ||
1579 | MODULE_ALIAS("snd-hda-codec-id:1002aa01"); | ||
1580 | MODULE_ALIAS("snd-hda-codec-id:10951390"); | ||
1581 | MODULE_ALIAS("snd-hda-codec-id:10951392"); | ||
1582 | MODULE_ALIAS("snd-hda-codec-id:10de0002"); | ||
1583 | MODULE_ALIAS("snd-hda-codec-id:10de0003"); | ||
1584 | MODULE_ALIAS("snd-hda-codec-id:10de0005"); | ||
1585 | MODULE_ALIAS("snd-hda-codec-id:10de0006"); | ||
1586 | MODULE_ALIAS("snd-hda-codec-id:10de0007"); | ||
1587 | MODULE_ALIAS("snd-hda-codec-id:10de000a"); | ||
1588 | MODULE_ALIAS("snd-hda-codec-id:10de000b"); | ||
1589 | MODULE_ALIAS("snd-hda-codec-id:10de000c"); | ||
1590 | MODULE_ALIAS("snd-hda-codec-id:10de000d"); | ||
1591 | MODULE_ALIAS("snd-hda-codec-id:10de0010"); | ||
1592 | MODULE_ALIAS("snd-hda-codec-id:10de0011"); | ||
1593 | MODULE_ALIAS("snd-hda-codec-id:10de0012"); | ||
1594 | MODULE_ALIAS("snd-hda-codec-id:10de0013"); | ||
1595 | MODULE_ALIAS("snd-hda-codec-id:10de0014"); | ||
1596 | MODULE_ALIAS("snd-hda-codec-id:10de0018"); | ||
1597 | MODULE_ALIAS("snd-hda-codec-id:10de0019"); | ||
1598 | MODULE_ALIAS("snd-hda-codec-id:10de001a"); | ||
1599 | MODULE_ALIAS("snd-hda-codec-id:10de001b"); | ||
1600 | MODULE_ALIAS("snd-hda-codec-id:10de001c"); | ||
1601 | MODULE_ALIAS("snd-hda-codec-id:10de0040"); | ||
1602 | MODULE_ALIAS("snd-hda-codec-id:10de0041"); | ||
1603 | MODULE_ALIAS("snd-hda-codec-id:10de0042"); | ||
1604 | MODULE_ALIAS("snd-hda-codec-id:10de0043"); | ||
1605 | MODULE_ALIAS("snd-hda-codec-id:10de0044"); | ||
1606 | MODULE_ALIAS("snd-hda-codec-id:10de0067"); | ||
1607 | MODULE_ALIAS("snd-hda-codec-id:10de8001"); | ||
1608 | MODULE_ALIAS("snd-hda-codec-id:17e80047"); | ||
1609 | MODULE_ALIAS("snd-hda-codec-id:80860054"); | ||
1610 | MODULE_ALIAS("snd-hda-codec-id:80862801"); | ||
1611 | MODULE_ALIAS("snd-hda-codec-id:80862802"); | ||
1612 | MODULE_ALIAS("snd-hda-codec-id:80862803"); | ||
1613 | MODULE_ALIAS("snd-hda-codec-id:80862804"); | ||
1614 | MODULE_ALIAS("snd-hda-codec-id:80862805"); | ||
1615 | MODULE_ALIAS("snd-hda-codec-id:808629fb"); | ||
1616 | |||
1617 | MODULE_LICENSE("GPL"); | ||
1618 | MODULE_DESCRIPTION("HDMI HD-audio codec"); | ||
1619 | MODULE_ALIAS("snd-hda-codec-intelhdmi"); | ||
1620 | MODULE_ALIAS("snd-hda-codec-nvhdmi"); | ||
1621 | MODULE_ALIAS("snd-hda-codec-atihdmi"); | ||
1622 | |||
1623 | static struct hda_codec_preset_list intel_list = { | ||
1624 | .preset = snd_hda_preset_hdmi, | ||
1625 | .owner = THIS_MODULE, | ||
1626 | }; | ||
1627 | |||
1628 | static int __init patch_hdmi_init(void) | ||
1629 | { | ||
1630 | return snd_hda_add_codec_preset(&intel_list); | ||
1631 | } | ||
1632 | |||
1633 | static void __exit patch_hdmi_exit(void) | ||
1634 | { | ||
1635 | snd_hda_delete_codec_preset(&intel_list); | ||
1636 | } | ||
1637 | |||
1638 | module_init(patch_hdmi_init) | ||
1639 | module_exit(patch_hdmi_exit) | ||