From patchwork Sun Aug 4 09:59:29 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tim Gardner X-Patchwork-Id: 264508 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) by ozlabs.org (Postfix) with ESMTP id 7D38C2C008C for ; Sun, 4 Aug 2013 20:00:13 +1000 (EST) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.76) (envelope-from ) id 1V5v6K-0005Ub-84; Sun, 04 Aug 2013 09:59:48 +0000 Received: from mail.tpi.com ([74.45.170.26]) by huckleberry.canonical.com with esmtp (Exim 4.76) (envelope-from ) id 1V5v6F-0005U9-0R for kernel-team@lists.ubuntu.com; Sun, 04 Aug 2013 09:59:43 +0000 Received: from salmon.rtg.net (mail.tpi.com [10.0.0.205]) by mail.tpi.com (Postfix) with ESMTP id 571BA3393A2; Sun, 4 Aug 2013 02:59:42 -0700 (PDT) Received: by salmon.rtg.net (Postfix, from userid 1000) id 157E822D00; Sun, 4 Aug 2013 03:59:42 -0600 (MDT) From: Tim Gardner To: kernel-team@lists.ubuntu.com Subject: [PATCH 3/3 Raring SRU] ALSA: hda - Apply pin-enablement workaround to all Haswell HDMI codecs Date: Sun, 4 Aug 2013 03:59:29 -0600 Message-Id: <1375610369-16225-3-git-send-email-tim.gardner@canonical.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1375610369-16225-1-git-send-email-tim.gardner@canonical.com> References: <1375610369-16225-1-git-send-email-tim.gardner@canonical.com> Cc: Takashi Iwai , Mengdong Lin X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.14 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: kernel-team-bounces@lists.ubuntu.com From: Takashi Iwai BugLink: http://bugs.launchpad.net/bugs/1183125 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 Signed-off-by: Takashi Iwai (cherry picked from commit 17df3f55652f7ea8fb1197b5c32e227b3da9f215) Signed-off-by: Tim Gardner --- sound/pci/hda/patch_hdmi.c | 54 ++++++++++++++++++-------------------------- 1 file changed, 22 insertions(+), 32 deletions(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index c635fa5..201d5a3 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1764,12 +1764,10 @@ static void intel_haswell_fixup_connect_list(struct hda_codec *codec, #define INTEL_EN_ALL_PIN_CVTS 0x01 /* enable 2nd & 3rd pins and convertors */ static void intel_haswell_enable_all_pins(struct hda_codec *codec, - const struct hda_fixup *fix, int action) + bool update_tree) { unsigned int vendor_param; - if (action != HDA_FIXUP_ACT_PRE_PROBE) - return; vendor_param = snd_hda_codec_read(codec, INTEL_VENDOR_NID, 0, INTEL_GET_VENDOR_VERB, 0); if (vendor_param == -1 || vendor_param & INTEL_EN_ALL_PIN_CVTS) @@ -1781,8 +1779,8 @@ static void intel_haswell_enable_all_pins(struct hda_codec *codec, if (vendor_param == -1) return; - snd_hda_codec_update_widgets(codec); - return; + if (update_tree) + snd_hda_codec_update_widgets(codec); } static void intel_haswell_fixup_enable_dp12(struct hda_codec *codec) @@ -1800,30 +1798,20 @@ static void intel_haswell_fixup_enable_dp12(struct hda_codec *codec) INTEL_SET_VENDOR_VERB, vendor_param); } +/* Haswell needs to re-issue the vendor-specific verbs before turning to D0. + * Otherwise you may get severe h/w communication errors. + */ +static void haswell_set_power_state(struct hda_codec *codec, hda_nid_t fg, + unsigned int power_state) +{ + if (power_state == AC_PWRST_D0) { + intel_haswell_enable_all_pins(codec, false); + intel_haswell_fixup_enable_dp12(codec); + } - -/* available models for fixup */ -enum { - INTEL_HASWELL, -}; - -static const struct hda_model_fixup hdmi_models[] = { - {.id = INTEL_HASWELL, .name = "Haswell"}, - {} -}; - -static const struct snd_pci_quirk hdmi_fixup_tbl[] = { - SND_PCI_QUIRK(0x8086, 0x2010, "Haswell", INTEL_HASWELL), - {} /* terminator */ -}; - -static const struct hda_fixup hdmi_fixups[] = { - [INTEL_HASWELL] = { - .type = HDA_FIXUP_FUNC, - .v.func = intel_haswell_enable_all_pins, - }, -}; - + snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, power_state); + snd_hda_codec_set_power_to_all(codec, fg, power_state); +} static int patch_generic_hdmi(struct hda_codec *codec) { @@ -1835,11 +1823,10 @@ static int patch_generic_hdmi(struct hda_codec *codec) codec->spec = spec; - snd_hda_pick_fixup(codec, hdmi_models, hdmi_fixup_tbl, hdmi_fixups); - snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); - - if (codec->vendor_id == 0x80862807) + if (codec->vendor_id == 0x80862807) { + intel_haswell_enable_all_pins(codec, true); intel_haswell_fixup_enable_dp12(codec); + } if (hdmi_parse_codec(codec) < 0) { codec->spec = NULL; @@ -1847,6 +1834,9 @@ static int patch_generic_hdmi(struct hda_codec *codec) return -EINVAL; } codec->patch_ops = generic_hdmi_patch_ops; + if (codec->vendor_id == 0x80862807) + codec->patch_ops.set_power_state = haswell_set_power_state; + generic_hdmi_init_per_pins(codec); init_channel_allocations();