diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 75 |
1 files changed, 58 insertions, 17 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 5a3e7853003f..55a5b4c4edf1 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5830,6 +5830,35 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, return ret; } +static bool intel_eld_uptodate(struct drm_connector *connector, + int reg_eldv, uint32_t bits_eldv, + int reg_elda, uint32_t bits_elda, + int reg_edid) +{ + struct drm_i915_private *dev_priv = connector->dev->dev_private; + uint8_t *eld = connector->eld; + uint32_t i; + + i = I915_READ(reg_eldv); + i &= bits_eldv; + + if (!eld[0]) + return !i; + + if (!i) + return false; + + i = I915_READ(reg_elda); + i &= ~bits_elda; + I915_WRITE(reg_elda, i); + + for (i = 0; i < eld[2]; i++) + if (I915_READ(reg_edid) != *((uint32_t *)eld + i)) + return false; + + return true; +} + static void g4x_write_eld(struct drm_connector *connector, struct drm_crtc *crtc) { @@ -5846,6 +5875,12 @@ static void g4x_write_eld(struct drm_connector *connector, else eldv = G4X_ELDV_DEVCTG; + if (intel_eld_uptodate(connector, + G4X_AUD_CNTL_ST, eldv, + G4X_AUD_CNTL_ST, G4X_ELD_ADDR, + G4X_HDMIW_HDMIEDID)) + return; + i = I915_READ(G4X_AUD_CNTL_ST); i &= ~(eldv | G4X_ELD_ADDR); len = (i >> 9) & 0x1f; /* ELD buffer size */ @@ -5876,14 +5911,14 @@ static void ironlake_write_eld(struct drm_connector *connector, int aud_cntl_st; int aud_cntrl_st2; - if (IS_IVYBRIDGE(connector->dev)) { - hdmiw_hdmiedid = GEN7_HDMIW_HDMIEDID_A; - aud_cntl_st = GEN7_AUD_CNTRL_ST_A; - aud_cntrl_st2 = GEN7_AUD_CNTRL_ST2; + if (HAS_PCH_IBX(connector->dev)) { + hdmiw_hdmiedid = IBX_HDMIW_HDMIEDID_A; + aud_cntl_st = IBX_AUD_CNTL_ST_A; + aud_cntrl_st2 = IBX_AUD_CNTL_ST2; } else { - hdmiw_hdmiedid = GEN5_HDMIW_HDMIEDID_A; - aud_cntl_st = GEN5_AUD_CNTL_ST_A; - aud_cntrl_st2 = GEN5_AUD_CNTL_ST2; + hdmiw_hdmiedid = CPT_HDMIW_HDMIEDID_A; + aud_cntl_st = CPT_AUD_CNTL_ST_A; + aud_cntrl_st2 = CPT_AUD_CNTRL_ST2; } i = to_intel_crtc(crtc)->pipe; @@ -5897,14 +5932,25 @@ static void ironlake_write_eld(struct drm_connector *connector, if (!i) { DRM_DEBUG_DRIVER("Audio directed to unknown port\n"); /* operate blindly on all ports */ - eldv = GEN5_ELD_VALIDB; - eldv |= GEN5_ELD_VALIDB << 4; - eldv |= GEN5_ELD_VALIDB << 8; + eldv = IBX_ELD_VALIDB; + eldv |= IBX_ELD_VALIDB << 4; + eldv |= IBX_ELD_VALIDB << 8; } else { DRM_DEBUG_DRIVER("ELD on port %c\n", 'A' + i); - eldv = GEN5_ELD_VALIDB << ((i - 1) * 4); + eldv = IBX_ELD_VALIDB << ((i - 1) * 4); + } + + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) { + DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n"); + eld[5] |= (1 << 2); /* Conn_Type, 0x1 = DisplayPort */ } + if (intel_eld_uptodate(connector, + aud_cntrl_st2, eldv, + aud_cntl_st, IBX_ELD_ADDRESS, + hdmiw_hdmiedid)) + return; + i = I915_READ(aud_cntrl_st2); i &= ~eldv; I915_WRITE(aud_cntrl_st2, i); @@ -5912,13 +5958,8 @@ static void ironlake_write_eld(struct drm_connector *connector, if (!eld[0]) return; - if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) { - DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n"); - eld[5] |= (1 << 2); /* Conn_Type, 0x1 = DisplayPort */ - } - i = I915_READ(aud_cntl_st); - i &= ~GEN5_ELD_ADDRESS; + i &= ~IBX_ELD_ADDRESS; I915_WRITE(aud_cntl_st, i); len = min_t(uint8_t, eld[2], 21); /* 84 bytes of hw ELD buffer */ |