diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_irq.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 810 |
1 files changed, 528 insertions, 282 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 759f523c6a6b..dc6febc63f1c 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -61,6 +61,8 @@ */ typedef bool (*long_pulse_detect_func)(enum hpd_pin pin, u32 val); +typedef u32 (*hotplug_enables_func)(struct drm_i915_private *i915, + enum hpd_pin pin); static const u32 hpd_ilk[HPD_NUM_PINS] = { [HPD_PORT_A] = DE_DP_A_HOTPLUG, @@ -71,7 +73,7 @@ static const u32 hpd_ivb[HPD_NUM_PINS] = { }; static const u32 hpd_bdw[HPD_NUM_PINS] = { - [HPD_PORT_A] = GEN8_PORT_DP_A_HOTPLUG, + [HPD_PORT_A] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_A), }; static const u32 hpd_ibx[HPD_NUM_PINS] = { @@ -126,30 +128,37 @@ static const u32 hpd_status_i915[HPD_NUM_PINS] = { }; static const u32 hpd_bxt[HPD_NUM_PINS] = { - [HPD_PORT_A] = BXT_DE_PORT_HP_DDIA, - [HPD_PORT_B] = BXT_DE_PORT_HP_DDIB, - [HPD_PORT_C] = BXT_DE_PORT_HP_DDIC, + [HPD_PORT_A] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_A), + [HPD_PORT_B] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_B), + [HPD_PORT_C] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_C), }; static const u32 hpd_gen11[HPD_NUM_PINS] = { - [HPD_PORT_TC1] = GEN11_TC_HOTPLUG(PORT_TC1) | GEN11_TBT_HOTPLUG(PORT_TC1), - [HPD_PORT_TC2] = GEN11_TC_HOTPLUG(PORT_TC2) | GEN11_TBT_HOTPLUG(PORT_TC2), - [HPD_PORT_TC3] = GEN11_TC_HOTPLUG(PORT_TC3) | GEN11_TBT_HOTPLUG(PORT_TC3), - [HPD_PORT_TC4] = GEN11_TC_HOTPLUG(PORT_TC4) | GEN11_TBT_HOTPLUG(PORT_TC4), - [HPD_PORT_TC5] = GEN11_TC_HOTPLUG(PORT_TC5) | GEN11_TBT_HOTPLUG(PORT_TC5), - [HPD_PORT_TC6] = GEN11_TC_HOTPLUG(PORT_TC6) | GEN11_TBT_HOTPLUG(PORT_TC6), + [HPD_PORT_TC1] = GEN11_TC_HOTPLUG(HPD_PORT_TC1) | GEN11_TBT_HOTPLUG(HPD_PORT_TC1), + [HPD_PORT_TC2] = GEN11_TC_HOTPLUG(HPD_PORT_TC2) | GEN11_TBT_HOTPLUG(HPD_PORT_TC2), + [HPD_PORT_TC3] = GEN11_TC_HOTPLUG(HPD_PORT_TC3) | GEN11_TBT_HOTPLUG(HPD_PORT_TC3), + [HPD_PORT_TC4] = GEN11_TC_HOTPLUG(HPD_PORT_TC4) | GEN11_TBT_HOTPLUG(HPD_PORT_TC4), + [HPD_PORT_TC5] = GEN11_TC_HOTPLUG(HPD_PORT_TC5) | GEN11_TBT_HOTPLUG(HPD_PORT_TC5), + [HPD_PORT_TC6] = GEN11_TC_HOTPLUG(HPD_PORT_TC6) | GEN11_TBT_HOTPLUG(HPD_PORT_TC6), }; static const u32 hpd_icp[HPD_NUM_PINS] = { - [HPD_PORT_A] = SDE_DDI_HOTPLUG_ICP(PORT_A), - [HPD_PORT_B] = SDE_DDI_HOTPLUG_ICP(PORT_B), - [HPD_PORT_C] = SDE_DDI_HOTPLUG_ICP(PORT_C), - [HPD_PORT_TC1] = SDE_TC_HOTPLUG_ICP(PORT_TC1), - [HPD_PORT_TC2] = SDE_TC_HOTPLUG_ICP(PORT_TC2), - [HPD_PORT_TC3] = SDE_TC_HOTPLUG_ICP(PORT_TC3), - [HPD_PORT_TC4] = SDE_TC_HOTPLUG_ICP(PORT_TC4), - [HPD_PORT_TC5] = SDE_TC_HOTPLUG_ICP(PORT_TC5), - [HPD_PORT_TC6] = SDE_TC_HOTPLUG_ICP(PORT_TC6), + [HPD_PORT_A] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_A), + [HPD_PORT_B] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_B), + [HPD_PORT_C] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_C), + [HPD_PORT_TC1] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC1), + [HPD_PORT_TC2] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC2), + [HPD_PORT_TC3] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC3), + [HPD_PORT_TC4] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC4), + [HPD_PORT_TC5] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC5), + [HPD_PORT_TC6] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC6), +}; + +static const u32 hpd_sde_dg1[HPD_NUM_PINS] = { + [HPD_PORT_A] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_A), + [HPD_PORT_B] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_B), + [HPD_PORT_C] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_C), + [HPD_PORT_D] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_D), }; static void intel_hpd_init_pins(struct drm_i915_private *dev_priv) @@ -176,11 +185,14 @@ static void intel_hpd_init_pins(struct drm_i915_private *dev_priv) else hpd->hpd = hpd_ilk; - if (!HAS_PCH_SPLIT(dev_priv) || HAS_PCH_NOP(dev_priv)) + if ((INTEL_PCH_TYPE(dev_priv) < PCH_DG1) && + (!HAS_PCH_SPLIT(dev_priv) || HAS_PCH_NOP(dev_priv))) return; - if (HAS_PCH_TGP(dev_priv) || HAS_PCH_JSP(dev_priv) || - HAS_PCH_ICP(dev_priv) || HAS_PCH_MCC(dev_priv)) + if (HAS_PCH_DG1(dev_priv)) + hpd->pch_hpd = hpd_sde_dg1; + else if (HAS_PCH_TGP(dev_priv) || HAS_PCH_JSP(dev_priv) || + HAS_PCH_ICP(dev_priv) || HAS_PCH_MCC(dev_priv)) hpd->pch_hpd = hpd_icp; else if (HAS_PCH_CNP(dev_priv) || HAS_PCH_SPT(dev_priv)) hpd->pch_hpd = hpd_spt; @@ -337,17 +349,14 @@ void ilk_update_display_irq(struct drm_i915_private *dev_priv, u32 new_val; lockdep_assert_held(&dev_priv->irq_lock); - drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask); - if (drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv))) - return; - new_val = dev_priv->irq_mask; new_val &= ~interrupt_mask; new_val |= (~enabled_irq_mask & interrupt_mask); - if (new_val != dev_priv->irq_mask) { + if (new_val != dev_priv->irq_mask && + !drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv))) { dev_priv->irq_mask = new_val; I915_WRITE(DEIMR, dev_priv->irq_mask); POSTING_READ(DEIMR); @@ -682,8 +691,12 @@ u32 i915_get_vblank_counter(struct drm_crtc *crtc) u32 g4x_get_vblank_counter(struct drm_crtc *crtc) { struct drm_i915_private *dev_priv = to_i915(crtc->dev); + struct drm_vblank_crtc *vblank = &dev_priv->drm.vblank[drm_crtc_index(crtc)]; enum pipe pipe = to_intel_crtc(crtc)->pipe; + if (!vblank->max_vblank_count) + return 0; + return I915_READ(PIPE_FRMCOUNT_G4X(pipe)); } @@ -1031,17 +1044,17 @@ static bool gen11_port_hotplug_long_detect(enum hpd_pin pin, u32 val) { switch (pin) { case HPD_PORT_TC1: - return val & GEN11_HOTPLUG_CTL_LONG_DETECT(PORT_TC1); + return val & GEN11_HOTPLUG_CTL_LONG_DETECT(HPD_PORT_TC1); case HPD_PORT_TC2: - return val & GEN11_HOTPLUG_CTL_LONG_DETECT(PORT_TC2); + return val & GEN11_HOTPLUG_CTL_LONG_DETECT(HPD_PORT_TC2); case HPD_PORT_TC3: - return val & GEN11_HOTPLUG_CTL_LONG_DETECT(PORT_TC3); + return val & GEN11_HOTPLUG_CTL_LONG_DETECT(HPD_PORT_TC3); case HPD_PORT_TC4: - return val & GEN11_HOTPLUG_CTL_LONG_DETECT(PORT_TC4); + return val & GEN11_HOTPLUG_CTL_LONG_DETECT(HPD_PORT_TC4); case HPD_PORT_TC5: - return val & GEN11_HOTPLUG_CTL_LONG_DETECT(PORT_TC5); + return val & GEN11_HOTPLUG_CTL_LONG_DETECT(HPD_PORT_TC5); case HPD_PORT_TC6: - return val & GEN11_HOTPLUG_CTL_LONG_DETECT(PORT_TC6); + return val & GEN11_HOTPLUG_CTL_LONG_DETECT(HPD_PORT_TC6); default: return false; } @@ -1065,11 +1078,13 @@ static bool icp_ddi_port_hotplug_long_detect(enum hpd_pin pin, u32 val) { switch (pin) { case HPD_PORT_A: - return val & SHOTPLUG_CTL_DDI_HPD_LONG_DETECT(PORT_A); + return val & SHOTPLUG_CTL_DDI_HPD_LONG_DETECT(HPD_PORT_A); case HPD_PORT_B: - return val & SHOTPLUG_CTL_DDI_HPD_LONG_DETECT(PORT_B); + return val & SHOTPLUG_CTL_DDI_HPD_LONG_DETECT(HPD_PORT_B); case HPD_PORT_C: - return val & SHOTPLUG_CTL_DDI_HPD_LONG_DETECT(PORT_C); + return val & SHOTPLUG_CTL_DDI_HPD_LONG_DETECT(HPD_PORT_C); + case HPD_PORT_D: + return val & SHOTPLUG_CTL_DDI_HPD_LONG_DETECT(HPD_PORT_D); default: return false; } @@ -1079,17 +1094,17 @@ static bool icp_tc_port_hotplug_long_detect(enum hpd_pin pin, u32 val) { switch (pin) { case HPD_PORT_TC1: - return val & ICP_TC_HPD_LONG_DETECT(PORT_TC1); + return val & ICP_TC_HPD_LONG_DETECT(HPD_PORT_TC1); case HPD_PORT_TC2: - return val & ICP_TC_HPD_LONG_DETECT(PORT_TC2); + return val & ICP_TC_HPD_LONG_DETECT(HPD_PORT_TC2); case HPD_PORT_TC3: - return val & ICP_TC_HPD_LONG_DETECT(PORT_TC3); + return val & ICP_TC_HPD_LONG_DETECT(HPD_PORT_TC3); case HPD_PORT_TC4: - return val & ICP_TC_HPD_LONG_DETECT(PORT_TC4); + return val & ICP_TC_HPD_LONG_DETECT(HPD_PORT_TC4); case HPD_PORT_TC5: - return val & ICP_TC_HPD_LONG_DETECT(PORT_TC5); + return val & ICP_TC_HPD_LONG_DETECT(HPD_PORT_TC5); case HPD_PORT_TC6: - return val & ICP_TC_HPD_LONG_DETECT(PORT_TC6); + return val & ICP_TC_HPD_LONG_DETECT(HPD_PORT_TC6); default: return false; } @@ -1192,6 +1207,43 @@ static void intel_get_hpd_pins(struct drm_i915_private *dev_priv, } +static u32 intel_hpd_enabled_irqs(struct drm_i915_private *dev_priv, + const u32 hpd[HPD_NUM_PINS]) +{ + struct intel_encoder *encoder; + u32 enabled_irqs = 0; + + for_each_intel_encoder(&dev_priv->drm, encoder) + if (dev_priv->hotplug.stats[encoder->hpd_pin].state == HPD_ENABLED) + enabled_irqs |= hpd[encoder->hpd_pin]; + + return enabled_irqs; +} + +static u32 intel_hpd_hotplug_irqs(struct drm_i915_private *dev_priv, + const u32 hpd[HPD_NUM_PINS]) +{ + struct intel_encoder *encoder; + u32 hotplug_irqs = 0; + + for_each_intel_encoder(&dev_priv->drm, encoder) + hotplug_irqs |= hpd[encoder->hpd_pin]; + + return hotplug_irqs; +} + +static u32 intel_hpd_hotplug_enables(struct drm_i915_private *i915, + hotplug_enables_func hotplug_enables) +{ + struct intel_encoder *encoder; + u32 hotplug = 0; + + for_each_intel_encoder(&i915->drm, encoder) + hotplug |= hotplug_enables(i915, encoder->hpd_pin); + + return hotplug; +} + static void gmbus_irq_handler(struct drm_i915_private *dev_priv) { wake_up_all(&dev_priv->gmbus_wait_queue); @@ -1245,6 +1297,23 @@ display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, u32 crc4) {} #endif +static void flip_done_handler(struct drm_i915_private *i915, + enum pipe pipe) +{ + struct intel_crtc *crtc = intel_get_crtc_for_pipe(i915, pipe); + struct drm_crtc_state *crtc_state = crtc->base.state; + struct drm_pending_vblank_event *e = crtc_state->event; + struct drm_device *dev = &i915->drm; + unsigned long irqflags; + + spin_lock_irqsave(&dev->event_lock, irqflags); + + crtc_state->event = NULL; + + drm_crtc_send_vblank_event(&crtc->base, e); + + spin_unlock_irqrestore(&dev->event_lock, irqflags); +} static void hsw_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, enum pipe pipe) @@ -1840,27 +1909,10 @@ static void cpt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) static void icp_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) { - u32 ddi_hotplug_trigger, tc_hotplug_trigger; + u32 ddi_hotplug_trigger = pch_iir & SDE_DDI_HOTPLUG_MASK_ICP; + u32 tc_hotplug_trigger = pch_iir & SDE_TC_HOTPLUG_MASK_ICP; u32 pin_mask = 0, long_mask = 0; - if (HAS_PCH_TGP(dev_priv)) { - ddi_hotplug_trigger = pch_iir & SDE_DDI_MASK_TGP; - tc_hotplug_trigger = pch_iir & SDE_TC_MASK_TGP; - } else if (HAS_PCH_JSP(dev_priv)) { - ddi_hotplug_trigger = pch_iir & SDE_DDI_MASK_TGP; - tc_hotplug_trigger = 0; - } else if (HAS_PCH_MCC(dev_priv)) { - ddi_hotplug_trigger = pch_iir & SDE_DDI_MASK_ICP; - tc_hotplug_trigger = pch_iir & SDE_TC_HOTPLUG_ICP(PORT_TC1); - } else { - drm_WARN(&dev_priv->drm, !HAS_PCH_ICP(dev_priv), - "Unrecognized PCH type 0x%x\n", - INTEL_PCH_TYPE(dev_priv)); - - ddi_hotplug_trigger = pch_iir & SDE_DDI_MASK_ICP; - tc_hotplug_trigger = pch_iir & SDE_TC_MASK_ICP; - } - if (ddi_hotplug_trigger) { u32 dig_hotplug_reg; @@ -2237,6 +2289,63 @@ gen8_de_misc_irq_handler(struct drm_i915_private *dev_priv, u32 iir) drm_err(&dev_priv->drm, "Unexpected DE Misc interrupt\n"); } +static void gen11_dsi_te_interrupt_handler(struct drm_i915_private *dev_priv, + u32 te_trigger) +{ + enum pipe pipe = INVALID_PIPE; + enum transcoder dsi_trans; + enum port port; + u32 val, tmp; + + /* + * Incase of dual link, TE comes from DSI_1 + * this is to check if dual link is enabled + */ + val = I915_READ(TRANS_DDI_FUNC_CTL2(TRANSCODER_DSI_0)); + val &= PORT_SYNC_MODE_ENABLE; + + /* + * if dual link is enabled, then read DSI_0 + * transcoder registers + */ + port = ((te_trigger & DSI1_TE && val) || (te_trigger & DSI0_TE)) ? + PORT_A : PORT_B; + dsi_trans = (port == PORT_A) ? TRANSCODER_DSI_0 : TRANSCODER_DSI_1; + + /* Check if DSI configured in command mode */ + val = I915_READ(DSI_TRANS_FUNC_CONF(dsi_trans)); + val = val & OP_MODE_MASK; + + if (val != CMD_MODE_NO_GATE && val != CMD_MODE_TE_GATE) { + drm_err(&dev_priv->drm, "DSI trancoder not configured in command mode\n"); + return; + } + + /* Get PIPE for handling VBLANK event */ + val = I915_READ(TRANS_DDI_FUNC_CTL(dsi_trans)); + switch (val & TRANS_DDI_EDP_INPUT_MASK) { + case TRANS_DDI_EDP_INPUT_A_ON: + pipe = PIPE_A; + break; + case TRANS_DDI_EDP_INPUT_B_ONOFF: + pipe = PIPE_B; + break; + case TRANS_DDI_EDP_INPUT_C_ONOFF: + pipe = PIPE_C; + break; + default: + drm_err(&dev_priv->drm, "Invalid PIPE\n"); + return; + } + + intel_handle_vblank(dev_priv, pipe); + + /* clear TE in dsi IIR */ + port = (te_trigger & DSI1_TE) ? PORT_B : PORT_A; + tmp = I915_READ(DSI_INTR_IDENT_REG(port)); + I915_WRITE(DSI_INTR_IDENT_REG(port), tmp); +} + static irqreturn_t gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) { @@ -2271,7 +2380,6 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) if (master_ctl & GEN8_DE_PORT_IRQ) { iir = I915_READ(GEN8_DE_PORT_IIR); if (iir) { - u32 tmp_mask; bool found = false; I915_WRITE(GEN8_DE_PORT_IIR, iir); @@ -2283,15 +2391,17 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) } if (IS_GEN9_LP(dev_priv)) { - tmp_mask = iir & BXT_DE_PORT_HOTPLUG_MASK; - if (tmp_mask) { - bxt_hpd_irq_handler(dev_priv, tmp_mask); + u32 hotplug_trigger = iir & BXT_DE_PORT_HOTPLUG_MASK; + + if (hotplug_trigger) { + bxt_hpd_irq_handler(dev_priv, hotplug_trigger); found = true; } } else if (IS_BROADWELL(dev_priv)) { - tmp_mask = iir & GEN8_PORT_DP_A_HOTPLUG; - if (tmp_mask) { - ilk_hpd_irq_handler(dev_priv, tmp_mask); + u32 hotplug_trigger = iir & BDW_DE_PORT_HOTPLUG_MASK; + + if (hotplug_trigger) { + ilk_hpd_irq_handler(dev_priv, hotplug_trigger); found = true; } } @@ -2301,6 +2411,15 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) found = true; } + if (INTEL_GEN(dev_priv) >= 11) { + u32 te_trigger = iir & (DSI0_TE | DSI1_TE); + + if (te_trigger) { + gen11_dsi_te_interrupt_handler(dev_priv, te_trigger); + found = true; + } + } + if (!found) drm_err(&dev_priv->drm, "Unexpected DE Port interrupt\n"); @@ -2329,6 +2448,9 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) if (iir & GEN8_PIPE_VBLANK) intel_handle_vblank(dev_priv, pipe); + if (iir & GEN9_PIPE_PLANE1_FLIP_DONE) + flip_done_handler(dev_priv, pipe); + if (iir & GEN8_PIPE_CDCLK_CRC_DONE) hsw_pipe_crc_irq_handler(dev_priv, pipe); @@ -2631,12 +2753,47 @@ int ilk_enable_vblank(struct drm_crtc *crtc) return 0; } +static bool gen11_dsi_configure_te(struct intel_crtc *intel_crtc, + bool enable) +{ + struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev); + enum port port; + u32 tmp; + + if (!(intel_crtc->mode_flags & + (I915_MODE_FLAG_DSI_USE_TE1 | I915_MODE_FLAG_DSI_USE_TE0))) + return false; + + /* for dual link cases we consider TE from slave */ + if (intel_crtc->mode_flags & I915_MODE_FLAG_DSI_USE_TE1) + port = PORT_B; + else + port = PORT_A; + + tmp = I915_READ(DSI_INTR_MASK_REG(port)); + if (enable) + tmp &= ~DSI_TE_EVENT; + else + tmp |= DSI_TE_EVENT; + + I915_WRITE(DSI_INTR_MASK_REG(port), tmp); + + tmp = I915_READ(DSI_INTR_IDENT_REG(port)); + I915_WRITE(DSI_INTR_IDENT_REG(port), tmp); + + return true; +} + int bdw_enable_vblank(struct drm_crtc *crtc) { struct drm_i915_private *dev_priv = to_i915(crtc->dev); - enum pipe pipe = to_intel_crtc(crtc)->pipe; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + enum pipe pipe = intel_crtc->pipe; unsigned long irqflags; + if (gen11_dsi_configure_te(intel_crtc, true)) + return 0; + spin_lock_irqsave(&dev_priv->irq_lock, irqflags); bdw_enable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK); spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); @@ -2650,6 +2807,19 @@ int bdw_enable_vblank(struct drm_crtc *crtc) return 0; } +void skl_enable_flip_done(struct intel_crtc *crtc) +{ + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + enum pipe pipe = crtc->pipe; + unsigned long irqflags; + + spin_lock_irqsave(&i915->irq_lock, irqflags); + + bdw_enable_pipe_irq(i915, pipe, GEN9_PIPE_PLANE1_FLIP_DONE); + + spin_unlock_irqrestore(&i915->irq_lock, irqflags); +} + /* Called from drm generic code, passed 'crtc' which * we use as a pipe index */ @@ -2702,14 +2872,31 @@ void ilk_disable_vblank(struct drm_crtc *crtc) void bdw_disable_vblank(struct drm_crtc *crtc) { struct drm_i915_private *dev_priv = to_i915(crtc->dev); - enum pipe pipe = to_intel_crtc(crtc)->pipe; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + enum pipe pipe = intel_crtc->pipe; unsigned long irqflags; + if (gen11_dsi_configure_te(intel_crtc, false)) + return; + spin_lock_irqsave(&dev_priv->irq_lock, irqflags); bdw_disable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK); spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); } +void skl_disable_flip_done(struct intel_crtc *crtc) +{ + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + enum pipe pipe = crtc->pipe; + unsigned long irqflags; + + spin_lock_irqsave(&i915->irq_lock, irqflags); + + bdw_disable_pipe_irq(i915, pipe, GEN9_PIPE_PLANE1_FLIP_DONE); + + spin_unlock_irqrestore(&i915->irq_lock, irqflags); +} + static void ibx_irq_reset(struct drm_i915_private *dev_priv) { struct intel_uncore *uncore = &dev_priv->uncore; @@ -2723,24 +2910,6 @@ static void ibx_irq_reset(struct drm_i915_private *dev_priv) I915_WRITE(SERR_INT, 0xffffffff); } -/* - * SDEIER is also touched by the interrupt handler to work around missed PCH - * interrupts. Hence we can't update it after the interrupt handler is enabled - - * instead we unconditionally enable all PCH interrupt sources here, but then - * only unmask them as needed with SDEIMR. - * - * This function needs to be called before interrupts are enabled. - */ -static void ibx_irq_pre_postinstall(struct drm_i915_private *dev_priv) -{ - if (HAS_PCH_NOP(dev_priv)) - return; - - drm_WARN_ON(&dev_priv->drm, I915_READ(SDEIER) != 0); - I915_WRITE(SDEIER, 0xffffffff); - POSTING_READ(SDEIER); -} - static void vlv_display_irq_reset(struct drm_i915_private *dev_priv) { struct intel_uncore *uncore = &dev_priv->uncore; @@ -2797,6 +2966,8 @@ static void ilk_irq_reset(struct drm_i915_private *dev_priv) struct intel_uncore *uncore = &dev_priv->uncore; GEN3_IRQ_RESET(uncore, DE); + dev_priv->irq_mask = ~0u; + if (IS_GEN(dev_priv, 7)) intel_uncore_write(uncore, GEN7_ERR_INT, 0xffffffff); @@ -2887,8 +3058,10 @@ static void gen11_display_irq_reset(struct drm_i915_private *dev_priv) if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) GEN3_IRQ_RESET(uncore, SDE); - /* Wa_14010685332:icl,jsl,ehl,tgl,rkl */ - if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) { + /* Wa_14010685332:cnp/cmp,tgp,adp */ + if (INTEL_PCH_TYPE(dev_priv) == PCH_CNP || + (INTEL_PCH_TYPE(dev_priv) >= PCH_TGP && + INTEL_PCH_TYPE(dev_priv) < PCH_DG1)) { intel_uncore_rmw(uncore, SOUTH_CHICKEN1, SBCLK_RUN_REFCLK_DIS, SBCLK_RUN_REFCLK_DIS); intel_uncore_rmw(uncore, SOUTH_CHICKEN1, @@ -2920,6 +3093,9 @@ void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv, u32 extra_ier = GEN8_PIPE_VBLANK | GEN8_PIPE_FIFO_UNDERRUN; enum pipe pipe; + if (INTEL_GEN(dev_priv) >= 9) + extra_ier |= GEN9_PIPE_PLANE1_FLIP_DONE; + spin_lock_irq(&dev_priv->irq_lock); if (!intel_irqs_enabled(dev_priv)) { @@ -2974,29 +3150,29 @@ static void cherryview_irq_reset(struct drm_i915_private *dev_priv) spin_unlock_irq(&dev_priv->irq_lock); } -static u32 intel_hpd_enabled_irqs(struct drm_i915_private *dev_priv, - const u32 hpd[HPD_NUM_PINS]) +static u32 ibx_hotplug_enables(struct drm_i915_private *i915, + enum hpd_pin pin) { - struct intel_encoder *encoder; - u32 enabled_irqs = 0; - - for_each_intel_encoder(&dev_priv->drm, encoder) - if (dev_priv->hotplug.stats[encoder->hpd_pin].state == HPD_ENABLED) - enabled_irqs |= hpd[encoder->hpd_pin]; - - return enabled_irqs; -} - -static u32 intel_hpd_hotplug_irqs(struct drm_i915_private *dev_priv, - const u32 hpd[HPD_NUM_PINS]) -{ - struct intel_encoder *encoder; - u32 hotplug_irqs = 0; - - for_each_intel_encoder(&dev_priv->drm, encoder) - hotplug_irqs |= hpd[encoder->hpd_pin]; - - return hotplug_irqs; + switch (pin) { + case HPD_PORT_A: + /* + * When CPU and PCH are on the same package, port A + * HPD must be enabled in both north and south. + */ + return HAS_PCH_LPT_LP(i915) ? + PORTA_HOTPLUG_ENABLE : 0; + case HPD_PORT_B: + return PORTB_HOTPLUG_ENABLE | + PORTB_PULSE_DURATION_2ms; + case HPD_PORT_C: + return PORTC_HOTPLUG_ENABLE | + PORTC_PULSE_DURATION_2ms; + case HPD_PORT_D: + return PORTD_HOTPLUG_ENABLE | + PORTD_PULSE_DURATION_2ms; + default: + return 0; + } } static void ibx_hpd_detection_setup(struct drm_i915_private *dev_priv) @@ -3009,18 +3185,14 @@ static void ibx_hpd_detection_setup(struct drm_i915_private *dev_priv) * The pulse duration bits are reserved on LPT+. */ hotplug = I915_READ(PCH_PORT_HOTPLUG); - hotplug &= ~(PORTB_PULSE_DURATION_MASK | + hotplug &= ~(PORTA_HOTPLUG_ENABLE | + PORTB_HOTPLUG_ENABLE | + PORTC_HOTPLUG_ENABLE | + PORTD_HOTPLUG_ENABLE | + PORTB_PULSE_DURATION_MASK | PORTC_PULSE_DURATION_MASK | PORTD_PULSE_DURATION_MASK); - hotplug |= PORTB_HOTPLUG_ENABLE | PORTB_PULSE_DURATION_2ms; - hotplug |= PORTC_HOTPLUG_ENABLE | PORTC_PULSE_DURATION_2ms; - hotplug |= PORTD_HOTPLUG_ENABLE | PORTD_PULSE_DURATION_2ms; - /* - * When CPU and PCH are on the same package, port A - * HPD must be enabled in both north and south. - */ - if (HAS_PCH_LPT_LP(dev_priv)) - hotplug |= PORTA_HOTPLUG_ENABLE; + hotplug |= intel_hpd_hotplug_enables(dev_priv, ibx_hotplug_enables); I915_WRITE(PCH_PORT_HOTPLUG, hotplug); } @@ -3036,28 +3208,65 @@ static void ibx_hpd_irq_setup(struct drm_i915_private *dev_priv) ibx_hpd_detection_setup(dev_priv); } -static void icp_ddi_hpd_detection_setup(struct drm_i915_private *dev_priv, - u32 enable_mask) +static u32 icp_ddi_hotplug_enables(struct drm_i915_private *i915, + enum hpd_pin pin) +{ + switch (pin) { + case HPD_PORT_A: + case HPD_PORT_B: + case HPD_PORT_C: + case HPD_PORT_D: + return SHOTPLUG_CTL_DDI_HPD_ENABLE(pin); + default: + return 0; + } +} + +static u32 icp_tc_hotplug_enables(struct drm_i915_private *i915, + enum hpd_pin pin) +{ + switch (pin) { + case HPD_PORT_TC1: + case HPD_PORT_TC2: + case HPD_PORT_TC3: + case HPD_PORT_TC4: + case HPD_PORT_TC5: + case HPD_PORT_TC6: + return ICP_TC_HPD_ENABLE(pin); + default: + return 0; + } +} + +static void icp_ddi_hpd_detection_setup(struct drm_i915_private *dev_priv) { u32 hotplug; hotplug = I915_READ(SHOTPLUG_CTL_DDI); - hotplug |= enable_mask; + hotplug &= ~(SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_A) | + SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_B) | + SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_C) | + SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_D)); + hotplug |= intel_hpd_hotplug_enables(dev_priv, icp_ddi_hotplug_enables); I915_WRITE(SHOTPLUG_CTL_DDI, hotplug); } -static void icp_tc_hpd_detection_setup(struct drm_i915_private *dev_priv, - u32 enable_mask) +static void icp_tc_hpd_detection_setup(struct drm_i915_private *dev_priv) { u32 hotplug; hotplug = I915_READ(SHOTPLUG_CTL_TC); - hotplug |= enable_mask; + hotplug &= ~(ICP_TC_HPD_ENABLE(HPD_PORT_TC1) | + ICP_TC_HPD_ENABLE(HPD_PORT_TC2) | + ICP_TC_HPD_ENABLE(HPD_PORT_TC3) | + ICP_TC_HPD_ENABLE(HPD_PORT_TC4) | + ICP_TC_HPD_ENABLE(HPD_PORT_TC5) | + ICP_TC_HPD_ENABLE(HPD_PORT_TC6)); + hotplug |= intel_hpd_hotplug_enables(dev_priv, icp_tc_hotplug_enables); I915_WRITE(SHOTPLUG_CTL_TC, hotplug); } -static void icp_hpd_irq_setup(struct drm_i915_private *dev_priv, - u32 ddi_enable_mask, u32 tc_enable_mask) +static void icp_hpd_irq_setup(struct drm_i915_private *dev_priv) { u32 hotplug_irqs, enabled_irqs; @@ -3069,52 +3278,67 @@ static void icp_hpd_irq_setup(struct drm_i915_private *dev_priv, ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs); - icp_ddi_hpd_detection_setup(dev_priv, ddi_enable_mask); - if (tc_enable_mask) - icp_tc_hpd_detection_setup(dev_priv, tc_enable_mask); + icp_ddi_hpd_detection_setup(dev_priv); + icp_tc_hpd_detection_setup(dev_priv); } -/* - * EHL doesn't need most of gen11_hpd_irq_setup, it's handling only the - * equivalent of SDE. - */ -static void mcc_hpd_irq_setup(struct drm_i915_private *dev_priv) +static u32 gen11_hotplug_enables(struct drm_i915_private *i915, + enum hpd_pin pin) { - icp_hpd_irq_setup(dev_priv, - ICP_DDI_HPD_ENABLE_MASK, ICP_TC_HPD_ENABLE(PORT_TC1)); + switch (pin) { + case HPD_PORT_TC1: + case HPD_PORT_TC2: + case HPD_PORT_TC3: + case HPD_PORT_TC4: + case HPD_PORT_TC5: + case HPD_PORT_TC6: + return GEN11_HOTPLUG_CTL_ENABLE(pin); + default: + return 0; + } } -/* - * JSP behaves exactly the same as MCC above except that port C is mapped to - * the DDI-C pins instead of the TC1 pins. This means we should follow TGP's - * masks & tables rather than ICP's masks & tables. - */ -static void jsp_hpd_irq_setup(struct drm_i915_private *dev_priv) +static void dg1_hpd_irq_setup(struct drm_i915_private *dev_priv) { - icp_hpd_irq_setup(dev_priv, - TGP_DDI_HPD_ENABLE_MASK, 0); + u32 val; + + val = I915_READ(SOUTH_CHICKEN1); + val |= (INVERT_DDIA_HPD | + INVERT_DDIB_HPD | + INVERT_DDIC_HPD | + INVERT_DDID_HPD); + I915_WRITE(SOUTH_CHICKEN1, val); + + icp_hpd_irq_setup(dev_priv); } -static void gen11_hpd_detection_setup(struct drm_i915_private *dev_priv) +static void gen11_tc_hpd_detection_setup(struct drm_i915_private *dev_priv) { u32 hotplug; hotplug = I915_READ(GEN11_TC_HOTPLUG_CTL); - hotplug |= GEN11_HOTPLUG_CTL_ENABLE(PORT_TC1) | - GEN11_HOTPLUG_CTL_ENABLE(PORT_TC2) | - GEN11_HOTPLUG_CTL_ENABLE(PORT_TC3) | - GEN11_HOTPLUG_CTL_ENABLE(PORT_TC4) | - GEN11_HOTPLUG_CTL_ENABLE(PORT_TC5) | - GEN11_HOTPLUG_CTL_ENABLE(PORT_TC6); + hotplug &= ~(GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC1) | + GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC2) | + GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC3) | + GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC4) | + GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC5) | + GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC6)); + hotplug |= intel_hpd_hotplug_enables(dev_priv, gen11_hotplug_enables); I915_WRITE(GEN11_TC_HOTPLUG_CTL, hotplug); +} + +static void gen11_tbt_hpd_detection_setup(struct drm_i915_private *dev_priv) +{ + u32 hotplug; hotplug = I915_READ(GEN11_TBT_HOTPLUG_CTL); - hotplug |= GEN11_HOTPLUG_CTL_ENABLE(PORT_TC1) | - GEN11_HOTPLUG_CTL_ENABLE(PORT_TC2) | - GEN11_HOTPLUG_CTL_ENABLE(PORT_TC3) | - GEN11_HOTPLUG_CTL_ENABLE(PORT_TC4) | - GEN11_HOTPLUG_CTL_ENABLE(PORT_TC5) | - GEN11_HOTPLUG_CTL_ENABLE(PORT_TC6); + hotplug &= ~(GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC1) | + GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC2) | + GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC3) | + GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC4) | + GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC5) | + GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC6)); + hotplug |= intel_hpd_hotplug_enables(dev_priv, gen11_hotplug_enables); I915_WRITE(GEN11_TBT_HOTPLUG_CTL, hotplug); } @@ -3132,14 +3356,39 @@ static void gen11_hpd_irq_setup(struct drm_i915_private *dev_priv) I915_WRITE(GEN11_DE_HPD_IMR, val); POSTING_READ(GEN11_DE_HPD_IMR); - gen11_hpd_detection_setup(dev_priv); + gen11_tc_hpd_detection_setup(dev_priv); + gen11_tbt_hpd_detection_setup(dev_priv); - if (INTEL_PCH_TYPE(dev_priv) >= PCH_TGP) - icp_hpd_irq_setup(dev_priv, - TGP_DDI_HPD_ENABLE_MASK, TGP_TC_HPD_ENABLE_MASK); - else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) - icp_hpd_irq_setup(dev_priv, - ICP_DDI_HPD_ENABLE_MASK, ICP_TC_HPD_ENABLE_MASK); + if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) + icp_hpd_irq_setup(dev_priv); +} + +static u32 spt_hotplug_enables(struct drm_i915_private *i915, + enum hpd_pin pin) +{ + switch (pin) { + case HPD_PORT_A: + return PORTA_HOTPLUG_ENABLE; + case HPD_PORT_B: + return PORTB_HOTPLUG_ENABLE; + case HPD_PORT_C: + return PORTC_HOTPLUG_ENABLE; + case HPD_PORT_D: + return PORTD_HOTPLUG_ENABLE; + default: + return 0; + } +} + +static u32 spt_hotplug2_enables(struct drm_i915_private *i915, + enum hpd_pin pin) +{ + switch (pin) { + case HPD_PORT_E: + return PORTE_HOTPLUG_ENABLE; + default: + return 0; + } } static void spt_hpd_detection_setup(struct drm_i915_private *dev_priv) @@ -3156,14 +3405,16 @@ static void spt_hpd_detection_setup(struct drm_i915_private *dev_priv) /* Enable digital hotplug on the PCH */ hotplug = I915_READ(PCH_PORT_HOTPLUG); - hotplug |= PORTA_HOTPLUG_ENABLE | - PORTB_HOTPLUG_ENABLE | - PORTC_HOTPLUG_ENABLE | - PORTD_HOTPLUG_ENABLE; + hotplug &= ~(PORTA_HOTPLUG_ENABLE | + PORTB_HOTPLUG_ENABLE | + PORTC_HOTPLUG_ENABLE | + PORTD_HOTPLUG_ENABLE); + hotplug |= intel_hpd_hotplug_enables(dev_priv, spt_hotplug_enables); I915_WRITE(PCH_PORT_HOTPLUG, hotplug); hotplug = I915_READ(PCH_PORT_HOTPLUG2); - hotplug |= PORTE_HOTPLUG_ENABLE; + hotplug &= ~PORTE_HOTPLUG_ENABLE; + hotplug |= intel_hpd_hotplug_enables(dev_priv, spt_hotplug2_enables); I915_WRITE(PCH_PORT_HOTPLUG2, hotplug); } @@ -3182,6 +3433,18 @@ static void spt_hpd_irq_setup(struct drm_i915_private *dev_priv) spt_hpd_detection_setup(dev_priv); } +static u32 ilk_hotplug_enables(struct drm_i915_private *i915, + enum hpd_pin pin) +{ + switch (pin) { + case HPD_PORT_A: + return DIGITAL_PORTA_HOTPLUG_ENABLE | + DIGITAL_PORTA_PULSE_DURATION_2ms; + default: + return 0; + } +} + static void ilk_hpd_detection_setup(struct drm_i915_private *dev_priv) { u32 hotplug; @@ -3192,9 +3455,9 @@ static void ilk_hpd_detection_setup(struct drm_i915_private *dev_priv) * The pulse duration bits are reserved on HSW+. */ hotplug = I915_READ(DIGITAL_PORT_HOTPLUG_CNTRL); - hotplug &= ~DIGITAL_PORTA_PULSE_DURATION_MASK; - hotplug |= DIGITAL_PORTA_HOTPLUG_ENABLE | - DIGITAL_PORTA_PULSE_DURATION_2ms; + hotplug &= ~(DIGITAL_PORTA_HOTPLUG_ENABLE | + DIGITAL_PORTA_PULSE_DURATION_MASK); + hotplug |= intel_hpd_hotplug_enables(dev_priv, ilk_hotplug_enables); I915_WRITE(DIGITAL_PORT_HOTPLUG_CNTRL, hotplug); } @@ -3215,41 +3478,45 @@ static void ilk_hpd_irq_setup(struct drm_i915_private *dev_priv) ibx_hpd_irq_setup(dev_priv); } -static void __bxt_hpd_detection_setup(struct drm_i915_private *dev_priv, - u32 enabled_irqs) +static u32 bxt_hotplug_enables(struct drm_i915_private *i915, + enum hpd_pin pin) { u32 hotplug; - hotplug = I915_READ(PCH_PORT_HOTPLUG); - hotplug |= PORTA_HOTPLUG_ENABLE | - PORTB_HOTPLUG_ENABLE | - PORTC_HOTPLUG_ENABLE; - - drm_dbg_kms(&dev_priv->drm, - "Invert bit setting: hp_ctl:%x hp_port:%x\n", - hotplug, enabled_irqs); - hotplug &= ~BXT_DDI_HPD_INVERT_MASK; - - /* - * For BXT invert bit has to be set based on AOB design - * for HPD detection logic, update it based on VBT fields. - */ - if ((enabled_irqs & BXT_DE_PORT_HP_DDIA) && - intel_bios_is_port_hpd_inverted(dev_priv, PORT_A)) - hotplug |= BXT_DDIA_HPD_INVERT; - if ((enabled_irqs & BXT_DE_PORT_HP_DDIB) && - intel_bios_is_port_hpd_inverted(dev_priv, PORT_B)) - hotplug |= BXT_DDIB_HPD_INVERT; - if ((enabled_irqs & BXT_DE_PORT_HP_DDIC) && - intel_bios_is_port_hpd_inverted(dev_priv, PORT_C)) - hotplug |= BXT_DDIC_HPD_INVERT; - - I915_WRITE(PCH_PORT_HOTPLUG, hotplug); + switch (pin) { + case HPD_PORT_A: + hotplug = PORTA_HOTPLUG_ENABLE; + if (intel_bios_is_port_hpd_inverted(i915, PORT_A)) + hotplug |= BXT_DDIA_HPD_INVERT; + return hotplug; + case HPD_PORT_B: + hotplug = PORTB_HOTPLUG_ENABLE; + if (intel_bios_is_port_hpd_inverted(i915, PORT_B)) + hotplug |= BXT_DDIB_HPD_INVERT; + return hotplug; + case HPD_PORT_C: + hotplug = PORTC_HOTPLUG_ENABLE; + if (intel_bios_is_port_hpd_inverted(i915, PORT_C)) + hotplug |= BXT_DDIC_HPD_INVERT; + return hotplug; + default: + return 0; + } } static void bxt_hpd_detection_setup(struct drm_i915_private *dev_priv) { - __bxt_hpd_detection_setup(dev_priv, BXT_DE_PORT_HOTPLUG_MASK); + u32 hotplug; + + hotplug = I915_READ(PCH_PORT_HOTPLUG); + hotplug &= ~(PORTA_HOTPLUG_ENABLE | + PORTB_HOTPLUG_ENABLE | + PORTC_HOTPLUG_ENABLE | + BXT_DDIA_HPD_INVERT | + BXT_DDIB_HPD_INVERT | + BXT_DDIC_HPD_INVERT); + hotplug |= intel_hpd_hotplug_enables(dev_priv, bxt_hotplug_enables); + I915_WRITE(PCH_PORT_HOTPLUG, hotplug); } static void bxt_hpd_irq_setup(struct drm_i915_private *dev_priv) @@ -3261,11 +3528,23 @@ static void bxt_hpd_irq_setup(struct drm_i915_private *dev_priv) bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs); - __bxt_hpd_detection_setup(dev_priv, enabled_irqs); + bxt_hpd_detection_setup(dev_priv); } +/* + * SDEIER is also touched by the interrupt handler to work around missed PCH + * interrupts. Hence we can't update it after the interrupt handler is enabled - + * instead we unconditionally enable all PCH interrupt sources here, but then + * only unmask them as needed with SDEIMR. + * + * Note that we currently do this after installing the interrupt handler, + * but before we enable the master interrupt. That should be sufficient + * to avoid races with the irq handler, assuming we have MSI. Shared legacy + * interrupts could still race. + */ static void ibx_irq_postinstall(struct drm_i915_private *dev_priv) { + struct intel_uncore *uncore = &dev_priv->uncore; u32 mask; if (HAS_PCH_NOP(dev_priv)) @@ -3278,14 +3557,7 @@ static void ibx_irq_postinstall(struct drm_i915_private *dev_priv) else mask = SDE_GMBUS_CPT; - gen3_assert_iir_is_zero(&dev_priv->uncore, SDEIIR); - I915_WRITE(SDEIMR, ~mask); - - if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv) || - HAS_PCH_LPT(dev_priv)) - ibx_hpd_detection_setup(dev_priv); - else - spt_hpd_detection_setup(dev_priv); + GEN3_IRQ_INIT(uncore, SDE, ~mask, 0xffffffff); } static void ilk_irq_postinstall(struct drm_i915_private *dev_priv) @@ -3303,7 +3575,7 @@ static void ilk_irq_postinstall(struct drm_i915_private *dev_priv) display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT | DE_AUX_CHANNEL_A | DE_PIPEB_CRC_DONE | DE_PIPEA_CRC_DONE | DE_POISON); - extra_mask = (DE_PIPEA_VBLANK | DE_PIPEB_VBLANK | DE_PCU_EVENT | + extra_mask = (DE_PIPEA_VBLANK | DE_PIPEB_VBLANK | DE_PIPEB_FIFO_UNDERRUN | DE_PIPEA_FIFO_UNDERRUN | DE_DP_A_HOTPLUG); } @@ -3313,29 +3585,17 @@ static void ilk_irq_postinstall(struct drm_i915_private *dev_priv) display_mask |= DE_EDP_PSR_INT_HSW; } - dev_priv->irq_mask = ~display_mask; + if (IS_IRONLAKE_M(dev_priv)) + extra_mask |= DE_PCU_EVENT; - ibx_irq_pre_postinstall(dev_priv); + dev_priv->irq_mask = ~display_mask; - GEN3_IRQ_INIT(uncore, DE, dev_priv->irq_mask, - display_mask | extra_mask); + ibx_irq_postinstall(dev_priv); gen5_gt_irq_postinstall(&dev_priv->gt); - ilk_hpd_detection_setup(dev_priv); - - ibx_irq_postinstall(dev_priv); - - if (IS_IRONLAKE_M(dev_priv)) { - /* Enable PCU event interrupts - * - * spinlocking not required here for correctness since interrupt - * setup is guaranteed to run in single-threaded context. But we - * need it to make the assert_spin_locked happy. */ - spin_lock_irq(&dev_priv->irq_lock); - ilk_enable_display_irq(dev_priv, DE_PCU_EVENT); - spin_unlock_irq(&dev_priv->irq_lock); - } + GEN3_IRQ_INIT(uncore, DE, dev_priv->irq_mask, + display_mask | extra_mask); } void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv) @@ -3400,14 +3660,24 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) if (IS_GEN9_LP(dev_priv)) de_port_masked |= BXT_DE_PORT_GMBUS; + if (INTEL_GEN(dev_priv) >= 11) { + enum port port; + + if (intel_bios_is_dsi_present(dev_priv, &port)) + de_port_masked |= DSI0_TE | DSI1_TE; + } + de_pipe_enables = de_pipe_masked | GEN8_PIPE_VBLANK | GEN8_PIPE_FIFO_UNDERRUN; + if (INTEL_GEN(dev_priv) >= 9) + de_pipe_enables |= GEN9_PIPE_PLANE1_FLIP_DONE; + de_port_enables = de_port_masked; if (IS_GEN9_LP(dev_priv)) de_port_enables |= BXT_DE_PORT_HOTPLUG_MASK; else if (IS_BROADWELL(dev_priv)) - de_port_enables |= GEN8_PORT_DP_A_HOTPLUG; + de_port_enables |= BDW_DE_PORT_HOTPLUG_MASK; if (INTEL_GEN(dev_priv) >= 12) { enum transcoder trans; @@ -3445,51 +3715,26 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) GEN3_IRQ_INIT(uncore, GEN11_DE_HPD_, ~de_hpd_masked, de_hpd_enables); - gen11_hpd_detection_setup(dev_priv); - } else if (IS_GEN9_LP(dev_priv)) { - bxt_hpd_detection_setup(dev_priv); - } else if (IS_BROADWELL(dev_priv)) { - ilk_hpd_detection_setup(dev_priv); } } static void gen8_irq_postinstall(struct drm_i915_private *dev_priv) { if (HAS_PCH_SPLIT(dev_priv)) - ibx_irq_pre_postinstall(dev_priv); + ibx_irq_postinstall(dev_priv); gen8_gt_irq_postinstall(&dev_priv->gt); gen8_de_irq_postinstall(dev_priv); - if (HAS_PCH_SPLIT(dev_priv)) - ibx_irq_postinstall(dev_priv); - gen8_master_intr_enable(dev_priv->uncore.regs); } static void icp_irq_postinstall(struct drm_i915_private *dev_priv) { + struct intel_uncore *uncore = &dev_priv->uncore; u32 mask = SDE_GMBUS_ICP; - drm_WARN_ON(&dev_priv->drm, I915_READ(SDEIER) != 0); - I915_WRITE(SDEIER, 0xffffffff); - POSTING_READ(SDEIER); - - gen3_assert_iir_is_zero(&dev_priv->uncore, SDEIIR); - I915_WRITE(SDEIMR, ~mask); - - if (HAS_PCH_TGP(dev_priv)) { - icp_ddi_hpd_detection_setup(dev_priv, TGP_DDI_HPD_ENABLE_MASK); - icp_tc_hpd_detection_setup(dev_priv, TGP_TC_HPD_ENABLE_MASK); - } else if (HAS_PCH_JSP(dev_priv)) { - icp_ddi_hpd_detection_setup(dev_priv, TGP_DDI_HPD_ENABLE_MASK); - } else if (HAS_PCH_MCC(dev_priv)) { - icp_ddi_hpd_detection_setup(dev_priv, ICP_DDI_HPD_ENABLE_MASK); - icp_tc_hpd_detection_setup(dev_priv, ICP_TC_HPD_ENABLE(PORT_TC1)); - } else { - icp_ddi_hpd_detection_setup(dev_priv, ICP_DDI_HPD_ENABLE_MASK); - icp_tc_hpd_detection_setup(dev_priv, ICP_TC_HPD_ENABLE_MASK); - } + GEN3_IRQ_INIT(uncore, SDE, ~mask, 0xffffffff); } static void gen11_irq_postinstall(struct drm_i915_private *dev_priv) @@ -3536,6 +3781,7 @@ static void i8xx_irq_reset(struct drm_i915_private *dev_priv) i9xx_pipestat_irq_reset(dev_priv); GEN2_IRQ_RESET(uncore); + dev_priv->irq_mask = ~0u; } static void i8xx_irq_postinstall(struct drm_i915_private *dev_priv) @@ -3705,6 +3951,7 @@ static void i915_irq_reset(struct drm_i915_private *dev_priv) i9xx_pipestat_irq_reset(dev_priv); GEN3_IRQ_RESET(uncore, GEN2_); + dev_priv->irq_mask = ~0u; } static void i915_irq_postinstall(struct drm_i915_private *dev_priv) @@ -3811,6 +4058,7 @@ static void i965_irq_reset(struct drm_i915_private *dev_priv) i9xx_pipestat_irq_reset(dev_priv); GEN3_IRQ_RESET(uncore, GEN2_); + dev_priv->irq_mask = ~0u; } static void i965_irq_postinstall(struct drm_i915_private *dev_priv) @@ -3958,10 +4206,6 @@ void intel_irq_init(struct drm_i915_private *dev_priv) struct drm_device *dev = &dev_priv->drm; int i; - intel_hpd_init_pins(dev_priv); - - intel_hpd_init_work(dev_priv); - INIT_WORK(&dev_priv->l3_parity.error_work, ivb_parity_work); for (i = 0; i < MAX_L3_SLICES; ++i) dev_priv->l3_parity.remap_info[i] = NULL; @@ -3970,6 +4214,13 @@ void intel_irq_init(struct drm_i915_private *dev_priv) if (HAS_GT_UC(dev_priv) && INTEL_GEN(dev_priv) < 11) dev_priv->gt.pm_guc_events = GUC_INTR_GUC2HOST << 16; + if (!HAS_DISPLAY(dev_priv)) + return; + + intel_hpd_init_pins(dev_priv); + + intel_hpd_init_work(dev_priv); + dev->vblank_disable_immediate = true; /* Most platforms treat the display irq block as an always-on @@ -3991,23 +4242,18 @@ void intel_irq_init(struct drm_i915_private *dev_priv) */ dev_priv->hotplug.hpd_short_storm_enabled = !HAS_DP_MST(dev_priv); - if (HAS_GMCH(dev_priv)) { - if (I915_HAS_HOTPLUG(dev_priv)) - dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup; - } else { - if (HAS_PCH_JSP(dev_priv)) - dev_priv->display.hpd_irq_setup = jsp_hpd_irq_setup; - else if (HAS_PCH_MCC(dev_priv)) - dev_priv->display.hpd_irq_setup = mcc_hpd_irq_setup; - else if (INTEL_GEN(dev_priv) >= 11) - dev_priv->display.hpd_irq_setup = gen11_hpd_irq_setup; - else if (IS_GEN9_LP(dev_priv)) - dev_priv->display.hpd_irq_setup = bxt_hpd_irq_setup; - else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT) - dev_priv->display.hpd_irq_setup = spt_hpd_irq_setup; - else - dev_priv->display.hpd_irq_setup = ilk_hpd_irq_setup; - } + if (HAS_PCH_DG1(dev_priv)) + dev_priv->display.hpd_irq_setup = dg1_hpd_irq_setup; + else if (INTEL_GEN(dev_priv) >= 11) + dev_priv->display.hpd_irq_setup = gen11_hpd_irq_setup; + else if (IS_GEN9_LP(dev_priv)) + dev_priv->display.hpd_irq_setup = bxt_hpd_irq_setup; + else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT) + dev_priv->display.hpd_irq_setup = spt_hpd_irq_setup; + else if (HAS_GMCH(dev_priv) && I915_HAS_HOTPLUG(dev_priv)) + dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup; + else + dev_priv->display.hpd_irq_setup = ilk_hpd_irq_setup; } /** |