Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0e32b39c authored by Dave Airlie's avatar Dave Airlie
Browse files

drm/i915: add DP 1.2 MST support (v0.7)



This adds DP 1.2 MST support on Haswell systems.

Notes:
a) this reworks irq handling for DP MST ports, so that we can
avoid the mode config locking in the current hpd handlers, as
we need to process up/down msgs at a better time.

Changes since v0.1:
use PORT_PCH_HOTPLUG to detect short vs long pulses
add a workqueue to deal with digital events as they can get blocked on the
main workqueue beyong mode_config mutex
fix a bunch of modeset checker warnings
acks irqs in the driver
cleanup the MST encoders

Changes since v0.2:
check irq status again in work handler
move around bring up and tear down to fix DPMS on/off
use path properties.

Changes since v0.3:
updates for mst apis
more state checker fixes
irq handling improvements
fbcon handling support
improved reference counting of link - fixes redocking.

Changes since v0.4:
handle gpu reset hpd reinit without oopsing
check link status on HPD irqs
fix suspend/resume

Changes since v0.5:
use proper functions to get max link/lane counts
fix another checker backtrace - due to connectors disappearing.
set output type in more places fro, unknown->displayport
don't talk to devices if no HPD asserted
check mst on short irqs only
check link status properly
rebase onto prepping irq changes.
drop unsued force_act

Changes since v0.6:
cleanup unused struct entry.

[airlied: fix some sparse warnings].

Reviewed-by: default avatarTodd Previte <tprevite@gmail.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent d05410f9
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@ i915-y += dvo_ch7017.o \
	  intel_crt.o \
	  intel_ddi.o \
	  intel_dp.o \
	  intel_dp_mst.o \
	  intel_dsi_cmd.o \
	  intel_dsi.o \
	  intel_dsi_pll.o \
+10 −0
Original line number Diff line number Diff line
@@ -1717,6 +1717,13 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
		goto out_mtrrfree;
	}

	dev_priv->dp_wq = alloc_ordered_workqueue("i915-dp", 0);
	if (dev_priv->dp_wq == NULL) {
		DRM_ERROR("Failed to create our dp workqueue.\n");
		ret = -ENOMEM;
		goto out_freewq;
	}

	intel_irq_init(dev);
	intel_uncore_sanitize(dev);

@@ -1792,6 +1799,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
	intel_teardown_gmbus(dev);
	intel_teardown_mchbar(dev);
	pm_qos_remove_request(&dev_priv->pm_qos);
	destroy_workqueue(dev_priv->dp_wq);
out_freewq:
	destroy_workqueue(dev_priv->wq);
out_mtrrfree:
	arch_phys_wc_del(dev_priv->gtt.mtrr);
@@ -1892,6 +1901,7 @@ int i915_driver_unload(struct drm_device *dev)
	intel_teardown_gmbus(dev);
	intel_teardown_mchbar(dev);

	destroy_workqueue(dev_priv->dp_wq);
	destroy_workqueue(dev_priv->wq);
	pm_qos_remove_request(&dev_priv->pm_qos);

+12 −1
Original line number Diff line number Diff line
@@ -518,7 +518,6 @@ static int i915_drm_freeze(struct drm_device *dev)

		flush_delayed_work(&dev_priv->rps.delayed_resume_work);

		intel_runtime_pm_disable_interrupts(dev);

		intel_suspend_gt_powersave(dev);

@@ -532,6 +531,9 @@ static int i915_drm_freeze(struct drm_device *dev)
		}
		drm_modeset_unlock_all(dev);

		intel_dp_mst_suspend(dev);
		intel_runtime_pm_disable_interrupts(dev);

		intel_modeset_suspend_hw(dev);
	}

@@ -646,6 +648,15 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings)

		intel_modeset_init_hw(dev);

		{
			unsigned long irqflags;
			spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
			if (dev_priv->display.hpd_irq_setup)
				dev_priv->display.hpd_irq_setup(dev);
			spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
		}

		intel_dp_mst_resume(dev);
		drm_modeset_lock_all(dev);
		intel_modeset_setup_hw_state(dev, true);
		drm_modeset_unlock_all(dev);
+9 −0
Original line number Diff line number Diff line
@@ -1595,6 +1595,15 @@ struct drm_i915_private {
	u32 short_hpd_port_mask;
	struct work_struct dig_port_work;

	/*
	 * if we get a HPD irq from DP and a HPD irq from non-DP
	 * the non-DP HPD could block the workqueue on a mode config
	 * mutex getting, that userspace may have taken. However
	 * userspace is waiting on the DP workqueue to run which is
	 * blocked behind the non-DP one.
	 */
	struct workqueue_struct *dp_wq;

	/* Old dri1 support infrastructure, beware the dragons ya fools entering
	 * here! */
	struct i915_dri1_state dri1;
+4 −2
Original line number Diff line number Diff line
@@ -1846,7 +1846,7 @@ static inline void intel_hpd_irq_handler(struct drm_device *dev,
	 * deadlock.
	 */
	if (queue_dig)
		schedule_work(&dev_priv->dig_port_work);
		queue_work(dev_priv->dp_wq, &dev_priv->dig_port_work);
	if (queue_hp)
		schedule_work(&dev_priv->hotplug_work);
}
@@ -4739,7 +4739,9 @@ void intel_hpd_init(struct drm_device *dev)
	list_for_each_entry(connector, &mode_config->connector_list, head) {
		struct intel_connector *intel_connector = to_intel_connector(connector);
		connector->polled = intel_connector->polled;
		if (!connector->polled && I915_HAS_HOTPLUG(dev) && intel_connector->encoder->hpd_pin > HPD_NONE)
		if (connector->encoder && !connector->polled && I915_HAS_HOTPLUG(dev) && intel_connector->encoder->hpd_pin > HPD_NONE)
			connector->polled = DRM_CONNECTOR_POLL_HPD;
		if (intel_connector->mst_port)
			connector->polled = DRM_CONNECTOR_POLL_HPD;
	}

Loading