]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/gpu/drm/i915/intel_display.c
drm/i915: don't intel_crt_init on any ULT machines
[karo-tx-linux.git] / drivers / gpu / drm / i915 / intel_display.c
index f235e8a48b3857cdbaefb1952581fb2d4987d059..6a8262867b0bcb0bd63412260fe007ef36baf5a9 100644 (file)
@@ -1227,8 +1227,8 @@ void assert_pipe(struct drm_i915_private *dev_priv,
        if (pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE)
                state = true;
 
-       if (IS_HASWELL(dev_priv->dev) && cpu_transcoder != TRANSCODER_EDP &&
-           !(I915_READ(HSW_PWR_WELL_DRIVER) & HSW_PWR_WELL_ENABLE)) {
+       if (!intel_using_power_well(dev_priv->dev) &&
+           cpu_transcoder != TRANSCODER_EDP) {
                cur_state = false;
        } else {
                reg = PIPECONF(cpu_transcoder);
@@ -2002,8 +2002,10 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev,
                alignment = 0;
                break;
        case I915_TILING_Y:
-               /* FIXME: Is this true? */
-               DRM_ERROR("Y tiled not allowed for scan out buffers\n");
+               /* Despite that we check this in framebuffer_init userspace can
+                * screw us over and change the tiling after the fact. Only
+                * pinned buffers can't change their tiling. */
+               DRM_DEBUG_DRIVER("Y tiled not allowed for scan out buffers\n");
                return -EINVAL;
        default:
                BUG();
@@ -3597,9 +3599,13 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
 
        intel_ddi_disable_transcoder_func(dev_priv, cpu_transcoder);
 
-       /* Disable PF */
-       I915_WRITE(PF_CTL(pipe), 0);
-       I915_WRITE(PF_WIN_SZ(pipe), 0);
+       /* XXX: Once we have proper panel fitter state tracking implemented with
+        * hardware state read/check support we should switch to only disable
+        * the panel fitter when we know it's used. */
+       if (intel_using_power_well(dev)) {
+               I915_WRITE(PF_CTL(pipe), 0);
+               I915_WRITE(PF_WIN_SZ(pipe), 0);
+       }
 
        intel_ddi_disable_pipe_clock(intel_crtc);
 
@@ -3718,6 +3724,26 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
                encoder->enable(encoder);
 }
 
+static void i9xx_pfit_disable(struct intel_crtc *crtc)
+{
+       struct drm_device *dev = crtc->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       enum pipe pipe;
+       uint32_t pctl = I915_READ(PFIT_CONTROL);
+
+       assert_pipe_disabled(dev_priv, crtc->pipe);
+
+       if (INTEL_INFO(dev)->gen >= 4)
+               pipe = (pctl & PFIT_PIPE_MASK) >> PFIT_PIPE_SHIFT;
+       else
+               pipe = PIPE_B;
+
+       if (pipe == crtc->pipe) {
+               DRM_DEBUG_DRIVER("disabling pfit, current: 0x%08x\n", pctl);
+               I915_WRITE(PFIT_CONTROL, 0);
+       }
+}
+
 static void i9xx_crtc_disable(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
@@ -3726,8 +3752,6 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
        struct intel_encoder *encoder;
        int pipe = intel_crtc->pipe;
        int plane = intel_crtc->plane;
-       u32 pctl;
-
 
        if (!intel_crtc->active)
                return;
@@ -3747,11 +3771,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
        intel_disable_plane(dev_priv, plane, pipe);
        intel_disable_pipe(dev_priv, pipe);
 
-       /* Disable pannel fitter if it is on this pipe. */
-       pctl = I915_READ(PFIT_CONTROL);
-       if ((pctl & PFIT_ENABLE) &&
-           ((pctl & PFIT_PIPE_MASK) >> PFIT_PIPE_SHIFT) == pipe)
-               I915_WRITE(PFIT_CONTROL, 0);
+       i9xx_pfit_disable(intel_crtc);
 
        intel_disable_pll(dev_priv, pipe);
 
@@ -4956,13 +4976,6 @@ static void lpt_init_pch_refclk(struct drm_device *dev)
        tmp |= (0x12 << 24);
        intel_sbi_write(dev_priv, 0x8008, tmp, SBI_MPHY);
 
-       if (!is_sdv) {
-               tmp = intel_sbi_read(dev_priv, 0x808C, SBI_MPHY);
-               tmp &= ~(0x3 << 6);
-               tmp |= (1 << 6) | (1 << 0);
-               intel_sbi_write(dev_priv, 0x808C, tmp, SBI_MPHY);
-       }
-
        if (is_sdv) {
                tmp = intel_sbi_read(dev_priv, 0x800C, SBI_MPHY);
                tmp |= 0x7FFF;
@@ -5469,7 +5482,8 @@ static void ironlake_fdi_set_m_n(struct drm_crtc *crtc)
 }
 
 static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc,
-                                     intel_clock_t *clock, u32 *fp)
+                                     intel_clock_t *clock, u32 *fp,
+                                     intel_clock_t *reduced_clock, u32 *fp2)
 {
        struct drm_crtc *crtc = &intel_crtc->base;
        struct drm_device *dev = crtc->dev;
@@ -5511,6 +5525,9 @@ static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc,
        if (clock->m < factor * clock->n)
                *fp |= FP_CB_TUNE;
 
+       if (fp2 && (reduced_clock->m < factor * reduced_clock->n))
+               *fp2 |= FP_CB_TUNE;
+
        dpll = 0;
 
        if (is_lvds)
@@ -5626,7 +5643,8 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
                fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 |
                        reduced_clock.m2;
 
-       dpll = ironlake_compute_dpll(intel_crtc, &clock, &fp);
+       dpll = ironlake_compute_dpll(intel_crtc, &clock, &fp, &reduced_clock,
+                                    has_reduced_clock ? &fp2 : NULL);
 
        DRM_DEBUG_KMS("Mode for pipe %d:\n", pipe);
        drm_mode_debug_printmodeline(mode);
@@ -7708,22 +7726,25 @@ intel_modeset_affected_pipes(struct drm_crtc *crtc, unsigned *modeset_pipes,
        if (crtc->enabled)
                *prepare_pipes |= 1 << intel_crtc->pipe;
 
-       /* We only support modeset on one single crtc, hence we need to do that
-        * only for the passed in crtc iff we change anything else than just
-        * disable crtcs.
-        *
-        * This is actually not true, to be fully compatible with the old crtc
-        * helper we automatically disable _any_ output (i.e. doesn't need to be
-        * connected to the crtc we're modesetting on) if it's disconnected.
-        * Which is a rather nutty api (since changed the output configuration
-        * without userspace's explicit request can lead to confusion), but
-        * alas. Hence we currently need to modeset on all pipes we prepare. */
+       /*
+        * For simplicity do a full modeset on any pipe where the output routing
+        * changed. We could be more clever, but that would require us to be
+        * more careful with calling the relevant encoder->mode_set functions.
+        */
        if (*prepare_pipes)
                *modeset_pipes = *prepare_pipes;
 
        /* ... and mask these out. */
        *modeset_pipes &= ~(*disable_pipes);
        *prepare_pipes &= ~(*disable_pipes);
+
+       /*
+        * HACK: We don't (yet) fully support global modesets. intel_set_config
+        * obies this rule, but the modeset restore mode of
+        * intel_modeset_setup_hw_state does not.
+        */
+       *modeset_pipes &= 1 << intel_crtc->pipe;
+       *prepare_pipes &= 1 << intel_crtc->pipe;
 }
 
 static bool intel_crtc_in_use(struct drm_crtc *crtc)
@@ -7916,9 +7937,9 @@ intel_modeset_check_state(struct drm_device *dev)
        }
 }
 
-int intel_set_mode(struct drm_crtc *crtc,
-                  struct drm_display_mode *mode,
-                  int x, int y, struct drm_framebuffer *fb)
+static int __intel_set_mode(struct drm_crtc *crtc,
+                           struct drm_display_mode *mode,
+                           int x, int y, struct drm_framebuffer *fb)
 {
        struct drm_device *dev = crtc->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
@@ -8012,8 +8033,6 @@ done:
        if (ret && crtc->enabled) {
                crtc->hwmode = *saved_hwmode;
                crtc->mode = *saved_mode;
-       } else {
-               intel_modeset_check_state(dev);
        }
 
 out:
@@ -8022,6 +8041,20 @@ out:
        return ret;
 }
 
+int intel_set_mode(struct drm_crtc *crtc,
+                    struct drm_display_mode *mode,
+                    int x, int y, struct drm_framebuffer *fb)
+{
+       int ret;
+
+       ret = __intel_set_mode(crtc, mode, x, y, fb);
+
+       if (ret == 0)
+               intel_modeset_check_state(crtc->dev);
+
+       return ret;
+}
+
 void intel_crtc_restore_mode(struct drm_crtc *crtc)
 {
        intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y, crtc->fb);
@@ -8462,7 +8495,7 @@ static void intel_setup_outputs(struct drm_device *dev)
                I915_WRITE(PFIT_CONTROL, 0);
        }
 
-       if (!(HAS_DDI(dev) && (I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_A_4_LANES)))
+       if (!IS_ULT(dev))
                intel_crt_init(dev);
 
        if (HAS_DDI(dev)) {
@@ -9333,10 +9366,16 @@ setup_pipes:
        }
 
        if (force_restore) {
+               /*
+                * We need to use raw interfaces for restoring state to avoid
+                * checking (bogus) intermediate states.
+                */
                for_each_pipe(pipe) {
                        struct drm_crtc *crtc =
                                dev_priv->pipe_to_crtc_mapping[pipe];
-                       intel_crtc_restore_mode(crtc);
+
+                       __intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y,
+                                        crtc->fb);
                }
                list_for_each_entry(plane, &dev->mode_config.plane_list, head)
                        intel_plane_restore(plane);
@@ -9401,6 +9440,9 @@ void intel_modeset_cleanup(struct drm_device *dev)
        /* flush any delayed tasks or pending work */
        flush_scheduled_work();
 
+       /* destroy backlight, if any, before the connectors */
+       intel_panel_destroy_backlight(dev);
+
        drm_mode_config_cleanup(dev);
 
        intel_cleanup_overlay(dev);