diff options
| author | Takashi Iwai <tiwai@suse.de> | 2009-12-12 12:18:08 -0500 |
|---|---|---|
| committer | Takashi Iwai <tiwai@suse.de> | 2009-12-12 12:18:08 -0500 |
| commit | 84a3bd061c1974aea4b14b954e518ce144e407c6 (patch) | |
| tree | 1dade22a9448d6aa0f7fd2a4d052374132b9567b | |
| parent | f52d7a4393136107f526040f6ef190ab49032496 (diff) | |
| parent | 52dc438606d1ef78b96f56cc04dbea9242005730 (diff) | |
Merge branch 'topic/hda' into for-linus
| -rw-r--r-- | sound/pci/hda/hda_codec.h | 5 | ||||
| -rw-r--r-- | sound/pci/hda/hda_intel.c | 3 | ||||
| -rw-r--r-- | sound/pci/hda/hda_proc.c | 7 | ||||
| -rw-r--r-- | sound/pci/hda/patch_intelhdmi.c | 114 | ||||
| -rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 103 |
5 files changed, 175 insertions, 57 deletions
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 2d627613aea3..1d541b7f5547 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
| @@ -255,9 +255,13 @@ enum { | |||
| 255 | * in HD-audio specification | 255 | * in HD-audio specification |
| 256 | */ | 256 | */ |
| 257 | #define AC_PINCAP_HDMI (1<<7) /* HDMI pin */ | 257 | #define AC_PINCAP_HDMI (1<<7) /* HDMI pin */ |
| 258 | #define AC_PINCAP_DP (1<<24) /* DisplayPort pin, can | ||
| 259 | * coexist with AC_PINCAP_HDMI | ||
| 260 | */ | ||
| 258 | #define AC_PINCAP_VREF (0x37<<8) | 261 | #define AC_PINCAP_VREF (0x37<<8) |
| 259 | #define AC_PINCAP_VREF_SHIFT 8 | 262 | #define AC_PINCAP_VREF_SHIFT 8 |
| 260 | #define AC_PINCAP_EAPD (1<<16) /* EAPD capable */ | 263 | #define AC_PINCAP_EAPD (1<<16) /* EAPD capable */ |
| 264 | #define AC_PINCAP_HBR (1<<27) /* High Bit Rate */ | ||
| 261 | /* Vref status (used in pin cap) */ | 265 | /* Vref status (used in pin cap) */ |
| 262 | #define AC_PINCAP_VREF_HIZ (1<<0) /* Hi-Z */ | 266 | #define AC_PINCAP_VREF_HIZ (1<<0) /* Hi-Z */ |
| 263 | #define AC_PINCAP_VREF_50 (1<<1) /* 50% */ | 267 | #define AC_PINCAP_VREF_50 (1<<1) /* 50% */ |
| @@ -635,6 +639,7 @@ struct hda_bus { | |||
| 635 | unsigned int rirb_error:1; /* error in codec communication */ | 639 | unsigned int rirb_error:1; /* error in codec communication */ |
| 636 | unsigned int response_reset:1; /* controller was reset */ | 640 | unsigned int response_reset:1; /* controller was reset */ |
| 637 | unsigned int in_reset:1; /* during reset operation */ | 641 | unsigned int in_reset:1; /* during reset operation */ |
| 642 | unsigned int power_keep_link_on:1; /* don't power off HDA link */ | ||
| 638 | }; | 643 | }; |
| 639 | 644 | ||
| 640 | /* | 645 | /* |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index efcc4f7c57f2..e54420e691ae 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
| @@ -2082,7 +2082,8 @@ static void azx_power_notify(struct hda_bus *bus) | |||
| 2082 | } | 2082 | } |
| 2083 | if (power_on) | 2083 | if (power_on) |
| 2084 | azx_init_chip(chip); | 2084 | azx_init_chip(chip); |
| 2085 | else if (chip->running && power_save_controller) | 2085 | else if (chip->running && power_save_controller && |
| 2086 | !bus->power_keep_link_on) | ||
| 2086 | azx_stop_chip(chip); | 2087 | azx_stop_chip(chip); |
| 2087 | } | 2088 | } |
| 2088 | #endif /* CONFIG_SND_HDA_POWER_SAVE */ | 2089 | #endif /* CONFIG_SND_HDA_POWER_SAVE */ |
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index 09476fc1ab64..c9afc04adac8 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c | |||
| @@ -240,9 +240,14 @@ static void print_pin_caps(struct snd_info_buffer *buffer, | |||
| 240 | /* Realtek uses this bit as a different meaning */ | 240 | /* Realtek uses this bit as a different meaning */ |
| 241 | if ((codec->vendor_id >> 16) == 0x10ec) | 241 | if ((codec->vendor_id >> 16) == 0x10ec) |
| 242 | snd_iprintf(buffer, " R/L"); | 242 | snd_iprintf(buffer, " R/L"); |
| 243 | else | 243 | else { |
| 244 | if (caps & AC_PINCAP_HBR) | ||
| 245 | snd_iprintf(buffer, " HBR"); | ||
| 244 | snd_iprintf(buffer, " HDMI"); | 246 | snd_iprintf(buffer, " HDMI"); |
| 247 | } | ||
| 245 | } | 248 | } |
| 249 | if (caps & AC_PINCAP_DP) | ||
| 250 | snd_iprintf(buffer, " DP"); | ||
| 246 | if (caps & AC_PINCAP_TRIG_REQ) | 251 | if (caps & AC_PINCAP_TRIG_REQ) |
| 247 | snd_iprintf(buffer, " Trigger"); | 252 | snd_iprintf(buffer, " Trigger"); |
| 248 | if (caps & AC_PINCAP_IMP_SENSE) | 253 | if (caps & AC_PINCAP_IMP_SENSE) |
diff --git a/sound/pci/hda/patch_intelhdmi.c b/sound/pci/hda/patch_intelhdmi.c index 928df59be5d8..918f40378d52 100644 --- a/sound/pci/hda/patch_intelhdmi.c +++ b/sound/pci/hda/patch_intelhdmi.c | |||
| @@ -146,38 +146,78 @@ struct cea_channel_speaker_allocation { | |||
| 146 | }; | 146 | }; |
| 147 | 147 | ||
| 148 | /* | 148 | /* |
| 149 | * ALSA sequence is: | ||
| 150 | * | ||
| 151 | * surround40 surround41 surround50 surround51 surround71 | ||
| 152 | * ch0 front left = = = = | ||
| 153 | * ch1 front right = = = = | ||
| 154 | * ch2 rear left = = = = | ||
| 155 | * ch3 rear right = = = = | ||
| 156 | * ch4 LFE center center center | ||
| 157 | * ch5 LFE LFE | ||
| 158 | * ch6 side left | ||
| 159 | * ch7 side right | ||
| 160 | * | ||
| 161 | * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR} | ||
| 162 | */ | ||
| 163 | static int hdmi_channel_mapping[0x32][8] = { | ||
| 164 | /* stereo */ | ||
| 165 | [0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, | ||
| 166 | /* 2.1 */ | ||
| 167 | [0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, | ||
| 168 | /* Dolby Surround */ | ||
| 169 | [0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 }, | ||
| 170 | /* surround40 */ | ||
| 171 | [0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 }, | ||
| 172 | /* 4ch */ | ||
| 173 | [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 }, | ||
| 174 | /* surround41 */ | ||
| 175 | [0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 }, | ||
| 176 | /* surround50 */ | ||
| 177 | [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 }, | ||
| 178 | /* surround51 */ | ||
| 179 | [0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 }, | ||
| 180 | /* 7.1 */ | ||
| 181 | [0x13] = { 0x00, 0x11, 0x26, 0x37, 0x43, 0x52, 0x64, 0x75 }, | ||
| 182 | }; | ||
| 183 | |||
| 184 | /* | ||
| 149 | * This is an ordered list! | 185 | * This is an ordered list! |
| 150 | * | 186 | * |
| 151 | * The preceding ones have better chances to be selected by | 187 | * The preceding ones have better chances to be selected by |
| 152 | * hdmi_setup_channel_allocation(). | 188 | * hdmi_setup_channel_allocation(). |
| 153 | */ | 189 | */ |
| 154 | static struct cea_channel_speaker_allocation channel_allocations[] = { | 190 | static struct cea_channel_speaker_allocation channel_allocations[] = { |
| 155 | /* channel: 8 7 6 5 4 3 2 1 */ | 191 | /* channel: 7 6 5 4 3 2 1 0 */ |
| 156 | { .ca_index = 0x00, .speakers = { 0, 0, 0, 0, 0, 0, FR, FL } }, | 192 | { .ca_index = 0x00, .speakers = { 0, 0, 0, 0, 0, 0, FR, FL } }, |
| 157 | /* 2.1 */ | 193 | /* 2.1 */ |
| 158 | { .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL } }, | 194 | { .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL } }, |
| 159 | /* Dolby Surround */ | 195 | /* Dolby Surround */ |
| 160 | { .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL } }, | 196 | { .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL } }, |
| 197 | /* surround40 */ | ||
| 198 | { .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } }, | ||
| 199 | /* surround41 */ | ||
| 200 | { .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } }, | ||
| 201 | /* surround50 */ | ||
| 202 | { .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } }, | ||
| 203 | /* surround51 */ | ||
| 204 | { .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } }, | ||
| 205 | /* 6.1 */ | ||
| 206 | { .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } }, | ||
| 207 | /* surround71 */ | ||
| 208 | { .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } }, | ||
| 209 | |||
| 161 | { .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL } }, | 210 | { .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL } }, |
| 162 | { .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL } }, | 211 | { .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL } }, |
| 163 | { .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL } }, | 212 | { .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL } }, |
| 164 | { .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL } }, | 213 | { .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL } }, |
| 165 | { .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL } }, | 214 | { .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL } }, |
| 166 | { .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } }, | ||
| 167 | { .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } }, | ||
| 168 | { .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } }, | ||
| 169 | /* 5.1 */ | ||
| 170 | { .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } }, | ||
| 171 | { .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL } }, | 215 | { .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL } }, |
| 172 | { .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL } }, | 216 | { .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL } }, |
| 173 | { .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL } }, | 217 | { .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL } }, |
| 174 | /* 6.1 */ | ||
| 175 | { .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } }, | ||
| 176 | { .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL } }, | 218 | { .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL } }, |
| 177 | { .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL } }, | 219 | { .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL } }, |
| 178 | { .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL } }, | 220 | { .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL } }, |
| 179 | /* 7.1 */ | ||
| 180 | { .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } }, | ||
| 181 | { .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL } }, | 221 | { .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL } }, |
| 182 | { .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL } }, | 222 | { .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL } }, |
| 183 | { .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL } }, | 223 | { .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL } }, |
| @@ -210,7 +250,6 @@ static struct cea_channel_speaker_allocation channel_allocations[] = { | |||
| 210 | { .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } }, | 250 | { .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } }, |
| 211 | }; | 251 | }; |
| 212 | 252 | ||
| 213 | |||
| 214 | /* | 253 | /* |
| 215 | * HDA/HDMI auto parsing | 254 | * HDA/HDMI auto parsing |
| 216 | */ | 255 | */ |
| @@ -344,7 +383,7 @@ static int intel_hdmi_parse_codec(struct hda_codec *codec) | |||
| 344 | break; | 383 | break; |
| 345 | case AC_WID_PIN: | 384 | case AC_WID_PIN: |
| 346 | caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); | 385 | caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); |
| 347 | if (!(caps & AC_PINCAP_HDMI)) | 386 | if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP))) |
| 348 | continue; | 387 | continue; |
| 349 | if (intel_hdmi_add_pin(codec, nid) < 0) | 388 | if (intel_hdmi_add_pin(codec, nid) < 0) |
| 350 | return -EINVAL; | 389 | return -EINVAL; |
| @@ -352,6 +391,17 @@ static int intel_hdmi_parse_codec(struct hda_codec *codec) | |||
| 352 | } | 391 | } |
| 353 | } | 392 | } |
| 354 | 393 | ||
| 394 | /* | ||
| 395 | * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event | ||
| 396 | * can be lost and presence sense verb will become inaccurate if the | ||
| 397 | * HDA link is powered off at hot plug or hw initialization time. | ||
| 398 | */ | ||
| 399 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
| 400 | if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) & | ||
| 401 | AC_PWRST_EPSS)) | ||
| 402 | codec->bus->power_keep_link_on = 1; | ||
| 403 | #endif | ||
| 404 | |||
| 355 | return 0; | 405 | return 0; |
| 356 | } | 406 | } |
| 357 | 407 | ||
| @@ -436,14 +486,15 @@ static void hdmi_set_channel_count(struct hda_codec *codec, | |||
| 436 | AC_VERB_SET_CVT_CHAN_COUNT, chs - 1); | 486 | AC_VERB_SET_CVT_CHAN_COUNT, chs - 1); |
| 437 | } | 487 | } |
| 438 | 488 | ||
| 439 | static void hdmi_debug_channel_mapping(struct hda_codec *codec, hda_nid_t nid) | 489 | static void hdmi_debug_channel_mapping(struct hda_codec *codec, |
| 490 | hda_nid_t pin_nid) | ||
| 440 | { | 491 | { |
| 441 | #ifdef CONFIG_SND_DEBUG_VERBOSE | 492 | #ifdef CONFIG_SND_DEBUG_VERBOSE |
| 442 | int i; | 493 | int i; |
| 443 | int slot; | 494 | int slot; |
| 444 | 495 | ||
| 445 | for (i = 0; i < 8; i++) { | 496 | for (i = 0; i < 8; i++) { |
| 446 | slot = snd_hda_codec_read(codec, nid, 0, | 497 | slot = snd_hda_codec_read(codec, pin_nid, 0, |
| 447 | AC_VERB_GET_HDMI_CHAN_SLOT, i); | 498 | AC_VERB_GET_HDMI_CHAN_SLOT, i); |
| 448 | printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n", | 499 | printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n", |
| 449 | slot >> 4, slot & 0xf); | 500 | slot >> 4, slot & 0xf); |
| @@ -619,25 +670,32 @@ static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid, | |||
| 619 | return ai->CA; | 670 | return ai->CA; |
| 620 | } | 671 | } |
| 621 | 672 | ||
| 622 | static void hdmi_setup_channel_mapping(struct hda_codec *codec, hda_nid_t nid, | 673 | static void hdmi_setup_channel_mapping(struct hda_codec *codec, |
| 674 | hda_nid_t pin_nid, | ||
| 623 | struct hdmi_audio_infoframe *ai) | 675 | struct hdmi_audio_infoframe *ai) |
| 624 | { | 676 | { |
| 625 | int i; | 677 | int i; |
| 678 | int ca = ai->CA; | ||
| 679 | int err; | ||
| 626 | 680 | ||
| 627 | if (!ai->CA) | 681 | if (hdmi_channel_mapping[ca][1] == 0) { |
| 628 | return; | 682 | for (i = 0; i < channel_allocations[ca].channels; i++) |
| 629 | 683 | hdmi_channel_mapping[ca][i] = i | (i << 4); | |
| 630 | /* | 684 | for (; i < 8; i++) |
| 631 | * TODO: adjust channel mapping if necessary | 685 | hdmi_channel_mapping[ca][i] = 0xf | (i << 4); |
| 632 | * ALSA sequence is front/surr/clfe/side? | 686 | } |
| 633 | */ | ||
| 634 | 687 | ||
| 635 | for (i = 0; i < 8; i++) | 688 | for (i = 0; i < 8; i++) { |
| 636 | snd_hda_codec_write(codec, nid, 0, | 689 | err = snd_hda_codec_write(codec, pin_nid, 0, |
| 637 | AC_VERB_SET_HDMI_CHAN_SLOT, | 690 | AC_VERB_SET_HDMI_CHAN_SLOT, |
| 638 | (i << 4) | i); | 691 | hdmi_channel_mapping[ca][i]); |
| 692 | if (err) { | ||
| 693 | snd_printdd(KERN_INFO "HDMI: channel mapping failed\n"); | ||
| 694 | break; | ||
| 695 | } | ||
| 696 | } | ||
| 639 | 697 | ||
| 640 | hdmi_debug_channel_mapping(codec, nid); | 698 | hdmi_debug_channel_mapping(codec, pin_nid); |
| 641 | } | 699 | } |
| 642 | 700 | ||
| 643 | static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, | 701 | static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, |
| @@ -676,7 +734,6 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid, | |||
| 676 | }; | 734 | }; |
| 677 | 735 | ||
| 678 | hdmi_setup_channel_allocation(codec, nid, &ai); | 736 | hdmi_setup_channel_allocation(codec, nid, &ai); |
| 679 | hdmi_setup_channel_mapping(codec, nid, &ai); | ||
| 680 | 737 | ||
| 681 | for (i = 0; i < spec->num_pins; i++) { | 738 | for (i = 0; i < spec->num_pins; i++) { |
| 682 | if (spec->pin_cvt[i] != nid) | 739 | if (spec->pin_cvt[i] != nid) |
| @@ -686,6 +743,7 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid, | |||
| 686 | 743 | ||
| 687 | pin_nid = spec->pin[i]; | 744 | pin_nid = spec->pin[i]; |
| 688 | if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) { | 745 | if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) { |
| 746 | hdmi_setup_channel_mapping(codec, pin_nid, &ai); | ||
| 689 | hdmi_stop_infoframe_trans(codec, pin_nid); | 747 | hdmi_stop_infoframe_trans(codec, pin_nid); |
| 690 | hdmi_fill_audio_infoframe(codec, pin_nid, &ai); | 748 | hdmi_fill_audio_infoframe(codec, pin_nid, &ai); |
| 691 | hdmi_start_infoframe_trans(codec, pin_nid); | 749 | hdmi_start_infoframe_trans(codec, pin_nid); |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 6b0bc040c3b1..3d59f8325848 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
| @@ -209,6 +209,7 @@ struct sigmatel_spec { | |||
| 209 | unsigned int gpio_data; | 209 | unsigned int gpio_data; |
| 210 | unsigned int gpio_mute; | 210 | unsigned int gpio_mute; |
| 211 | unsigned int gpio_led; | 211 | unsigned int gpio_led; |
| 212 | unsigned int gpio_led_polarity; | ||
| 212 | 213 | ||
| 213 | /* stream */ | 214 | /* stream */ |
| 214 | unsigned int stream_delay; | 215 | unsigned int stream_delay; |
| @@ -1538,6 +1539,13 @@ static unsigned int alienware_m17x_pin_configs[13] = { | |||
| 1538 | 0x904601b0, | 1539 | 0x904601b0, |
| 1539 | }; | 1540 | }; |
| 1540 | 1541 | ||
| 1542 | static unsigned int intel_dg45id_pin_configs[14] = { | ||
| 1543 | 0x02214230, 0x02A19240, 0x01013214, 0x01014210, | ||
| 1544 | 0x01A19250, 0x01011212, 0x01016211, 0x40f000f0, | ||
| 1545 | 0x40f000f0, 0x40f000f0, 0x40f000f0, 0x014510A0, | ||
| 1546 | 0x074510B0, 0x40f000f0 | ||
| 1547 | }; | ||
| 1548 | |||
| 1541 | static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = { | 1549 | static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = { |
| 1542 | [STAC_92HD73XX_REF] = ref92hd73xx_pin_configs, | 1550 | [STAC_92HD73XX_REF] = ref92hd73xx_pin_configs, |
| 1543 | [STAC_DELL_M6_AMIC] = dell_m6_pin_configs, | 1551 | [STAC_DELL_M6_AMIC] = dell_m6_pin_configs, |
| @@ -1545,6 +1553,7 @@ static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = { | |||
| 1545 | [STAC_DELL_M6_BOTH] = dell_m6_pin_configs, | 1553 | [STAC_DELL_M6_BOTH] = dell_m6_pin_configs, |
| 1546 | [STAC_DELL_EQ] = dell_m6_pin_configs, | 1554 | [STAC_DELL_EQ] = dell_m6_pin_configs, |
| 1547 | [STAC_ALIENWARE_M17X] = alienware_m17x_pin_configs, | 1555 | [STAC_ALIENWARE_M17X] = alienware_m17x_pin_configs, |
| 1556 | [STAC_92HD73XX_INTEL] = intel_dg45id_pin_configs, | ||
| 1548 | }; | 1557 | }; |
| 1549 | 1558 | ||
| 1550 | static const char *stac92hd73xx_models[STAC_92HD73XX_MODELS] = { | 1559 | static const char *stac92hd73xx_models[STAC_92HD73XX_MODELS] = { |
| @@ -4724,13 +4733,61 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) | |||
| 4724 | } | 4733 | } |
| 4725 | } | 4734 | } |
| 4726 | 4735 | ||
| 4727 | static int hp_bseries_system(u32 subsystem_id) | 4736 | /* |
| 4737 | * This method searches for the mute LED GPIO configuration | ||
| 4738 | * provided as OEM string in SMBIOS. The format of that string | ||
| 4739 | * is HP_Mute_LED_P_G or HP_Mute_LED_P | ||
| 4740 | * where P can be 0 or 1 and defines mute LED GPIO control state (low/high) | ||
| 4741 | * that corresponds to the NOT muted state of the master volume | ||
| 4742 | * and G is the index of the GPIO to use as the mute LED control (0..9) | ||
| 4743 | * If _G portion is missing it is assigned based on the codec ID | ||
| 4744 | * | ||
| 4745 | * So, HP B-series like systems may have HP_Mute_LED_0 (current models) | ||
| 4746 | * or HP_Mute_LED_0_3 (future models) OEM SMBIOS strings | ||
| 4747 | */ | ||
| 4748 | static int find_mute_led_gpio(struct hda_codec *codec) | ||
| 4749 | { | ||
| 4750 | struct sigmatel_spec *spec = codec->spec; | ||
| 4751 | const struct dmi_device *dev = NULL; | ||
| 4752 | |||
| 4753 | if ((codec->subsystem_id >> 16) == PCI_VENDOR_ID_HP) { | ||
| 4754 | while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, | ||
| 4755 | NULL, dev))) { | ||
| 4756 | if (sscanf(dev->name, "HP_Mute_LED_%d_%d", | ||
| 4757 | &spec->gpio_led_polarity, | ||
| 4758 | &spec->gpio_led) == 2) { | ||
| 4759 | spec->gpio_led = 1 << spec->gpio_led; | ||
| 4760 | return 1; | ||
| 4761 | } | ||
| 4762 | if (sscanf(dev->name, "HP_Mute_LED_%d", | ||
| 4763 | &spec->gpio_led_polarity) == 1) { | ||
| 4764 | switch (codec->vendor_id) { | ||
| 4765 | case 0x111d7608: | ||
| 4766 | /* GPIO 0 */ | ||
| 4767 | spec->gpio_led = 0x01; | ||
| 4768 | return 1; | ||
| 4769 | case 0x111d7600: | ||
| 4770 | case 0x111d7601: | ||
| 4771 | case 0x111d7602: | ||
| 4772 | case 0x111d7603: | ||
| 4773 | /* GPIO 3 */ | ||
| 4774 | spec->gpio_led = 0x08; | ||
| 4775 | return 1; | ||
| 4776 | } | ||
| 4777 | } | ||
| 4778 | } | ||
| 4779 | } | ||
| 4780 | return 0; | ||
| 4781 | } | ||
| 4782 | |||
| 4783 | static int hp_blike_system(u32 subsystem_id) | ||
| 4728 | { | 4784 | { |
| 4729 | switch (subsystem_id) { | 4785 | switch (subsystem_id) { |
| 4730 | case 0x103c307e: | 4786 | case 0x103c1520: |
| 4731 | case 0x103c307f: | 4787 | case 0x103c1521: |
| 4732 | case 0x103c3080: | 4788 | case 0x103c1523: |
| 4733 | case 0x103c3081: | 4789 | case 0x103c1524: |
| 4790 | case 0x103c1525: | ||
| 4734 | case 0x103c1722: | 4791 | case 0x103c1722: |
| 4735 | case 0x103c1723: | 4792 | case 0x103c1723: |
| 4736 | case 0x103c1724: | 4793 | case 0x103c1724: |
| @@ -4739,6 +4796,14 @@ static int hp_bseries_system(u32 subsystem_id) | |||
| 4739 | case 0x103c1727: | 4796 | case 0x103c1727: |
| 4740 | case 0x103c1728: | 4797 | case 0x103c1728: |
| 4741 | case 0x103c1729: | 4798 | case 0x103c1729: |
| 4799 | case 0x103c172a: | ||
| 4800 | case 0x103c172b: | ||
| 4801 | case 0x103c307e: | ||
| 4802 | case 0x103c307f: | ||
| 4803 | case 0x103c3080: | ||
| 4804 | case 0x103c3081: | ||
| 4805 | case 0x103c7007: | ||
| 4806 | case 0x103c7008: | ||
| 4742 | return 1; | 4807 | return 1; |
| 4743 | } | 4808 | } |
| 4744 | return 0; | 4809 | return 0; |
| @@ -4833,7 +4898,7 @@ static int stac92xx_hp_check_power_status(struct hda_codec *codec, | |||
| 4833 | else | 4898 | else |
| 4834 | spec->gpio_data |= spec->gpio_led; /* white */ | 4899 | spec->gpio_data |= spec->gpio_led; /* white */ |
| 4835 | 4900 | ||
| 4836 | if (hp_bseries_system(codec->subsystem_id)) { | 4901 | if (!spec->gpio_led_polarity) { |
| 4837 | /* LED state is inverted on these systems */ | 4902 | /* LED state is inverted on these systems */ |
| 4838 | spec->gpio_data ^= spec->gpio_led; | 4903 | spec->gpio_data ^= spec->gpio_led; |
| 4839 | } | 4904 | } |
| @@ -5526,7 +5591,7 @@ again: | |||
| 5526 | break; | 5591 | break; |
| 5527 | } | 5592 | } |
| 5528 | 5593 | ||
| 5529 | if (hp_bseries_system(codec->subsystem_id)) { | 5594 | if (hp_blike_system(codec->subsystem_id)) { |
| 5530 | pin_cfg = snd_hda_codec_get_pincfg(codec, 0x0f); | 5595 | pin_cfg = snd_hda_codec_get_pincfg(codec, 0x0f); |
| 5531 | if (get_defcfg_device(pin_cfg) == AC_JACK_LINE_OUT || | 5596 | if (get_defcfg_device(pin_cfg) == AC_JACK_LINE_OUT || |
| 5532 | get_defcfg_device(pin_cfg) == AC_JACK_SPEAKER || | 5597 | get_defcfg_device(pin_cfg) == AC_JACK_SPEAKER || |
| @@ -5544,26 +5609,10 @@ again: | |||
| 5544 | } | 5609 | } |
| 5545 | } | 5610 | } |
| 5546 | 5611 | ||
| 5547 | if ((codec->subsystem_id >> 16) == PCI_VENDOR_ID_HP) { | 5612 | if (find_mute_led_gpio(codec)) |
| 5548 | const struct dmi_device *dev = NULL; | 5613 | snd_printd("mute LED gpio %d polarity %d\n", |
| 5549 | while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, | 5614 | spec->gpio_led, |
| 5550 | NULL, dev))) { | 5615 | spec->gpio_led_polarity); |
| 5551 | if (strcmp(dev->name, "HP_Mute_LED_1")) { | ||
| 5552 | switch (codec->vendor_id) { | ||
| 5553 | case 0x111d7608: | ||
| 5554 | spec->gpio_led = 0x01; | ||
| 5555 | break; | ||
| 5556 | case 0x111d7600: | ||
| 5557 | case 0x111d7601: | ||
| 5558 | case 0x111d7602: | ||
| 5559 | case 0x111d7603: | ||
| 5560 | spec->gpio_led = 0x08; | ||
| 5561 | break; | ||
| 5562 | } | ||
| 5563 | break; | ||
| 5564 | } | ||
| 5565 | } | ||
| 5566 | } | ||
| 5567 | 5616 | ||
| 5568 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 5617 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
| 5569 | if (spec->gpio_led) { | 5618 | if (spec->gpio_led) { |
