/* * Copyright © 2006-2007 Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Authors: * Eric Anholt */ #include #include #include #include #include #include #include #include #include #include "intel_drv.h" #include #include "i915_drv.h" /*#include "i915_rpm.h"*/ #include "i915_trace.h" #include "intel_dsi.h" #include "intel_clrmgr.h" #include "hdmi_audio_if.h" #include #include #include #include #define MAX_BRIGHTNESS 255 /*extern*/ int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno, unsigned reset_counter, bool interruptible, struct timespec *timeout); struct i915_flip_data { struct drm_crtc *crtc; u32 seqno; u32 ring_id; }; struct i915_flip_work { struct i915_flip_data flipdata; struct work_struct work; }; /* Need one work item only for each plane, * as we support only one outstanding flip request * on each plane at a time. */ static struct i915_flip_work flip_works[I915_MAX_PLANES]; static void intel_increase_pllclock(struct drm_crtc *crtc); static void intel_crtc_update_cursor(struct drm_crtc *crtc, bool on); static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb, int x, int y); static void i9xx_crtc_clock_get(struct intel_crtc *crtc, struct intel_crtc_config *pipe_config); static void ironlake_crtc_clock_get(struct intel_crtc *crtc, struct intel_crtc_config *pipe_config); static int intel_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, int x, int y, struct drm_framebuffer *old_fb); static void intel_drop_scratch_page_for_fb(struct drm_i915_gem_object *obj); typedef struct { int min, max; } intel_range_t; typedef struct { int dot_limit; int p2_slow, p2_fast; } intel_p2_t; typedef struct intel_limit intel_limit_t; struct intel_limit { intel_range_t dot, vco, n, m, m1, m2, p, p1; intel_p2_t p2; }; /* FDI */ #define IRONLAKE_FDI_FREQ 2700000 /* in kHz for mode->clock */ int intel_pch_rawclk(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; WARN_ON(!HAS_PCH_SPLIT(dev)); return I915_READ(PCH_RAWCLK_FREQ) & RAWCLK_FREQ_MASK; } static inline u32 /* units of 100MHz */ intel_fdi_link_freq(struct drm_device *dev) { if (IS_GEN5(dev)) { struct drm_i915_private *dev_priv = dev->dev_private; return (I915_READ(FDI_PLL_BIOS_0) & FDI_PLL_FB_CLOCK_MASK) + 2; } else return 27; } static const intel_limit_t intel_limits_i8xx_dac = { .dot = { .min = 25000, .max = 350000 }, .vco = { .min = 930000, .max = 1400000 }, .n = { .min = 3, .max = 16 }, .m = { .min = 96, .max = 140 }, .m1 = { .min = 18, .max = 26 }, .m2 = { .min = 6, .max = 16 }, .p = { .min = 4, .max = 128 }, .p1 = { .min = 2, .max = 33 }, .p2 = { .dot_limit = 165000, .p2_slow = 4, .p2_fast = 2 }, }; static const intel_limit_t intel_limits_i8xx_dvo = { .dot = { .min = 25000, .max = 350000 }, .vco = { .min = 930000, .max = 1400000 }, .n = { .min = 3, .max = 16 }, .m = { .min = 96, .max = 140 }, .m1 = { .min = 18, .max = 26 }, .m2 = { .min = 6, .max = 16 }, .p = { .min = 4, .max = 128 }, .p1 = { .min = 2, .max = 33 }, .p2 = { .dot_limit = 165000, .p2_slow = 4, .p2_fast = 4 }, }; static const intel_limit_t intel_limits_i8xx_lvds = { .dot = { .min = 25000, .max = 350000 }, .vco = { .min = 930000, .max = 1400000 }, .n = { .min = 3, .max = 16 }, .m = { .min = 96, .max = 140 }, .m1 = { .min = 18, .max = 26 }, .m2 = { .min = 6, .max = 16 }, .p = { .min = 4, .max = 128 }, .p1 = { .min = 1, .max = 6 }, .p2 = { .dot_limit = 165000, .p2_slow = 14, .p2_fast = 7 }, }; static const intel_limit_t intel_limits_i9xx_sdvo = { .dot = { .min = 20000, .max = 400000 }, .vco = { .min = 1400000, .max = 2800000 }, .n = { .min = 1, .max = 6 }, .m = { .min = 70, .max = 120 }, .m1 = { .min = 8, .max = 18 }, .m2 = { .min = 3, .max = 7 }, .p = { .min = 5, .max = 80 }, .p1 = { .min = 1, .max = 8 }, .p2 = { .dot_limit = 200000, .p2_slow = 10, .p2_fast = 5 }, }; static const intel_limit_t intel_limits_i9xx_lvds = { .dot = { .min = 20000, .max = 400000 }, .vco = { .min = 1400000, .max = 2800000 }, .n = { .min = 1, .max = 6 }, .m = { .min = 70, .max = 120 }, .m1 = { .min = 8, .max = 18 }, .m2 = { .min = 3, .max = 7 }, .p = { .min = 7, .max = 98 }, .p1 = { .min = 1, .max = 8 }, .p2 = { .dot_limit = 112000, .p2_slow = 14, .p2_fast = 7 }, }; static const intel_limit_t intel_limits_g4x_sdvo = { .dot = { .min = 25000, .max = 270000 }, .vco = { .min = 1750000, .max = 3500000}, .n = { .min = 1, .max = 4 }, .m = { .min = 104, .max = 138 }, .m1 = { .min = 17, .max = 23 }, .m2 = { .min = 5, .max = 11 }, .p = { .min = 10, .max = 30 }, .p1 = { .min = 1, .max = 3}, .p2 = { .dot_limit = 270000, .p2_slow = 10, .p2_fast = 10 }, }; static const intel_limit_t intel_limits_g4x_hdmi = { .dot = { .min = 22000, .max = 400000 }, .vco = { .min = 1750000, .max = 3500000}, .n = { .min = 1, .max = 4 }, .m = { .min = 104, .max = 138 }, .m1 = { .min = 16, .max = 23 }, .m2 = { .min = 5, .max = 11 }, .p = { .min = 5, .max = 80 }, .p1 = { .min = 1, .max = 8}, .p2 = { .dot_limit = 165000, .p2_slow = 10, .p2_fast = 5 }, }; static const intel_limit_t intel_limits_g4x_single_channel_lvds = { .dot = { .min = 20000, .max = 115000 }, .vco = { .min = 1750000, .max = 3500000 }, .n = { .min = 1, .max = 3 }, .m = { .min = 104, .max = 138 }, .m1 = { .min = 17, .max = 23 }, .m2 = { .min = 5, .max = 11 }, .p = { .min = 28, .max = 112 }, .p1 = { .min = 2, .max = 8 }, .p2 = { .dot_limit = 0, .p2_slow = 14, .p2_fast = 14 }, }; static const intel_limit_t intel_limits_g4x_dual_channel_lvds = { .dot = { .min = 80000, .max = 224000 }, .vco = { .min = 1750000, .max = 3500000 }, .n = { .min = 1, .max = 3 }, .m = { .min = 104, .max = 138 }, .m1 = { .min = 17, .max = 23 }, .m2 = { .min = 5, .max = 11 }, .p = { .min = 14, .max = 42 }, .p1 = { .min = 2, .max = 6 }, .p2 = { .dot_limit = 0, .p2_slow = 7, .p2_fast = 7 }, }; static const intel_limit_t intel_limits_pineview_sdvo = { .dot = { .min = 20000, .max = 400000}, .vco = { .min = 1700000, .max = 3500000 }, /* Pineview's Ncounter is a ring counter */ .n = { .min = 3, .max = 6 }, .m = { .min = 2, .max = 256 }, /* Pineview only has one combined m divider, which we treat as m2. */ .m1 = { .min = 0, .max = 0 }, .m2 = { .min = 0, .max = 254 }, .p = { .min = 5, .max = 80 }, .p1 = { .min = 1, .max = 8 }, .p2 = { .dot_limit = 200000, .p2_slow = 10, .p2_fast = 5 }, }; static const intel_limit_t intel_limits_pineview_lvds = { .dot = { .min = 20000, .max = 400000 }, .vco = { .min = 1700000, .max = 3500000 }, .n = { .min = 3, .max = 6 }, .m = { .min = 2, .max = 256 }, .m1 = { .min = 0, .max = 0 }, .m2 = { .min = 0, .max = 254 }, .p = { .min = 7, .max = 112 }, .p1 = { .min = 1, .max = 8 }, .p2 = { .dot_limit = 112000, .p2_slow = 14, .p2_fast = 14 }, }; /* Ironlake / Sandybridge * * We calculate clock using (register_value + 2) for N/M1/M2, so here * the range value for them is (actual_value - 2). */ static const intel_limit_t intel_limits_ironlake_dac = { .dot = { .min = 25000, .max = 350000 }, .vco = { .min = 1760000, .max = 3510000 }, .n = { .min = 1, .max = 5 }, .m = { .min = 79, .max = 127 }, .m1 = { .min = 12, .max = 22 }, .m2 = { .min = 5, .max = 9 }, .p = { .min = 5, .max = 80 }, .p1 = { .min = 1, .max = 8 }, .p2 = { .dot_limit = 225000, .p2_slow = 10, .p2_fast = 5 }, }; static const intel_limit_t intel_limits_ironlake_single_lvds = { .dot = { .min = 25000, .max = 350000 }, .vco = { .min = 1760000, .max = 3510000 }, .n = { .min = 1, .max = 3 }, .m = { .min = 79, .max = 118 }, .m1 = { .min = 12, .max = 22 }, .m2 = { .min = 5, .max = 9 }, .p = { .min = 28, .max = 112 }, .p1 = { .min = 2, .max = 8 }, .p2 = { .dot_limit = 225000, .p2_slow = 14, .p2_fast = 14 }, }; static const intel_limit_t intel_limits_ironlake_dual_lvds = { .dot = { .min = 25000, .max = 350000 }, .vco = { .min = 1760000, .max = 3510000 }, .n = { .min = 1, .max = 3 }, .m = { .min = 79, .max = 127 }, .m1 = { .min = 12, .max = 22 }, .m2 = { .min = 5, .max = 9 }, .p = { .min = 14, .max = 56 }, .p1 = { .min = 2, .max = 8 }, .p2 = { .dot_limit = 225000, .p2_slow = 7, .p2_fast = 7 }, }; /* LVDS 100mhz refclk limits. */ static const intel_limit_t intel_limits_ironlake_single_lvds_100m = { .dot = { .min = 25000, .max = 350000 }, .vco = { .min = 1760000, .max = 3510000 }, .n = { .min = 1, .max = 2 }, .m = { .min = 79, .max = 126 }, .m1 = { .min = 12, .max = 22 }, .m2 = { .min = 5, .max = 9 }, .p = { .min = 28, .max = 112 }, .p1 = { .min = 2, .max = 8 }, .p2 = { .dot_limit = 225000, .p2_slow = 14, .p2_fast = 14 }, }; static const intel_limit_t intel_limits_ironlake_dual_lvds_100m = { .dot = { .min = 25000, .max = 350000 }, .vco = { .min = 1760000, .max = 3510000 }, .n = { .min = 1, .max = 3 }, .m = { .min = 79, .max = 126 }, .m1 = { .min = 12, .max = 22 }, .m2 = { .min = 5, .max = 9 }, .p = { .min = 14, .max = 42 }, .p1 = { .min = 2, .max = 6 }, .p2 = { .dot_limit = 225000, .p2_slow = 7, .p2_fast = 7 }, }; static const intel_limit_t intel_limits_vlv_dac = { .dot = { .min = 25000, .max = 270000 }, .vco = { .min = 4000000, .max = 6000000 }, .n = { .min = 1, .max = 7 }, .m = { .min = 22, .max = 450 }, /* guess */ .m1 = { .min = 2, .max = 3 }, .m2 = { .min = 11, .max = 156 }, .p = { .min = 10, .max = 30 }, .p1 = { .min = 1, .max = 3 }, .p2 = { .dot_limit = 270000, .p2_slow = 2, .p2_fast = 20 }, }; static const intel_limit_t intel_limits_vlv_hdmi = { .dot = { .min = 25000, .max = 180000 }, .vco = { .min = 4040000, .max = 5960000 }, .n = { .min = 1, .max = 5 }, .m = { .min = 60, .max = 300 }, /* guess */ .m1 = { .min = 2, .max = 3 }, .m2 = { .min = 15, .max = 149 }, .p = { .min = 10, .max = 30 }, .p1 = { .min = 1, .max = 3 }, .p2 = { .dot_limit = 270000, .p2_slow = 2, .p2_fast = 20 }, }; static const intel_limit_t intel_limits_vlv_dp = { .dot = { .min = 25000, .max = 270000 }, .vco = { .min = 4000000, .max = 6000000 }, .n = { .min = 1, .max = 7 }, .m = { .min = 22, .max = 450 }, .m1 = { .min = 2, .max = 3 }, .m2 = { .min = 11, .max = 156 }, .p = { .min = 10, .max = 30 }, .p1 = { .min = 1, .max = 3 }, .p2 = { .dot_limit = 270000, .p2_slow = 2, .p2_fast = 20 }, }; static bool check_live_status(struct drm_i915_private *dev_priv) { /* Since certain panels are causing delay in updating the live_status register * and increasing delay doesnot meet the KPI, now live_status is determined whether * the device is available or not */ DRM_DEBUG_DRIVER("HDMI live_status is returning is %d\n", !dev_priv->unplug); return !dev_priv->unplug; } void i915_update_plane_stat(struct drm_i915_private *dev_priv, int pipe, int plane, bool enable, int planes) { switch (pipe) { case 0: if (planes == DISPLAY_PLANE) { if (enable) dev_priv->plane_stat.primary = true; else dev_priv->plane_stat.primary = false; } else { switch (plane) { case 0: if (enable) dev_priv->plane_stat.sprite_a = true; else dev_priv->plane_stat.sprite_a = false; break; case 1: if (enable) dev_priv->plane_stat.sprite_b = true; else dev_priv->plane_stat.sprite_b = false; break; } } break; case 1: if (planes == DISPLAY_PLANE) { if (enable) dev_priv->plane_stat.secondary = true; else dev_priv->plane_stat.secondary = false; } else { switch (plane) { case 0: if (enable) dev_priv->plane_stat.sprite_c = true; else dev_priv->plane_stat.sprite_c = false; break; case 1: if (enable) dev_priv->plane_stat.sprite_d = true; else dev_priv->plane_stat.sprite_d = false; break; } } break; } } static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc, int refclk) { struct drm_device *dev = crtc->dev; const intel_limit_t *limit; if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { if (intel_is_dual_link_lvds(dev)) { if (refclk == 100000) limit = &intel_limits_ironlake_dual_lvds_100m; else limit = &intel_limits_ironlake_dual_lvds; } else { if (refclk == 100000) limit = &intel_limits_ironlake_single_lvds_100m; else limit = &intel_limits_ironlake_single_lvds; } } else limit = &intel_limits_ironlake_dac; return limit; } static const intel_limit_t *intel_g4x_limit(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; const intel_limit_t *limit; if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { if (intel_is_dual_link_lvds(dev)) limit = &intel_limits_g4x_dual_channel_lvds; else limit = &intel_limits_g4x_single_channel_lvds; } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI) || intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) { limit = &intel_limits_g4x_hdmi; } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO)) { limit = &intel_limits_g4x_sdvo; } else /* The option is for other outputs */ limit = &intel_limits_i9xx_sdvo; return limit; } static const intel_limit_t *intel_limit(struct drm_crtc *crtc, int refclk) { struct drm_device *dev = crtc->dev; const intel_limit_t *limit; if (HAS_PCH_SPLIT(dev)) limit = intel_ironlake_limit(crtc, refclk); else if (IS_G4X(dev)) { limit = intel_g4x_limit(crtc); } else if (IS_PINEVIEW(dev)) { if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) limit = &intel_limits_pineview_lvds; else limit = &intel_limits_pineview_sdvo; } else if (IS_VALLEYVIEW(dev)) { if (intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) limit = &intel_limits_vlv_dac; else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) limit = &intel_limits_vlv_hdmi; else limit = &intel_limits_vlv_dp; } else if (!IS_GEN2(dev)) { if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) limit = &intel_limits_i9xx_lvds; else limit = &intel_limits_i9xx_sdvo; } else { if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) limit = &intel_limits_i8xx_lvds; else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DVO)) limit = &intel_limits_i8xx_dvo; else limit = &intel_limits_i8xx_dac; } return limit; } /* m1 is reserved as 0 in Pineview, n is a ring counter */ static void pineview_clock(int refclk, intel_clock_t *clock) { clock->m = clock->m2 + 2; clock->p = clock->p1 * clock->p2; clock->vco = refclk * clock->m / clock->n; clock->dot = clock->vco / clock->p; } static uint32_t i9xx_dpll_compute_m(struct dpll *dpll) { return 5 * (dpll->m1 + 2) + (dpll->m2 + 2); } static void i9xx_clock(int refclk, intel_clock_t *clock) { clock->m = i9xx_dpll_compute_m(clock); clock->p = clock->p1 * clock->p2; clock->vco = refclk * clock->m / (clock->n + 2); clock->dot = clock->vco / clock->p; } /** * Returns whether any output on the specified pipe is of the specified type */ bool intel_pipe_has_type(const struct drm_crtc *crtc, int type) { struct drm_device *dev = crtc->dev; struct intel_encoder *encoder; for_each_encoder_on_crtc(dev, crtc, encoder) if (encoder->type == type) return true; return false; } #define INTELPllInvalid(s) do { /* DRM_DEBUG(s); */ return false; } while (0) /** * Returns whether the given set of divisors are valid for a given refclk with * the given connectors. */ static bool intel_PLL_is_valid(struct drm_device *dev, const intel_limit_t *limit, const intel_clock_t *clock) { if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1) INTELPllInvalid("p1 out of range\n"); if (clock->p < limit->p.min || limit->p.max < clock->p) INTELPllInvalid("p out of range\n"); if (clock->m2 < limit->m2.min || limit->m2.max < clock->m2) INTELPllInvalid("m2 out of range\n"); if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1) INTELPllInvalid("m1 out of range\n"); if (clock->m1 <= clock->m2 && !IS_PINEVIEW(dev)) INTELPllInvalid("m1 <= m2\n"); if (clock->m < limit->m.min || limit->m.max < clock->m) INTELPllInvalid("m out of range\n"); if (clock->n < limit->n.min || limit->n.max < clock->n) INTELPllInvalid("n out of range\n"); if (clock->vco < limit->vco.min || limit->vco.max < clock->vco) INTELPllInvalid("vco out of range\n"); /* XXX: We may need to be checking "Dot clock" depending on the multiplier, * connector, etc., rather than just a single range. */ if (clock->dot < limit->dot.min || limit->dot.max < clock->dot) INTELPllInvalid("dot out of range\n"); return true; } static bool i9xx_find_best_dpll(const intel_limit_t *limit, struct drm_crtc *crtc, int target, int refclk, intel_clock_t *match_clock, intel_clock_t *best_clock) { struct drm_device *dev = crtc->dev; intel_clock_t clock; int err = target; if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { /* * For LVDS just rely on its current settings for dual-channel. * We haven't figured out how to reliably set up different * single/dual channel state, if we even can. */ if (intel_is_dual_link_lvds(dev)) clock.p2 = limit->p2.p2_fast; else clock.p2 = limit->p2.p2_slow; } else { if (target < limit->p2.dot_limit) clock.p2 = limit->p2.p2_slow; else clock.p2 = limit->p2.p2_fast; } memset(best_clock, 0, sizeof(*best_clock)); for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) { for (clock.m2 = limit->m2.min; clock.m2 <= limit->m2.max; clock.m2++) { if (clock.m2 >= clock.m1) break; for (clock.n = limit->n.min; clock.n <= limit->n.max; clock.n++) { for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max; clock.p1++) { int this_err; i9xx_clock(refclk, &clock); if (!intel_PLL_is_valid(dev, limit, &clock)) continue; if (match_clock && clock.p != match_clock->p) continue; this_err = abs(clock.dot - target); if (this_err < err) { *best_clock = clock; err = this_err; } } } } } return (err != target); } static bool pnv_find_best_dpll(const intel_limit_t *limit, struct drm_crtc *crtc, int target, int refclk, intel_clock_t *match_clock, intel_clock_t *best_clock) { struct drm_device *dev = crtc->dev; intel_clock_t clock; int err = target; if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { /* * For LVDS just rely on its current settings for dual-channel. * We haven't figured out how to reliably set up different * single/dual channel state, if we even can. */ if (intel_is_dual_link_lvds(dev)) clock.p2 = limit->p2.p2_fast; else clock.p2 = limit->p2.p2_slow; } else { if (target < limit->p2.dot_limit) clock.p2 = limit->p2.p2_slow; else clock.p2 = limit->p2.p2_fast; } memset(best_clock, 0, sizeof(*best_clock)); for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) { for (clock.m2 = limit->m2.min; clock.m2 <= limit->m2.max; clock.m2++) { for (clock.n = limit->n.min; clock.n <= limit->n.max; clock.n++) { for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max; clock.p1++) { int this_err; pineview_clock(refclk, &clock); if (!intel_PLL_is_valid(dev, limit, &clock)) continue; if (match_clock && clock.p != match_clock->p) continue; this_err = abs(clock.dot - target); if (this_err < err) { *best_clock = clock; err = this_err; } } } } } return (err != target); } static bool g4x_find_best_dpll(const intel_limit_t *limit, struct drm_crtc *crtc, int target, int refclk, intel_clock_t *match_clock, intel_clock_t *best_clock) { struct drm_device *dev = crtc->dev; intel_clock_t clock; int max_n; bool found; /* approximately equals target * 0.00585 */ int err_most = (target >> 8) + (target >> 9); found = false; if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { if (intel_is_dual_link_lvds(dev)) clock.p2 = limit->p2.p2_fast; else clock.p2 = limit->p2.p2_slow; } else { if (target < limit->p2.dot_limit) clock.p2 = limit->p2.p2_slow; else clock.p2 = limit->p2.p2_fast; } memset(best_clock, 0, sizeof(*best_clock)); max_n = limit->n.max; /* based on hardware requirement, prefer smaller n to precision */ for (clock.n = limit->n.min; clock.n <= max_n; clock.n++) { /* based on hardware requirement, prefere larger m1,m2 */ for (clock.m1 = limit->m1.max; clock.m1 >= limit->m1.min; clock.m1--) { for (clock.m2 = limit->m2.max; clock.m2 >= limit->m2.min; clock.m2--) { for (clock.p1 = limit->p1.max; clock.p1 >= limit->p1.min; clock.p1--) { int this_err; i9xx_clock(refclk, &clock); if (!intel_PLL_is_valid(dev, limit, &clock)) continue; this_err = abs(clock.dot - target); if (this_err < err_most) { *best_clock = clock; err_most = this_err; max_n = clock.n; found = true; } } } } } return found; } static bool vlv_find_best_dpll(const intel_limit_t *limit, struct drm_crtc *crtc, int target, int refclk, intel_clock_t *match_clock, intel_clock_t *best_clock) { #define LONG_OVERFLOW 0x7FFFFFFF #define DIFF_OVERFLOW (LONG_OVERFLOW/10000) u32 p1, p2, m1, m2, vco, bestn, bestm1, bestm2, bestp1, bestp2; u32 m, n, fastclk; u32 updrate, minupdate, p; long bestppm, ppm, absppm, ppmdiff, absppmdiff; unsigned long ulMult = 1; int dotclk, flag; flag = 0; dotclk = target * 1000; bestppm = 1000000; ppm = absppm = 0; fastclk = dotclk / (2*100); updrate = 0; minupdate = 19200; n = p = p1 = p2 = m = m1 = m2 = vco = bestn = 0; bestm1 = bestm2 = bestp1 = bestp2 = 0; /* based on hardware requirement, prefer smaller n to precision */ for (n = limit->n.min; n <= ((refclk) / minupdate); n++) { updrate = refclk / n; for (p1 = limit->p1.max; p1 > limit->p1.min; p1--) { for (p2 = limit->p2.p2_fast+1; p2 > 0; p2--) { if (p2 > 10) p2 = p2 - 1; p = p1 * p2; /* based on hardware requirement, prefer bigger * m1,m2 values */ for (m1 = limit->m1.min; m1 <= limit->m1.max; m1++) { m2 = (((2*(fastclk * p * n / m1 )) + refclk) / (2*refclk)); m = m1 * m2; vco = updrate * m; if (vco >= limit->vco.min && vco < limit->vco.max) { ppmdiff = ((100*vco)/p) - (100*fastclk); absppmdiff = (ppmdiff > 0) ? ppmdiff : (-ppmdiff); ulMult = 1; while (absppmdiff > DIFF_OVERFLOW) { absppmdiff /= 10; ulMult *= 10; } absppm = ((absppmdiff*10000) / fastclk)*ulMult; if (absppm < 100 && ((p1 * p2) > (bestp1 * bestp2))) { bestppm = 0; flag = 1; } if (absppm < bestppm - 10) { bestppm = absppm; flag = 1; } if (flag) { bestn = n; bestm1 = m1; bestm2 = m2; bestp1 = p1; bestp2 = p2; flag = 0; } } } } } } best_clock->n = bestn; best_clock->m1 = bestm1; best_clock->m2 = bestm2; best_clock->p1 = bestp1; best_clock->p2 = bestp2; /*clock = (refclk * m1 * m2) / (n * p1 * (p2 / 2)) / 10*/ best_clock->dot = (2 * ((refclk * bestm1 * bestm2) / bestn)) / (bestp1 * bestp2) / 10; return true; } enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv, enum pipe pipe) { struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); return intel_crtc->config.cpu_transcoder; } 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 * @pipe: pipe to wait for * * Wait for vblank to occur on a given pipe. Needed for various bits of * mode setting code. */ 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. * * This races with i915_driver_irq_handler() with the result * that either function could miss a vblank event. Here it is not * fatal, as we will either wait upon the next vblank interrupt or * timeout. Generally speaking intel_wait_for_vblank() is only * called during modeset at which time the GPU should be idle and * should *not* be performing page flips and thus not waiting on * vblanks... * Currently, the result of us stealing a vblank from the irq * handler is that a single frame will be skipped during swapbuffers. */ I915_WRITE(pipestat_reg, I915_READ(pipestat_reg) | PIPE_VBLANK_INTERRUPT_STATUS); /* Wait for vblank interrupt bit to set */ if (wait_for(I915_READ(pipestat_reg) & PIPE_VBLANK_INTERRUPT_STATUS, 50)) DRM_DEBUG_KMS("vblank wait timed out\n"); } /* * intel_wait_for_pipe_off - wait for pipe to turn off * @dev: drm device * @pipe: pipe to wait for * * After disabling a pipe, we can't wait for vblank in the usual way, * spinning on the vblank interrupt status bit, since we won't actually * see an interrupt when the pipe is disabled. * * On Gen4 and above: * wait for the pipe register state bit to turn off * * Otherwise: * wait for the display line value to settle (it usually * ends up stopping at the start of the next frame). * */ void intel_wait_for_pipe_off(struct drm_device *dev, int pipe) { struct drm_i915_private *dev_priv = dev->dev_private; enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, pipe); if (INTEL_INFO(dev)->gen >= 4) { int reg = PIPECONF(cpu_transcoder); /* Wait for the Pipe State to go off */ if (wait_for((I915_READ(reg) & I965_PIPECONF_ACTIVE) == 0, 100)) WARN(1, "pipe_off wait timed out\n"); } else { 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) & line_mask; mdelay(5); } while (((I915_READ(reg) & line_mask) != last_line) && time_after(timeout, jiffies)); if (time_after(jiffies, timeout)) WARN(1, "pipe_off wait timed out\n"); } } /* * ibx_digital_port_connected - is the specified port connected? * @dev_priv: i915 private structure * @port: the port to test * * Returns true if @port is connected, false otherwise. */ bool ibx_digital_port_connected(struct drm_i915_private *dev_priv, struct intel_digital_port *port) { u32 bit; if (HAS_PCH_IBX(dev_priv->dev)) { switch(port->port) { case PORT_B: bit = SDE_PORTB_HOTPLUG; break; case PORT_C: bit = SDE_PORTC_HOTPLUG; break; case PORT_D: bit = SDE_PORTD_HOTPLUG; break; default: return true; } } else { switch(port->port) { case PORT_B: bit = SDE_PORTB_HOTPLUG_CPT; break; case PORT_C: bit = SDE_PORTC_HOTPLUG_CPT; break; case PORT_D: bit = SDE_PORTD_HOTPLUG_CPT; break; default: return true; } } return I915_READ(SDEISR) & bit; } static const char *state_string(bool enabled) { return enabled ? "on" : "off"; } /* Only for pre-ILK configs */ void assert_pll(struct drm_i915_private *dev_priv, enum pipe pipe, bool state) { int reg; u32 val; bool cur_state; reg = DPLL(pipe); val = I915_READ(reg); cur_state = !!(val & DPLL_VCO_ENABLE); WARN(cur_state != state, "PLL state assertion failure (expected %s, current %s)\n", state_string(state), state_string(cur_state)); } /* XXX: the dsi pll is shared between MIPI DSI ports */ static void assert_dsi_pll(struct drm_i915_private *dev_priv, bool state) { u32 val; bool cur_state; mutex_lock(&dev_priv->dpio_lock); val = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL); mutex_unlock(&dev_priv->dpio_lock); cur_state = val & DSI_PLL_VCO_EN; WARN(cur_state != state, "DSI PLL state assertion failure (expected %s, current %s)\n", state_string(state), state_string(cur_state)); } #define assert_dsi_pll_enabled(d) assert_dsi_pll(d, true) #define assert_dsi_pll_disabled(d) assert_dsi_pll(d, false) struct intel_shared_dpll * intel_crtc_to_shared_dpll(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; if (crtc->config.shared_dpll < 0) return NULL; return &dev_priv->shared_dplls[crtc->config.shared_dpll]; } /* For ILK+ */ void assert_shared_dpll(struct drm_i915_private *dev_priv, struct intel_shared_dpll *pll, bool state) { bool cur_state; struct intel_dpll_hw_state hw_state; if (HAS_PCH_LPT(dev_priv->dev)) { DRM_DEBUG_DRIVER("LPT detected: skipping PCH PLL test\n"); return; } if (WARN (!pll, "asserting DPLL %s with no DPLL\n", state_string(state))) return; cur_state = pll->get_hw_state(dev_priv, pll, &hw_state); WARN(cur_state != state, "%s assertion failure (expected %s, current %s)\n", pll->name, state_string(state), state_string(cur_state)); } static void assert_fdi_tx(struct drm_i915_private *dev_priv, enum pipe pipe, bool state) { int reg; u32 val; bool cur_state; enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, pipe); if (HAS_DDI(dev_priv->dev)) { /* DDI does not have a specific FDI_TX register */ reg = TRANS_DDI_FUNC_CTL(cpu_transcoder); val = I915_READ(reg); cur_state = !!(val & TRANS_DDI_FUNC_ENABLE); } else { reg = FDI_TX_CTL(pipe); val = I915_READ(reg); cur_state = !!(val & FDI_TX_ENABLE); } WARN(cur_state != state, "FDI TX state assertion failure (expected %s, current %s)\n", state_string(state), state_string(cur_state)); } #define assert_fdi_tx_enabled(d, p) assert_fdi_tx(d, p, true) #define assert_fdi_tx_disabled(d, p) assert_fdi_tx(d, p, false) static void assert_fdi_rx(struct drm_i915_private *dev_priv, enum pipe pipe, bool state) { int reg; u32 val; bool cur_state; reg = FDI_RX_CTL(pipe); val = I915_READ(reg); cur_state = !!(val & FDI_RX_ENABLE); WARN(cur_state != state, "FDI RX state assertion failure (expected %s, current %s)\n", state_string(state), state_string(cur_state)); } #define assert_fdi_rx_enabled(d, p) assert_fdi_rx(d, p, true) #define assert_fdi_rx_disabled(d, p) assert_fdi_rx(d, p, false) static void assert_fdi_tx_pll_enabled(struct drm_i915_private *dev_priv, enum pipe pipe) { int reg; u32 val; /* ILK FDI PLL is always enabled */ if (dev_priv->info->gen == 5) return; /* On Haswell, DDI ports are responsible for the FDI PLL setup */ if (HAS_DDI(dev_priv->dev)) return; reg = FDI_TX_CTL(pipe); val = I915_READ(reg); WARN(!(val & FDI_TX_PLL_ENABLE), "FDI TX PLL assertion failure, should be active but is disabled\n"); } void assert_fdi_rx_pll(struct drm_i915_private *dev_priv, enum pipe pipe, bool state) { int reg; u32 val; bool cur_state; reg = FDI_RX_CTL(pipe); val = I915_READ(reg); cur_state = !!(val & FDI_RX_PLL_ENABLE); WARN(cur_state != state, "FDI RX PLL assertion failure (expected %s, current %s)\n", state_string(state), state_string(cur_state)); } static void assert_panel_unlocked(struct drm_i915_private *dev_priv, enum pipe pipe) { int pp_reg, lvds_reg; u32 val; enum pipe panel_pipe = PIPE_A; bool locked = true; if (HAS_PCH_SPLIT(dev_priv->dev)) { pp_reg = PCH_PP_CONTROL; lvds_reg = PCH_LVDS; } else { pp_reg = PP_CONTROL; lvds_reg = LVDS; } val = I915_READ(pp_reg); if (!(val & PANEL_POWER_ON) || ((val & PANEL_UNLOCK_REGS) == PANEL_UNLOCK_REGS)) locked = false; if (I915_READ(lvds_reg) & LVDS_PIPEB_SELECT) panel_pipe = PIPE_B; WARN(panel_pipe == pipe && locked, "panel assertion failure, pipe %c regs locked\n", pipe_name(pipe)); } void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, bool state) { int reg; u32 val; bool cur_state; enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, pipe); /* if we need the pipe A quirk it must be always on */ if (pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) state = true; if (!intel_display_power_enabled(dev_priv->dev, POWER_DOMAIN_TRANSCODER(cpu_transcoder))) { cur_state = false; } else { reg = PIPECONF(cpu_transcoder); val = I915_READ(reg); cur_state = !!(val & PIPECONF_ENABLE); } WARN(cur_state != state, "pipe %c assertion failure (expected %s, current %s)\n", pipe_name(pipe), state_string(state), state_string(cur_state)); } static void assert_plane(struct drm_i915_private *dev_priv, enum plane plane, bool state) { int reg; u32 val; bool cur_state; reg = DSPCNTR(plane); val = I915_READ(reg); cur_state = !!(val & DISPLAY_PLANE_ENABLE); WARN(cur_state != state, "plane %c assertion failure (expected %s, current %s)\n", plane_name(plane), state_string(state), state_string(cur_state)); } #define assert_plane_enabled(d, p) assert_plane(d, p, true) #define assert_plane_disabled(d, p) assert_plane(d, p, false) bool is_plane_enabled(struct drm_i915_private *dev_priv, enum plane plane) { int reg; u32 val; reg = DSPCNTR(plane); val = I915_READ(reg); return val & DISPLAY_PLANE_ENABLE; } bool is_sprite_enabled(struct drm_i915_private *dev_priv, enum pipe pipe, enum plane plane) { int reg; u32 val; reg = SPCNTR(pipe, plane); val = I915_READ(reg); return val & SP_ENABLE; } bool is_cursor_enabled(struct drm_i915_private *dev_priv, enum pipe pipe) { int reg; bool ret = false; u32 val; reg = CURCNTR(pipe); val = I915_READ(reg); /* check bit 5 of cursor control register. if bit 5 is 1, then cursor enabled */ ret = val & CUR_MODE_SEL_BIT; /* if bit 5 is 0, check if bit 2:0 are all zeroes */ if (false == ret) ret = val & CUR_ENABLE; return ret; } bool is_maxfifo_needed(struct drm_i915_private *dev_priv) { int cnt = 0; if (dev_priv->plane_stat.primary) cnt++; if (dev_priv->plane_stat.secondary) cnt++; if (dev_priv->plane_stat.sprite_a) cnt++; if (dev_priv->plane_stat.sprite_b) cnt++; if (dev_priv->plane_stat.sprite_c) cnt++; if (dev_priv->plane_stat.sprite_d) cnt++; if (cnt == 1) return true; else return false; } static void assert_planes_disabled(struct drm_i915_private *dev_priv, enum pipe pipe) { struct drm_device *dev = dev_priv->dev; int reg, i; u32 val; int cur_pipe; /* Primary planes are fixed to pipes on gen4+ */ if ((INTEL_INFO(dev)->gen >= 4 || IS_VALLEYVIEW(dev_priv->dev))) { reg = DSPCNTR(pipe); val = I915_READ(reg); WARN((val & DISPLAY_PLANE_ENABLE), "plane %c assertion failure, should be disabled but not\n", plane_name(pipe)); return; } /* Need to check both planes against the pipe */ for_each_pipe(i) { reg = DSPCNTR(i); val = I915_READ(reg); cur_pipe = (val & DISPPLANE_SEL_PIPE_MASK) >> DISPPLANE_SEL_PIPE_SHIFT; WARN((val & DISPLAY_PLANE_ENABLE) && pipe == cur_pipe, "plane %c assertion failure, should be off on pipe %c but is still active\n", plane_name(i), pipe_name(pipe)); } } static void assert_sprites_disabled(struct drm_i915_private *dev_priv, enum pipe pipe) { struct drm_device *dev = dev_priv->dev; int reg, i; u32 val; if (IS_VALLEYVIEW(dev)) { for (i = 0; i < dev_priv->num_plane; i++) { reg = SPCNTR(pipe, i); val = I915_READ(reg); WARN((val & SP_ENABLE), "sprite %c assertion failure, should be off on pipe %c but is still active\n", sprite_name(pipe, i), pipe_name(pipe)); } } else if (INTEL_INFO(dev)->gen >= 7) { reg = SPRCTL(pipe); val = I915_READ(reg); WARN((val & SPRITE_ENABLE), "sprite %c assertion failure, should be off on pipe %c but is still active\n", plane_name(pipe), pipe_name(pipe)); } else if (INTEL_INFO(dev)->gen >= 5) { reg = DVSCNTR(pipe); val = I915_READ(reg); WARN((val & DVS_ENABLE), "sprite %c assertion failure, should be off on pipe %c but is still active\n", plane_name(pipe), pipe_name(pipe)); } } static void assert_pch_refclk_enabled(struct drm_i915_private *dev_priv) { u32 val; bool enabled; if (HAS_PCH_LPT(dev_priv->dev)) { DRM_DEBUG_DRIVER("LPT does not has PCH refclk, skipping check\n"); return; } val = I915_READ(PCH_DREF_CONTROL); enabled = !!(val & (DREF_SSC_SOURCE_MASK | DREF_NONSPREAD_SOURCE_MASK | DREF_SUPERSPREAD_SOURCE_MASK)); WARN(!enabled, "PCH refclk assertion failure, should be active but is disabled\n"); } static void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv, enum pipe pipe) { int reg; u32 val; bool enabled; reg = PCH_TRANSCONF(pipe); val = I915_READ(reg); enabled = !!(val & TRANS_ENABLE); WARN(enabled, "transcoder assertion failed, should be off on pipe %c but is still active\n", pipe_name(pipe)); } static bool dp_pipe_enabled(struct drm_i915_private *dev_priv, enum pipe pipe, u32 port_sel, u32 val) { if ((val & DP_PORT_EN) == 0) return false; if (HAS_PCH_CPT(dev_priv->dev)) { u32 trans_dp_ctl_reg = TRANS_DP_CTL(pipe); u32 trans_dp_ctl = I915_READ(trans_dp_ctl_reg); if ((trans_dp_ctl & TRANS_DP_PORT_SEL_MASK) != port_sel) return false; } else { if ((val & DP_PIPE_MASK) != (pipe << 30)) return false; } return true; } static bool hdmi_pipe_enabled(struct drm_i915_private *dev_priv, enum pipe pipe, u32 val) { if ((val & SDVO_ENABLE) == 0) return false; if (HAS_PCH_CPT(dev_priv->dev)) { if ((val & SDVO_PIPE_SEL_MASK_CPT) != SDVO_PIPE_SEL_CPT(pipe)) return false; } else { if ((val & SDVO_PIPE_SEL_MASK) != SDVO_PIPE_SEL(pipe)) return false; } return true; } static bool lvds_pipe_enabled(struct drm_i915_private *dev_priv, enum pipe pipe, u32 val) { if ((val & LVDS_PORT_EN) == 0) return false; if (HAS_PCH_CPT(dev_priv->dev)) { if ((val & PORT_TRANS_SEL_MASK) != PORT_TRANS_SEL_CPT(pipe)) return false; } else { if ((val & LVDS_PIPE_MASK) != LVDS_PIPE(pipe)) return false; } return true; } static bool adpa_pipe_enabled(struct drm_i915_private *dev_priv, enum pipe pipe, u32 val) { if ((val & ADPA_DAC_ENABLE) == 0) return false; if (HAS_PCH_CPT(dev_priv->dev)) { if ((val & PORT_TRANS_SEL_MASK) != PORT_TRANS_SEL_CPT(pipe)) return false; } else { if ((val & ADPA_PIPE_SELECT_MASK) != ADPA_PIPE_SELECT(pipe)) return false; } return true; } static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv, enum pipe pipe, int reg, u32 port_sel) { u32 val = I915_READ(reg); WARN(dp_pipe_enabled(dev_priv, pipe, port_sel, val), "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n", reg, pipe_name(pipe)); WARN(HAS_PCH_IBX(dev_priv->dev) && (val & DP_PORT_EN) == 0 && (val & DP_PIPEB_SELECT), "IBX PCH dp port still using transcoder B\n"); } static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv, enum pipe pipe, int reg) { u32 val = I915_READ(reg); WARN(hdmi_pipe_enabled(dev_priv, pipe, val), "PCH HDMI (0x%08x) enabled on transcoder %c, should be disabled\n", reg, pipe_name(pipe)); WARN(HAS_PCH_IBX(dev_priv->dev) && (val & SDVO_ENABLE) == 0 && (val & SDVO_PIPE_B_SELECT), "IBX PCH hdmi port still using transcoder B\n"); } static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv, enum pipe pipe) { int reg; u32 val; assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_B, TRANS_DP_PORT_SEL_B); assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_C, TRANS_DP_PORT_SEL_C); assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_D, TRANS_DP_PORT_SEL_D); reg = PCH_ADPA; val = I915_READ(reg); WARN(adpa_pipe_enabled(dev_priv, pipe, val), "PCH VGA enabled on transcoder %c, should be disabled\n", pipe_name(pipe)); reg = PCH_LVDS; val = I915_READ(reg); WARN(lvds_pipe_enabled(dev_priv, pipe, val), "PCH LVDS enabled on transcoder %c, should be disabled\n", pipe_name(pipe)); assert_pch_hdmi_disabled(dev_priv, pipe, PCH_HDMIB); assert_pch_hdmi_disabled(dev_priv, pipe, PCH_HDMIC); assert_pch_hdmi_disabled(dev_priv, pipe, PCH_HDMID); } static void vlv_enable_pll(struct intel_crtc *crtc) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; int reg = DPLL(crtc->pipe); u32 dpll = crtc->config.dpll_hw_state.dpll; assert_pipe_disabled(dev_priv, crtc->pipe); /* No really, not for ILK+ */ BUG_ON(!IS_VALLEYVIEW(dev_priv->dev)); /* PLL is protected by panel, make sure we can write it */ if (IS_MOBILE(dev_priv->dev) && !IS_I830(dev_priv->dev)) assert_panel_unlocked(dev_priv, crtc->pipe); I915_WRITE(reg, dpll); POSTING_READ(reg); udelay(150); if (wait_for(((I915_READ(reg) & DPLL_LOCK_VLV) == DPLL_LOCK_VLV), 1)) DRM_ERROR("DPLL %d failed to lock\n", crtc->pipe); I915_WRITE(DPLL_MD(crtc->pipe), crtc->config.dpll_hw_state.dpll_md); POSTING_READ(DPLL_MD(crtc->pipe)); } static void i9xx_enable_pll(struct intel_crtc *crtc) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; int reg = DPLL(crtc->pipe); u32 dpll = crtc->config.dpll_hw_state.dpll; assert_pipe_disabled(dev_priv, crtc->pipe); /* No really, not for ILK+ */ BUG_ON(dev_priv->info->gen >= 5); /* PLL is protected by panel, make sure we can write it */ if (IS_MOBILE(dev) && !IS_I830(dev)) assert_panel_unlocked(dev_priv, crtc->pipe); I915_WRITE(reg, dpll); /* Wait for the clocks to stabilize. */ POSTING_READ(reg); udelay(150); if (INTEL_INFO(dev)->gen >= 4) { I915_WRITE(DPLL_MD(crtc->pipe), crtc->config.dpll_hw_state.dpll_md); } else { /* The pixel multiplier can only be updated once the * DPLL is enabled and the clocks are stable. * * So write it again. */ I915_WRITE(reg, dpll); } /* We do this three times for luck */ I915_WRITE(reg, dpll); POSTING_READ(reg); udelay(150); /* wait for warmup */ I915_WRITE(reg, dpll); POSTING_READ(reg); udelay(150); /* wait for warmup */ I915_WRITE(reg, dpll); POSTING_READ(reg); udelay(150); /* wait for warmup */ } /** * i9xx_disable_pll - disable a PLL * @dev_priv: i915 private structure * @pipe: pipe PLL to disable * * Disable the PLL for @pipe, making sure the pipe is off first. * * Note! This is for pre-ILK only. */ static void i9xx_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe) { int reg; u32 val; /* Don't disable pipe A or pipe A PLLs if needed */ if (pipe == PIPE_A && (dev_priv->quirks & QUIRK_PIPEA_FORCE)) return; /* Make sure the pipe isn't still relying on us */ assert_pipe_disabled(dev_priv, pipe); reg = DPLL(pipe); val = I915_READ(reg); val &= ~(DPLL_VCO_ENABLE | DPLL_EXT_BUFFER_ENABLE_VLV | DPLL_VGA_MODE_DIS | DPLL_INTEGRATED_CLOCK_VLV); if (pipe) val &= ~DPLL_REFA_CLK_ENABLE_VLV; I915_WRITE(reg, val); POSTING_READ(reg); } void vlv_wait_port_ready(struct drm_i915_private *dev_priv, int port) { u32 port_mask; if (!port) port_mask = DPLL_PORTB_READY_MASK; else port_mask = DPLL_PORTC_READY_MASK; if (wait_for((I915_READ(DPLL(0)) & port_mask) == 0, 1000)) WARN(1, "timed out waiting for port %c ready: 0x%08x\n", 'B' + port, I915_READ(DPLL(0))); } /** * ironlake_enable_shared_dpll - enable PCH PLL * @dev_priv: i915 private structure * @pipe: pipe PLL to enable * * The PCH PLL needs to be enabled before the PCH transcoder, since it * drives the transcoder clock. */ static void ironlake_enable_shared_dpll(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc); /* PCH PLLs only available on ILK, SNB and IVB */ BUG_ON(dev_priv->info->gen < 5); if (WARN_ON(pll == NULL)) return; if (WARN_ON(pll->refcount == 0)) return; DRM_DEBUG_KMS("enable %s (active %d, on? %d)for crtc %d\n", pll->name, pll->active, pll->on, crtc->base.base.id); if (pll->active++) { WARN_ON(!pll->on); assert_shared_dpll_enabled(dev_priv, pll); return; } WARN_ON(pll->on); DRM_DEBUG_KMS("enabling %s\n", pll->name); pll->enable(dev_priv, pll); pll->on = true; } static void intel_disable_shared_dpll(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc); /* PCH only available on ILK+ */ BUG_ON(dev_priv->info->gen < 5); if (WARN_ON(pll == NULL)) return; if (WARN_ON(pll->refcount == 0)) return; DRM_DEBUG_KMS("disable %s (active %d, on? %d) for crtc %d\n", pll->name, pll->active, pll->on, crtc->base.base.id); if (WARN_ON(pll->active == 0)) { assert_shared_dpll_disabled(dev_priv, pll); return; } assert_shared_dpll_enabled(dev_priv, pll); WARN_ON(!pll->on); if (--pll->active) return; DRM_DEBUG_KMS("disabling %s\n", pll->name); pll->disable(dev_priv, pll); pll->on = false; } static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv, enum pipe pipe) { struct drm_device *dev = dev_priv->dev; struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); uint32_t reg, val, pipeconf_val; /* PCH only available on ILK+ */ BUG_ON(dev_priv->info->gen < 5); /* Make sure PCH DPLL is enabled */ assert_shared_dpll_enabled(dev_priv, intel_crtc_to_shared_dpll(intel_crtc)); /* FDI must be feeding us bits for PCH ports */ assert_fdi_tx_enabled(dev_priv, pipe); assert_fdi_rx_enabled(dev_priv, pipe); if (HAS_PCH_CPT(dev)) { /* Workaround: Set the timing override bit before enabling the * pch transcoder. */ reg = TRANS_CHICKEN2(pipe); val = I915_READ(reg); val |= TRANS_CHICKEN2_TIMING_OVERRIDE; I915_WRITE(reg, val); } reg = PCH_TRANSCONF(pipe); val = I915_READ(reg); pipeconf_val = I915_READ(PIPECONF(pipe)); if (HAS_PCH_IBX(dev_priv->dev)) { /* * make the BPC in transcoder be consistent with * that in pipeconf reg. */ val &= ~PIPECONF_BPC_MASK; val |= pipeconf_val & PIPECONF_BPC_MASK; } val &= ~TRANS_INTERLACE_MASK; if ((pipeconf_val & PIPECONF_INTERLACE_MASK) == PIPECONF_INTERLACED_ILK) if (HAS_PCH_IBX(dev_priv->dev) && intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO)) val |= TRANS_LEGACY_INTERLACED_ILK; else val |= TRANS_INTERLACED; else val |= TRANS_PROGRESSIVE; I915_WRITE(reg, val | TRANS_ENABLE); if (wait_for(I915_READ(reg) & TRANS_STATE_ENABLE, 100)) DRM_ERROR("failed to enable transcoder %c\n", pipe_name(pipe)); } static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv, enum transcoder cpu_transcoder) { u32 val, pipeconf_val; /* PCH only available on ILK+ */ BUG_ON(dev_priv->info->gen < 5); /* FDI must be feeding us bits for PCH ports */ assert_fdi_tx_enabled(dev_priv, (enum pipe) cpu_transcoder); assert_fdi_rx_enabled(dev_priv, TRANSCODER_A); /* Workaround: set timing override bit. */ val = I915_READ(_TRANSA_CHICKEN2); val |= TRANS_CHICKEN2_TIMING_OVERRIDE; I915_WRITE(_TRANSA_CHICKEN2, val); val = TRANS_ENABLE; pipeconf_val = I915_READ(PIPECONF(cpu_transcoder)); if ((pipeconf_val & PIPECONF_INTERLACE_MASK_HSW) == PIPECONF_INTERLACED_ILK) val |= TRANS_INTERLACED; else val |= TRANS_PROGRESSIVE; I915_WRITE(LPT_TRANSCONF, val); if (wait_for(I915_READ(LPT_TRANSCONF) & TRANS_STATE_ENABLE, 100)) DRM_ERROR("Failed to enable PCH transcoder\n"); } static void ironlake_disable_pch_transcoder(struct drm_i915_private *dev_priv, enum pipe pipe) { struct drm_device *dev = dev_priv->dev; uint32_t reg, val; /* FDI relies on the transcoder */ assert_fdi_tx_disabled(dev_priv, pipe); assert_fdi_rx_disabled(dev_priv, pipe); /* Ports must be off as well */ assert_pch_ports_disabled(dev_priv, pipe); reg = PCH_TRANSCONF(pipe); val = I915_READ(reg); val &= ~TRANS_ENABLE; I915_WRITE(reg, val); /* wait for PCH transcoder off, transcoder state */ if (wait_for((I915_READ(reg) & TRANS_STATE_ENABLE) == 0, 50)) DRM_ERROR("failed to disable transcoder %c\n", pipe_name(pipe)); if (!HAS_PCH_IBX(dev)) { /* Workaround: Clear the timing override chicken bit again. */ reg = TRANS_CHICKEN2(pipe); val = I915_READ(reg); val &= ~TRANS_CHICKEN2_TIMING_OVERRIDE; I915_WRITE(reg, val); } } static void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv) { u32 val; val = I915_READ(LPT_TRANSCONF); val &= ~TRANS_ENABLE; I915_WRITE(LPT_TRANSCONF, val); /* wait for PCH transcoder off, transcoder state */ if (wait_for((I915_READ(LPT_TRANSCONF) & TRANS_STATE_ENABLE) == 0, 50)) DRM_ERROR("Failed to disable PCH transcoder\n"); /* Workaround: clear timing override bit. */ val = I915_READ(_TRANSA_CHICKEN2); val &= ~TRANS_CHICKEN2_TIMING_OVERRIDE; I915_WRITE(_TRANSA_CHICKEN2, val); } /** * intel_enable_pipe - enable a pipe, asserting requirements * @dev_priv: i915 private structure * @pipe: pipe to enable * @pch_port: on ILK+, is this pipe driving a PCH port or not * * Enable @pipe, making sure that various hardware specific requirements * are met, if applicable, e.g. PLL enabled, LVDS pairs enabled, etc. * * @pipe should be %PIPE_A or %PIPE_B. * * Will wait until the pipe is actually running (i.e. first vblank) before * returning. */ static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, bool pch_port, bool dsi) { enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, pipe); enum pipe pch_transcoder; int reg; u32 val; assert_planes_disabled(dev_priv, pipe); assert_sprites_disabled(dev_priv, pipe); if (HAS_PCH_LPT(dev_priv->dev)) pch_transcoder = TRANSCODER_A; else pch_transcoder = pipe; /* * A pipe without a PLL won't actually be able to drive bits from * a plane. On ILK+ the pipe PLLs are integrated, so we don't * need the check. */ if (!HAS_PCH_SPLIT(dev_priv->dev)) if (dsi) assert_dsi_pll_enabled(dev_priv); else assert_pll_enabled(dev_priv, pipe); else { if (pch_port) { /* if driving the PCH, we need FDI enabled */ assert_fdi_rx_pll_enabled(dev_priv, pch_transcoder); assert_fdi_tx_pll_enabled(dev_priv, (enum pipe) cpu_transcoder); } /* FIXME: assert CPU port conditions for SNB+ */ } reg = PIPECONF(cpu_transcoder); val = I915_READ(reg); if (val & PIPECONF_ENABLE) return; I915_WRITE(reg, val | PIPECONF_ENABLE); /* No need to wait in case of mipi. * Since data will flow only when port is enabled. * wait for vblank will time out for mipi */ if (!dsi) intel_wait_for_vblank(dev_priv->dev, pipe); else POSTING_READ(reg); } /** * intel_disable_pipe - disable a pipe, asserting requirements * @dev_priv: i915 private structure * @pipe: pipe to disable * * Disable @pipe, making sure that various hardware specific requirements * are met, if applicable, e.g. plane disabled, panel fitter off, etc. * * @pipe should be %PIPE_A or %PIPE_B. * * Will wait until the pipe has shut down before returning. */ static void intel_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe) { enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, pipe); int reg; u32 val; /* * Make sure planes won't keep trying to pump pixels to us, * or we might hang the display. */ assert_planes_disabled(dev_priv, pipe); assert_sprites_disabled(dev_priv, pipe); /* Don't disable pipe A or pipe A PLLs if needed */ if (pipe == PIPE_A && (dev_priv->quirks & QUIRK_PIPEA_FORCE)) return; reg = PIPECONF(cpu_transcoder); val = I915_READ(reg); if ((val & PIPECONF_ENABLE) == 0) return; I915_WRITE(reg, val & ~PIPECONF_ENABLE); // intel_wait_for_pipe_off(dev_priv->dev, pipe); } /* * Plane regs are double buffered, going from enabled->disabled needs a * trigger in order to latch. The display address reg provides this. */ void intel_flush_display_plane(struct drm_i915_private *dev_priv, enum plane plane) { if (dev_priv->info->gen >= 4) I915_WRITE(DSPSURF(plane), I915_READ(DSPSURF(plane))); else I915_WRITE(DSPADDR(plane), I915_READ(DSPADDR(plane))); } /** * intel_enable_plane - enable a display plane on a given pipe * @dev_priv: i915 private structure * @plane: plane to enable * @pipe: pipe being fed * * Enable @plane on @pipe, making sure that @pipe is running first. */ static void intel_enable_plane(struct drm_i915_private *dev_priv, enum plane plane, enum pipe pipe) { int reg; u32 val; struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; /* If the pipe isn't enabled, we can't pump pixels and may hang */ assert_pipe_enabled(dev_priv, pipe); reg = DSPCNTR(plane); val = I915_READ(reg); if (val & DISPLAY_PLANE_ENABLE) return; I915_WRITE(reg, val | DISPLAY_PLANE_ENABLE); i915_update_plane_stat(dev_priv, pipe, plane, true, DISPLAY_PLANE); intel_flush_display_plane(dev_priv, plane); /* No need to wait in case of mipi. * Since data will flow only when port is enabled. * wait for vblank will time out for mipi */ if (!intel_pipe_has_type(crtc, INTEL_OUTPUT_DSI)) intel_wait_for_vblank(dev_priv->dev, pipe); else POSTING_READ(reg); } /** * intel_disable_plane - disable a display plane * @dev_priv: i915 private structure * @plane: plane to disable * @pipe: pipe consuming the data * * Disable @plane; should be an independent operation. */ static void intel_disable_plane(struct drm_i915_private *dev_priv, enum plane plane, enum pipe pipe) { int reg; u32 val; reg = DSPCNTR(plane); val = I915_READ(reg); if ((val & DISPLAY_PLANE_ENABLE) == 0) return; /* If MAX FIFO enabled disable */ if (dev_priv->maxfifo_enabled) { I915_WRITE(FW_BLC_SELF_VLV, ~FW_CSPWRDWNEN); dev_priv->maxfifo_enabled = false; } I915_WRITE(reg, val & ~DISPLAY_PLANE_ENABLE); i915_update_plane_stat(dev_priv, pipe, plane, false, DISPLAY_PLANE); intel_flush_display_plane(dev_priv, plane); intel_wait_for_vblank(dev_priv->dev, pipe); /* disable the sprite planes */ if (IS_VALLEYVIEW(dev_priv->dev)) { int i; for (i = 0; i < VLV_NUM_SPRITES; i++) { val = I915_READ(SPCNTR(pipe, i)); if ((val & SP_ENABLE) == 0) break; I915_WRITE(SPCNTR(pipe, i), (val & ~SP_ENABLE)); /* Activate double buffered register update */ I915_MODIFY_DISPBASE(SPSURF(pipe, i), 0); POSTING_READ(SPSURF(pipe, i)); } } } static bool need_vtd_wa(struct drm_device *dev) { #ifdef CONFIG_INTEL_IOMMU if (INTEL_INFO(dev)->gen >= 6 && intel_iommu_gfx_mapped) return true; #endif return false; } int intel_pin_and_fence_fb_obj(struct drm_device *dev, struct drm_i915_gem_object *obj, struct intel_ring_buffer *pipelined) { struct drm_i915_private *dev_priv = dev->dev_private; u32 alignment = 0; int ret; switch (obj->tiling_mode) { case I915_TILING_NONE: if (IS_BROADWATER(dev) || IS_CRESTLINE(dev) || IS_VALLEYVIEW(dev)) alignment = 128 * 1024; else if (INTEL_INFO(dev)->gen >= 4) alignment = 4 * 1024; else alignment = 64 * 1024; break; case I915_TILING_X: /* pin() will align the object as required by fence */ alignment = 0; break; case I915_TILING_Y: /* 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(); } /* Note that the w/a also requires 64 PTE of padding following the * bo. We currently fill all unused PTE with the shadow page and so * we should always have valid PTE following the scanout preventing * the VT-d warning. */ if (need_vtd_wa(dev) && alignment < 256 * 1024) alignment = 256 * 1024; dev_priv->mm.interruptible = false; ret = i915_gem_object_pin_to_display_plane(obj, alignment, pipelined); if (ret) goto err_interruptible; /* Install a fence for tiled scan-out. Pre-i965 always needs a * fence, whereas 965+ only requires a fence if using * framebuffer compression. For simplicity, we always install * a fence as the cost is not that onerous. */ ret = i915_gem_object_get_fence(obj); if (ret) goto err_unpin; i915_gem_object_pin_fence(obj); dev_priv->mm.interruptible = true; return 0; err_unpin: i915_gem_object_unpin_from_display_plane(obj); err_interruptible: dev_priv->mm.interruptible = true; return ret; } void intel_unpin_fb_obj(struct drm_i915_gem_object *obj) { i915_gem_object_unpin_fence(obj); i915_gem_object_unpin_from_display_plane(obj); intel_drop_scratch_page_for_fb(obj); } int i915_enable_plane_reserved_reg_bit_2(struct drm_device *dev, void *data, struct drm_file *file) { struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_reserved_reg_bit_2 *rrb; u32 reg, val; if (!data) return -EINVAL; rrb = data; switch (rrb->plane) { case SPRITEA: /* SPRITE A */ reg = SPSURF(0, 0); break; case SPRITEB: /* SPRITE B */ reg = SPSURF(0, 1); break; case SPRITEC: /* SPRITE C */ reg = SPSURF(1, 0); break; case SPRITED: /* SPRITE D */ reg = SPSURF(1, 1); break; default: return -EINVAL; } /* Program bit enable if it was requested */ if (rrb->enable) { val = I915_READ(reg); val |= PLANE_RESERVED_REG_BIT_2_ENABLE; I915_WRITE(reg, val); } else { /* Clear the older rrb setting*/ val = I915_READ(reg); val &= ~PLANE_RESERVED_REG_BIT_2_ENABLE; I915_WRITE(reg, val); } return 0; } /* Computes the linear offset to the base tile and adjusts x, y. bytes per pixel * is assumed to be a power-of-two. */ unsigned long intel_gen4_compute_page_offset(int *x, int *y, unsigned int tiling_mode, unsigned int cpp, unsigned int pitch) { if (tiling_mode != I915_TILING_NONE) { unsigned int tile_rows, tiles; tile_rows = *y / 8; *y %= 8; tiles = *x / (512/cpp); *x %= 512/cpp; return tile_rows * pitch * 8 + tiles * 4096; } else { unsigned int offset; offset = *y * pitch + *x * cpp; *y = 0; *x = (offset & 4095) / cpp; return offset & -4096; } } int i915_set_plane_180_rotation(struct drm_device *dev, void *data, struct drm_file *file) { struct drm_i915_plane_180_rotation *rotation = data; struct drm_mode_object *obj; struct drm_crtc *crtc; struct intel_crtc *intel_crtc; struct drm_plane *plane; struct intel_plane *intel_plane; int ret = -EINVAL; if (rotation->obj_type == DRM_MODE_OBJECT_PLANE) { obj = drm_mode_object_find(dev, rotation->obj_id, DRM_MODE_OBJECT_PLANE); if (!obj) { DRM_DEBUG_DRIVER("Unknown PLANE ID %d\n", rotation->obj_id); return -EINVAL; } plane = obj_to_plane(obj); intel_plane = to_intel_plane(plane); intel_plane->rotate180 = (rotation->rotate & 0x1) ? true : false; ret = 0; } else if (rotation->obj_type == DRM_MODE_OBJECT_CRTC) { obj = drm_mode_object_find(dev, rotation->obj_id, DRM_MODE_OBJECT_CRTC); if (!obj) { DRM_DEBUG_DRIVER("Unknown CRTC ID %d\n", rotation->obj_id); return -EINVAL; } crtc = obj_to_crtc(obj); intel_crtc = to_intel_crtc(crtc); intel_crtc->rotate180 = (rotation->rotate & 0x1) ? true : false; ret = 0; } return ret; } void i9xx_get_pfit_mode(struct drm_crtc *crtc, uint32_t src_w, uint32_t src_h) { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct drm_display_mode *adjusted_mode = &intel_crtc->config.adjusted_mode; u32 scaled_width = adjusted_mode->hdisplay * src_h; u32 scaled_height = src_w * adjusted_mode->vdisplay; u32 pfit_control = intel_crtc->config.gmch_pfit.control; if (scaled_width > scaled_height) { pfit_control &= MASK_PFIT_SCALING_MODE; pfit_control |= PFIT_SCALING_PILLAR; } else if (scaled_width < scaled_height) { pfit_control &= MASK_PFIT_SCALING_MODE; pfit_control |= PFIT_SCALING_LETTER; } else if (!(adjusted_mode->hdisplay <= (src_w+25) && adjusted_mode->hdisplay >= (src_w-25))) { /* * TODO: If native width doest not lies b/n src layer * width-25 and width+25, we put pfit in auto scale, * not expecting variation more than 25 */ pfit_control &= MASK_PFIT_SCALING_MODE; pfit_control |= PFIT_SCALING_AUTO; } intel_crtc->config.gmch_pfit.control = pfit_control; } static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb, int x, int y) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_framebuffer *intel_fb; struct drm_i915_gem_object *obj; struct drm_display_mode *mode = &intel_crtc->config.requested_mode; int plane = intel_crtc->plane; int pipe = intel_crtc->pipe; unsigned long linear_offset; bool rotate = false; u32 dspcntr; u32 reg; u32 mask; int pixel_size; int plane_ddl, prec_multi, plane_prec_multi; switch (plane) { case 0: case 1: break; default: DRM_ERROR("Can't update plane %c in SAREA\n", plane_name(plane)); return -EINVAL; } pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); intel_fb = to_intel_framebuffer(fb); obj = intel_fb->obj; reg = DSPCNTR(plane); /* * In case of atomic update, primary enable/disable is already cached as * part of sprite flip, make use of that over here */ if (intel_crtc->pri_update && dev_priv->atomic_update) { dspcntr = intel_crtc->reg.cntr; intel_crtc->pri_update = false; } else dspcntr = I915_READ(reg); /* Mask out pixel format bits in case we change it */ dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; switch (fb->pixel_format) { case DRM_FORMAT_C8: dspcntr |= DISPPLANE_8BPP; break; case DRM_FORMAT_RGB565: dspcntr |= DISPPLANE_BGRX565; break; case DRM_FORMAT_XRGB8888: dspcntr |= DISPPLANE_BGRX888; break; case DRM_FORMAT_ARGB8888: if (!intel_crtc->alpha) dspcntr |= DISPPLANE_BGRX888; else dspcntr |= DISPPLANE_BGRA888; break; case DRM_FORMAT_XBGR8888: dspcntr |= DISPPLANE_RGBX888; break; case DRM_FORMAT_ABGR8888: if (!intel_crtc->alpha) dspcntr |= DISPPLANE_RGBX888; else dspcntr |= DISPPLANE_RGBA888; break; case DRM_FORMAT_XRGB2101010: dspcntr |= DISPPLANE_BGRX101010; break; case DRM_FORMAT_ARGB2101010: if (!intel_crtc->alpha) dspcntr |= DISPPLANE_BGRX101010; else dspcntr |= DISPPLANE_BGRA101010; break; case DRM_FORMAT_XBGR2101010: dspcntr |= DISPPLANE_RGBX101010; break; case DRM_FORMAT_ABGR2101010: if (!intel_crtc->alpha) dspcntr |= DISPPLANE_RGBX101010; else dspcntr |= DISPPLANE_RGBA101010; break; default: BUG(); } if (!intel_crtc->rotate180 != !((dev_priv->vbt.is_180_rotation_enabled) && (pipe == 0))) rotate = true; if (INTEL_INFO(dev)->gen >= 4) { if (obj->tiling_mode != I915_TILING_NONE) dspcntr |= DISPPLANE_TILED; else dspcntr &= ~DISPPLANE_TILED; } if (IS_G4X(dev)) dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE; if (rotate) dspcntr |= DISPPLANE_180_ROTATION_ENABLE; else dspcntr &= ~DISPPLANE_180_ROTATION_ENABLE; if (IS_VALLEYVIEW(dev)) { /* if panel fitter is enabled program the input src size */ if (intel_crtc->scaling_src_size && (intel_crtc->config.gmch_pfit.control & PFIT_ENABLE)) { intel_crtc->reg.pfit_control = intel_crtc->config.gmch_pfit.control; intel_crtc->reg.pipesrc = intel_crtc->scaling_src_size; if (!dev_priv->atomic_update) { I915_WRITE(PFIT_CONTROL, intel_crtc->reg.pfit_control); I915_WRITE(PIPESRC(pipe), intel_crtc->reg.pipesrc); intel_crtc->pfit_en_status = true; } } else if (intel_crtc->pfit_en_status) { intel_crtc->reg.pfit_control = intel_crtc->config.gmch_pfit.control; intel_crtc->reg.pipesrc = ((mode->hdisplay - 1) << SCALING_SRCSIZE_SHIFT) | (mode->vdisplay - 1); if (!dev_priv->atomic_update) { I915_WRITE(PIPESRC(pipe), intel_crtc->reg.pipesrc); I915_WRITE(PFIT_CONTROL, intel_crtc->reg.pfit_control); intel_crtc->pfit_en_status = false; } } } /* When in maxfifo dspcntr cannot be changed */ if (dspcntr != I915_READ(DSPCNTR(pipe)) && dev_priv->maxfifo_enabled && dev_priv->atomic_update) { I915_WRITE(FW_BLC_SELF_VLV, ~FW_CSPWRDWNEN); dev_priv->maxfifo_enabled = false; dev_priv->wait_vbl = true; dev_priv->vblcount = atomic_read( &dev->_vblank_count[intel_crtc->pipe]); } /* * calculate the DDL and set to 0 is there is a change. Else cache * the value and wrrite on next vblank. */ mask = 0x000000ff; vlv_calculate_ddl(crtc, pixel_size, &prec_multi, &plane_ddl); plane_prec_multi = (prec_multi == DRAIN_LATENCY_PRECISION_32) ? DDL_PLANE_PRECISION_32 : DDL_PLANE_PRECISION_64; plane_ddl = plane_prec_multi | (plane_ddl); intel_crtc->reg_ddl.plane_ddl = plane_ddl; intel_crtc->reg_ddl.plane_ddl_mask = mask; if (((plane_ddl & mask) != (I915_READ(VLV_DDL(pipe)) & mask)) || !(dspcntr & DISPLAY_PLANE_ENABLE)) { I915_WRITE_BITS(VLV_DDL(pipe), 0x00, mask); if (!(dspcntr & DISPLAY_PLANE_ENABLE)) intel_crtc->reg_ddl.plane_ddl = 0; } intel_crtc->reg.cntr = dspcntr; if (!dev_priv->atomic_update) I915_WRITE(reg, intel_crtc->reg.cntr); linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8); if (INTEL_INFO(dev)->gen >= 4) { intel_crtc->dspaddr_offset = intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode, fb->bits_per_pixel / 8, fb->pitches[0]); linear_offset -= intel_crtc->dspaddr_offset; } else { intel_crtc->dspaddr_offset = linear_offset; } intel_crtc->reg.stride = fb->pitches[0]; if (!dev_priv->atomic_update) I915_WRITE(DSPSTRIDE(plane), intel_crtc->reg.stride); if (INTEL_INFO(dev)->gen >= 4) { intel_crtc->reg.surf = i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset; if (!dev_priv->atomic_update) I915_MODIFY_DISPBASE(DSPSURF(plane), i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset); if (rotate) { intel_crtc->reg.tileoff = (((y + mode->vdisplay - 1) << 16) | (x + mode->hdisplay - 1)); /* Linear Offset should be the difference b/w the last pixel of * the last line of the display data in its unrotated orientation * and the display surface address. */ intel_crtc->reg.linoff = linear_offset + (mode->vdisplay - 1) * fb->pitches[0] + (mode->hdisplay - 1) * pixel_size; if (!dev_priv->atomic_update) { I915_WRITE(DSPTILEOFF(plane), intel_crtc->reg.tileoff); I915_WRITE(DSPLINOFF(plane), intel_crtc->reg.linoff); } } else { intel_crtc->reg.tileoff = (y << 16) | x; intel_crtc->reg.linoff = linear_offset; if (!dev_priv->atomic_update) { I915_WRITE(DSPTILEOFF(plane), intel_crtc->reg.tileoff); I915_WRITE(DSPLINOFF(plane), intel_crtc->reg.linoff); } } } else I915_WRITE(DSPADDR(plane), i915_gem_obj_ggtt_offset(obj) + linear_offset); POSTING_READ(reg); return 0; } static int ironlake_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb, int x, int y) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_framebuffer *intel_fb; struct drm_i915_gem_object *obj; int plane = intel_crtc->plane; unsigned long linear_offset; u32 dspcntr; u32 reg; switch (plane) { case 0: case 1: case 2: break; default: DRM_ERROR("Can't update plane %c in SAREA\n", plane_name(plane)); return -EINVAL; } intel_fb = to_intel_framebuffer(fb); obj = intel_fb->obj; reg = DSPCNTR(plane); dspcntr = I915_READ(reg); /* Mask out pixel format bits in case we change it */ dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; switch (fb->pixel_format) { case DRM_FORMAT_C8: dspcntr |= DISPPLANE_8BPP; break; case DRM_FORMAT_RGB565: dspcntr |= DISPPLANE_BGRX565; break; case DRM_FORMAT_XRGB8888: case DRM_FORMAT_ARGB8888: dspcntr |= DISPPLANE_BGRX888; break; case DRM_FORMAT_XBGR8888: case DRM_FORMAT_ABGR8888: dspcntr |= DISPPLANE_RGBX888; break; case DRM_FORMAT_XRGB2101010: case DRM_FORMAT_ARGB2101010: dspcntr |= DISPPLANE_BGRX101010; break; case DRM_FORMAT_XBGR2101010: case DRM_FORMAT_ABGR2101010: dspcntr |= DISPPLANE_RGBX101010; break; default: BUG(); } if (obj->tiling_mode != I915_TILING_NONE) dspcntr |= DISPPLANE_TILED; else dspcntr &= ~DISPPLANE_TILED; /* must disable */ dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE; I915_WRITE(reg, dspcntr); linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8); intel_crtc->dspaddr_offset = intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode, fb->bits_per_pixel / 8, fb->pitches[0]); linear_offset -= intel_crtc->dspaddr_offset; DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n", i915_gem_obj_ggtt_offset(obj), linear_offset, x, y, fb->pitches[0]); I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]); I915_MODIFY_DISPBASE(DSPSURF(plane), i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset); if (IS_HASWELL(dev)) { I915_WRITE(DSPOFFSET(plane), (y << 16) | x); } else { I915_WRITE(DSPTILEOFF(plane), (y << 16) | x); I915_WRITE(DSPLINOFF(plane), linear_offset); } POSTING_READ(reg); return 0; } /* Assume fb object is pinned & idle & fenced and just update base pointers */ static int intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, int x, int y, enum mode_set_atomic state) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; if (dev_priv->display.disable_fbc) dev_priv->display.disable_fbc(dev); intel_increase_pllclock(crtc); return dev_priv->display.update_plane(crtc, fb, x, y); } void intel_display_handle_reset(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct drm_crtc *crtc; /* * Flips in the rings have been nuked by the reset, * so complete all pending flips so that user space * will get its events and not get stuck. * * Also update the base address of all primary * planes to the the last fb to make sure we're * showing the correct fb after a reset. * * Need to make two loops over the crtcs so that we * don't try to grab a crtc mutex before the * pending_flip_queue really got woken up. * * For MMIO based page flips it is also possible that * the GPU could be reset between requesting the page * flip and before it reaches the next vblank when it * would normally send the page flip interrupt. * In that case we would be left with unpin work that * will not get cleaned up so we must cleanup any * pending page flips after a global reset. */ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); enum plane plane = intel_crtc->plane; intel_prepare_page_flip(dev, plane); intel_finish_page_flip_plane(dev, plane); intel_prepare_sprite_page_flip(dev, intel_crtc->pipe); intel_finish_sprite_page_flip(dev, intel_crtc->pipe); } list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); mutex_lock(&crtc->mutex); if (intel_crtc->active) { if (!intel_crtc->primary_disabled) dev_priv->display.update_plane(crtc, crtc->fb, crtc->x, crtc->y); } mutex_unlock(&crtc->mutex); } } static int intel_finish_fb(struct drm_framebuffer *old_fb) { struct drm_i915_gem_object *obj = to_intel_framebuffer(old_fb)->obj; struct drm_i915_private *dev_priv = obj->base.dev->dev_private; bool was_interruptible = dev_priv->mm.interruptible; int ret; /* Big Hammer, we also need to ensure that any pending * MI_WAIT_FOR_EVENT inside a user batch buffer on the * current scanout is retired before unpinning the old * framebuffer. * * This should only fail upon a hung GPU, in which case we * can safely continue. */ dev_priv->mm.interruptible = false; ret = i915_gem_object_finish_gpu(obj); dev_priv->mm.interruptible = was_interruptible; return ret; } static void intel_crtc_update_sarea_pos(struct drm_crtc *crtc, int x, int y) { struct drm_device *dev = crtc->dev; struct drm_i915_master_private *master_priv; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int pipe = intel_crtc->pipe; if (!dev->primary->master) return; master_priv = dev->primary->master->driver_priv; if (!master_priv->sarea_priv) return; switch (pipe) { case 0: master_priv->sarea_priv->pipeA_x = x; master_priv->sarea_priv->pipeA_y = y; break; case 1: master_priv->sarea_priv->pipeB_x = x; master_priv->sarea_priv->pipeB_y = y; break; default: break; } } static int intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *fb) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct drm_framebuffer *old_fb; int ret; /* no fb bound */ if (!fb) { DRM_ERROR("No FB bound\n"); return 0; } if (intel_crtc->plane > INTEL_INFO(dev)->num_pipes) { DRM_ERROR("no plane for crtc: plane %c, num_pipes %d\n", plane_name(intel_crtc->plane), INTEL_INFO(dev)->num_pipes); return -EINVAL; } mutex_lock(&dev->struct_mutex); ret = intel_pin_and_fence_fb_obj(dev, to_intel_framebuffer(fb)->obj, NULL); if (ret != 0) { mutex_unlock(&dev->struct_mutex); DRM_ERROR("pin & fence failed\n"); return ret; } /* Update pipe size and adjust fitter if needed */ if (i915_fastboot) { I915_WRITE(PIPESRC(intel_crtc->pipe), ((crtc->mode.hdisplay - 1) << 16) | (crtc->mode.vdisplay - 1)); if (!intel_crtc->config.pch_pfit.size && (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) || intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))) { I915_WRITE(PF_CTL(intel_crtc->pipe), 0); I915_WRITE(PF_WIN_POS(intel_crtc->pipe), 0); I915_WRITE(PF_WIN_SZ(intel_crtc->pipe), 0); } } ret = dev_priv->display.update_plane(crtc, fb, x, y); if (ret) { intel_unpin_fb_obj(to_intel_framebuffer(fb)->obj); mutex_unlock(&dev->struct_mutex); DRM_ERROR("failed to update base address\n"); return ret; } old_fb = crtc->fb; crtc->fb = fb; crtc->x = x; crtc->y = y; if (old_fb) { if (intel_crtc->active && old_fb != fb) intel_wait_for_vblank(dev, intel_crtc->pipe); intel_unpin_fb_obj(to_intel_framebuffer(old_fb)->obj); } intel_update_fbc(dev); intel_update_drrs(dev); intel_edp_psr_update(dev); mutex_unlock(&dev->struct_mutex); intel_crtc_update_sarea_pos(crtc, x, y); return 0; } static void intel_fdi_normal_train(struct drm_crtc *crtc) { 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; u32 reg, temp; /* enable normal train */ reg = FDI_TX_CTL(pipe); temp = I915_READ(reg); if (IS_IVYBRIDGE(dev)) { temp &= ~FDI_LINK_TRAIN_NONE_IVB; temp |= FDI_LINK_TRAIN_NONE_IVB | FDI_TX_ENHANCE_FRAME_ENABLE; } else { temp &= ~FDI_LINK_TRAIN_NONE; temp |= FDI_LINK_TRAIN_NONE | FDI_TX_ENHANCE_FRAME_ENABLE; } I915_WRITE(reg, temp); reg = FDI_RX_CTL(pipe); temp = I915_READ(reg); if (HAS_PCH_CPT(dev)) { temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; temp |= FDI_LINK_TRAIN_NORMAL_CPT; } else { temp &= ~FDI_LINK_TRAIN_NONE; temp |= FDI_LINK_TRAIN_NONE; } I915_WRITE(reg, temp | FDI_RX_ENHANCE_FRAME_ENABLE); /* wait one idle pattern time */ POSTING_READ(reg); udelay(1000); /* IVB wants error correction enabled */ if (IS_IVYBRIDGE(dev)) I915_WRITE(reg, I915_READ(reg) | FDI_FS_ERRC_ENABLE | FDI_FE_ERRC_ENABLE); } static bool pipe_has_enabled_pch(struct intel_crtc *intel_crtc) { return intel_crtc->base.enabled && intel_crtc->config.has_pch_encoder; } static void ivb_modeset_global_resources(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *pipe_B_crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[PIPE_B]); struct intel_crtc *pipe_C_crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[PIPE_C]); uint32_t temp; /* * When everything is off disable fdi C so that we could enable fdi B * with all lanes. Note that we don't care about enabled pipes without * an enabled pch encoder. */ if (!pipe_has_enabled_pch(pipe_B_crtc) && !pipe_has_enabled_pch(pipe_C_crtc)) { WARN_ON(I915_READ(FDI_RX_CTL(PIPE_B)) & FDI_RX_ENABLE); WARN_ON(I915_READ(FDI_RX_CTL(PIPE_C)) & FDI_RX_ENABLE); temp = I915_READ(SOUTH_CHICKEN1); temp &= ~FDI_BC_BIFURCATION_SELECT; DRM_DEBUG_KMS("disabling fdi C rx\n"); I915_WRITE(SOUTH_CHICKEN1, temp); } } /* The FDI link training functions for ILK/Ibexpeak. */ static void ironlake_fdi_link_train(struct drm_crtc *crtc) { 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; int plane = intel_crtc->plane; u32 reg, temp, tries; /* FDI needs bits from pipe & plane first */ assert_pipe_enabled(dev_priv, pipe); assert_plane_enabled(dev_priv, plane); /* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit for train result */ reg = FDI_RX_IMR(pipe); temp = I915_READ(reg); temp &= ~FDI_RX_SYMBOL_LOCK; temp &= ~FDI_RX_BIT_LOCK; I915_WRITE(reg, temp); I915_READ(reg); udelay(150); /* enable CPU FDI TX and PCH FDI RX */ reg = FDI_TX_CTL(pipe); temp = I915_READ(reg); temp &= ~FDI_DP_PORT_WIDTH_MASK; temp |= FDI_DP_PORT_WIDTH(intel_crtc->config.fdi_lanes); temp &= ~FDI_LINK_TRAIN_NONE; temp |= FDI_LINK_TRAIN_PATTERN_1; I915_WRITE(reg, temp | FDI_TX_ENABLE); reg = FDI_RX_CTL(pipe); temp = I915_READ(reg); temp &= ~FDI_LINK_TRAIN_NONE; temp |= FDI_LINK_TRAIN_PATTERN_1; I915_WRITE(reg, temp | FDI_RX_ENABLE); POSTING_READ(reg); udelay(150); /* Ironlake workaround, enable clock pointer after FDI enable*/ I915_WRITE(FDI_RX_CHICKEN(pipe), FDI_RX_PHASE_SYNC_POINTER_OVR); I915_WRITE(FDI_RX_CHICKEN(pipe), FDI_RX_PHASE_SYNC_POINTER_OVR | FDI_RX_PHASE_SYNC_POINTER_EN); reg = FDI_RX_IIR(pipe); for (tries = 0; tries < 5; tries++) { temp = I915_READ(reg); DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); if ((temp & FDI_RX_BIT_LOCK)) { DRM_DEBUG_KMS("FDI train 1 done.\n"); I915_WRITE(reg, temp | FDI_RX_BIT_LOCK); break; } } if (tries == 5) DRM_ERROR("FDI train 1 fail!\n"); /* Train 2 */ reg = FDI_TX_CTL(pipe); temp = I915_READ(reg); temp &= ~FDI_LINK_TRAIN_NONE; temp |= FDI_LINK_TRAIN_PATTERN_2; I915_WRITE(reg, temp); reg = FDI_RX_CTL(pipe); temp = I915_READ(reg); temp &= ~FDI_LINK_TRAIN_NONE; temp |= FDI_LINK_TRAIN_PATTERN_2; I915_WRITE(reg, temp); POSTING_READ(reg); udelay(150); reg = FDI_RX_IIR(pipe); for (tries = 0; tries < 5; tries++) { temp = I915_READ(reg); DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); if (temp & FDI_RX_SYMBOL_LOCK) { I915_WRITE(reg, temp | FDI_RX_SYMBOL_LOCK); DRM_DEBUG_KMS("FDI train 2 done.\n"); break; } } if (tries == 5) DRM_ERROR("FDI train 2 fail!\n"); DRM_DEBUG_KMS("FDI train done\n"); } static const int snb_b_fdi_train_param[] = { FDI_LINK_TRAIN_400MV_0DB_SNB_B, FDI_LINK_TRAIN_400MV_6DB_SNB_B, FDI_LINK_TRAIN_600MV_3_5DB_SNB_B, FDI_LINK_TRAIN_800MV_0DB_SNB_B, }; /* The FDI link training functions for SNB/Cougarpoint. */ static void gen6_fdi_link_train(struct drm_crtc *crtc) { 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; u32 reg, temp, i, retry; /* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit for train result */ reg = FDI_RX_IMR(pipe); temp = I915_READ(reg); temp &= ~FDI_RX_SYMBOL_LOCK; temp &= ~FDI_RX_BIT_LOCK; I915_WRITE(reg, temp); POSTING_READ(reg); udelay(150); /* enable CPU FDI TX and PCH FDI RX */ reg = FDI_TX_CTL(pipe); temp = I915_READ(reg); temp &= ~FDI_DP_PORT_WIDTH_MASK; temp |= FDI_DP_PORT_WIDTH(intel_crtc->config.fdi_lanes); temp &= ~FDI_LINK_TRAIN_NONE; temp |= FDI_LINK_TRAIN_PATTERN_1; temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; /* SNB-B */ temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B; I915_WRITE(reg, temp | FDI_TX_ENABLE); I915_WRITE(FDI_RX_MISC(pipe), FDI_RX_TP1_TO_TP2_48 | FDI_RX_FDI_DELAY_90); reg = FDI_RX_CTL(pipe); temp = I915_READ(reg); if (HAS_PCH_CPT(dev)) { temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; temp |= FDI_LINK_TRAIN_PATTERN_1_CPT; } else { temp &= ~FDI_LINK_TRAIN_NONE; temp |= FDI_LINK_TRAIN_PATTERN_1; } I915_WRITE(reg, temp | FDI_RX_ENABLE); POSTING_READ(reg); udelay(150); for (i = 0; i < 4; i++) { reg = FDI_TX_CTL(pipe); temp = I915_READ(reg); temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; temp |= snb_b_fdi_train_param[i]; I915_WRITE(reg, temp); POSTING_READ(reg); udelay(500); for (retry = 0; retry < 5; retry++) { reg = FDI_RX_IIR(pipe); temp = I915_READ(reg); DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); if (temp & FDI_RX_BIT_LOCK) { I915_WRITE(reg, temp | FDI_RX_BIT_LOCK); DRM_DEBUG_KMS("FDI train 1 done.\n"); break; } udelay(50); } if (retry < 5) break; } if (i == 4) DRM_ERROR("FDI train 1 fail!\n"); /* Train 2 */ reg = FDI_TX_CTL(pipe); temp = I915_READ(reg); temp &= ~FDI_LINK_TRAIN_NONE; temp |= FDI_LINK_TRAIN_PATTERN_2; if (IS_GEN6(dev)) { temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; /* SNB-B */ temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B; } I915_WRITE(reg, temp); reg = FDI_RX_CTL(pipe); temp = I915_READ(reg); if (HAS_PCH_CPT(dev)) { temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; temp |= FDI_LINK_TRAIN_PATTERN_2_CPT; } else { temp &= ~FDI_LINK_TRAIN_NONE; temp |= FDI_LINK_TRAIN_PATTERN_2; } I915_WRITE(reg, temp); POSTING_READ(reg); udelay(150); for (i = 0; i < 4; i++) { reg = FDI_TX_CTL(pipe); temp = I915_READ(reg); temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; temp |= snb_b_fdi_train_param[i]; I915_WRITE(reg, temp); POSTING_READ(reg); udelay(500); for (retry = 0; retry < 5; retry++) { reg = FDI_RX_IIR(pipe); temp = I915_READ(reg); DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); if (temp & FDI_RX_SYMBOL_LOCK) { I915_WRITE(reg, temp | FDI_RX_SYMBOL_LOCK); DRM_DEBUG_KMS("FDI train 2 done.\n"); break; } udelay(50); } if (retry < 5) break; } if (i == 4) DRM_ERROR("FDI train 2 fail!\n"); DRM_DEBUG_KMS("FDI train done.\n"); } /* Manual link training for Ivy Bridge A0 parts */ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc) { 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; u32 reg, temp, i, j; /* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit for train result */ reg = FDI_RX_IMR(pipe); temp = I915_READ(reg); temp &= ~FDI_RX_SYMBOL_LOCK; temp &= ~FDI_RX_BIT_LOCK; I915_WRITE(reg, temp); POSTING_READ(reg); udelay(150); DRM_DEBUG_KMS("FDI_RX_IIR before link train 0x%x\n", I915_READ(FDI_RX_IIR(pipe))); /* Try each vswing and preemphasis setting twice before moving on */ for (j = 0; j < ARRAY_SIZE(snb_b_fdi_train_param) * 2; j++) { /* disable first in case we need to retry */ reg = FDI_TX_CTL(pipe); temp = I915_READ(reg); temp &= ~(FDI_LINK_TRAIN_AUTO | FDI_LINK_TRAIN_NONE_IVB); temp &= ~FDI_TX_ENABLE; I915_WRITE(reg, temp); reg = FDI_RX_CTL(pipe); temp = I915_READ(reg); temp &= ~FDI_LINK_TRAIN_AUTO; temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; temp &= ~FDI_RX_ENABLE; I915_WRITE(reg, temp); /* enable CPU FDI TX and PCH FDI RX */ reg = FDI_TX_CTL(pipe); temp = I915_READ(reg); temp &= ~FDI_DP_PORT_WIDTH_MASK; temp |= FDI_DP_PORT_WIDTH(intel_crtc->config.fdi_lanes); temp |= FDI_LINK_TRAIN_PATTERN_1_IVB; temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; temp |= snb_b_fdi_train_param[j/2]; temp |= FDI_COMPOSITE_SYNC; I915_WRITE(reg, temp | FDI_TX_ENABLE); I915_WRITE(FDI_RX_MISC(pipe), FDI_RX_TP1_TO_TP2_48 | FDI_RX_FDI_DELAY_90); reg = FDI_RX_CTL(pipe); temp = I915_READ(reg); temp |= FDI_LINK_TRAIN_PATTERN_1_CPT; temp |= FDI_COMPOSITE_SYNC; I915_WRITE(reg, temp | FDI_RX_ENABLE); POSTING_READ(reg); udelay(1); /* should be 0.5us */ for (i = 0; i < 4; i++) { reg = FDI_RX_IIR(pipe); temp = I915_READ(reg); DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); if (temp & FDI_RX_BIT_LOCK || (I915_READ(reg) & FDI_RX_BIT_LOCK)) { I915_WRITE(reg, temp | FDI_RX_BIT_LOCK); DRM_DEBUG_KMS("FDI train 1 done, level %i.\n", i); break; } udelay(1); /* should be 0.5us */ } if (i == 4) { DRM_DEBUG_KMS("FDI train 1 fail on vswing %d\n", j / 2); continue; } /* Train 2 */ reg = FDI_TX_CTL(pipe); temp = I915_READ(reg); temp &= ~FDI_LINK_TRAIN_NONE_IVB; temp |= FDI_LINK_TRAIN_PATTERN_2_IVB; I915_WRITE(reg, temp); reg = FDI_RX_CTL(pipe); temp = I915_READ(reg); temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; temp |= FDI_LINK_TRAIN_PATTERN_2_CPT; I915_WRITE(reg, temp); POSTING_READ(reg); udelay(2); /* should be 1.5us */ for (i = 0; i < 4; i++) { reg = FDI_RX_IIR(pipe); temp = I915_READ(reg); DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); if (temp & FDI_RX_SYMBOL_LOCK || (I915_READ(reg) & FDI_RX_SYMBOL_LOCK)) { I915_WRITE(reg, temp | FDI_RX_SYMBOL_LOCK); DRM_DEBUG_KMS("FDI train 2 done, level %i.\n", i); goto train_done; } udelay(2); /* should be 1.5us */ } if (i == 4) DRM_DEBUG_KMS("FDI train 2 fail on vswing %d\n", j / 2); } train_done: DRM_DEBUG_KMS("FDI train done.\n"); } static void ironlake_fdi_pll_enable(struct intel_crtc *intel_crtc) { struct drm_device *dev = intel_crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; int pipe = intel_crtc->pipe; u32 reg, temp; /* enable PCH FDI RX PLL, wait warmup plus DMI latency */ reg = FDI_RX_CTL(pipe); temp = I915_READ(reg); temp &= ~(FDI_DP_PORT_WIDTH_MASK | (0x7 << 16)); temp |= FDI_DP_PORT_WIDTH(intel_crtc->config.fdi_lanes); temp |= (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) << 11; I915_WRITE(reg, temp | FDI_RX_PLL_ENABLE); POSTING_READ(reg); udelay(200); /* Switch from Rawclk to PCDclk */ temp = I915_READ(reg); I915_WRITE(reg, temp | FDI_PCDCLK); POSTING_READ(reg); udelay(200); /* Enable CPU FDI TX PLL, always on for Ironlake */ reg = FDI_TX_CTL(pipe); temp = I915_READ(reg); if ((temp & FDI_TX_PLL_ENABLE) == 0) { I915_WRITE(reg, temp | FDI_TX_PLL_ENABLE); POSTING_READ(reg); udelay(100); } } static void ironlake_fdi_pll_disable(struct intel_crtc *intel_crtc) { struct drm_device *dev = intel_crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; int pipe = intel_crtc->pipe; u32 reg, temp; /* Switch from PCDclk to Rawclk */ reg = FDI_RX_CTL(pipe); temp = I915_READ(reg); I915_WRITE(reg, temp & ~FDI_PCDCLK); /* Disable CPU FDI TX PLL */ reg = FDI_TX_CTL(pipe); temp = I915_READ(reg); I915_WRITE(reg, temp & ~FDI_TX_PLL_ENABLE); POSTING_READ(reg); udelay(100); reg = FDI_RX_CTL(pipe); temp = I915_READ(reg); I915_WRITE(reg, temp & ~FDI_RX_PLL_ENABLE); /* Wait for the clocks to turn off. */ POSTING_READ(reg); udelay(100); } static void ironlake_fdi_disable(struct drm_crtc *crtc) { 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; u32 reg, temp; /* disable CPU FDI tx and PCH FDI rx */ reg = FDI_TX_CTL(pipe); temp = I915_READ(reg); I915_WRITE(reg, temp & ~FDI_TX_ENABLE); POSTING_READ(reg); reg = FDI_RX_CTL(pipe); temp = I915_READ(reg); temp &= ~(0x7 << 16); temp |= (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) << 11; I915_WRITE(reg, temp & ~FDI_RX_ENABLE); POSTING_READ(reg); udelay(100); /* Ironlake workaround, disable clock pointer after downing FDI */ if (HAS_PCH_IBX(dev)) { I915_WRITE(FDI_RX_CHICKEN(pipe), FDI_RX_PHASE_SYNC_POINTER_OVR); } /* still set train pattern 1 */ reg = FDI_TX_CTL(pipe); temp = I915_READ(reg); temp &= ~FDI_LINK_TRAIN_NONE; temp |= FDI_LINK_TRAIN_PATTERN_1; I915_WRITE(reg, temp); reg = FDI_RX_CTL(pipe); temp = I915_READ(reg); if (HAS_PCH_CPT(dev)) { temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; temp |= FDI_LINK_TRAIN_PATTERN_1_CPT; } else { temp &= ~FDI_LINK_TRAIN_NONE; temp |= FDI_LINK_TRAIN_PATTERN_1; } /* BPC in FDI rx is consistent with that in PIPECONF */ temp &= ~(0x07 << 16); temp |= (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) << 11; I915_WRITE(reg, temp); POSTING_READ(reg); udelay(100); } static bool intel_crtc_has_pending_flip(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; unsigned long flags; bool pending; spin_lock_irqsave(&dev->event_lock, flags); pending = ((to_intel_crtc(crtc)->unpin_work != NULL) || (to_intel_crtc(crtc)->sprite_unpin_work != NULL)); spin_unlock_irqrestore(&dev->event_lock, flags); return pending; } static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; 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 long flags; if (crtc->fb == NULL) return; WARN_ON(waitqueue_active(&dev_priv->pending_flip_queue)); /* flush pending flip to avoid wait_pending_flips stuck later */ flush_workqueue(dev_priv->flipwq); obj = to_intel_framebuffer(crtc->fb)->obj; if (wait_event_timeout(dev_priv->pending_flip_queue, !intel_crtc_has_pending_flip(crtc), 5) == 0) { DRM_DEBUG_DRIVER("flip wait timed out.\n"); /* cleanup */ if (intel_crtc->unpin_work) { intel_unpin_work_fn(&intel_crtc->unpin_work->work); atomic_clear_mask(1 << intel_crtc->plane, &obj->pending_flip.counter); spin_lock_irqsave(&dev->event_lock, flags); intel_crtc->unpin_work = NULL; spin_unlock_irqrestore(&dev->event_lock, flags); } if (intel_crtc->sprite_unpin_work) { intel_unpin_sprite_work_fn( &intel_crtc->sprite_unpin_work->work); obj = intel_crtc->sprite_unpin_work->old_fb_obj; atomic_clear_mask(1 << intel_crtc->plane, &obj->pending_flip.counter); spin_lock_irqsave(&dev->event_lock, flags); intel_crtc->sprite_unpin_work = NULL; spin_unlock_irqrestore(&dev->event_lock, flags); } } mutex_lock(&dev->struct_mutex); intel_finish_fb(crtc->fb); mutex_unlock(&dev->struct_mutex); } /* Program iCLKIP clock to the desired frequency */ static void lpt_program_iclkip(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; u32 divsel, phaseinc, auxdiv, phasedir = 0; u32 temp; mutex_lock(&dev_priv->dpio_lock); /* It is necessary to ungate the pixclk gate prior to programming * the divisors, and gate it back when it is done. */ I915_WRITE(PIXCLK_GATE, PIXCLK_GATE_GATE); /* Disable SSCCTL */ intel_sbi_write(dev_priv, SBI_SSCCTL6, intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK) | SBI_SSCCTL_DISABLE, SBI_ICLK); /* 20MHz is a corner case which is out of range for the 7-bit divisor */ if (crtc->mode.clock == 20000) { auxdiv = 1; divsel = 0x41; phaseinc = 0x20; } else { /* The iCLK virtual clock root frequency is in MHz, * but the crtc->mode.clock in in KHz. To get the divisors, * it is necessary to divide one by another, so we * convert the virtual clock precision to KHz here for higher * precision. */ u32 iclk_virtual_root_freq = 172800 * 1000; u32 iclk_pi_range = 64; u32 desired_divisor, msb_divisor_value, pi_value; desired_divisor = (iclk_virtual_root_freq / crtc->mode.clock); msb_divisor_value = desired_divisor / iclk_pi_range; pi_value = desired_divisor % iclk_pi_range; auxdiv = 0; divsel = msb_divisor_value - 2; phaseinc = pi_value; } /* This should not happen with any sane values */ WARN_ON(SBI_SSCDIVINTPHASE_DIVSEL(divsel) & ~SBI_SSCDIVINTPHASE_DIVSEL_MASK); WARN_ON(SBI_SSCDIVINTPHASE_DIR(phasedir) & ~SBI_SSCDIVINTPHASE_INCVAL_MASK); DRM_DEBUG_KMS("iCLKIP clock: found settings for %dKHz refresh rate: auxdiv=%x, divsel=%x, phasedir=%x, phaseinc=%x\n", crtc->mode.clock, auxdiv, divsel, phasedir, phaseinc); /* Program SSCDIVINTPHASE6 */ temp = intel_sbi_read(dev_priv, SBI_SSCDIVINTPHASE6, SBI_ICLK); temp &= ~SBI_SSCDIVINTPHASE_DIVSEL_MASK; temp |= SBI_SSCDIVINTPHASE_DIVSEL(divsel); temp &= ~SBI_SSCDIVINTPHASE_INCVAL_MASK; temp |= SBI_SSCDIVINTPHASE_INCVAL(phaseinc); temp |= SBI_SSCDIVINTPHASE_DIR(phasedir); temp |= SBI_SSCDIVINTPHASE_PROPAGATE; intel_sbi_write(dev_priv, SBI_SSCDIVINTPHASE6, temp, SBI_ICLK); /* Program SSCAUXDIV */ temp = intel_sbi_read(dev_priv, SBI_SSCAUXDIV6, SBI_ICLK); temp &= ~SBI_SSCAUXDIV_FINALDIV2SEL(1); temp |= SBI_SSCAUXDIV_FINALDIV2SEL(auxdiv); intel_sbi_write(dev_priv, SBI_SSCAUXDIV6, temp, SBI_ICLK); /* Enable modulator and associated divider */ temp = intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK); temp &= ~SBI_SSCCTL_DISABLE; intel_sbi_write(dev_priv, SBI_SSCCTL6, temp, SBI_ICLK); /* Wait for initialization time */ udelay(24); I915_WRITE(PIXCLK_GATE, PIXCLK_GATE_UNGATE); mutex_unlock(&dev_priv->dpio_lock); } static void ironlake_pch_transcoder_set_timings(struct intel_crtc *crtc, enum pipe pch_transcoder) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; enum transcoder cpu_transcoder = crtc->config.cpu_transcoder; I915_WRITE(PCH_TRANS_HTOTAL(pch_transcoder), I915_READ(HTOTAL(cpu_transcoder))); I915_WRITE(PCH_TRANS_HBLANK(pch_transcoder), I915_READ(HBLANK(cpu_transcoder))); I915_WRITE(PCH_TRANS_HSYNC(pch_transcoder), I915_READ(HSYNC(cpu_transcoder))); I915_WRITE(PCH_TRANS_VTOTAL(pch_transcoder), I915_READ(VTOTAL(cpu_transcoder))); I915_WRITE(PCH_TRANS_VBLANK(pch_transcoder), I915_READ(VBLANK(cpu_transcoder))); I915_WRITE(PCH_TRANS_VSYNC(pch_transcoder), I915_READ(VSYNC(cpu_transcoder))); I915_WRITE(PCH_TRANS_VSYNCSHIFT(pch_transcoder), I915_READ(VSYNCSHIFT(cpu_transcoder))); } /* * Enable PCH resources required for PCH ports: * - PCH PLLs * - FDI training & RX/TX * - update transcoder timings * - DP transcoding bits * - transcoder */ static void ironlake_pch_enable(struct drm_crtc *crtc) { 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; u32 reg, temp; assert_pch_transcoder_disabled(dev_priv, pipe); /* Write the TU size bits before fdi link training, so that error * detection works. */ I915_WRITE(FDI_RX_TUSIZE1(pipe), I915_READ(PIPE_DATA_M1(pipe)) & TU_SIZE_MASK); /* For PCH output, training FDI link */ dev_priv->display.fdi_link_train(crtc); /* We need to program the right clock selection before writing the pixel * mutliplier into the DPLL. */ if (HAS_PCH_CPT(dev)) { u32 sel; temp = I915_READ(PCH_DPLL_SEL); temp |= TRANS_DPLL_ENABLE(pipe); sel = TRANS_DPLLB_SEL(pipe); if (intel_crtc->config.shared_dpll == DPLL_ID_PCH_PLL_B) temp |= sel; else temp &= ~sel; I915_WRITE(PCH_DPLL_SEL, temp); } /* XXX: pch pll's can be enabled any time before we enable the PCH * transcoder, and we actually should do this to not upset any PCH * transcoder that already use the clock when we share it. * * Note that enable_shared_dpll tries to do the right thing, but * get_shared_dpll unconditionally resets the pll - we need that to have * the right LVDS enable sequence. */ ironlake_enable_shared_dpll(intel_crtc); /* set transcoder timing, panel must allow it */ assert_panel_unlocked(dev_priv, pipe); ironlake_pch_transcoder_set_timings(intel_crtc, pipe); intel_fdi_normal_train(crtc); /* For PCH DP, enable TRANS_DP_CTL */ if (HAS_PCH_CPT(dev) && (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) || intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))) { u32 bpc = (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) >> 5; reg = TRANS_DP_CTL(pipe); temp = I915_READ(reg); temp &= ~(TRANS_DP_PORT_SEL_MASK | TRANS_DP_SYNC_MASK | TRANS_DP_BPC_MASK); temp |= (TRANS_DP_OUTPUT_ENABLE | TRANS_DP_ENH_FRAMING); temp |= bpc << 9; /* same format but at 11:9 */ if (crtc->mode.flags & DRM_MODE_FLAG_PHSYNC) temp |= TRANS_DP_HSYNC_ACTIVE_HIGH; if (crtc->mode.flags & DRM_MODE_FLAG_PVSYNC) temp |= TRANS_DP_VSYNC_ACTIVE_HIGH; switch (intel_trans_dp_port_sel(crtc)) { case PCH_DP_B: temp |= TRANS_DP_PORT_SEL_B; break; case PCH_DP_C: temp |= TRANS_DP_PORT_SEL_C; break; case PCH_DP_D: temp |= TRANS_DP_PORT_SEL_D; break; default: BUG(); } I915_WRITE(reg, temp); } ironlake_enable_pch_transcoder(dev_priv, pipe); } static void lpt_pch_enable(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder; assert_pch_transcoder_disabled(dev_priv, TRANSCODER_A); lpt_program_iclkip(crtc); /* Set transcoder timing. */ ironlake_pch_transcoder_set_timings(intel_crtc, PIPE_A); lpt_enable_pch_transcoder(dev_priv, cpu_transcoder); } static void intel_put_shared_dpll(struct intel_crtc *crtc) { struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc); if (pll == NULL) return; if (pll->refcount == 0) { WARN(1, "bad %s refcount\n", pll->name); return; } if (--pll->refcount == 0) { WARN_ON(pll->on); WARN_ON(pll->active); } crtc->config.shared_dpll = DPLL_ID_PRIVATE; } static struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc); enum intel_dpll_id i; if (pll) { DRM_DEBUG_KMS("CRTC:%d dropping existing %s\n", crtc->base.base.id, pll->name); intel_put_shared_dpll(crtc); } if (HAS_PCH_IBX(dev_priv->dev)) { /* Ironlake PCH has a fixed PLL->PCH pipe mapping. */ i = (enum intel_dpll_id) crtc->pipe; pll = &dev_priv->shared_dplls[i]; DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n", crtc->base.base.id, pll->name); goto found; } for (i = 0; i < dev_priv->num_shared_dpll; i++) { pll = &dev_priv->shared_dplls[i]; /* Only want to check enabled timings first */ if (pll->refcount == 0) continue; if (memcmp(&crtc->config.dpll_hw_state, &pll->hw_state, sizeof(pll->hw_state)) == 0) { DRM_DEBUG_KMS("CRTC:%d sharing existing %s (refcount %d, ative %d)\n", crtc->base.base.id, pll->name, pll->refcount, pll->active); goto found; } } /* Ok no matching timings, maybe there's a free one? */ for (i = 0; i < dev_priv->num_shared_dpll; i++) { pll = &dev_priv->shared_dplls[i]; if (pll->refcount == 0) { DRM_DEBUG_KMS("CRTC:%d allocated %s\n", crtc->base.base.id, pll->name); goto found; } } return NULL; found: crtc->config.shared_dpll = i; DRM_DEBUG_DRIVER("using %s for pipe %c\n", pll->name, pipe_name(crtc->pipe)); if (pll->active == 0) { memcpy(&pll->hw_state, &crtc->config.dpll_hw_state, sizeof(pll->hw_state)); DRM_DEBUG_DRIVER("setting up %s\n", pll->name); WARN_ON(pll->on); assert_shared_dpll_disabled(dev_priv, pll); pll->mode_set(dev_priv, pll); } pll->refcount++; return pll; } static void cpt_verify_modeset(struct drm_device *dev, int pipe) { struct drm_i915_private *dev_priv = dev->dev_private; int dslreg = PIPEDSL(pipe); u32 temp; temp = I915_READ(dslreg); udelay(500); if (wait_for(I915_READ(dslreg) != temp, 5)) { if (wait_for(I915_READ(dslreg) != temp, 5)) DRM_ERROR("mode set failed: pipe %c stuck\n", pipe_name(pipe)); } } static void ironlake_pfit_enable(struct intel_crtc *crtc) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; int pipe = crtc->pipe; if (crtc->config.pch_pfit.size) { /* Force use of hard-coded filter coefficients * as some pre-programmed values are broken, * e.g. x201. */ if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3 | PF_PIPE_SEL_IVB(pipe)); else I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3); I915_WRITE(PF_WIN_POS(pipe), crtc->config.pch_pfit.pos); I915_WRITE(PF_WIN_SZ(pipe), crtc->config.pch_pfit.size); } } static void intel_enable_planes(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; enum pipe pipe = to_intel_crtc(crtc)->pipe; struct intel_plane *intel_plane; list_for_each_entry(intel_plane, &dev->mode_config.plane_list, base.head) if (intel_plane->pipe == pipe) intel_plane_restore(&intel_plane->base); } static void intel_disable_planes(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; enum pipe pipe = to_intel_crtc(crtc)->pipe; struct intel_plane *intel_plane; list_for_each_entry(intel_plane, &dev->mode_config.plane_list, base.head) if (intel_plane->pipe == pipe) intel_plane_disable(&intel_plane->base); } static void ironlake_crtc_enable(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_encoder *encoder; int pipe = intel_crtc->pipe; int plane = intel_crtc->plane; WARN_ON(!crtc->enabled); if (intel_crtc->active) return; intel_crtc->active = true; intel_set_cpu_fifo_underrun_reporting(dev, pipe, true); intel_set_pch_fifo_underrun_reporting(dev, pipe, true); intel_update_watermarks(dev); for_each_encoder_on_crtc(dev, crtc, encoder) if (encoder->pre_enable) encoder->pre_enable(encoder); if (intel_crtc->config.has_pch_encoder) { /* Note: FDI PLL enabling _must_ be done before we enable the * cpu pipes, hence this is separate from all the other fdi/pch * enabling. */ ironlake_fdi_pll_enable(intel_crtc); } else { assert_fdi_tx_disabled(dev_priv, pipe); assert_fdi_rx_disabled(dev_priv, pipe); } ironlake_pfit_enable(intel_crtc); /* * 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, intel_crtc->config.has_pch_encoder, false); intel_enable_plane(dev_priv, plane, pipe); intel_enable_planes(crtc); intel_crtc_update_cursor(crtc, true); if (intel_crtc->config.has_pch_encoder) ironlake_pch_enable(crtc); mutex_lock(&dev->struct_mutex); intel_update_fbc(dev); intel_update_drrs(dev); mutex_unlock(&dev->struct_mutex); for_each_encoder_on_crtc(dev, crtc, encoder) encoder->enable(encoder); if (HAS_PCH_CPT(dev)) cpt_verify_modeset(dev, intel_crtc->pipe); /* * There seems to be a race in PCH platform hw (at least on some * outputs) where an enabled pipe still completes any pageflip right * away (as if the pipe is off) instead of waiting for vblank. As soon * as the first vblank happend, everything works as expected. Hence just * wait for one vblank before returning to avoid strange things * happening. */ intel_wait_for_vblank(dev, intel_crtc->pipe); } /* IPS only exists on ULT machines and is tied to pipe A. */ static bool hsw_crtc_supports_ips(struct intel_crtc *crtc) { return HAS_IPS(crtc->base.dev) && crtc->pipe == PIPE_A; } static void hsw_enable_ips(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; if (!crtc->config.ips_enabled) return; /* We can only enable IPS after we enable a plane and wait for a vblank. * We guarantee that the plane is enabled by calling intel_enable_ips * only after intel_enable_plane. And intel_enable_plane already waits * for a vblank, so all we need to do here is to enable the IPS bit. */ assert_plane_enabled(dev_priv, crtc->plane); I915_WRITE(IPS_CTL, IPS_ENABLE); } static void hsw_disable_ips(struct intel_crtc *crtc) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; if (!crtc->config.ips_enabled) return; assert_plane_enabled(dev_priv, crtc->plane); I915_WRITE(IPS_CTL, 0); /* We need to wait for a vblank before we can disable the plane. */ intel_wait_for_vblank(dev, crtc->pipe); } static void haswell_crtc_enable(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_encoder *encoder; int pipe = intel_crtc->pipe; int plane = intel_crtc->plane; WARN_ON(!crtc->enabled); if (intel_crtc->active) return; intel_crtc->active = true; intel_set_cpu_fifo_underrun_reporting(dev, pipe, true); if (intel_crtc->config.has_pch_encoder) intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, true); intel_update_watermarks(dev); if (intel_crtc->config.has_pch_encoder) dev_priv->display.fdi_link_train(crtc); for_each_encoder_on_crtc(dev, crtc, encoder) if (encoder->pre_enable) encoder->pre_enable(encoder); intel_ddi_enable_pipe_clock(intel_crtc); ironlake_pfit_enable(intel_crtc); /* * On ILK+ LUT must be loaded before the pipe is running but with * clocks enabled */ intel_crtc_load_lut(crtc); intel_ddi_set_pipe_settings(crtc); intel_ddi_enable_transcoder_func(crtc); intel_enable_pipe(dev_priv, pipe, intel_crtc->config.has_pch_encoder, false); intel_enable_plane(dev_priv, plane, pipe); intel_enable_planes(crtc); intel_crtc_update_cursor(crtc, true); hsw_enable_ips(intel_crtc); if (intel_crtc->config.has_pch_encoder) lpt_pch_enable(crtc); mutex_lock(&dev->struct_mutex); intel_update_fbc(dev); intel_update_drrs(dev); mutex_unlock(&dev->struct_mutex); for_each_encoder_on_crtc(dev, crtc, encoder) encoder->enable(encoder); /* * There seems to be a race in PCH platform hw (at least on some * outputs) where an enabled pipe still completes any pageflip right * away (as if the pipe is off) instead of waiting for vblank. As soon * as the first vblank happend, everything works as expected. Hence just * wait for one vblank before returning to avoid strange things * happening. */ intel_wait_for_vblank(dev, intel_crtc->pipe); } static void ironlake_pfit_disable(struct intel_crtc *crtc) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; int pipe = crtc->pipe; /* To avoid upsetting the power well on haswell only disable the pfit if * it's in use. The hw state code will make sure we get this right. */ if (crtc->config.pch_pfit.size) { I915_WRITE(PF_CTL(pipe), 0); I915_WRITE(PF_WIN_POS(pipe), 0); I915_WRITE(PF_WIN_SZ(pipe), 0); } } static void ironlake_crtc_disable(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_encoder *encoder; int pipe = intel_crtc->pipe; int plane = intel_crtc->plane; u32 reg, temp; if (!intel_crtc->active) return; for_each_encoder_on_crtc(dev, crtc, encoder) encoder->disable(encoder); intel_crtc_wait_for_pending_flips(crtc); drm_vblank_off(dev, pipe); if (dev_priv->fbc.plane == plane) intel_disable_fbc(dev); intel_crtc_update_cursor(crtc, false); intel_disable_planes(crtc); intel_disable_plane(dev_priv, plane, pipe); if (intel_crtc->config.has_pch_encoder) intel_set_pch_fifo_underrun_reporting(dev, pipe, false); intel_disable_pipe(dev_priv, pipe); ironlake_pfit_disable(intel_crtc); for_each_encoder_on_crtc(dev, crtc, encoder) if (encoder->post_disable) encoder->post_disable(encoder); if (intel_crtc->config.has_pch_encoder) { ironlake_fdi_disable(crtc); ironlake_disable_pch_transcoder(dev_priv, pipe); intel_set_pch_fifo_underrun_reporting(dev, pipe, true); if (HAS_PCH_CPT(dev)) { /* disable TRANS_DP_CTL */ reg = TRANS_DP_CTL(pipe); temp = I915_READ(reg); temp &= ~(TRANS_DP_OUTPUT_ENABLE | TRANS_DP_PORT_SEL_MASK); temp |= TRANS_DP_PORT_SEL_NONE; I915_WRITE(reg, temp); /* disable DPLL_SEL */ temp = I915_READ(PCH_DPLL_SEL); temp &= ~(TRANS_DPLL_ENABLE(pipe) | TRANS_DPLLB_SEL(pipe)); I915_WRITE(PCH_DPLL_SEL, temp); } /* disable PCH DPLL */ intel_disable_shared_dpll(intel_crtc); ironlake_fdi_pll_disable(intel_crtc); } intel_crtc->active = false; intel_update_watermarks(dev); mutex_lock(&dev->struct_mutex); intel_update_fbc(dev); intel_update_drrs(dev); mutex_unlock(&dev->struct_mutex); } static void haswell_crtc_disable(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_encoder *encoder; int pipe = intel_crtc->pipe; int plane = intel_crtc->plane; enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder; if (!intel_crtc->active) return; for_each_encoder_on_crtc(dev, crtc, encoder) encoder->disable(encoder); intel_crtc_wait_for_pending_flips(crtc); drm_vblank_off(dev, pipe); /* FBC must be disabled before disabling the plane on HSW. */ if (dev_priv->fbc.plane == plane) intel_disable_fbc(dev); hsw_disable_ips(intel_crtc); intel_crtc_update_cursor(crtc, false); intel_disable_planes(crtc); intel_disable_plane(dev_priv, plane, pipe); if (intel_crtc->config.has_pch_encoder) intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, false); intel_disable_pipe(dev_priv, pipe); intel_ddi_disable_transcoder_func(dev_priv, cpu_transcoder); ironlake_pfit_disable(intel_crtc); intel_ddi_disable_pipe_clock(intel_crtc); for_each_encoder_on_crtc(dev, crtc, encoder) if (encoder->post_disable) encoder->post_disable(encoder); if (intel_crtc->config.has_pch_encoder) { lpt_disable_pch_transcoder(dev_priv); intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, true); intel_ddi_fdi_disable(crtc); } intel_crtc->active = false; intel_update_watermarks(dev); mutex_lock(&dev->struct_mutex); intel_update_fbc(dev); intel_update_drrs(dev); mutex_unlock(&dev->struct_mutex); } static void ironlake_crtc_off(struct drm_crtc *crtc) { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); intel_put_shared_dpll(intel_crtc); } static void haswell_crtc_off(struct drm_crtc *crtc) { intel_ddi_put_crtc_pll(crtc); } static void intel_crtc_dpms_overlay(struct intel_crtc *intel_crtc, bool enable) { if (!enable && intel_crtc->overlay) { struct drm_device *dev = intel_crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; mutex_lock(&dev->struct_mutex); dev_priv->mm.interruptible = false; (void) intel_overlay_switch_off(intel_crtc->overlay); dev_priv->mm.interruptible = true; mutex_unlock(&dev->struct_mutex); } /* Let userspace switch the overlay on again. In most cases userspace * has to recompute where to put it anyway. */ } /** * i9xx_fixup_plane - ugly workaround for G45 to fire up the hardware * cursor plane briefly if not already running after enabling the display * plane. * This workaround avoids occasional blank screens when self refresh is * enabled. */ static void g4x_fixup_plane(struct drm_i915_private *dev_priv, enum pipe pipe) { u32 cntl = I915_READ(CURCNTR(pipe)); if ((cntl & CURSOR_MODE) == 0) { u32 fw_bcl_self = I915_READ(FW_BLC_SELF); I915_WRITE(FW_BLC_SELF, fw_bcl_self & ~FW_BLC_SELF_EN); I915_WRITE(CURCNTR(pipe), CURSOR_MODE_64_ARGB_AX); intel_wait_for_vblank(dev_priv->dev, pipe); I915_WRITE(CURCNTR(pipe), cntl); I915_WRITE(CURBASE(pipe), I915_READ(CURBASE(pipe))); I915_WRITE(FW_BLC_SELF, fw_bcl_self); } } static void i9xx_pfit_enable(struct intel_crtc *crtc) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc_config *pipe_config = &crtc->config; if (!crtc->config.gmch_pfit.control && !dev_priv->scaling_reqd) return; /* * The panel fitter should only be adjusted whilst the pipe is disabled, * according to register description and PRM. */ if (I915_READ(PFIT_CONTROL) & PFIT_ENABLE) return; assert_pipe_disabled(dev_priv, crtc->pipe); I915_WRITE(PFIT_PGM_RATIOS, pipe_config->gmch_pfit.pgm_ratios); I915_WRITE(PFIT_CONTROL, pipe_config->gmch_pfit.control); /* Border color in case we don't scale up to the full screen. Black by * default, change to something else for debugging. */ I915_WRITE(BCLRPAT(crtc->pipe), 0); crtc->pfit_en_status = true; } static void vlv_update_watermarks(struct drm_i915_private *dev_priv) { I915_WRITE(DSPARB, DSPARB_VLV_DEFAULT); I915_WRITE(DSPFW1, (DSPFW_SR_VAL << DSPFW_SR_SHIFT) | (DSPFW_CURSORB_VAL << DSPFW_CURSORB_SHIFT) | (DSPFW_PLANEB_VAL << DSPFW_PLANEB_SHIFT) | DSPFW_PLANEA_VAL); I915_WRITE(DSPFW2, (DSPFW2_RESERVED) | (DSPFW_CURSORA_VAL << DSPFW_CURSORA_SHIFT) | DSPFW_PLANEC_VAL); I915_WRITE(DSPFW3, (I915_READ(DSPFW3) & ~DSPFW_CURSOR_SR_MASK) | (DSPFW3_VLV)); I915_WRITE(DSPFW4, (DSPFW4_SPRITEB_VAL << DSPFW4_SPRITEB_SHIFT) | (DSPFW4_CURSORA_VAL << DSPFW4_CURSORA_SHIFT) | DSPFW4_SPRITEA_VAL); POSTING_READ(DSPFW4); I915_WRITE(DSPFW5, (DSPFW5_DISPLAYB_VAL << DSPFW5_DISPLAYB_SHIFT) | (DSPFW5_DISPLAYA_VAL << DSPFW5_DISPLAYA_SHIFT) | (DSPFW5_CURSORB_VAL << DSPFW5_CURSORB_SHIFT) | DSPFW5_CURSORSR_VAL); I915_WRITE(DSPFW6, DSPFW6_DISPLAYSR_VAL); I915_WRITE(DSPFW7, (DSPFW7_SPRITED1_VAL << DSPFW7_SPRITED1_SHIFT) | (DSPFW7_SPRITED_VAL << DSPFW7_SPRITED_SHIFT) | (DSPFW7_SPRITEC1_VAL << DSPFW7_SPRITEC1_SHIFT) | DSPFW7_SPRITEC_VAL); } static void valleyview_crtc_enable(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_encoder *encoder; int pipe = intel_crtc->pipe; int plane = intel_crtc->plane; bool is_dsi; struct intel_program_clock_bending clockbend; struct intel_program_clock_spread clockspread; WARN_ON(!crtc->enabled); if (intel_crtc->active) return; intel_crtc->active = true; if (dev_priv->s0ixstat == true) intel_crtc->s0ix_suspend_state = false; vlv_update_watermarks(dev_priv); for_each_encoder_on_crtc(dev, crtc, encoder) if (encoder->pre_pll_enable) encoder->pre_pll_enable(encoder); is_dsi = intel_pipe_has_type(crtc, INTEL_OUTPUT_DSI); if (!is_dsi) vlv_enable_pll(intel_crtc); /* Bending and Spread Clock controls */ for_each_encoder_on_crtc(dev, crtc, encoder) { if (encoder->type == INTEL_OUTPUT_EDP) { DRM_DEBUG_DRIVER("INFO: Enable spread eDP\n"); dev_priv->clockspread = true; valleyview_program_clock_spread( dev_priv, &clockspread); } else if ((encoder->type == INTEL_OUTPUT_HDMI) && (check_live_status(dev_priv) == true)) { dev_priv->unplug = false; DRM_DEBUG_DRIVER("INFO: Enable Bending For HDMI\n"); dev_priv->clockbend = true; valleyview_program_clock_bending( dev_priv, &clockbend); } else if (encoder->type == INTEL_OUTPUT_DSI) DRM_DEBUG_DRIVER("INFO: None For DSI\n"); } for_each_encoder_on_crtc(dev, crtc, encoder) { if (encoder->pre_enable) encoder->pre_enable(encoder); } i9xx_pfit_enable(intel_crtc); intel_crtc_load_lut(crtc); intel_enable_pipe(dev_priv, pipe, false, is_dsi); intel_enable_plane(dev_priv, plane, pipe); intel_enable_planes(crtc); intel_crtc_update_cursor(crtc, true); intel_update_drrs(dev); intel_update_fbc(dev); for_each_encoder_on_crtc(dev, crtc, encoder) { /* For DSI already enabled above */ encoder->enable(encoder); } } static void i9xx_crtc_enable(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_encoder *encoder; int pipe = intel_crtc->pipe; int plane = intel_crtc->plane; WARN_ON(!crtc->enabled); if (intel_crtc->active) return; intel_crtc->active = true; for_each_encoder_on_crtc(dev, crtc, encoder) if (encoder->pre_enable) encoder->pre_enable(encoder); if (!intel_pipe_has_type(crtc, INTEL_OUTPUT_DSI)) i9xx_enable_pll(intel_crtc); i9xx_pfit_enable(intel_crtc); intel_crtc_load_lut(crtc); intel_enable_pipe(dev_priv, pipe, false, false); intel_enable_plane(dev_priv, plane, pipe); intel_enable_planes(crtc); /* The fixup needs to happen before cursor is enabled */ if (IS_G4X(dev)) g4x_fixup_plane(dev_priv, pipe); intel_crtc_update_cursor(crtc, true); /* Give the overlay scaler a chance to enable if it's on this pipe */ intel_crtc_dpms_overlay(intel_crtc, true); intel_update_fbc(dev); intel_update_drrs(dev); for_each_encoder_on_crtc(dev, crtc, encoder) 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; if (!crtc->config.gmch_pfit.control) return; assert_pipe_disabled(dev_priv, crtc->pipe); DRM_DEBUG_DRIVER("disabling pfit, current: 0x%08x\n", I915_READ(PFIT_CONTROL)); if (I915_READ(PFIT_CONTROL) != (crtc->config.gmch_pfit.control & ~PFIT_ENABLE)) I915_WRITE(PFIT_CONTROL, (crtc->config.gmch_pfit.control & ~PFIT_ENABLE)); crtc->pfit_en_status = false; } static void i9xx_crtc_disable(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_encoder *encoder; int pipe = intel_crtc->pipe; int plane = intel_crtc->plane; u32 data = 0; struct intel_program_clock_bending clockbend; struct intel_program_clock_spread clockspread; if (!intel_crtc->active) return; if ((pipe == 0) && (dev_priv->is_mipi || dev_priv->is_hdmi)) { /* XXX: Disable PPS */ /* temporary fix for the IA firwware issue */ I915_WRITE_BITS(VLV_PIPE_PP_CONTROL(pipe), 0xabcd0000, 0xffff0000); I915_WRITE_BITS(VLV_PIPE_PP_CONTROL(pipe), 0, 0x00000001); if (wait_for((I915_READ(VLV_PIPE_PP_STATUS(pipe)) & 0x80000000) == 0, 50)) DRM_DEBUG_KMS("PPS Disableing timedout\n"); } for_each_encoder_on_crtc(dev, crtc, encoder) encoder->disable(encoder); /* Give the overlay scaler a chance to disable if it's on this pipe */ intel_crtc_wait_for_pending_flips(crtc); drm_vblank_off(dev, pipe); if (dev_priv->fbc.plane == plane) intel_disable_fbc(dev); intel_crtc_dpms_overlay(intel_crtc, false); intel_crtc_update_cursor(crtc, false); intel_disable_planes(crtc); intel_disable_plane(dev_priv, plane, pipe); mdelay(1); intel_disable_pipe(dev_priv, pipe); /* Bending and Spread Clock controls */ if (dev_priv->is_suspending || dev_priv->unplug) { for_each_encoder_on_crtc(dev, crtc, encoder) { if (encoder->type == INTEL_OUTPUT_EDP) { dev_priv->clockspread = false; valleyview_program_clock_spread( dev_priv, &clockspread); } else if (encoder->type == INTEL_OUTPUT_HDMI) { dev_priv->clockbend = false; valleyview_program_clock_bending( dev_priv, &clockbend); if (dev_priv->unplug) dev_priv->unplug = false; } } /* FIXME: Wait for bending/spread clocks */ mdelay(1); } i9xx_pfit_disable(intel_crtc); for_each_encoder_on_crtc(dev, crtc, encoder) if (encoder->post_disable) encoder->post_disable(encoder); if (!intel_pipe_has_type(crtc, INTEL_OUTPUT_DSI)) i9xx_disable_pll(dev_priv, pipe); intel_crtc->active = false; if (dev_priv->s0ixstat == true) intel_crtc->s0ix_suspend_state = true; intel_update_fbc(dev); intel_update_drrs(dev); if ((pipe == 0) && (dev_priv->is_mipi || dev_priv->is_hdmi)) { /* Ensure that port, plane, pipe, pf, pll are all disabled * XXX Fis the register constants */ /* temporary fix for the IA firwware issue */ I915_WRITE_BITS(VLV_DISPLAY_BASE + 0x64200, 0, 0x80000000); I915_WRITE_BITS(VLV_DISPLAY_BASE + 0x70180, 0, 0x80000000); I915_WRITE_BITS(VLV_DISPLAY_BASE + 0x70008, 0, 0x80000000); /* Wait till pipe off bit is not set */ if (wait_for(I915_READ( VLV_DISPLAY_BASE + 0x70008) & 0x40000000, 50)) DRM_DEBUG_KMS("pipe not turned off\n"); I915_WRITE_BITS(VLV_DISPLAY_BASE + 0x6014, 0, 0x80000000); } data = vlv_punit_read(dev_priv, VLV_IOSFSB_PWRGT_STATUS); /* Power gate DPIO RX Lanes */ if ((VLV_PWRGT_DPIO_RX_LANES_MASK & data) != VLV_PWRGT_DPIO_RX_LANES_MASK) { vlv_punit_write32_bits(dev_priv, VLV_IOSFSB_PWRGT_CNT_CTRL, VLV_PWRGT_DPIO_RX_LANES_MASK, VLV_PWRGT_DPIO_RX_LANES_MASK); } intel_update_drrs(dev); } #define BNDSPRDOFF ((vlv_ccu_read(dev_priv, CCU_ICLK_GATE_CTRL_REG) & (ICLKGTCTRL_SSON | ICLKGTCTRL_BNDON)) != (ICLKGTCTRL_SSON | ICLKGTCTRL_BNDON)) void clock_off_bend_spread(struct drm_i915_private *dev_priv) { bool done = false; /* * We have only one bit to control both spread and bend main clocks * If Spread is not being used, we can disable clocks */ u32 punitspare = vlv_punit_read(dev_priv, PUNIT_GVD_SPARE1); if (punitspare == PUNIT_CLKS_ON) { vlv_punit_write(dev_priv, PUNIT_GVD_SPARE1, PUNIT_CLKS_OFF); done = wait_for_atomic(BNDSPRDOFF, 10) == 0; if (!done) DRM_DEBUG("WARN! Failed to turn off Bend/Spread clocks\n"); } else DRM_DEBUG("INFO: PUNIT clocks already OFF\n"); } #define BNDSPRDON ((vlv_ccu_read(dev_priv, CCU_ICLK_GATE_CTRL_REG) & (ICLKGTCTRL_SSON | ICLKGTCTRL_BNDON)) == (ICLKGTCTRL_SSON | ICLKGTCTRL_BNDON)) void clock_on_bend_spread(struct drm_i915_private *dev_priv) { bool done = false; /* * We have only one bit to control both spread and bend main clocks * If Spread is not being used, we can disable clocks */ u32 punitspare = vlv_punit_read(dev_priv, PUNIT_GVD_SPARE1); if (punitspare == PUNIT_CLKS_OFF) { vlv_punit_write(dev_priv, PUNIT_GVD_SPARE1, PUNIT_CLKS_ON); done = wait_for_atomic(BNDSPRDON, 10) == 0; if (!done) DRM_DEBUG("WARN! Failed to turn on Bend/Spread clocks\n"); } else DRM_DEBUG("INFO: PUNIT clocks already ON\n"); } #define BNDOFF ((vlv_ccu_read(dev_priv, CCU_ICLK5_REG) & ICLK5_DISPBENDCLKEN) != ICLK5_DISPBENDCLKEN) void disable_bend_clock(struct drm_i915_private *dev_priv) { u32 iClk5val = 0; bool done = false; /* HW WA - Clear the dispbendclken */ intel_pmc_read(dev_priv, PMC_WA_FORICLK5_REG, &iClk5val); intel_pmc_write(dev_priv, PMC_WA_FORICLK5_REG, ((iClk5val & ~PMC_WA_ICLK5_BIT16_BND) | PMC_WA_HNDSHK)); done = wait_for_atomic(BNDOFF, 10) == 0; if (!done) DRM_DEBUG("WARN! Clock bending disable timed out\n"); udelay(100); dev_priv->clockbend = false; } #define BNDON ((vlv_ccu_read(dev_priv, CCU_ICLK5_REG) & ICLK5_DISPBENDCLKEN) == ICLK5_DISPBENDCLKEN) void enable_bend_clock(struct drm_i915_private *dev_priv) { u32 iClk5val = 0; bool done = false; /* Enable clock bend Alternative HW WA * Handshake bit and bit 1 mapped to bit 16 of iclk5 */ intel_pmc_read(dev_priv, PMC_WA_FORICLK5_REG, &iClk5val); intel_pmc_write(dev_priv, PMC_WA_FORICLK5_REG, ((iClk5val | PMC_WA_ICLK5_BIT16_BND) | PMC_WA_HNDSHK)); done = wait_for_atomic(BNDON, 10) == 0; if (!done) DRM_DEBUG("WARN! Clock bending enable timed out\n"); udelay(100); } #define SPRDOFF ((vlv_ccu_read(dev_priv, CCU_ICLK5_REG) & ICLK5_DISPSSCLK_SSEN) != ICLK5_DISPSSCLK_SSEN) void disable_spread_clock(struct drm_i915_private *dev_priv) { u32 iClk5val = 0; bool done = false; /* HW WA - Clear the dispspreadclken */ intel_pmc_read(dev_priv, PMC_WA_FORICLK5_REG, &iClk5val); intel_pmc_write(dev_priv, PMC_WA_FORICLK5_REG, ((iClk5val & ~PMC_WA_ICLK5_BIT17_SPRD) | PMC_WA_HNDSHK)); done = wait_for_atomic(SPRDOFF, 10) == 0; if (!done) DRM_DEBUG("SPREAD: Clock Spread disable timed out\n"); dev_priv->clockspread = false; udelay(100); } #define SPRDON ((vlv_ccu_read(dev_priv, CCU_ICLK5_REG) & ICLK5_DISPSSCLK_SSEN) == ICLK5_DISPSSCLK_SSEN) void enable_spread_clock(struct drm_i915_private *dev_priv) { u32 iClk5val = 0; bool done = false; /* enable clock spread Alternative HW WA * Handshake bit and bit 2 mapped to bit 17 of iclk5 */ intel_pmc_read(dev_priv, PMC_WA_FORICLK5_REG, &iClk5val); intel_pmc_write(dev_priv, PMC_WA_FORICLK5_REG, ((iClk5val | PMC_WA_ICLK5_BIT17_SPRD) | PMC_WA_HNDSHK)); done = wait_for_atomic(SPRDON, 10) == 0; if (!done) DRM_DEBUG("SPREAD: Clock spread enable timed out\n"); udelay(100); } void valleyview_program_clock_bending(struct drm_i915_private *dev_priv, struct intel_program_clock_bending *clockbend) { u32 iClk0val = 0, iClk1val = 0; if (!dev_priv->clockbend) { iClk0val = vlv_ccu_read(dev_priv, CCU_ICLK0_REG); iClk0val = iClk0val & ~ICLK0_BENDSTEPSIZE; vlv_ccu_write(dev_priv, CCU_ICLK0_REG, iClk0val); iClk1val = vlv_ccu_read(dev_priv, CCU_ICLK1_REG); iClk1val = iClk1val & ~(ICLK1_BENDTIMETOSW | ICLK1_BENDUPDOWN); vlv_ccu_write(dev_priv, CCU_ICLK1_REG, iClk1val); disable_bend_clock(dev_priv); if (!dev_priv->clockspread) clock_off_bend_spread(dev_priv); } else if (dev_priv->clockbend) { clock_on_bend_spread(dev_priv); enable_bend_clock(dev_priv); } } void valleyview_program_clock_spread( struct drm_i915_private *dev_priv, struct intel_program_clock_spread *clockspread) { if (!dev_priv->clockspread) { disable_spread_clock(dev_priv); if (!dev_priv->clockbend) clock_off_bend_spread(dev_priv); } else if (dev_priv->clockspread) { clock_on_bend_spread(dev_priv); enable_spread_clock(dev_priv); } } static void i9xx_crtc_off(struct drm_crtc *crtc) { } static void intel_crtc_update_sarea(struct drm_crtc *crtc, bool enabled) { struct drm_device *dev = crtc->dev; struct drm_i915_master_private *master_priv; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int pipe = intel_crtc->pipe; if (!dev->primary->master) return; master_priv = dev->primary->master->driver_priv; if (!master_priv->sarea_priv) return; switch (pipe) { case 0: master_priv->sarea_priv->pipeA_w = enabled ? crtc->mode.hdisplay : 0; master_priv->sarea_priv->pipeA_h = enabled ? crtc->mode.vdisplay : 0; break; case 1: master_priv->sarea_priv->pipeB_w = enabled ? crtc->mode.hdisplay : 0; master_priv->sarea_priv->pipeB_h = enabled ? crtc->mode.vdisplay : 0; break; default: DRM_ERROR("Can't update pipe %c in SAREA\n", pipe_name(pipe)); break; } } /** * Sets the power management mode of the pipe and plane. */ void intel_crtc_update_dpms(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_encoder *intel_encoder; struct drm_encoder *drm_encoder = NULL; struct drm_encoder_helper_funcs *encoder_funcs = NULL; bool enable = false; for_each_encoder_on_crtc(dev, crtc, intel_encoder) { enable |= intel_encoder->connectors_active; if (enable && intel_encoder->type == INTEL_OUTPUT_DSI) { drm_encoder = &intel_encoder->base; encoder_funcs = drm_encoder->helper_private; encoder_funcs->dpms(drm_encoder, DRM_MODE_DPMS_ON); } } if (enable) dev_priv->display.crtc_enable(crtc); else dev_priv->display.crtc_disable(crtc); intel_crtc_update_sarea(crtc, enable); } static void intel_crtc_disable(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_connector *connector; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); /* crtc should still be enabled when we disable it. */ WARN_ON(!crtc->enabled); dev_priv->display.crtc_disable(crtc); intel_crtc->eld_vld = false; intel_crtc_update_sarea(crtc, false); dev_priv->display.off(crtc); assert_plane_disabled(dev->dev_private, to_intel_crtc(crtc)->plane); assert_pipe_disabled(dev->dev_private, to_intel_crtc(crtc)->pipe); if (crtc->fb) { mutex_lock(&dev->struct_mutex); intel_unpin_fb_obj(to_intel_framebuffer(crtc->fb)->obj); mutex_unlock(&dev->struct_mutex); crtc->fb = NULL; } /* Update computed state. */ list_for_each_entry(connector, &dev->mode_config.connector_list, head) { if (!connector->encoder || !connector->encoder->crtc) continue; if (connector->encoder->crtc != crtc) continue; connector->dpms = DRM_MODE_DPMS_OFF; to_intel_encoder(connector->encoder)->connectors_active = false; } } void intel_encoder_destroy(struct drm_encoder *encoder) { struct intel_encoder *intel_encoder = to_intel_encoder(encoder); drm_encoder_cleanup(encoder); kfree(intel_encoder); } /* Simple dpms helper for encoders with just one connector, no cloning and only * one kind of off state. It clamps all !ON modes to fully OFF and changes the * state of the entire output pipe. */ static void intel_encoder_dpms(struct intel_encoder *encoder, int mode) { if (mode == DRM_MODE_DPMS_ON) { encoder->connectors_active = true; intel_crtc_update_dpms(encoder->base.crtc); /* Restore Gamma/Csc/Hue/Saturation/Brightness/Contrast */ if (!intel_restore_clr_mgr_status(encoder->base.crtc->dev)) DRM_ERROR("Restore Color manager status failed"); } else { encoder->connectors_active = false; /* Save Hue/Saturation/Brightness/Contrast status */ intel_save_clr_mgr_status(encoder->base.crtc->dev); intel_crtc_update_dpms(encoder->base.crtc); } } /* Cross check the actual hw state with our own modeset state tracking (and it's * internal consistency). */ static void intel_connector_check_state(struct intel_connector *connector) { if (connector->get_hw_state(connector)) { struct intel_encoder *encoder = connector->encoder; struct drm_crtc *crtc; bool encoder_enabled; enum pipe pipe; DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.base.id, drm_get_connector_name(&connector->base)); WARN(connector->base.dpms == DRM_MODE_DPMS_OFF, "wrong connector dpms state\n"); WARN(connector->base.encoder != &encoder->base, "active connector not linked to encoder\n"); WARN(!encoder->connectors_active, "encoder->connectors_active not set\n"); encoder_enabled = encoder->get_hw_state(encoder, &pipe); WARN(!encoder_enabled, "encoder not enabled\n"); if (WARN_ON(!encoder->base.crtc)) return; crtc = encoder->base.crtc; WARN(!crtc->enabled, "crtc not enabled\n"); WARN(!to_intel_crtc(crtc)->active, "crtc not active\n"); WARN(pipe != to_intel_crtc(crtc)->pipe, "encoder active on the wrong pipe\n"); } } /* Even simpler default implementation, if there's really no special case to * consider. */ void intel_connector_dpms(struct drm_connector *connector, int mode) { /* All the simple cases only support two dpms states. */ if (mode != DRM_MODE_DPMS_ON) mode = DRM_MODE_DPMS_OFF; if (mode == connector->dpms) return; connector->dpms = mode; /* Only need to change hw state when actually enabled */ if (connector->encoder) intel_encoder_dpms(to_intel_encoder(connector->encoder), mode); intel_modeset_check_state(connector->dev); } /* Simple connector->get_hw_state implementation for encoders that support only * one connector and no cloning and hence the encoder state determines the state * of the connector. */ bool intel_connector_get_hw_state(struct intel_connector *connector) { enum pipe pipe = 0; struct intel_encoder *encoder = connector->encoder; return encoder->get_hw_state(encoder, &pipe); } static bool ironlake_check_fdi_lanes(struct drm_device *dev, enum pipe pipe, struct intel_crtc_config *pipe_config) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *pipe_B_crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[PIPE_B]); DRM_DEBUG_KMS("checking fdi config on pipe %c, lanes %i\n", pipe_name(pipe), pipe_config->fdi_lanes); if (pipe_config->fdi_lanes > 4) { DRM_DEBUG_KMS("invalid fdi lane config on pipe %c: %i lanes\n", pipe_name(pipe), pipe_config->fdi_lanes); return false; } if (IS_HASWELL(dev)) { if (pipe_config->fdi_lanes > 2) { DRM_DEBUG_KMS("only 2 lanes on haswell, required: %i lanes\n", pipe_config->fdi_lanes); return false; } else { return true; } } if (INTEL_INFO(dev)->num_pipes == 2) return true; /* Ivybridge 3 pipe is really complicated */ switch (pipe) { case PIPE_A: return true; case PIPE_B: if (dev_priv->pipe_to_crtc_mapping[PIPE_C]->enabled && pipe_config->fdi_lanes > 2) { DRM_DEBUG_KMS("invalid shared fdi lane config on pipe %c: %i lanes\n", pipe_name(pipe), pipe_config->fdi_lanes); return false; } return true; case PIPE_C: if (!pipe_has_enabled_pch(pipe_B_crtc) || pipe_B_crtc->config.fdi_lanes <= 2) { if (pipe_config->fdi_lanes > 2) { DRM_DEBUG_KMS("invalid shared fdi lane config on pipe %c: %i lanes\n", pipe_name(pipe), pipe_config->fdi_lanes); return false; } } else { DRM_DEBUG_KMS("fdi link B uses too many lanes to enable link C\n"); return false; } return true; default: BUG(); return false; } } #define RETRY 1 static int ironlake_fdi_compute_config(struct intel_crtc *intel_crtc, struct intel_crtc_config *pipe_config) { struct drm_device *dev = intel_crtc->base.dev; struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode; int lane, link_bw, fdi_dotclock; bool setup_ok, needs_recompute = false; retry: /* FDI is a binary signal running at ~2.7GHz, encoding * each output octet as 10 bits. The actual frequency * is stored as a divider into a 100MHz clock, and the * mode pixel clock is stored in units of 1KHz. * Hence the bw of each lane in terms of the mode signal * is: */ link_bw = intel_fdi_link_freq(dev) * MHz(100)/KHz(1)/10; fdi_dotclock = adjusted_mode->clock; fdi_dotclock /= pipe_config->pixel_multiplier; lane = ironlake_get_lanes_required(fdi_dotclock, link_bw, pipe_config->pipe_bpp); pipe_config->fdi_lanes = lane; intel_link_compute_m_n(pipe_config->pipe_bpp, lane, fdi_dotclock, link_bw, &pipe_config->fdi_m_n); setup_ok = ironlake_check_fdi_lanes(intel_crtc->base.dev, intel_crtc->pipe, pipe_config); if (!setup_ok && pipe_config->pipe_bpp > 6*3) { pipe_config->pipe_bpp -= 2*3; DRM_DEBUG_KMS("fdi link bw constraint, reducing pipe bpp to %i\n", pipe_config->pipe_bpp); needs_recompute = true; pipe_config->bw_constrained = true; goto retry; } if (needs_recompute) return RETRY; return setup_ok ? 0 : -EINVAL; } static void hsw_compute_ips_config(struct intel_crtc *crtc, struct intel_crtc_config *pipe_config) { pipe_config->ips_enabled = i915_enable_ips && hsw_crtc_supports_ips(crtc) && pipe_config->pipe_bpp <= 24; } static int intel_crtc_compute_config(struct intel_crtc *crtc, struct intel_crtc_config *pipe_config) { struct drm_device *dev = crtc->base.dev; struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode; if (HAS_PCH_SPLIT(dev)) { /* FDI link clock is fixed at 2.7G */ if (pipe_config->requested_mode.clock * 3 > IRONLAKE_FDI_FREQ * 4) return -EINVAL; } /* Cantiga+ cannot handle modes with a hsync front porch of 0. * WaPruneModeWithIncorrectHsyncOffset:ctg,elk,ilk,snb,ivb,vlv,hsw. */ if ((INTEL_INFO(dev)->gen > 4 || IS_G4X(dev)) && adjusted_mode->hsync_start == adjusted_mode->hdisplay) return -EINVAL; if ((IS_G4X(dev) || IS_VALLEYVIEW(dev)) && pipe_config->pipe_bpp > 10*3) { pipe_config->pipe_bpp = 10*3; /* 12bpc is gen5+ */ } else if (INTEL_INFO(dev)->gen <= 4 && pipe_config->pipe_bpp > 8*3) { /* only a 8bpc pipe, with 6bpc dither through the panel fitter * for lvds. */ pipe_config->pipe_bpp = 8*3; } if (HAS_IPS(dev)) hsw_compute_ips_config(crtc, pipe_config); /* XXX: PCH clock sharing is done in ->mode_set, so make sure the old * clock survives for now. */ if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) pipe_config->shared_dpll = crtc->config.shared_dpll; if (pipe_config->has_pch_encoder) return ironlake_fdi_compute_config(crtc, pipe_config); return 0; } static int valleyview_get_display_clock_speed(struct drm_device *dev) { return 400000; /* FIXME */ } static int i945_get_display_clock_speed(struct drm_device *dev) { return 400000; } static int i915_get_display_clock_speed(struct drm_device *dev) { return 333000; } static int i9xx_misc_get_display_clock_speed(struct drm_device *dev) { return 200000; } static int pnv_get_display_clock_speed(struct drm_device *dev) { u16 gcfgc = 0; pci_read_config_word(dev->pdev, GCFGC, &gcfgc); switch (gcfgc & GC_DISPLAY_CLOCK_MASK) { case GC_DISPLAY_CLOCK_267_MHZ_PNV: return 267000; case GC_DISPLAY_CLOCK_333_MHZ_PNV: return 333000; case GC_DISPLAY_CLOCK_444_MHZ_PNV: return 444000; case GC_DISPLAY_CLOCK_200_MHZ_PNV: return 200000; default: DRM_ERROR("Unknown pnv display core clock 0x%04x\n", gcfgc); case GC_DISPLAY_CLOCK_133_MHZ_PNV: return 133000; case GC_DISPLAY_CLOCK_167_MHZ_PNV: return 167000; } } static int i915gm_get_display_clock_speed(struct drm_device *dev) { u16 gcfgc = 0; pci_read_config_word(dev->pdev, GCFGC, &gcfgc); if (gcfgc & GC_LOW_FREQUENCY_ENABLE) return 133000; else { switch (gcfgc & GC_DISPLAY_CLOCK_MASK) { case GC_DISPLAY_CLOCK_333_MHZ: return 333000; default: case GC_DISPLAY_CLOCK_190_200_MHZ: return 190000; } } } static int i865_get_display_clock_speed(struct drm_device *dev) { return 266000; } static int i855_get_display_clock_speed(struct drm_device *dev) { u16 hpllcc = 0; /* Assume that the hardware is in the high speed state. This * should be the default. */ switch (hpllcc & GC_CLOCK_CONTROL_MASK) { case GC_CLOCK_133_200: case GC_CLOCK_100_200: return 200000; case GC_CLOCK_166_250: return 250000; case GC_CLOCK_100_133: return 133000; } /* Shouldn't happen */ return 0; } static int i830_get_display_clock_speed(struct drm_device *dev) { return 133000; } static void intel_reduce_m_n_ratio(uint32_t *num, uint32_t *den) { while (*num > DATA_LINK_M_N_MASK || *den > DATA_LINK_M_N_MASK) { *num >>= 1; *den >>= 1; } } static void compute_m_n(unsigned int m, unsigned int n, uint32_t *ret_m, uint32_t *ret_n) { *ret_n = min_t(unsigned int, roundup_pow_of_two(n), DATA_LINK_N_MAX); *ret_m = div_u64((uint64_t) m * *ret_n, n); intel_reduce_m_n_ratio(ret_m, ret_n); } void intel_link_compute_m_n(int bits_per_pixel, int nlanes, int pixel_clock, int link_clock, struct intel_link_m_n *m_n) { m_n->tu = 64; compute_m_n(bits_per_pixel * pixel_clock, link_clock * nlanes * 8, &m_n->gmch_m, &m_n->gmch_n); compute_m_n(pixel_clock, link_clock, &m_n->link_m, &m_n->link_n); } static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv) { if (i915_panel_use_ssc >= 0) return i915_panel_use_ssc != 0; return dev_priv->vbt.lvds_use_ssc && !(dev_priv->quirks & QUIRK_LVDS_SSC_DISABLE); } static int vlv_get_refclk(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; int refclk = 27000; /* for DP & HDMI */ return 100000; /* only one validated so far */ if (intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) { refclk = 96000; } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { if (intel_panel_use_ssc(dev_priv)) refclk = 100000; else refclk = 96000; } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) { refclk = 100000; } return refclk; } static int i9xx_get_refclk(struct drm_crtc *crtc, int num_connectors) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; int refclk; if (IS_VALLEYVIEW(dev)) { refclk = vlv_get_refclk(crtc); } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && intel_panel_use_ssc(dev_priv) && num_connectors < 2) { refclk = dev_priv->vbt.lvds_ssc_freq * 1000; DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n", refclk / 1000); } else if (!IS_GEN2(dev)) { refclk = 96000; } else { refclk = 48000; } return refclk; } static uint32_t pnv_dpll_compute_fp(struct dpll *dpll) { return (1 << dpll->n) << 16 | dpll->m2; } static uint32_t i9xx_dpll_compute_fp(struct dpll *dpll) { return dpll->n << 16 | dpll->m1 << 8 | dpll->m2; } static void i9xx_update_pll_dividers(struct intel_crtc *crtc, intel_clock_t *reduced_clock) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; int pipe = crtc->pipe; u32 fp, fp2 = 0; if (IS_PINEVIEW(dev)) { fp = pnv_dpll_compute_fp(&crtc->config.dpll); if (reduced_clock) fp2 = pnv_dpll_compute_fp(reduced_clock); } else { fp = i9xx_dpll_compute_fp(&crtc->config.dpll); if (reduced_clock) fp2 = i9xx_dpll_compute_fp(reduced_clock); } I915_WRITE(FP0(pipe), fp); crtc->config.dpll_hw_state.fp0 = fp; crtc->lowfreq_avail = false; if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_LVDS) && reduced_clock && i915_powersave) { I915_WRITE(FP1(pipe), fp2); crtc->config.dpll_hw_state.fp1 = fp2; crtc->lowfreq_avail = true; } else { I915_WRITE(FP1(pipe), fp); crtc->config.dpll_hw_state.fp1 = fp; } } static void vlv_pllb_recal_opamp(struct drm_i915_private *dev_priv) { u32 reg_val; /* * PLLB opamp always calibrates to max value of 0x3f, force enable it * and set it to a reasonable value instead. */ reg_val = vlv_dpio_read(dev_priv, DPIO_IREF(1)); reg_val &= 0xffffff00; reg_val |= 0x00000030; vlv_dpio_write(dev_priv, DPIO_IREF(1), reg_val); reg_val = vlv_dpio_read(dev_priv, DPIO_CALIBRATION); reg_val &= 0x8cffffff; reg_val |= 0x8c000000; vlv_dpio_write(dev_priv, DPIO_CALIBRATION, reg_val); reg_val = vlv_dpio_read(dev_priv, DPIO_IREF(1)); reg_val &= 0xffffff00; vlv_dpio_write(dev_priv, DPIO_IREF(1), reg_val); reg_val = vlv_dpio_read(dev_priv, DPIO_CALIBRATION); reg_val &= 0x00ffffff; reg_val |= 0xb0000000; vlv_dpio_write(dev_priv, DPIO_CALIBRATION, reg_val); } static void intel_pch_transcoder_set_m_n(struct intel_crtc *crtc, struct intel_link_m_n *m_n) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; int pipe = crtc->pipe; I915_WRITE(PCH_TRANS_DATA_M1(pipe), TU_SIZE(m_n->tu) | m_n->gmch_m); I915_WRITE(PCH_TRANS_DATA_N1(pipe), m_n->gmch_n); I915_WRITE(PCH_TRANS_LINK_M1(pipe), m_n->link_m); I915_WRITE(PCH_TRANS_LINK_N1(pipe), m_n->link_n); } static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc, struct intel_link_m_n *m_n) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; int pipe = crtc->pipe; enum transcoder transcoder = crtc->config.cpu_transcoder; if (INTEL_INFO(dev)->gen >= 5) { I915_WRITE(PIPE_DATA_M1(transcoder), TU_SIZE(m_n->tu) | m_n->gmch_m); I915_WRITE(PIPE_DATA_N1(transcoder), m_n->gmch_n); I915_WRITE(PIPE_LINK_M1(transcoder), m_n->link_m); I915_WRITE(PIPE_LINK_N1(transcoder), m_n->link_n); } else { I915_WRITE(PIPE_DATA_M_G4X(pipe), TU_SIZE(m_n->tu) | m_n->gmch_m); I915_WRITE(PIPE_DATA_N_G4X(pipe), m_n->gmch_n); I915_WRITE(PIPE_LINK_M_G4X(pipe), m_n->link_m); I915_WRITE(PIPE_LINK_N_G4X(pipe), m_n->link_n); } } static void intel_dp_set_m_n(struct intel_crtc *crtc) { if (crtc->config.has_pch_encoder) intel_pch_transcoder_set_m_n(crtc, &crtc->config.dp_m_n); else intel_cpu_transcoder_set_m_n(crtc, &crtc->config.dp_m_n); } static void vlv_update_pll(struct intel_crtc *crtc) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; int pipe = crtc->pipe; u32 dpll, mdiv; u32 bestn, bestm1, bestm2, bestp1, bestp2; u32 coreclk, reg_val, dpll_md; mutex_lock(&dev_priv->dpio_lock); bestn = crtc->config.dpll.n; bestm1 = crtc->config.dpll.m1; bestm2 = crtc->config.dpll.m2; bestp1 = crtc->config.dpll.p1; bestp2 = crtc->config.dpll.p2; /* See eDP HDMI DPIO driver vbios notes doc */ /* PLL B needs special handling */ if (pipe) vlv_pllb_recal_opamp(dev_priv); /* Set up Tx target for periodic Rcomp update */ vlv_dpio_write(dev_priv, DPIO_IREF_BCAST, 0x0100000f); /* Disable target IRef on PLL */ reg_val = vlv_dpio_read(dev_priv, DPIO_IREF_CTL(pipe)); reg_val &= 0x00ffffff; vlv_dpio_write(dev_priv, DPIO_IREF_CTL(pipe), reg_val); /* Disable fast lock */ vlv_dpio_write(dev_priv, DPIO_FASTCLK_DISABLE, 0x610); if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP) || intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT)) { /* Set HBR and RBR LPF coefficients */ if (crtc->config.port_clock == 162000 || intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_ANALOG) || intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_HDMI)) vlv_dpio_write(dev_priv, DPIO_LPF_COEFF(pipe), 0x009f0003); else vlv_dpio_write(dev_priv, DPIO_LPF_COEFF(pipe), 0x00d0000f); } else /* HDMI */ vlv_dpio_write(dev_priv, DPIO_LPF_COEFF(pipe), 0x005f0021); if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP) || intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT)) { /* Use SSC source */ if (!pipe) vlv_dpio_write(dev_priv, DPIO_REFSFR(pipe), 0x0df40000); else vlv_dpio_write(dev_priv, DPIO_REFSFR(pipe), 0x0df70000); } else { /* HDMI or VGA */ /* Use bend source */ if (!pipe) vlv_dpio_write(dev_priv, DPIO_REFSFR(pipe), 0x0df70000); else vlv_dpio_write(dev_priv, DPIO_REFSFR(pipe), 0x0df40000); } /* Set idtafcrecal before PLL is enabled */ mdiv = ((bestm1 << DPIO_M1DIV_SHIFT) | (bestm2 & DPIO_M2DIV_MASK)); mdiv |= ((bestp1 << DPIO_P1_SHIFT) | (bestp2 << DPIO_P2_SHIFT)); mdiv |= ((bestn << DPIO_N_SHIFT)); mdiv |= (1 << DPIO_K_SHIFT); /* * Post divider depends on pixel clock rate, DAC vs digital (and LVDS, * but we don't support that). * Note: don't use the DAC post divider as it seems unstable. */ mdiv |= (DPIO_POST_DIV_HDMIDP << DPIO_POST_DIV_SHIFT); vlv_dpio_write(dev_priv, DPIO_DIV(pipe), mdiv); mdiv |= DPIO_ENABLE_CALIBRATION; vlv_dpio_write(dev_priv, DPIO_DIV(pipe), mdiv); coreclk = vlv_dpio_read(dev_priv, DPIO_CORE_CLK(pipe)); coreclk = (coreclk & 0x0000ff00) | 0x01c00000; vlv_dpio_write(dev_priv, DPIO_CORE_CLK(pipe), coreclk); vlv_dpio_write(dev_priv, DPIO_PLL_CML(pipe), 0x87871000); /* Enable DPIO clock input */ dpll = DPLL_EXT_BUFFER_ENABLE_VLV | DPLL_REFA_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS | DPLL_INTEGRATED_CLOCK_VLV; if (pipe) dpll |= DPLL_INTEGRATED_CRI_CLK_VLV; dpll |= DPLL_VCO_ENABLE; crtc->config.dpll_hw_state.dpll = dpll; dpll_md = (crtc->config.pixel_multiplier - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT; crtc->config.dpll_hw_state.dpll_md = dpll_md; if (crtc->config.has_dp_encoder || intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP)) intel_dp_set_m_n(crtc); mutex_unlock(&dev_priv->dpio_lock); } static void i9xx_update_pll(struct intel_crtc *crtc, intel_clock_t *reduced_clock, int num_connectors) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; u32 dpll; bool is_sdvo; struct dpll *clock = &crtc->config.dpll; i9xx_update_pll_dividers(crtc, reduced_clock); is_sdvo = intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_SDVO) || intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_HDMI); dpll = DPLL_VGA_MODE_DIS; if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_LVDS)) dpll |= DPLLB_MODE_LVDS; else dpll |= DPLLB_MODE_DAC_SERIAL; if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) { dpll |= (crtc->config.pixel_multiplier - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; } if (is_sdvo) dpll |= DPLL_SDVO_HIGH_SPEED; if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT)) dpll |= DPLL_SDVO_HIGH_SPEED; /* compute bitmask from p1 value */ if (IS_PINEVIEW(dev)) dpll |= (1 << (clock->p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW; else { dpll |= (1 << (clock->p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT; if (IS_G4X(dev) && reduced_clock) dpll |= (1 << (reduced_clock->p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT; } switch (clock->p2) { case 5: dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5; break; case 7: dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7; break; case 10: dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10; break; case 14: dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14; break; } if (INTEL_INFO(dev)->gen >= 4) dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT); if (crtc->config.sdvo_tv_clock) dpll |= PLL_REF_INPUT_TVCLKINBC; else if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_LVDS) && intel_panel_use_ssc(dev_priv) && num_connectors < 2) dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN; else dpll |= PLL_REF_INPUT_DREFCLK; dpll |= DPLL_VCO_ENABLE; crtc->config.dpll_hw_state.dpll = dpll; if (INTEL_INFO(dev)->gen >= 4) { u32 dpll_md = (crtc->config.pixel_multiplier - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT; crtc->config.dpll_hw_state.dpll_md = dpll_md; } if (crtc->config.has_dp_encoder) intel_dp_set_m_n(crtc); } static void i8xx_update_pll(struct intel_crtc *crtc, intel_clock_t *reduced_clock, int num_connectors) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; u32 dpll; struct dpll *clock = &crtc->config.dpll; i9xx_update_pll_dividers(crtc, reduced_clock); dpll = DPLL_VGA_MODE_DIS; if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_LVDS)) { dpll |= (1 << (clock->p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT; } else { if (clock->p1 == 2) dpll |= PLL_P1_DIVIDE_BY_TWO; else dpll |= (clock->p1 - 2) << DPLL_FPA01_P1_POST_DIV_SHIFT; if (clock->p2 == 4) dpll |= PLL_P2_DIVIDE_BY_4; } if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DVO)) dpll |= DPLL_DVO_2X_MODE; if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_LVDS) && intel_panel_use_ssc(dev_priv) && num_connectors < 2) dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN; else dpll |= PLL_REF_INPUT_DREFCLK; dpll |= DPLL_VCO_ENABLE; crtc->config.dpll_hw_state.dpll = dpll; } static void intel_set_pipe_timings(struct intel_crtc *intel_crtc) { struct drm_device *dev = intel_crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; enum pipe pipe = intel_crtc->pipe; enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder; struct drm_display_mode *adjusted_mode = &intel_crtc->config.adjusted_mode; struct drm_display_mode *mode = &intel_crtc->config.requested_mode; uint32_t vsyncshift, crtc_vtotal, crtc_vblank_end; /* We need to be careful not to changed the adjusted mode, for otherwise * the hw state checker will get angry at the mismatch. */ crtc_vtotal = adjusted_mode->crtc_vtotal; crtc_vblank_end = adjusted_mode->crtc_vblank_end; if (!IS_GEN2(dev) && adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) { /* the chip adds 2 halflines automatically */ crtc_vtotal -= 1; crtc_vblank_end -= 1; vsyncshift = adjusted_mode->crtc_hsync_start - adjusted_mode->crtc_htotal / 2; } else { vsyncshift = 0; } if (INTEL_INFO(dev)->gen > 3) I915_WRITE(VSYNCSHIFT(cpu_transcoder), vsyncshift); I915_WRITE(HTOTAL(cpu_transcoder), (adjusted_mode->crtc_hdisplay - 1) | ((adjusted_mode->crtc_htotal - 1) << 16)); I915_WRITE(HBLANK(cpu_transcoder), (adjusted_mode->crtc_hblank_start - 1) | ((adjusted_mode->crtc_hblank_end - 1) << 16)); I915_WRITE(HSYNC(cpu_transcoder), (adjusted_mode->crtc_hsync_start - 1) | ((adjusted_mode->crtc_hsync_end - 1) << 16)); I915_WRITE(VTOTAL(cpu_transcoder), (adjusted_mode->crtc_vdisplay - 1) | ((crtc_vtotal - 1) << 16)); I915_WRITE(VBLANK(cpu_transcoder), (adjusted_mode->crtc_vblank_start - 1) | ((crtc_vblank_end - 1) << 16)); I915_WRITE(VSYNC(cpu_transcoder), (adjusted_mode->crtc_vsync_start - 1) | ((adjusted_mode->crtc_vsync_end - 1) << 16)); /* Workaround: when the EDP input selection is B, the VTOTAL_B must be * programmed with the VTOTAL_EDP value. Same for VTOTAL_C. This is * documented on the DDI_FUNC_CTL register description, EDP Input Select * bits. */ if (IS_HASWELL(dev) && cpu_transcoder == TRANSCODER_EDP && (pipe == PIPE_B || pipe == PIPE_C)) I915_WRITE(VTOTAL(pipe), I915_READ(VTOTAL(cpu_transcoder))); /* pipesrc controls the size that is scaled from, which should * always be the user's requested size. */ if (IS_VALLEYVIEW(dev) && intel_crtc->scaling_src_size && intel_crtc->config.gmch_pfit.control) I915_WRITE(PIPESRC(pipe), intel_crtc->scaling_src_size); else I915_WRITE(PIPESRC(pipe), ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1)); } static void intel_get_pipe_timings(struct intel_crtc *crtc, struct intel_crtc_config *pipe_config) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; enum transcoder cpu_transcoder = pipe_config->cpu_transcoder; uint32_t tmp; tmp = I915_READ(HTOTAL(cpu_transcoder)); pipe_config->adjusted_mode.crtc_hdisplay = (tmp & 0xffff) + 1; pipe_config->adjusted_mode.crtc_htotal = ((tmp >> 16) & 0xffff) + 1; tmp = I915_READ(HBLANK(cpu_transcoder)); pipe_config->adjusted_mode.crtc_hblank_start = (tmp & 0xffff) + 1; pipe_config->adjusted_mode.crtc_hblank_end = ((tmp >> 16) & 0xffff) + 1; tmp = I915_READ(HSYNC(cpu_transcoder)); pipe_config->adjusted_mode.crtc_hsync_start = (tmp & 0xffff) + 1; pipe_config->adjusted_mode.crtc_hsync_end = ((tmp >> 16) & 0xffff) + 1; tmp = I915_READ(VTOTAL(cpu_transcoder)); pipe_config->adjusted_mode.crtc_vdisplay = (tmp & 0xffff) + 1; pipe_config->adjusted_mode.crtc_vtotal = ((tmp >> 16) & 0xffff) + 1; tmp = I915_READ(VBLANK(cpu_transcoder)); pipe_config->adjusted_mode.crtc_vblank_start = (tmp & 0xffff) + 1; pipe_config->adjusted_mode.crtc_vblank_end = ((tmp >> 16) & 0xffff) + 1; tmp = I915_READ(VSYNC(cpu_transcoder)); pipe_config->adjusted_mode.crtc_vsync_start = (tmp & 0xffff) + 1; pipe_config->adjusted_mode.crtc_vsync_end = ((tmp >> 16) & 0xffff) + 1; if (I915_READ(PIPECONF(cpu_transcoder)) & PIPECONF_INTERLACE_MASK) { pipe_config->adjusted_mode.flags |= DRM_MODE_FLAG_INTERLACE; pipe_config->adjusted_mode.crtc_vtotal += 1; pipe_config->adjusted_mode.crtc_vblank_end += 1; } tmp = I915_READ(PIPESRC(crtc->pipe)); pipe_config->requested_mode.vdisplay = (tmp & 0xffff) + 1; pipe_config->requested_mode.hdisplay = ((tmp >> 16) & 0xffff) + 1; } static void intel_crtc_mode_from_pipe_config(struct intel_crtc *intel_crtc, struct intel_crtc_config *pipe_config) { struct drm_crtc *crtc = &intel_crtc->base; crtc->mode.hdisplay = pipe_config->adjusted_mode.crtc_hdisplay; crtc->mode.htotal = pipe_config->adjusted_mode.crtc_htotal; crtc->mode.hsync_start = pipe_config->adjusted_mode.crtc_hsync_start; crtc->mode.hsync_end = pipe_config->adjusted_mode.crtc_hsync_end; crtc->mode.vdisplay = pipe_config->adjusted_mode.crtc_vdisplay; crtc->mode.vtotal = pipe_config->adjusted_mode.crtc_vtotal; crtc->mode.vsync_start = pipe_config->adjusted_mode.crtc_vsync_start; crtc->mode.vsync_end = pipe_config->adjusted_mode.crtc_vsync_end; crtc->mode.flags = pipe_config->adjusted_mode.flags; crtc->mode.clock = pipe_config->adjusted_mode.clock; crtc->mode.flags |= pipe_config->adjusted_mode.flags; } static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc) { struct drm_device *dev = intel_crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; uint32_t pipeconf; pipeconf = 0; if (intel_crtc->pipe == 0 && INTEL_INFO(dev)->gen < 4) { /* Enable pixel doubling when the dot clock is > 90% of the (display) * core speed. * * XXX: No double-wide on 915GM pipe B. Is that the only reason for the * pipe == 0 check? */ if (intel_crtc->config.requested_mode.clock > dev_priv->display.get_display_clock_speed(dev) * 9 / 10) pipeconf |= PIPECONF_DOUBLE_WIDE; } /* only g4x and later have fancy bpc/dither controls */ if (IS_G4X(dev) || IS_VALLEYVIEW(dev)) { /* Bspec claims that we can't use dithering for 30bpp pipes. */ if (intel_crtc->config.dither && intel_crtc->config.pipe_bpp != 30) pipeconf |= PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP; switch (intel_crtc->config.pipe_bpp) { case 18: pipeconf |= PIPECONF_6BPC; break; case 24: pipeconf |= PIPECONF_8BPC; break; case 30: pipeconf |= PIPECONF_10BPC; break; default: /* Case prevented by intel_choose_pipe_bpp_dither. */ BUG(); } } if (HAS_PIPE_CXSR(dev)) { if (intel_crtc->lowfreq_avail) { DRM_DEBUG_KMS("enabling CxSR downclocking\n"); pipeconf |= PIPECONF_CXSR_DOWNCLOCK; } else { DRM_DEBUG_KMS("disabling CxSR downclocking\n"); } } if (!IS_GEN2(dev) && intel_crtc->config.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION; else pipeconf |= PIPECONF_PROGRESSIVE; if (IS_VALLEYVIEW(dev) && intel_crtc->config.limited_color_range) pipeconf |= PIPECONF_COLOR_RANGE_SELECT; I915_WRITE(PIPECONF(intel_crtc->pipe), pipeconf); POSTING_READ(PIPECONF(intel_crtc->pipe)); } void intel_iosf_rw(struct drm_i915_private *dev_priv, u8 opcode, u32 port, u32 reg, u32 *val) { u32 cmd, devfn, be, bar; bar = 0; be = 0xf; devfn = 16; cmd = (devfn << IOSF_DEVFN_SHIFT) | (opcode << IOSF_OPCODE_SHIFT) | (port << IOSF_PORT_SHIFT) | (be << IOSF_BYTE_ENABLES_SHIFT) | (bar << IOSF_BAR_SHIFT); if (I915_READ(VLV_IOSF_DOORBELL_REQ) & IOSF_SB_BUSY) { DRM_DEBUG_DRIVER("warning: pcode (%s) mailbox access failed\n", opcode == OPCODE_REG_READ ? "read" : "write"); return; } I915_WRITE(VLV_IOSF_ADDR, reg); if (opcode == OPCODE_REG_WRITE) I915_WRITE(VLV_IOSF_DATA, *val); I915_WRITE(VLV_IOSF_DOORBELL_REQ, cmd); if (wait_for((I915_READ(VLV_IOSF_DOORBELL_REQ) & IOSF_SB_BUSY) == 0, 500)) { DRM_ERROR("timeout waiting for pcode %s (%d) to finish\n", opcode == OPCODE_REG_READ ? "read" : "write", reg); return; } if (opcode == OPCODE_REG_READ) *val = I915_READ(VLV_IOSF_DATA); I915_WRITE(VLV_IOSF_DATA, 0); return; } static int i9xx_crtc_mode_set(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *fb) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct drm_display_mode *mode = &intel_crtc->config.adjusted_mode; int pipe = intel_crtc->pipe; int plane = intel_crtc->plane; int refclk, num_connectors = 0; intel_clock_t clock, reduced_clock; u32 dspcntr; bool ok, has_reduced_clock = false; bool is_lvds = false, is_dsi = false; struct intel_encoder *encoder; const intel_limit_t *limit; int ret; for_each_encoder_on_crtc(dev, crtc, encoder) { switch (encoder->type) { case INTEL_OUTPUT_LVDS: is_lvds = true; break; case INTEL_OUTPUT_DSI: is_dsi = true; break; } num_connectors++; } refclk = i9xx_get_refclk(crtc, num_connectors); if (!is_dsi) { /* * Returns a set of divisors for the desired target clock with * the given refclk, or FALSE. The returned values represent * the clock equation: reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + * 2) / p1 / p2. */ limit = intel_limit(crtc, refclk); ok = dev_priv->display.find_dpll(limit, crtc, intel_crtc->config.port_clock, refclk, NULL, &clock); if (!ok && !intel_crtc->config.clock_set) { DRM_ERROR("Couldn't find PLL settings for mode!\n"); return -EINVAL; } } /* Ensure that the cursor is valid for the new mode before changing... */ intel_crtc_update_cursor(crtc, true); if (!is_dsi && is_lvds && dev_priv->lvds_downclock_avail) { /* * Ensure we match the reduced clock's P to the target clock. * If the clocks don't match, we can't switch the display clock * by using the FP0/FP1. In such case we will disable the LVDS * downclock feature. */ has_reduced_clock = dev_priv->display.find_dpll(limit, crtc, dev_priv->lvds_downclock, refclk, &clock, &reduced_clock); } /* Compat-code for transition, will disappear. */ if (!intel_crtc->config.clock_set) { intel_crtc->config.dpll.n = clock.n; intel_crtc->config.dpll.m1 = clock.m1; intel_crtc->config.dpll.m2 = clock.m2; intel_crtc->config.dpll.p1 = clock.p1; intel_crtc->config.dpll.p2 = clock.p2; } if (IS_GEN2(dev)) { i8xx_update_pll(intel_crtc, has_reduced_clock ? &reduced_clock : NULL, num_connectors); } else if (IS_VALLEYVIEW(dev)) { if (!is_dsi) vlv_update_pll(intel_crtc); } else { i9xx_update_pll(intel_crtc, has_reduced_clock ? &reduced_clock : NULL, num_connectors); } /* Set up the display plane register */ dspcntr = DISPPLANE_GAMMA_ENABLE; if (!IS_VALLEYVIEW(dev)) { if (pipe == 0) dspcntr &= ~DISPPLANE_SEL_PIPE_MASK; else dspcntr |= DISPPLANE_SEL_PIPE_B; } intel_set_pipe_timings(intel_crtc); /* pipesrc and dspsize control the size that is scaled from, * which should always be the user's requested size. */ I915_WRITE(DSPSIZE(plane), ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1)); I915_WRITE(DSPPOS(plane), 0); i9xx_set_pipeconf(intel_crtc); I915_WRITE(DSPCNTR(plane), dspcntr); POSTING_READ(DSPCNTR(plane)); ret = intel_pipe_set_base(crtc, x, y, fb); /* Added for HDMI Audio */ if (IS_VALLEYVIEW(dev) && intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) { dev_priv->tmds_clock_speed = intel_crtc->config.port_clock; mid_hdmi_audio_signal_event(dev_priv->dev, HAD_EVENT_MODE_CHANGING); } return ret; } static void i9xx_get_pfit_config(struct intel_crtc *crtc, struct intel_crtc_config *pipe_config) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; uint32_t tmp; tmp = I915_READ(PFIT_CONTROL); if (!(tmp & PFIT_ENABLE)) return; /* Check whether the pfit is attached to our pipe. */ if (INTEL_INFO(dev)->gen < 4) { if (crtc->pipe != PIPE_B) return; } else { if ((tmp & PFIT_PIPE_MASK) != (crtc->pipe << PFIT_PIPE_SHIFT)) return; } pipe_config->gmch_pfit.control = tmp; pipe_config->gmch_pfit.pgm_ratios = I915_READ(PFIT_PGM_RATIOS); if (INTEL_INFO(dev)->gen < 5) pipe_config->gmch_pfit.lvds_border_bits = I915_READ(LVDS) & LVDS_BORDER_ENABLE; } static void vlv_crtc_clock_get(struct intel_crtc *crtc, struct intel_crtc_config *pipe_config) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; int pipe = pipe_config->cpu_transcoder; intel_clock_t clock; u32 mdiv; int refclk = 100000, fastclk, update_rate; mutex_lock(&dev_priv->dpio_lock); mdiv = vlv_dpio_read(dev_priv, DPIO_DIV(pipe)); mutex_unlock(&dev_priv->dpio_lock); clock.m1 = (mdiv >> DPIO_M1DIV_SHIFT) & 7; clock.m2 = mdiv & DPIO_M2DIV_MASK; clock.n = (mdiv >> DPIO_N_SHIFT) & 0xf; clock.p1 = (mdiv >> DPIO_P1_SHIFT) & 7; clock.p2 = (mdiv >> DPIO_P2_SHIFT) & 0x1f; update_rate = refclk / clock.n; clock.vco = update_rate * clock.m1 * clock.m2; fastclk = clock.vco / clock.p1 / clock.p2; clock.dot = (2 * fastclk); pipe_config->port_clock = clock.dot / 10; } static bool i9xx_get_pipe_config(struct intel_crtc *crtc, struct intel_crtc_config *pipe_config) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; uint32_t tmp; pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe; pipe_config->shared_dpll = DPLL_ID_PRIVATE; tmp = I915_READ(PIPECONF(crtc->pipe)); if (!(tmp & PIPECONF_ENABLE)) return false; intel_get_pipe_timings(crtc, pipe_config); i9xx_get_pfit_config(crtc, pipe_config); if (INTEL_INFO(dev)->gen >= 4) { tmp = I915_READ(DPLL_MD(crtc->pipe)); pipe_config->pixel_multiplier = ((tmp & DPLL_MD_UDI_MULTIPLIER_MASK) >> DPLL_MD_UDI_MULTIPLIER_SHIFT) + 1; pipe_config->dpll_hw_state.dpll_md = tmp; } else if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) { tmp = I915_READ(DPLL(crtc->pipe)); pipe_config->pixel_multiplier = ((tmp & SDVO_MULTIPLIER_MASK) >> SDVO_MULTIPLIER_SHIFT_HIRES) + 1; } else { /* Note that on i915G/GM the pixel multiplier is in the sdvo * port and will be fixed up in the encoder->get_config * function. */ pipe_config->pixel_multiplier = 1; } pipe_config->dpll_hw_state.dpll = I915_READ(DPLL(crtc->pipe)); if (!IS_VALLEYVIEW(dev)) { pipe_config->dpll_hw_state.fp0 = I915_READ(FP0(crtc->pipe)); pipe_config->dpll_hw_state.fp1 = I915_READ(FP1(crtc->pipe)); } else { /* Mask out read-only status bits. */ pipe_config->dpll_hw_state.dpll &= ~(DPLL_LOCK_VLV | DPLL_PORTC_READY_MASK | DPLL_PORTB_READY_MASK); } if (IS_VALLEYVIEW(dev)) vlv_crtc_clock_get(crtc, pipe_config); else i9xx_crtc_clock_get(crtc, pipe_config); return true; } static void ironlake_init_pch_refclk(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct drm_mode_config *mode_config = &dev->mode_config; struct intel_encoder *encoder; u32 val, final; bool has_lvds = false; bool has_cpu_edp = false; bool has_panel = false; bool has_ck505 = false; bool can_ssc = false; /* We need to take the global config into account */ list_for_each_entry(encoder, &mode_config->encoder_list, base.head) { switch (encoder->type) { case INTEL_OUTPUT_LVDS: has_panel = true; has_lvds = true; break; case INTEL_OUTPUT_EDP: has_panel = true; if (enc_to_dig_port(&encoder->base)->port == PORT_A) has_cpu_edp = true; break; } } if (HAS_PCH_IBX(dev)) { has_ck505 = dev_priv->vbt.display_clock_mode; can_ssc = has_ck505; } else { has_ck505 = false; can_ssc = true; } DRM_DEBUG_KMS("has_panel %d has_lvds %d has_ck505 %d\n", has_panel, has_lvds, has_ck505); /* Ironlake: try to setup display ref clock before DPLL * enabling. This is only under driver's control after * PCH B stepping, previous chipset stepping should be * ignoring this setting. */ val = I915_READ(PCH_DREF_CONTROL); /* As we must carefully and slowly disable/enable each source in turn, * compute the final state we want first and check if we need to * make any changes at all. */ final = val; final &= ~DREF_NONSPREAD_SOURCE_MASK; if (has_ck505) final |= DREF_NONSPREAD_CK505_ENABLE; else final |= DREF_NONSPREAD_SOURCE_ENABLE; final &= ~DREF_SSC_SOURCE_MASK; final &= ~DREF_CPU_SOURCE_OUTPUT_MASK; final &= ~DREF_SSC1_ENABLE; if (has_panel) { final |= DREF_SSC_SOURCE_ENABLE; if (intel_panel_use_ssc(dev_priv) && can_ssc) final |= DREF_SSC1_ENABLE; if (has_cpu_edp) { if (intel_panel_use_ssc(dev_priv) && can_ssc) final |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD; else final |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD; } else final |= DREF_CPU_SOURCE_OUTPUT_DISABLE; } else { final |= DREF_SSC_SOURCE_DISABLE; final |= DREF_CPU_SOURCE_OUTPUT_DISABLE; } if (final == val) return; /* Always enable nonspread source */ val &= ~DREF_NONSPREAD_SOURCE_MASK; if (has_ck505) val |= DREF_NONSPREAD_CK505_ENABLE; else val |= DREF_NONSPREAD_SOURCE_ENABLE; if (has_panel) { val &= ~DREF_SSC_SOURCE_MASK; val |= DREF_SSC_SOURCE_ENABLE; /* SSC must be turned on before enabling the CPU output */ if (intel_panel_use_ssc(dev_priv) && can_ssc) { DRM_DEBUG_KMS("Using SSC on panel\n"); val |= DREF_SSC1_ENABLE; } else val &= ~DREF_SSC1_ENABLE; /* Get SSC going before enabling the outputs */ I915_WRITE(PCH_DREF_CONTROL, val); POSTING_READ(PCH_DREF_CONTROL); udelay(200); val &= ~DREF_CPU_SOURCE_OUTPUT_MASK; /* Enable CPU source on CPU attached eDP */ if (has_cpu_edp) { if (intel_panel_use_ssc(dev_priv) && can_ssc) { DRM_DEBUG_KMS("Using SSC on eDP\n"); val |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD; } else val |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD; } else val |= DREF_CPU_SOURCE_OUTPUT_DISABLE; I915_WRITE(PCH_DREF_CONTROL, val); POSTING_READ(PCH_DREF_CONTROL); udelay(200); } else { DRM_DEBUG_KMS("Disabling SSC entirely\n"); val &= ~DREF_CPU_SOURCE_OUTPUT_MASK; /* Turn off CPU output */ val |= DREF_CPU_SOURCE_OUTPUT_DISABLE; I915_WRITE(PCH_DREF_CONTROL, val); POSTING_READ(PCH_DREF_CONTROL); udelay(200); /* Turn off the SSC source */ val &= ~DREF_SSC_SOURCE_MASK; val |= DREF_SSC_SOURCE_DISABLE; /* Turn off SSC1 */ val &= ~DREF_SSC1_ENABLE; I915_WRITE(PCH_DREF_CONTROL, val); POSTING_READ(PCH_DREF_CONTROL); udelay(200); } BUG_ON(val != final); } static void lpt_reset_fdi_mphy(struct drm_i915_private *dev_priv) { uint32_t tmp; tmp = I915_READ(SOUTH_CHICKEN2); tmp |= FDI_MPHY_IOSFSB_RESET_CTL; I915_WRITE(SOUTH_CHICKEN2, tmp); if (wait_for_atomic_us(I915_READ(SOUTH_CHICKEN2) & FDI_MPHY_IOSFSB_RESET_STATUS, 100)) DRM_ERROR("FDI mPHY reset assert timeout\n"); tmp = I915_READ(SOUTH_CHICKEN2); tmp &= ~FDI_MPHY_IOSFSB_RESET_CTL; I915_WRITE(SOUTH_CHICKEN2, tmp); if (wait_for_atomic_us((I915_READ(SOUTH_CHICKEN2) & FDI_MPHY_IOSFSB_RESET_STATUS) == 0, 100)) DRM_ERROR("FDI mPHY reset de-assert timeout\n"); } /* WaMPhyProgramming:hsw */ static void lpt_program_fdi_mphy(struct drm_i915_private *dev_priv) { uint32_t tmp; tmp = intel_sbi_read(dev_priv, 0x8008, SBI_MPHY); tmp &= ~(0xFF << 24); tmp |= (0x12 << 24); intel_sbi_write(dev_priv, 0x8008, tmp, SBI_MPHY); tmp = intel_sbi_read(dev_priv, 0x2008, SBI_MPHY); tmp |= (1 << 11); intel_sbi_write(dev_priv, 0x2008, tmp, SBI_MPHY); tmp = intel_sbi_read(dev_priv, 0x2108, SBI_MPHY); tmp |= (1 << 11); intel_sbi_write(dev_priv, 0x2108, tmp, SBI_MPHY); tmp = intel_sbi_read(dev_priv, 0x206C, SBI_MPHY); tmp |= (1 << 24) | (1 << 21) | (1 << 18); intel_sbi_write(dev_priv, 0x206C, tmp, SBI_MPHY); tmp = intel_sbi_read(dev_priv, 0x216C, SBI_MPHY); tmp |= (1 << 24) | (1 << 21) | (1 << 18); intel_sbi_write(dev_priv, 0x216C, tmp, SBI_MPHY); tmp = intel_sbi_read(dev_priv, 0x2080, SBI_MPHY); tmp &= ~(7 << 13); tmp |= (5 << 13); intel_sbi_write(dev_priv, 0x2080, tmp, SBI_MPHY); tmp = intel_sbi_read(dev_priv, 0x2180, SBI_MPHY); tmp &= ~(7 << 13); tmp |= (5 << 13); intel_sbi_write(dev_priv, 0x2180, tmp, SBI_MPHY); tmp = intel_sbi_read(dev_priv, 0x208C, SBI_MPHY); tmp &= ~0xFF; tmp |= 0x1C; intel_sbi_write(dev_priv, 0x208C, tmp, SBI_MPHY); tmp = intel_sbi_read(dev_priv, 0x218C, SBI_MPHY); tmp &= ~0xFF; tmp |= 0x1C; intel_sbi_write(dev_priv, 0x218C, tmp, SBI_MPHY); tmp = intel_sbi_read(dev_priv, 0x2098, SBI_MPHY); tmp &= ~(0xFF << 16); tmp |= (0x1C << 16); intel_sbi_write(dev_priv, 0x2098, tmp, SBI_MPHY); tmp = intel_sbi_read(dev_priv, 0x2198, SBI_MPHY); tmp &= ~(0xFF << 16); tmp |= (0x1C << 16); intel_sbi_write(dev_priv, 0x2198, tmp, SBI_MPHY); tmp = intel_sbi_read(dev_priv, 0x20C4, SBI_MPHY); tmp |= (1 << 27); intel_sbi_write(dev_priv, 0x20C4, tmp, SBI_MPHY); tmp = intel_sbi_read(dev_priv, 0x21C4, SBI_MPHY); tmp |= (1 << 27); intel_sbi_write(dev_priv, 0x21C4, tmp, SBI_MPHY); tmp = intel_sbi_read(dev_priv, 0x20EC, SBI_MPHY); tmp &= ~(0xF << 28); tmp |= (4 << 28); intel_sbi_write(dev_priv, 0x20EC, tmp, SBI_MPHY); tmp = intel_sbi_read(dev_priv, 0x21EC, SBI_MPHY); tmp &= ~(0xF << 28); tmp |= (4 << 28); intel_sbi_write(dev_priv, 0x21EC, tmp, SBI_MPHY); } /* Implements 3 different sequences from BSpec chapter "Display iCLK * Programming" based on the parameters passed: * - Sequence to enable CLKOUT_DP * - Sequence to enable CLKOUT_DP without spread * - Sequence to enable CLKOUT_DP for FDI usage and configure PCH FDI I/O */ static void lpt_enable_clkout_dp(struct drm_device *dev, bool with_spread, bool with_fdi) { struct drm_i915_private *dev_priv = dev->dev_private; uint32_t reg, tmp; if (WARN(with_fdi && !with_spread, "FDI requires downspread\n")) with_spread = true; if (WARN(dev_priv->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE && with_fdi, "LP PCH doesn't have FDI\n")) with_fdi = false; mutex_lock(&dev_priv->dpio_lock); tmp = intel_sbi_read(dev_priv, SBI_SSCCTL, SBI_ICLK); tmp &= ~SBI_SSCCTL_DISABLE; tmp |= SBI_SSCCTL_PATHALT; intel_sbi_write(dev_priv, SBI_SSCCTL, tmp, SBI_ICLK); udelay(24); if (with_spread) { tmp = intel_sbi_read(dev_priv, SBI_SSCCTL, SBI_ICLK); tmp &= ~SBI_SSCCTL_PATHALT; intel_sbi_write(dev_priv, SBI_SSCCTL, tmp, SBI_ICLK); if (with_fdi) { lpt_reset_fdi_mphy(dev_priv); lpt_program_fdi_mphy(dev_priv); } } reg = (dev_priv->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) ? SBI_GEN0 : SBI_DBUFF0; tmp = intel_sbi_read(dev_priv, reg, SBI_ICLK); tmp |= SBI_GEN0_CFG_BUFFENABLE_DISABLE; intel_sbi_write(dev_priv, reg, tmp, SBI_ICLK); mutex_unlock(&dev_priv->dpio_lock); } /* Sequence to disable CLKOUT_DP */ static void lpt_disable_clkout_dp(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; uint32_t reg, tmp; mutex_lock(&dev_priv->dpio_lock); reg = (dev_priv->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) ? SBI_GEN0 : SBI_DBUFF0; tmp = intel_sbi_read(dev_priv, reg, SBI_ICLK); tmp &= ~SBI_GEN0_CFG_BUFFENABLE_DISABLE; intel_sbi_write(dev_priv, reg, tmp, SBI_ICLK); tmp = intel_sbi_read(dev_priv, SBI_SSCCTL, SBI_ICLK); if (!(tmp & SBI_SSCCTL_DISABLE)) { if (!(tmp & SBI_SSCCTL_PATHALT)) { tmp |= SBI_SSCCTL_PATHALT; intel_sbi_write(dev_priv, SBI_SSCCTL, tmp, SBI_ICLK); udelay(32); } tmp |= SBI_SSCCTL_DISABLE; intel_sbi_write(dev_priv, SBI_SSCCTL, tmp, SBI_ICLK); } mutex_unlock(&dev_priv->dpio_lock); } static void lpt_init_pch_refclk(struct drm_device *dev) { struct drm_mode_config *mode_config = &dev->mode_config; struct intel_encoder *encoder; bool has_vga = false; list_for_each_entry(encoder, &mode_config->encoder_list, base.head) { switch (encoder->type) { case INTEL_OUTPUT_ANALOG: has_vga = true; break; } } if (has_vga) lpt_enable_clkout_dp(dev, true, true); else lpt_disable_clkout_dp(dev); } /* * Initialize reference clocks when the driver loads */ void intel_init_pch_refclk(struct drm_device *dev) { if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) ironlake_init_pch_refclk(dev); else if (HAS_PCH_LPT(dev)) lpt_init_pch_refclk(dev); } static int ironlake_get_refclk(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_encoder *encoder; int num_connectors = 0; bool is_lvds = false; for_each_encoder_on_crtc(dev, crtc, encoder) { switch (encoder->type) { case INTEL_OUTPUT_LVDS: is_lvds = true; break; } num_connectors++; } if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2) { DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n", dev_priv->vbt.lvds_ssc_freq); return dev_priv->vbt.lvds_ssc_freq * 1000; } return 120000; } static void ironlake_set_pipeconf(struct drm_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int pipe = intel_crtc->pipe; uint32_t val; val = 0; switch (intel_crtc->config.pipe_bpp) { case 18: val |= PIPECONF_6BPC; break; case 24: val |= PIPECONF_8BPC; break; case 30: val |= PIPECONF_10BPC; break; case 36: val |= PIPECONF_12BPC; break; default: /* Case prevented by intel_choose_pipe_bpp_dither. */ BUG(); } if (intel_crtc->config.dither) val |= (PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP); if (intel_crtc->config.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) val |= PIPECONF_INTERLACED_ILK; else val |= PIPECONF_PROGRESSIVE; if (intel_crtc->config.limited_color_range) val |= PIPECONF_COLOR_RANGE_SELECT; I915_WRITE(PIPECONF(pipe), val); POSTING_READ(PIPECONF(pipe)); } /* * Set up the pipe CSC unit. * * Currently only full range RGB to limited range RGB conversion * is supported, but eventually this should handle various * RGB<->YCbCr scenarios as well. */ static void intel_set_pipe_csc(struct drm_crtc *crtc) { 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; uint16_t coeff = 0x7800; /* 1.0 */ /* * TODO: Check what kind of values actually come out of the pipe * with these coeff/postoff values and adjust to get the best * accuracy. Perhaps we even need to take the bpc value into * consideration. */ if (intel_crtc->config.limited_color_range) coeff = ((235 - 16) * (1 << 12) / 255) & 0xff8; /* 0.xxx... */ /* * GY/GU and RY/RU should be the other way around according * to BSpec, but reality doesn't agree. Just set them up in * a way that results in the correct picture. */ I915_WRITE(PIPE_CSC_COEFF_RY_GY(pipe), coeff << 16); I915_WRITE(PIPE_CSC_COEFF_BY(pipe), 0); I915_WRITE(PIPE_CSC_COEFF_RU_GU(pipe), coeff); I915_WRITE(PIPE_CSC_COEFF_BU(pipe), 0); I915_WRITE(PIPE_CSC_COEFF_RV_GV(pipe), 0); I915_WRITE(PIPE_CSC_COEFF_BV(pipe), coeff << 16); I915_WRITE(PIPE_CSC_PREOFF_HI(pipe), 0); I915_WRITE(PIPE_CSC_PREOFF_ME(pipe), 0); I915_WRITE(PIPE_CSC_PREOFF_LO(pipe), 0); if (INTEL_INFO(dev)->gen > 6) { uint16_t postoff = 0; if (intel_crtc->config.limited_color_range) postoff = (16 * (1 << 13) / 255) & 0x1fff; I915_WRITE(PIPE_CSC_POSTOFF_HI(pipe), postoff); I915_WRITE(PIPE_CSC_POSTOFF_ME(pipe), postoff); I915_WRITE(PIPE_CSC_POSTOFF_LO(pipe), postoff); I915_WRITE(PIPE_CSC_MODE(pipe), 0); } else { uint32_t mode = CSC_MODE_YUV_TO_RGB; if (intel_crtc->config.limited_color_range) mode |= CSC_BLACK_SCREEN_OFFSET; I915_WRITE(PIPE_CSC_MODE(pipe), mode); } } static void haswell_set_pipeconf(struct drm_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder; uint32_t val; val = 0; if (intel_crtc->config.dither) val |= (PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP); if (intel_crtc->config.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) val |= PIPECONF_INTERLACED_ILK; else val |= PIPECONF_PROGRESSIVE; I915_WRITE(PIPECONF(cpu_transcoder), val); POSTING_READ(PIPECONF(cpu_transcoder)); I915_WRITE(GAMMA_MODE(intel_crtc->pipe), GAMMA_MODE_MODE_8BIT); POSTING_READ(GAMMA_MODE(intel_crtc->pipe)); } static bool ironlake_compute_clocks(struct drm_crtc *crtc, intel_clock_t *clock, bool *has_reduced_clock, intel_clock_t *reduced_clock) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_encoder *intel_encoder; int refclk; const intel_limit_t *limit; bool ret, is_lvds = false; for_each_encoder_on_crtc(dev, crtc, intel_encoder) { switch (intel_encoder->type) { case INTEL_OUTPUT_LVDS: is_lvds = true; break; } } refclk = ironlake_get_refclk(crtc); /* * Returns a set of divisors for the desired target clock with the given * refclk, or FALSE. The returned values represent the clock equation: * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. */ limit = intel_limit(crtc, refclk); ret = dev_priv->display.find_dpll(limit, crtc, to_intel_crtc(crtc)->config.port_clock, refclk, NULL, clock); if (!ret) return false; if (is_lvds && dev_priv->lvds_downclock_avail) { /* * Ensure we match the reduced clock's P to the target clock. * If the clocks don't match, we can't switch the display clock * by using the FP0/FP1. In such case we will disable the LVDS * downclock feature. */ *has_reduced_clock = dev_priv->display.find_dpll(limit, crtc, dev_priv->lvds_downclock, refclk, clock, reduced_clock); } return true; } static void cpt_enable_fdi_bc_bifurcation(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; uint32_t temp; temp = I915_READ(SOUTH_CHICKEN1); if (temp & FDI_BC_BIFURCATION_SELECT) return; WARN_ON(I915_READ(FDI_RX_CTL(PIPE_B)) & FDI_RX_ENABLE); WARN_ON(I915_READ(FDI_RX_CTL(PIPE_C)) & FDI_RX_ENABLE); temp |= FDI_BC_BIFURCATION_SELECT; DRM_DEBUG_KMS("enabling fdi C rx\n"); I915_WRITE(SOUTH_CHICKEN1, temp); POSTING_READ(SOUTH_CHICKEN1); } static void ivybridge_update_fdi_bc_bifurcation(struct intel_crtc *intel_crtc) { struct drm_device *dev = intel_crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; switch (intel_crtc->pipe) { case PIPE_A: break; case PIPE_B: if (intel_crtc->config.fdi_lanes > 2) WARN_ON(I915_READ(SOUTH_CHICKEN1) & FDI_BC_BIFURCATION_SELECT); else cpt_enable_fdi_bc_bifurcation(dev); break; case PIPE_C: cpt_enable_fdi_bc_bifurcation(dev); break; default: BUG(); } } int ironlake_get_lanes_required(int target_clock, int link_bw, int bpp) { /* * Account for spread spectrum to avoid * oversubscribing the link. Max center spread * is 2.5%; use 5% for safety's sake. */ u32 bps = target_clock * bpp * 21 / 20; return bps / (link_bw * 8) + 1; } static bool ironlake_needs_fb_cb_tune(struct dpll *dpll, int factor) { return i9xx_dpll_compute_m(dpll) < factor * dpll->n; } static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc, u32 *fp, intel_clock_t *reduced_clock, u32 *fp2) { struct drm_crtc *crtc = &intel_crtc->base; struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_encoder *intel_encoder; uint32_t dpll; int factor, num_connectors = 0; bool is_lvds = false, is_sdvo = false; for_each_encoder_on_crtc(dev, crtc, intel_encoder) { switch (intel_encoder->type) { case INTEL_OUTPUT_LVDS: is_lvds = true; break; case INTEL_OUTPUT_SDVO: case INTEL_OUTPUT_HDMI: is_sdvo = true; break; } num_connectors++; } /* Enable autotuning of the PLL clock (if permissible) */ factor = 21; if (is_lvds) { if ((intel_panel_use_ssc(dev_priv) && dev_priv->vbt.lvds_ssc_freq == 100) || (HAS_PCH_IBX(dev) && intel_is_dual_link_lvds(dev))) factor = 25; } else if (intel_crtc->config.sdvo_tv_clock) factor = 20; if (ironlake_needs_fb_cb_tune(&intel_crtc->config.dpll, factor)) *fp |= FP_CB_TUNE; if (fp2 && (reduced_clock->m < factor * reduced_clock->n)) *fp2 |= FP_CB_TUNE; dpll = 0; if (is_lvds) dpll |= DPLLB_MODE_LVDS; else dpll |= DPLLB_MODE_DAC_SERIAL; dpll |= (intel_crtc->config.pixel_multiplier - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT; if (is_sdvo) dpll |= DPLL_SDVO_HIGH_SPEED; if (intel_crtc->config.has_dp_encoder) dpll |= DPLL_SDVO_HIGH_SPEED; /* compute bitmask from p1 value */ dpll |= (1 << (intel_crtc->config.dpll.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT; /* also FPA1 */ dpll |= (1 << (intel_crtc->config.dpll.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT; switch (intel_crtc->config.dpll.p2) { case 5: dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5; break; case 7: dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7; break; case 10: dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10; break; case 14: dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14; break; } if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2) dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN; else dpll |= PLL_REF_INPUT_DREFCLK; return dpll | DPLL_VCO_ENABLE; } static int ironlake_crtc_mode_set(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *fb) { 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; int plane = intel_crtc->plane; int num_connectors = 0; intel_clock_t clock, reduced_clock; u32 dpll = 0, fp = 0, fp2 = 0; bool ok, has_reduced_clock = false; bool is_lvds = false; struct intel_encoder *encoder; struct intel_shared_dpll *pll; int ret; for_each_encoder_on_crtc(dev, crtc, encoder) { switch (encoder->type) { case INTEL_OUTPUT_LVDS: is_lvds = true; break; } num_connectors++; } WARN(!(HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)), "Unexpected PCH type %d\n", INTEL_PCH_TYPE(dev)); ok = ironlake_compute_clocks(crtc, &clock, &has_reduced_clock, &reduced_clock); if (!ok && !intel_crtc->config.clock_set) { DRM_ERROR("Couldn't find PLL settings for mode!\n"); return -EINVAL; } /* Compat-code for transition, will disappear. */ if (!intel_crtc->config.clock_set) { intel_crtc->config.dpll.n = clock.n; intel_crtc->config.dpll.m1 = clock.m1; intel_crtc->config.dpll.m2 = clock.m2; intel_crtc->config.dpll.p1 = clock.p1; intel_crtc->config.dpll.p2 = clock.p2; } /* Ensure that the cursor is valid for the new mode before changing... */ intel_crtc_update_cursor(crtc, true); /* CPU eDP is the only output that doesn't need a PCH PLL of its own. */ if (intel_crtc->config.has_pch_encoder) { fp = i9xx_dpll_compute_fp(&intel_crtc->config.dpll); if (has_reduced_clock) fp2 = i9xx_dpll_compute_fp(&reduced_clock); dpll = ironlake_compute_dpll(intel_crtc, &fp, &reduced_clock, has_reduced_clock ? &fp2 : NULL); intel_crtc->config.dpll_hw_state.dpll = dpll; intel_crtc->config.dpll_hw_state.fp0 = fp; if (has_reduced_clock) intel_crtc->config.dpll_hw_state.fp1 = fp2; else intel_crtc->config.dpll_hw_state.fp1 = fp; pll = intel_get_shared_dpll(intel_crtc); if (pll == NULL) { DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n", pipe_name(pipe)); return -EINVAL; } } else intel_put_shared_dpll(intel_crtc); if (intel_crtc->config.has_dp_encoder) intel_dp_set_m_n(intel_crtc); if (is_lvds && has_reduced_clock && i915_powersave) intel_crtc->lowfreq_avail = true; else intel_crtc->lowfreq_avail = false; if (intel_crtc->config.has_pch_encoder) { pll = intel_crtc_to_shared_dpll(intel_crtc); if (pll == NULL) { DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n", pipe_name(pipe)); return -EINVAL; } } intel_set_pipe_timings(intel_crtc); if (intel_crtc->config.has_pch_encoder) { intel_cpu_transcoder_set_m_n(intel_crtc, &intel_crtc->config.fdi_m_n); } if (IS_IVYBRIDGE(dev)) ivybridge_update_fdi_bc_bifurcation(intel_crtc); ironlake_set_pipeconf(crtc); /* Set up the display plane register */ I915_WRITE(DSPCNTR(plane), DISPPLANE_GAMMA_ENABLE); POSTING_READ(DSPCNTR(plane)); ret = intel_pipe_set_base(crtc, x, y, fb); intel_update_watermarks(dev); return ret; } static void ironlake_get_fdi_m_n_config(struct intel_crtc *crtc, struct intel_crtc_config *pipe_config) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; enum transcoder transcoder = pipe_config->cpu_transcoder; pipe_config->fdi_m_n.link_m = I915_READ(PIPE_LINK_M1(transcoder)); pipe_config->fdi_m_n.link_n = I915_READ(PIPE_LINK_N1(transcoder)); pipe_config->fdi_m_n.gmch_m = I915_READ(PIPE_DATA_M1(transcoder)) & ~TU_SIZE_MASK; pipe_config->fdi_m_n.gmch_n = I915_READ(PIPE_DATA_N1(transcoder)); pipe_config->fdi_m_n.tu = ((I915_READ(PIPE_DATA_M1(transcoder)) & TU_SIZE_MASK) >> TU_SIZE_SHIFT) + 1; } static void ironlake_get_pfit_config(struct intel_crtc *crtc, struct intel_crtc_config *pipe_config) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; uint32_t tmp; tmp = I915_READ(PF_CTL(crtc->pipe)); if (tmp & PF_ENABLE) { pipe_config->pch_pfit.pos = I915_READ(PF_WIN_POS(crtc->pipe)); pipe_config->pch_pfit.size = I915_READ(PF_WIN_SZ(crtc->pipe)); /* We currently do not free assignements of panel fitters on * ivb/hsw (since we don't use the higher upscaling modes which * differentiates them) so just WARN about this case for now. */ if (IS_GEN7(dev)) { WARN_ON((tmp & PF_PIPE_SEL_MASK_IVB) != PF_PIPE_SEL_IVB(crtc->pipe)); } } } static bool ironlake_get_pipe_config(struct intel_crtc *crtc, struct intel_crtc_config *pipe_config) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; uint32_t tmp; pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe; pipe_config->shared_dpll = DPLL_ID_PRIVATE; tmp = I915_READ(PIPECONF(crtc->pipe)); if (!(tmp & PIPECONF_ENABLE)) return false; if (I915_READ(PCH_TRANSCONF(crtc->pipe)) & TRANS_ENABLE) { struct intel_shared_dpll *pll; pipe_config->has_pch_encoder = true; tmp = I915_READ(FDI_RX_CTL(crtc->pipe)); pipe_config->fdi_lanes = ((FDI_DP_PORT_WIDTH_MASK & tmp) >> FDI_DP_PORT_WIDTH_SHIFT) + 1; ironlake_get_fdi_m_n_config(crtc, pipe_config); if (HAS_PCH_IBX(dev_priv->dev)) { pipe_config->shared_dpll = (enum intel_dpll_id) crtc->pipe; } else { tmp = I915_READ(PCH_DPLL_SEL); if (tmp & TRANS_DPLLB_SEL(crtc->pipe)) pipe_config->shared_dpll = DPLL_ID_PCH_PLL_B; else pipe_config->shared_dpll = DPLL_ID_PCH_PLL_A; } pll = &dev_priv->shared_dplls[pipe_config->shared_dpll]; WARN_ON(!pll->get_hw_state(dev_priv, pll, &pipe_config->dpll_hw_state)); tmp = pipe_config->dpll_hw_state.dpll; pipe_config->pixel_multiplier = ((tmp & PLL_REF_SDVO_HDMI_MULTIPLIER_MASK) >> PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT) + 1; } else { pipe_config->pixel_multiplier = 1; } intel_get_pipe_timings(crtc, pipe_config); ironlake_get_pfit_config(crtc, pipe_config); return true; } static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv) { struct drm_device *dev = dev_priv->dev; struct intel_ddi_plls *plls = &dev_priv->ddi_plls; struct intel_crtc *crtc; unsigned long irqflags; 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", pipe_name(crtc->pipe)); WARN(I915_READ(HSW_PWR_WELL_DRIVER), "Power well on\n"); WARN(plls->spll_refcount, "SPLL enabled\n"); WARN(plls->wrpll1_refcount, "WRPLL1 enabled\n"); WARN(plls->wrpll2_refcount, "WRPLL2 enabled\n"); WARN(I915_READ(PCH_PP_STATUS) & PP_ON, "Panel power on\n"); WARN(I915_READ(BLC_PWM_CPU_CTL2) & BLM_PWM_ENABLE, "CPU PWM1 enabled\n"); WARN(I915_READ(HSW_BLC_PWM2_CTL) & BLM_PWM_ENABLE, "CPU PWM2 enabled\n"); WARN(I915_READ(BLC_PWM_PCH_CTL1) & BLM_PCH_PWM_ENABLE, "PCH PWM1 enabled\n"); WARN(I915_READ(UTIL_PIN_CTL) & UTIL_PIN_ENABLE, "Utility pin enabled\n"); WARN(I915_READ(PCH_GTC_CTL) & PCH_GTC_ENABLE, "PCH GTC enabled\n"); spin_lock_irqsave(&dev_priv->irq_lock, irqflags); val = I915_READ(DEIMR); WARN((val & ~DE_PCH_EVENT_IVB) != val, "Unexpected DEIMR bits enabled: 0x%x\n", val); val = I915_READ(SDEIMR); WARN((val | SDE_HOTPLUG_MASK_CPT) != 0xffffffff, "Unexpected SDEIMR bits enabled: 0x%x\n", val); spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); } /* * This function implements pieces of two sequences from BSpec: * - Sequence for display software to disable LCPLL * - Sequence for display software to allow package C8+ * The steps implemented here are just the steps that actually touch the LCPLL * register. Callers should take care of disabling all the display engine * functions, doing the mode unset, fixing interrupts, etc. */ void hsw_disable_lcpll(struct drm_i915_private *dev_priv, bool switch_to_fclk, bool allow_power_down) { uint32_t val; assert_can_disable_lcpll(dev_priv); val = I915_READ(LCPLL_CTL); if (switch_to_fclk) { val |= LCPLL_CD_SOURCE_FCLK; I915_WRITE(LCPLL_CTL, val); if (wait_for_atomic_us(I915_READ(LCPLL_CTL) & LCPLL_CD_SOURCE_FCLK_DONE, 1)) DRM_ERROR("Switching to FCLK failed\n"); val = I915_READ(LCPLL_CTL); } val |= LCPLL_PLL_DISABLE; I915_WRITE(LCPLL_CTL, val); POSTING_READ(LCPLL_CTL); if (wait_for((I915_READ(LCPLL_CTL) & LCPLL_PLL_LOCK) == 0, 1)) DRM_ERROR("LCPLL still locked\n"); val = I915_READ(D_COMP); val |= D_COMP_COMP_DISABLE; I915_WRITE(D_COMP, val); POSTING_READ(D_COMP); ndelay(100); if (wait_for((I915_READ(D_COMP) & D_COMP_RCOMP_IN_PROGRESS) == 0, 1)) DRM_ERROR("D_COMP RCOMP still in progress\n"); if (allow_power_down) { val = I915_READ(LCPLL_CTL); val |= LCPLL_POWER_DOWN_ALLOW; I915_WRITE(LCPLL_CTL, val); POSTING_READ(LCPLL_CTL); } } /* * Fully restores LCPLL, disallowing power down and switching back to LCPLL * source. */ void hsw_restore_lcpll(struct drm_i915_private *dev_priv) { uint32_t val; val = I915_READ(LCPLL_CTL); if ((val & (LCPLL_PLL_LOCK | LCPLL_PLL_DISABLE | LCPLL_CD_SOURCE_FCLK | LCPLL_POWER_DOWN_ALLOW)) == LCPLL_PLL_LOCK) return; /* 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, FORCEWAKE_ALL); if (val & LCPLL_POWER_DOWN_ALLOW) { val &= ~LCPLL_POWER_DOWN_ALLOW; I915_WRITE(LCPLL_CTL, val); POSTING_READ(LCPLL_CTL); } val = I915_READ(D_COMP); val |= D_COMP_COMP_FORCE; val &= ~D_COMP_COMP_DISABLE; I915_WRITE(D_COMP, val); POSTING_READ(D_COMP); val = I915_READ(LCPLL_CTL); val &= ~LCPLL_PLL_DISABLE; I915_WRITE(LCPLL_CTL, val); if (wait_for(I915_READ(LCPLL_CTL) & LCPLL_PLL_LOCK, 5)) DRM_ERROR("LCPLL not locked yet\n"); if (val & LCPLL_CD_SOURCE_FCLK) { val = I915_READ(LCPLL_CTL); val &= ~LCPLL_CD_SOURCE_FCLK; I915_WRITE(LCPLL_CTL, val); if (wait_for_atomic_us((I915_READ(LCPLL_CTL) & LCPLL_CD_SOURCE_FCLK_DONE) == 0, 1)) DRM_ERROR("Switching back to LCPLL failed\n"); } dev_priv->uncore.funcs.force_wake_put(dev_priv, FORCEWAKE_ALL); } void hsw_enable_pc8_work(struct work_struct *__work) { struct drm_i915_private *dev_priv = container_of(to_delayed_work(__work), struct drm_i915_private, pc8.enable_work); struct drm_device *dev = dev_priv->dev; uint32_t val; if (dev_priv->pc8.enabled) return; DRM_DEBUG_KMS("Enabling package C8+\n"); dev_priv->pc8.enabled = true; if (dev_priv->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) { val = I915_READ(SOUTH_DSPCLK_GATE_D); val &= ~PCH_LP_PARTITION_LEVEL_DISABLE; I915_WRITE(SOUTH_DSPCLK_GATE_D, val); } lpt_disable_clkout_dp(dev); hsw_pc8_disable_interrupts(dev); hsw_disable_lcpll(dev_priv, true, true); } static void __hsw_enable_package_c8(struct drm_i915_private *dev_priv) { WARN_ON(!mutex_is_locked(&dev_priv->pc8.lock)); WARN(dev_priv->pc8.disable_count < 1, "pc8.disable_count: %d\n", dev_priv->pc8.disable_count); dev_priv->pc8.disable_count--; if (dev_priv->pc8.disable_count != 0) return; schedule_delayed_work(&dev_priv->pc8.enable_work, msecs_to_jiffies(i915_pc8_timeout)); } static void __hsw_disable_package_c8(struct drm_i915_private *dev_priv) { struct drm_device *dev = dev_priv->dev; uint32_t val; WARN_ON(!mutex_is_locked(&dev_priv->pc8.lock)); WARN(dev_priv->pc8.disable_count < 0, "pc8.disable_count: %d\n", dev_priv->pc8.disable_count); dev_priv->pc8.disable_count++; if (dev_priv->pc8.disable_count != 1) return; cancel_delayed_work_sync(&dev_priv->pc8.enable_work); if (!dev_priv->pc8.enabled) return; DRM_DEBUG_KMS("Disabling package C8+\n"); hsw_restore_lcpll(dev_priv); hsw_pc8_restore_interrupts(dev); lpt_init_pch_refclk(dev); if (dev_priv->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) { val = I915_READ(SOUTH_DSPCLK_GATE_D); val |= PCH_LP_PARTITION_LEVEL_DISABLE; I915_WRITE(SOUTH_DSPCLK_GATE_D, val); } intel_prepare_ddi(dev); i915_gem_init_swizzling(dev); mutex_lock(&dev_priv->rps.hw_lock); gen6_update_ring_freq(dev); mutex_unlock(&dev_priv->rps.hw_lock); dev_priv->pc8.enabled = false; } void hsw_enable_package_c8(struct drm_i915_private *dev_priv) { mutex_lock(&dev_priv->pc8.lock); __hsw_enable_package_c8(dev_priv); mutex_unlock(&dev_priv->pc8.lock); } void hsw_disable_package_c8(struct drm_i915_private *dev_priv) { mutex_lock(&dev_priv->pc8.lock); __hsw_disable_package_c8(dev_priv); mutex_unlock(&dev_priv->pc8.lock); } static bool hsw_can_enable_package_c8(struct drm_i915_private *dev_priv) { struct drm_device *dev = dev_priv->dev; struct intel_crtc *crtc; uint32_t val; list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) if (crtc->base.enabled) return false; /* This case is still possible since we have the i915.disable_power_well * parameter and also the KVMr or something else might be requesting the * power well. */ val = I915_READ(HSW_PWR_WELL_DRIVER); if (val != 0) { DRM_DEBUG_KMS("Not enabling PC8: power well on\n"); return false; } return true; } /* Since we're called from modeset_global_resources there's no way to * symmetrically increase and decrease the refcount, so we use * dev_priv->pc8.requirements_met to track whether we already have the refcount * or not. */ static void hsw_update_package_c8(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; bool allow; if (!i915_enable_pc8) return; mutex_lock(&dev_priv->pc8.lock); allow = hsw_can_enable_package_c8(dev_priv); if (allow == dev_priv->pc8.requirements_met) goto done; dev_priv->pc8.requirements_met = allow; if (allow) __hsw_enable_package_c8(dev_priv); else __hsw_disable_package_c8(dev_priv); done: mutex_unlock(&dev_priv->pc8.lock); } static void hsw_package_c8_gpu_idle(struct drm_i915_private *dev_priv) { if (!dev_priv->pc8.gpu_idle) { dev_priv->pc8.gpu_idle = true; hsw_enable_package_c8(dev_priv); } } static void hsw_package_c8_gpu_busy(struct drm_i915_private *dev_priv) { if (dev_priv->pc8.gpu_idle) { dev_priv->pc8.gpu_idle = false; hsw_disable_package_c8(dev_priv); } } static void haswell_modeset_global_resources(struct drm_device *dev) { bool enable = false; struct intel_crtc *crtc; list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) { if (!crtc->base.enabled) continue; if (crtc->pipe != PIPE_A || crtc->config.pch_pfit.size || crtc->config.cpu_transcoder != TRANSCODER_EDP) enable = true; } intel_set_power_well(dev, enable); hsw_update_package_c8(dev); } static int haswell_crtc_mode_set(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *fb) { 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 plane = intel_crtc->plane; int ret; if (!intel_ddi_pll_mode_set(crtc)) return -EINVAL; /* Ensure that the cursor is valid for the new mode before changing... */ intel_crtc_update_cursor(crtc, true); if (intel_crtc->config.has_dp_encoder) intel_dp_set_m_n(intel_crtc); intel_crtc->lowfreq_avail = false; intel_set_pipe_timings(intel_crtc); if (intel_crtc->config.has_pch_encoder) { intel_cpu_transcoder_set_m_n(intel_crtc, &intel_crtc->config.fdi_m_n); } haswell_set_pipeconf(crtc); intel_set_pipe_csc(crtc); /* Set up the display plane register */ I915_WRITE(DSPCNTR(plane), DISPPLANE_GAMMA_ENABLE | DISPPLANE_PIPE_CSC_ENABLE); POSTING_READ(DSPCNTR(plane)); ret = intel_pipe_set_base(crtc, x, y, fb); intel_update_watermarks(dev); return ret; } static bool haswell_get_pipe_config(struct intel_crtc *crtc, struct intel_crtc_config *pipe_config) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; enum intel_display_power_domain pfit_domain; uint32_t tmp; pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe; pipe_config->shared_dpll = DPLL_ID_PRIVATE; tmp = I915_READ(TRANS_DDI_FUNC_CTL(TRANSCODER_EDP)); if (tmp & TRANS_DDI_FUNC_ENABLE) { enum pipe trans_edp_pipe; switch (tmp & TRANS_DDI_EDP_INPUT_MASK) { default: WARN(1, "unknown pipe linked to edp transcoder\n"); case TRANS_DDI_EDP_INPUT_A_ONOFF: case TRANS_DDI_EDP_INPUT_A_ON: trans_edp_pipe = PIPE_A; break; case TRANS_DDI_EDP_INPUT_B_ONOFF: trans_edp_pipe = PIPE_B; break; case TRANS_DDI_EDP_INPUT_C_ONOFF: trans_edp_pipe = PIPE_C; break; } if (trans_edp_pipe == crtc->pipe) pipe_config->cpu_transcoder = TRANSCODER_EDP; } if (!intel_display_power_enabled(dev, POWER_DOMAIN_TRANSCODER(pipe_config->cpu_transcoder))) return false; tmp = I915_READ(PIPECONF(pipe_config->cpu_transcoder)); if (!(tmp & PIPECONF_ENABLE)) return false; /* * Haswell has only FDI/PCH transcoder A. It is which is connected to * DDI E. So just check whether this pipe is wired to DDI E and whether * the PCH transcoder is on. */ tmp = I915_READ(TRANS_DDI_FUNC_CTL(pipe_config->cpu_transcoder)); if ((tmp & TRANS_DDI_PORT_MASK) == TRANS_DDI_SELECT_PORT(PORT_E) && I915_READ(LPT_TRANSCONF) & TRANS_ENABLE) { pipe_config->has_pch_encoder = true; tmp = I915_READ(FDI_RX_CTL(PIPE_A)); pipe_config->fdi_lanes = ((FDI_DP_PORT_WIDTH_MASK & tmp) >> FDI_DP_PORT_WIDTH_SHIFT) + 1; ironlake_get_fdi_m_n_config(crtc, pipe_config); } intel_get_pipe_timings(crtc, pipe_config); pfit_domain = POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe); if (intel_display_power_enabled(dev, pfit_domain)) ironlake_get_pfit_config(crtc, pipe_config); pipe_config->ips_enabled = hsw_crtc_supports_ips(crtc) && (I915_READ(IPS_CTL) & IPS_ENABLE); pipe_config->pixel_multiplier = 1; return true; } static int intel_crtc_mode_set(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *fb) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_encoder *encoder; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct drm_display_mode *mode = &intel_crtc->config.requested_mode; int pipe = intel_crtc->pipe; int ret; drm_vblank_pre_modeset(dev, pipe); ret = dev_priv->display.crtc_mode_set(crtc, x, y, fb); drm_vblank_post_modeset(dev, pipe); if (ret != 0) return ret; for_each_encoder_on_crtc(dev, crtc, encoder) { DRM_DEBUG_KMS("[ENCODER:%d:%s] set [MODE:%d:%s]\n", encoder->base.base.id, drm_get_encoder_name(&encoder->base), mode->base.id, mode->name); encoder->mode_set(encoder); } return 0; } static bool intel_eld_uptodate(struct drm_connector *connector, int reg_eldv, uint32_t bits_eldv, int reg_elda, uint32_t bits_elda, int reg_edid) { struct drm_i915_private *dev_priv = connector->dev->dev_private; uint8_t *eld = connector->eld; uint32_t i; i = I915_READ(reg_eldv); i &= bits_eldv; if (!eld[0]) return !i; if (!i) return false; i = I915_READ(reg_elda); i &= ~bits_elda; I915_WRITE(reg_elda, i); for (i = 0; i < eld[2]; i++) if (I915_READ(reg_edid) != *((uint32_t *)eld + i)) return false; return true; } static void g4x_write_eld(struct drm_connector *connector, struct drm_crtc *crtc) { struct drm_i915_private *dev_priv = connector->dev->dev_private; uint8_t *eld = connector->eld; uint32_t eldv; uint32_t len; uint32_t i; i = I915_READ(G4X_AUD_VID_DID); if (i == INTEL_AUDIO_DEVBLC || i == INTEL_AUDIO_DEVCL) eldv = G4X_ELDV_DEVCL_DEVBLC; else eldv = G4X_ELDV_DEVCTG; if (intel_eld_uptodate(connector, G4X_AUD_CNTL_ST, eldv, G4X_AUD_CNTL_ST, G4X_ELD_ADDR, G4X_HDMIW_HDMIEDID)) return; i = I915_READ(G4X_AUD_CNTL_ST); i &= ~(eldv | G4X_ELD_ADDR); len = (i >> 9) & 0x1f; /* ELD buffer size */ I915_WRITE(G4X_AUD_CNTL_ST, i); if (!eld[0]) return; len = min_t(uint8_t, eld[2], len); DRM_DEBUG_DRIVER("ELD size %d\n", len); for (i = 0; i < len; i++) I915_WRITE(G4X_HDMIW_HDMIEDID, *((uint32_t *)eld + i)); i = I915_READ(G4X_AUD_CNTL_ST); i |= eldv; I915_WRITE(G4X_AUD_CNTL_ST, i); } static void haswell_write_eld(struct drm_connector *connector, struct drm_crtc *crtc) { struct drm_i915_private *dev_priv = connector->dev->dev_private; uint8_t *eld = connector->eld; struct drm_device *dev = crtc->dev; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); uint32_t eldv; uint32_t i; int len; int pipe = to_intel_crtc(crtc)->pipe; int tmp; int hdmiw_hdmiedid = HSW_AUD_EDID_DATA(pipe); int aud_cntl_st = HSW_AUD_DIP_ELD_CTRL(pipe); int aud_config = HSW_AUD_CFG(pipe); int aud_cntrl_st2 = HSW_AUD_PIN_ELD_CP_VLD; DRM_DEBUG_DRIVER("HDMI: Haswell Audio initialize....\n"); /* Audio output enable */ DRM_DEBUG_DRIVER("HDMI audio: enable codec\n"); tmp = I915_READ(aud_cntrl_st2); tmp |= (AUDIO_OUTPUT_ENABLE_A << (pipe * 4)); I915_WRITE(aud_cntrl_st2, tmp); /* Wait for 1 vertical blank */ intel_wait_for_vblank(dev, pipe); /* Set ELD valid state */ tmp = I915_READ(aud_cntrl_st2); DRM_DEBUG_DRIVER("HDMI audio: pin eld vld status=0x%8x\n", tmp); tmp |= (AUDIO_ELD_VALID_A << (pipe * 4)); I915_WRITE(aud_cntrl_st2, tmp); tmp = I915_READ(aud_cntrl_st2); DRM_DEBUG_DRIVER("HDMI audio: eld vld status=0x%8x\n", tmp); /* Enable HDMI mode */ tmp = I915_READ(aud_config); DRM_DEBUG_DRIVER("HDMI audio: audio conf: 0x%8x\n", tmp); /* clear N_programing_enable and N_value_index */ tmp &= ~(AUD_CONFIG_N_VALUE_INDEX | AUD_CONFIG_N_PROG_ENABLE); I915_WRITE(aud_config, tmp); DRM_DEBUG_DRIVER("ELD on pipe %c\n", pipe_name(pipe)); eldv = AUDIO_ELD_VALID_A << (pipe * 4); intel_crtc->eld_vld = true; if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) { DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n"); eld[5] |= (1 << 2); /* Conn_Type, 0x1 = DisplayPort */ I915_WRITE(aud_config, AUD_CONFIG_N_VALUE_INDEX); /* 0x1 = DP */ } else I915_WRITE(aud_config, 0); if (intel_eld_uptodate(connector, aud_cntrl_st2, eldv, aud_cntl_st, IBX_ELD_ADDRESS, hdmiw_hdmiedid)) return; i = I915_READ(aud_cntrl_st2); i &= ~eldv; I915_WRITE(aud_cntrl_st2, i); if (!eld[0]) return; i = I915_READ(aud_cntl_st); i &= ~IBX_ELD_ADDRESS; I915_WRITE(aud_cntl_st, i); i = (i >> 29) & DIP_PORT_SEL_MASK; /* DIP_Port_Select, 0x1 = PortB */ DRM_DEBUG_DRIVER("port num:%d\n", i); len = min_t(uint8_t, eld[2], 21); /* 84 bytes of hw ELD buffer */ DRM_DEBUG_DRIVER("ELD size %d\n", len); for (i = 0; i < len; i++) I915_WRITE(hdmiw_hdmiedid, *((uint32_t *)eld + i)); i = I915_READ(aud_cntrl_st2); i |= eldv; I915_WRITE(aud_cntrl_st2, i); } static void ironlake_write_eld(struct drm_connector *connector, struct drm_crtc *crtc) { struct drm_i915_private *dev_priv = connector->dev->dev_private; uint8_t *eld = connector->eld; uint32_t eldv; uint32_t i; int len; int hdmiw_hdmiedid; int aud_config; int aud_cntl_st; int aud_cntrl_st2; int pipe = to_intel_crtc(crtc)->pipe; if (HAS_PCH_IBX(connector->dev)) { hdmiw_hdmiedid = IBX_HDMIW_HDMIEDID(pipe); aud_config = IBX_AUD_CFG(pipe); aud_cntl_st = IBX_AUD_CNTL_ST(pipe); aud_cntrl_st2 = IBX_AUD_CNTL_ST2; } else { hdmiw_hdmiedid = CPT_HDMIW_HDMIEDID(pipe); aud_config = CPT_AUD_CFG(pipe); aud_cntl_st = CPT_AUD_CNTL_ST(pipe); aud_cntrl_st2 = CPT_AUD_CNTRL_ST2; } DRM_DEBUG_DRIVER("ELD on pipe %c\n", pipe_name(pipe)); i = I915_READ(aud_cntl_st); i = (i >> 29) & DIP_PORT_SEL_MASK; /* DIP_Port_Select, 0x1 = PortB */ if (!i) { DRM_DEBUG_DRIVER("Audio directed to unknown port\n"); /* operate blindly on all ports */ eldv = IBX_ELD_VALIDB; eldv |= IBX_ELD_VALIDB << 4; eldv |= IBX_ELD_VALIDB << 8; } else { DRM_DEBUG_DRIVER("ELD on port %c\n", port_name(i)); eldv = IBX_ELD_VALIDB << ((i - 1) * 4); } if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) { DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n"); eld[5] |= (1 << 2); /* Conn_Type, 0x1 = DisplayPort */ I915_WRITE(aud_config, AUD_CONFIG_N_VALUE_INDEX); /* 0x1 = DP */ } else I915_WRITE(aud_config, 0); if (intel_eld_uptodate(connector, aud_cntrl_st2, eldv, aud_cntl_st, IBX_ELD_ADDRESS, hdmiw_hdmiedid)) return; i = I915_READ(aud_cntrl_st2); i &= ~eldv; I915_WRITE(aud_cntrl_st2, i); if (!eld[0]) return; i = I915_READ(aud_cntl_st); i &= ~IBX_ELD_ADDRESS; I915_WRITE(aud_cntl_st, i); len = min_t(uint8_t, eld[2], 21); /* 84 bytes of hw ELD buffer */ DRM_DEBUG_DRIVER("ELD size %d\n", len); for (i = 0; i < len; i++) I915_WRITE(hdmiw_hdmiedid, *((uint32_t *)eld + i)); i = I915_READ(aud_cntrl_st2); i |= eldv; I915_WRITE(aud_cntrl_st2, i); } void intel_write_eld(struct drm_encoder *encoder, struct drm_display_mode *mode) { struct drm_crtc *crtc = encoder->crtc; struct drm_connector *connector; struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; connector = drm_select_eld(encoder, mode); if (!connector) return; DRM_DEBUG_DRIVER("ELD on [CONNECTOR:%d:%s], [ENCODER:%d:%s]\n", connector->base.id, drm_get_connector_name(connector), connector->encoder->base.id, drm_get_encoder_name(connector->encoder)); connector->eld[6] = drm_av_sync_delay(connector, mode) / 2; if (dev_priv->display.write_eld) dev_priv->display.write_eld(connector, crtc); } /** Loads the palette/gamma unit for the CRTC with the prepared values */ void intel_crtc_load_lut(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); enum pipe pipe = intel_crtc->pipe; int palreg = PALETTE(pipe); int i; bool reenable_ips = false; /* The clocks have to be on to load the palette. */ if (!crtc->enabled || !intel_crtc->active) return; if (!HAS_PCH_SPLIT(dev_priv->dev)) { if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DSI)) assert_dsi_pll_enabled(dev_priv); else assert_pll_enabled(dev_priv, pipe); } /* use legacy palette for Ironlake */ if (HAS_PCH_SPLIT(dev)) palreg = LGC_PALETTE(pipe); /* Workaround : Do not read or write the pipe palette/gamma data while * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled. */ if (intel_crtc->config.ips_enabled && ((I915_READ(GAMMA_MODE(pipe)) & GAMMA_MODE_MODE_MASK) == GAMMA_MODE_MODE_SPLIT)) { hsw_disable_ips(intel_crtc); reenable_ips = true; } for (i = 0; i < 256; i++) { I915_WRITE(palreg + 4 * i, (intel_crtc->lut_r[i] << 16) | (intel_crtc->lut_g[i] << 8) | intel_crtc->lut_b[i]); } if (reenable_ips) hsw_enable_ips(intel_crtc); } static void i845_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); bool visible = base != 0; u32 cntl; if (intel_crtc->cursor_visible == visible) return; cntl = I915_READ(_CURACNTR); if (visible) { /* On these chipsets we can only modify the base whilst * the cursor is disabled. */ I915_WRITE(_CURABASE, base); cntl &= ~(CURSOR_FORMAT_MASK); /* XXX width must be 64, stride 256 => 0x00 << 28 */ cntl |= CURSOR_ENABLE | CURSOR_GAMMA_ENABLE | CURSOR_FORMAT_ARGB; } else cntl &= ~(CURSOR_ENABLE | CURSOR_GAMMA_ENABLE); I915_WRITE(_CURACNTR, cntl); intel_crtc->cursor_visible = visible; } static void i9xx_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) { int x = intel_crtc->cursor_width; uint32_t cntl = I915_READ(CURCNTR(pipe)); if (base) { cntl &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT); if (x == 128) cntl |= CURSOR_MODE_128_ARGB_AX | CURSOR_GAMMA_ENABLE; else if (x == 256) cntl |= CURSOR_MODE_256_ARGB_AX | MCURSOR_GAMMA_ENABLE; else cntl |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE; cntl |= pipe << 28; /* Connect to correct pipe */ } else { cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE); cntl |= CURSOR_MODE_DISABLE; } I915_WRITE(CURCNTR(pipe), cntl); intel_crtc->cursor_visible = visible; } /* and commit changes on next vblank */ 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; } if (IS_HASWELL(dev)) cntl |= CURSOR_PIPE_CSC_ENABLE; 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) { 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; int x = intel_crtc->cursor_x; int y = intel_crtc->cursor_y; u32 base, pos; bool visible; pos = 0; if (on && crtc->enabled && crtc->fb) { base = intel_crtc->cursor_addr; if (x > (int) crtc->fb->width) base = 0; if (y > (int) crtc->fb->height) base = 0; } else base = 0; if (x < 0) { if (x + intel_crtc->cursor_width < 0) base = 0; pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT; x = -x; } pos |= x << CURSOR_X_SHIFT; if (y < 0) { if (y + intel_crtc->cursor_height < 0) base = 0; pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT; y = -y; } pos |= y << CURSOR_Y_SHIFT; visible = base != 0; if (!visible && !intel_crtc->cursor_visible) return; if (IS_IVYBRIDGE(dev) || IS_HASWELL(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); } } static int intel_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file, uint32_t handle, uint32_t width, uint32_t height) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct drm_i915_gem_object *obj; uint32_t addr; int ret; /* if we want to turn off the cursor ignore width and height */ if (!handle) { DRM_DEBUG_KMS("cursor off\n"); addr = 0; obj = NULL; mutex_lock(&dev->struct_mutex); goto finish; } /* Check for which cursor types we support */ if (width > 256 && height > 256) { DRM_ERROR("only supports 64, 128, 256 cursor mode\n"); return -EINVAL; } obj = to_intel_bo(drm_gem_object_lookup(dev, file, handle)); if (&obj->base == NULL) return -ENOENT; if (obj->base.size < width * height * 4) { DRM_ERROR("buffer too small %zu needs to be bigger than %u\n", obj->base.size, width * height * 4); ret = -ENOMEM; goto fail; } /* we only need to pin inside GTT if cursor is non-phy */ mutex_lock(&dev->struct_mutex); if (!dev_priv->info->cursor_needs_physical) { unsigned alignment; if (obj->tiling_mode) { DRM_ERROR("cursor cannot be tiled\n"); ret = -EINVAL; goto fail_locked; } /* Note that the w/a also requires 2 PTE of padding following * the bo. We currently fill all unused PTE with the shadow * page and so we should always have valid PTE following the * cursor preventing the VT-d warning. */ alignment = 0; if (need_vtd_wa(dev)) alignment = 64*1024; ret = i915_gem_object_pin_to_display_plane(obj, alignment, NULL); if (ret) { DRM_ERROR("failed to move cursor bo into the GTT\n"); goto fail_locked; } ret = i915_gem_object_put_fence(obj); if (ret) { DRM_ERROR("failed to release fence for cursor"); goto fail_unpin; } addr = i915_gem_obj_ggtt_offset(obj); } else { int align = IS_I830(dev) ? 16 * 1024 : 256; ret = i915_gem_attach_phys_object(dev, obj, (intel_crtc->pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1, align); if (ret) { DRM_ERROR("failed to attach phys object\n"); goto fail_locked; } addr = obj->phys_obj->handle->busaddr; } if (IS_GEN2(dev)) I915_WRITE(CURSIZE, (height << 12) | width); finish: if (intel_crtc->cursor_bo) { if (dev_priv->info->cursor_needs_physical) { if (intel_crtc->cursor_bo != obj) i915_gem_detach_phys_object(dev, intel_crtc->cursor_bo); } else i915_gem_object_unpin_from_display_plane(intel_crtc->cursor_bo); drm_gem_object_unreference(&intel_crtc->cursor_bo->base); } mutex_unlock(&dev->struct_mutex); intel_crtc->cursor_addr = addr; intel_crtc->cursor_bo = obj; intel_crtc->cursor_width = width; intel_crtc->cursor_height = height; intel_crtc_update_cursor(crtc, intel_crtc->cursor_bo != NULL); return 0; fail_unpin: i915_gem_object_unpin_from_display_plane(obj); fail_locked: mutex_unlock(&dev->struct_mutex); fail: drm_gem_object_unreference_unlocked(&obj->base); return ret; } static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); intel_crtc->cursor_x = x; intel_crtc->cursor_y = y; intel_crtc_update_cursor(crtc, intel_crtc->cursor_bo != NULL); return 0; } /** Sets the color ramps on behalf of RandR */ void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, u16 blue, int regno) { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); intel_crtc->lut_r[regno] = red >> 8; intel_crtc->lut_g[regno] = green >> 8; intel_crtc->lut_b[regno] = blue >> 8; } void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, u16 *blue, int regno) { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); *red = intel_crtc->lut_r[regno] << 8; *green = intel_crtc->lut_g[regno] << 8; *blue = intel_crtc->lut_b[regno] << 8; } static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, u16 *blue, uint32_t start, uint32_t size) { int end = (start + size > 256) ? 256 : start + size, i; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); for (i = start; i < end; i++) { intel_crtc->lut_r[i] = red[i] >> 8; intel_crtc->lut_g[i] = green[i] >> 8; intel_crtc->lut_b[i] = blue[i] >> 8; } intel_crtc_load_lut(crtc); } /* VESA 640x480x72Hz mode to set on the pipe */ static struct drm_display_mode load_detect_mode = { DRM_MODE("640x480", DRM_MODE_TYPE_DEFAULT, 31500, 640, 664, 704, 832, 0, 480, 489, 491, 520, 0, DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, 0), }; static struct drm_framebuffer * intel_framebuffer_create(struct drm_device *dev, struct drm_mode_fb_cmd2 *mode_cmd, struct drm_i915_gem_object *obj) { struct intel_framebuffer *intel_fb; int ret; intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL); if (!intel_fb) { drm_gem_object_unreference_unlocked(&obj->base); return ERR_PTR(-ENOMEM); } ret = intel_framebuffer_init(dev, intel_fb, mode_cmd, obj); if (ret) { drm_gem_object_unreference_unlocked(&obj->base); kfree(intel_fb); return ERR_PTR(ret); } return &intel_fb->base; } static u32 intel_framebuffer_pitch_for_width(int width, int bpp) { u32 pitch = DIV_ROUND_UP(width * bpp, 8); return ALIGN(pitch, 64); } static u32 intel_framebuffer_size_for_mode(struct drm_display_mode *mode, int bpp) { u32 pitch = intel_framebuffer_pitch_for_width(mode->hdisplay, bpp); return ALIGN(pitch * mode->vdisplay, PAGE_SIZE); } static struct drm_framebuffer * intel_framebuffer_create_for_mode(struct drm_device *dev, struct drm_display_mode *mode, int depth, int bpp) { struct drm_i915_gem_object *obj; struct drm_mode_fb_cmd2 mode_cmd = { 0 }; obj = i915_gem_alloc_object(dev, intel_framebuffer_size_for_mode(mode, bpp)); if (obj == NULL) return ERR_PTR(-ENOMEM); mode_cmd.width = mode->hdisplay; mode_cmd.height = mode->vdisplay; mode_cmd.pitches[0] = intel_framebuffer_pitch_for_width(mode_cmd.width, bpp); mode_cmd.pixel_format = drm_mode_legacy_fb_format(bpp, depth); return intel_framebuffer_create(dev, &mode_cmd, obj); } static struct drm_framebuffer * mode_fits_in_fbdev(struct drm_device *dev, struct drm_display_mode *mode) { struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_gem_object *obj; struct drm_framebuffer *fb; if (dev_priv->fbdev == NULL) return NULL; obj = dev_priv->fbdev->ifb.obj; if (obj == NULL) return NULL; fb = &dev_priv->fbdev->ifb.base; if (fb->pitches[0] < intel_framebuffer_pitch_for_width(mode->hdisplay, fb->bits_per_pixel)) return NULL; if (obj->base.size < mode->vdisplay * fb->pitches[0]) return NULL; return fb; } bool intel_get_load_detect_pipe(struct drm_connector *connector, struct drm_display_mode *mode, struct intel_load_detect_pipe *old) { struct intel_crtc *intel_crtc; struct intel_encoder *intel_encoder = intel_attached_encoder(connector); struct drm_crtc *possible_crtc; struct drm_encoder *encoder = &intel_encoder->base; struct drm_crtc *crtc = NULL; struct drm_device *dev = encoder->dev; struct drm_framebuffer *fb; int i = -1; DRM_DEBUG_KMS("[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n", connector->base.id, drm_get_connector_name(connector), encoder->base.id, drm_get_encoder_name(encoder)); /* * Algorithm gets a little messy: * * - if the connector already has an assigned crtc, use it (but make * sure it's on first) * * - try to find the first unused crtc that can drive this connector, * and use that if we find one */ /* See if we already have a CRTC for this connector */ if (encoder->crtc) { crtc = encoder->crtc; mutex_lock(&crtc->mutex); old->dpms_mode = connector->dpms; old->load_detect_temp = false; /* Make sure the crtc and connector are running */ if (connector->dpms != DRM_MODE_DPMS_ON) connector->funcs->dpms(connector, DRM_MODE_DPMS_ON); return true; } /* Find an unused one (if possible) */ list_for_each_entry(possible_crtc, &dev->mode_config.crtc_list, head) { i++; if (!(encoder->possible_crtcs & (1 << i))) continue; if (!possible_crtc->enabled) { crtc = possible_crtc; break; } } /* * If we didn't find an unused CRTC, don't use any. */ if (!crtc) { DRM_DEBUG_KMS("no pipe available for load-detect\n"); return false; } mutex_lock(&crtc->mutex); intel_encoder->new_crtc = to_intel_crtc(crtc); to_intel_connector(connector)->new_encoder = intel_encoder; intel_crtc = to_intel_crtc(crtc); old->dpms_mode = connector->dpms; old->load_detect_temp = true; old->release_fb = NULL; if (!mode) mode = &load_detect_mode; /* We need a framebuffer large enough to accommodate all accesses * that the plane may generate whilst we perform load detection. * We can not rely on the fbcon either being present (we get called * during its initialisation to detect all boot displays, or it may * not even exist) or that it is large enough to satisfy the * requested mode. */ fb = mode_fits_in_fbdev(dev, mode); if (fb == NULL) { DRM_DEBUG_KMS("creating tmp fb for load-detection\n"); fb = intel_framebuffer_create_for_mode(dev, mode, 24, 32); old->release_fb = fb; } else DRM_DEBUG_KMS("reusing fbdev for load-detection framebuffer\n"); if (IS_ERR(fb)) { DRM_DEBUG_KMS("failed to allocate framebuffer for load-detection\n"); mutex_unlock(&crtc->mutex); return false; } if (intel_set_mode(crtc, mode, 0, 0, fb)) { DRM_DEBUG_KMS("failed to set mode on load-detect pipe\n"); if (old->release_fb) old->release_fb->funcs->destroy(old->release_fb); mutex_unlock(&crtc->mutex); return false; } /* let the connector get through one full cycle before testing */ intel_wait_for_vblank(dev, intel_crtc->pipe); return true; } void intel_release_load_detect_pipe(struct drm_connector *connector, struct intel_load_detect_pipe *old) { struct intel_encoder *intel_encoder = intel_attached_encoder(connector); struct drm_encoder *encoder = &intel_encoder->base; struct drm_crtc *crtc = encoder->crtc; DRM_DEBUG_KMS("[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n", connector->base.id, drm_get_connector_name(connector), encoder->base.id, drm_get_encoder_name(encoder)); if (old->load_detect_temp) { to_intel_connector(connector)->new_encoder = NULL; intel_encoder->new_crtc = NULL; intel_set_mode(crtc, NULL, 0, 0, NULL); if (old->release_fb) { drm_framebuffer_unregister_private(old->release_fb); drm_framebuffer_unreference(old->release_fb); } mutex_unlock(&crtc->mutex); return; } /* Switch crtc and encoder back off if necessary */ if (old->dpms_mode != DRM_MODE_DPMS_ON) connector->funcs->dpms(connector, old->dpms_mode); mutex_unlock(&crtc->mutex); } /* Returns the clock of the currently programmed mode of the given pipe. */ static void i9xx_crtc_clock_get(struct intel_crtc *crtc, struct intel_crtc_config *pipe_config) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; int pipe = pipe_config->cpu_transcoder; u32 dpll = I915_READ(DPLL(pipe)); u32 fp; intel_clock_t clock; if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0) fp = I915_READ(FP0(pipe)); else fp = I915_READ(FP1(pipe)); clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT; if (IS_PINEVIEW(dev)) { clock.n = ffs((fp & FP_N_PINEVIEW_DIV_MASK) >> FP_N_DIV_SHIFT) - 1; clock.m2 = (fp & FP_M2_PINEVIEW_DIV_MASK) >> FP_M2_DIV_SHIFT; } else { clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT; clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT; } if (!IS_GEN2(dev)) { if (IS_PINEVIEW(dev)) clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW) >> DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW); else clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK) >> DPLL_FPA01_P1_POST_DIV_SHIFT); switch (dpll & DPLL_MODE_MASK) { case DPLLB_MODE_DAC_SERIAL: clock.p2 = dpll & DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 ? 5 : 10; break; case DPLLB_MODE_LVDS: clock.p2 = dpll & DPLLB_LVDS_P2_CLOCK_DIV_7 ? 7 : 14; break; default: DRM_DEBUG_KMS("Unknown DPLL mode %08x in programmed " "mode\n", (int)(dpll & DPLL_MODE_MASK)); return; } if (IS_PINEVIEW(dev)) pineview_clock(96000, &clock); else i9xx_clock(96000, &clock); } else { bool is_lvds = (pipe == 1) && (I915_READ(LVDS) & LVDS_PORT_EN); if (is_lvds) { clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >> DPLL_FPA01_P1_POST_DIV_SHIFT); clock.p2 = 14; if ((dpll & PLL_REF_INPUT_MASK) == PLLB_REF_INPUT_SPREADSPECTRUMIN) { /* XXX: might not be 66MHz */ i9xx_clock(66000, &clock); } else i9xx_clock(48000, &clock); } else { if (dpll & PLL_P1_DIVIDE_BY_TWO) clock.p1 = 2; else { clock.p1 = ((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830) >> DPLL_FPA01_P1_POST_DIV_SHIFT) + 2; } if (dpll & PLL_P2_DIVIDE_BY_4) clock.p2 = 4; else clock.p2 = 2; i9xx_clock(48000, &clock); } } pipe_config->adjusted_mode.clock = clock.dot * pipe_config->pixel_multiplier; } static void ironlake_crtc_clock_get(struct intel_crtc *crtc, struct intel_crtc_config *pipe_config) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; enum transcoder cpu_transcoder = pipe_config->cpu_transcoder; int link_freq, repeat; u64 clock; u32 link_m, link_n; repeat = pipe_config->pixel_multiplier; /* * The calculation for the data clock is: * pixel_clock = ((m/n)*(link_clock * nr_lanes * repeat))/bpp * But we want to avoid losing precison if possible, so: * pixel_clock = ((m * link_clock * nr_lanes * repeat)/(n*bpp)) * * and the link clock is simpler: * link_clock = (m * link_clock * repeat) / n */ /* * We need to get the FDI or DP link clock here to derive * the M/N dividers. * * For FDI, we read it from the BIOS or use a fixed 2.7GHz. * For DP, it's either 1.62GHz or 2.7GHz. * We do our calculations in 10*MHz since we don't need much precison. */ if (pipe_config->has_pch_encoder) link_freq = intel_fdi_link_freq(dev) * 10000; else link_freq = pipe_config->port_clock; link_m = I915_READ(PIPE_LINK_M1(cpu_transcoder)); link_n = I915_READ(PIPE_LINK_N1(cpu_transcoder)); if (!link_m || !link_n) return; clock = ((u64)link_m * (u64)link_freq * (u64)repeat); do_div(clock, link_n); pipe_config->adjusted_mode.clock = clock; } /** Returns the currently programmed mode of the given pipe. */ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev, struct drm_crtc *crtc) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder; struct drm_display_mode *mode; struct intel_crtc_config pipe_config; int htot = I915_READ(HTOTAL(cpu_transcoder)); int hsync = I915_READ(HSYNC(cpu_transcoder)); int vtot = I915_READ(VTOTAL(cpu_transcoder)); int vsync = I915_READ(VSYNC(cpu_transcoder)); mode = kzalloc(sizeof(*mode), GFP_KERNEL); if (!mode) return NULL; /* * Construct a pipe_config sufficient for getting the clock info * back out of crtc_clock_get. * * Note, if LVDS ever uses a non-1 pixel multiplier, we'll need * to use a real value here instead. */ pipe_config.cpu_transcoder = (enum transcoder) intel_crtc->pipe; pipe_config.pixel_multiplier = 1; i9xx_crtc_clock_get(intel_crtc, &pipe_config); mode->clock = pipe_config.adjusted_mode.clock; mode->hdisplay = (htot & 0xffff) + 1; mode->htotal = ((htot & 0xffff0000) >> 16) + 1; mode->hsync_start = (hsync & 0xffff) + 1; mode->hsync_end = ((hsync & 0xffff0000) >> 16) + 1; mode->vdisplay = (vtot & 0xffff) + 1; mode->vtotal = ((vtot & 0xffff0000) >> 16) + 1; mode->vsync_start = (vsync & 0xffff) + 1; mode->vsync_end = ((vsync & 0xffff0000) >> 16) + 1; drm_mode_set_name(mode); return mode; } static void intel_increase_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; if (HAS_PCH_SPLIT(dev)) return; if (!dev_priv->lvds_downclock_avail) return; dpll = I915_READ(dpll_reg); if (!HAS_PIPE_CXSR(dev) && (dpll & DISPLAY_RATE_SELECT_FPA1)) { DRM_DEBUG_DRIVER("upclocking LVDS\n"); assert_panel_unlocked(dev_priv, pipe); dpll &= ~DISPLAY_RATE_SELECT_FPA1; I915_WRITE(dpll_reg, dpll); intel_wait_for_vblank(dev, pipe); dpll = I915_READ(dpll_reg); if (dpll & DISPLAY_RATE_SELECT_FPA1) DRM_DEBUG_DRIVER("failed to upclock LVDS!\n"); } } 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); if (HAS_PCH_SPLIT(dev)) return; if (!dev_priv->lvds_downclock_avail) return; /* * Since this is called by a timer, we should never get here in * 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); dpll = I915_READ(dpll_reg); if (!(dpll & DISPLAY_RATE_SELECT_FPA1)) DRM_DEBUG_DRIVER("failed to downclock LVDS!\n"); } } void intel_mark_busy(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; hsw_package_c8_gpu_busy(dev_priv); i915_update_gfx_val(dev_priv); } void intel_mark_idle(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct drm_crtc *crtc; hsw_package_c8_gpu_idle(dev_priv); if (!i915_powersave) return; list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { if (!crtc->fb) continue; intel_decrease_pllclock(crtc); } } void intel_mark_fb_busy(struct drm_i915_gem_object *obj, struct intel_ring_buffer *ring) { struct drm_device *dev = obj->base.dev; struct drm_crtc *crtc; if (!i915_powersave) return; list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { if (!crtc->fb) continue; if (to_intel_framebuffer(crtc->fb)->obj != obj) continue; intel_increase_pllclock(crtc); if (ring && intel_fbc_enabled(dev)) ring->fbc_dirty = true; } } static void intel_crtc_destroy(struct drm_crtc *crtc) { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct drm_device *dev = crtc->dev; struct intel_unpin_work *work, *sprite_work; unsigned long flags; spin_lock_irqsave(&dev->event_lock, flags); work = intel_crtc->unpin_work; sprite_work = intel_crtc->sprite_unpin_work; intel_crtc->unpin_work = NULL; intel_crtc->sprite_unpin_work = NULL; spin_unlock_irqrestore(&dev->event_lock, flags); if (work) { cancel_work_sync(&work->work); kfree(work); } if (sprite_work) { cancel_work_sync(&sprite_work->work); kfree(sprite_work); } intel_crtc_cursor_set(crtc, NULL, 0, 0, 0); drm_crtc_cleanup(crtc); kfree(intel_crtc); } static inline void intel_use_scratch_page_for_fb(struct drm_i915_gem_object *obj) { struct drm_i915_private *dev_priv = obj->base.dev->dev_private; int ret; /* A fb being flipped without having any allocated backing physical * space is most probably going to be used as a blanking buffer (black * colored). So instead of allocating the real backing physical space * for this buffer, we can try to currently back this object by a * scratch page, which is already allocated. * So we check if no shmem data pages have been allocated to the fb * we can back it by a scratch page and thus save time by avoiding * allocation of backing physical space & subsequent CPU cache flush. */ if (obj->base.filp) { struct inode *inode = file_inode(obj->base.filp); struct shmem_inode_info *info = SHMEM_I(inode); if (!inode) DRM_ERROR("No inode\n"); spin_lock(&info->lock); ret = info->alloced; spin_unlock(&info->lock); if ((ret == 0) && (obj->pages == NULL)) { /* * Set the 'pages' field with the object pointer * itself, this will avoid the need of a new field in * obj structure to identify the object backed up by a * scratch page and will also avoid the call to * 'get_pages', thus also saving on the time required * for allocation of 'scatterlist' structure. */ obj->pages = (struct sg_table *)(obj); /* * To avoid calls to gtt prepare & finish, as those * will dereference the 'pages' field */ obj->has_dma_mapping = 1; list_add_tail(&obj->global_list, &dev_priv->mm.unbound_list); trace_printk("Using Scratch page for obj %p\n", obj); } } } static void intel_drop_scratch_page_for_fb(struct drm_i915_gem_object *obj) { int ret; /* * Unmap the object backed up by scratch page, as it is no * longer being scanned out and thus it can be now allowed * to be used as a normal object. * Assumption: The User space will ensure that only when the * object is no longer being scanned out, it will be reused * for rendering. This is a valid assumption as there is no * such handling in driver for other regular fb objects also. */ if ((unsigned long)obj->pages == (unsigned long)obj) { ret = i915_gem_object_ggtt_unbind(obj); /* EBUSY is ok: this means that pin count is still not zero */ if (!ret) { ret = i915_gem_object_put_pages(obj); if (!ret) obj->has_dma_mapping = 0; } else if (ret != -EBUSY) DRM_ERROR("unbind error %d\n", ret); } } void intel_unpin_work_fn(struct work_struct *__work) { struct intel_unpin_work *work = container_of(__work, struct intel_unpin_work, work); struct drm_device *dev = work->crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; mutex_lock(&dev->struct_mutex); intel_unpin_fb_obj(work->old_fb_obj); drm_gem_object_unreference(&work->pending_flip_obj->base); drm_gem_object_unreference(&work->old_fb_obj->base); if (dev_priv->fwlogo_size) { clear_reserved_fwlogo_mem(dev_priv); dev_priv->fwlogo_size = 0; } intel_update_fbc(dev); /* disable current DRRS work scheduled and restart * to push work by another x seconds */ intel_update_drrs(dev); mutex_unlock(&dev->struct_mutex); BUG_ON(atomic_read(&to_intel_crtc(work->crtc)->unpin_work_count) == 0); atomic_dec(&to_intel_crtc(work->crtc)->unpin_work_count); kfree(work); } static void do_intel_finish_page_flip(struct drm_device *dev, struct drm_crtc *crtc) { drm_i915_private_t *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_unpin_work *work; unsigned long flags; /* Ignore early vblank irqs */ if (intel_crtc == NULL) return; spin_lock_irqsave(&dev->event_lock, flags); work = intel_crtc->unpin_work; /* Ensure we don't miss a work->pending update ... */ smp_rmb(); if (work == NULL || atomic_read(&work->pending) < INTEL_FLIP_COMPLETE) { spin_unlock_irqrestore(&dev->event_lock, flags); DRM_DEBUG("invalid or inactive unpin_work!\n"); return; } /* Program the precalculated DDL value */ if (intel_crtc->reg_ddl.plane_ddl) { I915_WRITE_BITS(VLV_DDL(intel_crtc->pipe), intel_crtc->reg_ddl.plane_ddl, intel_crtc->reg_ddl.plane_ddl_mask); intel_crtc->reg_ddl.plane_ddl = 0; } /* and that the unpin work is consistent wrt ->pending. */ smp_rmb(); intel_crtc->unpin_work = NULL; if (intel_crtc->dummy_flip) intel_crtc->dummy_flip = false; else { if (work->event) drm_send_vblank_event(dev, intel_crtc->pipe, work->event); } drm_vblank_put(dev, intel_crtc->pipe); spin_unlock_irqrestore(&dev->event_lock, flags); wake_up_all(&dev_priv->pending_flip_queue); queue_work(dev_priv->wq, &work->work); trace_i915_flip_complete(intel_crtc->plane, work->pending_flip_obj); } void intel_finish_page_flip(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = dev->dev_private; struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; do_intel_finish_page_flip(dev, crtc); } void intel_finish_page_flip_plane(struct drm_device *dev, int plane) { drm_i915_private_t *dev_priv = dev->dev_private; struct drm_crtc *crtc = dev_priv->plane_to_crtc_mapping[plane]; do_intel_finish_page_flip(dev, crtc); } void intel_prepare_page_flip(struct drm_device *dev, int plane) { drm_i915_private_t *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(dev_priv->plane_to_crtc_mapping[plane]); unsigned long flags; /* NB: An MMIO update of the plane base pointer will also * generate a page-flip completion irq, i.e. every modeset * is also accompanied by a spurious intel_prepare_page_flip(). */ spin_lock_irqsave(&dev->event_lock, flags); if (intel_crtc->unpin_work) atomic_inc_not_zero(&intel_crtc->unpin_work->pending); spin_unlock_irqrestore(&dev->event_lock, flags); } inline static void intel_mark_page_flip_active(struct intel_crtc *intel_crtc) { /* Ensure that the work item is consistent when activating it ... */ smp_wmb(); atomic_set(&intel_crtc->unpin_work->pending, INTEL_FLIP_PENDING); /* and that it is marked active as soon as the irq could fire. */ smp_wmb(); } 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); u32 flip_mask; struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; int ret; ret = intel_pin_and_fence_fb_obj(dev, obj, ring); if (ret) goto err; ret = intel_ring_begin(ring, 6); if (ret) goto err_unpin; /* 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; intel_ring_emit(ring, MI_WAIT_FOR_EVENT | flip_mask); intel_ring_emit(ring, MI_NOOP); intel_ring_emit(ring, MI_DISPLAY_FLIP | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); intel_ring_emit(ring, fb->pitches[0]); intel_ring_emit(ring, i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset); intel_ring_emit(ring, 0); /* aux display base address, unused */ intel_mark_page_flip_active(intel_crtc); intel_ring_advance(ring); return 0; err_unpin: intel_unpin_fb_obj(obj); err: 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); u32 flip_mask; struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; int ret; ret = intel_pin_and_fence_fb_obj(dev, obj, ring); if (ret) goto err; ret = intel_ring_begin(ring, 6); if (ret) goto err_unpin; if (intel_crtc->plane) flip_mask = MI_WAIT_FOR_PLANE_B_FLIP; else flip_mask = MI_WAIT_FOR_PLANE_A_FLIP; intel_ring_emit(ring, MI_WAIT_FOR_EVENT | flip_mask); intel_ring_emit(ring, MI_NOOP); intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); intel_ring_emit(ring, fb->pitches[0]); intel_ring_emit(ring, i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset); intel_ring_emit(ring, MI_NOOP); intel_mark_page_flip_active(intel_crtc); intel_ring_advance(ring); return 0; err_unpin: intel_unpin_fb_obj(obj); err: 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; struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; int ret; ret = intel_pin_and_fence_fb_obj(dev, obj, ring); if (ret) goto err; ret = intel_ring_begin(ring, 4); if (ret) goto err_unpin; /* 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. */ intel_ring_emit(ring, MI_DISPLAY_FLIP | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); intel_ring_emit(ring, fb->pitches[0]); intel_ring_emit(ring, (i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_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; intel_ring_emit(ring, pf | pipesrc); intel_mark_page_flip_active(intel_crtc); intel_ring_advance(ring); return 0; err_unpin: intel_unpin_fb_obj(obj); err: 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); struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; uint32_t pf, pipesrc; int ret; ret = intel_pin_and_fence_fb_obj(dev, obj, ring); if (ret) goto err; ret = intel_ring_begin(ring, 4); if (ret) goto err_unpin; intel_ring_emit(ring, MI_DISPLAY_FLIP | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); intel_ring_emit(ring, fb->pitches[0] | obj->tiling_mode); intel_ring_emit(ring, i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset); /* 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_mark_page_flip_active(intel_crtc); intel_ring_advance(ring); return 0; err_unpin: intel_unpin_fb_obj(obj); err: return ret; } static void intel_gen7_queue_mmio_flip_work(struct work_struct *__work) { struct i915_flip_work *flipwork = container_of(__work, struct i915_flip_work, work); int ret = 0; unsigned int reset_counter; struct drm_crtc *crtc = flipwork->flipdata.crtc; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_ring_buffer *ring = &dev_priv->ring[flipwork->flipdata.ring_id]; if (dev_priv->ums.mm_suspended || (ring->obj == NULL)) { DRM_ERROR("flip attempted while the ring is not ready\n"); return; } /* Wait is needed only for nonZero Seqnos, as zero Seqno indicates that either the rendering on the object (through GPU) is already completed or not intiated at all */ if (flipwork->flipdata.seqno > 0) { reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter); /* sleep wait until the seqno has passed */ ret = __wait_seqno(ring, flipwork->flipdata.seqno, reset_counter, true, NULL); if (ret) DRM_ERROR("wait_seqno failed on seqno 0x%x(%d)\n", flipwork->flipdata.seqno, flipwork->flipdata.ring_id); } intel_mark_page_flip_active(intel_crtc); i9xx_update_plane(crtc, crtc->fb, 0, 0); } static void intel_gen7_queue_mmio_flip_work_sync(struct i915_flip_work *flipwork) { int ret = 0; unsigned int reset_counter; struct drm_crtc *crtc = flipwork->flipdata.crtc; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_ring_buffer *ring = &dev_priv->ring[flipwork->flipdata.ring_id]; if (dev_priv->ums.mm_suspended || (ring->obj == NULL)) { DRM_ERROR("flip attempted while the ring is not ready\n"); return; } /* Wait is needed only for nonZero Seqnos, as zero Seqno indicates that either the rendering on the object (through GPU) is already completed or not intiated at all */ if (flipwork->flipdata.seqno > 0) { reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter); /* sleep wait until the seqno has passed */ ret = __wait_seqno(ring, flipwork->flipdata.seqno, reset_counter, true, NULL); if (ret) DRM_ERROR("wait_seqno failed on seqno 0x%x(%d)\n", flipwork->flipdata.seqno, flipwork->flipdata.ring_id); } intel_mark_page_flip_active(intel_crtc); i9xx_update_plane(crtc, crtc->fb, 0, 0); } /* Using MMIO based flips starting from VLV, for Media power well * residency optimization. The other alternative of having Render * ring based flip calls is not being used, as the performance * (FPS) of certain 3D Apps was getting severly affected. */ static int intel_gen7_queue_mmio_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 i915_flip_work *work = &flip_works[intel_crtc->plane]; int ret; intel_use_scratch_page_for_fb(obj); ret = intel_pin_and_fence_fb_obj(dev, obj, obj->ring); if (ret) goto err; switch (intel_crtc->plane) { case PLANE_A: case PLANE_B: case PLANE_C: break; default: WARN_ONCE(1, "unknown plane in flip command\n"); ret = -ENODEV; goto err_unpin; } /* * Check opportunistically, if rendering has already completed or not * on the buffer to be flipped. Else we need to wait and we queue * a work item for that, so as to wait from worker thread's context. */ if (!obj->ring || i915_seqno_passed(obj->ring->get_seqno(obj->ring, false), obj->last_write_seqno)) { intel_mark_page_flip_active(intel_crtc); i9xx_update_plane(crtc, crtc->fb, 0, 0); return 0; } work->flipdata.crtc = crtc; work->flipdata.seqno = obj->last_write_seqno; work->flipdata.ring_id = RCS; if (obj->last_write_seqno > 0) { if (obj->ring) { work->flipdata.ring_id = obj->ring->id; /* Check if there is a need to add the request * in the ring to emit the seqno for this fb obj */ ret = i915_gem_check_olr(obj->ring, obj->last_write_seqno); if (ret) goto err_unpin; } else { DRM_ERROR("NULL ring for active obj with seqno %x\n", obj->last_write_seqno); ret = -EINVAL; goto err_unpin; } } if (dev_priv->atomic_update) intel_gen7_queue_mmio_flip_work_sync(work); else { INIT_WORK(&work->work, intel_gen7_queue_mmio_flip_work); /* * Queue the MMIO flip work in our private workqueue, * from which the work items will be dequeued sequentially * one by one */ queue_work(dev_priv->flipwq, &work->work); } return 0; err_unpin: intel_unpin_fb_obj(obj); err: 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]; uint32_t plane_bit = 0; int ret; ret = intel_pin_and_fence_fb_obj(dev, obj, ring); if (ret) goto err; switch(intel_crtc->plane) { case PLANE_A: plane_bit = MI_DISPLAY_FLIP_IVB_PLANE_A; break; case PLANE_B: plane_bit = MI_DISPLAY_FLIP_IVB_PLANE_B; break; case PLANE_C: plane_bit = MI_DISPLAY_FLIP_IVB_PLANE_C; break; default: WARN_ONCE(1, "unknown plane in flip command\n"); ret = -ENODEV; goto err_unpin; } ret = intel_ring_begin(ring, 16); if (ret) goto err_unpin; /* Set a flag to indicate that a page flip interrupt is expected. * The flag is used by the TDR logic to detect whether the blitter hung * on a page flip command, in which case it will need to manually * complete the page flip. * The 'flag' is actually the pipe value associated with this page * flip + 1 so that the TDR code knows which pipe failed to flip. * A value of 0 indicates that a flip is not currently in progress on * the HW.*/ intel_ring_emit(ring, MI_STORE_DWORD_INDEX); intel_ring_emit(ring, I915_GEM_PGFLIP_INDEX << MI_STORE_DWORD_INDEX_SHIFT); intel_ring_emit(ring, intel_crtc->pipe + 1); intel_ring_emit(ring, MI_NOOP); if (IS_VALLEYVIEW(dev)) i9xx_update_plane(crtc, fb, 0, 0); intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | plane_bit); intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode)); intel_ring_emit(ring, i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset); intel_ring_emit(ring, (MI_NOOP)); /* Clear the flag as soon as we pass over the page flip command. * If we passed over the command without hanging then an interrupt should * be received to complete the page flip.*/ intel_ring_emit(ring, MI_STORE_DWORD_INDEX); intel_ring_emit(ring, I915_GEM_PGFLIP_INDEX << MI_STORE_DWORD_INDEX_SHIFT); intel_ring_emit(ring, 0); intel_ring_emit(ring, MI_NOOP); intel_mark_page_flip_active(intel_crtc); intel_ring_advance(ring); i915_add_request_wo_flush(ring); return 0; err_unpin: intel_unpin_fb_obj(obj); err: 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) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct drm_framebuffer *old_fb = crtc->fb; struct drm_i915_gem_object *obj = to_intel_framebuffer(fb)->obj; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_unpin_work *work; unsigned long flags; int ret; struct intel_framebuffer *intel_fb, *intel_new_fb; intel_fb = to_intel_framebuffer(crtc->fb); intel_new_fb = to_intel_framebuffer(fb); /* Avoid flip operation if shutdown is in progress */ if (dev_priv->pm.shutdown_in_progress || !intel_crtc->active) return -EINVAL; /* Can't change pixel format via MI display flips. */ if (fb->pixel_format != crtc->fb->pixel_format) { if (IS_VALLEYVIEW(dev)) DRM_DEBUG("Allow dynamic pixel format for vlv\n"); else return -EINVAL; } /* * TILEOFF/LINOFF registers can't be changed via MI display flips. * Note that pitch changes could also affect these register. */ if (INTEL_INFO(dev)->gen > 3 && (fb->offsets[0] != crtc->fb->offsets[0] || fb->pitches[0] != crtc->fb->pitches[0] || fb->depth != crtc->fb->depth || fb->bits_per_pixel != crtc->fb->bits_per_pixel || intel_new_fb->obj->tiling_mode != intel_fb->obj->tiling_mode)) { if (IS_VALLEYVIEW(dev)) DRM_DEBUG("Allow dynamic pixel format for vlv\n"); else return -EINVAL; } work = kzalloc(sizeof *work, GFP_KERNEL); if (work == NULL) return -ENOMEM; work->event = event; work->crtc = crtc; work->old_fb_obj = to_intel_framebuffer(old_fb)->obj; INIT_WORK(&work->work, intel_unpin_work_fn); ret = drm_vblank_get(dev, intel_crtc->pipe); if (ret) goto free_work; /* We borrow the event spin lock for protecting unpin_work */ spin_lock_irqsave(&dev->event_lock, flags); if (intel_crtc->unpin_work) { spin_unlock_irqrestore(&dev->event_lock, flags); kfree(work); drm_vblank_put(dev, intel_crtc->pipe); DRM_DEBUG_DRIVER("flip queue: crtc already busy\n"); return -EBUSY; } intel_crtc->unpin_work = work; spin_unlock_irqrestore(&dev->event_lock, flags); if (atomic_read(&intel_crtc->unpin_work_count) >= 2) flush_workqueue(dev_priv->wq); ret = i915_mutex_lock_interruptible(dev); if (ret) goto cleanup; /* Reference the objects for the scheduled work. */ drm_gem_object_reference(&work->old_fb_obj->base); drm_gem_object_reference(&obj->base); crtc->fb = fb; work->pending_flip_obj = obj; work->enable_stall_check = true; atomic_inc(&intel_crtc->unpin_work_count); intel_crtc->reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter); ret = dev_priv->display.queue_flip(dev, crtc, fb, obj); if (ret) goto cleanup_pending; intel_disable_fbc(dev); intel_disable_drrs(dev); intel_mark_fb_busy(obj, NULL); mutex_unlock(&dev->struct_mutex); trace_i915_flip_request(intel_crtc->plane, obj); return 0; cleanup_pending: atomic_dec(&intel_crtc->unpin_work_count); crtc->fb = old_fb; drm_gem_object_unreference(&work->old_fb_obj->base); drm_gem_object_unreference(&obj->base); mutex_unlock(&dev->struct_mutex); cleanup: spin_lock_irqsave(&dev->event_lock, flags); intel_crtc->unpin_work = NULL; spin_unlock_irqrestore(&dev->event_lock, flags); drm_vblank_put(dev, intel_crtc->pipe); free_work: kfree(work); return ret; } static void i915_commit(struct drm_i915_private *dev_priv, struct intel_plane *intel_plane, enum pipe pipe, enum planes type) { struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_disp_reg *reg; int plane = 0; if (type == SPRITE_PLANE) { reg = &intel_plane->reg; plane = intel_plane->plane; } else { reg = &intel_crtc->reg; plane = intel_crtc->plane; } /* Enable Primary plane */ if (type == SPRITE_PLANE) { if (intel_plane->pri_update && (reg->dspcntr & (1 << 31))) { I915_WRITE(DSPCNTR(pipe), reg->dspcntr); intel_plane->pri_update = false; } } if (reg->pfit_control && reg->pipesrc) { if (dev_priv->pfit_pipe == ((reg->pfit_control & PFIT_PIPE_MASK) >> 29) && I915_READ(PFIT_CONTROL) != reg->pfit_control) I915_WRITE(PFIT_CONTROL, reg->pfit_control); if (I915_READ(PIPESRC(pipe)) != reg->pipesrc) I915_WRITE(PIPESRC(pipe), reg->pipesrc); intel_crtc->pfit_en_status = true; } else if (intel_crtc->pfit_en_status) { if (I915_READ(PIPESRC(pipe)) != reg->pipesrc) I915_WRITE(PIPESRC(pipe), reg->pipesrc); if (dev_priv->pfit_pipe == ((reg->pfit_control & PFIT_PIPE_MASK) >> 29) && I915_READ(PFIT_CONTROL) != reg->pfit_control) I915_WRITE(PFIT_CONTROL, reg->pfit_control); intel_crtc->pfit_en_status = false; } if (type == SPRITE_PLANE) { I915_WRITE(SPSTRIDE(pipe, plane), reg->stride); I915_WRITE(SPPOS(pipe, plane), reg->pos); I915_WRITE(SPTILEOFF(pipe, plane), reg->tileoff); I915_WRITE(SPLINOFF(pipe, plane), reg->linoff); I915_WRITE(SPSIZE(pipe, plane), reg->size); I915_WRITE_BITS(SPCNTR(pipe, plane), reg->cntr, 0xBFFFFFF8); I915_WRITE(SPSURF(pipe, plane), reg->surf); if (intel_plane->pri_update) { I915_WRITE(DSPCNTR(pipe), reg->dspcntr); I915_MODIFY_DISPBASE(DSPSURF(pipe), I915_READ(DSPSURF(pipe))); intel_plane->pri_update = false; } POSTING_READ(SPSURF(pipe, plane)); } else { I915_WRITE(DSPSTRIDE(pipe), reg->stride); I915_WRITE(DSPTILEOFF(pipe), reg->tileoff); I915_WRITE(DSPLINOFF(pipe), reg->linoff); I915_WRITE(DSPCNTR(pipe), reg->cntr); I915_MODIFY_DISPBASE(DSPSURF(pipe), reg->surf); POSTING_READ(DSPCNTR(pipe)); } /* Reset the register */ reg->surf = 0; } static unsigned int usecs_to_scanlines(struct drm_crtc *crtc, unsigned int usecs) { /* paranoia */ if (!crtc->hwmode.crtc_htotal) return 1; return DIV_ROUND_UP(usecs * crtc->hwmode.clock, 1000 * crtc->hwmode.crtc_htotal); } static void intel_pipe_vblank_evade(struct drm_crtc *crtc) { 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; /* FIXME needs to be calibrated sensibly */ u32 min = crtc->hwmode.crtc_vdisplay - usecs_to_scanlines(crtc, 50); u32 max = crtc->hwmode.crtc_vdisplay - 1; u32 val; local_irq_disable(); val = I915_READ(PIPEDSL(pipe)); local_irq_enable(); while (val >= min && val <= max) { intel_wait_for_vblank(dev_priv->dev, intel_crtc->pipe); local_irq_disable(); val = I915_READ(PIPEDSL(pipe)); local_irq_enable(); dev_priv->wait_vbl = false; } if (val >= min && val <= max) dev_warn(dev->dev, "Page flipping close to vblank start (DSL=%u, VBL=%u)\n", val, crtc->hwmode.crtc_vdisplay); } static int intel_crtc_flip_prepare(struct drm_crtc *crtc, struct drm_mode_set_display *disp, struct drm_file *file_priv) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_plane_180_rotation *rotate; struct drm_i915_set_plane_zorder *zorder; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct drm_mode_crtc_page_flip *flip; struct drm_mode_set_plane *plane; struct drm_mode_object *obj; struct drm_plane *drm_plane; struct intel_plane *intel_plane; int i, tmp_ret, ret = 0; int plane_cnt = 0; disp->errored = 0; disp->presented = 0; /* * userspace app will not call this function again until the * page_flip done event is received so no locking is required here */ /* Disable maxfifo if multiple planes are enabled */ for (i = disp->num_planes-1; i >= 0; i--) { if (disp->plane[i].update_flag & DRM_MODE_SET_DISPLAY_PLANE_UPDATE_PRESENT) plane_cnt++; } if ((plane_cnt > 1) && dev_priv->maxfifo_enabled) { I915_WRITE(FW_BLC_SELF_VLV, ~FW_CSPWRDWNEN); dev_priv->maxfifo_enabled = false; dev_priv->wait_vbl = true; dev_priv->vblcount = atomic_read( &dev->_vblank_count[intel_crtc->pipe]); } if (disp->update_flag & DRM_MODE_SET_DISPLAY_UPDATE_PANEL_FITTER) { if (intel_crtc->config.gmch_pfit.control || disp->panel_fitter.mode) { u32 pfit_control = intel_crtc->config.gmch_pfit.control; /* If any of the mode is set then panel fitter should be enabled*/ pfit_control = (1 << 31) | pfit_control; if (disp->panel_fitter.mode == AUTOSCALE) { pfit_control &= MASK_PFIT_SCALING_MODE; pfit_control |= PFIT_SCALING_AUTO; } else if (disp->panel_fitter.mode == PILLARBOX) { pfit_control &= MASK_PFIT_SCALING_MODE; pfit_control |= PFIT_SCALING_PILLAR; } else if (disp->panel_fitter.mode == LETTERBOX) { pfit_control &= MASK_PFIT_SCALING_MODE; pfit_control |= PFIT_SCALING_LETTER; } else { if (!dev_priv->scaling_reqd) { /* None of the above mode, then pfit is disabled */ pfit_control &= ~PFIT_ENABLE; } else pfit_control &= MASK_PFIT_SCALING_MODE; } intel_crtc->config.gmch_pfit.control = pfit_control; } intel_crtc->scaling_src_size = (((disp->panel_fitter.src_w - 1) << 16) | (disp->panel_fitter.src_h - 1)); } if (disp->update_flag & DRM_MODE_SET_DISPLAY_UPDATE_ZORDER) { zorder = kzalloc(sizeof(struct drm_i915_set_plane_zorder), GFP_KERNEL); if (!zorder) { DRM_ERROR("Failed to alloc memory set zorder fail\n"); return -ENOMEM; } zorder->order = disp->zorder; tmp_ret = i915_set_plane_zorder(dev, (void *)zorder, NULL); if (tmp_ret) { DRM_ERROR("i915_set_plane_zorder failed\n"); DRM_ERROR("::order %u ret %d\n", zorder->order, tmp_ret); ret = -EINVAL; } kfree(zorder); } /* Need to issue the drm_mode_page_flip_ioctl last as it triggers the flip done callback. * It just happens that index 0 is for the CRTC id, but this should be fixed properly. */ for (i = disp->num_planes-1; i >= 0; i--) { if (!(disp->update_flag & DRM_MODE_SET_DISPLAY_UPDATE_PLANE(i))) continue; DRM_DEBUG("plane %u (obj_id %u, obj_type 0x%x)", i, disp->plane[i].obj_id, disp->plane[i].obj_type); if (disp->plane[i].update_flag & DRM_MODE_SET_DISPLAY_PLANE_UPDATE_TRANSFORM) { rotate = kzalloc(sizeof(struct drm_i915_plane_180_rotation), GFP_KERNEL); if (!rotate) { DRM_ERROR( "Failed to alloc memory-180 Rotate\n"); disp->errored |= (1 << i); ret = -ENOMEM; } else { rotate->obj_id = disp->plane[i].obj_id; rotate->obj_type = disp->plane[i].obj_type; rotate->rotate = disp->plane[i].transform == DRM_MODE_SET_DISPLAY_PLANE_TRANSFORM_ROT180 ? 1 : 0; tmp_ret = i915_set_plane_180_rotation(dev, (void *)rotate, NULL); if (tmp_ret) { DRM_ERROR("i915_set_plane_180_rotation failed\n"); DRM_ERROR("::obj id %u obj type %u rotate %u ret %d\n", rotate->obj_id, rotate->obj_type, rotate->rotate, tmp_ret); disp->errored |= (1 << i); ret = -EINVAL; } kfree(rotate); } } if (disp->plane[i].update_flag & DRM_MODE_SET_DISPLAY_PLANE_UPDATE_PRESENT) { if (disp->plane[i].obj_type == DRM_MODE_OBJECT_CRTC) { flip = kzalloc(sizeof (struct drm_mode_crtc_page_flip), GFP_ATOMIC); if (!flip) { DRM_ERROR("Failed to alloc memory - page_flip\n"); disp->errored |= (1 << i); ret = -ENOMEM; continue; } /* * for primary and secondary planes page flip call drm * page flip ioctl, set_plane is done as part of this. */ flip->crtc_id = disp->plane[i].obj_id; flip->fb_id = disp->plane[i].fb_id; flip->flags = disp->plane[i].flags; flip->reserved = 0; flip->user_data = disp->plane[i].user_data; /* pass alpha information */ if (disp->plane[i].update_flag & DRM_MODE_SET_DISPLAY_PLANE_UPDATE_ALPHA) intel_crtc->alpha = disp->plane[i].alpha; tmp_ret = drm_mode_page_flip_ioctl(dev, flip, file_priv); if (tmp_ret) { DRM_ERROR("drm_mode_page_flio_ioctl failed\n"); DRM_ERROR("::crtc_id %u fb %u flags 0x%x ud %llu ret %d\n", flip->crtc_id, flip->fb_id, flip->flags, flip->user_data, tmp_ret); disp->errored |= (1 << i); kfree(flip); return tmp_ret; } else { disp->presented |= (1 << i); } kfree(flip); } else { plane = kzalloc(sizeof (struct drm_mode_set_plane), GFP_ATOMIC); if (!plane) { DRM_ERROR("Failed to alloc memory - set_plane\n"); disp->errored |= (1 << i); ret = -ENOMEM; continue; } /* * for sprite plane call update_plane or setplane, which * internally does page_flip. */ plane->plane_id = disp->plane[i].obj_id; plane->crtc_id = disp->crtc_id; plane->fb_id = disp->plane[i].fb_id; plane->flags = disp->plane[i].flags; plane->crtc_x = disp->plane[i].crtc_x; plane->crtc_y = disp->plane[i].crtc_y; plane->crtc_w = disp->plane[i].crtc_w; plane->crtc_h = disp->plane[i].crtc_h; plane->src_x = disp->plane[i].src_x; plane->src_y = disp->plane[i].src_y; plane->src_w = disp->plane[i].src_w; plane->src_h = disp->plane[i].src_h; plane->user_data = disp->plane[i].user_data; obj = drm_mode_object_find(dev, disp->plane[i].obj_id, DRM_MODE_OBJECT_PLANE); if (!obj) return -ENOENT; drm_plane = obj_to_plane(obj); intel_plane = to_intel_plane(drm_plane); /* pass rrb2 information */ if (disp->plane[i].update_flag & DRM_MODE_SET_DISPLAY_PLANE_UPDATE_RRB2) intel_plane->rrb2_enable = disp->plane[i].rrb2_enable; /* pass alpha information */ if (disp->plane[i].update_flag & DRM_MODE_SET_DISPLAY_PLANE_UPDATE_ALPHA) intel_plane->alpha = disp->plane[i].alpha; tmp_ret = drm_mode_setplane(dev, plane, file_priv); if (tmp_ret) { DRM_ERROR_RATELIMITED("drm_mode_setplane failed\n"); DRM_ERROR_RATELIMITED("::plane_id %u crtc_id %u fb %u flags 0x%x {%d,%d,%ux%u %d,%d,%ux%u} ud %llu ret %d\n", plane->plane_id, plane->crtc_id, plane->fb_id, plane->flags, plane->crtc_x, plane->crtc_y, plane->crtc_w, plane->crtc_h, plane->src_x, plane->src_y, plane->src_h, plane->src_w, plane->user_data, tmp_ret); disp->errored |= (1<presented |= (1<dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct drm_mode_object *obj; struct drm_plane *drm_plane; struct intel_plane *intel_plane; int i; /* Program the z-order */ if (disp->update_flag & DRM_MODE_SET_DISPLAY_UPDATE_ZORDER) { I915_WRITE_BITS(SPCNTR(intel_crtc->pipe, 0), intel_crtc->reg.spacntr, 0x00000007); I915_WRITE(SPSURF(intel_crtc->pipe, 0), I915_READ(SPSURF(intel_crtc->pipe, 0))); I915_WRITE_BITS(SPCNTR(intel_crtc->pipe, 1), intel_crtc->reg.spbcntr, 0x00000007); I915_WRITE(SPSURF(intel_crtc->pipe, 1), I915_READ(SPSURF(intel_crtc->pipe, 1))); } /* Write to all display registers */ for (i = disp->num_planes-1; i >= 0; i--) { if (!(disp->update_flag & DRM_MODE_SET_DISPLAY_UPDATE_PLANE(i))) continue; if (disp->plane[i].update_flag & DRM_MODE_SET_DISPLAY_PLANE_UPDATE_PRESENT) { if (disp->plane[i].obj_type == DRM_MODE_OBJECT_CRTC) { i915_commit(dev_priv, NULL, intel_crtc->pipe, DISPLAY_PLANE); } else { obj = drm_mode_object_find(dev, disp->plane[i].obj_id, DRM_MODE_OBJECT_PLANE); drm_plane = obj_to_plane(obj); intel_plane = to_intel_plane(drm_plane); i915_commit(dev_priv, (void *)intel_plane, intel_crtc->pipe, SPRITE_PLANE); } } } /* Enable maxffo if required */ if (is_maxfifo_needed(dev_priv) && !dev_priv->maxfifo_enabled) { I915_WRITE(FW_BLC_SELF_VLV, FW_CSPWRDWNEN); dev_priv->maxfifo_enabled = true; } } static int intel_crtc_set_display(struct drm_crtc *crtc, struct drm_mode_set_display *disp, struct drm_file *file_priv) { 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 ret = 0; disp->errored = 0; disp->presented = 0; /* If HWC version and size of the struct doesnt match, return NULL */ if (!(disp->version == DRM_MODE_SET_DISPLAY_VERSION && disp->size == sizeof(struct drm_mode_set_display))) { DRM_ERROR("HWC version or struct size mismatch"); return -EINVAL; } dev_priv->atomic_update = true; /* Prepare or calculate plane properties for flip */ ret = intel_crtc_flip_prepare(crtc, disp, file_priv); if (ret) { DRM_ERROR_RATELIMITED("failed to validate or calculate plane data\n"); return ret; } /* Check if we need to a vblank, if so wait for vblank */ if (dev_priv->wait_vbl) { if (dev_priv->vblcount == atomic_read(&dev->_vblank_count[intel_crtc->pipe])) { intel_wait_for_vblank(dev, intel_crtc->pipe); } dev_priv->wait_vbl = false; } /* make sure to start from a fresh vsync, it we are close to vblank */ intel_pipe_vblank_evade(crtc); /* flip: write to the plane registers */ intel_crtc_flip_commit(crtc, disp, file_priv); dev_priv->atomic_update = false; return ret; } static struct drm_crtc_helper_funcs intel_helper_funcs = { .mode_set_base_atomic = intel_pipe_set_base_atomic, .load_lut = intel_crtc_load_lut, }; static bool intel_encoder_crtc_ok(struct drm_encoder *encoder, struct drm_crtc *crtc) { struct drm_device *dev; struct drm_crtc *tmp; int crtc_mask = 1; WARN(!crtc, "checking null crtc?\n"); dev = crtc->dev; list_for_each_entry(tmp, &dev->mode_config.crtc_list, head) { if (tmp == crtc) break; crtc_mask <<= 1; } if (encoder->possible_crtcs & crtc_mask) return true; return false; } /** * intel_modeset_update_staged_output_state * * Updates the staged output configuration state, e.g. after we've read out the * current hw state. */ static void intel_modeset_update_staged_output_state(struct drm_device *dev) { struct intel_encoder *encoder; struct intel_connector *connector; list_for_each_entry(connector, &dev->mode_config.connector_list, base.head) { connector->new_encoder = to_intel_encoder(connector->base.encoder); } list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) { encoder->new_crtc = to_intel_crtc(encoder->base.crtc); } } /** * intel_modeset_commit_output_state * * This function copies the stage display pipe configuration to the real one. */ static void intel_modeset_commit_output_state(struct drm_device *dev) { struct intel_encoder *encoder; struct intel_connector *connector; list_for_each_entry(connector, &dev->mode_config.connector_list, base.head) { connector->base.encoder = &connector->new_encoder->base; } list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) { encoder->base.crtc = &encoder->new_crtc->base; } } static void connected_sink_compute_bpp(struct intel_connector * connector, struct intel_crtc_config *pipe_config) { int bpp = pipe_config->pipe_bpp; DRM_DEBUG_KMS("[CONNECTOR:%d:%s] checking for sink bpp constrains\n", connector->base.base.id, drm_get_connector_name(&connector->base)); /* Don't use an invalid EDID bpc value */ if (connector->base.display_info.bpc && connector->base.display_info.bpc * 3 < bpp) { DRM_DEBUG_KMS("clamping display bpp (was %d) to EDID reported max of %d\n", bpp, connector->base.display_info.bpc*3); pipe_config->pipe_bpp = connector->base.display_info.bpc*3; } /* Clamp bpp to 8 on screens without EDID 1.4 */ if (connector->base.display_info.bpc == 0 && bpp > 24) { DRM_DEBUG_KMS("clamping display bpp (was %d) to default limit of 24\n", bpp); pipe_config->pipe_bpp = 24; } } static int compute_baseline_pipe_bpp(struct intel_crtc *crtc, struct drm_framebuffer *fb, struct intel_crtc_config *pipe_config) { struct drm_device *dev = crtc->base.dev; struct intel_connector *connector; int bpp; switch (fb->pixel_format) { case DRM_FORMAT_C8: bpp = 8*3; /* since we go through a colormap */ break; case DRM_FORMAT_XRGB1555: case DRM_FORMAT_ARGB1555: /* checked in intel_framebuffer_init already */ if (WARN_ON(INTEL_INFO(dev)->gen > 3)) return -EINVAL; case DRM_FORMAT_RGB565: bpp = 6*3; /* min is 18bpp */ break; case DRM_FORMAT_XBGR8888: case DRM_FORMAT_ABGR8888: /* checked in intel_framebuffer_init already */ if (WARN_ON(INTEL_INFO(dev)->gen < 4)) return -EINVAL; case DRM_FORMAT_XRGB8888: case DRM_FORMAT_ARGB8888: bpp = 8*3; break; case DRM_FORMAT_XRGB2101010: case DRM_FORMAT_ARGB2101010: case DRM_FORMAT_XBGR2101010: case DRM_FORMAT_ABGR2101010: /* checked in intel_framebuffer_init already */ if (WARN_ON(INTEL_INFO(dev)->gen < 4)) return -EINVAL; bpp = 10*3; break; /* TODO: gen4+ supports 16 bpc floating point, too. */ default: DRM_DEBUG_KMS("unsupported depth\n"); return -EINVAL; } pipe_config->pipe_bpp = bpp; /* Clamp display bpp to EDID value */ list_for_each_entry(connector, &dev->mode_config.connector_list, base.head) { if (!connector->new_encoder || connector->new_encoder->new_crtc != crtc) continue; connected_sink_compute_bpp(connector, pipe_config); } return bpp; } static void intel_dump_pipe_config(struct intel_crtc *crtc, struct intel_crtc_config *pipe_config, const char *context) { DRM_DEBUG_KMS("[CRTC:%d]%s config for pipe %c\n", crtc->base.base.id, context, pipe_name(crtc->pipe)); DRM_DEBUG_KMS("cpu_transcoder: %c\n", transcoder_name(pipe_config->cpu_transcoder)); DRM_DEBUG_KMS("pipe bpp: %i, dithering: %i\n", pipe_config->pipe_bpp, pipe_config->dither); DRM_DEBUG_KMS("fdi/pch: %i, lanes: %i, gmch_m: %u, gmch_n: %u, link_m: %u, link_n: %u, tu: %u\n", pipe_config->has_pch_encoder, pipe_config->fdi_lanes, pipe_config->fdi_m_n.gmch_m, pipe_config->fdi_m_n.gmch_n, pipe_config->fdi_m_n.link_m, pipe_config->fdi_m_n.link_n, pipe_config->fdi_m_n.tu); DRM_DEBUG_KMS("requested mode:\n"); drm_mode_debug_printmodeline(&pipe_config->requested_mode); DRM_DEBUG_KMS("adjusted mode:\n"); drm_mode_debug_printmodeline(&pipe_config->adjusted_mode); DRM_DEBUG_KMS("gmch pfit: control: 0x%08x, ratios: 0x%08x, lvds border: 0x%08x\n", pipe_config->gmch_pfit.control, pipe_config->gmch_pfit.pgm_ratios, pipe_config->gmch_pfit.lvds_border_bits); DRM_DEBUG_KMS("pch pfit: pos: 0x%08x, size: 0x%08x\n", pipe_config->pch_pfit.pos, pipe_config->pch_pfit.size); DRM_DEBUG_KMS("ips: %i\n", pipe_config->ips_enabled); } static bool check_encoder_cloning(struct drm_crtc *crtc) { int num_encoders = 0; bool uncloneable_encoders = false; struct intel_encoder *encoder; list_for_each_entry(encoder, &crtc->dev->mode_config.encoder_list, base.head) { if (&encoder->new_crtc->base != crtc) continue; num_encoders++; if (!encoder->cloneable) uncloneable_encoders = true; } return !(num_encoders > 1 && uncloneable_encoders); } static struct intel_crtc_config * intel_modeset_pipe_config(struct drm_crtc *crtc, struct drm_framebuffer *fb, struct drm_display_mode *mode) { struct drm_device *dev = crtc->dev; struct intel_encoder *encoder; struct intel_crtc_config *pipe_config; int plane_bpp, ret = -EINVAL; bool retry = true; if (!check_encoder_cloning(crtc)) { DRM_DEBUG_KMS("rejecting invalid cloning configuration\n"); return ERR_PTR(-EINVAL); } /* Block a dummy modeset with NULL mode values which might cause panic*/ if (mode == NULL) { DRM_DEBUG_KMS("Mode is NULL"); return ERR_PTR(-EINVAL); } if (fb == NULL) { DRM_DEBUG_KMS("FB is NULL"); return ERR_PTR(-EINVAL); } pipe_config = kzalloc(sizeof(*pipe_config), GFP_KERNEL); if (!pipe_config) return ERR_PTR(-ENOMEM); drm_mode_copy(&pipe_config->adjusted_mode, mode); drm_mode_copy(&pipe_config->requested_mode, mode); pipe_config->cpu_transcoder = (enum transcoder) to_intel_crtc(crtc)->pipe; pipe_config->shared_dpll = DPLL_ID_PRIVATE; /* * Sanitize sync polarity flags based on requested ones. If neither * positive or negative polarity is requested, treat this as meaning * negative polarity. */ if (!(pipe_config->adjusted_mode.flags & (DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NHSYNC))) pipe_config->adjusted_mode.flags |= DRM_MODE_FLAG_NHSYNC; if (!(pipe_config->adjusted_mode.flags & (DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC))) pipe_config->adjusted_mode.flags |= DRM_MODE_FLAG_NVSYNC; /* Compute a starting value for pipe_config->pipe_bpp taking the source * plane pixel format and any sink constraints into account. Returns the * source plane bpp so that dithering can be selected on mismatches * after encoders and crtc also have had their say. */ plane_bpp = compute_baseline_pipe_bpp(to_intel_crtc(crtc), fb, pipe_config); if (plane_bpp < 0) goto fail; encoder_retry: /* Ensure the port clock defaults are reset when retrying. */ pipe_config->port_clock = 0; pipe_config->pixel_multiplier = 1; /* Fill in default crtc timings, allow encoders to overwrite them. */ drm_mode_set_crtcinfo(&pipe_config->adjusted_mode, 0); /* Pass our mode to the connectors and the CRTC to give them a chance to * adjust it according to limitations or connector properties, and also * a chance to reject the mode entirely. */ list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) { if (&encoder->new_crtc->base != crtc) continue; if (!(encoder->compute_config(encoder, pipe_config))) { DRM_DEBUG_KMS("Encoder config failure\n"); goto fail; } } /* Set default port clock if not overwritten by the encoder. Needs to be * done afterwards in case the encoder adjusts the mode. */ if (!pipe_config->port_clock) pipe_config->port_clock = pipe_config->adjusted_mode.clock; ret = intel_crtc_compute_config(to_intel_crtc(crtc), pipe_config); if (ret < 0) { DRM_DEBUG_KMS("CRTC fixup failed\n"); goto fail; } if (ret == RETRY) { if (WARN(!retry, "loop in pipe configuration computation\n")) { ret = -EINVAL; goto fail; } DRM_DEBUG_KMS("CRTC bw constrained, retrying\n"); retry = false; goto encoder_retry; } DRM_DEBUG_KMS("plane bpp: %i, pipe bpp: %i, dithering: %i\n", plane_bpp, pipe_config->pipe_bpp, pipe_config->dither); return pipe_config; fail: kfree(pipe_config); return ERR_PTR(ret); } /* Computes which crtcs are affected and sets the relevant bits in the mask. For * simplicity we use the crtc's pipe number (because it's easier to obtain). */ static void intel_modeset_affected_pipes(struct drm_crtc *crtc, unsigned *modeset_pipes, unsigned *prepare_pipes, unsigned *disable_pipes) { struct intel_crtc *intel_crtc; struct drm_device *dev = crtc->dev; struct intel_encoder *encoder; struct intel_connector *connector; struct drm_crtc *tmp_crtc; *disable_pipes = *modeset_pipes = *prepare_pipes = 0; /* Check which crtcs have changed outputs connected to them, these need * to be part of the prepare_pipes mask. We don't (yet) support global * modeset across multiple crtcs, so modeset_pipes will only have one * bit set at most. */ list_for_each_entry(connector, &dev->mode_config.connector_list, base.head) { if (connector->base.encoder == &connector->new_encoder->base) continue; if (connector->base.encoder) { tmp_crtc = connector->base.encoder->crtc; *prepare_pipes |= 1 << to_intel_crtc(tmp_crtc)->pipe; } if (connector->new_encoder) *prepare_pipes |= 1 << connector->new_encoder->new_crtc->pipe; } list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) { if (encoder->base.crtc == &encoder->new_crtc->base) continue; if (encoder->base.crtc) { tmp_crtc = encoder->base.crtc; *prepare_pipes |= 1 << to_intel_crtc(tmp_crtc)->pipe; } if (encoder->new_crtc) *prepare_pipes |= 1 << encoder->new_crtc->pipe; } /* Check for any pipes that will be fully disabled ... */ list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) { bool used = false; /* Don't try to disable disabled crtcs. */ if (!intel_crtc->base.enabled) continue; list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) { if (encoder->new_crtc == intel_crtc) used = true; } if (!used) *disable_pipes |= 1 << intel_crtc->pipe; } /* set_mode is also used to update properties on life display pipes. */ intel_crtc = to_intel_crtc(crtc); if (crtc->enabled) *prepare_pipes |= 1 << intel_crtc->pipe; /* * 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; DRM_DEBUG_KMS("set mode pipe masks: modeset: %x, prepare: %x, disable: %x\n", *modeset_pipes, *prepare_pipes, *disable_pipes); } static bool intel_crtc_in_use(struct drm_crtc *crtc) { struct drm_encoder *encoder; struct drm_device *dev = crtc->dev; list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) if (encoder->crtc == crtc) return true; return false; } static void intel_modeset_update_state(struct drm_device *dev, unsigned prepare_pipes) { struct intel_encoder *intel_encoder; struct intel_crtc *intel_crtc; struct drm_connector *connector; list_for_each_entry(intel_encoder, &dev->mode_config.encoder_list, base.head) { if (!intel_encoder->base.crtc) continue; intel_crtc = to_intel_crtc(intel_encoder->base.crtc); if (prepare_pipes & (1 << intel_crtc->pipe)) intel_encoder->connectors_active = false; } intel_modeset_commit_output_state(dev); /* Update computed state. */ list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) { intel_crtc->base.enabled = intel_crtc_in_use(&intel_crtc->base); } list_for_each_entry(connector, &dev->mode_config.connector_list, head) { if (!connector->encoder || !connector->encoder->crtc) continue; intel_crtc = to_intel_crtc(connector->encoder->crtc); if (prepare_pipes & (1 << intel_crtc->pipe)) { struct drm_property *dpms_property = dev->mode_config.dpms_property; connector->dpms = DRM_MODE_DPMS_ON; drm_object_property_set_value(&connector->base, dpms_property, DRM_MODE_DPMS_ON); intel_encoder = to_intel_encoder(connector->encoder); intel_encoder->connectors_active = true; } } } /*Retaining the unused function, as it might be used in future */ #if 0 static bool intel_fuzzy_clock_check(struct intel_crtc_config *cur, struct intel_crtc_config *new) { int clock1, clock2, diff; clock1 = cur->adjusted_mode.clock; clock2 = new->adjusted_mode.clock; if (clock1 == clock2) return true; if (!clock1 || !clock2) return false; diff = abs(clock1 - clock2); if (((((diff + clock1 + clock2) * 100)) / (clock1 + clock2)) < 105) return true; return false; } #endif #define for_each_intel_crtc_masked(dev, mask, intel_crtc) \ list_for_each_entry((intel_crtc), \ &(dev)->mode_config.crtc_list, \ base.head) \ if (mask & (1 <<(intel_crtc)->pipe)) /*Retaining the unused function, as it might be used in future */ #if 0 static bool intel_pipe_config_compare(struct drm_device *dev, struct intel_crtc_config *current_config, struct intel_crtc_config *pipe_config) { #define PIPE_CONF_CHECK_X(name) \ if (current_config->name != pipe_config->name) { \ DRM_ERROR("mismatch in " #name " " \ "(expected 0x%08x, found 0x%08x)\n", \ current_config->name, \ pipe_config->name); \ return false; \ } #define PIPE_CONF_CHECK_I(name) \ if (current_config->name != pipe_config->name) { \ DRM_ERROR("mismatch in " #name " " \ "(expected %i, found %i)\n", \ current_config->name, \ pipe_config->name); \ return false; \ } #define PIPE_CONF_CHECK_FLAGS(name, mask) \ if ((current_config->name ^ pipe_config->name) & (mask)) { \ DRM_ERROR("mismatch in " #name "(" #mask ") " \ "(expected %i, found %i)\n", \ current_config->name & (mask), \ pipe_config->name & (mask)); \ return false; \ } #define PIPE_CONF_QUIRK(quirk) \ ((current_config->quirks | pipe_config->quirks) & (quirk)) PIPE_CONF_CHECK_I(cpu_transcoder); PIPE_CONF_CHECK_I(has_pch_encoder); PIPE_CONF_CHECK_I(fdi_lanes); PIPE_CONF_CHECK_I(fdi_m_n.gmch_m); PIPE_CONF_CHECK_I(fdi_m_n.gmch_n); PIPE_CONF_CHECK_I(fdi_m_n.link_m); PIPE_CONF_CHECK_I(fdi_m_n.link_n); PIPE_CONF_CHECK_I(fdi_m_n.tu); PIPE_CONF_CHECK_I(adjusted_mode.crtc_hdisplay); PIPE_CONF_CHECK_I(adjusted_mode.crtc_htotal); PIPE_CONF_CHECK_I(adjusted_mode.crtc_hblank_start); PIPE_CONF_CHECK_I(adjusted_mode.crtc_hblank_end); PIPE_CONF_CHECK_I(adjusted_mode.crtc_hsync_start); PIPE_CONF_CHECK_I(adjusted_mode.crtc_hsync_end); PIPE_CONF_CHECK_I(adjusted_mode.crtc_vdisplay); PIPE_CONF_CHECK_I(adjusted_mode.crtc_vtotal); PIPE_CONF_CHECK_I(adjusted_mode.crtc_vblank_start); PIPE_CONF_CHECK_I(adjusted_mode.crtc_vblank_end); PIPE_CONF_CHECK_I(adjusted_mode.crtc_vsync_start); PIPE_CONF_CHECK_I(adjusted_mode.crtc_vsync_end); PIPE_CONF_CHECK_I(pixel_multiplier); PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags, DRM_MODE_FLAG_INTERLACE); if (!PIPE_CONF_QUIRK(PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS)) { PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags, DRM_MODE_FLAG_PHSYNC); PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags, DRM_MODE_FLAG_NHSYNC); PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags, DRM_MODE_FLAG_PVSYNC); PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags, DRM_MODE_FLAG_NVSYNC); } PIPE_CONF_CHECK_I(requested_mode.hdisplay); PIPE_CONF_CHECK_I(requested_mode.vdisplay); PIPE_CONF_CHECK_I(gmch_pfit.control); /* pfit ratios are autocomputed by the hw on gen4+ */ if (INTEL_INFO(dev)->gen < 4) PIPE_CONF_CHECK_I(gmch_pfit.pgm_ratios); PIPE_CONF_CHECK_I(gmch_pfit.lvds_border_bits); PIPE_CONF_CHECK_I(pch_pfit.pos); PIPE_CONF_CHECK_I(pch_pfit.size); PIPE_CONF_CHECK_I(ips_enabled); PIPE_CONF_CHECK_I(shared_dpll); PIPE_CONF_CHECK_X(dpll_hw_state.dpll); PIPE_CONF_CHECK_X(dpll_hw_state.dpll_md); PIPE_CONF_CHECK_X(dpll_hw_state.fp0); PIPE_CONF_CHECK_X(dpll_hw_state.fp1); #undef PIPE_CONF_CHECK_X #undef PIPE_CONF_CHECK_I #undef PIPE_CONF_CHECK_FLAGS #undef PIPE_CONF_QUIRK if (!IS_HASWELL(dev)) { if (!intel_fuzzy_clock_check(current_config, pipe_config)) { DRM_ERROR("mismatch in clock (expected %d, found %d)\n", current_config->adjusted_mode.clock, pipe_config->adjusted_mode.clock); return false; } } return true; } #endif static void check_connector_state(struct drm_device *dev) { struct intel_connector *connector; list_for_each_entry(connector, &dev->mode_config.connector_list, base.head) { /* This also checks the encoder/connector hw state with the * ->get_hw_state callbacks. */ intel_connector_check_state(connector); WARN(&connector->new_encoder->base != connector->base.encoder, "connector's staged encoder doesn't match current encoder\n"); } } static void check_encoder_state(struct drm_device *dev) { struct intel_encoder *encoder; struct intel_connector *connector; list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) { bool enabled = false; bool active = false; enum pipe pipe, tracked_pipe; DRM_DEBUG_KMS("[ENCODER:%d:%s]\n", encoder->base.base.id, drm_get_encoder_name(&encoder->base)); WARN(&encoder->new_crtc->base != encoder->base.crtc, "encoder's stage crtc doesn't match current crtc\n"); WARN(encoder->connectors_active && !encoder->base.crtc, "encoder's active_connectors set, but no crtc\n"); list_for_each_entry(connector, &dev->mode_config.connector_list, base.head) { if (connector->base.encoder != &encoder->base) continue; enabled = true; if (connector->base.dpms != DRM_MODE_DPMS_OFF) active = true; } WARN(!!encoder->base.crtc != enabled, "encoder's enabled state mismatch " "(expected %i, found %i)\n", !!encoder->base.crtc, enabled); WARN(active && !encoder->base.crtc, "active encoder with no crtc\n"); WARN(encoder->connectors_active != active, "encoder's computed active state doesn't match tracked active state " "(expected %i, found %i)\n", active, encoder->connectors_active); active = encoder->get_hw_state(encoder, &pipe); WARN(active != encoder->connectors_active, "encoder's hw state doesn't match sw tracking " "(expected %i, found %i)\n", encoder->connectors_active, active); if (!encoder->base.crtc) continue; tracked_pipe = to_intel_crtc(encoder->base.crtc)->pipe; WARN(active && pipe != tracked_pipe, "active encoder's pipe doesn't match" "(expected %i, found %i)\n", tracked_pipe, pipe); } } static void check_crtc_state(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; struct intel_crtc *crtc; struct intel_encoder *encoder; struct intel_crtc_config pipe_config; list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) { bool enabled = false; bool active = false; memset(&pipe_config, 0, sizeof(pipe_config)); DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.base.id); WARN(crtc->active && !crtc->base.enabled, "active crtc, but not enabled in sw tracking\n"); list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) { if (encoder->base.crtc != &crtc->base) continue; enabled = true; if (encoder->connectors_active) active = true; } WARN(active != crtc->active, "crtc's computed active state doesn't match tracked active state " "(expected %i, found %i)\n", active, crtc->active); WARN(enabled != crtc->base.enabled, "crtc's computed enabled state doesn't match tracked enabled state " "(expected %i, found %i)\n", enabled, crtc->base.enabled); active = dev_priv->display.get_pipe_config(crtc, &pipe_config); list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) { if (encoder->base.crtc != &crtc->base) continue; if (encoder->get_config) encoder->get_config(encoder, &pipe_config); } /* hw state is inconsistent with the pipe A quirk */ if (crtc->pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) active = crtc->active; if (dev_priv->display.get_clock) dev_priv->display.get_clock(crtc, &pipe_config); WARN(crtc->active != active, "crtc active state doesn't match with hw state " "(expected %i, found %i)\n", crtc->active, active); #if 0 if (active && !intel_pipe_config_compare(dev, &crtc->config, &pipe_config)) { WARN(1, "pipe state doesn't match!\n"); intel_dump_pipe_config(crtc, &pipe_config, "[hw state]"); intel_dump_pipe_config(crtc, &crtc->config, "[sw state]"); } #endif } } static void check_shared_dpll_state(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; struct intel_crtc *crtc; struct intel_dpll_hw_state dpll_hw_state; int i; for (i = 0; i < dev_priv->num_shared_dpll; i++) { struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i]; int enabled_crtcs = 0, active_crtcs = 0; bool active; memset(&dpll_hw_state, 0, sizeof(dpll_hw_state)); DRM_DEBUG_KMS("%s\n", pll->name); active = pll->get_hw_state(dev_priv, pll, &dpll_hw_state); WARN(pll->active > pll->refcount, "more active pll users than references: %i vs %i\n", pll->active, pll->refcount); WARN(pll->active && !pll->on, "pll in active use but not on in sw tracking\n"); WARN(pll->on && !pll->active, "pll in on but not on in use in sw tracking\n"); WARN(pll->on != active, "pll on state mismatch (expected %i, found %i)\n", pll->on, active); list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) { if (crtc->base.enabled && intel_crtc_to_shared_dpll(crtc) == pll) enabled_crtcs++; if (crtc->active && intel_crtc_to_shared_dpll(crtc) == pll) active_crtcs++; } WARN(pll->active != active_crtcs, "pll active crtcs mismatch (expected %i, found %i)\n", pll->active, active_crtcs); WARN(pll->refcount != enabled_crtcs, "pll enabled crtcs mismatch (expected %i, found %i)\n", pll->refcount, enabled_crtcs); WARN(pll->on && memcmp(&pll->hw_state, &dpll_hw_state, sizeof(dpll_hw_state)), "pll hw state mismatch\n"); } } void intel_modeset_check_state(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; if (dev_priv->port_disabled_on_unplug) { dev_priv->port_disabled_on_unplug = false; return; } if (dev_priv->is_suspending) return; check_connector_state(dev); check_encoder_state(dev); check_crtc_state(dev); check_shared_dpll_state(dev); } 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; struct drm_display_mode *saved_mode, *saved_hwmode; struct intel_crtc_config *pipe_config = NULL; struct intel_crtc *intel_crtc; unsigned disable_pipes, prepare_pipes, modeset_pipes; int ret = 0; saved_mode = kcalloc(2, sizeof(*saved_mode), GFP_KERNEL); if (!saved_mode) return -ENOMEM; saved_hwmode = saved_mode + 1; intel_modeset_affected_pipes(crtc, &modeset_pipes, &prepare_pipes, &disable_pipes); *saved_hwmode = crtc->hwmode; *saved_mode = crtc->mode; /* Hack: Because we don't (yet) support global modeset on multiple * crtcs, we don't keep track of the new mode for more than one crtc. * Hence simply check whether any bit is set in modeset_pipes in all the * pieces of code that are not yet converted to deal with mutliple crtcs * changing their mode at the same time. */ if (modeset_pipes) { pipe_config = intel_modeset_pipe_config(crtc, fb, mode); if (IS_ERR(pipe_config)) { ret = PTR_ERR(pipe_config); pipe_config = NULL; goto out; } intel_dump_pipe_config(to_intel_crtc(crtc), pipe_config, "[modeset]"); } for_each_intel_crtc_masked(dev, disable_pipes, intel_crtc) intel_crtc_disable(&intel_crtc->base); for_each_intel_crtc_masked(dev, prepare_pipes, intel_crtc) { if (intel_crtc->base.enabled) dev_priv->display.crtc_disable(&intel_crtc->base); } /* DO it only once */ if (IS_VALLEYVIEW(dev)) if (dev_priv->is_first_modeset) { program_pfi_credits(dev_priv, true); dev_priv->is_first_modeset = false; } /* crtc->mode is already used by the ->mode_set callbacks, hence we need * to set it here already despite that we pass it down the callchain. */ if (modeset_pipes) { crtc->mode = *mode; /* mode_set/enable/disable functions rely on a correct pipe * config. */ to_intel_crtc(crtc)->config = *pipe_config; } /* Only after disabling all output pipelines that will be changed can we * update the the output configuration. */ intel_modeset_update_state(dev, prepare_pipes); if (dev_priv->display.modeset_global_resources) dev_priv->display.modeset_global_resources(dev); /* Set up the DPLL and any encoders state that needs to adjust or depend * on the DPLL. */ for_each_intel_crtc_masked(dev, modeset_pipes, intel_crtc) { ret = intel_crtc_mode_set(&intel_crtc->base, x, y, fb); if (ret) goto done; } /* Now enable the clocks, plane, pipe, and connectors that we set up. */ for_each_intel_crtc_masked(dev, prepare_pipes, intel_crtc) dev_priv->display.crtc_enable(&intel_crtc->base); if (modeset_pipes) { /* Store real post-adjustment hardware mode. */ crtc->hwmode = pipe_config->adjusted_mode; /* Calculate and store various constants which * are later needed by vblank and swap-completion * timestamping. They are derived from true hwmode. */ drm_calc_timestamping_constants(crtc); } /* FIXME: add subpixel order */ done: if (ret && crtc->enabled) { crtc->hwmode = *saved_hwmode; crtc->mode = *saved_mode; } out: kfree(pipe_config); kfree(saved_mode); return ret; } static 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); } #undef for_each_intel_crtc_masked static void intel_set_config_free(struct intel_set_config *config) { if (!config) return; kfree(config->save_connector_encoders); kfree(config->save_encoder_crtcs); kfree(config); } static int intel_set_config_save_state(struct drm_device *dev, struct intel_set_config *config) { struct drm_encoder *encoder; struct drm_connector *connector; int count; config->save_encoder_crtcs = kcalloc(dev->mode_config.num_encoder, sizeof(struct drm_crtc *), GFP_KERNEL); if (!config->save_encoder_crtcs) return -ENOMEM; config->save_connector_encoders = kcalloc(dev->mode_config.num_connector, sizeof(struct drm_encoder *), GFP_KERNEL); if (!config->save_connector_encoders) return -ENOMEM; /* Copy data. Note that driver private data is not affected. * Should anything bad happen only the expected state is * restored, not the drivers personal bookkeeping. */ count = 0; list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { config->save_encoder_crtcs[count++] = encoder->crtc; } count = 0; list_for_each_entry(connector, &dev->mode_config.connector_list, head) { config->save_connector_encoders[count++] = connector->encoder; } return 0; } static void intel_set_config_restore_state(struct drm_device *dev, struct intel_set_config *config) { struct intel_encoder *encoder; struct intel_connector *connector; int count; count = 0; list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) { encoder->new_crtc = to_intel_crtc(config->save_encoder_crtcs[count++]); } count = 0; list_for_each_entry(connector, &dev->mode_config.connector_list, base.head) { connector->new_encoder = to_intel_encoder(config->save_connector_encoders[count++]); } } static bool is_crtc_connector_off(struct drm_mode_set *set) { int i; if (set->num_connectors == 0) return false; if (WARN_ON(set->connectors == NULL)) return false; for (i = 0; i < set->num_connectors; i++) if (set->connectors[i]->encoder && set->connectors[i]->encoder->crtc == set->crtc && set->connectors[i]->dpms != DRM_MODE_DPMS_ON) return true; return false; } static void intel_set_config_compute_mode_changes(struct drm_mode_set *set, struct intel_set_config *config) { /* We should be able to check here if the fb has the same properties * and then just flip_or_move it */ if (is_crtc_connector_off(set)) { config->mode_changed = true; } else if (set->crtc->fb != set->fb) { /* If we have no fb then treat it as a full mode set */ if (set->crtc->fb == NULL) { struct intel_crtc *intel_crtc = to_intel_crtc(set->crtc); if (intel_crtc->active && i915_fastboot) { DRM_DEBUG_KMS("crtc has no fb, will flip\n"); config->fb_changed = true; } else { DRM_DEBUG_KMS("inactive crtc, full mode set\n"); config->mode_changed = true; } } else if (set->fb == NULL) { config->mode_changed = true; } else if (set->fb->pixel_format != set->crtc->fb->pixel_format) { config->mode_changed = true; } else { config->fb_changed = true; } } if (set->fb && (set->x != set->crtc->x || set->y != set->crtc->y)) config->fb_changed = true; if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) { DRM_DEBUG_KMS("modes are different, full mode set\n"); drm_mode_debug_printmodeline(&set->crtc->mode); drm_mode_debug_printmodeline(set->mode); config->mode_changed = true; } DRM_DEBUG_KMS("computed changes for [CRTC:%d], mode_changed=%d, fb_changed=%d\n", set->crtc->base.id, config->mode_changed, config->fb_changed); } static int intel_modeset_stage_output_state(struct drm_device *dev, struct drm_mode_set *set, struct intel_set_config *config) { struct drm_crtc *new_crtc; struct intel_connector *connector; struct intel_encoder *encoder; int ro; /* The upper layers ensure that we either disable a crtc or have a list * of connectors. For paranoia, double-check this. */ WARN_ON(!set->fb && (set->num_connectors != 0)); WARN_ON(set->fb && (set->num_connectors == 0)); list_for_each_entry(connector, &dev->mode_config.connector_list, base.head) { /* Otherwise traverse passed in connector list and get encoders * for them. */ for (ro = 0; ro < set->num_connectors; ro++) { if (set->connectors[ro] == &connector->base) { connector->new_encoder = connector->encoder; break; } } /* If we disable the crtc, disable all its connectors. Also, if * the connector is on the changing crtc but not on the new * connector list, disable it. */ if ((!set->fb || ro == set->num_connectors) && connector->base.encoder && connector->base.encoder->crtc == set->crtc) { connector->new_encoder = NULL; DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [NOCRTC]\n", connector->base.base.id, drm_get_connector_name(&connector->base)); } if (&connector->new_encoder->base != connector->base.encoder) { DRM_DEBUG_KMS("encoder changed, full mode switch\n"); config->mode_changed = true; } } /* connector->new_encoder is now updated for all connectors. */ /* Update crtc of enabled connectors. */ list_for_each_entry(connector, &dev->mode_config.connector_list, base.head) { if (!connector->new_encoder) continue; new_crtc = connector->new_encoder->base.crtc; for (ro = 0; ro < set->num_connectors; ro++) { if (set->connectors[ro] == &connector->base) new_crtc = set->crtc; } /* Make sure the new CRTC will work with the encoder */ if (!intel_encoder_crtc_ok(&connector->new_encoder->base, new_crtc)) { return -EINVAL; } connector->encoder->new_crtc = to_intel_crtc(new_crtc); DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [CRTC:%d]\n", connector->base.base.id, drm_get_connector_name(&connector->base), new_crtc->base.id); } /* Check for any encoders that needs to be disabled. */ list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) { list_for_each_entry(connector, &dev->mode_config.connector_list, base.head) { if (connector->new_encoder == encoder) { WARN_ON(!connector->new_encoder->new_crtc); goto next_encoder; } } encoder->new_crtc = NULL; next_encoder: /* Only now check for crtc changes so we don't miss encoders * that will be disabled. */ if (&encoder->new_crtc->base != encoder->base.crtc) { DRM_DEBUG_KMS("crtc changed, full mode switch\n"); config->mode_changed = true; } } /* Now we've also updated encoder->new_crtc for all encoders. */ return 0; } static int intel_crtc_set_config(struct drm_mode_set *set) { struct drm_device *dev; struct drm_mode_set save_set; struct intel_set_config *config; int ret; BUG_ON(!set); BUG_ON(!set->crtc); BUG_ON(!set->crtc->helper_private); /* Enforce sane interface api - has been abused by the fb helper. */ BUG_ON(!set->mode && set->fb); BUG_ON(set->fb && set->num_connectors == 0); if (set->fb) { DRM_DEBUG_KMS("[CRTC:%d] [FB:%d] #connectors=%d (x y) (%i %i)\n", set->crtc->base.id, set->fb->base.id, (int)set->num_connectors, set->x, set->y); } else { DRM_DEBUG_KMS("[CRTC:%d] [NOFB]\n", set->crtc->base.id); } dev = set->crtc->dev; ret = -ENOMEM; config = kzalloc(sizeof(*config), GFP_KERNEL); if (!config) return ret; ret = intel_set_config_save_state(dev, config); if (ret) goto out_config; save_set.crtc = set->crtc; save_set.mode = &set->crtc->mode; save_set.x = set->crtc->x; save_set.y = set->crtc->y; save_set.fb = set->crtc->fb; /* Identifying the Media Playback DRRS request */ if (is_media_playback_drrs_request(set)) { /* While requesting for Media Playback DRRS Userspace should * make sure that fb passed is same as that is in use. * Else at successful drrs request, we will hit a warn_on on * return path for fb mismatch */ ret = intel_media_playback_drrs_configure(dev, set->mode); goto out_config; } /* Compute whether we need a full modeset, only an fb base update or no * change at all. In the future we might also check whether only the * mode changed, e.g. for LVDS where we only change the panel fitter in * such cases. */ intel_set_config_compute_mode_changes(set, config); ret = intel_modeset_stage_output_state(dev, set, config); if (ret) goto fail; if (config->mode_changed) { ret = intel_set_mode(set->crtc, set->mode, set->x, set->y, set->fb); } else if (config->fb_changed) { intel_crtc_wait_for_pending_flips(set->crtc); ret = intel_pipe_set_base(set->crtc, set->x, set->y, set->fb); } if (ret) { DRM_DEBUG_KMS("failed to set mode on [CRTC:%d], err = %d\n", set->crtc->base.id, ret); fail: intel_set_config_restore_state(dev, config); /* Try to restore the config */ if (config->mode_changed && intel_set_mode(save_set.crtc, save_set.mode, save_set.x, save_set.y, save_set.fb)) DRM_ERROR("failed to restore config after modeset failure\n"); } out_config: intel_set_config_free(config); return ret; } static const struct drm_crtc_funcs intel_crtc_funcs = { .cursor_set = intel_crtc_cursor_set, .cursor_move = intel_crtc_cursor_move, .gamma_set = intel_crtc_gamma_set, .set_config = intel_crtc_set_config, .destroy = intel_crtc_destroy, .page_flip = intel_crtc_page_flip, .set_display = intel_crtc_set_display, }; static void intel_cpu_pll_init(struct drm_device *dev) { if (HAS_DDI(dev)) intel_ddi_pll_init(dev); } static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv, struct intel_shared_dpll *pll, struct intel_dpll_hw_state *hw_state) { uint32_t val; val = I915_READ(PCH_DPLL(pll->id)); hw_state->dpll = val; hw_state->fp0 = I915_READ(PCH_FP0(pll->id)); hw_state->fp1 = I915_READ(PCH_FP1(pll->id)); return val & DPLL_VCO_ENABLE; } static void ibx_pch_dpll_mode_set(struct drm_i915_private *dev_priv, struct intel_shared_dpll *pll) { I915_WRITE(PCH_FP0(pll->id), pll->hw_state.fp0); I915_WRITE(PCH_FP1(pll->id), pll->hw_state.fp1); } static void ibx_pch_dpll_enable(struct drm_i915_private *dev_priv, struct intel_shared_dpll *pll) { /* PCH refclock must be enabled first */ assert_pch_refclk_enabled(dev_priv); I915_WRITE(PCH_DPLL(pll->id), pll->hw_state.dpll); /* Wait for the clocks to stabilize. */ POSTING_READ(PCH_DPLL(pll->id)); udelay(150); /* The pixel multiplier can only be updated once the * DPLL is enabled and the clocks are stable. * * So write it again. */ I915_WRITE(PCH_DPLL(pll->id), pll->hw_state.dpll); POSTING_READ(PCH_DPLL(pll->id)); udelay(200); } static void ibx_pch_dpll_disable(struct drm_i915_private *dev_priv, struct intel_shared_dpll *pll) { struct drm_device *dev = dev_priv->dev; struct intel_crtc *crtc; /* Make sure no transcoder isn't still depending on us. */ list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) { if (intel_crtc_to_shared_dpll(crtc) == pll) assert_pch_transcoder_disabled(dev_priv, crtc->pipe); } I915_WRITE(PCH_DPLL(pll->id), 0); POSTING_READ(PCH_DPLL(pll->id)); udelay(200); } static char *ibx_pch_dpll_names[] = { "PCH DPLL A", "PCH DPLL B", }; static void ibx_pch_dpll_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; int i; dev_priv->num_shared_dpll = 2; for (i = 0; i < dev_priv->num_shared_dpll; i++) { dev_priv->shared_dplls[i].id = i; dev_priv->shared_dplls[i].name = ibx_pch_dpll_names[i]; dev_priv->shared_dplls[i].mode_set = ibx_pch_dpll_mode_set; dev_priv->shared_dplls[i].enable = ibx_pch_dpll_enable; dev_priv->shared_dplls[i].disable = ibx_pch_dpll_disable; dev_priv->shared_dplls[i].get_hw_state = ibx_pch_dpll_get_hw_state; } } static void intel_shared_dpll_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) ibx_pch_dpll_init(dev); else dev_priv->num_shared_dpll = 0; BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS); DRM_DEBUG_KMS("%i shared PLLs initialized\n", dev_priv->num_shared_dpll); } extern void intel_cancel_fbc_work(struct drm_i915_private *dev_priv); static int display_disable_wq(struct drm_device *drm_dev) { struct drm_i915_private *dev_priv = drm_dev->dev_private; /*struct drm_crtc *crtc; struct intel_encoder *intel_encoder;*/ cancel_work_sync(&dev_priv->hotplug_work); //intel_cancel_fbc_work(dev_priv); /* Uncomment this once HDMI audio code is integrated */ /* cancel_work_sync(&dev_priv->hdmi_audio_wq); */ /*list_for_each_entry(crtc, &drm_dev->mode_config.crtc_list, head) { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); for_each_encoder_on_crtc(drm_dev, crtc, intel_encoder) { struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base); if (intel_dp) cancel_delayed_work_sync( &intel_dp->panel_vdd_work); } }*/ /* No need to explictly flush the flipwq here. There is already * a wait for pending flips to get completed in crtc_disable, * and that wait will be over only when the pending flip work * items, if any, gets scheduled & a corresponding flip done * interrupt is generated. * And once the wait for pending flips in crtc_disable is completed * & crtc itself is also disabled, no new flip calls will be * accepted(TBD??) which can queue new flip work items. */ return 0; } enum {SAVEHPD, RESTOREHPD}; static void display_save_restore_hotplug(struct drm_device *drm_dev, int flag) { struct drm_i915_private *dev_priv = drm_dev->dev_private; u32 hotplug_en; if (flag == SAVEHPD) { hotplug_en = I915_READ(PORT_HOTPLUG_EN); dev_priv->hotplugstat = hotplug_en; hotplug_en &= ~(HDMIB_HOTPLUG_INT_EN | HDMIC_HOTPLUG_INT_EN | HDMID_HOTPLUG_INT_EN | SDVOB_HOTPLUG_INT_EN | SDVOC_HOTPLUG_INT_EN); I915_WRITE(PORT_HOTPLUG_EN, hotplug_en); } else if (flag == RESTOREHPD) I915_WRITE(PORT_HOTPLUG_EN, dev_priv->hotplugstat); } ssize_t display_runtime_suspend(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct drm_crtc *crtc; dev_priv->is_suspending = true; dev_priv->audio_suspended = mid_hdmi_audio_suspend(dev); if (!dev_priv->audio_suspended) DRM_ERROR("Audio active, CRTC will not be suspended\n"); /* Save Hue/Saturation/Brightness/Contrast status */ intel_save_clr_mgr_status(dev); dev_priv->dpst.state = dev_priv->dpst.enabled; if (dev_priv->dpst.state) i915_dpst_disable_hist_interrupt(dev, true); /* ignore lid events during suspend */ mutex_lock(&dev_priv->modeset_restore_lock); dev_priv->modeset_restore = MODESET_SUSPENDED; mutex_unlock(&dev_priv->modeset_restore_lock); drm_kms_helper_poll_disable(dev); display_save_restore_hotplug(dev, SAVEHPD); display_disable_wq(dev); drm_modeset_lock_all(dev); dev_priv->s0ixstat = true; /* If KMS is active, we do the leavevt stuff here */ if (drm_core_check_feature(dev, DRIVER_MODESET)) { dev_priv->enable_hotplug_processing = false; /* * Disable CRTCs directly since we want to preserve sw state * for _thaw. */ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); if ((intel_crtc->pipe == PIPE_B) && (!dev_priv->audio_suspended)) continue; dev_priv->display.crtc_disable(crtc); } } dev_priv->s0ixstat = false; drm_modeset_unlock_all(dev); i915_rpm_put_disp(dev); if (!dev_priv->audio_suspended) { DRM_DEBUG_DRIVER("Not suspending display since audio is active\n"); return -1; } return 0; } extern void intel_resume_hotplug(struct drm_device *dev); ssize_t display_runtime_resume(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; i915_rpm_get_disp(dev); dev_priv->s0ixstat = true; dev_priv->late_resume = true; /* * DO NOT Move it from here * HOTPLUG_EN needs to be enabled for reading LIVE STATUS */ display_save_restore_hotplug(dev, RESTOREHPD); /* KMS EnterVT equivalent */ if (drm_core_check_feature(dev, DRIVER_MODESET)) { drm_modeset_lock_all(dev); /* For Bending/Spread controls */ if (check_live_status(dev_priv) == false) dev_priv->unplug = true; intel_modeset_setup_hw_state(dev, true); drm_modeset_unlock_all(dev); /* * ... but also need to make sure that hotplug processing * doesn't cause havoc. Like in the driver load code we don't * bother with the tiny race here where we might loose hotplug * notifications. * */ intel_hpd_init(dev); dev_priv->enable_hotplug_processing = true; /* Config may have changed between suspend and resume */ intel_resume_hotplug(dev); } drm_kms_helper_poll_enable(dev); mid_hdmi_audio_resume(dev); /* Restore Gamma/Csc/Hue/Saturation/Brightness/Contrast */ if (!intel_restore_clr_mgr_status(dev)) DRM_ERROR("Restore Color manager status failed"); dev_priv->late_resume = false; dev_priv->is_resuming = false; dev_priv->s0ixstat = false; i915_dpst_set_default_luma(dev); if (dev_priv->dpst.state) i915_dpst_enable_hist_interrupt(dev, true); DRM_DEBUG_PM("Value in iClk5val = %x\n", vlv_ccu_read(dev_priv, CCU_ICLK5_REG)); DRM_DEBUG_PM("Value in iClkgtval = %x\n", vlv_ccu_read(dev_priv, CCU_ICLK_GATE_CTRL_REG)); return 0; } static void intel_crtc_init(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc; int i; struct intel_program_clock_bending clockbend; struct intel_program_clock_spread clockspread; intel_crtc = kzalloc(sizeof(struct intel_crtc) + (INTELFB_CONN_LIMIT * sizeof(struct drm_connector *)), GFP_KERNEL); if (intel_crtc == NULL) return; drm_crtc_init(dev, &intel_crtc->base, &intel_crtc_funcs); drm_mode_crtc_set_gamma_size(&intel_crtc->base, 256); for (i = 0; i < 256; i++) { intel_crtc->lut_r[i] = i; intel_crtc->lut_g[i] = i; intel_crtc->lut_b[i] = i; } /* Swap pipes & planes for FBC on pre-965 */ intel_crtc->pipe = pipe; intel_crtc->plane = pipe; if (IS_MOBILE(dev) && IS_GEN3(dev)) { DRM_DEBUG_KMS("swapping pipes & planes for FBC\n"); intel_crtc->plane = !pipe; } BUG_ON(pipe >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) || dev_priv->plane_to_crtc_mapping[intel_crtc->plane] != NULL); dev_priv->plane_to_crtc_mapping[intel_crtc->plane] = &intel_crtc->base; dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = &intel_crtc->base; dev_priv->s0ixstat = false; /* Keep the s0ixstat false initially */ intel_crtc->s0ix_suspend_state = false; intel_crtc->rotate180 = false; drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs); intel_crtc->sprite_unpin_work = NULL; /* Disable both bend spread initially */ dev_priv->clockspread = false; dev_priv->clockbend = false; dev_priv->unplug = true; dev_priv->audio_suspended = true; valleyview_program_clock_bending( dev_priv, &clockbend); valleyview_program_clock_spread( dev_priv, &clockspread); intel_crtc->base.panning_en = false; intel_crtc->scaling_src_size = 0; intel_crtc->pfit_en_status = false; intel_crtc->dummy_flip = false; /* * TODO: Assigning PFIT to LFP */ I915_WRITE(PFIT_CONTROL, 0); dev_priv->pfit_pipe = 0; } int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, struct drm_file *file) { struct drm_i915_get_pipe_from_crtc_id *pipe_from_crtc_id = data; struct drm_mode_object *drmmode_obj; struct intel_crtc *crtc; if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -ENODEV; drmmode_obj = drm_mode_object_find(dev, pipe_from_crtc_id->crtc_id, DRM_MODE_OBJECT_CRTC); if (!drmmode_obj) { DRM_ERROR("no such CRTC id\n"); return -EINVAL; } crtc = to_intel_crtc(obj_to_crtc(drmmode_obj)); pipe_from_crtc_id->pipe = crtc->pipe; return 0; } static int intel_encoder_clones(struct intel_encoder *encoder) { struct drm_device *dev = encoder->base.dev; struct intel_encoder *source_encoder; int index_mask = 0; int entry = 0; list_for_each_entry(source_encoder, &dev->mode_config.encoder_list, base.head) { if (encoder == source_encoder) index_mask |= (1 << entry); /* Intel hw has only one MUX where enocoders could be cloned. */ if (encoder->cloneable && source_encoder->cloneable) index_mask |= (1 << entry); entry++; } return index_mask; } static bool has_edp_a(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; if (!IS_MOBILE(dev)) return false; if ((I915_READ(DP_A) & DP_DETECTED) == 0) return false; if (IS_GEN5(dev) && (I915_READ(ILK_DISPLAY_CHICKEN_FUSES) & ILK_eDP_A_DISABLE)) return false; return true; } static void intel_setup_outputs(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_encoder *encoder; bool dpd_is_edp = false; intel_lvds_init(dev); if (!IS_ULT(dev) && !IS_VALLEYVIEW(dev)) intel_crt_init(dev); if (HAS_DDI(dev)) { int found; /* Haswell uses DDI functions to detect digital outputs */ found = I915_READ(DDI_BUF_CTL_A) & DDI_INIT_DISPLAY_DETECTED; /* DDI A only supports eDP */ if (found) intel_ddi_init(dev, PORT_A); /* DDI B, C and D detection is indicated by the SFUSE_STRAP * register */ found = I915_READ(SFUSE_STRAP); if (found & SFUSE_STRAP_DDIB_DETECTED) intel_ddi_init(dev, PORT_B); if (found & SFUSE_STRAP_DDIC_DETECTED) intel_ddi_init(dev, PORT_C); if (found & SFUSE_STRAP_DDID_DETECTED) intel_ddi_init(dev, PORT_D); } else if (HAS_PCH_SPLIT(dev)) { int found; dpd_is_edp = intel_dpd_is_edp(dev); if (has_edp_a(dev)) intel_dp_init(dev, DP_A, PORT_A); if (I915_READ(PCH_HDMIB) & SDVO_DETECTED) { /* PCH SDVOB multiplex with HDMIB */ found = intel_sdvo_init(dev, PCH_SDVOB, true); if (!found) intel_hdmi_init(dev, PCH_HDMIB, PORT_B); if (!found && (I915_READ(PCH_DP_B) & DP_DETECTED)) intel_dp_init(dev, PCH_DP_B, PORT_B); } if (I915_READ(PCH_HDMIC) & SDVO_DETECTED) intel_hdmi_init(dev, PCH_HDMIC, PORT_C); if (!dpd_is_edp && I915_READ(PCH_HDMID) & SDVO_DETECTED) intel_hdmi_init(dev, PCH_HDMID, PORT_D); if (I915_READ(PCH_DP_C) & DP_DETECTED) intel_dp_init(dev, PCH_DP_C, PORT_C); if (I915_READ(PCH_DP_D) & DP_DETECTED) intel_dp_init(dev, PCH_DP_D, PORT_D); } else if (IS_VALLEYVIEW(dev)) { /* In VLV A0 board after rework there is HDMI on PORT B and * either of DP or eDP on Port C * * Enable both for now as we know that VLV Baylake supports * both. * * eDP Vs MIPI detection is based on VBT */ if (dev_priv->is_mipi_from_vbt) intel_dsi_init(dev); else intel_dp_init(dev, VLV_DISPLAY_BASE + DP_C, PORT_C); intel_hdmi_init(dev, VLV_DISPLAY_BASE + GEN4_HDMIB, PORT_B); } else if (SUPPORTS_DIGITAL_OUTPUTS(dev)) { bool found = false; if (I915_READ(GEN3_SDVOB) & SDVO_DETECTED) { DRM_DEBUG_KMS("probing SDVOB\n"); found = intel_sdvo_init(dev, GEN3_SDVOB, true); if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) { DRM_DEBUG_KMS("probing HDMI on SDVOB\n"); intel_hdmi_init(dev, GEN4_HDMIB, PORT_B); } if (!found && SUPPORTS_INTEGRATED_DP(dev)) intel_dp_init(dev, DP_B, PORT_B); } /* Before G4X SDVOC doesn't have its own detect register */ if (I915_READ(GEN3_SDVOB) & SDVO_DETECTED) { DRM_DEBUG_KMS("probing SDVOC\n"); found = intel_sdvo_init(dev, GEN3_SDVOC, false); } if (!found && (I915_READ(GEN3_SDVOC) & SDVO_DETECTED)) { if (SUPPORTS_INTEGRATED_HDMI(dev)) { DRM_DEBUG_KMS("probing HDMI on SDVOC\n"); intel_hdmi_init(dev, GEN4_HDMIC, PORT_C); } if (SUPPORTS_INTEGRATED_DP(dev)) intel_dp_init(dev, DP_C, PORT_C); } if (SUPPORTS_INTEGRATED_DP(dev) && (I915_READ(DP_D) & DP_DETECTED)) intel_dp_init(dev, DP_D, PORT_D); } else if (IS_GEN2(dev)) intel_dvo_init(dev); if (SUPPORTS_TV(dev)) intel_tv_init(dev); list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) { encoder->base.possible_crtcs = encoder->crtc_mask; encoder->base.possible_clones = intel_encoder_clones(encoder); } intel_init_pch_refclk(dev); drm_helper_move_panel_connectors_to_head(dev); } void intel_framebuffer_fini(struct intel_framebuffer *fb) { drm_framebuffer_cleanup(&fb->base); drm_gem_object_unreference_unlocked(&fb->obj->base); } static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb) { struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); intel_fb->obj->user_fb = 0; intel_framebuffer_fini(intel_fb); kfree(intel_fb); } static int intel_user_framebuffer_create_handle(struct drm_framebuffer *fb, struct drm_file *file, unsigned int *handle) { struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); struct drm_i915_gem_object *obj = intel_fb->obj; return drm_gem_handle_create(file, &obj->base, handle); } static const struct drm_framebuffer_funcs intel_fb_funcs = { .destroy = intel_user_framebuffer_destroy, .create_handle = intel_user_framebuffer_create_handle, }; int intel_framebuffer_init(struct drm_device *dev, struct intel_framebuffer *intel_fb, struct drm_mode_fb_cmd2 *mode_cmd, struct drm_i915_gem_object *obj) { int pitch_limit; int ret; if (obj->tiling_mode == I915_TILING_Y) { DRM_DEBUG("hardware does not support tiling Y\n"); return -EINVAL; } if (mode_cmd->pitches[0] & 63) { DRM_DEBUG("pitch (%d) must be at least 64 byte aligned\n", mode_cmd->pitches[0]); return -EINVAL; } if (INTEL_INFO(dev)->gen >= 5 && !IS_VALLEYVIEW(dev)) { pitch_limit = 32*1024; } else if (INTEL_INFO(dev)->gen >= 4) { if (obj->tiling_mode) pitch_limit = 16*1024; else pitch_limit = 32*1024; } else if (INTEL_INFO(dev)->gen >= 3) { if (obj->tiling_mode) pitch_limit = 8*1024; else pitch_limit = 16*1024; } else /* XXX DSPC is limited to 4k tiled */ pitch_limit = 8*1024; if (mode_cmd->pitches[0] > pitch_limit) { DRM_DEBUG("%s pitch (%d) must be at less than %d\n", obj->tiling_mode ? "tiled" : "linear", mode_cmd->pitches[0], pitch_limit); return -EINVAL; } if (obj->tiling_mode != I915_TILING_NONE && mode_cmd->pitches[0] != obj->stride) { DRM_DEBUG("pitch (%d) must match tiling stride (%d)\n", mode_cmd->pitches[0], obj->stride); return -EINVAL; } /* Reject formats not supported by any plane early. */ switch (mode_cmd->pixel_format) { case DRM_FORMAT_C8: case DRM_FORMAT_RGB565: case DRM_FORMAT_XRGB8888: case DRM_FORMAT_ARGB8888: break; case DRM_FORMAT_XRGB1555: case DRM_FORMAT_ARGB1555: if (INTEL_INFO(dev)->gen > 3) { DRM_DEBUG("unsupported pixel format: %s\n", drm_get_format_name(mode_cmd->pixel_format)); return -EINVAL; } break; case DRM_FORMAT_XBGR8888: case DRM_FORMAT_ABGR8888: case DRM_FORMAT_XRGB2101010: case DRM_FORMAT_ARGB2101010: case DRM_FORMAT_XBGR2101010: case DRM_FORMAT_ABGR2101010: if (INTEL_INFO(dev)->gen < 4) { DRM_DEBUG("unsupported pixel format: %s\n", drm_get_format_name(mode_cmd->pixel_format)); return -EINVAL; } break; case DRM_FORMAT_YUYV: case DRM_FORMAT_UYVY: case DRM_FORMAT_YVYU: case DRM_FORMAT_VYUY: if (INTEL_INFO(dev)->gen < 5) { DRM_DEBUG("unsupported pixel format: %s\n", drm_get_format_name(mode_cmd->pixel_format)); return -EINVAL; } break; default: DRM_DEBUG("unsupported pixel format: %s\n", drm_get_format_name(mode_cmd->pixel_format)); return -EINVAL; } /* FIXME need to adjust LINOFF/TILEOFF accordingly. */ if (mode_cmd->offsets[0] != 0) return -EINVAL; drm_helper_mode_fill_fb_struct(&intel_fb->base, mode_cmd); intel_fb->obj = obj; ret = drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs); if (ret) { DRM_ERROR("framebuffer init failed %d\n", ret); return ret; } return 0; } static struct drm_framebuffer * intel_user_framebuffer_create(struct drm_device *dev, struct drm_file *filp, struct drm_mode_fb_cmd2 *mode_cmd) { struct drm_i915_gem_object *obj; obj = to_intel_bo(drm_gem_object_lookup(dev, filp, mode_cmd->handles[0])); if (&obj->base == NULL) return ERR_PTR(-ENOENT); obj->user_fb = 1; if (obj->tiling_mode == I915_TILING_X) { /* Tiled(X) Scanout buffers are more suitable for allocation from stolen area, as its very unlikely that they will be accessed directly from the CPU side and any allocation from stolen area is not directly CPU accessible, only through the aperture space it can be accessed */ i915_gem_object_move_to_stolen(obj); } return intel_framebuffer_create(dev, mode_cmd, obj); } static const struct drm_mode_config_funcs intel_mode_funcs = { .fb_create = intel_user_framebuffer_create, .output_poll_changed = intel_fb_output_poll_changed, }; /* Set up chip specific display functions */ static void intel_init_display(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; if (HAS_PCH_SPLIT(dev) || IS_G4X(dev)) dev_priv->display.find_dpll = g4x_find_best_dpll; else if (IS_VALLEYVIEW(dev)) dev_priv->display.find_dpll = vlv_find_best_dpll; else if (IS_PINEVIEW(dev)) dev_priv->display.find_dpll = pnv_find_best_dpll; else dev_priv->display.find_dpll = i9xx_find_best_dpll; if (HAS_DDI(dev)) { dev_priv->display.get_pipe_config = haswell_get_pipe_config; dev_priv->display.crtc_mode_set = haswell_crtc_mode_set; dev_priv->display.crtc_enable = haswell_crtc_enable; dev_priv->display.crtc_disable = haswell_crtc_disable; dev_priv->display.off = haswell_crtc_off; dev_priv->display.update_plane = ironlake_update_plane; } else if (HAS_PCH_SPLIT(dev)) { dev_priv->display.get_pipe_config = ironlake_get_pipe_config; dev_priv->display.get_clock = ironlake_crtc_clock_get; dev_priv->display.crtc_mode_set = ironlake_crtc_mode_set; dev_priv->display.crtc_enable = ironlake_crtc_enable; dev_priv->display.crtc_disable = ironlake_crtc_disable; dev_priv->display.off = ironlake_crtc_off; dev_priv->display.update_plane = ironlake_update_plane; } else if (IS_VALLEYVIEW(dev)) { dev_priv->display.get_pipe_config = i9xx_get_pipe_config; dev_priv->display.get_clock = i9xx_crtc_clock_get; dev_priv->display.crtc_mode_set = i9xx_crtc_mode_set; dev_priv->display.crtc_enable = valleyview_crtc_enable; dev_priv->display.crtc_disable = i9xx_crtc_disable; dev_priv->display.off = i9xx_crtc_off; dev_priv->display.update_plane = i9xx_update_plane; } else { dev_priv->display.get_pipe_config = i9xx_get_pipe_config; dev_priv->display.get_clock = i9xx_crtc_clock_get; dev_priv->display.crtc_mode_set = i9xx_crtc_mode_set; dev_priv->display.crtc_enable = i9xx_crtc_enable; dev_priv->display.crtc_disable = i9xx_crtc_disable; dev_priv->display.off = i9xx_crtc_off; dev_priv->display.update_plane = i9xx_update_plane; } /* Returns the core display clock speed */ if (IS_VALLEYVIEW(dev)) dev_priv->display.get_display_clock_speed = valleyview_get_display_clock_speed; else if (IS_I945G(dev) || (IS_G33(dev) && !IS_PINEVIEW_M(dev))) dev_priv->display.get_display_clock_speed = i945_get_display_clock_speed; else if (IS_I915G(dev)) dev_priv->display.get_display_clock_speed = i915_get_display_clock_speed; else if (IS_I945GM(dev) || IS_845G(dev)) dev_priv->display.get_display_clock_speed = i9xx_misc_get_display_clock_speed; else if (IS_PINEVIEW(dev)) dev_priv->display.get_display_clock_speed = pnv_get_display_clock_speed; else if (IS_I915GM(dev)) dev_priv->display.get_display_clock_speed = i915gm_get_display_clock_speed; else if (IS_I865G(dev)) dev_priv->display.get_display_clock_speed = i865_get_display_clock_speed; else if (IS_I85X(dev)) dev_priv->display.get_display_clock_speed = i855_get_display_clock_speed; else /* 852, 830 */ dev_priv->display.get_display_clock_speed = i830_get_display_clock_speed; if (HAS_PCH_SPLIT(dev)) { if (IS_GEN5(dev)) { dev_priv->display.fdi_link_train = ironlake_fdi_link_train; dev_priv->display.write_eld = ironlake_write_eld; } else if (IS_GEN6(dev)) { dev_priv->display.fdi_link_train = gen6_fdi_link_train; dev_priv->display.write_eld = ironlake_write_eld; } else if (IS_IVYBRIDGE(dev)) { /* FIXME: detect B0+ stepping and use auto training */ dev_priv->display.fdi_link_train = ivb_manual_fdi_link_train; dev_priv->display.write_eld = ironlake_write_eld; dev_priv->display.modeset_global_resources = ivb_modeset_global_resources; } else if (IS_HASWELL(dev)) { dev_priv->display.fdi_link_train = hsw_fdi_link_train; dev_priv->display.write_eld = haswell_write_eld; dev_priv->display.modeset_global_resources = haswell_modeset_global_resources; } } else if (IS_G4X(dev)) { dev_priv->display.write_eld = g4x_write_eld; } /* 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; } if (IS_VALLEYVIEW(dev)) dev_priv->display.queue_flip = intel_gen7_queue_mmio_flip; } /* * Some BIOSes insist on assuming the GPU's pipe A is enabled at suspend, * resume, or other times. This quirk makes sure that's the case for * affected systems. */ static void quirk_pipea_force(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; dev_priv->quirks |= QUIRK_PIPEA_FORCE; DRM_INFO("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; DRM_INFO("applying lvds SSC disable quirk\n"); } /* * A machine (e.g. Acer Aspire 5734Z) may need to invert the panel backlight * brightness value */ static void quirk_invert_brightness(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; dev_priv->quirks |= QUIRK_INVERT_BRIGHTNESS; DRM_INFO("applying inverted panel brightness quirk\n"); } /* * Some machines (Dell XPS13) suffer broken backlight controls if * BLM_PCH_PWM_ENABLE is set. */ static void quirk_no_pcm_pwm_enable(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; dev_priv->quirks |= QUIRK_NO_PCH_PWM_ENABLE; DRM_INFO("applying no-PCH_PWM_ENABLE quirk\n"); } struct intel_quirk { int device; int subsystem_vendor; int subsystem_device; void (*hook)(struct drm_device *dev); }; /* For systems that don't have a meaningful PCI subdevice/subvendor ID */ struct intel_dmi_quirk { void (*hook)(struct drm_device *dev); const struct dmi_system_id (*dmi_id_list)[]; }; static int intel_dmi_reverse_brightness(const struct dmi_system_id *id) { DRM_INFO("Backlight polarity reversed on %s\n", id->ident); return 1; } static const struct intel_dmi_quirk intel_dmi_quirks[] = { { .dmi_id_list = &(const struct dmi_system_id[]) { { .callback = intel_dmi_reverse_brightness, .ident = "NCR Corporation", .matches = {DMI_MATCH(DMI_SYS_VENDOR, "NCR Corporation"), DMI_MATCH(DMI_PRODUCT_NAME, ""), }, }, { } /* terminating entry */ }, .hook = quirk_invert_brightness, }, }; static struct intel_quirk intel_quirks[] = { /* HP Mini needs pipe A force quirk (LP: #322104) */ { 0x27ae, 0x103c, 0x361a, quirk_pipea_force }, /* Toshiba Protege R-205, S-209 needs pipe A force quirk */ { 0x2592, 0x1179, 0x0001, quirk_pipea_force }, /* ThinkPad T60 needs pipe A force quirk (bug #16494) */ { 0x2782, 0x17aa, 0x201a, quirk_pipea_force }, /* 830/845 need to leave pipe A & dpll A up */ { 0x2562, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force }, { 0x3577, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force }, /* Lenovo U160 cannot use SSC on LVDS */ { 0x0046, 0x17aa, 0x3920, quirk_ssc_force_disable }, /* Sony Vaio Y cannot use SSC on LVDS */ { 0x0046, 0x104d, 0x9076, quirk_ssc_force_disable }, /* Acer Aspire 5734Z must invert backlight brightness */ { 0x2a42, 0x1025, 0x0459, quirk_invert_brightness }, /* Acer/eMachines G725 */ { 0x2a42, 0x1025, 0x0210, quirk_invert_brightness }, /* Acer/eMachines e725 */ { 0x2a42, 0x1025, 0x0212, quirk_invert_brightness }, /* Acer/Packard Bell NCL20 */ { 0x2a42, 0x1025, 0x034b, quirk_invert_brightness }, /* Acer Aspire 4736Z */ { 0x2a42, 0x1025, 0x0260, quirk_invert_brightness }, /* Dell XPS13 HD Sandy Bridge */ { 0x0116, 0x1028, 0x052e, quirk_no_pcm_pwm_enable }, /* Dell XPS13 HD and XPS13 FHD Ivy Bridge */ { 0x0166, 0x1028, 0x058b, quirk_no_pcm_pwm_enable }, }; static void intel_init_quirks(struct drm_device *dev) { struct pci_dev *d = dev->pdev; int i; for (i = 0; i < ARRAY_SIZE(intel_quirks); i++) { struct intel_quirk *q = &intel_quirks[i]; if (d->device == q->device && (d->subsystem_vendor == q->subsystem_vendor || q->subsystem_vendor == PCI_ANY_ID) && (d->subsystem_device == q->subsystem_device || q->subsystem_device == PCI_ANY_ID)) q->hook(dev); } for (i = 0; i < ARRAY_SIZE(intel_dmi_quirks); i++) { if (dmi_check_system(*intel_dmi_quirks[i].dmi_id_list) != 0) intel_dmi_quirks[i].hook(dev); } } /* Disable the VGA plane that we never use */ static void i915_disable_vga(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; u8 sr1; u32 vga_reg = i915_vgacntrl_reg(dev); vga_get_uninterruptible(dev->pdev, VGA_RSRC_LEGACY_IO); outb(SR01, VGA_SR_INDEX); sr1 = inb(VGA_SR_DATA); outb(sr1 | 1<<5, VGA_SR_DATA); vga_put(dev->pdev, VGA_RSRC_LEGACY_IO); udelay(300); I915_WRITE(vga_reg, VGA_DISP_DISABLE); POSTING_READ(vga_reg); } void intel_modeset_init_hw(struct drm_device *dev) { intel_init_power_well(dev); intel_prepare_ddi(dev); intel_init_clock_gating(dev); mutex_lock(&dev->struct_mutex); intel_enable_gt_powersave(dev); mutex_unlock(&dev->struct_mutex); } void intel_modeset_suspend_hw(struct drm_device *dev) { intel_suspend_hw(dev); } void intel_modeset_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; int i, j, ret; drm_mode_config_init(dev); dev->mode_config.min_width = 0; dev->mode_config.min_height = 0; dev->mode_config.preferred_depth = 24; dev->mode_config.prefer_shadow = 1; dev->mode_config.funcs = &intel_mode_funcs; intel_init_quirks(dev); intel_init_pm(dev); if (INTEL_INFO(dev)->num_pipes == 0) return; intel_init_display(dev); if (IS_GEN2(dev)) { dev->mode_config.max_width = 2048; dev->mode_config.max_height = 2048; } else if (IS_GEN3(dev)) { dev->mode_config.max_width = 4096; dev->mode_config.max_height = 4096; } else { dev->mode_config.max_width = 8192; dev->mode_config.max_height = 8192; } dev->mode_config.fb_base = dev_priv->gtt.mappable_base; DRM_DEBUG_KMS("%d display pipe%s available.\n", INTEL_INFO(dev)->num_pipes, INTEL_INFO(dev)->num_pipes > 1 ? "s" : ""); for_each_pipe(i) { intel_crtc_init(dev, i); for (j = 0; j < dev_priv->num_plane; j++) { ret = intel_plane_init(dev, i, j); if (ret) DRM_DEBUG_KMS("pipe %c sprite %c init failed: %d\n", pipe_name(i), sprite_name(i, j), ret); } } intel_cpu_pll_init(dev); intel_shared_dpll_init(dev); /* Just disable it once at startup */ i915_disable_vga(dev); intel_setup_outputs(dev); /* Just in case the BIOS is doing something questionable. */ intel_disable_fbc(dev); intel_disable_drrs(dev); } static void intel_connector_break_all_links(struct intel_connector *connector) { connector->base.dpms = DRM_MODE_DPMS_OFF; connector->base.encoder = NULL; connector->encoder->connectors_active = false; connector->encoder->base.crtc = NULL; } static void intel_enable_pipe_a(struct drm_device *dev) { struct intel_connector *connector; struct drm_connector *crt = NULL; struct intel_load_detect_pipe load_detect_temp; /* We can't just switch on the pipe A, we need to set things up with a * proper mode and output configuration. As a gross hack, enable pipe A * by enabling the load detect pipe once. */ list_for_each_entry(connector, &dev->mode_config.connector_list, base.head) { if (connector->encoder->type == INTEL_OUTPUT_ANALOG) { crt = &connector->base; break; } } if (!crt) return; if (intel_get_load_detect_pipe(crt, NULL, &load_detect_temp)) intel_release_load_detect_pipe(crt, &load_detect_temp); } static bool intel_check_plane_mapping(struct intel_crtc *crtc) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; u32 reg, val; if (INTEL_INFO(dev)->num_pipes == 1) return true; reg = DSPCNTR(!crtc->plane); val = I915_READ(reg); if ((val & DISPLAY_PLANE_ENABLE) && (!!(val & DISPPLANE_SEL_PIPE_MASK) == crtc->pipe)) return false; return true; } static void intel_sanitize_crtc(struct intel_crtc *crtc) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; u32 reg; /* Clear any frame start delays used for debugging left by the BIOS */ reg = PIPECONF(crtc->config.cpu_transcoder); I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK); /* We need to sanitize the plane -> pipe mapping first because this will * disable the crtc (and hence change the state) if it is wrong. Note * that gen4+ has a fixed plane -> pipe mapping. */ if (INTEL_INFO(dev)->gen < 4 && !intel_check_plane_mapping(crtc)) { struct intel_connector *connector; bool plane; DRM_DEBUG_KMS("[CRTC:%d] wrong plane connection detected!\n", crtc->base.base.id); /* Pipe has the wrong plane attached and the plane is active. * Temporarily change the plane mapping and disable everything * ... */ plane = crtc->plane; crtc->plane = !plane; dev_priv->display.crtc_disable(&crtc->base); crtc->plane = plane; /* ... and break all links. */ list_for_each_entry(connector, &dev->mode_config.connector_list, base.head) { if (connector->encoder->base.crtc != &crtc->base) continue; intel_connector_break_all_links(connector); } WARN_ON(crtc->active); crtc->base.enabled = false; } if (dev_priv->quirks & QUIRK_PIPEA_FORCE && crtc->pipe == PIPE_A && !crtc->active) { /* BIOS forgot to enable pipe A, this mostly happens after * resume. Force-enable the pipe to fix this, the update_dpms * call below we restore the pipe to the right state, but leave * the required bits on. */ intel_enable_pipe_a(dev); } /* Adjust the state of the output pipe according to whether we * have active connectors/encoders. */ intel_crtc_update_dpms(&crtc->base); if (crtc->active != crtc->base.enabled) { struct intel_encoder *encoder; /* This can happen either due to bugs in the get_hw_state * functions or because the pipe is force-enabled due to the * pipe A quirk. */ DRM_DEBUG_KMS("[CRTC:%d] hw state adjusted, was %s, now %s\n", crtc->base.base.id, crtc->base.enabled ? "enabled" : "disabled", crtc->active ? "enabled" : "disabled"); crtc->base.enabled = crtc->active; /* Because we only establish the connector -> encoder -> * crtc links if something is active, this means the * crtc is now deactivated. Break the links. connector * -> encoder links are only establish when things are * actually up, hence no need to break them. */ WARN_ON(crtc->active); for_each_encoder_on_crtc(dev, &crtc->base, encoder) { WARN_ON(encoder->connectors_active); encoder->base.crtc = NULL; } } } static void intel_sanitize_encoder(struct intel_encoder *encoder) { struct intel_connector *connector; struct drm_device *dev = encoder->base.dev; /* We need to check both for a crtc link (meaning that the * encoder is active and trying to read from a pipe) and the * pipe itself being active. */ bool has_active_crtc = encoder->base.crtc && to_intel_crtc(encoder->base.crtc)->active; if (encoder->connectors_active && !has_active_crtc) { DRM_DEBUG_KMS("[ENCODER:%d:%s] has active connectors but no active pipe!\n", encoder->base.base.id, drm_get_encoder_name(&encoder->base)); /* Connector is active, but has no active pipe. This is * fallout from our resume register restoring. Disable * the encoder manually again. */ if (encoder->base.crtc) { DRM_DEBUG_KMS("[ENCODER:%d:%s] manually disabled\n", encoder->base.base.id, drm_get_encoder_name(&encoder->base)); encoder->disable(encoder); } /* Inconsistent output/port/pipe state happens presumably due to * a bug in one of the get_hw_state functions. Or someplace else * in our code, like the register restore mess on resume. Clamp * things to off as a safer default. */ list_for_each_entry(connector, &dev->mode_config.connector_list, base.head) { if (connector->encoder != encoder) continue; intel_connector_break_all_links(connector); } } /* Enabled encoders without active connectors will be fixed in * the crtc fixup. */ } void i915_redisable_vga(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; u32 vga_reg = i915_vgacntrl_reg(dev); /* This function can be called both from intel_modeset_setup_hw_state or * at a very early point in our resume sequence, where the power well * structures are not yet restored. Since this function is at a very * paranoid "someone might have enabled VGA while we were not looking" * level, just check if the power well is enabled instead of trying to * follow the "don't touch the power well if we don't need it" policy * the rest of the driver uses. */ if (HAS_POWER_WELL(dev) && (I915_READ(HSW_PWR_WELL_DRIVER) & HSW_PWR_WELL_STATE_ENABLED) == 0) return; if (I915_READ(vga_reg) != VGA_DISP_DISABLE) { DRM_DEBUG_KMS("Something enabled VGA plane, disabling it\n"); i915_disable_vga(dev); } } static void intel_modeset_readout_hw_state(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; enum pipe pipe; struct intel_crtc *crtc; struct intel_encoder *encoder; struct intel_connector *connector; int i; list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) { if (crtc->pipe == PIPE_B && !dev_priv->audio_suspended) continue; memset(&crtc->config, 0, sizeof(crtc->config)); crtc->active = dev_priv->display.get_pipe_config(crtc, &crtc->config); crtc->base.enabled = crtc->active; DRM_DEBUG_KMS("[CRTC:%d] hw state readout: %s\n", crtc->base.base.id, crtc->active ? "enabled" : "disabled"); } /* FIXME: Smash this into the new shared dpll infrastructure. */ if (HAS_DDI(dev)) intel_ddi_setup_hw_pll_state(dev); for (i = 0; i < dev_priv->num_shared_dpll; i++) { struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i]; pll->on = pll->get_hw_state(dev_priv, pll, &pll->hw_state); pll->active = 0; list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) { if (crtc->active && intel_crtc_to_shared_dpll(crtc) == pll) pll->active++; } pll->refcount = pll->active; DRM_DEBUG_KMS("%s hw state readout: refcount %i, on %i\n", pll->name, pll->refcount, pll->on); } list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) { pipe = 0; 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); } else { encoder->base.crtc = NULL; } encoder->connectors_active = false; DRM_DEBUG_KMS("[ENCODER:%d:%s] hw state readout: %s, pipe=%i\n", encoder->base.base.id, drm_get_encoder_name(&encoder->base), encoder->base.crtc ? "enabled" : "disabled", pipe); if ((encoder->type == INTEL_OUTPUT_DSI) && encoder->base.crtc) { /* DSI will be enabled by IAFW; set a flag for this case * so that during sanitize process we do not apply DPMS * on DSI. Enable the flag to indicate that MIPI was * initialized by IAFW */ dev_priv->mipi_fw = 1; } } list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) { if (!crtc->active) continue; if (dev_priv->display.get_clock) dev_priv->display.get_clock(crtc, &crtc->config); } list_for_each_entry(connector, &dev->mode_config.connector_list, base.head) { if (connector->get_hw_state(connector)) { connector->base.dpms = DRM_MODE_DPMS_ON; connector->encoder->connectors_active = true; connector->base.encoder = &connector->encoder->base; } else { connector->base.dpms = DRM_MODE_DPMS_OFF; connector->base.encoder = NULL; } DRM_DEBUG_KMS("[CONNECTOR:%d:%s] hw state readout: %s\n", connector->base.base.id, drm_get_connector_name(&connector->base), connector->base.encoder ? "enabled" : "disabled"); } } /* Scan out the current hw modeset state, sanitizes it and maps it into the drm * and i915 state tracking structures. */ void intel_modeset_setup_hw_state(struct drm_device *dev, bool force_restore) { struct drm_i915_private *dev_priv = dev->dev_private; enum pipe pipe; struct drm_plane *plane; struct intel_crtc *crtc; struct intel_encoder *encoder; struct drm_encoder *drm_encoder = NULL; struct drm_encoder_helper_funcs *encoder_funcs = NULL; int i; intel_modeset_readout_hw_state(dev); /* * Now that we have the config, copy it to each CRTC struct * Note that this could go away if we move to using crtc_config * checking everywhere. */ list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) { if (crtc->active && i915_fastboot) { intel_crtc_mode_from_pipe_config(crtc, &crtc->config); DRM_DEBUG_KMS("[CRTC:%d] found active mode: ", crtc->base.base.id); drm_mode_debug_printmodeline(&crtc->base.mode); } } /* HW state is read out, now we need to sanitize this mess. */ list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) { if (encoder->type == INTEL_OUTPUT_HDMI) { drm_encoder = &encoder->base; encoder_funcs = drm_encoder->helper_private; } intel_sanitize_encoder(encoder); } for_each_pipe(pipe) { crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); intel_sanitize_crtc(crtc); intel_dump_pipe_config(crtc, &crtc->config, "[setup_hw_state]"); } for (i = 0; i < dev_priv->num_shared_dpll; i++) { struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i]; if (!pll->on || pll->active) continue; DRM_DEBUG_KMS("%s enabled but not in use, disabling\n", pll->name); pll->disable(dev_priv, pll); pll->on = false; } 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]; if ((drm_encoder != NULL) && (pipe == 1)) { struct drm_encoder_helper_funcs *encoder_funcs = drm_encoder->helper_private; if (encoder_funcs->inuse( drm_encoder)) continue; } __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); i915_redisable_vga(dev); } else { intel_modeset_update_staged_output_state(dev); } intel_modeset_check_state(dev); drm_mode_config_reset(dev); } void intel_modeset_gem_init(struct drm_device *dev) { intel_modeset_init_hw(dev); intel_setup_overlay(dev); intel_modeset_setup_hw_state(dev, false); } void intel_modeset_cleanup(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct drm_crtc *crtc; /* * Interrupts and polling as the first thing to avoid creating havoc. * Too much stuff here (turning of rps, connectors, ...) would * experience fancy races otherwise. */ drm_irq_uninstall(dev); cancel_work_sync(&dev_priv->hotplug_work); /* * Due to the hpd irq storm handling the hotplug work can re-arm the * poll handlers. Hence disable polling after hpd handling is shut down. */ drm_kms_helper_poll_fini(dev); mutex_lock(&dev->struct_mutex); intel_unregister_dsm_handler(); list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { /* Skip inactive CRTCs */ if (!crtc->fb) continue; intel_increase_pllclock(crtc); } intel_disable_fbc(dev); intel_disable_drrs(dev); intel_disable_gt_powersave(dev); ironlake_teardown_rc6(dev); mutex_unlock(&dev->struct_mutex); /* 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); } /* * Return which encoder is currently attached for connector. */ struct drm_encoder *intel_best_encoder(struct drm_connector *connector) { return &intel_attached_encoder(connector)->base; } void intel_connector_attach_encoder(struct intel_connector *connector, struct intel_encoder *encoder) { connector->encoder = encoder; drm_mode_connector_attach_encoder(&connector->base, &encoder->base); } /* * set vga decode state - true == enable VGA decode */ int intel_modeset_vga_set_state(struct drm_device *dev, bool state) { struct drm_i915_private *dev_priv = dev->dev_private; u16 gmch_ctrl = 0; pci_read_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, &gmch_ctrl); if (state) gmch_ctrl &= ~INTEL_GMCH_VGA_DISABLE; else gmch_ctrl |= INTEL_GMCH_VGA_DISABLE; pci_write_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, gmch_ctrl); return 0; } struct intel_display_error_state { u32 power_well_driver; struct intel_cursor_error_state { u32 control; u32 position; u32 base; u32 size; } cursor[I915_MAX_PIPES]; struct intel_pipe_error_state { enum transcoder cpu_transcoder; u32 conf; u32 source; u32 htotal; u32 hblank; u32 hsync; u32 vtotal; u32 vblank; u32 vsync; } pipe[I915_MAX_PIPES]; struct intel_plane_error_state { u32 control; u32 stride; u32 size; u32 pos; u32 addr; u32 surface; u32 tile_offset; } plane[I915_MAX_PIPES]; }; struct intel_display_error_state * intel_display_capture_error_state(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; struct intel_display_error_state *error; enum transcoder cpu_transcoder; int i; error = kmalloc(sizeof(*error), GFP_ATOMIC); if (error == NULL) return NULL; if (HAS_POWER_WELL(dev)) error->power_well_driver = I915_READ(HSW_PWR_WELL_DRIVER); for_each_pipe(i) { cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, i); error->pipe[i].cpu_transcoder = cpu_transcoder; if (INTEL_INFO(dev)->gen <= 6 || IS_VALLEYVIEW(dev)) { error->cursor[i].control = I915_READ(CURCNTR(i)); error->cursor[i].position = I915_READ(CURPOS(i)); error->cursor[i].base = I915_READ(CURBASE(i)); } else { error->cursor[i].control = I915_READ(CURCNTR_IVB(i)); error->cursor[i].position = I915_READ(CURPOS_IVB(i)); error->cursor[i].base = I915_READ(CURBASE_IVB(i)); } error->plane[i].control = I915_READ(DSPCNTR(i)); error->plane[i].stride = I915_READ(DSPSTRIDE(i)); if (INTEL_INFO(dev)->gen <= 3) { error->plane[i].size = I915_READ(DSPSIZE(i)); error->plane[i].pos = I915_READ(DSPPOS(i)); } if (INTEL_INFO(dev)->gen <= 7 && !IS_HASWELL(dev)) error->plane[i].addr = I915_READ(DSPADDR(i)); if (INTEL_INFO(dev)->gen >= 4) { error->plane[i].surface = I915_READ(DSPSURF(i)); error->plane[i].tile_offset = I915_READ(DSPTILEOFF(i)); } error->pipe[i].conf = I915_READ(PIPECONF(cpu_transcoder)); error->pipe[i].source = I915_READ(PIPESRC(i)); error->pipe[i].htotal = I915_READ(HTOTAL(cpu_transcoder)); error->pipe[i].hblank = I915_READ(HBLANK(cpu_transcoder)); error->pipe[i].hsync = I915_READ(HSYNC(cpu_transcoder)); error->pipe[i].vtotal = I915_READ(VTOTAL(cpu_transcoder)); error->pipe[i].vblank = I915_READ(VBLANK(cpu_transcoder)); error->pipe[i].vsync = I915_READ(VSYNC(cpu_transcoder)); } /* In the code above we read the registers without checking if the power * well was on, so here we have to clear the FPGA_DBG_RM_NOCLAIM bit to * prevent the next I915_WRITE from detecting it and printing an error * message. */ intel_uncore_clear_errors(dev); return error; } #define err_printf(e, ...) i915_error_printf(e, __VA_ARGS__) void intel_display_print_error_state(struct drm_i915_error_state_buf *m, struct drm_device *dev, struct intel_display_error_state *error) { int i; err_printf(m, "Num Pipes: %d\n", INTEL_INFO(dev)->num_pipes); if (HAS_POWER_WELL(dev)) err_printf(m, "PWR_WELL_CTL2: %08x\n", error->power_well_driver); for_each_pipe(i) { err_printf(m, "Pipe [%d]:\n", i); err_printf(m, " CPU transcoder: %c\n", transcoder_name(error->pipe[i].cpu_transcoder)); err_printf(m, " CONF: %08x\n", error->pipe[i].conf); err_printf(m, " SRC: %08x\n", error->pipe[i].source); err_printf(m, " HTOTAL: %08x\n", error->pipe[i].htotal); err_printf(m, " HBLANK: %08x\n", error->pipe[i].hblank); err_printf(m, " HSYNC: %08x\n", error->pipe[i].hsync); err_printf(m, " VTOTAL: %08x\n", error->pipe[i].vtotal); err_printf(m, " VBLANK: %08x\n", error->pipe[i].vblank); err_printf(m, " VSYNC: %08x\n", error->pipe[i].vsync); err_printf(m, "Plane [%d]:\n", i); err_printf(m, " CNTR: %08x\n", error->plane[i].control); err_printf(m, " STRIDE: %08x\n", error->plane[i].stride); if (INTEL_INFO(dev)->gen <= 3) { err_printf(m, " SIZE: %08x\n", error->plane[i].size); err_printf(m, " POS: %08x\n", error->plane[i].pos); } if (INTEL_INFO(dev)->gen <= 7 && !IS_HASWELL(dev)) err_printf(m, " ADDR: %08x\n", error->plane[i].addr); if (INTEL_INFO(dev)->gen >= 4) { err_printf(m, " SURF: %08x\n", error->plane[i].surface); err_printf(m, " TILEOFF: %08x\n", error->plane[i].tile_offset); } err_printf(m, "Cursor [%d]:\n", i); err_printf(m, " CNTR: %08x\n", error->cursor[i].control); err_printf(m, " POS: %08x\n", error->cursor[i].position); err_printf(m, " BASE: %08x\n", error->cursor[i].base); } } int i915_disp_screen_control(struct drm_device *dev, void *data, struct drm_file *file) { struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_disp_screen_control *screen_cntrl = data; struct drm_mode_object *obj; struct drm_crtc *crtc; struct intel_crtc *intel_crtc; int pipe; u32 val; static u32 previous_bck_level; obj = drm_mode_object_find(dev, screen_cntrl->crtc_id, DRM_MODE_OBJECT_CRTC); if (!obj) { DRM_DEBUG_DRIVER("Unknown CRTC ID %d\n", screen_cntrl->crtc_id); return -EINVAL; } crtc = obj_to_crtc(obj); DRM_DEBUG_DRIVER("[CRTC:%d]\n", crtc->base.id); intel_crtc = to_intel_crtc(crtc); pipe = intel_crtc->pipe; DRM_DEBUG_DRIVER("pipe = %d, on_off_cntrl = %d", \ pipe, screen_cntrl->on_off_cntrl); if (intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) { if (screen_cntrl->on_off_cntrl == DISP_SCREEN_OFF) { previous_bck_level = dev_priv->backlight.level; intel_panel_set_backlight(dev, 0, MAX_BRIGHTNESS); } else if (screen_cntrl->on_off_cntrl == DISP_SCREEN_ON) intel_panel_set_backlight(dev, previous_bck_level, MAX_BRIGHTNESS); } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) { val = I915_READ(PIPECONF(pipe)); if (screen_cntrl->on_off_cntrl == DISP_SCREEN_OFF) { if (!(val & PIPECONF_DISP_OVERLAY_OFF)) val |= PIPECONF_DISP_OVERLAY_OFF; if (!(val & PIPECONF_CURSOR_OFF)) val |= PIPECONF_CURSOR_OFF; } else if (screen_cntrl->on_off_cntrl == DISP_SCREEN_ON) { if (val & PIPECONF_DISP_OVERLAY_OFF) val &= ~PIPECONF_DISP_OVERLAY_OFF; if (val & PIPECONF_CURSOR_OFF) val &= ~PIPECONF_CURSOR_OFF; } I915_WRITE(PIPECONF(pipe), val); } return 0; }