]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/gpu/drm/i915/i915_irq.c
Merge tag 'drm-for-v4.11-less-shouty' of git://people.freedesktop.org/~airlied/linux
[karo-tx-linux.git] / drivers / gpu / drm / i915 / i915_irq.c
index f0880afbb87858db7198145f5fedc1bf3150e6a2..e6ffef2f707a01934a3a6f777b1dc7548ef370c8 100644 (file)
@@ -1170,6 +1170,9 @@ static void gen6_pm_rps_work(struct work_struct *work)
                        adj *= 2;
                else /* CHV needs even encode values */
                        adj = IS_CHERRYVIEW(dev_priv) ? 2 : 1;
+
+               if (new_delay >= dev_priv->rps.max_freq_softlimit)
+                       adj = 0;
                /*
                 * For better performance, jump directly
                 * to RPe if we're below it.
@@ -1191,6 +1194,9 @@ static void gen6_pm_rps_work(struct work_struct *work)
                        adj *= 2;
                else /* CHV needs even encode values */
                        adj = IS_CHERRYVIEW(dev_priv) ? -2 : -1;
+
+               if (new_delay <= dev_priv->rps.min_freq_softlimit)
+                       adj = 0;
        } else { /* unknown event */
                adj = 0;
        }
@@ -1553,41 +1559,68 @@ static void display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
 {
        struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe];
        struct intel_pipe_crc_entry *entry;
+       struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
+       struct drm_driver *driver = dev_priv->drm.driver;
+       uint32_t crcs[5];
        int head, tail;
 
        spin_lock(&pipe_crc->lock);
+       if (pipe_crc->source) {
+               if (!pipe_crc->entries) {
+                       spin_unlock(&pipe_crc->lock);
+                       DRM_DEBUG_KMS("spurious interrupt\n");
+                       return;
+               }
 
-       if (!pipe_crc->entries) {
-               spin_unlock(&pipe_crc->lock);
-               DRM_DEBUG_KMS("spurious interrupt\n");
-               return;
-       }
-
-       head = pipe_crc->head;
-       tail = pipe_crc->tail;
+               head = pipe_crc->head;
+               tail = pipe_crc->tail;
 
-       if (CIRC_SPACE(head, tail, INTEL_PIPE_CRC_ENTRIES_NR) < 1) {
-               spin_unlock(&pipe_crc->lock);
-               DRM_ERROR("CRC buffer overflowing\n");
-               return;
-       }
+               if (CIRC_SPACE(head, tail, INTEL_PIPE_CRC_ENTRIES_NR) < 1) {
+                       spin_unlock(&pipe_crc->lock);
+                       DRM_ERROR("CRC buffer overflowing\n");
+                       return;
+               }
 
-       entry = &pipe_crc->entries[head];
+               entry = &pipe_crc->entries[head];
 
-       entry->frame = dev_priv->drm.driver->get_vblank_counter(&dev_priv->drm,
-                                                                pipe);
-       entry->crc[0] = crc0;
-       entry->crc[1] = crc1;
-       entry->crc[2] = crc2;
-       entry->crc[3] = crc3;
-       entry->crc[4] = crc4;
+               entry->frame = driver->get_vblank_counter(&dev_priv->drm, pipe);
+               entry->crc[0] = crc0;
+               entry->crc[1] = crc1;
+               entry->crc[2] = crc2;
+               entry->crc[3] = crc3;
+               entry->crc[4] = crc4;
 
-       head = (head + 1) & (INTEL_PIPE_CRC_ENTRIES_NR - 1);
-       pipe_crc->head = head;
+               head = (head + 1) & (INTEL_PIPE_CRC_ENTRIES_NR - 1);
+               pipe_crc->head = head;
 
-       spin_unlock(&pipe_crc->lock);
+               spin_unlock(&pipe_crc->lock);
 
-       wake_up_interruptible(&pipe_crc->wq);
+               wake_up_interruptible(&pipe_crc->wq);
+       } else {
+               /*
+                * For some not yet identified reason, the first CRC is
+                * bonkers. So let's just wait for the next vblank and read
+                * out the buggy result.
+                *
+                * On CHV sometimes the second CRC is bonkers as well, so
+                * don't trust that one either.
+                */
+               if (pipe_crc->skipped == 0 ||
+                   (IS_CHERRYVIEW(dev_priv) && pipe_crc->skipped == 1)) {
+                       pipe_crc->skipped++;
+                       spin_unlock(&pipe_crc->lock);
+                       return;
+               }
+               spin_unlock(&pipe_crc->lock);
+               crcs[0] = crc0;
+               crcs[1] = crc1;
+               crcs[2] = crc2;
+               crcs[3] = crc3;
+               crcs[4] = crc4;
+               drm_crtc_add_crc_entry(&crtc->base, true,
+                                      drm_accurate_vblank_count(&crtc->base),
+                                      crcs);
+       }
 }
 #else
 static inline void
@@ -1683,8 +1716,8 @@ static void gen9_guc_irq_handler(struct drm_i915_private *dev_priv, u32 gt_iir)
                u32 msg, flush;
 
                msg = I915_READ(SOFT_SCRATCH(15));
-               flush = msg & (GUC2HOST_MSG_CRASH_DUMP_POSTED |
-                              GUC2HOST_MSG_FLUSH_LOG_BUFFER);
+               flush = msg & (INTEL_GUC_RECV_MSG_CRASH_DUMP_POSTED |
+                              INTEL_GUC_RECV_MSG_FLUSH_LOG_BUFFER);
                if (flush) {
                        /* Clear the message bits that are handled */
                        I915_WRITE(SOFT_SCRATCH(15), msg & ~flush);
@@ -2444,7 +2477,7 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl)
                                found = true;
                        }
 
-                       if (IS_BROXTON(dev_priv)) {
+                       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,
@@ -2460,7 +2493,7 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl)
                                }
                        }
 
-                       if (IS_BROXTON(dev_priv) && (iir & BXT_DE_PORT_GMBUS)) {
+                       if (IS_GEN9_LP(dev_priv) && (iir & BXT_DE_PORT_GMBUS)) {
                                gmbus_irq_handler(dev_priv);
                                found = true;
                        }
@@ -2712,12 +2745,13 @@ static void i915_clear_error_registers(struct drm_i915_private *dev_priv)
  * i915_handle_error - handle a gpu error
  * @dev_priv: i915 device private
  * @engine_mask: mask representing engines that are hung
+ * @fmt: Error message format string
+ *
  * Do some basic checking of register state at error time and
  * dump it to the syslog.  Also call i915_capture_error_state() to make
  * sure we get a record and make it available in debugfs.  Fire a uevent
  * so userspace knows something bad happened (should trigger collection
  * of a ring dump etc.).
- * @fmt: Error message format string
  */
 void i915_handle_error(struct drm_i915_private *dev_priv,
                       u32 engine_mask,
@@ -3105,19 +3139,16 @@ static void ibx_hpd_irq_setup(struct drm_i915_private *dev_priv)
        I915_WRITE(PCH_PORT_HOTPLUG, hotplug);
 }
 
-static void spt_hpd_irq_setup(struct drm_i915_private *dev_priv)
+static void spt_hpd_detection_setup(struct drm_i915_private *dev_priv)
 {
-       u32 hotplug_irqs, hotplug, enabled_irqs;
-
-       hotplug_irqs = SDE_HOTPLUG_MASK_SPT;
-       enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd_spt);
-
-       ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs);
+       u32 hotplug;
 
        /* Enable digital hotplug on the PCH */
        hotplug = I915_READ(PCH_PORT_HOTPLUG);
-       hotplug |= PORTD_HOTPLUG_ENABLE | PORTC_HOTPLUG_ENABLE |
-               PORTB_HOTPLUG_ENABLE | PORTA_HOTPLUG_ENABLE;
+       hotplug |= PORTA_HOTPLUG_ENABLE |
+                  PORTB_HOTPLUG_ENABLE |
+                  PORTC_HOTPLUG_ENABLE |
+                  PORTD_HOTPLUG_ENABLE;
        I915_WRITE(PCH_PORT_HOTPLUG, hotplug);
 
        hotplug = I915_READ(PCH_PORT_HOTPLUG2);
@@ -3125,6 +3156,18 @@ static void spt_hpd_irq_setup(struct drm_i915_private *dev_priv)
        I915_WRITE(PCH_PORT_HOTPLUG2, hotplug);
 }
 
+static void spt_hpd_irq_setup(struct drm_i915_private *dev_priv)
+{
+       u32 hotplug_irqs, enabled_irqs;
+
+       hotplug_irqs = SDE_HOTPLUG_MASK_SPT;
+       enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd_spt);
+
+       ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs);
+
+       spt_hpd_detection_setup(dev_priv);
+}
+
 static void ilk_hpd_irq_setup(struct drm_i915_private *dev_priv)
 {
        u32 hotplug_irqs, hotplug, enabled_irqs;
@@ -3159,18 +3202,15 @@ static void ilk_hpd_irq_setup(struct drm_i915_private *dev_priv)
        ibx_hpd_irq_setup(dev_priv);
 }
 
-static void bxt_hpd_irq_setup(struct drm_i915_private *dev_priv)
+static void __bxt_hpd_detection_setup(struct drm_i915_private *dev_priv,
+                                     u32 enabled_irqs)
 {
-       u32 hotplug_irqs, hotplug, enabled_irqs;
-
-       enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd_bxt);
-       hotplug_irqs = BXT_DE_PORT_HOTPLUG_MASK;
-
-       bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs);
+       u32 hotplug;
 
        hotplug = I915_READ(PCH_PORT_HOTPLUG);
-       hotplug |= PORTC_HOTPLUG_ENABLE | PORTB_HOTPLUG_ENABLE |
-               PORTA_HOTPLUG_ENABLE;
+       hotplug |= PORTA_HOTPLUG_ENABLE |
+                  PORTB_HOTPLUG_ENABLE |
+                  PORTC_HOTPLUG_ENABLE;
 
        DRM_DEBUG_KMS("Invert bit setting: hp_ctl:%x hp_port:%x\n",
                      hotplug, enabled_irqs);
@@ -3180,7 +3220,6 @@ static void bxt_hpd_irq_setup(struct drm_i915_private *dev_priv)
         * 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;
@@ -3194,6 +3233,23 @@ static void bxt_hpd_irq_setup(struct drm_i915_private *dev_priv)
        I915_WRITE(PCH_PORT_HOTPLUG, hotplug);
 }
 
+static void bxt_hpd_detection_setup(struct drm_i915_private *dev_priv)
+{
+       __bxt_hpd_detection_setup(dev_priv, BXT_DE_PORT_HOTPLUG_MASK);
+}
+
+static void bxt_hpd_irq_setup(struct drm_i915_private *dev_priv)
+{
+       u32 hotplug_irqs, enabled_irqs;
+
+       enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd_bxt);
+       hotplug_irqs = BXT_DE_PORT_HOTPLUG_MASK;
+
+       bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs);
+
+       __bxt_hpd_detection_setup(dev_priv, enabled_irqs);
+}
+
 static void ibx_irq_postinstall(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = to_i915(dev);
@@ -3209,6 +3265,12 @@ static void ibx_irq_postinstall(struct drm_device *dev)
 
        gen5_assert_iir_is_zero(dev_priv, SDEIIR);
        I915_WRITE(SDEIMR, ~mask);
+
+       if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv) ||
+           HAS_PCH_LPT(dev_priv))
+               ; /* TODO: Enable HPD detection on older PCH platforms too */
+       else
+               spt_hpd_detection_setup(dev_priv);
 }
 
 static void gen5_gt_irq_postinstall(struct drm_device *dev)
@@ -3391,7 +3453,7 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
                                  GEN9_DE_PIPE_IRQ_FAULT_ERRORS;
                de_port_masked |= GEN9_AUX_CHANNEL_B | GEN9_AUX_CHANNEL_C |
                                  GEN9_AUX_CHANNEL_D;
-               if (IS_BROXTON(dev_priv))
+               if (IS_GEN9_LP(dev_priv))
                        de_port_masked |= BXT_DE_PORT_GMBUS;
        } else {
                de_pipe_masked |= GEN8_PIPE_PRIMARY_FLIP_DONE |
@@ -3402,7 +3464,7 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
                                           GEN8_PIPE_FIFO_UNDERRUN;
 
        de_port_enables = de_port_masked;
-       if (IS_BROXTON(dev_priv))
+       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;
@@ -3420,6 +3482,9 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
 
        GEN5_IRQ_INIT(GEN8_DE_PORT_, ~de_port_masked, de_port_enables);
        GEN5_IRQ_INIT(GEN8_DE_MISC_, ~de_misc_masked, de_misc_masked);
+
+       if (IS_GEN9_LP(dev_priv))
+               bxt_hpd_detection_setup(dev_priv);
 }
 
 static int gen8_irq_postinstall(struct drm_device *dev)
@@ -4227,7 +4292,7 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
                dev->driver->irq_uninstall = gen8_irq_uninstall;
                dev->driver->enable_vblank = gen8_enable_vblank;
                dev->driver->disable_vblank = gen8_disable_vblank;
-               if (IS_BROXTON(dev_priv))
+               if (IS_GEN9_LP(dev_priv))
                        dev_priv->display.hpd_irq_setup = bxt_hpd_irq_setup;
                else if (HAS_PCH_SPT(dev_priv) || HAS_PCH_KBP(dev_priv))
                        dev_priv->display.hpd_irq_setup = spt_hpd_irq_setup;