Commit 2318fcd6 authored by Dave Airlie's avatar Dave Airlie

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
parents f9f23a77 097354eb
...@@ -337,6 +337,8 @@ typedef struct drm_i915_private { ...@@ -337,6 +337,8 @@ typedef struct drm_i915_private {
struct timer_list hangcheck_timer; struct timer_list hangcheck_timer;
int hangcheck_count; int hangcheck_count;
uint32_t last_acthd; uint32_t last_acthd;
uint32_t last_acthd_bsd;
uint32_t last_acthd_blt;
uint32_t last_instdone; uint32_t last_instdone;
uint32_t last_instdone1; uint32_t last_instdone1;
......
...@@ -1669,7 +1669,7 @@ void i915_hangcheck_elapsed(unsigned long data) ...@@ -1669,7 +1669,7 @@ void i915_hangcheck_elapsed(unsigned long data)
{ {
struct drm_device *dev = (struct drm_device *)data; struct drm_device *dev = (struct drm_device *)data;
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
uint32_t acthd, instdone, instdone1; uint32_t acthd, instdone, instdone1, acthd_bsd, acthd_blt;
bool err = false; bool err = false;
if (!i915_enable_hangcheck) if (!i915_enable_hangcheck)
...@@ -1686,16 +1686,21 @@ void i915_hangcheck_elapsed(unsigned long data) ...@@ -1686,16 +1686,21 @@ void i915_hangcheck_elapsed(unsigned long data)
} }
if (INTEL_INFO(dev)->gen < 4) { if (INTEL_INFO(dev)->gen < 4) {
acthd = I915_READ(ACTHD);
instdone = I915_READ(INSTDONE); instdone = I915_READ(INSTDONE);
instdone1 = 0; instdone1 = 0;
} else { } else {
acthd = I915_READ(ACTHD_I965);
instdone = I915_READ(INSTDONE_I965); instdone = I915_READ(INSTDONE_I965);
instdone1 = I915_READ(INSTDONE1); instdone1 = I915_READ(INSTDONE1);
} }
acthd = intel_ring_get_active_head(&dev_priv->ring[RCS]);
acthd_bsd = HAS_BSD(dev) ?
intel_ring_get_active_head(&dev_priv->ring[VCS]) : 0;
acthd_blt = HAS_BLT(dev) ?
intel_ring_get_active_head(&dev_priv->ring[BCS]) : 0;
if (dev_priv->last_acthd == acthd && if (dev_priv->last_acthd == acthd &&
dev_priv->last_acthd_bsd == acthd_bsd &&
dev_priv->last_acthd_blt == acthd_blt &&
dev_priv->last_instdone == instdone && dev_priv->last_instdone == instdone &&
dev_priv->last_instdone1 == instdone1) { dev_priv->last_instdone1 == instdone1) {
if (dev_priv->hangcheck_count++ > 1) { if (dev_priv->hangcheck_count++ > 1) {
...@@ -1727,6 +1732,8 @@ void i915_hangcheck_elapsed(unsigned long data) ...@@ -1727,6 +1732,8 @@ void i915_hangcheck_elapsed(unsigned long data)
dev_priv->hangcheck_count = 0; dev_priv->hangcheck_count = 0;
dev_priv->last_acthd = acthd; dev_priv->last_acthd = acthd;
dev_priv->last_acthd_bsd = acthd_bsd;
dev_priv->last_acthd_blt = acthd_blt;
dev_priv->last_instdone = instdone; dev_priv->last_instdone = instdone;
dev_priv->last_instdone1 = instdone1; dev_priv->last_instdone1 = instdone1;
} }
......
...@@ -3570,17 +3570,17 @@ ...@@ -3570,17 +3570,17 @@
#define G4X_ELD_ACK (1 << 4) #define G4X_ELD_ACK (1 << 4)
#define G4X_HDMIW_HDMIEDID 0x6210C #define G4X_HDMIW_HDMIEDID 0x6210C
#define GEN5_HDMIW_HDMIEDID_A 0xE2050 #define IBX_HDMIW_HDMIEDID_A 0xE2050
#define GEN5_AUD_CNTL_ST_A 0xE20B4 #define IBX_AUD_CNTL_ST_A 0xE20B4
#define GEN5_ELD_BUFFER_SIZE (0x1f << 10) #define IBX_ELD_BUFFER_SIZE (0x1f << 10)
#define GEN5_ELD_ADDRESS (0x1f << 5) #define IBX_ELD_ADDRESS (0x1f << 5)
#define GEN5_ELD_ACK (1 << 4) #define IBX_ELD_ACK (1 << 4)
#define GEN5_AUD_CNTL_ST2 0xE20C0 #define IBX_AUD_CNTL_ST2 0xE20C0
#define GEN5_ELD_VALIDB (1 << 0) #define IBX_ELD_VALIDB (1 << 0)
#define GEN5_CP_READYB (1 << 1) #define IBX_CP_READYB (1 << 1)
#define GEN7_HDMIW_HDMIEDID_A 0xE5050 #define CPT_HDMIW_HDMIEDID_A 0xE5050
#define GEN7_AUD_CNTRL_ST_A 0xE50B4 #define CPT_AUD_CNTL_ST_A 0xE50B4
#define GEN7_AUD_CNTRL_ST2 0xE50C0 #define CPT_AUD_CNTRL_ST2 0xE50C0
#endif /* _I915_REG_H_ */ #endif /* _I915_REG_H_ */
...@@ -5830,6 +5830,35 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, ...@@ -5830,6 +5830,35 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
return ret; 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, static void g4x_write_eld(struct drm_connector *connector,
struct drm_crtc *crtc) struct drm_crtc *crtc)
{ {
...@@ -5846,6 +5875,12 @@ static void g4x_write_eld(struct drm_connector *connector, ...@@ -5846,6 +5875,12 @@ static void g4x_write_eld(struct drm_connector *connector,
else else
eldv = G4X_ELDV_DEVCTG; 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 = I915_READ(G4X_AUD_CNTL_ST);
i &= ~(eldv | G4X_ELD_ADDR); i &= ~(eldv | G4X_ELD_ADDR);
len = (i >> 9) & 0x1f; /* ELD buffer size */ len = (i >> 9) & 0x1f; /* ELD buffer size */
...@@ -5876,14 +5911,14 @@ static void ironlake_write_eld(struct drm_connector *connector, ...@@ -5876,14 +5911,14 @@ static void ironlake_write_eld(struct drm_connector *connector,
int aud_cntl_st; int aud_cntl_st;
int aud_cntrl_st2; int aud_cntrl_st2;
if (IS_IVYBRIDGE(connector->dev)) { if (HAS_PCH_IBX(connector->dev)) {
hdmiw_hdmiedid = GEN7_HDMIW_HDMIEDID_A; hdmiw_hdmiedid = IBX_HDMIW_HDMIEDID_A;
aud_cntl_st = GEN7_AUD_CNTRL_ST_A; aud_cntl_st = IBX_AUD_CNTL_ST_A;
aud_cntrl_st2 = GEN7_AUD_CNTRL_ST2; aud_cntrl_st2 = IBX_AUD_CNTL_ST2;
} else { } else {
hdmiw_hdmiedid = GEN5_HDMIW_HDMIEDID_A; hdmiw_hdmiedid = CPT_HDMIW_HDMIEDID_A;
aud_cntl_st = GEN5_AUD_CNTL_ST_A; aud_cntl_st = CPT_AUD_CNTL_ST_A;
aud_cntrl_st2 = GEN5_AUD_CNTL_ST2; aud_cntrl_st2 = CPT_AUD_CNTRL_ST2;
} }
i = to_intel_crtc(crtc)->pipe; i = to_intel_crtc(crtc)->pipe;
...@@ -5897,14 +5932,25 @@ static void ironlake_write_eld(struct drm_connector *connector, ...@@ -5897,14 +5932,25 @@ static void ironlake_write_eld(struct drm_connector *connector,
if (!i) { if (!i) {
DRM_DEBUG_DRIVER("Audio directed to unknown port\n"); DRM_DEBUG_DRIVER("Audio directed to unknown port\n");
/* operate blindly on all ports */ /* operate blindly on all ports */
eldv = GEN5_ELD_VALIDB; eldv = IBX_ELD_VALIDB;
eldv |= GEN5_ELD_VALIDB << 4; eldv |= IBX_ELD_VALIDB << 4;
eldv |= GEN5_ELD_VALIDB << 8; eldv |= IBX_ELD_VALIDB << 8;
} else { } else {
DRM_DEBUG_DRIVER("ELD on port %c\n", 'A' + i); 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 = I915_READ(aud_cntrl_st2);
i &= ~eldv; i &= ~eldv;
I915_WRITE(aud_cntrl_st2, i); I915_WRITE(aud_cntrl_st2, i);
...@@ -5912,13 +5958,8 @@ static void ironlake_write_eld(struct drm_connector *connector, ...@@ -5912,13 +5958,8 @@ static void ironlake_write_eld(struct drm_connector *connector,
if (!eld[0]) if (!eld[0])
return; 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 = I915_READ(aud_cntl_st);
i &= ~GEN5_ELD_ADDRESS; i &= ~IBX_ELD_ADDRESS;
I915_WRITE(aud_cntl_st, i); I915_WRITE(aud_cntl_st, i);
len = min_t(uint8_t, eld[2], 21); /* 84 bytes of hw ELD buffer */ len = min_t(uint8_t, eld[2], 21); /* 84 bytes of hw ELD buffer */
......
...@@ -1926,6 +1926,7 @@ intel_dp_link_down(struct intel_dp *intel_dp) ...@@ -1926,6 +1926,7 @@ intel_dp_link_down(struct intel_dp *intel_dp)
intel_wait_for_vblank(dev, to_intel_crtc(crtc)->pipe); intel_wait_for_vblank(dev, to_intel_crtc(crtc)->pipe);
} }
DP &= ~DP_AUDIO_OUTPUT_ENABLE;
I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN); I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN);
POSTING_READ(intel_dp->output_reg); POSTING_READ(intel_dp->output_reg);
msleep(intel_dp->panel_power_down_delay); msleep(intel_dp->panel_power_down_delay);
......
...@@ -269,6 +269,10 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode) ...@@ -269,6 +269,10 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
u32 temp; u32 temp;
u32 enable_bits = SDVO_ENABLE;
if (intel_hdmi->has_audio)
enable_bits |= SDVO_AUDIO_ENABLE;
temp = I915_READ(intel_hdmi->sdvox_reg); temp = I915_READ(intel_hdmi->sdvox_reg);
...@@ -281,9 +285,9 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode) ...@@ -281,9 +285,9 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)
} }
if (mode != DRM_MODE_DPMS_ON) { if (mode != DRM_MODE_DPMS_ON) {
temp &= ~SDVO_ENABLE; temp &= ~enable_bits;
} else { } else {
temp |= SDVO_ENABLE; temp |= enable_bits;
} }
I915_WRITE(intel_hdmi->sdvox_reg, temp); I915_WRITE(intel_hdmi->sdvox_reg, temp);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment