From ab5c608b2d96c8db80b9c7df072f18f3a4226b55 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Fri, 5 Apr 2013 13:12:41 -0700 Subject: drm/i915: Don't touch South Display when PCH_NOP Interrupts, clock gating, LVDS, and GMBUS are all within the, "this will be bad for CPU" range when we have PCH_NOP. There is a bit of a hack in init clock gating. We want to do most of the clock gating, but the part we skip will hang the system. It could probably be abstracted a bit better, but I don't feel it's too unsightly. v2: Use inverse HAS_PCH_NOP check (Jani) v3: Actually do what I claimed in v2 (spotted by Daniel) Merge Ivybridge IRQ handler PCH check to decrease whitespace (Daniel) Move LVDS bail into this patch (Ben) v4: logical rebase conflict resolution with SDEIIR (Ben) Signed-off-by: Ben Widawsky Brush up patch a bit and resolve conflicts: - Adjust PCH_NOP checks due to Egbert's hpd handling rework. - Addd a PCH_NOP check in the irq uninstall code. - Resolve conflicts with Paulo's SDE irq handling race fix. v5: Drop the added hunks in the ilk irq handler again, they're bogus. OOps. Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 28 +++++++++++++++++++++------- drivers/gpu/drm/i915/intel_bios.c | 3 +++ drivers/gpu/drm/i915/intel_i2c.c | 4 +++- drivers/gpu/drm/i915/intel_pm.c | 3 ++- 4 files changed, 29 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 4c5bdd03738..b4e237d9927 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -758,7 +758,7 @@ static irqreturn_t ivybridge_irq_handler(int irq, void *arg) { struct drm_device *dev = (struct drm_device *) arg; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - u32 de_iir, gt_iir, de_ier, pm_iir, sde_ier; + u32 de_iir, gt_iir, de_ier, pm_iir, sde_ier = 0; irqreturn_t ret = IRQ_NONE; int i; @@ -773,9 +773,11 @@ static irqreturn_t ivybridge_irq_handler(int irq, void *arg) * able to process them after we restore SDEIER (as soon as we restore * it, we'll get an interrupt if SDEIIR still has something to process * due to its back queue). */ - sde_ier = I915_READ(SDEIER); - I915_WRITE(SDEIER, 0); - POSTING_READ(SDEIER); + if (!HAS_PCH_NOP(dev)) { + sde_ier = I915_READ(SDEIER); + I915_WRITE(SDEIER, 0); + POSTING_READ(SDEIER); + } gt_iir = I915_READ(GTIIR); if (gt_iir) { @@ -802,7 +804,7 @@ static irqreturn_t ivybridge_irq_handler(int irq, void *arg) } /* check event from PCH */ - if (de_iir & DE_PCH_EVENT_IVB) { + if (!HAS_PCH_NOP(dev) && (de_iir & DE_PCH_EVENT_IVB)) { u32 pch_iir = I915_READ(SDEIIR); cpt_irq_handler(dev, pch_iir); @@ -825,8 +827,10 @@ static irqreturn_t ivybridge_irq_handler(int irq, void *arg) I915_WRITE(DEIER, de_ier); POSTING_READ(DEIER); - I915_WRITE(SDEIER, sde_ier); - POSTING_READ(SDEIER); + if (!HAS_PCH_NOP(dev)) { + I915_WRITE(SDEIER, sde_ier); + POSTING_READ(SDEIER); + } return ret; } @@ -2027,6 +2031,9 @@ static void ironlake_irq_preinstall(struct drm_device *dev) I915_WRITE(GTIER, 0x0); POSTING_READ(GTIER); + if (HAS_PCH_NOP(dev)) + return; + /* south display irq */ I915_WRITE(SDEIMR, 0xffffffff); /* @@ -2112,6 +2119,10 @@ static void ibx_irq_postinstall(struct drm_device *dev) mask = SDE_GMBUS | SDE_AUX_MASK; else mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT; + + if (HAS_PCH_NOP(dev)) + return; + I915_WRITE(SDEIIR, I915_READ(SDEIIR)); I915_WRITE(SDEIMR, ~mask); } @@ -2306,6 +2317,9 @@ static void ironlake_irq_uninstall(struct drm_device *dev) I915_WRITE(GTIER, 0x0); I915_WRITE(GTIIR, I915_READ(GTIIR)); + if (HAS_PCH_NOP(dev)) + return; + I915_WRITE(SDEIMR, 0xffffffff); I915_WRITE(SDEIER, 0x0); I915_WRITE(SDEIIR, I915_READ(SDEIIR)); diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 55ffba1f581..194df27c89e 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -692,6 +692,9 @@ intel_parse_bios(struct drm_device *dev) struct bdb_header *bdb = NULL; u8 __iomem *bios = NULL; + if (HAS_PCH_NOP(dev)) + return -ENODEV; + init_vbt_defaults(dev_priv); /* XXX Should this validation be moved to intel_opregion.c? */ diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index ef4744e1bf0..5d245031e39 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -522,7 +522,9 @@ int intel_setup_gmbus(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; int ret, i; - if (HAS_PCH_SPLIT(dev)) + if (HAS_PCH_NOP(dev)) + return 0; + else if (HAS_PCH_SPLIT(dev)) dev_priv->gpio_mmio_base = PCH_GPIOA - GPIOA; else if (IS_VALLEYVIEW(dev)) dev_priv->gpio_mmio_base = VLV_DISPLAY_BASE; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 13a0666a53b..17f157a7b64 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3890,7 +3890,8 @@ static void ivybridge_init_clock_gating(struct drm_device *dev) snpcr |= GEN6_MBC_SNPCR_MED; I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr); - cpt_init_clock_gating(dev); + if (!HAS_PCH_NOP(dev)) + cpt_init_clock_gating(dev); gen6_check_mch_setup(dev); } -- cgit v1.2.3-18-g5258