ALSA: hda - Restore default pin configs for realtek codecs

Some machines have broken BIOS resume that doesn't restore the default
pin configuration properly, which results in a wrong detection of HP
pin. This causes a silent speaker output due to missing HP detection.
Related bug: Novell bug#406101
https://bugzilla.novell.com/show_bug.cgi?id=406101

This patch fixes the issue by saving/restoring the default pin configs
by the driver itself.

Signed-off-by: Takashi Iwai <tiwai@suse.de>

+77
+77
sound/pci/hda/patch_realtek.c
··· 307 307 /* for PLL fix */ 308 308 hda_nid_t pll_nid; 309 309 unsigned int pll_coef_idx, pll_coef_bit; 310 + 311 + #ifdef SND_HDA_NEEDS_RESUME 312 + #define ALC_MAX_PINS 16 313 + unsigned int num_pins; 314 + hda_nid_t pin_nids[ALC_MAX_PINS]; 315 + unsigned int pin_cfgs[ALC_MAX_PINS]; 316 + #endif 310 317 }; 311 318 312 319 /* ··· 2785 2778 codec->spec = NULL; /* to be sure */ 2786 2779 } 2787 2780 2781 + #ifdef SND_HDA_NEEDS_RESUME 2782 + static void store_pin_configs(struct hda_codec *codec) 2783 + { 2784 + struct alc_spec *spec = codec->spec; 2785 + hda_nid_t nid, end_nid; 2786 + 2787 + end_nid = codec->start_nid + codec->num_nodes; 2788 + for (nid = codec->start_nid; nid < end_nid; nid++) { 2789 + unsigned int wid_caps = get_wcaps(codec, nid); 2790 + unsigned int wid_type = 2791 + (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; 2792 + if (wid_type != AC_WID_PIN) 2793 + continue; 2794 + if (spec->num_pins >= ARRAY_SIZE(spec->pin_nids)) 2795 + break; 2796 + spec->pin_nids[spec->num_pins] = nid; 2797 + spec->pin_cfgs[spec->num_pins] = 2798 + snd_hda_codec_read(codec, nid, 0, 2799 + AC_VERB_GET_CONFIG_DEFAULT, 0); 2800 + spec->num_pins++; 2801 + } 2802 + } 2803 + 2804 + static void resume_pin_configs(struct hda_codec *codec) 2805 + { 2806 + struct alc_spec *spec = codec->spec; 2807 + int i; 2808 + 2809 + for (i = 0; i < spec->num_pins; i++) { 2810 + hda_nid_t pin_nid = spec->pin_nids[i]; 2811 + unsigned int pin_config = spec->pin_cfgs[i]; 2812 + snd_hda_codec_write(codec, pin_nid, 0, 2813 + AC_VERB_SET_CONFIG_DEFAULT_BYTES_0, 2814 + pin_config & 0x000000ff); 2815 + snd_hda_codec_write(codec, pin_nid, 0, 2816 + AC_VERB_SET_CONFIG_DEFAULT_BYTES_1, 2817 + (pin_config & 0x0000ff00) >> 8); 2818 + snd_hda_codec_write(codec, pin_nid, 0, 2819 + AC_VERB_SET_CONFIG_DEFAULT_BYTES_2, 2820 + (pin_config & 0x00ff0000) >> 16); 2821 + snd_hda_codec_write(codec, pin_nid, 0, 2822 + AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, 2823 + pin_config >> 24); 2824 + } 2825 + } 2826 + 2827 + static int alc_resume(struct hda_codec *codec) 2828 + { 2829 + resume_pin_configs(codec); 2830 + codec->patch_ops.init(codec); 2831 + snd_hda_codec_resume_amp(codec); 2832 + snd_hda_codec_resume_cache(codec); 2833 + return 0; 2834 + } 2835 + #else 2836 + #define store_pin_configs(codec) 2837 + #endif 2838 + 2788 2839 /* 2789 2840 */ 2790 2841 static struct hda_codec_ops alc_patch_ops = { ··· 2851 2786 .init = alc_init, 2852 2787 .free = alc_free, 2853 2788 .unsol_event = alc_unsol_event, 2789 + #ifdef SND_HDA_NEEDS_RESUME 2790 + .resume = alc_resume, 2791 + #endif 2854 2792 #ifdef CONFIG_SND_HDA_POWER_SAVE 2855 2793 .check_power_status = alc_check_power_status, 2856 2794 #endif ··· 3900 3832 spec->num_mux_defs = 1; 3901 3833 spec->input_mux = &spec->private_imux; 3902 3834 3835 + store_pin_configs(codec); 3903 3836 return 1; 3904 3837 } 3905 3838 ··· 5319 5250 } 5320 5251 spec->num_mixers++; 5321 5252 5253 + store_pin_configs(codec); 5322 5254 return 1; 5323 5255 } 5324 5256 ··· 10383 10313 if (err < 0) 10384 10314 return err; 10385 10315 10316 + store_pin_configs(codec); 10386 10317 return 1; 10387 10318 } 10388 10319 ··· 11518 11447 if (err < 0) 11519 11448 return err; 11520 11449 11450 + store_pin_configs(codec); 11521 11451 return 1; 11522 11452 } 11523 11453 ··· 12302 12230 spec->mixers[spec->num_mixers] = alc269_capture_mixer; 12303 12231 spec->num_mixers++; 12304 12232 12233 + store_pin_configs(codec); 12305 12234 return 1; 12306 12235 } 12307 12236 ··· 13389 13316 spec->mixers[spec->num_mixers] = alc861_capture_mixer; 13390 13317 spec->num_mixers++; 13391 13318 13319 + store_pin_configs(codec); 13392 13320 return 1; 13393 13321 } 13394 13322 ··· 14501 14427 if (err < 0) 14502 14428 return err; 14503 14429 14430 + store_pin_configs(codec); 14504 14431 return 1; 14505 14432 } 14506 14433 ··· 16333 16258 16334 16259 spec->mixers[spec->num_mixers] = alc662_capture_mixer; 16335 16260 spec->num_mixers++; 16261 + 16262 + store_pin_configs(codec); 16336 16263 return 1; 16337 16264 } 16338 16265