ALSA: hda - Haswell converter power state D0 verify
authorWang Xingchao <xingchao.wang@linux.intel.com>
Tue, 18 Jun 2013 02:41:53 +0000 (10:41 +0800)
committerTakashi Iwai <tiwai@suse.de>
Tue, 18 Jun 2013 06:04:15 +0000 (08:04 +0200)
Haswell converters maybe in wrong power state before usage.
i.e. only converter 0 is in D0, converter 1/2 are in D3.
When pin choose converter 1/2, there's no audio output, this
cause dependency when playing differnt stream on pins.

AUD_PWRST  ConvertorA_Widget_Power_State_Current        D0
AUD_PWRST  ConvertorA_Widget_Power_State_Requsted       D0
AUD_PWRST  ConvertorB_Widget_Power_State_Current        D3
AUD_PWRST  ConvertorB_Widget_Power_State_Requested      D3
AUD_PWRST  ConvC_Widget_PwrSt_Curr                      D3
AUD_PWRST  ConvC_Widget_PwrSt_Req                       D3

This patch check converter's power state and set D0 if it's in D3 mode.

Signed-off-by: Wang Xingchao <xingchao.wang@linux.intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/pci/hda/patch_hdmi.c

index e12f7a030c58efae2c5a93829ec6bfce1fb17ac7..8983747f2a3747bbaa6d24fd73a184defe1fc12e 100644 (file)
@@ -1018,10 +1018,19 @@ static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res)
                hdmi_non_intrinsic_event(codec, res);
 }
 
-static void haswell_verify_pin_D0(struct hda_codec *codec, hda_nid_t nid)
+static void haswell_verify_pin_D0(struct hda_codec *codec,
+               hda_nid_t cvt_nid, hda_nid_t nid)
 {
        int pwr, lamp, ramp;
 
+       /* For Haswell, the converter 1/2 may keep in D3 state after bootup,
+        * thus pins could only choose converter 0 for use. Make sure the
+        * converters are in correct power state */
+       pwr = snd_hda_codec_read(codec, cvt_nid, 0, AC_VERB_GET_POWER_STATE, 0);
+       pwr = (pwr & AC_PWRST_ACTUAL) >> AC_PWRST_ACTUAL_SHIFT;
+       if (pwr != AC_PWRST_D0)
+               snd_hda_codec_write(codec, cvt_nid, 0, AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+
        pwr = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_POWER_STATE, 0);
        pwr = (pwr & AC_PWRST_ACTUAL) >> AC_PWRST_ACTUAL_SHIFT;
        if (pwr != AC_PWRST_D0) {
@@ -1068,7 +1077,7 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid,
        int new_pinctl = 0;
 
        if (codec->vendor_id == 0x80862807)
-               haswell_verify_pin_D0(codec, pin_nid);
+               haswell_verify_pin_D0(codec, cvt_nid, pin_nid);
 
        if (snd_hda_query_pin_caps(codec, pin_nid) & AC_PINCAP_HBR) {
                pinctl = snd_hda_codec_read(codec, pin_nid, 0,