]> Pileus Git - ~andy/linux/blobdiff - drivers/gpu/drm/i915/intel_display.c
Merge tag 'v3.13-rc3' into drm-intel-next-queued
[~andy/linux] / drivers / gpu / drm / i915 / intel_display.c
index 22b7b141a22fc2d9c6543663d2c2bc6136377b91..596ad09f0e5157b83ae1bf026cf26d82fed848c5 100644 (file)
@@ -329,6 +329,8 @@ static void vlv_clock(int refclk, intel_clock_t *clock)
 {
        clock->m = clock->m1 * clock->m2;
        clock->p = clock->p1 * clock->p2;
+       if (WARN_ON(clock->n == 0 || clock->p == 0))
+               return;
        clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n);
        clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
 }
@@ -430,6 +432,8 @@ static void pineview_clock(int refclk, intel_clock_t *clock)
 {
        clock->m = clock->m2 + 2;
        clock->p = clock->p1 * clock->p2;
+       if (WARN_ON(clock->n == 0 || clock->p == 0))
+               return;
        clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n);
        clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
 }
@@ -443,6 +447,8 @@ static void i9xx_clock(int refclk, intel_clock_t *clock)
 {
        clock->m = i9xx_dpll_compute_m(clock);
        clock->p = clock->p1 * clock->p2;
+       if (WARN_ON(clock->n + 2 == 0 || clock->p == 0))
+               return;
        clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n + 2);
        clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
 }
@@ -1513,7 +1519,7 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
 
        if (wait_for((I915_READ(DPLL(0)) & port_mask) == 0, 1000))
                WARN(1, "timed out waiting for port %c ready: 0x%08x\n",
-                    'B' + dport->port, I915_READ(DPLL(0)));
+                    port_name(dport->port), I915_READ(DPLL(0)));
 }
 
 /**
@@ -2241,7 +2247,12 @@ void intel_display_handle_reset(struct drm_device *dev)
                struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
                mutex_lock(&crtc->mutex);
-               if (intel_crtc->active)
+               /*
+                * FIXME: Once we have proper support for primary planes (and
+                * disabling them without disabling the entire crtc) allow again
+                * a NULL crtc->fb.
+                */
+               if (intel_crtc->active && crtc->fb)
                        dev_priv->display.update_plane(crtc, crtc->fb,
                                                       crtc->x, crtc->y);
                mutex_unlock(&crtc->mutex);
@@ -6479,7 +6490,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
        uint32_t val;
 
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head)
-               WARN(crtc->base.enabled, "CRTC for pipe %c enabled\n",
+               WARN(crtc->active, "CRTC for pipe %c enabled\n",
                     pipe_name(crtc->pipe));
 
        WARN(I915_READ(HSW_PWR_WELL_DRIVER), "Power well on\n");
@@ -6578,7 +6589,7 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
 
        /* Make sure we're not on PC8 state before disabling PC8, otherwise
         * we'll hang the machine! */
-       dev_priv->uncore.funcs.force_wake_get(dev_priv);
+       dev_priv->uncore.funcs.force_wake_get(dev_priv, FORCEWAKE_ALL);
 
        if (val & LCPLL_POWER_DOWN_ALLOW) {
                val &= ~LCPLL_POWER_DOWN_ALLOW;
@@ -6612,7 +6623,7 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
                        DRM_ERROR("Switching back to LCPLL failed\n");
        }
 
-       dev_priv->uncore.funcs.force_wake_put(dev_priv);
+       dev_priv->uncore.funcs.force_wake_put(dev_priv, FORCEWAKE_ALL);
 }
 
 void hsw_enable_pc8_work(struct work_struct *__work)
@@ -6694,6 +6705,9 @@ static void __hsw_disable_package_c8(struct drm_i915_private *dev_priv)
 
 void hsw_enable_package_c8(struct drm_i915_private *dev_priv)
 {
+       if (!HAS_PC8(dev_priv->dev))
+               return;
+
        mutex_lock(&dev_priv->pc8.lock);
        __hsw_enable_package_c8(dev_priv);
        mutex_unlock(&dev_priv->pc8.lock);
@@ -6701,6 +6715,9 @@ void hsw_enable_package_c8(struct drm_i915_private *dev_priv)
 
 void hsw_disable_package_c8(struct drm_i915_private *dev_priv)
 {
+       if (!HAS_PC8(dev_priv->dev))
+               return;
+
        mutex_lock(&dev_priv->pc8.lock);
        __hsw_disable_package_c8(dev_priv);
        mutex_unlock(&dev_priv->pc8.lock);
@@ -6738,6 +6755,9 @@ static void hsw_update_package_c8(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
        bool allow;
 
+       if (!HAS_PC8(dev_priv->dev))
+               return;
+
        if (!i915_enable_pc8)
                return;
 
@@ -6761,6 +6781,9 @@ done:
 
 static void hsw_package_c8_gpu_idle(struct drm_i915_private *dev_priv)
 {
+       if (!HAS_PC8(dev_priv->dev))
+               return;
+
        mutex_lock(&dev_priv->pc8.lock);
        if (!dev_priv->pc8.gpu_idle) {
                dev_priv->pc8.gpu_idle = true;
@@ -6771,6 +6794,9 @@ static void hsw_package_c8_gpu_idle(struct drm_i915_private *dev_priv)
 
 static void hsw_package_c8_gpu_busy(struct drm_i915_private *dev_priv)
 {
+       if (!HAS_PC8(dev_priv->dev))
+               return;
+
        mutex_lock(&dev_priv->pc8.lock);
        if (dev_priv->pc8.gpu_idle) {
                dev_priv->pc8.gpu_idle = false;
@@ -7364,7 +7390,9 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base)
                intel_crtc->cursor_visible = visible;
        }
        /* and commit changes on next vblank */
+       POSTING_READ(CURCNTR(pipe));
        I915_WRITE(CURBASE(pipe), base);
+       POSTING_READ(CURBASE(pipe));
 }
 
 static void ivb_update_cursor(struct drm_crtc *crtc, u32 base)
@@ -7393,7 +7421,9 @@ static void ivb_update_cursor(struct drm_crtc *crtc, u32 base)
                intel_crtc->cursor_visible = visible;
        }
        /* and commit changes on next vblank */
+       POSTING_READ(CURCNTR_IVB(pipe));
        I915_WRITE(CURBASE_IVB(pipe), base);
+       POSTING_READ(CURBASE_IVB(pipe));
 }
 
 /* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */
@@ -9428,8 +9458,7 @@ check_crtc_state(struct drm_device *dev)
                        enum pipe pipe;
                        if (encoder->base.crtc != &crtc->base)
                                continue;
-                       if (encoder->get_config &&
-                           encoder->get_hw_state(encoder, &pipe))
+                       if (encoder->get_hw_state(encoder, &pipe))
                                encoder->get_config(encoder, &pipe_config);
                }
 
@@ -10098,10 +10127,13 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
                intel_crtc->lut_b[i] = i;
        }
 
-       /* Swap pipes & planes for FBC on pre-965 */
+       /*
+        * On gen2/3 only plane A can do fbc, but the panel fitter and lvds port
+        * is hooked to plane B. Hence we want plane A feeding pipe B.
+        */
        intel_crtc->pipe = pipe;
        intel_crtc->plane = pipe;
-       if (IS_MOBILE(dev) && IS_GEN3(dev)) {
+       if (IS_MOBILE(dev) && INTEL_INFO(dev)->gen < 4) {
                DRM_DEBUG_KMS("swapping pipes & planes for FBC\n");
                intel_crtc->plane = !pipe;
        }
@@ -11093,8 +11125,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
                if (encoder->get_hw_state(encoder, &pipe)) {
                        crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
                        encoder->base.crtc = &crtc->base;
-                       if (encoder->get_config)
-                               encoder->get_config(encoder, &crtc->config);
+                       encoder->get_config(encoder, &crtc->config);
                } else {
                        encoder->base.crtc = NULL;
                }
@@ -11312,6 +11343,7 @@ struct intel_display_error_state {
        } cursor[I915_MAX_PIPES];
 
        struct intel_pipe_error_state {
+               bool power_domain_on;
                u32 source;
        } pipe[I915_MAX_PIPES];
 
@@ -11326,6 +11358,7 @@ struct intel_display_error_state {
        } plane[I915_MAX_PIPES];
 
        struct intel_transcoder_error_state {
+               bool power_domain_on;
                enum transcoder cpu_transcoder;
 
                u32 conf;
@@ -11363,7 +11396,9 @@ intel_display_capture_error_state(struct drm_device *dev)
                error->power_well_driver = I915_READ(HSW_PWR_WELL_DRIVER);
 
        for_each_pipe(i) {
-               if (!intel_display_power_enabled(dev, POWER_DOMAIN_PIPE(i)))
+               error->pipe[i].power_domain_on =
+                       intel_display_power_enabled_sw(dev, POWER_DOMAIN_PIPE(i));
+               if (!error->pipe[i].power_domain_on)
                        continue;
 
                if (INTEL_INFO(dev)->gen <= 6 || IS_VALLEYVIEW(dev)) {
@@ -11399,8 +11434,9 @@ intel_display_capture_error_state(struct drm_device *dev)
        for (i = 0; i < error->num_transcoders; i++) {
                enum transcoder cpu_transcoder = transcoders[i];
 
-               if (!intel_display_power_enabled(dev,
-                               POWER_DOMAIN_TRANSCODER(cpu_transcoder)))
+               error->transcoder[i].power_domain_on =
+                       intel_display_power_enabled_sw(dev, POWER_DOMAIN_PIPE(i));
+               if (!error->transcoder[i].power_domain_on)
                        continue;
 
                error->transcoder[i].cpu_transcoder = cpu_transcoder;
@@ -11435,6 +11471,8 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m,
                           error->power_well_driver);
        for_each_pipe(i) {
                err_printf(m, "Pipe [%d]:\n", i);
+               err_printf(m, "  Power: %s\n",
+                          error->pipe[i].power_domain_on ? "on" : "off");
                err_printf(m, "  SRC: %08x\n", error->pipe[i].source);
 
                err_printf(m, "Plane [%d]:\n", i);
@@ -11460,6 +11498,8 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m,
        for (i = 0; i < error->num_transcoders; i++) {
                err_printf(m, "CPU transcoder: %c\n",
                           transcoder_name(error->transcoder[i].cpu_transcoder));
+               err_printf(m, "  Power: %s\n",
+                          error->transcoder[i].power_domain_on ? "on" : "off");
                err_printf(m, "  CONF: %08x\n", error->transcoder[i].conf);
                err_printf(m, "  HTOTAL: %08x\n", error->transcoder[i].htotal);
                err_printf(m, "  HBLANK: %08x\n", error->transcoder[i].hblank);