drm/i915/vlv: use W_SYNC_SHIFT for interlaced modes on VLV
[linux-2.6-block.git] / drivers / gpu / drm / i915 / intel_display.c
index 4b5cffa3f0330a66040619d9ba961b44868d6684..564b6ab6ceb5c666e4eb5c9a59c471316dffd3d4 100644 (file)
@@ -5533,8 +5533,11 @@ static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc)
                }
        }
 
-       if (!IS_GEN2(dev) &&
+       if (IS_VALLEYVIEW(dev) &&
            intel_crtc->config.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
+               pipeconf |= PIPECONF_INTERLACE_W_SYNC_SHIFT;
+       else if (!IS_GEN2(dev) &&
+                intel_crtc->config.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
                pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION;
        else
                pipeconf |= PIPECONF_PROGRESSIVE;
@@ -7024,7 +7027,30 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
-void __hsw_do_enable_pc8(struct drm_i915_private *dev_priv)
+/*
+ * Package states C8 and deeper are really deep PC states that can only be
+ * reached when all the devices on the system allow it, so even if the graphics
+ * device allows PC8+, it doesn't mean the system will actually get to these
+ * states. Our driver only allows PC8+ when going into runtime PM.
+ *
+ * The requirements for PC8+ are that all the outputs are disabled, the power
+ * well is disabled and most interrupts are disabled, and these are also
+ * requirements for runtime PM. When these conditions are met, we manually do
+ * the other conditions: disable the interrupts, clocks and switch LCPLL refclk
+ * to Fclk. If we're in PC8+ and we get an non-hotplug interrupt, we can hard
+ * hang the machine.
+ *
+ * When we really reach PC8 or deeper states (not just when we allow it) we lose
+ * the state of some registers, so when we come back from PC8+ we need to
+ * restore this state. We don't get into PC8+ if we're not in RC6, so we don't
+ * need to take care of the registers kept by RC6. Notice that this happens even
+ * if we don't put the device in PCI D3 state (which is what currently happens
+ * because of the runtime PM support).
+ *
+ * For more, read "Display Sequences for Package C8" on the hardware
+ * documentation.
+ */
+void hsw_enable_pc8(struct drm_i915_private *dev_priv)
 {
        struct drm_device *dev = dev_priv->dev;
        uint32_t val;
@@ -7044,7 +7070,7 @@ void __hsw_do_enable_pc8(struct drm_i915_private *dev_priv)
        hsw_disable_lcpll(dev_priv, true, true);
 }
 
-void __hsw_do_disable_pc8(struct drm_i915_private *dev_priv)
+void hsw_disable_pc8(struct drm_i915_private *dev_priv)
 {
        struct drm_device *dev = dev_priv->dev;
        uint32_t val;
@@ -7576,10 +7602,26 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base)
        bool visible = base != 0;
 
        if (intel_crtc->cursor_visible != visible) {
+               int16_t width = intel_crtc->cursor_width;
                uint32_t cntl = I915_READ(CURCNTR(pipe));
                if (base) {
                        cntl &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
-                       cntl |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
+                       cntl |= MCURSOR_GAMMA_ENABLE;
+
+                       switch (width) {
+                       case 64:
+                               cntl |= CURSOR_MODE_64_ARGB_AX;
+                               break;
+                       case 128:
+                               cntl |= CURSOR_MODE_128_ARGB_AX;
+                               break;
+                       case 256:
+                               cntl |= CURSOR_MODE_256_ARGB_AX;
+                               break;
+                       default:
+                               WARN_ON(1);
+                               return;
+                       }
                        cntl |= pipe << 28; /* Connect to correct pipe */
                } else {
                        cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE);
@@ -7604,10 +7646,25 @@ static void ivb_update_cursor(struct drm_crtc *crtc, u32 base)
        bool visible = base != 0;
 
        if (intel_crtc->cursor_visible != visible) {
+               int16_t width = intel_crtc->cursor_width;
                uint32_t cntl = I915_READ(CURCNTR_IVB(pipe));
                if (base) {
                        cntl &= ~CURSOR_MODE;
-                       cntl |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
+                       cntl |= MCURSOR_GAMMA_ENABLE;
+                       switch (width) {
+                       case 64:
+                               cntl |= CURSOR_MODE_64_ARGB_AX;
+                               break;
+                       case 128:
+                               cntl |= CURSOR_MODE_128_ARGB_AX;
+                               break;
+                       case 256:
+                               cntl |= CURSOR_MODE_256_ARGB_AX;
+                               break;
+                       default:
+                               WARN_ON(1);
+                               return;
+                       }
                } else {
                        cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE);
                        cntl |= CURSOR_MODE_DISABLE;
@@ -7691,6 +7748,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct drm_i915_gem_object *obj;
+       unsigned old_width;
        uint32_t addr;
        int ret;
 
@@ -7703,9 +7761,11 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
                goto finish;
        }
 
-       /* Currently we only support 64x64 cursors */
-       if (width != 64 || height != 64) {
-               DRM_ERROR("we currently only support 64x64 cursors\n");
+       /* Check for which cursor types we support */
+       if (!((width == 64 && height == 64) ||
+                       (width == 128 && height == 128 && !IS_GEN2(dev)) ||
+                       (width == 256 && height == 256 && !IS_GEN2(dev)))) {
+               DRM_DEBUG("Cursor dimension not supported\n");
                return -EINVAL;
        }
 
@@ -7779,13 +7839,18 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
 
        mutex_unlock(&dev->struct_mutex);
 
+       old_width = intel_crtc->cursor_width;
+
        intel_crtc->cursor_addr = addr;
        intel_crtc->cursor_bo = obj;
        intel_crtc->cursor_width = width;
        intel_crtc->cursor_height = height;
 
-       if (intel_crtc->active)
+       if (intel_crtc->active) {
+               if (old_width != width)
+                       intel_update_watermarks(crtc);
                intel_crtc_update_cursor(crtc, intel_crtc->cursor_bo != NULL);
+       }
 
        return 0;
 fail_unpin:
@@ -10491,6 +10556,16 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
 
        drm_crtc_init(dev, &intel_crtc->base, &intel_crtc_funcs);
 
+       if (IS_GEN2(dev)) {
+               intel_crtc->max_cursor_width = GEN2_CURSOR_WIDTH;
+               intel_crtc->max_cursor_height = GEN2_CURSOR_HEIGHT;
+       } else {
+               intel_crtc->max_cursor_width = CURSOR_WIDTH;
+               intel_crtc->max_cursor_height = CURSOR_HEIGHT;
+       }
+       dev->mode_config.cursor_width = intel_crtc->max_cursor_width;
+       dev->mode_config.cursor_height = intel_crtc->max_cursor_height;
+
        drm_mode_crtc_set_gamma_size(&intel_crtc->base, 256);
        for (i = 0; i < 256; i++) {
                intel_crtc->lut_r[i] = i;
@@ -11433,6 +11508,17 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
                        encoder->base.crtc = NULL;
                }
        }
+       if (crtc->active) {
+               /*
+                * We start out with underrun reporting disabled to avoid races.
+                * For correct bookkeeping mark this on active crtcs.
+                *
+                * No protection against concurrent access is required - at
+                * worst a fifo underrun happens which also sets this to false.
+                */
+               crtc->cpu_fifo_underrun_disabled = true;
+               crtc->pch_fifo_underrun_disabled = true;
+       }
 }
 
 static void intel_sanitize_encoder(struct intel_encoder *encoder)