<html><head>
<meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type">
</head><body bgcolor="#FFFFFF" text="#000000">This looks like it's good
to go. <br>
<br>
As an aside, I don't *think* any of the compliance testing stuff I'm
working on cares whether it's short of long pulse (1.1a compliance), but
it will be interesting to see if/when/where it might have an effect.<br>
<br>
Reviewed-by: Todd Previte <a class="moz-txt-link-rfc2396E" href="mailto:tprevite@gmail.com"><tprevite@gmail.com></a><br>
<br>
<blockquote style="border: 0px none;"
cite="mid:1403054975-12576-3-git-send-email-airlied@gmail.com"
type="cite">
<div style="margin:30px 25px 10px 25px;" class="__pbConvHr"><div
style="display:table;width:100%;border-top:1px solid
#EDEEF0;padding-top:5px"> <div
style="display:table-cell;vertical-align:middle;padding-right:6px;"><img
photoaddress="airlied@gmail.com" photoname="Dave Airlie"
src="cid:part1.02070802.03080302@gmail.com" name="postbox-contact.jpg"
height="25px" width="25px"></div> <div
style="display:table-cell;white-space:nowrap;vertical-align:middle;width:100%">
<a moz-do-not-send="true" href="mailto:airlied@gmail.com"
style="color:#737F92
!important;padding-right:6px;font-weight:bold;text-decoration:none
!important;">Dave Airlie</a></div> <div
style="display:table-cell;white-space:nowrap;vertical-align:middle;">
<font color="#9FA2A5"><span style="padding-left:6px">Tuesday, June 17,
2014 6:29 PM</span></font></div></div></div>
<div style="color:#888888;margin-left:24px;margin-right:24px;"
__pbrmquotes="true" class="__pbConvBody"><div>From: Dave Airlie
<a class="moz-txt-link-rfc2396E" href="mailto:airlied@redhat.com"><airlied@redhat.com></a><br><br>The digital ports from Ironlake and up
have the ability to distinguish<br>between long and short HPD pulses.
Displayport 1.1 only uses the short<br>form to request link retraining
usually, so we haven't really needed<br>support for it until now.<br><br>However
with DP 1.2 MST we need to handle the short irqs on their<br>own
outside the modesetting locking the long hpd's involve. This<br>patch
adds the framework to distinguish between short/long to the<br>current
code base, to lay the basis for future DP 1.2 MST work.<br><br>This
should mean we get better bisectability in case of regression<br>due to
the new irq handling.<br><br>v2: add GM45 support (untested, due to lack
of hw)<br><br>Signed-off-by: Dave Airlie <a class="moz-txt-link-rfc2396E" href="mailto:airlied@redhat.com"><airlied@redhat.com></a><br>---<br>
drivers/gpu/drm/i915/i915_drv.h | 5 ++<br>
drivers/gpu/drm/i915/i915_irq.c | 160
+++++++++++++++++++++++++++++++++++++--<br>
drivers/gpu/drm/i915/intel_ddi.c | 3 +<br>
drivers/gpu/drm/i915/intel_dp.c | 20 +++++<br>
drivers/gpu/drm/i915/intel_drv.h | 2 +<br> 5 files changed, 182
insertions(+), 8 deletions(-)<br><br>diff --git
a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h<br>index
8f68678..5fd5bf3 100644<br>--- a/drivers/gpu/drm/i915/i915_drv.h<br>+++
b/drivers/gpu/drm/i915/i915_drv.h<br>@@ -1551,6 +1551,11 @@ struct
drm_i915_private {<br> <br> struct i915_runtime_pm pm;<br> <br>+ struct
intel_digital_port *hpd_irq_port[I915_MAX_PORTS];<br>+ u32
long_hpd_port_mask;<br>+ u32 short_hpd_port_mask;<br>+ struct
work_struct dig_port_work;<br>+<br> /* Old dri1 support infrastructure,
beware the dragons ya fools entering<br> * here! */<br> struct
i915_dri1_state dri1;<br>diff --git a/drivers/gpu/drm/i915/i915_irq.c
b/drivers/gpu/drm/i915/i915_irq.c<br>index cbf31cb..9913c08 100644<br>---
a/drivers/gpu/drm/i915/i915_irq.c<br>+++
b/drivers/gpu/drm/i915/i915_irq.c<br>@@ -1096,6 +1096,53 @@ static bool
intel_hpd_irq_event(struct drm_device *dev,<br> return true;<br> }<br> <br>+static
void i915_digport_work_func(struct work_struct *work)<br>+{<br>+ struct
drm_i915_private *dev_priv =<br>+ container_of(work, struct
drm_i915_private, dig_port_work);<br>+ unsigned long irqflags;<br>+ u32
long_port_mask, short_port_mask;<br>+ struct intel_digital_port
*intel_dig_port;<br>+ int i, ret;<br>+ u32 old_bits = 0;<br>+<br>+
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);<br>+
long_port_mask = dev_priv->long_hpd_port_mask;<br>+
dev_priv->long_hpd_port_mask = 0;<br>+ short_port_mask =
dev_priv->short_hpd_port_mask;<br>+ dev_priv->short_hpd_port_mask =
0;<br>+ spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);<br>+<br>+
for (i = 0; i < I915_MAX_PORTS; i++) {<br>+ bool valid = false;<br>+
bool long_hpd = false;<br>+ intel_dig_port =
dev_priv->hpd_irq_port[i];<br>+ if (!intel_dig_port ||
!intel_dig_port->hpd_pulse)<br>+ continue;<br>+<br>+ if
(long_port_mask & (1 << i)) {<br>+ valid = true;<br>+
long_hpd = true;<br>+ } else if (short_port_mask & (1 << i))<br>+
valid = true;<br>+<br>+ if (valid) {<br>+ ret =
intel_dig_port->hpd_pulse(intel_dig_port, long_hpd);<br>+ if (ret
== true) {<br>+ /* if we get true fallback to old school hpd */<br>+
old_bits |= (1 << intel_dig_port->base.hpd_pin);<br>+ }<br>+
}<br>+ }<br>+<br>+ if (old_bits) {<br>+
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);<br>+
dev_priv->hpd_event_bits |= old_bits;<br>+
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);<br>+
schedule_work(&dev_priv->hotplug_work);<br>+ }<br>+}<br>+<br> /*<br>
* Handle hotplug events outside the interrupt handler proper.<br> */<br>@@
-1520,23 +1567,104 @@ static irqreturn_t gen8_gt_irq_handler(struct
drm_device *dev,<br> #define HPD_STORM_DETECT_PERIOD 1000<br> #define
HPD_STORM_THRESHOLD 5<br> <br>+static int ilk_port_to_hotplug_shift(enum
port port)<br>+{<br>+ switch (port) {<br>+ case PORT_A:<br>+ case
PORT_E:<br>+ default:<br>+ return -1;<br>+ case PORT_B:<br>+ return 0;<br>+
case PORT_C:<br>+ return 8;<br>+ case PORT_D:<br>+ return 16;<br>+ }<br>+}<br>+<br>+static
int g4x_port_to_hotplug_shift(enum port port)<br>+{<br>+ switch (port) {<br>+
case PORT_A:<br>+ case PORT_E:<br>+ default:<br>+ return -1;<br>+ case
PORT_B:<br>+ return 17;<br>+ case PORT_C:<br>+ return 19;<br>+ case
PORT_D:<br>+ return 21;<br>+ }<br>+}<br>+<br>+static inline enum port
get_port_from_pin(enum hpd_pin pin)<br>+{<br>+ switch (pin) {<br>+ case
HPD_PORT_B:<br>+ return PORT_B;<br>+ case HPD_PORT_C:<br>+ return
PORT_C;<br>+ case HPD_PORT_D:<br>+ return PORT_D;<br>+ default:<br>+
return PORT_A; /* no hpd */<br>+ }<br>+}<br>+<br> static inline void
intel_hpd_irq_handler(struct drm_device *dev,<br> u32
hotplug_trigger,<br>+ u32 dig_hotplug_reg,<br> const u32
*hpd)<br> {<br> struct drm_i915_private *dev_priv =
dev->dev_private;<br> int i;<br>+ enum port port;<br> bool
storm_detected = false;<br>+ bool queue_dig = false, queue_hp = false;<br>+
u32 dig_shift;<br>+ u32 dig_port_mask = 0;<br> <br> if
(!hotplug_trigger)<br> return;<br> <br>- DRM_DEBUG_DRIVER("hotplug
event received, stat 0x%08x\n",<br>- hotplug_trigger);<br>+
DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x, dig 0x%08x\n",<br>+
hotplug_trigger, dig_hotplug_reg);<br> <br>
spin_lock(&dev_priv->irq_lock);<br> for (i = 1; i <
HPD_NUM_PINS; i++) {<br>+ if (!(hpd[i] & hotplug_trigger))<br>+
continue;<br>+<br>+ port = get_port_from_pin(i);<br>+ if (port
&& dev_priv->hpd_irq_port[port]) {<br>+ bool long_hpd;<br>+<br>+
if (IS_G4X(dev)) {<br>+ dig_shift =
g4x_port_to_hotplug_shift(port);<br>+ long_hpd = (hotplug_trigger
>> dig_shift) & PORTB_HOTPLUG_LONG_DETECT;<br>+ } else {<br>+
dig_shift = ilk_port_to_hotplug_shift(port);<br>+ long_hpd =
(dig_hotplug_reg >> dig_shift) & PORTB_HOTPLUG_LONG_DETECT;<br>+
}<br>+<br>+ DRM_DEBUG_DRIVER("digital hpd port %d %d\n", port,
long_hpd);<br>+ /* for long HPD pulses we want to have the digital
queue happen,<br>+ but we still want HPD storm detection to
function. */<br>+ if (long_hpd) {<br>+
dev_priv->long_hpd_port_mask |= (1 << port);<br>+
dig_port_mask |= hpd[i];<br>+ } else {<br>+ /* for short HPD just
trigger the digital queue */<br>+ dev_priv->short_hpd_port_mask |=
(1 << port);<br>+ hotplug_trigger &= ~hpd[i];<br>+ }<br>+
queue_dig = true;<br>+ }<br>+ }<br> <br>+ for (i = 1; i <
HPD_NUM_PINS; i++) {<br> if (hpd[i] & hotplug_trigger &&<br>
dev_priv->hpd_stats[i].hpd_mark == HPD_DISABLED) {<br> /*<br>@@
-1556,7 +1684,11 @@ static inline void intel_hpd_irq_handler(struct
drm_device *dev,<br> dev_priv->hpd_stats[i].hpd_mark !=
HPD_ENABLED)<br> continue;<br> <br>- dev_priv->hpd_event_bits |=
(1 << i);<br>+ if (!(dig_port_mask & hpd[i])) {<br>+
dev_priv->hpd_event_bits |= (1 << i);<br>+ queue_hp = true;<br>+
}<br>+<br> if (!time_in_range(jiffies,
dev_priv->hpd_stats[i].hpd_last_jiffies,<br>
dev_priv->hpd_stats[i].hpd_last_jiffies<br> +
msecs_to_jiffies(HPD_STORM_DETECT_PERIOD))) {<br>@@ -1585,7 +1717,10 @@
static inline void intel_hpd_irq_handler(struct drm_device *dev,<br> *
queue for otherwise the flush_work in the pageflip code will<br> *
deadlock.<br> */<br>- schedule_work(&dev_priv->hotplug_work);<br>+
if (queue_dig)<br>+ schedule_work(&dev_priv->dig_port_work);<br>+
if (queue_hp)<br>+ schedule_work(&dev_priv->hotplug_work);<br> }<br>
<br> static void gmbus_irq_handler(struct drm_device *dev)<br>@@
-1818,11 +1953,11 @@ static void i9xx_hpd_irq_handler(struct drm_device
*dev)<br> if (IS_G4X(dev)) {<br> u32 hotplug_trigger = hotplug_status
& HOTPLUG_INT_STATUS_G4X;<br> <br>- intel_hpd_irq_handler(dev,
hotplug_trigger, hpd_status_g4x);<br>+ intel_hpd_irq_handler(dev,
hotplug_trigger, 0, hpd_status_g4x);<br> } else {<br> u32
hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_I915;<br> <br>-
intel_hpd_irq_handler(dev, hotplug_trigger, hpd_status_i915);<br>+
intel_hpd_irq_handler(dev, hotplug_trigger, 0, hpd_status_i915);<br> }<br>
<br> if ((IS_G4X(dev) || IS_VALLEYVIEW(dev)) &&<br>@@ -1913,8
+2048,12 @@ static void ibx_irq_handler(struct drm_device *dev, u32
pch_iir)<br> struct drm_i915_private *dev_priv = dev->dev_private;<br>
int pipe;<br> u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK;<br>+
u32 dig_hotplug_reg;<br>+<br>+ dig_hotplug_reg =
I915_READ(PCH_PORT_HOTPLUG);<br>+ I915_WRITE(PCH_PORT_HOTPLUG,
dig_hotplug_reg);<br> <br>- intel_hpd_irq_handler(dev, hotplug_trigger,
hpd_ibx);<br>+ intel_hpd_irq_handler(dev, hotplug_trigger,
dig_hotplug_reg, hpd_ibx);<br> <br> if (pch_iir &
SDE_AUDIO_POWER_MASK) {<br> int port = ffs((pch_iir &
SDE_AUDIO_POWER_MASK) >><br>@@ -2020,8 +2159,12 @@ static void
cpt_irq_handler(struct drm_device *dev, u32 pch_iir)<br> struct
drm_i915_private *dev_priv = dev->dev_private;<br> int pipe;<br>
u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_CPT;<br>+ u32
dig_hotplug_reg;<br>+<br>+ dig_hotplug_reg =
I915_READ(PCH_PORT_HOTPLUG);<br>+ I915_WRITE(PCH_PORT_HOTPLUG,
dig_hotplug_reg);<br> <br>- intel_hpd_irq_handler(dev, hotplug_trigger,
hpd_cpt);<br>+ intel_hpd_irq_handler(dev, hotplug_trigger,
dig_hotplug_reg, hpd_cpt);<br> <br> if (pch_iir &
SDE_AUDIO_POWER_MASK_CPT) {<br> int port = ffs((pch_iir &
SDE_AUDIO_POWER_MASK_CPT) >><br>@@ -4338,6 +4481,7 @@ void
intel_irq_init(struct drm_device *dev)<br> struct drm_i915_private
*dev_priv = dev->dev_private;<br> <br>
INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);<br>+
INIT_WORK(&dev_priv->dig_port_work, i915_digport_work_func);<br>
INIT_WORK(&dev_priv->gpu_error.work, i915_error_work_func);<br>
INIT_WORK(&dev_priv->rps.work, gen6_pm_rps_work);<br>
INIT_WORK(&dev_priv->l3_parity.error_work,
ivybridge_parity_work);<br>diff --git a/drivers/gpu/drm/i915/intel_ddi.c
b/drivers/gpu/drm/i915/intel_ddi.c<br>index b17b9c7..a80cb3e 100644<br>---
a/drivers/gpu/drm/i915/intel_ddi.c<br>+++
b/drivers/gpu/drm/i915/intel_ddi.c<br>@@ -1705,6 +1705,9 @@ void
intel_ddi_init(struct drm_device *dev, enum port port)<br>
intel_encoder->cloneable = 0;<br> intel_encoder->hot_plug =
intel_ddi_hot_plug;<br> <br>+ intel_dig_port->hpd_pulse =
intel_dp_hpd_pulse;<br>+ dev_priv->hpd_irq_port[port] =
intel_dig_port;<br>+<br> if (init_dp)<br> dp_connector =
intel_ddi_init_dp_connector(intel_dig_port);<br> <br>diff --git
a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c<br>index
d01bb43..f110522 100644<br>--- a/drivers/gpu/drm/i915/intel_dp.c<br>+++
b/drivers/gpu/drm/i915/intel_dp.c<br>@@ -3699,6 +3699,22 @@
intel_dp_hot_plug(struct intel_encoder *intel_encoder)<br>
intel_dp_check_link_status(intel_dp);<br> }<br> <br>+bool<br>+intel_dp_hpd_pulse(struct
intel_digital_port *intel_dig_port, bool long_hpd)<br>+{<br>+ struct
intel_dp *intel_dp = &intel_dig_port->dp;<br>+<br>+ if (long_hpd)<br>+
return true;<br>+<br>+ /*<br>+ * we'll check the link status via the
normal hot plug path later -<br>+ * but for short hpds we should check
it now<br>+ */<br>+ intel_dp_check_link_status(intel_dp);<br>+ return
false;<br>+}<br>+<br> /* Return which DP Port should be selected for
Transcoder DP control */<br> int<br> intel_trans_dp_port_sel(struct
drm_crtc *crtc)<br>@@ -4273,6 +4289,7 @@ intel_dp_init_connector(struct
intel_digital_port *intel_dig_port,<br> void<br> intel_dp_init(struct
drm_device *dev, int output_reg, enum port port)<br> {<br>+ struct
drm_i915_private *dev_priv = dev->dev_private;<br> struct
intel_digital_port *intel_dig_port;<br> struct intel_encoder
*intel_encoder;<br> struct drm_encoder *encoder;<br>@@ -4328,6 +4345,9
@@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)<br>
intel_encoder->cloneable = 0;<br> intel_encoder->hot_plug =
intel_dp_hot_plug;<br> <br>+ intel_dig_port->hpd_pulse =
intel_dp_hpd_pulse;<br>+ dev_priv->hpd_irq_port[port] =
intel_dig_port;<br>+<br> if (!intel_dp_init_connector(intel_dig_port,
intel_connector)) {<br> drm_encoder_cleanup(encoder);<br>
kfree(intel_dig_port);<br>diff --git a/drivers/gpu/drm/i915/intel_drv.h
b/drivers/gpu/drm/i915/intel_drv.h<br>index f1d5897..9666ec3 100644<br>---
a/drivers/gpu/drm/i915/intel_drv.h<br>+++
b/drivers/gpu/drm/i915/intel_drv.h<br>@@ -563,6 +563,7 @@ struct
intel_digital_port {<br> u32 saved_port_bits;<br> struct intel_dp dp;<br>
struct intel_hdmi hdmi;<br>+ bool (*hpd_pulse)(struct
intel_digital_port *, bool);<br> };<br> <br> static inline int<br>@@
-830,6 +831,7 @@ void intel_edp_psr_enable(struct intel_dp *intel_dp);<br>
void intel_edp_psr_disable(struct intel_dp *intel_dp);<br> void
intel_edp_psr_update(struct drm_device *dev);<br> void
intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate);<br>+bool
intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool
long_hpd);<br> <br> /* intel_dsi.c */<br> bool intel_dsi_init(struct
drm_device *dev);<br></div></div>
<div style="margin:30px 25px 10px 25px;" class="__pbConvHr"><div
style="display:table;width:100%;border-top:1px solid
#EDEEF0;padding-top:5px"> <div
style="display:table-cell;vertical-align:middle;padding-right:6px;"><img
photoaddress="airlied@gmail.com" photoname="Dave Airlie"
src="cid:part1.02070802.03080302@gmail.com" name="postbox-contact.jpg"
height="25px" width="25px"></div> <div
style="display:table-cell;white-space:nowrap;vertical-align:middle;width:100%">
<a moz-do-not-send="true" href="mailto:airlied@gmail.com"
style="color:#737F92
!important;padding-right:6px;font-weight:bold;text-decoration:none
!important;">Dave Airlie</a></div> <div
style="display:table-cell;white-space:nowrap;vertical-align:middle;">
<font color="#9FA2A5"><span style="padding-left:6px">Tuesday, June 17,
2014 6:29 PM</span></font></div></div></div>
<div style="color:#888888;margin-left:24px;margin-right:24px;"
__pbrmquotes="true" class="__pbConvBody"><div>Can we get these merged or
even looked at?, they are blocking the whole MST progress,<br>and I
don't have any insight to secret Intel review process. :-)<br><br>Dave.<br><br>_______________________________________________<br>Intel-gfx
mailing list<br><a class="moz-txt-link-abbreviated" href="mailto:Intel-gfx@lists.freedesktop.org">Intel-gfx@lists.freedesktop.org</a><br><a class="moz-txt-link-freetext" href="http://lists.freedesktop.org/mailman/listinfo/intel-gfx">http://lists.freedesktop.org/mailman/listinfo/intel-gfx</a><br></div></div>
</blockquote>
<br>
<div class="moz-signature">-- <br>
<div>Sent with <a href="http://www.getpostbox.com"><span style="color:
rgb(51, 102, 153);">Postbox</span></a></div></div>
</body></html>