aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2013-05-08 02:09:34 -0400
committerTakashi Iwai <tiwai@suse.de>2013-05-08 02:24:57 -0400
commit17df3f55652f7ea8fb1197b5c32e227b3da9f215 (patch)
treeaab1cb7a8737524cfccf8d581176ef841b367f89 /sound
parent2195b063f6609e4c6268f291683902f25eaf9aa6 (diff)
ALSA: hda - Apply pin-enablement workaround to all Haswell HDMI codecs
This is a revised patch based on Mengdong Lin's fix patch, which is a supplement to a previous patch [1611a9c9: ALSA: hda - Add fixup for Haswell to enable all pin and convertor widgets]. Some Haswell BIOS will disable the 2nd and 3rd pin/covertor widgets when the HD-A controller changes state from D3 to D0. So when the controller resumes after a system or runtime suspend, these widgets are disabled and programming these widgets to D0 will cause H/W error and codec will not respond. In addition, we found out that some BIOS disables the pins at S3 although it shows up at boot. This confuses the driver utterly, and the hardware falls into the fatal communication error like the above. So in this patch, we apply intel_haswell_enable_all_pins() not only as a fixup to a certain device (with 8086:2010) but to all Haswell machines. The codec driver basically assumes that all pins are exposed, so it's anyway better to see them from the beginning. Even if all pins and converters are shown by this call, there should be no regression in practice: the pin default configurations are still kept, thus the disabled pins are handled as disabled by the driver properly. Signed-off-by: Mengdong Lin <mengdong.lin@intel.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/hda/patch_hdmi.c54
1 files changed, 22 insertions, 32 deletions
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 32930e668854..e12f7a030c58 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -1832,12 +1832,10 @@ static void intel_haswell_fixup_connect_list(struct hda_codec *codec,
1832#define INTEL_EN_ALL_PIN_CVTS 0x01 /* enable 2nd & 3rd pins and convertors */ 1832#define INTEL_EN_ALL_PIN_CVTS 0x01 /* enable 2nd & 3rd pins and convertors */
1833 1833
1834static void intel_haswell_enable_all_pins(struct hda_codec *codec, 1834static void intel_haswell_enable_all_pins(struct hda_codec *codec,
1835 const struct hda_fixup *fix, int action) 1835 bool update_tree)
1836{ 1836{
1837 unsigned int vendor_param; 1837 unsigned int vendor_param;
1838 1838
1839 if (action != HDA_FIXUP_ACT_PRE_PROBE)
1840 return;
1841 vendor_param = snd_hda_codec_read(codec, INTEL_VENDOR_NID, 0, 1839 vendor_param = snd_hda_codec_read(codec, INTEL_VENDOR_NID, 0,
1842 INTEL_GET_VENDOR_VERB, 0); 1840 INTEL_GET_VENDOR_VERB, 0);
1843 if (vendor_param == -1 || vendor_param & INTEL_EN_ALL_PIN_CVTS) 1841 if (vendor_param == -1 || vendor_param & INTEL_EN_ALL_PIN_CVTS)
@@ -1849,8 +1847,8 @@ static void intel_haswell_enable_all_pins(struct hda_codec *codec,
1849 if (vendor_param == -1) 1847 if (vendor_param == -1)
1850 return; 1848 return;
1851 1849
1852 snd_hda_codec_update_widgets(codec); 1850 if (update_tree)
1853 return; 1851 snd_hda_codec_update_widgets(codec);
1854} 1852}
1855 1853
1856static void intel_haswell_fixup_enable_dp12(struct hda_codec *codec) 1854static void intel_haswell_fixup_enable_dp12(struct hda_codec *codec)
@@ -1868,30 +1866,20 @@ static void intel_haswell_fixup_enable_dp12(struct hda_codec *codec)
1868 INTEL_SET_VENDOR_VERB, vendor_param); 1866 INTEL_SET_VENDOR_VERB, vendor_param);
1869} 1867}
1870 1868
1869/* Haswell needs to re-issue the vendor-specific verbs before turning to D0.
1870 * Otherwise you may get severe h/w communication errors.
1871 */
1872static void haswell_set_power_state(struct hda_codec *codec, hda_nid_t fg,
1873 unsigned int power_state)
1874{
1875 if (power_state == AC_PWRST_D0) {
1876 intel_haswell_enable_all_pins(codec, false);
1877 intel_haswell_fixup_enable_dp12(codec);
1878 }
1871 1879
1872 1880 snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, power_state);
1873/* available models for fixup */ 1881 snd_hda_codec_set_power_to_all(codec, fg, power_state);
1874enum { 1882}
1875 INTEL_HASWELL,
1876};
1877
1878static const struct hda_model_fixup hdmi_models[] = {
1879 {.id = INTEL_HASWELL, .name = "Haswell"},
1880 {}
1881};
1882
1883static const struct snd_pci_quirk hdmi_fixup_tbl[] = {
1884 SND_PCI_QUIRK(0x8086, 0x2010, "Haswell", INTEL_HASWELL),
1885 {} /* terminator */
1886};
1887
1888static const struct hda_fixup hdmi_fixups[] = {
1889 [INTEL_HASWELL] = {
1890 .type = HDA_FIXUP_FUNC,
1891 .v.func = intel_haswell_enable_all_pins,
1892 },
1893};
1894
1895 1883
1896static int patch_generic_hdmi(struct hda_codec *codec) 1884static int patch_generic_hdmi(struct hda_codec *codec)
1897{ 1885{
@@ -1904,11 +1892,10 @@ static int patch_generic_hdmi(struct hda_codec *codec)
1904 codec->spec = spec; 1892 codec->spec = spec;
1905 hdmi_array_init(spec, 4); 1893 hdmi_array_init(spec, 4);
1906 1894
1907 snd_hda_pick_fixup(codec, hdmi_models, hdmi_fixup_tbl, hdmi_fixups); 1895 if (codec->vendor_id == 0x80862807) {
1908 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); 1896 intel_haswell_enable_all_pins(codec, true);
1909
1910 if (codec->vendor_id == 0x80862807)
1911 intel_haswell_fixup_enable_dp12(codec); 1897 intel_haswell_fixup_enable_dp12(codec);
1898 }
1912 1899
1913 if (hdmi_parse_codec(codec) < 0) { 1900 if (hdmi_parse_codec(codec) < 0) {
1914 codec->spec = NULL; 1901 codec->spec = NULL;
@@ -1916,6 +1903,9 @@ static int patch_generic_hdmi(struct hda_codec *codec)
1916 return -EINVAL; 1903 return -EINVAL;
1917 } 1904 }
1918 codec->patch_ops = generic_hdmi_patch_ops; 1905 codec->patch_ops = generic_hdmi_patch_ops;
1906 if (codec->vendor_id == 0x80862807)
1907 codec->patch_ops.set_power_state = haswell_set_power_state;
1908
1919 generic_hdmi_init_per_pins(codec); 1909 generic_hdmi_init_per_pins(codec);
1920 1910
1921 init_channel_allocations(); 1911 init_channel_allocations();