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

Commit c650156a authored by Zhenyu Wang's avatar Zhenyu Wang Committed by Eric Anholt
Browse files

drm/i915: Add display hotplug event on Ironlake



Enable display hotplug irqs from Ibex Peak (PCH).

Signed-off-by: default avatarZhenyu Wang <zhenyuw@linux.intel.com>
Signed-off-by: default avatarEric Anholt <eric@anholt.net>
parent 01c66889
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -214,6 +214,8 @@ typedef struct drm_i915_private {
	u32 gt_irq_mask_reg;
	u32 gt_irq_enable_reg;
	u32 de_irq_enable_reg;
	u32 pch_irq_mask_reg;
	u32 pch_irq_enable_reg;

	u32 hotplug_supported_mask;
	struct work_struct hotplug_work;
+31 −4
Original line number Diff line number Diff line
@@ -270,19 +270,24 @@ irqreturn_t igdng_irq_handler(struct drm_device *dev)
{
	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
	int ret = IRQ_NONE;
	u32 de_iir, gt_iir;
	u32 new_de_iir, new_gt_iir;
	u32 de_iir, gt_iir, pch_iir;
	u32 new_de_iir, new_gt_iir, new_pch_iir;
	struct drm_i915_master_private *master_priv;

	de_iir = I915_READ(DEIIR);
	gt_iir = I915_READ(GTIIR);
	pch_iir = I915_READ(SDEIIR);

	for (;;) {
		if (de_iir == 0 && gt_iir == 0)
		if (de_iir == 0 && gt_iir == 0 && pch_iir == 0)
			break;

		ret = IRQ_HANDLED;

		/* should clear PCH hotplug event before clear CPU irq */
		I915_WRITE(SDEIIR, pch_iir);
		new_pch_iir = I915_READ(SDEIIR);

		I915_WRITE(DEIIR, de_iir);
		new_de_iir = I915_READ(DEIIR);
		I915_WRITE(GTIIR, gt_iir);
@@ -305,8 +310,15 @@ irqreturn_t igdng_irq_handler(struct drm_device *dev)
		if (de_iir & DE_GSE)
			ironlake_opregion_gse_intr(dev);

		/* check event from PCH */
		if ((de_iir & DE_PCH_EVENT) &&
			(pch_iir & SDE_HOTPLUG_MASK)) {
			queue_work(dev_priv->wq, &dev_priv->hotplug_work);
		}

		de_iir = new_de_iir;
		gt_iir = new_gt_iir;
		pch_iir = new_pch_iir;
	}

	return ret;
@@ -1003,14 +1015,21 @@ static void igdng_irq_preinstall(struct drm_device *dev)
	I915_WRITE(GTIMR, 0xffffffff);
	I915_WRITE(GTIER, 0x0);
	(void) I915_READ(GTIER);

	/* south display irq */
	I915_WRITE(SDEIMR, 0xffffffff);
	I915_WRITE(SDEIER, 0x0);
	(void) I915_READ(SDEIER);
}

static int igdng_irq_postinstall(struct drm_device *dev)
{
	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
	/* enable kind of interrupts always enabled */
	u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE /*| DE_PCH_EVENT */;
	u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT;
	u32 render_mask = GT_USER_INTERRUPT;
	u32 hotplug_mask = SDE_CRT_HOTPLUG | SDE_PORTB_HOTPLUG |
			   SDE_PORTC_HOTPLUG | SDE_PORTD_HOTPLUG;

	dev_priv->irq_mask_reg = ~display_mask;
	dev_priv->de_irq_enable_reg = display_mask;
@@ -1030,6 +1049,14 @@ static int igdng_irq_postinstall(struct drm_device *dev)
	I915_WRITE(GTIER, dev_priv->gt_irq_enable_reg);
	(void) I915_READ(GTIER);

	dev_priv->pch_irq_mask_reg = ~hotplug_mask;
	dev_priv->pch_irq_enable_reg = hotplug_mask;

	I915_WRITE(SDEIIR, I915_READ(SDEIIR));
	I915_WRITE(SDEIMR, dev_priv->pch_irq_mask_reg);
	I915_WRITE(SDEIER, dev_priv->pch_irq_enable_reg);
	(void) I915_READ(SDEIER);

	return 0;
}

+1 −0
Original line number Diff line number Diff line
@@ -2126,6 +2126,7 @@
#define SDE_PORTC_HOTPLUG       (1 << 9)
#define SDE_PORTB_HOTPLUG       (1 << 8)
#define SDE_SDVOB_HOTPLUG       (1 << 6)
#define SDE_HOTPLUG_MASK	(0xf << 8)

#define SDEISR  0xc4000
#define SDEIMR  0xc4004