drm/i915: gen7: Disable the RHWO optimization as it can cause GPU hangs.
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / drm / i915 / intel_display.c
index aa43e7be6053bdfd6dc6fd7274d17ccd544b799f..57f90437d08ca56d000a61a2e202c18374d05495 100644 (file)
@@ -2340,6 +2340,7 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc)
        temp |= FDI_LINK_TRAIN_PATTERN_1_IVB;
        temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
        temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B;
+       temp |= FDI_COMPOSITE_SYNC;
        I915_WRITE(reg, temp | FDI_TX_ENABLE);
 
        reg = FDI_RX_CTL(pipe);
@@ -2347,6 +2348,7 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc)
        temp &= ~FDI_LINK_TRAIN_AUTO;
        temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
        temp |= FDI_LINK_TRAIN_PATTERN_1_CPT;
+       temp |= FDI_COMPOSITE_SYNC;
        I915_WRITE(reg, temp | FDI_RX_ENABLE);
 
        POSTING_READ(reg);
@@ -2699,14 +2701,18 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
                I915_WRITE(PF_WIN_SZ(pipe), dev_priv->pch_pf_size);
        }
 
+       /*
+        * On ILK+ LUT must be loaded before the pipe is running but with
+        * clocks enabled
+        */
+       intel_crtc_load_lut(crtc);
+
        intel_enable_pipe(dev_priv, pipe, is_pch_port);
        intel_enable_plane(dev_priv, plane, pipe);
 
        if (is_pch_port)
                ironlake_pch_enable(crtc);
 
-       intel_crtc_load_lut(crtc);
-
        mutex_lock(&dev->struct_mutex);
        intel_update_fbc(dev);
        mutex_unlock(&dev->struct_mutex);
@@ -4305,7 +4311,8 @@ static void intel_update_watermarks(struct drm_device *dev)
 
 static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
 {
-       return dev_priv->lvds_use_ssc && i915_panel_use_ssc;
+       return dev_priv->lvds_use_ssc && i915_panel_use_ssc
+               && !(dev_priv->quirks & QUIRK_LVDS_SSC_DISABLE);
 }
 
 static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
@@ -4965,7 +4972,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
        } else if (is_sdvo && is_tv)
                factor = 20;
 
-       if (clock.m1 < factor * clock.n)
+       if (clock.m < factor * clock.n)
                fp |= FP_CB_TUNE;
 
        dpll = 0;
@@ -5258,7 +5265,7 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
        int i;
 
        /* The clocks have to be on to load the palette. */
-       if (!crtc->enabled)
+       if (!crtc->enabled || !intel_crtc->active)
                return;
 
        /* use legacy palette for Ironlake */
@@ -5329,6 +5336,31 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base)
        I915_WRITE(CURBASE(pipe), base);
 }
 
+static void ivb_update_cursor(struct drm_crtc *crtc, u32 base)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       int pipe = intel_crtc->pipe;
+       bool visible = base != 0;
+
+       if (intel_crtc->cursor_visible != visible) {
+               uint32_t cntl = I915_READ(CURCNTR_IVB(pipe));
+               if (base) {
+                       cntl &= ~CURSOR_MODE;
+                       cntl |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
+               } else {
+                       cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE);
+                       cntl |= CURSOR_MODE_DISABLE;
+               }
+               I915_WRITE(CURCNTR_IVB(pipe), cntl);
+
+               intel_crtc->cursor_visible = visible;
+       }
+       /* and commit changes on next vblank */
+       I915_WRITE(CURBASE_IVB(pipe), base);
+}
+
 /* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */
 static void intel_crtc_update_cursor(struct drm_crtc *crtc,
                                     bool on)
@@ -5376,11 +5408,16 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
        if (!visible && !intel_crtc->cursor_visible)
                return;
 
-       I915_WRITE(CURPOS(pipe), pos);
-       if (IS_845G(dev) || IS_I865G(dev))
-               i845_update_cursor(crtc, base);
-       else
-               i9xx_update_cursor(crtc, base);
+       if (IS_IVYBRIDGE(dev)) {
+               I915_WRITE(CURPOS_IVB(pipe), pos);
+               ivb_update_cursor(crtc, base);
+       } else {
+               I915_WRITE(CURPOS(pipe), pos);
+               if (IS_845G(dev) || IS_I865G(dev))
+                       i845_update_cursor(crtc, base);
+               else
+                       i9xx_update_cursor(crtc, base);
+       }
 
        if (visible)
                intel_mark_busy(dev, to_intel_framebuffer(crtc->fb)->obj);
@@ -6261,6 +6298,197 @@ void intel_prepare_page_flip(struct drm_device *dev, int plane)
        spin_unlock_irqrestore(&dev->event_lock, flags);
 }
 
+static int intel_gen2_queue_flip(struct drm_device *dev,
+                                struct drm_crtc *crtc,
+                                struct drm_framebuffer *fb,
+                                struct drm_i915_gem_object *obj)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       unsigned long offset;
+       u32 flip_mask;
+       int ret;
+
+       ret = intel_pin_and_fence_fb_obj(dev, obj, LP_RING(dev_priv));
+       if (ret)
+               goto out;
+
+       /* Offset into the new buffer for cases of shared fbs between CRTCs */
+       offset = crtc->y * fb->pitch + crtc->x * fb->bits_per_pixel/8;
+
+       ret = BEGIN_LP_RING(6);
+       if (ret)
+               goto out;
+
+       /* Can't queue multiple flips, so wait for the previous
+        * one to finish before executing the next.
+        */
+       if (intel_crtc->plane)
+               flip_mask = MI_WAIT_FOR_PLANE_B_FLIP;
+       else
+               flip_mask = MI_WAIT_FOR_PLANE_A_FLIP;
+       OUT_RING(MI_WAIT_FOR_EVENT | flip_mask);
+       OUT_RING(MI_NOOP);
+       OUT_RING(MI_DISPLAY_FLIP |
+                MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
+       OUT_RING(fb->pitch);
+       OUT_RING(obj->gtt_offset + offset);
+       OUT_RING(MI_NOOP);
+       ADVANCE_LP_RING();
+out:
+       return ret;
+}
+
+static int intel_gen3_queue_flip(struct drm_device *dev,
+                                struct drm_crtc *crtc,
+                                struct drm_framebuffer *fb,
+                                struct drm_i915_gem_object *obj)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       unsigned long offset;
+       u32 flip_mask;
+       int ret;
+
+       ret = intel_pin_and_fence_fb_obj(dev, obj, LP_RING(dev_priv));
+       if (ret)
+               goto out;
+
+       /* Offset into the new buffer for cases of shared fbs between CRTCs */
+       offset = crtc->y * fb->pitch + crtc->x * fb->bits_per_pixel/8;
+
+       ret = BEGIN_LP_RING(6);
+       if (ret)
+               goto out;
+
+       if (intel_crtc->plane)
+               flip_mask = MI_WAIT_FOR_PLANE_B_FLIP;
+       else
+               flip_mask = MI_WAIT_FOR_PLANE_A_FLIP;
+       OUT_RING(MI_WAIT_FOR_EVENT | flip_mask);
+       OUT_RING(MI_NOOP);
+       OUT_RING(MI_DISPLAY_FLIP_I915 |
+                MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
+       OUT_RING(fb->pitch);
+       OUT_RING(obj->gtt_offset + offset);
+       OUT_RING(MI_NOOP);
+
+       ADVANCE_LP_RING();
+out:
+       return ret;
+}
+
+static int intel_gen4_queue_flip(struct drm_device *dev,
+                                struct drm_crtc *crtc,
+                                struct drm_framebuffer *fb,
+                                struct drm_i915_gem_object *obj)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       uint32_t pf, pipesrc;
+       int ret;
+
+       ret = intel_pin_and_fence_fb_obj(dev, obj, LP_RING(dev_priv));
+       if (ret)
+               goto out;
+
+       ret = BEGIN_LP_RING(4);
+       if (ret)
+               goto out;
+
+       /* i965+ uses the linear or tiled offsets from the
+        * Display Registers (which do not change across a page-flip)
+        * so we need only reprogram the base address.
+        */
+       OUT_RING(MI_DISPLAY_FLIP |
+                MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
+       OUT_RING(fb->pitch);
+       OUT_RING(obj->gtt_offset | obj->tiling_mode);
+
+       /* XXX Enabling the panel-fitter across page-flip is so far
+        * untested on non-native modes, so ignore it for now.
+        * pf = I915_READ(pipe == 0 ? PFA_CTL_1 : PFB_CTL_1) & PF_ENABLE;
+        */
+       pf = 0;
+       pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff;
+       OUT_RING(pf | pipesrc);
+       ADVANCE_LP_RING();
+out:
+       return ret;
+}
+
+static int intel_gen6_queue_flip(struct drm_device *dev,
+                                struct drm_crtc *crtc,
+                                struct drm_framebuffer *fb,
+                                struct drm_i915_gem_object *obj)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       uint32_t pf, pipesrc;
+       int ret;
+
+       ret = intel_pin_and_fence_fb_obj(dev, obj, LP_RING(dev_priv));
+       if (ret)
+               goto out;
+
+       ret = BEGIN_LP_RING(4);
+       if (ret)
+               goto out;
+
+       OUT_RING(MI_DISPLAY_FLIP |
+                MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
+       OUT_RING(fb->pitch | obj->tiling_mode);
+       OUT_RING(obj->gtt_offset);
+
+       pf = I915_READ(PF_CTL(intel_crtc->pipe)) & PF_ENABLE;
+       pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff;
+       OUT_RING(pf | pipesrc);
+       ADVANCE_LP_RING();
+out:
+       return ret;
+}
+
+/*
+ * On gen7 we currently use the blit ring because (in early silicon at least)
+ * the render ring doesn't give us interrpts for page flip completion, which
+ * means clients will hang after the first flip is queued.  Fortunately the
+ * blit ring generates interrupts properly, so use it instead.
+ */
+static int intel_gen7_queue_flip(struct drm_device *dev,
+                                struct drm_crtc *crtc,
+                                struct drm_framebuffer *fb,
+                                struct drm_i915_gem_object *obj)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       struct intel_ring_buffer *ring = &dev_priv->ring[BCS];
+       int ret;
+
+       ret = intel_pin_and_fence_fb_obj(dev, obj, ring);
+       if (ret)
+               goto out;
+
+       ret = intel_ring_begin(ring, 4);
+       if (ret)
+               goto out;
+
+       intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | (intel_crtc->plane << 19));
+       intel_ring_emit(ring, (fb->pitch | obj->tiling_mode));
+       intel_ring_emit(ring, (obj->gtt_offset));
+       intel_ring_emit(ring, (MI_NOOP));
+       intel_ring_advance(ring);
+out:
+       return ret;
+}
+
+static int intel_default_queue_flip(struct drm_device *dev,
+                                   struct drm_crtc *crtc,
+                                   struct drm_framebuffer *fb,
+                                   struct drm_i915_gem_object *obj)
+{
+       return -ENODEV;
+}
+
 static int intel_crtc_page_flip(struct drm_crtc *crtc,
                                struct drm_framebuffer *fb,
                                struct drm_pending_vblank_event *event)
@@ -6271,9 +6499,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
        struct drm_i915_gem_object *obj;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct intel_unpin_work *work;
-       unsigned long flags, offset;
-       int pipe = intel_crtc->pipe;
-       u32 pf, pipesrc;
+       unsigned long flags;
        int ret;
 
        work = kzalloc(sizeof *work, GFP_KERNEL);
@@ -6302,9 +6528,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
        obj = intel_fb->obj;
 
        mutex_lock(&dev->struct_mutex);
-       ret = intel_pin_and_fence_fb_obj(dev, obj, LP_RING(dev_priv));
-       if (ret)
-               goto cleanup_work;
 
        /* Reference the objects for the scheduled work. */
        drm_gem_object_reference(&work->old_fb_obj->base);
@@ -6316,91 +6539,18 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
        if (ret)
                goto cleanup_objs;
 
-       if (IS_GEN3(dev) || IS_GEN2(dev)) {
-               u32 flip_mask;
-
-               /* Can't queue multiple flips, so wait for the previous
-                * one to finish before executing the next.
-                */
-               ret = BEGIN_LP_RING(2);
-               if (ret)
-                       goto cleanup_objs;
-
-               if (intel_crtc->plane)
-                       flip_mask = MI_WAIT_FOR_PLANE_B_FLIP;
-               else
-                       flip_mask = MI_WAIT_FOR_PLANE_A_FLIP;
-               OUT_RING(MI_WAIT_FOR_EVENT | flip_mask);
-               OUT_RING(MI_NOOP);
-               ADVANCE_LP_RING();
-       }
-
        work->pending_flip_obj = obj;
 
        work->enable_stall_check = true;
 
-       /* Offset into the new buffer for cases of shared fbs between CRTCs */
-       offset = crtc->y * fb->pitch + crtc->x * fb->bits_per_pixel/8;
-
-       ret = BEGIN_LP_RING(4);
-       if (ret)
-               goto cleanup_objs;
-
        /* Block clients from rendering to the new back buffer until
         * the flip occurs and the object is no longer visible.
         */
        atomic_add(1 << intel_crtc->plane, &work->old_fb_obj->pending_flip);
 
-       switch (INTEL_INFO(dev)->gen) {
-       case 2:
-               OUT_RING(MI_DISPLAY_FLIP |
-                        MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
-               OUT_RING(fb->pitch);
-               OUT_RING(obj->gtt_offset + offset);
-               OUT_RING(MI_NOOP);
-               break;
-
-       case 3:
-               OUT_RING(MI_DISPLAY_FLIP_I915 |
-                        MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
-               OUT_RING(fb->pitch);
-               OUT_RING(obj->gtt_offset + offset);
-               OUT_RING(MI_NOOP);
-               break;
-
-       case 4:
-       case 5:
-               /* i965+ uses the linear or tiled offsets from the
-                * Display Registers (which do not change across a page-flip)
-                * so we need only reprogram the base address.
-                */
-               OUT_RING(MI_DISPLAY_FLIP |
-                        MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
-               OUT_RING(fb->pitch);
-               OUT_RING(obj->gtt_offset | obj->tiling_mode);
-
-               /* XXX Enabling the panel-fitter across page-flip is so far
-                * untested on non-native modes, so ignore it for now.
-                * pf = I915_READ(pipe == 0 ? PFA_CTL_1 : PFB_CTL_1) & PF_ENABLE;
-                */
-               pf = 0;
-               pipesrc = I915_READ(PIPESRC(pipe)) & 0x0fff0fff;
-               OUT_RING(pf | pipesrc);
-               break;
-
-       case 6:
-       case 7:
-               OUT_RING(MI_DISPLAY_FLIP |
-                        MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
-               OUT_RING(fb->pitch | obj->tiling_mode);
-               OUT_RING(obj->gtt_offset);
-
-               pf = I915_READ(PF_CTL(pipe)) & PF_ENABLE;
-               pipesrc = I915_READ(PIPESRC(pipe)) & 0x0fff0fff;
-               OUT_RING(pf | pipesrc);
-               break;
-       }
-       ADVANCE_LP_RING();
+       ret = dev_priv->display.queue_flip(dev, crtc, fb, obj);
+       if (ret)
+               goto cleanup_pending;
 
        mutex_unlock(&dev->struct_mutex);
 
@@ -6408,10 +6558,11 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
 
        return 0;
 
+cleanup_pending:
+       atomic_sub(1 << intel_crtc->plane, &work->old_fb_obj->pending_flip);
 cleanup_objs:
        drm_gem_object_unreference(&work->old_fb_obj->base);
        drm_gem_object_unreference(&obj->base);
-cleanup_work:
        mutex_unlock(&dev->struct_mutex);
 
        spin_lock_irqsave(&dev->event_lock, flags);
@@ -7254,6 +7405,20 @@ static void gen6_init_clock_gating(struct drm_device *dev)
        I915_WRITE(WM2_LP_ILK, 0);
        I915_WRITE(WM1_LP_ILK, 0);
 
+       /* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock
+        * gating disable must be set.  Failure to set it results in
+        * flickering pixels due to Z write ordering failures after
+        * some amount of runtime in the Mesa "fire" demo, and Unigine
+        * Sanctuary and Tropics, and apparently anything else with
+        * alpha test or pixel discard.
+        *
+        * According to the spec, bit 11 (RCCUNIT) must also be set,
+        * but we didn't debug actual testcases to find it out.
+        */
+       I915_WRITE(GEN6_UCGCTL2,
+                  GEN6_RCPBUNIT_CLOCK_GATE_DISABLE |
+                  GEN6_RCCUNIT_CLOCK_GATE_DISABLE);
+
        /*
         * According to the spec the following bits should be
         * set in order to enable memory self-refresh and fbc:
@@ -7292,8 +7457,28 @@ static void ivybridge_init_clock_gating(struct drm_device *dev)
        I915_WRITE(WM2_LP_ILK, 0);
        I915_WRITE(WM1_LP_ILK, 0);
 
+       /* According to the spec, bit 13 (RCZUNIT) must be set on IVB.
+        * This implements the WaDisableRCZUnitClockGating workaround.
+        */
+       I915_WRITE(GEN6_UCGCTL2, GEN6_RCZUNIT_CLOCK_GATE_DISABLE);
+
        I915_WRITE(ILK_DSPCLK_GATE, IVB_VRHUNIT_CLK_GATE);
 
+       /* Apply the WaDisableRHWOOptimizationForRenderHang workaround. */
+       I915_WRITE(GEN7_COMMON_SLICE_CHICKEN1,
+                  GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC);
+
+       /* WaApplyL3ControlAndL3ChickenMode requires those two on Ivy Bridge */
+       I915_WRITE(GEN7_L3CNTLREG1,
+                       GEN7_WA_FOR_GEN7_L3_CONTROL);
+       I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER,
+                       GEN7_WA_L3_CHICKEN_MODE);
+
+       /* This is required by WaCatErrorRejectionIssue */
+       I915_WRITE(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG,
+                       I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) |
+                       GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB);
+
        for_each_pipe(pipe)
                I915_WRITE(DSPCNTR(pipe),
                           I915_READ(DSPCNTR(pipe)) |
@@ -7656,6 +7841,31 @@ static void intel_init_display(struct drm_device *dev)
                else
                        dev_priv->display.get_fifo_size = i830_get_fifo_size;
        }
+
+       /* Default just returns -ENODEV to indicate unsupported */
+       dev_priv->display.queue_flip = intel_default_queue_flip;
+
+       switch (INTEL_INFO(dev)->gen) {
+       case 2:
+               dev_priv->display.queue_flip = intel_gen2_queue_flip;
+               break;
+
+       case 3:
+               dev_priv->display.queue_flip = intel_gen3_queue_flip;
+               break;
+
+       case 4:
+       case 5:
+               dev_priv->display.queue_flip = intel_gen4_queue_flip;
+               break;
+
+       case 6:
+               dev_priv->display.queue_flip = intel_gen6_queue_flip;
+               break;
+       case 7:
+               dev_priv->display.queue_flip = intel_gen7_queue_flip;
+               break;
+       }
 }
 
 /*
@@ -7671,6 +7881,15 @@ static void quirk_pipea_force (struct drm_device *dev)
        DRM_DEBUG_DRIVER("applying pipe a force quirk\n");
 }
 
+/*
+ * Some machines (Lenovo U160) do not work with SSC on LVDS for some reason
+ */
+static void quirk_ssc_force_disable(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       dev_priv->quirks |= QUIRK_LVDS_SSC_DISABLE;
+}
+
 struct intel_quirk {
        int device;
        int subsystem_vendor;
@@ -7699,6 +7918,9 @@ struct intel_quirk intel_quirks[] = {
        /* 855 & before need to leave pipe A & dpll A up */
        { 0x3582, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force },
        { 0x2562, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force },
+
+       /* Lenovo U160 cannot use SSC on LVDS */
+       { 0x0046, 0x17aa, 0x3920, quirk_ssc_force_disable },
 };
 
 static void intel_init_quirks(struct drm_device *dev)
@@ -7787,7 +8009,7 @@ void intel_modeset_init(struct drm_device *dev)
                intel_init_emon(dev);
        }
 
-       if (IS_GEN6(dev))
+       if (IS_GEN6(dev) || IS_GEN7(dev))
                gen6_enable_rps(dev_priv);
 
        INIT_WORK(&dev_priv->idle_work, intel_idle_update);
@@ -7829,7 +8051,7 @@ void intel_modeset_cleanup(struct drm_device *dev)
 
        if (IS_IRONLAKE_M(dev))
                ironlake_disable_drps(dev);
-       if (IS_GEN6(dev))
+       if (IS_GEN6(dev) || IS_GEN7(dev))
                gen6_disable_rps(dev);
 
        if (IS_IRONLAKE_M(dev))