diff options
| author | Dave Airlie <airlied@redhat.com> | 2012-01-03 04:34:43 -0500 |
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2012-01-03 04:34:43 -0500 |
| commit | 2318fcd65c1fb1e842f860c1e3fe4dba7e55cd11 (patch) | |
| tree | 8f2d73ee6f8be3f49ee07881a8579fa15f9e1881 /drivers/gpu | |
| parent | f9f23a77f07506a32d9dc1d925bf85c0e7507b66 (diff) | |
| parent | 097354eb14fa94d31a09c64d640643f58e4a5a9a (diff) | |
Merge branch 'drm-intel-next' of git://people.freedesktop.org/~keithp/linux into drm-core-next
* 'drm-intel-next' of git://people.freedesktop.org/~keithp/linux:
drm/i915: check ACTHD of all rings
drm/i915: DisplayPort hot remove notification to audio driver
drm/i915: HDMI hot remove notification to audio driver
drm/i915: dont trigger hotplug events on unchanged ELD
drm/i915: rename audio ELD registers
drm/i915: fix ELD writing for SandyBridge
Diffstat (limited to 'drivers/gpu')
| -rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 13 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 24 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 75 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_hdmi.c | 8 |
6 files changed, 89 insertions, 34 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 554bef7a3b9c..505af3f64a07 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
| @@ -337,6 +337,8 @@ typedef struct drm_i915_private { | |||
| 337 | struct timer_list hangcheck_timer; | 337 | struct timer_list hangcheck_timer; |
| 338 | int hangcheck_count; | 338 | int hangcheck_count; |
| 339 | uint32_t last_acthd; | 339 | uint32_t last_acthd; |
| 340 | uint32_t last_acthd_bsd; | ||
| 341 | uint32_t last_acthd_blt; | ||
| 340 | uint32_t last_instdone; | 342 | uint32_t last_instdone; |
| 341 | uint32_t last_instdone1; | 343 | uint32_t last_instdone1; |
| 342 | 344 | ||
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 3700df47ad93..58493114c942 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
| @@ -1669,7 +1669,7 @@ void i915_hangcheck_elapsed(unsigned long data) | |||
| 1669 | { | 1669 | { |
| 1670 | struct drm_device *dev = (struct drm_device *)data; | 1670 | struct drm_device *dev = (struct drm_device *)data; |
| 1671 | drm_i915_private_t *dev_priv = dev->dev_private; | 1671 | drm_i915_private_t *dev_priv = dev->dev_private; |
| 1672 | uint32_t acthd, instdone, instdone1; | 1672 | uint32_t acthd, instdone, instdone1, acthd_bsd, acthd_blt; |
| 1673 | bool err = false; | 1673 | bool err = false; |
| 1674 | 1674 | ||
| 1675 | if (!i915_enable_hangcheck) | 1675 | if (!i915_enable_hangcheck) |
| @@ -1686,16 +1686,21 @@ void i915_hangcheck_elapsed(unsigned long data) | |||
| 1686 | } | 1686 | } |
| 1687 | 1687 | ||
| 1688 | if (INTEL_INFO(dev)->gen < 4) { | 1688 | if (INTEL_INFO(dev)->gen < 4) { |
| 1689 | acthd = I915_READ(ACTHD); | ||
| 1690 | instdone = I915_READ(INSTDONE); | 1689 | instdone = I915_READ(INSTDONE); |
| 1691 | instdone1 = 0; | 1690 | instdone1 = 0; |
| 1692 | } else { | 1691 | } else { |
| 1693 | acthd = I915_READ(ACTHD_I965); | ||
| 1694 | instdone = I915_READ(INSTDONE_I965); | 1692 | instdone = I915_READ(INSTDONE_I965); |
| 1695 | instdone1 = I915_READ(INSTDONE1); | 1693 | instdone1 = I915_READ(INSTDONE1); |
| 1696 | } | 1694 | } |
| 1695 | acthd = intel_ring_get_active_head(&dev_priv->ring[RCS]); | ||
| 1696 | acthd_bsd = HAS_BSD(dev) ? | ||
| 1697 | intel_ring_get_active_head(&dev_priv->ring[VCS]) : 0; | ||
| 1698 | acthd_blt = HAS_BLT(dev) ? | ||
| 1699 | intel_ring_get_active_head(&dev_priv->ring[BCS]) : 0; | ||
| 1697 | 1700 | ||
| 1698 | if (dev_priv->last_acthd == acthd && | 1701 | if (dev_priv->last_acthd == acthd && |
| 1702 | dev_priv->last_acthd_bsd == acthd_bsd && | ||
| 1703 | dev_priv->last_acthd_blt == acthd_blt && | ||
| 1699 | dev_priv->last_instdone == instdone && | 1704 | dev_priv->last_instdone == instdone && |
| 1700 | dev_priv->last_instdone1 == instdone1) { | 1705 | dev_priv->last_instdone1 == instdone1) { |
| 1701 | if (dev_priv->hangcheck_count++ > 1) { | 1706 | if (dev_priv->hangcheck_count++ > 1) { |
| @@ -1727,6 +1732,8 @@ void i915_hangcheck_elapsed(unsigned long data) | |||
| 1727 | dev_priv->hangcheck_count = 0; | 1732 | dev_priv->hangcheck_count = 0; |
| 1728 | 1733 | ||
| 1729 | dev_priv->last_acthd = acthd; | 1734 | dev_priv->last_acthd = acthd; |
| 1735 | dev_priv->last_acthd_bsd = acthd_bsd; | ||
| 1736 | dev_priv->last_acthd_blt = acthd_blt; | ||
| 1730 | dev_priv->last_instdone = instdone; | 1737 | dev_priv->last_instdone = instdone; |
| 1731 | dev_priv->last_instdone1 = instdone1; | 1738 | dev_priv->last_instdone1 = instdone1; |
| 1732 | } | 1739 | } |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 853f2f0acaa2..194d9874002b 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
| @@ -3570,17 +3570,17 @@ | |||
| 3570 | #define G4X_ELD_ACK (1 << 4) | 3570 | #define G4X_ELD_ACK (1 << 4) |
| 3571 | #define G4X_HDMIW_HDMIEDID 0x6210C | 3571 | #define G4X_HDMIW_HDMIEDID 0x6210C |
| 3572 | 3572 | ||
| 3573 | #define GEN5_HDMIW_HDMIEDID_A 0xE2050 | 3573 | #define IBX_HDMIW_HDMIEDID_A 0xE2050 |
| 3574 | #define GEN5_AUD_CNTL_ST_A 0xE20B4 | 3574 | #define IBX_AUD_CNTL_ST_A 0xE20B4 |
| 3575 | #define GEN5_ELD_BUFFER_SIZE (0x1f << 10) | 3575 | #define IBX_ELD_BUFFER_SIZE (0x1f << 10) |
| 3576 | #define GEN5_ELD_ADDRESS (0x1f << 5) | 3576 | #define IBX_ELD_ADDRESS (0x1f << 5) |
| 3577 | #define GEN5_ELD_ACK (1 << 4) | 3577 | #define IBX_ELD_ACK (1 << 4) |
| 3578 | #define GEN5_AUD_CNTL_ST2 0xE20C0 | 3578 | #define IBX_AUD_CNTL_ST2 0xE20C0 |
| 3579 | #define GEN5_ELD_VALIDB (1 << 0) | 3579 | #define IBX_ELD_VALIDB (1 << 0) |
| 3580 | #define GEN5_CP_READYB (1 << 1) | 3580 | #define IBX_CP_READYB (1 << 1) |
| 3581 | 3581 | ||
| 3582 | #define GEN7_HDMIW_HDMIEDID_A 0xE5050 | 3582 | #define CPT_HDMIW_HDMIEDID_A 0xE5050 |
| 3583 | #define GEN7_AUD_CNTRL_ST_A 0xE50B4 | 3583 | #define CPT_AUD_CNTL_ST_A 0xE50B4 |
| 3584 | #define GEN7_AUD_CNTRL_ST2 0xE50C0 | 3584 | #define CPT_AUD_CNTRL_ST2 0xE50C0 |
| 3585 | 3585 | ||
| 3586 | #endif /* _I915_REG_H_ */ | 3586 | #endif /* _I915_REG_H_ */ |
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, | |||
| 5830 | return ret; | 5830 | return ret; |
| 5831 | } | 5831 | } |
| 5832 | 5832 | ||
| 5833 | static bool intel_eld_uptodate(struct drm_connector *connector, | ||
| 5834 | int reg_eldv, uint32_t bits_eldv, | ||
| 5835 | int reg_elda, uint32_t bits_elda, | ||
| 5836 | int reg_edid) | ||
| 5837 | { | ||
| 5838 | struct drm_i915_private *dev_priv = connector->dev->dev_private; | ||
| 5839 | uint8_t *eld = connector->eld; | ||
| 5840 | uint32_t i; | ||
| 5841 | |||
| 5842 | i = I915_READ(reg_eldv); | ||
| 5843 | i &= bits_eldv; | ||
| 5844 | |||
| 5845 | if (!eld[0]) | ||
| 5846 | return !i; | ||
| 5847 | |||
| 5848 | if (!i) | ||
| 5849 | return false; | ||
| 5850 | |||
| 5851 | i = I915_READ(reg_elda); | ||
| 5852 | i &= ~bits_elda; | ||
| 5853 | I915_WRITE(reg_elda, i); | ||
| 5854 | |||
| 5855 | for (i = 0; i < eld[2]; i++) | ||
| 5856 | if (I915_READ(reg_edid) != *((uint32_t *)eld + i)) | ||
| 5857 | return false; | ||
| 5858 | |||
| 5859 | return true; | ||
| 5860 | } | ||
| 5861 | |||
| 5833 | static void g4x_write_eld(struct drm_connector *connector, | 5862 | static void g4x_write_eld(struct drm_connector *connector, |
| 5834 | struct drm_crtc *crtc) | 5863 | struct drm_crtc *crtc) |
| 5835 | { | 5864 | { |
| @@ -5846,6 +5875,12 @@ static void g4x_write_eld(struct drm_connector *connector, | |||
| 5846 | else | 5875 | else |
| 5847 | eldv = G4X_ELDV_DEVCTG; | 5876 | eldv = G4X_ELDV_DEVCTG; |
| 5848 | 5877 | ||
| 5878 | if (intel_eld_uptodate(connector, | ||
| 5879 | G4X_AUD_CNTL_ST, eldv, | ||
| 5880 | G4X_AUD_CNTL_ST, G4X_ELD_ADDR, | ||
| 5881 | G4X_HDMIW_HDMIEDID)) | ||
| 5882 | return; | ||
| 5883 | |||
| 5849 | i = I915_READ(G4X_AUD_CNTL_ST); | 5884 | i = I915_READ(G4X_AUD_CNTL_ST); |
| 5850 | i &= ~(eldv | G4X_ELD_ADDR); | 5885 | i &= ~(eldv | G4X_ELD_ADDR); |
| 5851 | len = (i >> 9) & 0x1f; /* ELD buffer size */ | 5886 | len = (i >> 9) & 0x1f; /* ELD buffer size */ |
| @@ -5876,14 +5911,14 @@ static void ironlake_write_eld(struct drm_connector *connector, | |||
| 5876 | int aud_cntl_st; | 5911 | int aud_cntl_st; |
| 5877 | int aud_cntrl_st2; | 5912 | int aud_cntrl_st2; |
| 5878 | 5913 | ||
| 5879 | if (IS_IVYBRIDGE(connector->dev)) { | 5914 | if (HAS_PCH_IBX(connector->dev)) { |
| 5880 | hdmiw_hdmiedid = GEN7_HDMIW_HDMIEDID_A; | 5915 | hdmiw_hdmiedid = IBX_HDMIW_HDMIEDID_A; |
| 5881 | aud_cntl_st = GEN7_AUD_CNTRL_ST_A; | 5916 | aud_cntl_st = IBX_AUD_CNTL_ST_A; |
| 5882 | aud_cntrl_st2 = GEN7_AUD_CNTRL_ST2; | 5917 | aud_cntrl_st2 = IBX_AUD_CNTL_ST2; |
| 5883 | } else { | 5918 | } else { |
| 5884 | hdmiw_hdmiedid = GEN5_HDMIW_HDMIEDID_A; | 5919 | hdmiw_hdmiedid = CPT_HDMIW_HDMIEDID_A; |
| 5885 | aud_cntl_st = GEN5_AUD_CNTL_ST_A; | 5920 | aud_cntl_st = CPT_AUD_CNTL_ST_A; |
| 5886 | aud_cntrl_st2 = GEN5_AUD_CNTL_ST2; | 5921 | aud_cntrl_st2 = CPT_AUD_CNTRL_ST2; |
| 5887 | } | 5922 | } |
| 5888 | 5923 | ||
| 5889 | i = to_intel_crtc(crtc)->pipe; | 5924 | i = to_intel_crtc(crtc)->pipe; |
| @@ -5897,14 +5932,25 @@ static void ironlake_write_eld(struct drm_connector *connector, | |||
| 5897 | if (!i) { | 5932 | if (!i) { |
| 5898 | DRM_DEBUG_DRIVER("Audio directed to unknown port\n"); | 5933 | DRM_DEBUG_DRIVER("Audio directed to unknown port\n"); |
| 5899 | /* operate blindly on all ports */ | 5934 | /* operate blindly on all ports */ |
| 5900 | eldv = GEN5_ELD_VALIDB; | 5935 | eldv = IBX_ELD_VALIDB; |
| 5901 | eldv |= GEN5_ELD_VALIDB << 4; | 5936 | eldv |= IBX_ELD_VALIDB << 4; |
| 5902 | eldv |= GEN5_ELD_VALIDB << 8; | 5937 | eldv |= IBX_ELD_VALIDB << 8; |
| 5903 | } else { | 5938 | } else { |
| 5904 | DRM_DEBUG_DRIVER("ELD on port %c\n", 'A' + i); | 5939 | DRM_DEBUG_DRIVER("ELD on port %c\n", 'A' + i); |
| 5905 | eldv = GEN5_ELD_VALIDB << ((i - 1) * 4); | 5940 | eldv = IBX_ELD_VALIDB << ((i - 1) * 4); |
| 5941 | } | ||
| 5942 | |||
| 5943 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) { | ||
| 5944 | DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n"); | ||
| 5945 | eld[5] |= (1 << 2); /* Conn_Type, 0x1 = DisplayPort */ | ||
| 5906 | } | 5946 | } |
| 5907 | 5947 | ||
| 5948 | if (intel_eld_uptodate(connector, | ||
| 5949 | aud_cntrl_st2, eldv, | ||
| 5950 | aud_cntl_st, IBX_ELD_ADDRESS, | ||
| 5951 | hdmiw_hdmiedid)) | ||
| 5952 | return; | ||
| 5953 | |||
| 5908 | i = I915_READ(aud_cntrl_st2); | 5954 | i = I915_READ(aud_cntrl_st2); |
| 5909 | i &= ~eldv; | 5955 | i &= ~eldv; |
| 5910 | I915_WRITE(aud_cntrl_st2, i); | 5956 | I915_WRITE(aud_cntrl_st2, i); |
| @@ -5912,13 +5958,8 @@ static void ironlake_write_eld(struct drm_connector *connector, | |||
| 5912 | if (!eld[0]) | 5958 | if (!eld[0]) |
| 5913 | return; | 5959 | return; |
| 5914 | 5960 | ||
| 5915 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) { | ||
| 5916 | DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n"); | ||
| 5917 | eld[5] |= (1 << 2); /* Conn_Type, 0x1 = DisplayPort */ | ||
| 5918 | } | ||
| 5919 | |||
| 5920 | i = I915_READ(aud_cntl_st); | 5961 | i = I915_READ(aud_cntl_st); |
| 5921 | i &= ~GEN5_ELD_ADDRESS; | 5962 | i &= ~IBX_ELD_ADDRESS; |
| 5922 | I915_WRITE(aud_cntl_st, i); | 5963 | I915_WRITE(aud_cntl_st, i); |
| 5923 | 5964 | ||
| 5924 | len = min_t(uint8_t, eld[2], 21); /* 84 bytes of hw ELD buffer */ | 5965 | len = min_t(uint8_t, eld[2], 21); /* 84 bytes of hw ELD buffer */ |
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 92b041b66e49..db3b461ad412 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
| @@ -1926,6 +1926,7 @@ intel_dp_link_down(struct intel_dp *intel_dp) | |||
| 1926 | intel_wait_for_vblank(dev, to_intel_crtc(crtc)->pipe); | 1926 | intel_wait_for_vblank(dev, to_intel_crtc(crtc)->pipe); |
| 1927 | } | 1927 | } |
| 1928 | 1928 | ||
| 1929 | DP &= ~DP_AUDIO_OUTPUT_ENABLE; | ||
| 1929 | I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN); | 1930 | I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN); |
| 1930 | POSTING_READ(intel_dp->output_reg); | 1931 | POSTING_READ(intel_dp->output_reg); |
| 1931 | msleep(intel_dp->panel_power_down_delay); | 1932 | msleep(intel_dp->panel_power_down_delay); |
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index d4f5a0b2120d..64541f7ef900 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c | |||
| @@ -269,6 +269,10 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode) | |||
| 269 | struct drm_i915_private *dev_priv = dev->dev_private; | 269 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 270 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); | 270 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
| 271 | u32 temp; | 271 | u32 temp; |
| 272 | u32 enable_bits = SDVO_ENABLE; | ||
| 273 | |||
| 274 | if (intel_hdmi->has_audio) | ||
| 275 | enable_bits |= SDVO_AUDIO_ENABLE; | ||
| 272 | 276 | ||
| 273 | temp = I915_READ(intel_hdmi->sdvox_reg); | 277 | temp = I915_READ(intel_hdmi->sdvox_reg); |
| 274 | 278 | ||
| @@ -281,9 +285,9 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode) | |||
| 281 | } | 285 | } |
| 282 | 286 | ||
| 283 | if (mode != DRM_MODE_DPMS_ON) { | 287 | if (mode != DRM_MODE_DPMS_ON) { |
| 284 | temp &= ~SDVO_ENABLE; | 288 | temp &= ~enable_bits; |
| 285 | } else { | 289 | } else { |
| 286 | temp |= SDVO_ENABLE; | 290 | temp |= enable_bits; |
| 287 | } | 291 | } |
| 288 | 292 | ||
| 289 | I915_WRITE(intel_hdmi->sdvox_reg, temp); | 293 | I915_WRITE(intel_hdmi->sdvox_reg, temp); |
