]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - drivers/gpu/drm/i915/intel_display.c
drm/i915: do not use fdi_normal_train on Haswell
[mirror_ubuntu-artful-kernel.git] / drivers / gpu / drm / i915 / intel_display.c
index 6ab195c0097f9bb78a8361863d71ddef0ed73a82..cc910e69f7097d9b4592cc814235f7b9f57120ff 100644 (file)
@@ -784,6 +784,17 @@ intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc,
        return true;
 }
 
+static void ironlake_wait_for_vblank(struct drm_device *dev, int pipe)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 frame, frame_reg = PIPEFRAME(pipe);
+
+       frame = I915_READ(frame_reg);
+
+       if (wait_for(I915_READ_NOTRACE(frame_reg) != frame, 50))
+               DRM_DEBUG_KMS("vblank wait timed out\n");
+}
+
 /**
  * intel_wait_for_vblank - wait for vblank on a given pipe
  * @dev: drm device
@@ -797,6 +808,11 @@ void intel_wait_for_vblank(struct drm_device *dev, int pipe)
        struct drm_i915_private *dev_priv = dev->dev_private;
        int pipestat_reg = PIPESTAT(pipe);
 
+       if (INTEL_INFO(dev)->gen >= 5) {
+               ironlake_wait_for_vblank(dev, pipe);
+               return;
+       }
+
        /* Clear existing vblank status. Note this will clear any other
         * sticky status fields as well.
         *
@@ -849,15 +865,20 @@ void intel_wait_for_pipe_off(struct drm_device *dev, int pipe)
                             100))
                        DRM_DEBUG_KMS("pipe_off wait timed out\n");
        } else {
-               u32 last_line;
+               u32 last_line, line_mask;
                int reg = PIPEDSL(pipe);
                unsigned long timeout = jiffies + msecs_to_jiffies(100);
 
+               if (IS_GEN2(dev))
+                       line_mask = DSL_LINEMASK_GEN2;
+               else
+                       line_mask = DSL_LINEMASK_GEN3;
+
                /* Wait for the display line to settle */
                do {
-                       last_line = I915_READ(reg) & DSL_LINEMASK;
+                       last_line = I915_READ(reg) & line_mask;
                        mdelay(5);
-               } while (((I915_READ(reg) & DSL_LINEMASK) != last_line) &&
+               } while (((I915_READ(reg) & line_mask) != last_line) &&
                         time_after(timeout, jiffies));
                if (time_after(jiffies, timeout))
                        DRM_DEBUG_KMS("pipe_off wait timed out\n");
@@ -1278,6 +1299,69 @@ static void intel_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
        POSTING_READ(reg);
 }
 
+/* SBI access */
+static void
+intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&dev_priv->dpio_lock, flags);
+       if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_READY) == 0,
+                               100)) {
+               DRM_ERROR("timeout waiting for SBI to become ready\n");
+               goto out_unlock;
+       }
+
+       I915_WRITE(SBI_ADDR,
+                       (reg << 16));
+       I915_WRITE(SBI_DATA,
+                       value);
+       I915_WRITE(SBI_CTL_STAT,
+                       SBI_BUSY |
+                       SBI_CTL_OP_CRWR);
+
+       if (wait_for((I915_READ(SBI_CTL_STAT) & (SBI_READY | SBI_RESPONSE_SUCCESS)) == 0,
+                               100)) {
+               DRM_ERROR("timeout waiting for SBI to complete write transaction\n");
+               goto out_unlock;
+       }
+
+out_unlock:
+       spin_unlock_irqrestore(&dev_priv->dpio_lock, flags);
+}
+
+static u32
+intel_sbi_read(struct drm_i915_private *dev_priv, u16 reg)
+{
+       unsigned long flags;
+       u32 value;
+
+       spin_lock_irqsave(&dev_priv->dpio_lock, flags);
+       if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_READY) == 0,
+                               100)) {
+               DRM_ERROR("timeout waiting for SBI to become ready\n");
+               goto out_unlock;
+       }
+
+       I915_WRITE(SBI_ADDR,
+                       (reg << 16));
+       I915_WRITE(SBI_CTL_STAT,
+                       SBI_BUSY |
+                       SBI_CTL_OP_CRRD);
+
+       if (wait_for((I915_READ(SBI_CTL_STAT) & (SBI_READY | SBI_RESPONSE_SUCCESS)) == 0,
+                               100)) {
+               DRM_ERROR("timeout waiting for SBI to complete read transaction\n");
+               goto out_unlock;
+       }
+
+       value = I915_READ(SBI_DATA);
+
+out_unlock:
+       spin_unlock_irqrestore(&dev_priv->dpio_lock, flags);
+       return value;
+}
+
 /**
  * intel_enable_pch_pll - enable PCH PLL
  * @dev_priv: i915 private structure
@@ -1896,16 +1980,10 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
                return 0;
        }
 
-       switch (intel_crtc->plane) {
-       case 0:
-       case 1:
-               break;
-       case 2:
-               if (IS_IVYBRIDGE(dev))
-                       break;
-               /* fall through otherwise */
-       default:
-               DRM_ERROR("no plane for crtc\n");
+       if(intel_crtc->plane > dev_priv->num_pipe) {
+               DRM_ERROR("no plane for crtc: plane %d, num_pipes %d\n",
+                               intel_crtc->plane,
+                               dev_priv->num_pipe);
                return -EINVAL;
        }
 
@@ -2601,7 +2679,8 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
        I915_WRITE(TRANS_VSYNC(pipe),  I915_READ(VSYNC(pipe)));
        I915_WRITE(TRANS_VSYNCSHIFT(pipe),  I915_READ(VSYNCSHIFT(pipe)));
 
-       intel_fdi_normal_train(crtc);
+       if (!IS_HASWELL(dev))
+               intel_fdi_normal_train(crtc);
 
        /* For PCH DP, enable TRANS_DP_CTL */
        if (HAS_PCH_CPT(dev) &&
@@ -3120,8 +3199,7 @@ void intel_encoder_commit(struct drm_encoder *encoder)
 {
        struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
        struct drm_device *dev = encoder->dev;
-       struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
-       struct intel_crtc *intel_crtc = to_intel_crtc(intel_encoder->base.crtc);
+       struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
 
        /* lvds has its own version of commit see intel_lvds_commit */
        encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
@@ -3150,8 +3228,11 @@ static bool intel_crtc_mode_fixup(struct drm_crtc *crtc,
                        return false;
        }
 
-       /* All interlaced capable intel hw wants timings in frames. */
-       drm_mode_set_crtcinfo(adjusted_mode, 0);
+       /* All interlaced capable intel hw wants timings in frames. Note though
+        * that intel_lvds_mode_fixup does some funny tricks with the crtc
+        * timings, so we need to be careful not to clobber these.*/
+       if (!(adjusted_mode->private_flags & INTEL_MODE_CRTC_TIMINGS_SET))
+               drm_mode_set_crtcinfo(adjusted_mode, 0);
 
        return true;
 }
@@ -4834,9 +4915,6 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
                else
                        i9xx_update_cursor(crtc, base);
        }
-
-       if (visible)
-               intel_mark_busy(dev, to_intel_framebuffer(crtc->fb)->obj);
 }
 
 static int intel_crtc_cursor_set(struct drm_crtc *crtc,
@@ -5360,7 +5438,6 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
        mode->vsync_end = ((vsync & 0xffff0000) >> 16) + 1;
 
        drm_mode_set_name(mode);
-       drm_mode_set_crtcinfo(mode, 0);
 
        return mode;
 }
@@ -5445,9 +5522,6 @@ static void intel_decrease_pllclock(struct drm_crtc *crtc)
        struct drm_device *dev = crtc->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       int pipe = intel_crtc->pipe;
-       int dpll_reg = DPLL(pipe);
-       int dpll = I915_READ(dpll_reg);
 
        if (HAS_PCH_SPLIT(dev))
                return;
@@ -5460,10 +5534,15 @@ static void intel_decrease_pllclock(struct drm_crtc *crtc)
         * the manual case.
         */
        if (!HAS_PIPE_CXSR(dev) && intel_crtc->lowfreq_avail) {
+               int pipe = intel_crtc->pipe;
+               int dpll_reg = DPLL(pipe);
+               int dpll;
+
                DRM_DEBUG_DRIVER("downclocking LVDS\n");
 
                assert_panel_unlocked(dev_priv, pipe);
 
+               dpll = I915_READ(dpll_reg);
                dpll |= DISPLAY_RATE_SELECT_FPA1;
                I915_WRITE(dpll_reg, dpll);
                intel_wait_for_vblank(dev, pipe);
@@ -5530,12 +5609,16 @@ void intel_mark_busy(struct drm_device *dev, struct drm_i915_gem_object *obj)
        if (!drm_core_check_feature(dev, DRIVER_MODESET))
                return;
 
-       if (!dev_priv->busy)
+       if (!dev_priv->busy) {
+               intel_sanitize_pm(dev);
                dev_priv->busy = true;
-       else
+       else
                mod_timer(&dev_priv->idle_timer, jiffies +
                          msecs_to_jiffies(GPU_IDLE_TIMEOUT));
 
+       if (obj == NULL)
+               return;
+
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                if (!crtc->fb)
                        continue;
@@ -5857,7 +5940,13 @@ static int intel_gen6_queue_flip(struct drm_device *dev,
        intel_ring_emit(ring, fb->pitches[0] | obj->tiling_mode);
        intel_ring_emit(ring, obj->gtt_offset);
 
-       pf = I915_READ(PF_CTL(intel_crtc->pipe)) & PF_ENABLE;
+       /* Contrary to the suggestions in the documentation,
+        * "Enable Panel Fitter" does not seem to be required when page
+        * flipping with a non-native mode, and worse causes a normal
+        * modeset to fail.
+        * pf = I915_READ(PF_CTL(intel_crtc->pipe)) & PF_ENABLE;
+        */
+       pf = 0;
        pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff;
        intel_ring_emit(ring, pf | pipesrc);
        intel_ring_advance(ring);
@@ -5979,6 +6068,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
                goto cleanup_pending;
 
        intel_disable_fbc(dev);
+       intel_mark_busy(dev, obj);
        mutex_unlock(&dev->struct_mutex);
 
        trace_i915_flip_request(intel_crtc->plane, obj);
@@ -6626,6 +6716,7 @@ void intel_modeset_init_hw(struct drm_device *dev)
 
        if (IS_IRONLAKE_M(dev)) {
                ironlake_enable_drps(dev);
+               ironlake_enable_rc6(dev);
                intel_init_emon(dev);
        }
 
@@ -6687,8 +6778,6 @@ void intel_modeset_init(struct drm_device *dev)
        i915_disable_vga(dev);
        intel_setup_outputs(dev);
 
-       intel_modeset_init_hw(dev);
-
        INIT_WORK(&dev_priv->idle_work, intel_idle_update);
        setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer,
                    (unsigned long)dev);
@@ -6696,8 +6785,7 @@ void intel_modeset_init(struct drm_device *dev)
 
 void intel_modeset_gem_init(struct drm_device *dev)
 {
-       if (IS_IRONLAKE_M(dev))
-               ironlake_enable_rc6(dev);
+       intel_modeset_init_hw(dev);
 
        intel_setup_overlay(dev);
 }