diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 2171 |
1 files changed, 1125 insertions, 1046 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e7a16f119a29..3d220a67f865 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -37,6 +37,7 @@ #include <drm/i915_drm.h> #include "i915_drv.h" #include "i915_trace.h" +#include <drm/drm_atomic_helper.h> #include <drm/drm_dp_helper.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_plane_helper.h> @@ -76,9 +77,9 @@ static const uint32_t intel_cursor_formats[] = { static void intel_crtc_update_cursor(struct drm_crtc *crtc, bool on); static void i9xx_crtc_clock_get(struct intel_crtc *crtc, - struct intel_crtc_config *pipe_config); + struct intel_crtc_state *pipe_config); static void ironlake_pch_clock_get(struct intel_crtc *crtc, - struct intel_crtc_config *pipe_config); + struct intel_crtc_state *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); @@ -95,9 +96,11 @@ static void ironlake_set_pipeconf(struct drm_crtc *crtc); static void haswell_set_pipeconf(struct drm_crtc *crtc); static void intel_set_pipe_csc(struct drm_crtc *crtc); static void vlv_prepare_pll(struct intel_crtc *crtc, - const struct intel_crtc_config *pipe_config); + const struct intel_crtc_state *pipe_config); static void chv_prepare_pll(struct intel_crtc *crtc, - const struct intel_crtc_config *pipe_config); + const struct intel_crtc_state *pipe_config); +static void intel_begin_crtc_commit(struct drm_crtc *crtc); +static void intel_finish_crtc_commit(struct drm_crtc *crtc); static struct intel_encoder *intel_find_encoder(struct intel_connector *connector, int pipe) { @@ -895,7 +898,7 @@ bool intel_crtc_active(struct drm_crtc *crtc) * properly reconstruct framebuffers. */ return intel_crtc->active && crtc->primary->fb && - intel_crtc->config.adjusted_mode.crtc_clock; + intel_crtc->config->base.adjusted_mode.crtc_clock; } enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv, @@ -904,7 +907,7 @@ enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv, 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; + return intel_crtc->config->cpu_transcoder; } static bool pipe_dsl_stopped(struct drm_device *dev, enum pipe pipe) @@ -946,7 +949,7 @@ static void intel_wait_for_pipe_off(struct intel_crtc *crtc) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - enum transcoder cpu_transcoder = crtc->config.cpu_transcoder; + enum transcoder cpu_transcoder = crtc->config->cpu_transcoder; enum pipe pipe = crtc->pipe; if (INTEL_INFO(dev)->gen >= 4) { @@ -1024,7 +1027,7 @@ void assert_pll(struct drm_i915_private *dev_priv, reg = DPLL(pipe); val = I915_READ(reg); cur_state = !!(val & DPLL_VCO_ENABLE); - WARN(cur_state != state, + I915_STATE_WARN(cur_state != state, "PLL state assertion failure (expected %s, current %s)\n", state_string(state), state_string(cur_state)); } @@ -1040,7 +1043,7 @@ static void assert_dsi_pll(struct drm_i915_private *dev_priv, bool state) mutex_unlock(&dev_priv->dpio_lock); cur_state = val & DSI_PLL_VCO_EN; - WARN(cur_state != state, + I915_STATE_WARN(cur_state != state, "DSI PLL state assertion failure (expected %s, current %s)\n", state_string(state), state_string(cur_state)); } @@ -1052,10 +1055,10 @@ 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) + if (crtc->config->shared_dpll < 0) return NULL; - return &dev_priv->shared_dplls[crtc->config.shared_dpll]; + return &dev_priv->shared_dplls[crtc->config->shared_dpll]; } /* For ILK+ */ @@ -1071,7 +1074,7 @@ void assert_shared_dpll(struct drm_i915_private *dev_priv, return; cur_state = pll->get_hw_state(dev_priv, pll, &hw_state); - WARN(cur_state != state, + I915_STATE_WARN(cur_state != state, "%s assertion failure (expected %s, current %s)\n", pll->name, state_string(state), state_string(cur_state)); } @@ -1095,7 +1098,7 @@ static void assert_fdi_tx(struct drm_i915_private *dev_priv, val = I915_READ(reg); cur_state = !!(val & FDI_TX_ENABLE); } - WARN(cur_state != state, + I915_STATE_WARN(cur_state != state, "FDI TX state assertion failure (expected %s, current %s)\n", state_string(state), state_string(cur_state)); } @@ -1112,7 +1115,7 @@ static void assert_fdi_rx(struct drm_i915_private *dev_priv, reg = FDI_RX_CTL(pipe); val = I915_READ(reg); cur_state = !!(val & FDI_RX_ENABLE); - WARN(cur_state != state, + I915_STATE_WARN(cur_state != state, "FDI RX state assertion failure (expected %s, current %s)\n", state_string(state), state_string(cur_state)); } @@ -1135,7 +1138,7 @@ static void assert_fdi_tx_pll_enabled(struct drm_i915_private *dev_priv, 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"); + I915_STATE_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, @@ -1148,7 +1151,7 @@ void assert_fdi_rx_pll(struct drm_i915_private *dev_priv, reg = FDI_RX_CTL(pipe); val = I915_READ(reg); cur_state = !!(val & FDI_RX_PLL_ENABLE); - WARN(cur_state != state, + I915_STATE_WARN(cur_state != state, "FDI RX PLL assertion failure (expected %s, current %s)\n", state_string(state), state_string(cur_state)); } @@ -1190,7 +1193,7 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv, ((val & PANEL_UNLOCK_MASK) == PANEL_UNLOCK_REGS)) locked = false; - WARN(panel_pipe == pipe && locked, + I915_STATE_WARN(panel_pipe == pipe && locked, "panel assertion failure, pipe %c regs locked\n", pipe_name(pipe)); } @@ -1206,7 +1209,7 @@ static void assert_cursor(struct drm_i915_private *dev_priv, else cur_state = I915_READ(CURCNTR(pipe)) & CURSOR_MODE; - WARN(cur_state != state, + I915_STATE_WARN(cur_state != state, "cursor on pipe %c assertion failure (expected %s, current %s)\n", pipe_name(pipe), state_string(state), state_string(cur_state)); } @@ -1236,7 +1239,7 @@ void assert_pipe(struct drm_i915_private *dev_priv, cur_state = !!(val & PIPECONF_ENABLE); } - WARN(cur_state != state, + I915_STATE_WARN(cur_state != state, "pipe %c assertion failure (expected %s, current %s)\n", pipe_name(pipe), state_string(state), state_string(cur_state)); } @@ -1251,7 +1254,7 @@ static void assert_plane(struct drm_i915_private *dev_priv, reg = DSPCNTR(plane); val = I915_READ(reg); cur_state = !!(val & DISPLAY_PLANE_ENABLE); - WARN(cur_state != state, + I915_STATE_WARN(cur_state != state, "plane %c assertion failure (expected %s, current %s)\n", plane_name(plane), state_string(state), state_string(cur_state)); } @@ -1271,7 +1274,7 @@ static void assert_planes_disabled(struct drm_i915_private *dev_priv, if (INTEL_INFO(dev)->gen >= 4) { reg = DSPCNTR(pipe); val = I915_READ(reg); - WARN(val & DISPLAY_PLANE_ENABLE, + I915_STATE_WARN(val & DISPLAY_PLANE_ENABLE, "plane %c assertion failure, should be disabled but not\n", plane_name(pipe)); return; @@ -1283,7 +1286,7 @@ static void assert_planes_disabled(struct drm_i915_private *dev_priv, val = I915_READ(reg); cur_pipe = (val & DISPPLANE_SEL_PIPE_MASK) >> DISPPLANE_SEL_PIPE_SHIFT; - WARN((val & DISPLAY_PLANE_ENABLE) && pipe == cur_pipe, + I915_STATE_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)); } @@ -1299,7 +1302,7 @@ static void assert_sprites_disabled(struct drm_i915_private *dev_priv, if (INTEL_INFO(dev)->gen >= 9) { for_each_sprite(pipe, sprite) { val = I915_READ(PLANE_CTL(pipe, sprite)); - WARN(val & PLANE_CTL_ENABLE, + I915_STATE_WARN(val & PLANE_CTL_ENABLE, "plane %d assertion failure, should be off on pipe %c but is still active\n", sprite, pipe_name(pipe)); } @@ -1307,20 +1310,20 @@ static void assert_sprites_disabled(struct drm_i915_private *dev_priv, for_each_sprite(pipe, sprite) { reg = SPCNTR(pipe, sprite); val = I915_READ(reg); - WARN(val & SP_ENABLE, + I915_STATE_WARN(val & SP_ENABLE, "sprite %c assertion failure, should be off on pipe %c but is still active\n", sprite_name(pipe, sprite), pipe_name(pipe)); } } else if (INTEL_INFO(dev)->gen >= 7) { reg = SPRCTL(pipe); val = I915_READ(reg); - WARN(val & SPRITE_ENABLE, + I915_STATE_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, + I915_STATE_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)); } @@ -1328,7 +1331,7 @@ static void assert_sprites_disabled(struct drm_i915_private *dev_priv, static void assert_vblank_disabled(struct drm_crtc *crtc) { - if (WARN_ON(drm_crtc_vblank_get(crtc) == 0)) + if (I915_STATE_WARN_ON(drm_crtc_vblank_get(crtc) == 0)) drm_crtc_vblank_put(crtc); } @@ -1337,12 +1340,12 @@ static void ibx_assert_pch_refclk_enabled(struct drm_i915_private *dev_priv) u32 val; bool enabled; - WARN_ON(!(HAS_PCH_IBX(dev_priv->dev) || HAS_PCH_CPT(dev_priv->dev))); + I915_STATE_WARN_ON(!(HAS_PCH_IBX(dev_priv->dev) || HAS_PCH_CPT(dev_priv->dev))); 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"); + I915_STATE_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, @@ -1355,7 +1358,7 @@ static void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv, reg = PCH_TRANSCONF(pipe); val = I915_READ(reg); enabled = !!(val & TRANS_ENABLE); - WARN(enabled, + I915_STATE_WARN(enabled, "transcoder assertion failed, should be off on pipe %c but is still active\n", pipe_name(pipe)); } @@ -1435,11 +1438,11 @@ 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), + I915_STATE_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 + I915_STATE_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"); } @@ -1448,11 +1451,11 @@ 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), + I915_STATE_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 + I915_STATE_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"); } @@ -1469,13 +1472,13 @@ static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv, reg = PCH_ADPA; val = I915_READ(reg); - WARN(adpa_pipe_enabled(dev_priv, pipe, val), + I915_STATE_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), + I915_STATE_WARN(lvds_pipe_enabled(dev_priv, pipe, val), "PCH LVDS enabled on transcoder %c, should be disabled\n", pipe_name(pipe)); @@ -1505,7 +1508,7 @@ static void intel_init_dpio(struct drm_device *dev) } static void vlv_enable_pll(struct intel_crtc *crtc, - const struct intel_crtc_config *pipe_config) + const struct intel_crtc_state *pipe_config) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -1544,7 +1547,7 @@ static void vlv_enable_pll(struct intel_crtc *crtc, } static void chv_enable_pll(struct intel_crtc *crtc, - const struct intel_crtc_config *pipe_config) + const struct intel_crtc_state *pipe_config) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -1599,7 +1602,7 @@ 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; + u32 dpll = crtc->config->dpll_hw_state.dpll; assert_pipe_disabled(dev_priv, crtc->pipe); @@ -1629,7 +1632,7 @@ static void i9xx_enable_pll(struct intel_crtc *crtc) if (INTEL_INFO(dev)->gen >= 4) { I915_WRITE(DPLL_MD(crtc->pipe), - crtc->config.dpll_hw_state.dpll_md); + 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. @@ -2034,7 +2037,7 @@ static void intel_enable_pipe(struct intel_crtc *crtc) else assert_pll_enabled(dev_priv, pipe); else { - if (crtc->config.has_pch_encoder) { + if (crtc->config->has_pch_encoder) { /* if driving the PCH, we need FDI enabled */ assert_fdi_rx_pll_enabled(dev_priv, pch_transcoder); assert_fdi_tx_pll_enabled(dev_priv, @@ -2068,7 +2071,7 @@ static void intel_enable_pipe(struct intel_crtc *crtc) static void intel_disable_pipe(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; - enum transcoder cpu_transcoder = crtc->config.cpu_transcoder; + enum transcoder cpu_transcoder = crtc->config->cpu_transcoder; enum pipe pipe = crtc->pipe; int reg; u32 val; @@ -2090,7 +2093,7 @@ static void intel_disable_pipe(struct intel_crtc *crtc) * Double wide has implications for planes * so best keep it disabled when not needed. */ - if (crtc->config.double_wide) + if (crtc->config->double_wide) val &= ~PIPECONF_DOUBLE_WIDE; /* Don't disable pipe or pipe PLLs if needed */ @@ -2165,7 +2168,8 @@ static void intel_disable_primary_hw_plane(struct drm_plane *plane, struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - assert_pipe_enabled(dev_priv, intel_crtc->pipe); + if (WARN_ON(!intel_crtc->active)) + return; if (!intel_crtc->primary_enabled) return; @@ -2185,11 +2189,12 @@ static bool need_vtd_wa(struct drm_device *dev) return false; } -static int intel_align_height(struct drm_device *dev, int height, bool tiled) +int +intel_fb_align_height(struct drm_device *dev, int height, unsigned int tiling) { int tile_height; - tile_height = tiled ? (IS_GEN2(dev) ? 16 : 8) : 1; + tile_height = tiling ? (IS_GEN2(dev) ? 16 : 8) : 1; return ALIGN(height, tile_height); } @@ -2312,7 +2317,7 @@ unsigned long intel_gen4_compute_page_offset(int *x, int *y, } } -int intel_format_to_fourcc(int format) +static int i9xx_format_to_fourcc(int format) { switch (format) { case DISPPLANE_8BPP: @@ -2333,8 +2338,35 @@ int intel_format_to_fourcc(int format) } } -static bool intel_alloc_plane_obj(struct intel_crtc *crtc, - struct intel_plane_config *plane_config) +static int skl_format_to_fourcc(int format, bool rgb_order, bool alpha) +{ + switch (format) { + case PLANE_CTL_FORMAT_RGB_565: + return DRM_FORMAT_RGB565; + default: + case PLANE_CTL_FORMAT_XRGB_8888: + if (rgb_order) { + if (alpha) + return DRM_FORMAT_ABGR8888; + else + return DRM_FORMAT_XBGR8888; + } else { + if (alpha) + return DRM_FORMAT_ARGB8888; + else + return DRM_FORMAT_XRGB8888; + } + case PLANE_CTL_FORMAT_XRGB_2101010: + if (rgb_order) + return DRM_FORMAT_XBGR2101010; + else + return DRM_FORMAT_XRGB2101010; + } +} + +static bool +intel_alloc_plane_obj(struct intel_crtc *crtc, + struct intel_initial_plane_config *plane_config) { struct drm_device *dev = crtc->base.dev; struct drm_i915_gem_object *obj = NULL; @@ -2349,10 +2381,9 @@ static bool intel_alloc_plane_obj(struct intel_crtc *crtc, if (!obj) return false; - if (plane_config->tiled) { - obj->tiling_mode = I915_TILING_X; + obj->tiling_mode = plane_config->tiling; + if (obj->tiling_mode == I915_TILING_X) obj->stride = crtc->base.primary->fb->pitches[0]; - } mode_cmd.pixel_format = crtc->base.primary->fb->pixel_format; mode_cmd.width = crtc->base.primary->fb->width; @@ -2379,8 +2410,9 @@ out_unref_obj: return false; } -static void intel_find_plane_obj(struct intel_crtc *intel_crtc, - struct intel_plane_config *plane_config) +static void +intel_find_plane_obj(struct intel_crtc *intel_crtc, + struct intel_initial_plane_config *plane_config) { struct drm_device *dev = intel_crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -2468,13 +2500,13 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc, * which should always be the user's requested size. */ I915_WRITE(DSPSIZE(plane), - ((intel_crtc->config.pipe_src_h - 1) << 16) | - (intel_crtc->config.pipe_src_w - 1)); + ((intel_crtc->config->pipe_src_h - 1) << 16) | + (intel_crtc->config->pipe_src_w - 1)); I915_WRITE(DSPPOS(plane), 0); } else if (IS_CHERRYVIEW(dev) && plane == PLANE_B) { I915_WRITE(PRIMSIZE(plane), - ((intel_crtc->config.pipe_src_h - 1) << 16) | - (intel_crtc->config.pipe_src_w - 1)); + ((intel_crtc->config->pipe_src_h - 1) << 16) | + (intel_crtc->config->pipe_src_w - 1)); I915_WRITE(PRIMPOS(plane), 0); I915_WRITE(PRIMCNSTALPHA(plane), 0); } @@ -2529,17 +2561,17 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc, intel_crtc->dspaddr_offset = linear_offset; } - if (to_intel_plane(crtc->primary)->rotation == BIT(DRM_ROTATE_180)) { + if (crtc->primary->state->rotation == BIT(DRM_ROTATE_180)) { dspcntr |= DISPPLANE_ROTATE_180; - x += (intel_crtc->config.pipe_src_w - 1); - y += (intel_crtc->config.pipe_src_h - 1); + x += (intel_crtc->config->pipe_src_w - 1); + y += (intel_crtc->config->pipe_src_h - 1); /* Finding the last pixel of the last line of the display data and adding to linear_offset*/ linear_offset += - (intel_crtc->config.pipe_src_h - 1) * fb->pitches[0] + - (intel_crtc->config.pipe_src_w - 1) * pixel_size; + (intel_crtc->config->pipe_src_h - 1) * fb->pitches[0] + + (intel_crtc->config->pipe_src_w - 1) * pixel_size; } I915_WRITE(reg, dspcntr); @@ -2631,18 +2663,18 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc, pixel_size, fb->pitches[0]); linear_offset -= intel_crtc->dspaddr_offset; - if (to_intel_plane(crtc->primary)->rotation == BIT(DRM_ROTATE_180)) { + if (crtc->primary->state->rotation == BIT(DRM_ROTATE_180)) { dspcntr |= DISPPLANE_ROTATE_180; if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) { - x += (intel_crtc->config.pipe_src_w - 1); - y += (intel_crtc->config.pipe_src_h - 1); + x += (intel_crtc->config->pipe_src_w - 1); + y += (intel_crtc->config->pipe_src_h - 1); /* Finding the last pixel of the last line of the display data and adding to linear_offset*/ linear_offset += - (intel_crtc->config.pipe_src_h - 1) * fb->pitches[0] + - (intel_crtc->config.pipe_src_w - 1) * pixel_size; + (intel_crtc->config->pipe_src_h - 1) * fb->pitches[0] + + (intel_crtc->config->pipe_src_w - 1) * pixel_size; } } @@ -2728,7 +2760,7 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc, } plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE; - if (to_intel_plane(crtc->primary)->rotation == BIT(DRM_ROTATE_180)) + if (crtc->primary->state->rotation == BIT(DRM_ROTATE_180)) plane_ctl |= PLANE_CTL_ROTATE_180; I915_WRITE(PLANE_CTL(pipe, 0), plane_ctl); @@ -2741,8 +2773,8 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc, I915_WRITE(PLANE_POS(pipe, 0), 0); I915_WRITE(PLANE_OFFSET(pipe, 0), (y << 16) | x); I915_WRITE(PLANE_SIZE(pipe, 0), - (intel_crtc->config.pipe_src_h - 1) << 16 | - (intel_crtc->config.pipe_src_w - 1)); + (intel_crtc->config->pipe_src_h - 1) << 16 | + (intel_crtc->config->pipe_src_w - 1)); I915_WRITE(PLANE_STRIDE(pipe, 0), stride); I915_WRITE(PLANE_SURF(pipe, 0), i915_gem_obj_ggtt_offset(obj)); @@ -2938,85 +2970,20 @@ static void intel_update_pipe_size(struct intel_crtc *crtc) * then update the pipesrc and pfit state, even on the flip path. */ - adjusted_mode = &crtc->config.adjusted_mode; + adjusted_mode = &crtc->config->base.adjusted_mode; I915_WRITE(PIPESRC(crtc->pipe), ((adjusted_mode->crtc_hdisplay - 1) << 16) | (adjusted_mode->crtc_vdisplay - 1)); - if (!crtc->config.pch_pfit.enabled && + if (!crtc->config->pch_pfit.enabled && (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) || intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))) { I915_WRITE(PF_CTL(crtc->pipe), 0); I915_WRITE(PF_WIN_POS(crtc->pipe), 0); I915_WRITE(PF_WIN_SZ(crtc->pipe), 0); } - crtc->config.pipe_src_w = adjusted_mode->crtc_hdisplay; - crtc->config.pipe_src_h = adjusted_mode->crtc_vdisplay; -} - -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); - enum pipe pipe = intel_crtc->pipe; - struct drm_framebuffer *old_fb = crtc->primary->fb; - struct drm_i915_gem_object *old_obj = intel_fb_obj(old_fb); - int ret; - - if (intel_crtc_has_pending_flip(crtc)) { - DRM_ERROR("pipe is still busy with an old pageflip\n"); - return -EBUSY; - } - - /* 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(crtc->primary, fb, NULL); - if (ret == 0) - i915_gem_track_fb(old_obj, intel_fb_obj(fb), - INTEL_FRONTBUFFER_PRIMARY(pipe)); - mutex_unlock(&dev->struct_mutex); - if (ret != 0) { - DRM_ERROR("pin & fence failed\n"); - return ret; - } - - dev_priv->display.update_primary_plane(crtc, fb, x, y); - - if (intel_crtc->active) - intel_frontbuffer_flip(dev, INTEL_FRONTBUFFER_PRIMARY(pipe)); - - crtc->primary->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); - mutex_lock(&dev->struct_mutex); - intel_unpin_fb_obj(old_obj); - mutex_unlock(&dev->struct_mutex); - } - - mutex_lock(&dev->struct_mutex); - intel_update_fbc(dev); - mutex_unlock(&dev->struct_mutex); - - return 0; + crtc->config->pipe_src_w = adjusted_mode->crtc_hdisplay; + crtc->config->pipe_src_h = adjusted_mode->crtc_vdisplay; } static void intel_fdi_normal_train(struct drm_crtc *crtc) @@ -3063,7 +3030,7 @@ static void intel_fdi_normal_train(struct drm_crtc *crtc) static bool pipe_has_enabled_pch(struct intel_crtc *crtc) { return crtc->base.enabled && crtc->active && - crtc->config.has_pch_encoder; + crtc->config->has_pch_encoder; } static void ivb_modeset_global_resources(struct drm_device *dev) @@ -3118,7 +3085,7 @@ static void ironlake_fdi_link_train(struct drm_crtc *crtc) 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_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); @@ -3216,7 +3183,7 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc) 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_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; @@ -3367,7 +3334,7 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc) 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_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]; @@ -3455,7 +3422,7 @@ static void ironlake_fdi_pll_enable(struct intel_crtc *intel_crtc) 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 |= 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); @@ -3639,7 +3606,7 @@ static void lpt_program_iclkip(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; - int clock = to_intel_crtc(crtc)->config.adjusted_mode.crtc_clock; + int clock = to_intel_crtc(crtc)->config->base.adjusted_mode.crtc_clock; u32 divsel, phaseinc, auxdiv, phasedir = 0; u32 temp; @@ -3728,7 +3695,7 @@ static void ironlake_pch_transcoder_set_timings(struct intel_crtc *crtc, { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - enum transcoder cpu_transcoder = crtc->config.cpu_transcoder; + enum transcoder cpu_transcoder = crtc->config->cpu_transcoder; I915_WRITE(PCH_TRANS_HTOTAL(pch_transcoder), I915_READ(HTOTAL(cpu_transcoder))); @@ -3774,7 +3741,7 @@ static void ivybridge_update_fdi_bc_bifurcation(struct intel_crtc *intel_crtc) case PIPE_A: break; case PIPE_B: - if (intel_crtc->config.fdi_lanes > 2) + if (intel_crtc->config->fdi_lanes > 2) WARN_ON(I915_READ(SOUTH_CHICKEN1) & FDI_BC_BIFURCATION_SELECT); else cpt_enable_fdi_bc_bifurcation(dev); @@ -3826,7 +3793,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc) 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) + if (intel_crtc->config->shared_dpll == DPLL_ID_PCH_PLL_B) temp |= sel; else temp &= ~sel; @@ -3849,7 +3816,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc) intel_fdi_normal_train(crtc); /* For PCH DP, enable TRANS_DP_CTL */ - if (HAS_PCH_CPT(dev) && intel_crtc->config.has_dp_encoder) { + if (HAS_PCH_CPT(dev) && intel_crtc->config->has_dp_encoder) { u32 bpc = (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) >> 5; reg = TRANS_DP_CTL(pipe); temp = I915_READ(reg); @@ -3890,7 +3857,7 @@ 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; + enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder; assert_pch_transcoder_disabled(dev_priv, TRANSCODER_A); @@ -3920,10 +3887,11 @@ void intel_put_shared_dpll(struct intel_crtc *crtc) WARN_ON(pll->active); } - crtc->config.shared_dpll = DPLL_ID_PRIVATE; + crtc->config->shared_dpll = DPLL_ID_PRIVATE; } -struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc) +struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc, + struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; struct intel_shared_dpll *pll; @@ -3949,7 +3917,7 @@ struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc) if (pll->new_config->crtc_mask == 0) continue; - if (memcmp(&crtc->new_config->dpll_hw_state, + if (memcmp(&crtc_state->dpll_hw_state, &pll->new_config->hw_state, sizeof(pll->new_config->hw_state)) == 0) { DRM_DEBUG_KMS("CRTC:%d sharing existing %s (crtc mask 0x%08x, ative %d)\n", @@ -3974,9 +3942,9 @@ struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc) found: if (pll->new_config->crtc_mask == 0) - pll->new_config->hw_state = crtc->new_config->dpll_hw_state; + pll->new_config->hw_state = crtc_state->dpll_hw_state; - crtc->new_config->shared_dpll = i; + crtc_state->shared_dpll = i; DRM_DEBUG_DRIVER("using %s for pipe %c\n", pll->name, pipe_name(crtc->pipe)); @@ -4073,10 +4041,10 @@ static void skylake_pfit_enable(struct intel_crtc *crtc) struct drm_i915_private *dev_priv = dev->dev_private; int pipe = crtc->pipe; - if (crtc->config.pch_pfit.enabled) { + if (crtc->config->pch_pfit.enabled) { I915_WRITE(PS_CTL(pipe), PS_ENABLE); - I915_WRITE(PS_WIN_POS(pipe), crtc->config.pch_pfit.pos); - I915_WRITE(PS_WIN_SZ(pipe), crtc->config.pch_pfit.size); + I915_WRITE(PS_WIN_POS(pipe), crtc->config->pch_pfit.pos); + I915_WRITE(PS_WIN_SZ(pipe), crtc->config->pch_pfit.size); } } @@ -4086,7 +4054,7 @@ static void ironlake_pfit_enable(struct intel_crtc *crtc) struct drm_i915_private *dev_priv = dev->dev_private; int pipe = crtc->pipe; - if (crtc->config.pch_pfit.enabled) { + if (crtc->config->pch_pfit.enabled) { /* Force use of hard-coded filter coefficients * as some pre-programmed values are broken, * e.g. x201. @@ -4096,12 +4064,12 @@ static void ironlake_pfit_enable(struct intel_crtc *crtc) 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); + 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) +static void intel_enable_sprite_planes(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; enum pipe pipe = to_intel_crtc(crtc)->pipe; @@ -4115,7 +4083,7 @@ static void intel_enable_planes(struct drm_crtc *crtc) } } -static void intel_disable_planes(struct drm_crtc *crtc) +static void intel_disable_sprite_planes(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; enum pipe pipe = to_intel_crtc(crtc)->pipe; @@ -4125,7 +4093,7 @@ static void intel_disable_planes(struct drm_crtc *crtc) drm_for_each_legacy_plane(plane, &dev->mode_config.plane_list) { intel_plane = to_intel_plane(plane); if (intel_plane->pipe == pipe) - intel_plane_disable(&intel_plane->base); + plane->funcs->disable_plane(plane); } } @@ -4134,7 +4102,7 @@ void hsw_enable_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) + if (!crtc->config->ips_enabled) return; /* We can only enable IPS after we enable a plane and wait for a vblank */ @@ -4167,7 +4135,7 @@ 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) + if (!crtc->config->ips_enabled) return; assert_plane_enabled(dev_priv, crtc->plane); @@ -4216,7 +4184,7 @@ static void intel_crtc_load_lut(struct drm_crtc *crtc) /* 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 (IS_HASWELL(dev) && intel_crtc->config.ips_enabled && + if (IS_HASWELL(dev) && intel_crtc->config->ips_enabled && ((I915_READ(GAMMA_MODE(pipe)) & GAMMA_MODE_MODE_MASK) == GAMMA_MODE_MODE_SPLIT)) { hsw_disable_ips(intel_crtc); @@ -4259,14 +4227,14 @@ static void intel_crtc_enable_planes(struct drm_crtc *crtc) int pipe = intel_crtc->pipe; intel_enable_primary_hw_plane(crtc->primary, crtc); - intel_enable_planes(crtc); + intel_enable_sprite_planes(crtc); intel_crtc_update_cursor(crtc, true); intel_crtc_dpms_overlay(intel_crtc, true); hsw_enable_ips(intel_crtc); mutex_lock(&dev->struct_mutex); - intel_update_fbc(dev); + intel_fbc_update(dev); mutex_unlock(&dev->struct_mutex); /* @@ -4288,13 +4256,13 @@ static void intel_crtc_disable_planes(struct drm_crtc *crtc) intel_crtc_wait_for_pending_flips(crtc); if (dev_priv->fbc.plane == plane) - intel_disable_fbc(dev); + intel_fbc_disable(dev); hsw_disable_ips(intel_crtc); intel_crtc_dpms_overlay(intel_crtc, false); intel_crtc_update_cursor(crtc, false); - intel_disable_planes(crtc); + intel_disable_sprite_planes(crtc); intel_disable_primary_hw_plane(crtc->primary, crtc); /* @@ -4318,17 +4286,17 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) if (intel_crtc->active) return; - if (intel_crtc->config.has_pch_encoder) + if (intel_crtc->config->has_pch_encoder) intel_prepare_shared_dpll(intel_crtc); - if (intel_crtc->config.has_dp_encoder) + if (intel_crtc->config->has_dp_encoder) intel_dp_set_m_n(intel_crtc); intel_set_pipe_timings(intel_crtc); - if (intel_crtc->config.has_pch_encoder) { + if (intel_crtc->config->has_pch_encoder) { intel_cpu_transcoder_set_m_n(intel_crtc, - &intel_crtc->config.fdi_m_n, NULL); + &intel_crtc->config->fdi_m_n, NULL); } ironlake_set_pipeconf(crtc); @@ -4342,7 +4310,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) if (encoder->pre_enable) encoder->pre_enable(encoder); - if (intel_crtc->config.has_pch_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. */ @@ -4363,18 +4331,18 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) intel_update_watermarks(crtc); intel_enable_pipe(intel_crtc); - if (intel_crtc->config.has_pch_encoder) + if (intel_crtc->config->has_pch_encoder) ironlake_pch_enable(crtc); + assert_vblank_disabled(crtc); + drm_crtc_vblank_on(crtc); + for_each_encoder_on_crtc(dev, crtc, encoder) encoder->enable(encoder); if (HAS_PCH_CPT(dev)) cpt_verify_modeset(dev, intel_crtc->pipe); - assert_vblank_disabled(crtc); - drm_crtc_vblank_on(crtc); - intel_crtc_enable_planes(crtc); } @@ -4429,19 +4397,19 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) if (intel_crtc_to_shared_dpll(intel_crtc)) intel_enable_shared_dpll(intel_crtc); - if (intel_crtc->config.has_dp_encoder) + if (intel_crtc->config->has_dp_encoder) intel_dp_set_m_n(intel_crtc); intel_set_pipe_timings(intel_crtc); - if (intel_crtc->config.cpu_transcoder != TRANSCODER_EDP) { - I915_WRITE(PIPE_MULT(intel_crtc->config.cpu_transcoder), - intel_crtc->config.pixel_multiplier - 1); + if (intel_crtc->config->cpu_transcoder != TRANSCODER_EDP) { + I915_WRITE(PIPE_MULT(intel_crtc->config->cpu_transcoder), + intel_crtc->config->pixel_multiplier - 1); } - if (intel_crtc->config.has_pch_encoder) { + if (intel_crtc->config->has_pch_encoder) { intel_cpu_transcoder_set_m_n(intel_crtc, - &intel_crtc->config.fdi_m_n, NULL); + &intel_crtc->config->fdi_m_n, NULL); } haswell_set_pipeconf(crtc); @@ -4455,7 +4423,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) if (encoder->pre_enable) encoder->pre_enable(encoder); - if (intel_crtc->config.has_pch_encoder) { + if (intel_crtc->config->has_pch_encoder) { intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A, true); dev_priv->display.fdi_link_train(crtc); @@ -4480,20 +4448,20 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) intel_update_watermarks(crtc); intel_enable_pipe(intel_crtc); - if (intel_crtc->config.has_pch_encoder) + if (intel_crtc->config->has_pch_encoder) lpt_pch_enable(crtc); - if (intel_crtc->config.dp_encoder_is_mst) + if (intel_crtc->config->dp_encoder_is_mst) intel_ddi_set_vc_payload_alloc(crtc, true); + assert_vblank_disabled(crtc); + drm_crtc_vblank_on(crtc); + for_each_encoder_on_crtc(dev, crtc, encoder) { encoder->enable(encoder); intel_opregion_notify_encoder(encoder, true); } - assert_vblank_disabled(crtc); - drm_crtc_vblank_on(crtc); - /* If we change the relative order between pipe/planes enabling, we need * to change the workaround. */ haswell_mode_set_planes_workaround(intel_crtc); @@ -4508,7 +4476,7 @@ static void skylake_pfit_disable(struct intel_crtc *crtc) /* 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.enabled) { + if (crtc->config->pch_pfit.enabled) { I915_WRITE(PS_CTL(pipe), 0); I915_WRITE(PS_WIN_POS(pipe), 0); I915_WRITE(PS_WIN_SZ(pipe), 0); @@ -4523,7 +4491,7 @@ static void ironlake_pfit_disable(struct intel_crtc *crtc) /* 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.enabled) { + if (crtc->config->pch_pfit.enabled) { I915_WRITE(PF_CTL(pipe), 0); I915_WRITE(PF_WIN_POS(pipe), 0); I915_WRITE(PF_WIN_SZ(pipe), 0); @@ -4544,13 +4512,13 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) intel_crtc_disable_planes(crtc); - drm_crtc_vblank_off(crtc); - assert_vblank_disabled(crtc); - for_each_encoder_on_crtc(dev, crtc, encoder) encoder->disable(encoder); - if (intel_crtc->config.has_pch_encoder) + drm_crtc_vblank_off(crtc); + assert_vblank_disabled(crtc); + + if (intel_crtc->config->has_pch_encoder) intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, false); intel_disable_pipe(intel_crtc); @@ -4561,7 +4529,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) if (encoder->post_disable) encoder->post_disable(encoder); - if (intel_crtc->config.has_pch_encoder) { + if (intel_crtc->config->has_pch_encoder) { ironlake_fdi_disable(crtc); ironlake_disable_pch_transcoder(dev_priv, pipe); @@ -4591,7 +4559,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) intel_update_watermarks(crtc); mutex_lock(&dev->struct_mutex); - intel_update_fbc(dev); + intel_fbc_update(dev); mutex_unlock(&dev->struct_mutex); } @@ -4601,27 +4569,27 @@ static void haswell_crtc_disable(struct drm_crtc *crtc) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_encoder *encoder; - enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder; + enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder; if (!intel_crtc->active) return; intel_crtc_disable_planes(crtc); - drm_crtc_vblank_off(crtc); - assert_vblank_disabled(crtc); - for_each_encoder_on_crtc(dev, crtc, encoder) { intel_opregion_notify_encoder(encoder, false); encoder->disable(encoder); } - if (intel_crtc->config.has_pch_encoder) + drm_crtc_vblank_off(crtc); + assert_vblank_disabled(crtc); + + if (intel_crtc->config->has_pch_encoder) intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A, false); intel_disable_pipe(intel_crtc); - if (intel_crtc->config.dp_encoder_is_mst) + if (intel_crtc->config->dp_encoder_is_mst) intel_ddi_set_vc_payload_alloc(crtc, false); intel_ddi_disable_transcoder_func(dev_priv, cpu_transcoder); @@ -4633,7 +4601,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc) intel_ddi_disable_pipe_clock(intel_crtc); - if (intel_crtc->config.has_pch_encoder) { + if (intel_crtc->config->has_pch_encoder) { lpt_disable_pch_transcoder(dev_priv); intel_ddi_fdi_disable(crtc); } @@ -4646,7 +4614,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc) intel_update_watermarks(crtc); mutex_lock(&dev->struct_mutex); - intel_update_fbc(dev); + intel_fbc_update(dev); mutex_unlock(&dev->struct_mutex); if (intel_crtc_to_shared_dpll(intel_crtc)) @@ -4664,9 +4632,9 @@ 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; + struct intel_crtc_state *pipe_config = crtc->config; - if (!crtc->config.gmch_pfit.control) + if (!pipe_config->gmch_pfit.control) return; /* @@ -4745,8 +4713,8 @@ static unsigned long get_crtc_power_domains(struct drm_crtc *crtc) mask = BIT(POWER_DOMAIN_PIPE(pipe)); mask |= BIT(POWER_DOMAIN_TRANSCODER(transcoder)); - if (intel_crtc->config.pch_pfit.enabled || - intel_crtc->config.pch_pfit.force_thru) + if (intel_crtc->config->pch_pfit.enabled || + intel_crtc->config->pch_pfit.force_thru) mask |= BIT(POWER_DOMAIN_PIPE_PANEL_FITTER(pipe)); for_each_encoder_on_crtc(dev, crtc, intel_encoder) @@ -4909,7 +4877,7 @@ static void cherryview_set_cdclk(struct drm_device *dev, int cdclk) cmd = 0; break; default: - WARN_ON(1); + MISSING_CASE(cdclk); return; } @@ -4970,7 +4938,7 @@ static int intel_mode_max_pixclk(struct drm_i915_private *dev_priv) for_each_intel_crtc(dev, intel_crtc) { if (intel_crtc->new_enabled) max_pixclk = max(max_pixclk, - intel_crtc->new_config->adjusted_mode.crtc_clock); + intel_crtc->new_config->base.adjusted_mode.crtc_clock); } return max_pixclk; @@ -5038,12 +5006,12 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc) if (!is_dsi) { if (IS_CHERRYVIEW(dev)) - chv_prepare_pll(intel_crtc, &intel_crtc->config); + chv_prepare_pll(intel_crtc, intel_crtc->config); else - vlv_prepare_pll(intel_crtc, &intel_crtc->config); + vlv_prepare_pll(intel_crtc, intel_crtc->config); } - if (intel_crtc->config.has_dp_encoder) + if (intel_crtc->config->has_dp_encoder) intel_dp_set_m_n(intel_crtc); intel_set_pipe_timings(intel_crtc); @@ -5067,9 +5035,9 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc) if (!is_dsi) { if (IS_CHERRYVIEW(dev)) - chv_enable_pll(intel_crtc, &intel_crtc->config); + chv_enable_pll(intel_crtc, intel_crtc->config); else - vlv_enable_pll(intel_crtc, &intel_crtc->config); + vlv_enable_pll(intel_crtc, intel_crtc->config); } for_each_encoder_on_crtc(dev, crtc, encoder) @@ -5083,12 +5051,12 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc) intel_update_watermarks(crtc); intel_enable_pipe(intel_crtc); - for_each_encoder_on_crtc(dev, crtc, encoder) - encoder->enable(encoder); - assert_vblank_disabled(crtc); drm_crtc_vblank_on(crtc); + for_each_encoder_on_crtc(dev, crtc, encoder) + encoder->enable(encoder); + intel_crtc_enable_planes(crtc); /* Underruns don't raise interrupts, so check manually. */ @@ -5100,8 +5068,8 @@ static void i9xx_set_pll_dividers(struct intel_crtc *crtc) struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - I915_WRITE(FP0(crtc->pipe), crtc->config.dpll_hw_state.fp0); - I915_WRITE(FP1(crtc->pipe), crtc->config.dpll_hw_state.fp1); + I915_WRITE(FP0(crtc->pipe), crtc->config->dpll_hw_state.fp0); + I915_WRITE(FP1(crtc->pipe), crtc->config->dpll_hw_state.fp1); } static void i9xx_crtc_enable(struct drm_crtc *crtc) @@ -5119,7 +5087,7 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc) i9xx_set_pll_dividers(intel_crtc); - if (intel_crtc->config.has_dp_encoder) + if (intel_crtc->config->has_dp_encoder) intel_dp_set_m_n(intel_crtc); intel_set_pipe_timings(intel_crtc); @@ -5144,12 +5112,12 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc) intel_update_watermarks(crtc); intel_enable_pipe(intel_crtc); - for_each_encoder_on_crtc(dev, crtc, encoder) - encoder->enable(encoder); - assert_vblank_disabled(crtc); drm_crtc_vblank_on(crtc); + for_each_encoder_on_crtc(dev, crtc, encoder) + encoder->enable(encoder); + intel_crtc_enable_planes(crtc); /* @@ -5171,7 +5139,7 @@ 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) + if (!crtc->config->gmch_pfit.control) return; assert_pipe_disabled(dev_priv, crtc->pipe); @@ -5221,12 +5189,12 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc) */ intel_wait_for_vblank(dev, pipe); - drm_crtc_vblank_off(crtc); - assert_vblank_disabled(crtc); - for_each_encoder_on_crtc(dev, crtc, encoder) encoder->disable(encoder); + drm_crtc_vblank_off(crtc); + assert_vblank_disabled(crtc); + intel_disable_pipe(intel_crtc); i9xx_pfit_disable(intel_crtc); @@ -5251,7 +5219,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc) intel_update_watermarks(crtc); mutex_lock(&dev->struct_mutex); - intel_update_fbc(dev); + intel_fbc_update(dev); mutex_unlock(&dev->struct_mutex); } @@ -5309,8 +5277,6 @@ 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 drm_i915_gem_object *old_obj = intel_fb_obj(crtc->primary->fb); - enum pipe pipe = to_intel_crtc(crtc)->pipe; /* crtc should still be enabled when we disable it. */ WARN_ON(!crtc->enabled); @@ -5318,14 +5284,7 @@ static void intel_crtc_disable(struct drm_crtc *crtc) dev_priv->display.crtc_disable(crtc); dev_priv->display.off(crtc); - if (crtc->primary->fb) { - mutex_lock(&dev->struct_mutex); - intel_unpin_fb_obj(old_obj); - i915_gem_track_fb(old_obj, NULL, - INTEL_FRONTBUFFER_PRIMARY(pipe)); - mutex_unlock(&dev->struct_mutex); - crtc->primary->fb = NULL; - } + crtc->primary->funcs->disable_plane(crtc->primary); /* Update computed state. */ list_for_each_entry(connector, &dev->mode_config.connector_list, head) { @@ -5382,25 +5341,25 @@ static void intel_connector_check_state(struct intel_connector *connector) if (connector->mst_port) return; - WARN(connector->base.dpms == DRM_MODE_DPMS_OFF, + I915_STATE_WARN(connector->base.dpms == DRM_MODE_DPMS_OFF, "wrong connector dpms state\n"); - WARN(connector->base.encoder != &encoder->base, + I915_STATE_WARN(connector->base.encoder != &encoder->base, "active connector not linked to encoder\n"); if (encoder) { - WARN(!encoder->connectors_active, + I915_STATE_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)) + I915_STATE_WARN(!encoder_enabled, "encoder not enabled\n"); + if (I915_STATE_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, + I915_STATE_WARN(!crtc->enabled, "crtc not enabled\n"); + I915_STATE_WARN(!to_intel_crtc(crtc)->active, "crtc not active\n"); + I915_STATE_WARN(pipe != to_intel_crtc(crtc)->pipe, "encoder active on the wrong pipe\n"); } } @@ -5438,7 +5397,7 @@ bool intel_connector_get_hw_state(struct intel_connector *connector) } static bool ironlake_check_fdi_lanes(struct drm_device *dev, enum pipe pipe, - struct intel_crtc_config *pipe_config) + struct intel_crtc_state *pipe_config) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *pipe_B_crtc = @@ -5479,7 +5438,7 @@ static bool ironlake_check_fdi_lanes(struct drm_device *dev, enum pipe pipe, return true; case PIPE_C: if (!pipe_has_enabled_pch(pipe_B_crtc) || - pipe_B_crtc->config.fdi_lanes <= 2) { + 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); @@ -5497,10 +5456,10 @@ static bool ironlake_check_fdi_lanes(struct drm_device *dev, enum pipe pipe, #define RETRY 1 static int ironlake_fdi_compute_config(struct intel_crtc *intel_crtc, - struct intel_crtc_config *pipe_config) + struct intel_crtc_state *pipe_config) { struct drm_device *dev = intel_crtc->base.dev; - struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode; + struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; int lane, link_bw, fdi_dotclock; bool setup_ok, needs_recompute = false; @@ -5543,7 +5502,7 @@ retry: } static void hsw_compute_ips_config(struct intel_crtc *crtc, - struct intel_crtc_config *pipe_config) + struct intel_crtc_state *pipe_config) { pipe_config->ips_enabled = i915.enable_ips && hsw_crtc_supports_ips(crtc) && @@ -5551,11 +5510,11 @@ static void hsw_compute_ips_config(struct intel_crtc *crtc, } static int intel_crtc_compute_config(struct intel_crtc *crtc, - struct intel_crtc_config *pipe_config) + struct intel_crtc_state *pipe_config) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode; + struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; /* FIXME should check pixel clock limits on all platforms */ if (INTEL_INFO(dev)->gen < 4) { @@ -5800,30 +5759,31 @@ static uint32_t i9xx_dpll_compute_fp(struct dpll *dpll) } static void i9xx_update_pll_dividers(struct intel_crtc *crtc, + struct intel_crtc_state *crtc_state, intel_clock_t *reduced_clock) { struct drm_device *dev = crtc->base.dev; u32 fp, fp2 = 0; if (IS_PINEVIEW(dev)) { - fp = pnv_dpll_compute_fp(&crtc->new_config->dpll); + fp = pnv_dpll_compute_fp(&crtc_state->dpll); if (reduced_clock) fp2 = pnv_dpll_compute_fp(reduced_clock); } else { - fp = i9xx_dpll_compute_fp(&crtc->new_config->dpll); + fp = i9xx_dpll_compute_fp(&crtc_state->dpll); if (reduced_clock) fp2 = i9xx_dpll_compute_fp(reduced_clock); } - crtc->new_config->dpll_hw_state.fp0 = fp; + crtc_state->dpll_hw_state.fp0 = fp; crtc->lowfreq_avail = false; if (intel_pipe_will_have_type(crtc, INTEL_OUTPUT_LVDS) && reduced_clock && i915.powersave) { - crtc->new_config->dpll_hw_state.fp1 = fp2; + crtc_state->dpll_hw_state.fp1 = fp2; crtc->lowfreq_avail = true; } else { - crtc->new_config->dpll_hw_state.fp1 = fp; + crtc_state->dpll_hw_state.fp1 = fp; } } @@ -5876,7 +5836,7 @@ static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc, 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; + 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); @@ -5888,7 +5848,7 @@ static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc, * registers are not unnecessarily accessed). */ if (m2_n2 && INTEL_INFO(dev)->gen < 8 && - crtc->config.has_drrs) { + crtc->config->has_drrs) { I915_WRITE(PIPE_DATA_M2(transcoder), TU_SIZE(m2_n2->tu) | m2_n2->gmch_m); I915_WRITE(PIPE_DATA_N2(transcoder), m2_n2->gmch_n); @@ -5905,15 +5865,15 @@ static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc, 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); + 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, - &crtc->config.dp_m2_n2); + intel_cpu_transcoder_set_m_n(crtc, &crtc->config->dp_m_n, + &crtc->config->dp_m2_n2); } static void vlv_update_pll(struct intel_crtc *crtc, - struct intel_crtc_config *pipe_config) + struct intel_crtc_state *pipe_config) { u32 dpll, dpll_md; @@ -5936,7 +5896,7 @@ static void vlv_update_pll(struct intel_crtc *crtc, } static void vlv_prepare_pll(struct intel_crtc *crtc, - const struct intel_crtc_config *pipe_config) + const struct intel_crtc_state *pipe_config) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -5997,7 +5957,7 @@ static void vlv_prepare_pll(struct intel_crtc *crtc, vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW10(pipe), 0x00d0000f); - if (crtc->config.has_dp_encoder) { + if (pipe_config->has_dp_encoder) { /* Use SSC source */ if (pipe == PIPE_A) vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe), @@ -6027,7 +5987,7 @@ static void vlv_prepare_pll(struct intel_crtc *crtc, } static void chv_update_pll(struct intel_crtc *crtc, - struct intel_crtc_config *pipe_config) + struct intel_crtc_state *pipe_config) { pipe_config->dpll_hw_state.dpll = DPLL_SSC_REF_CLOCK_CHV | DPLL_REFA_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS | @@ -6040,7 +6000,7 @@ static void chv_update_pll(struct intel_crtc *crtc, } static void chv_prepare_pll(struct intel_crtc *crtc, - const struct intel_crtc_config *pipe_config) + const struct intel_crtc_state *pipe_config) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -6125,7 +6085,7 @@ void vlv_force_pll_on(struct drm_device *dev, enum pipe pipe, { struct intel_crtc *crtc = to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe)); - struct intel_crtc_config pipe_config = { + struct intel_crtc_state pipe_config = { .pixel_multiplier = 1, .dpll = *dpll, }; @@ -6158,6 +6118,7 @@ void vlv_force_pll_off(struct drm_device *dev, enum pipe pipe) } static void i9xx_update_pll(struct intel_crtc *crtc, + struct intel_crtc_state *crtc_state, intel_clock_t *reduced_clock, int num_connectors) { @@ -6165,9 +6126,9 @@ static void i9xx_update_pll(struct intel_crtc *crtc, struct drm_i915_private *dev_priv = dev->dev_private; u32 dpll; bool is_sdvo; - struct dpll *clock = &crtc->new_config->dpll; + struct dpll *clock = &crtc_state->dpll; - i9xx_update_pll_dividers(crtc, reduced_clock); + i9xx_update_pll_dividers(crtc, crtc_state, reduced_clock); is_sdvo = intel_pipe_will_have_type(crtc, INTEL_OUTPUT_SDVO) || intel_pipe_will_have_type(crtc, INTEL_OUTPUT_HDMI); @@ -6180,14 +6141,14 @@ static void i9xx_update_pll(struct intel_crtc *crtc, dpll |= DPLLB_MODE_DAC_SERIAL; if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) { - dpll |= (crtc->new_config->pixel_multiplier - 1) + dpll |= (crtc_state->pixel_multiplier - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; } if (is_sdvo) dpll |= DPLL_SDVO_HIGH_SPEED; - if (crtc->new_config->has_dp_encoder) + if (crtc_state->has_dp_encoder) dpll |= DPLL_SDVO_HIGH_SPEED; /* compute bitmask from p1 value */ @@ -6215,7 +6176,7 @@ static void i9xx_update_pll(struct intel_crtc *crtc, if (INTEL_INFO(dev)->gen >= 4) dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT); - if (crtc->new_config->sdvo_tv_clock) + if (crtc_state->sdvo_tv_clock) dpll |= PLL_REF_INPUT_TVCLKINBC; else if (intel_pipe_will_have_type(crtc, INTEL_OUTPUT_LVDS) && intel_panel_use_ssc(dev_priv) && num_connectors < 2) @@ -6224,25 +6185,26 @@ static void i9xx_update_pll(struct intel_crtc *crtc, dpll |= PLL_REF_INPUT_DREFCLK; dpll |= DPLL_VCO_ENABLE; - crtc->new_config->dpll_hw_state.dpll = dpll; + crtc_state->dpll_hw_state.dpll = dpll; if (INTEL_INFO(dev)->gen >= 4) { - u32 dpll_md = (crtc->new_config->pixel_multiplier - 1) + u32 dpll_md = (crtc_state->pixel_multiplier - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT; - crtc->new_config->dpll_hw_state.dpll_md = dpll_md; + crtc_state->dpll_hw_state.dpll_md = dpll_md; } } static void i8xx_update_pll(struct intel_crtc *crtc, + struct intel_crtc_state *crtc_state, 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->new_config->dpll; + struct dpll *clock = &crtc_state->dpll; - i9xx_update_pll_dividers(crtc, reduced_clock); + i9xx_update_pll_dividers(crtc, crtc_state, reduced_clock); dpll = DPLL_VGA_MODE_DIS; @@ -6267,7 +6229,7 @@ static void i8xx_update_pll(struct intel_crtc *crtc, dpll |= PLL_REF_INPUT_DREFCLK; dpll |= DPLL_VCO_ENABLE; - crtc->new_config->dpll_hw_state.dpll = dpll; + crtc_state->dpll_hw_state.dpll = dpll; } static void intel_set_pipe_timings(struct intel_crtc *intel_crtc) @@ -6275,9 +6237,9 @@ 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; + enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder; struct drm_display_mode *adjusted_mode = - &intel_crtc->config.adjusted_mode; + &intel_crtc->config->base.adjusted_mode; uint32_t crtc_vtotal, crtc_vblank_end; int vsyncshift = 0; @@ -6335,12 +6297,12 @@ static void intel_set_pipe_timings(struct intel_crtc *intel_crtc) * always be the user's requested size. */ I915_WRITE(PIPESRC(pipe), - ((intel_crtc->config.pipe_src_w - 1) << 16) | - (intel_crtc->config.pipe_src_h - 1)); + ((intel_crtc->config->pipe_src_w - 1) << 16) | + (intel_crtc->config->pipe_src_h - 1)); } static void intel_get_pipe_timings(struct intel_crtc *crtc, - struct intel_crtc_config *pipe_config) + struct intel_crtc_state *pipe_config) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -6348,56 +6310,56 @@ static void intel_get_pipe_timings(struct intel_crtc *crtc, 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; + pipe_config->base.adjusted_mode.crtc_hdisplay = (tmp & 0xffff) + 1; + pipe_config->base.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; + pipe_config->base.adjusted_mode.crtc_hblank_start = (tmp & 0xffff) + 1; + pipe_config->base.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; + pipe_config->base.adjusted_mode.crtc_hsync_start = (tmp & 0xffff) + 1; + pipe_config->base.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; + pipe_config->base.adjusted_mode.crtc_vdisplay = (tmp & 0xffff) + 1; + pipe_config->base.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; + pipe_config->base.adjusted_mode.crtc_vblank_start = (tmp & 0xffff) + 1; + pipe_config->base.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; + pipe_config->base.adjusted_mode.crtc_vsync_start = (tmp & 0xffff) + 1; + pipe_config->base.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; + pipe_config->base.adjusted_mode.flags |= DRM_MODE_FLAG_INTERLACE; + pipe_config->base.adjusted_mode.crtc_vtotal += 1; + pipe_config->base.adjusted_mode.crtc_vblank_end += 1; } tmp = I915_READ(PIPESRC(crtc->pipe)); pipe_config->pipe_src_h = (tmp & 0xffff) + 1; pipe_config->pipe_src_w = ((tmp >> 16) & 0xffff) + 1; - pipe_config->requested_mode.vdisplay = pipe_config->pipe_src_h; - pipe_config->requested_mode.hdisplay = pipe_config->pipe_src_w; + pipe_config->base.mode.vdisplay = pipe_config->pipe_src_h; + pipe_config->base.mode.hdisplay = pipe_config->pipe_src_w; } void intel_mode_from_pipe_config(struct drm_display_mode *mode, - struct intel_crtc_config *pipe_config) + struct intel_crtc_state *pipe_config) { - mode->hdisplay = pipe_config->adjusted_mode.crtc_hdisplay; - mode->htotal = pipe_config->adjusted_mode.crtc_htotal; - mode->hsync_start = pipe_config->adjusted_mode.crtc_hsync_start; - mode->hsync_end = pipe_config->adjusted_mode.crtc_hsync_end; + mode->hdisplay = pipe_config->base.adjusted_mode.crtc_hdisplay; + mode->htotal = pipe_config->base.adjusted_mode.crtc_htotal; + mode->hsync_start = pipe_config->base.adjusted_mode.crtc_hsync_start; + mode->hsync_end = pipe_config->base.adjusted_mode.crtc_hsync_end; - mode->vdisplay = pipe_config->adjusted_mode.crtc_vdisplay; - mode->vtotal = pipe_config->adjusted_mode.crtc_vtotal; - mode->vsync_start = pipe_config->adjusted_mode.crtc_vsync_start; - mode->vsync_end = pipe_config->adjusted_mode.crtc_vsync_end; + mode->vdisplay = pipe_config->base.adjusted_mode.crtc_vdisplay; + mode->vtotal = pipe_config->base.adjusted_mode.crtc_vtotal; + mode->vsync_start = pipe_config->base.adjusted_mode.crtc_vsync_start; + mode->vsync_end = pipe_config->base.adjusted_mode.crtc_vsync_end; - mode->flags = pipe_config->adjusted_mode.flags; + mode->flags = pipe_config->base.adjusted_mode.flags; - mode->clock = pipe_config->adjusted_mode.crtc_clock; - mode->flags |= pipe_config->adjusted_mode.flags; + mode->clock = pipe_config->base.adjusted_mode.crtc_clock; + mode->flags |= pipe_config->base.adjusted_mode.flags; } static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc) @@ -6412,17 +6374,17 @@ static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc) (intel_crtc->pipe == PIPE_B && dev_priv->quirks & QUIRK_PIPEB_FORCE)) pipeconf |= I915_READ(PIPECONF(intel_crtc->pipe)) & PIPECONF_ENABLE; - if (intel_crtc->config.double_wide) + if (intel_crtc->config->double_wide) 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) + 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) { + switch (intel_crtc->config->pipe_bpp) { case 18: pipeconf |= PIPECONF_6BPC; break; @@ -6447,7 +6409,7 @@ static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc) } } - if (intel_crtc->config.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) { + if (intel_crtc->config->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) { if (INTEL_INFO(dev)->gen < 4 || intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_SDVO)) pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION; @@ -6456,14 +6418,15 @@ static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc) } else pipeconf |= PIPECONF_PROGRESSIVE; - if (IS_VALLEYVIEW(dev) && intel_crtc->config.limited_color_range) + 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)); } -static int i9xx_crtc_compute_clock(struct intel_crtc *crtc) +static int i9xx_crtc_compute_clock(struct intel_crtc *crtc, + struct intel_crtc_state *crtc_state) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -6495,7 +6458,7 @@ static int i9xx_crtc_compute_clock(struct intel_crtc *crtc) if (is_dsi) return 0; - if (!crtc->new_config->clock_set) { + if (!crtc_state->clock_set) { refclk = i9xx_get_refclk(crtc, num_connectors); /* @@ -6506,7 +6469,7 @@ static int i9xx_crtc_compute_clock(struct intel_crtc *crtc) */ limit = intel_limit(crtc, refclk); ok = dev_priv->display.find_dpll(limit, crtc, - crtc->new_config->port_clock, + crtc_state->port_clock, refclk, NULL, &clock); if (!ok) { DRM_ERROR("Couldn't find PLL settings for mode!\n"); @@ -6527,23 +6490,23 @@ static int i9xx_crtc_compute_clock(struct intel_crtc *crtc) &reduced_clock); } /* Compat-code for transition, will disappear. */ - crtc->new_config->dpll.n = clock.n; - crtc->new_config->dpll.m1 = clock.m1; - crtc->new_config->dpll.m2 = clock.m2; - crtc->new_config->dpll.p1 = clock.p1; - crtc->new_config->dpll.p2 = clock.p2; + crtc_state->dpll.n = clock.n; + crtc_state->dpll.m1 = clock.m1; + crtc_state->dpll.m2 = clock.m2; + crtc_state->dpll.p1 = clock.p1; + crtc_state->dpll.p2 = clock.p2; } if (IS_GEN2(dev)) { - i8xx_update_pll(crtc, + i8xx_update_pll(crtc, crtc_state, has_reduced_clock ? &reduced_clock : NULL, num_connectors); } else if (IS_CHERRYVIEW(dev)) { - chv_update_pll(crtc, crtc->new_config); + chv_update_pll(crtc, crtc_state); } else if (IS_VALLEYVIEW(dev)) { - vlv_update_pll(crtc, crtc->new_config); + vlv_update_pll(crtc, crtc_state); } else { - i9xx_update_pll(crtc, + i9xx_update_pll(crtc, crtc_state, has_reduced_clock ? &reduced_clock : NULL, num_connectors); } @@ -6552,7 +6515,7 @@ static int i9xx_crtc_compute_clock(struct intel_crtc *crtc) } static void i9xx_get_pfit_config(struct intel_crtc *crtc, - struct intel_crtc_config *pipe_config) + struct intel_crtc_state *pipe_config) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -6582,7 +6545,7 @@ static void i9xx_get_pfit_config(struct intel_crtc *crtc, } static void vlv_crtc_clock_get(struct intel_crtc *crtc, - struct intel_crtc_config *pipe_config) + struct intel_crtc_state *pipe_config) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -6611,8 +6574,9 @@ static void vlv_crtc_clock_get(struct intel_crtc *crtc, pipe_config->port_clock = clock.dot / 5; } -static void i9xx_get_plane_config(struct intel_crtc *crtc, - struct intel_plane_config *plane_config) +static void +i9xx_get_initial_plane_config(struct intel_crtc *crtc, + struct intel_initial_plane_config *plane_config) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -6620,27 +6584,30 @@ static void i9xx_get_plane_config(struct intel_crtc *crtc, int pipe = crtc->pipe, plane = crtc->plane; int fourcc, pixel_format; int aligned_height; + struct drm_framebuffer *fb; + struct intel_framebuffer *intel_fb; - crtc->base.primary->fb = kzalloc(sizeof(struct intel_framebuffer), GFP_KERNEL); - if (!crtc->base.primary->fb) { + intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL); + if (!intel_fb) { DRM_DEBUG_KMS("failed to alloc fb\n"); return; } + fb = &intel_fb->base; + val = I915_READ(DSPCNTR(plane)); if (INTEL_INFO(dev)->gen >= 4) if (val & DISPPLANE_TILED) - plane_config->tiled = true; + plane_config->tiling = I915_TILING_X; pixel_format = val & DISPPLANE_PIXFORMAT_MASK; - fourcc = intel_format_to_fourcc(pixel_format); - crtc->base.primary->fb->pixel_format = fourcc; - crtc->base.primary->fb->bits_per_pixel = - drm_format_plane_cpp(fourcc, 0) * 8; + fourcc = i9xx_format_to_fourcc(pixel_format); + fb->pixel_format = fourcc; + fb->bits_per_pixel = drm_format_plane_cpp(fourcc, 0) * 8; if (INTEL_INFO(dev)->gen >= 4) { - if (plane_config->tiled) + if (plane_config->tiling) offset = I915_READ(DSPTILEOFF(plane)); else offset = I915_READ(DSPLINOFF(plane)); @@ -6651,29 +6618,27 @@ static void i9xx_get_plane_config(struct intel_crtc *crtc, plane_config->base = base; val = I915_READ(PIPESRC(pipe)); - crtc->base.primary->fb->width = ((val >> 16) & 0xfff) + 1; - crtc->base.primary->fb->height = ((val >> 0) & 0xfff) + 1; + fb->width = ((val >> 16) & 0xfff) + 1; + fb->height = ((val >> 0) & 0xfff) + 1; val = I915_READ(DSPSTRIDE(pipe)); - crtc->base.primary->fb->pitches[0] = val & 0xffffffc0; + fb->pitches[0] = val & 0xffffffc0; - aligned_height = intel_align_height(dev, crtc->base.primary->fb->height, - plane_config->tiled); + aligned_height = intel_fb_align_height(dev, fb->height, + plane_config->tiling); - plane_config->size = PAGE_ALIGN(crtc->base.primary->fb->pitches[0] * - aligned_height); + plane_config->size = PAGE_ALIGN(fb->pitches[0] * aligned_height); - DRM_DEBUG_KMS("pipe/plane %d/%d with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n", - pipe, plane, crtc->base.primary->fb->width, - crtc->base.primary->fb->height, - crtc->base.primary->fb->bits_per_pixel, base, - crtc->base.primary->fb->pitches[0], + DRM_DEBUG_KMS("pipe/plane %c/%d with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n", + pipe_name(pipe), plane, fb->width, fb->height, + fb->bits_per_pixel, base, fb->pitches[0], plane_config->size); + crtc->base.primary->fb = fb; } static void chv_crtc_clock_get(struct intel_crtc *crtc, - struct intel_crtc_config *pipe_config) + struct intel_crtc_state *pipe_config) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -6703,7 +6668,7 @@ static void chv_crtc_clock_get(struct intel_crtc *crtc, } static bool i9xx_get_pipe_config(struct intel_crtc *crtc, - struct intel_crtc_config *pipe_config) + struct intel_crtc_state *pipe_config) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -7183,7 +7148,7 @@ static void ironlake_set_pipeconf(struct drm_crtc *crtc) val = 0; - switch (intel_crtc->config.pipe_bpp) { + switch (intel_crtc->config->pipe_bpp) { case 18: val |= PIPECONF_6BPC; break; @@ -7201,15 +7166,15 @@ static void ironlake_set_pipeconf(struct drm_crtc *crtc) BUG(); } - if (intel_crtc->config.dither) + if (intel_crtc->config->dither) val |= (PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP); - if (intel_crtc->config.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) + if (intel_crtc->config->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) val |= PIPECONF_INTERLACED_ILK; else val |= PIPECONF_PROGRESSIVE; - if (intel_crtc->config.limited_color_range) + if (intel_crtc->config->limited_color_range) val |= PIPECONF_COLOR_RANGE_SELECT; I915_WRITE(PIPECONF(pipe), val); @@ -7238,7 +7203,7 @@ static void intel_set_pipe_csc(struct drm_crtc *crtc) * consideration. */ - if (intel_crtc->config.limited_color_range) + if (intel_crtc->config->limited_color_range) coeff = ((235 - 16) * (1 << 12) / 255) & 0xff8; /* 0.xxx... */ /* @@ -7262,7 +7227,7 @@ static void intel_set_pipe_csc(struct drm_crtc *crtc) if (INTEL_INFO(dev)->gen > 6) { uint16_t postoff = 0; - if (intel_crtc->config.limited_color_range) + if (intel_crtc->config->limited_color_range) postoff = (16 * (1 << 12) / 255) & 0x1fff; I915_WRITE(PIPE_CSC_POSTOFF_HI(pipe), postoff); @@ -7273,7 +7238,7 @@ static void intel_set_pipe_csc(struct drm_crtc *crtc) } else { uint32_t mode = CSC_MODE_YUV_TO_RGB; - if (intel_crtc->config.limited_color_range) + if (intel_crtc->config->limited_color_range) mode |= CSC_BLACK_SCREEN_OFFSET; I915_WRITE(PIPE_CSC_MODE(pipe), mode); @@ -7286,15 +7251,15 @@ static void haswell_set_pipeconf(struct drm_crtc *crtc) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); enum pipe pipe = intel_crtc->pipe; - enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder; + enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder; uint32_t val; val = 0; - if (IS_HASWELL(dev) && intel_crtc->config.dither) + if (IS_HASWELL(dev) && intel_crtc->config->dither) val |= (PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP); - if (intel_crtc->config.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) + if (intel_crtc->config->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) val |= PIPECONF_INTERLACED_ILK; else val |= PIPECONF_PROGRESSIVE; @@ -7308,7 +7273,7 @@ static void haswell_set_pipeconf(struct drm_crtc *crtc) if (IS_BROADWELL(dev) || INTEL_INFO(dev)->gen >= 9) { val = 0; - switch (intel_crtc->config.pipe_bpp) { + switch (intel_crtc->config->pipe_bpp) { case 18: val |= PIPEMISC_DITHER_6_BPC; break; @@ -7326,7 +7291,7 @@ static void haswell_set_pipeconf(struct drm_crtc *crtc) BUG(); } - if (intel_crtc->config.dither) + if (intel_crtc->config->dither) val |= PIPEMISC_DITHER_ENABLE | PIPEMISC_DITHER_TYPE_SP; I915_WRITE(PIPEMISC(pipe), val); @@ -7334,6 +7299,7 @@ static void haswell_set_pipeconf(struct drm_crtc *crtc) } static bool ironlake_compute_clocks(struct drm_crtc *crtc, + struct intel_crtc_state *crtc_state, intel_clock_t *clock, bool *has_reduced_clock, intel_clock_t *reduced_clock) @@ -7356,7 +7322,7 @@ static bool ironlake_compute_clocks(struct drm_crtc *crtc, */ limit = intel_limit(intel_crtc, refclk); ret = dev_priv->display.find_dpll(limit, intel_crtc, - intel_crtc->new_config->port_clock, + crtc_state->port_clock, refclk, NULL, clock); if (!ret) return false; @@ -7395,6 +7361,7 @@ static bool ironlake_needs_fb_cb_tune(struct dpll *dpll, int factor) } static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc, + struct intel_crtc_state *crtc_state, u32 *fp, intel_clock_t *reduced_clock, u32 *fp2) { @@ -7432,10 +7399,10 @@ static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc, dev_priv->vbt.lvds_ssc_freq == 100000) || (HAS_PCH_IBX(dev) && intel_is_dual_link_lvds(dev))) factor = 25; - } else if (intel_crtc->new_config->sdvo_tv_clock) + } else if (crtc_state->sdvo_tv_clock) factor = 20; - if (ironlake_needs_fb_cb_tune(&intel_crtc->new_config->dpll, factor)) + if (ironlake_needs_fb_cb_tune(&crtc_state->dpll, factor)) *fp |= FP_CB_TUNE; if (fp2 && (reduced_clock->m < factor * reduced_clock->n)) @@ -7448,20 +7415,20 @@ static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc, else dpll |= DPLLB_MODE_DAC_SERIAL; - dpll |= (intel_crtc->new_config->pixel_multiplier - 1) + dpll |= (crtc_state->pixel_multiplier - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT; if (is_sdvo) dpll |= DPLL_SDVO_HIGH_SPEED; - if (intel_crtc->new_config->has_dp_encoder) + if (crtc_state->has_dp_encoder) dpll |= DPLL_SDVO_HIGH_SPEED; /* compute bitmask from p1 value */ - dpll |= (1 << (intel_crtc->new_config->dpll.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT; + dpll |= (1 << (crtc_state->dpll.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT; /* also FPA1 */ - dpll |= (1 << (intel_crtc->new_config->dpll.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT; + dpll |= (1 << (crtc_state->dpll.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT; - switch (intel_crtc->new_config->dpll.p2) { + switch (crtc_state->dpll.p2) { case 5: dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5; break; @@ -7484,7 +7451,8 @@ static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc, return dpll | DPLL_VCO_ENABLE; } -static int ironlake_crtc_compute_clock(struct intel_crtc *crtc) +static int ironlake_crtc_compute_clock(struct intel_crtc *crtc, + struct intel_crtc_state *crtc_state) { struct drm_device *dev = crtc->base.dev; intel_clock_t clock, reduced_clock; @@ -7498,39 +7466,39 @@ static int ironlake_crtc_compute_clock(struct intel_crtc *crtc) WARN(!(HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)), "Unexpected PCH type %d\n", INTEL_PCH_TYPE(dev)); - ok = ironlake_compute_clocks(&crtc->base, &clock, + ok = ironlake_compute_clocks(&crtc->base, crtc_state, &clock, &has_reduced_clock, &reduced_clock); - if (!ok && !crtc->new_config->clock_set) { + if (!ok && !crtc_state->clock_set) { DRM_ERROR("Couldn't find PLL settings for mode!\n"); return -EINVAL; } /* Compat-code for transition, will disappear. */ - if (!crtc->new_config->clock_set) { - crtc->new_config->dpll.n = clock.n; - crtc->new_config->dpll.m1 = clock.m1; - crtc->new_config->dpll.m2 = clock.m2; - crtc->new_config->dpll.p1 = clock.p1; - crtc->new_config->dpll.p2 = clock.p2; + if (!crtc_state->clock_set) { + crtc_state->dpll.n = clock.n; + crtc_state->dpll.m1 = clock.m1; + crtc_state->dpll.m2 = clock.m2; + crtc_state->dpll.p1 = clock.p1; + crtc_state->dpll.p2 = clock.p2; } /* CPU eDP is the only output that doesn't need a PCH PLL of its own. */ - if (crtc->new_config->has_pch_encoder) { - fp = i9xx_dpll_compute_fp(&crtc->new_config->dpll); + if (crtc_state->has_pch_encoder) { + fp = i9xx_dpll_compute_fp(&crtc_state->dpll); if (has_reduced_clock) fp2 = i9xx_dpll_compute_fp(&reduced_clock); - dpll = ironlake_compute_dpll(crtc, + dpll = ironlake_compute_dpll(crtc, crtc_state, &fp, &reduced_clock, has_reduced_clock ? &fp2 : NULL); - crtc->new_config->dpll_hw_state.dpll = dpll; - crtc->new_config->dpll_hw_state.fp0 = fp; + crtc_state->dpll_hw_state.dpll = dpll; + crtc_state->dpll_hw_state.fp0 = fp; if (has_reduced_clock) - crtc->new_config->dpll_hw_state.fp1 = fp2; + crtc_state->dpll_hw_state.fp1 = fp2; else - crtc->new_config->dpll_hw_state.fp1 = fp; + crtc_state->dpll_hw_state.fp1 = fp; - pll = intel_get_shared_dpll(crtc); + pll = intel_get_shared_dpll(crtc, crtc_state); if (pll == NULL) { DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n", pipe_name(crtc->pipe)); @@ -7584,7 +7552,7 @@ static void intel_cpu_transcoder_get_m_n(struct intel_crtc *crtc, * registers are not unnecessarily read). */ if (m2_n2 && INTEL_INFO(dev)->gen < 8 && - crtc->config.has_drrs) { + crtc->config->has_drrs) { m2_n2->link_m = I915_READ(PIPE_LINK_M2(transcoder)); m2_n2->link_n = I915_READ(PIPE_LINK_N2(transcoder)); m2_n2->gmch_m = I915_READ(PIPE_DATA_M2(transcoder)) @@ -7605,9 +7573,9 @@ static void intel_cpu_transcoder_get_m_n(struct intel_crtc *crtc, } void intel_dp_get_m_n(struct intel_crtc *crtc, - struct intel_crtc_config *pipe_config) + struct intel_crtc_state *pipe_config) { - if (crtc->config.has_pch_encoder) + if (pipe_config->has_pch_encoder) intel_pch_transcoder_get_m_n(crtc, &pipe_config->dp_m_n); else intel_cpu_transcoder_get_m_n(crtc, pipe_config->cpu_transcoder, @@ -7616,14 +7584,14 @@ void intel_dp_get_m_n(struct intel_crtc *crtc, } static void ironlake_get_fdi_m_n_config(struct intel_crtc *crtc, - struct intel_crtc_config *pipe_config) + struct intel_crtc_state *pipe_config) { intel_cpu_transcoder_get_m_n(crtc, pipe_config->cpu_transcoder, &pipe_config->fdi_m_n, NULL); } static void skylake_get_pfit_config(struct intel_crtc *crtc, - struct intel_crtc_config *pipe_config) + struct intel_crtc_state *pipe_config) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -7638,8 +7606,80 @@ static void skylake_get_pfit_config(struct intel_crtc *crtc, } } +static void +skylake_get_initial_plane_config(struct intel_crtc *crtc, + struct intel_initial_plane_config *plane_config) +{ + struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + u32 val, base, offset, stride_mult; + int pipe = crtc->pipe; + int fourcc, pixel_format; + int aligned_height; + struct drm_framebuffer *fb; + struct intel_framebuffer *intel_fb; + + intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL); + if (!intel_fb) { + DRM_DEBUG_KMS("failed to alloc fb\n"); + return; + } + + fb = &intel_fb->base; + + val = I915_READ(PLANE_CTL(pipe, 0)); + if (val & PLANE_CTL_TILED_MASK) + plane_config->tiling = I915_TILING_X; + + pixel_format = val & PLANE_CTL_FORMAT_MASK; + fourcc = skl_format_to_fourcc(pixel_format, + val & PLANE_CTL_ORDER_RGBX, + val & PLANE_CTL_ALPHA_MASK); + fb->pixel_format = fourcc; + fb->bits_per_pixel = drm_format_plane_cpp(fourcc, 0) * 8; + + base = I915_READ(PLANE_SURF(pipe, 0)) & 0xfffff000; + plane_config->base = base; + + offset = I915_READ(PLANE_OFFSET(pipe, 0)); + + val = I915_READ(PLANE_SIZE(pipe, 0)); + fb->height = ((val >> 16) & 0xfff) + 1; + fb->width = ((val >> 0) & 0x1fff) + 1; + + val = I915_READ(PLANE_STRIDE(pipe, 0)); + switch (plane_config->tiling) { + case I915_TILING_NONE: + stride_mult = 64; + break; + case I915_TILING_X: + stride_mult = 512; + break; + default: + MISSING_CASE(plane_config->tiling); + goto error; + } + fb->pitches[0] = (val & 0x3ff) * stride_mult; + + aligned_height = intel_fb_align_height(dev, fb->height, + plane_config->tiling); + + plane_config->size = ALIGN(fb->pitches[0] * aligned_height, PAGE_SIZE); + + DRM_DEBUG_KMS("pipe %c with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n", + pipe_name(pipe), fb->width, fb->height, + fb->bits_per_pixel, base, fb->pitches[0], + plane_config->size); + + crtc->base.primary->fb = fb; + return; + +error: + kfree(fb); +} + static void ironlake_get_pfit_config(struct intel_crtc *crtc, - struct intel_crtc_config *pipe_config) + struct intel_crtc_state *pipe_config) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -7662,68 +7702,71 @@ static void ironlake_get_pfit_config(struct intel_crtc *crtc, } } -static void ironlake_get_plane_config(struct intel_crtc *crtc, - struct intel_plane_config *plane_config) +static void +ironlake_get_initial_plane_config(struct intel_crtc *crtc, + struct intel_initial_plane_config *plane_config) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; u32 val, base, offset; - int pipe = crtc->pipe, plane = crtc->plane; + int pipe = crtc->pipe; int fourcc, pixel_format; int aligned_height; + struct drm_framebuffer *fb; + struct intel_framebuffer *intel_fb; - crtc->base.primary->fb = kzalloc(sizeof(struct intel_framebuffer), GFP_KERNEL); - if (!crtc->base.primary->fb) { + intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL); + if (!intel_fb) { DRM_DEBUG_KMS("failed to alloc fb\n"); return; } - val = I915_READ(DSPCNTR(plane)); + fb = &intel_fb->base; + + val = I915_READ(DSPCNTR(pipe)); if (INTEL_INFO(dev)->gen >= 4) if (val & DISPPLANE_TILED) - plane_config->tiled = true; + plane_config->tiling = I915_TILING_X; pixel_format = val & DISPPLANE_PIXFORMAT_MASK; - fourcc = intel_format_to_fourcc(pixel_format); - crtc->base.primary->fb->pixel_format = fourcc; - crtc->base.primary->fb->bits_per_pixel = - drm_format_plane_cpp(fourcc, 0) * 8; + fourcc = i9xx_format_to_fourcc(pixel_format); + fb->pixel_format = fourcc; + fb->bits_per_pixel = drm_format_plane_cpp(fourcc, 0) * 8; - base = I915_READ(DSPSURF(plane)) & 0xfffff000; + base = I915_READ(DSPSURF(pipe)) & 0xfffff000; if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { - offset = I915_READ(DSPOFFSET(plane)); + offset = I915_READ(DSPOFFSET(pipe)); } else { - if (plane_config->tiled) - offset = I915_READ(DSPTILEOFF(plane)); + if (plane_config->tiling) + offset = I915_READ(DSPTILEOFF(pipe)); else - offset = I915_READ(DSPLINOFF(plane)); + offset = I915_READ(DSPLINOFF(pipe)); } plane_config->base = base; val = I915_READ(PIPESRC(pipe)); - crtc->base.primary->fb->width = ((val >> 16) & 0xfff) + 1; - crtc->base.primary->fb->height = ((val >> 0) & 0xfff) + 1; + fb->width = ((val >> 16) & 0xfff) + 1; + fb->height = ((val >> 0) & 0xfff) + 1; val = I915_READ(DSPSTRIDE(pipe)); - crtc->base.primary->fb->pitches[0] = val & 0xffffffc0; + fb->pitches[0] = val & 0xffffffc0; - aligned_height = intel_align_height(dev, crtc->base.primary->fb->height, - plane_config->tiled); + aligned_height = intel_fb_align_height(dev, fb->height, + plane_config->tiling); - plane_config->size = PAGE_ALIGN(crtc->base.primary->fb->pitches[0] * - aligned_height); + plane_config->size = PAGE_ALIGN(fb->pitches[0] * aligned_height); - DRM_DEBUG_KMS("pipe/plane %d/%d with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n", - pipe, plane, crtc->base.primary->fb->width, - crtc->base.primary->fb->height, - crtc->base.primary->fb->bits_per_pixel, base, - crtc->base.primary->fb->pitches[0], + DRM_DEBUG_KMS("pipe %c with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n", + pipe_name(pipe), fb->width, fb->height, + fb->bits_per_pixel, base, fb->pitches[0], plane_config->size); + + crtc->base.primary->fb = fb; } static bool ironlake_get_pipe_config(struct intel_crtc *crtc, - struct intel_crtc_config *pipe_config) + struct intel_crtc_state *pipe_config) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -7810,24 +7853,24 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv) struct intel_crtc *crtc; for_each_intel_crtc(dev, crtc) - WARN(crtc->active, "CRTC for pipe %c enabled\n", + I915_STATE_WARN(crtc->active, "CRTC for pipe %c enabled\n", pipe_name(crtc->pipe)); - WARN(I915_READ(HSW_PWR_WELL_DRIVER), "Power well on\n"); - WARN(I915_READ(SPLL_CTL) & SPLL_PLL_ENABLE, "SPLL enabled\n"); - WARN(I915_READ(WRPLL_CTL1) & WRPLL_PLL_ENABLE, "WRPLL1 enabled\n"); - WARN(I915_READ(WRPLL_CTL2) & WRPLL_PLL_ENABLE, "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, + I915_STATE_WARN(I915_READ(HSW_PWR_WELL_DRIVER), "Power well on\n"); + I915_STATE_WARN(I915_READ(SPLL_CTL) & SPLL_PLL_ENABLE, "SPLL enabled\n"); + I915_STATE_WARN(I915_READ(WRPLL_CTL1) & WRPLL_PLL_ENABLE, "WRPLL1 enabled\n"); + I915_STATE_WARN(I915_READ(WRPLL_CTL2) & WRPLL_PLL_ENABLE, "WRPLL2 enabled\n"); + I915_STATE_WARN(I915_READ(PCH_PP_STATUS) & PP_ON, "Panel power on\n"); + I915_STATE_WARN(I915_READ(BLC_PWM_CPU_CTL2) & BLM_PWM_ENABLE, "CPU PWM1 enabled\n"); if (IS_HASWELL(dev)) - WARN(I915_READ(HSW_BLC_PWM2_CTL) & BLM_PWM_ENABLE, + I915_STATE_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, + I915_STATE_WARN(I915_READ(BLC_PWM_PCH_CTL1) & BLM_PCH_PWM_ENABLE, "PCH PWM1 enabled\n"); - WARN(I915_READ(UTIL_PIN_CTL) & UTIL_PIN_ENABLE, + I915_STATE_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"); + I915_STATE_WARN(I915_READ(PCH_GTC_CTL) & PCH_GTC_ENABLE, "PCH GTC enabled\n"); /* * In theory we can still leave IRQs enabled, as long as only the HPD @@ -7835,7 +7878,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv) * gen-specific and since we only disable LCPLL after we fully disable * the interrupts, the check below should be enough. */ - WARN(intel_irqs_enabled(dev_priv), "IRQs enabled\n"); + I915_STATE_WARN(intel_irqs_enabled(dev_priv), "IRQs enabled\n"); } static uint32_t hsw_read_dcomp(struct drm_i915_private *dev_priv) @@ -7933,19 +7976,8 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv) /* * Make sure we're not on PC8 state before disabling PC8, otherwise * we'll hang the machine. To prevent PC8 state, just enable force_wake. - * - * The other problem is that hsw_restore_lcpll() is called as part of - * the runtime PM resume sequence, so we can't just call - * gen6_gt_force_wake_get() because that function calls - * intel_runtime_pm_get(), and we can't change the runtime PM refcount - * while we are on the resume sequence. So to solve this problem we have - * to call special forcewake code that doesn't touch runtime PM and - * doesn't enable the forcewake delayed work. */ - spin_lock_irq(&dev_priv->uncore.lock); - if (dev_priv->uncore.forcewake_count++ == 0) - dev_priv->uncore.funcs.force_wake_get(dev_priv, FORCEWAKE_ALL); - spin_unlock_irq(&dev_priv->uncore.lock); + intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); if (val & LCPLL_POWER_DOWN_ALLOW) { val &= ~LCPLL_POWER_DOWN_ALLOW; @@ -7975,11 +8007,7 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv) DRM_ERROR("Switching back to LCPLL failed\n"); } - /* See the big comment above. */ - spin_lock_irq(&dev_priv->uncore.lock); - if (--dev_priv->uncore.forcewake_count == 0) - dev_priv->uncore.funcs.force_wake_put(dev_priv, FORCEWAKE_ALL); - spin_unlock_irq(&dev_priv->uncore.lock); + intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); } /* @@ -8041,9 +8069,10 @@ void hsw_disable_pc8(struct drm_i915_private *dev_priv) intel_prepare_ddi(dev); } -static int haswell_crtc_compute_clock(struct intel_crtc *crtc) +static int haswell_crtc_compute_clock(struct intel_crtc *crtc, + struct intel_crtc_state *crtc_state) { - if (!intel_ddi_pll_select(crtc)) + if (!intel_ddi_pll_select(crtc, crtc_state)) return -EINVAL; crtc->lowfreq_avail = false; @@ -8053,14 +8082,23 @@ static int haswell_crtc_compute_clock(struct intel_crtc *crtc) static void skylake_get_ddi_pll(struct drm_i915_private *dev_priv, enum port port, - struct intel_crtc_config *pipe_config) + struct intel_crtc_state *pipe_config) { - u32 temp; + u32 temp, dpll_ctl1; temp = I915_READ(DPLL_CTRL2) & DPLL_CTRL2_DDI_CLK_SEL_MASK(port); pipe_config->ddi_pll_sel = temp >> (port * 3 + 1); switch (pipe_config->ddi_pll_sel) { + case SKL_DPLL0: + /* + * On SKL the eDP DPLL (DPLL0 as we don't use SSC) is not part + * of the shared DPLL framework and thus needs to be read out + * separately + */ + dpll_ctl1 = I915_READ(DPLL_CTRL1); + pipe_config->dpll_hw_state.ctrl1 = dpll_ctl1 & 0x3f; + break; case SKL_DPLL1: pipe_config->shared_dpll = DPLL_ID_SKL_DPLL1; break; @@ -8075,7 +8113,7 @@ static void skylake_get_ddi_pll(struct drm_i915_private *dev_priv, static void haswell_get_ddi_pll(struct drm_i915_private *dev_priv, enum port port, - struct intel_crtc_config *pipe_config) + struct intel_crtc_state *pipe_config) { pipe_config->ddi_pll_sel = I915_READ(PORT_CLK_SEL(port)); @@ -8090,7 +8128,7 @@ static void haswell_get_ddi_pll(struct drm_i915_private *dev_priv, } static void haswell_get_ddi_port_state(struct intel_crtc *crtc, - struct intel_crtc_config *pipe_config) + struct intel_crtc_state *pipe_config) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -8132,7 +8170,7 @@ static void haswell_get_ddi_port_state(struct intel_crtc *crtc, } static bool haswell_get_pipe_config(struct intel_crtc *crtc, - struct intel_crtc_config *pipe_config) + struct intel_crtc_state *pipe_config) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -8286,7 +8324,7 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base) cntl |= CURSOR_MODE_256_ARGB_AX; break; default: - WARN_ON(1); + MISSING_CASE(intel_crtc->cursor_width); return; } cntl |= pipe << 28; /* Connect to correct pipe */ @@ -8295,7 +8333,7 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base) cntl |= CURSOR_PIPE_CSC_ENABLE; } - if (to_intel_plane(crtc->cursor)->rotation == BIT(DRM_ROTATE_180)) + if (crtc->cursor->state->rotation == BIT(DRM_ROTATE_180)) cntl |= CURSOR_ROTATE_180; if (intel_crtc->cursor_cntl != cntl) { @@ -8326,10 +8364,10 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc, if (on) base = intel_crtc->cursor_addr; - if (x >= intel_crtc->config.pipe_src_w) + if (x >= intel_crtc->config->pipe_src_w) base = 0; - if (y >= intel_crtc->config.pipe_src_h) + if (y >= intel_crtc->config->pipe_src_h) base = 0; if (x < 0) { @@ -8357,7 +8395,7 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc, /* ILK+ do this automagically */ if (HAS_GMCH_DISPLAY(dev) && - to_intel_plane(crtc->cursor)->rotation == BIT(DRM_ROTATE_180)) { + crtc->cursor->state->rotation == BIT(DRM_ROTATE_180)) { base += (intel_crtc->cursor_height * intel_crtc->cursor_width - 1) * 4; } @@ -8405,109 +8443,6 @@ static bool cursor_size_ok(struct drm_device *dev, return true; } -static int intel_crtc_cursor_set_obj(struct drm_crtc *crtc, - struct drm_i915_gem_object *obj, - uint32_t width, uint32_t height) -{ - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - enum pipe pipe = intel_crtc->pipe; - unsigned old_width; - uint32_t addr; - int ret; - - /* if we want to turn off the cursor ignore width and height */ - if (!obj) { - DRM_DEBUG_KMS("cursor off\n"); - addr = 0; - mutex_lock(&dev->struct_mutex); - goto finish; - } - - /* we only need to pin inside GTT if cursor is non-phy */ - mutex_lock(&dev->struct_mutex); - if (!INTEL_INFO(dev)->cursor_needs_physical) { - unsigned alignment; - - /* - * Global gtt pte registers are special registers which actually - * forward writes to a chunk of system memory. Which means that - * there is no risk that the register values disappear as soon - * as we call intel_runtime_pm_put(), so it is correct to wrap - * only the pin/unpin/fence and not more. - */ - intel_runtime_pm_get(dev_priv); - - /* 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_DEBUG_KMS("failed to move cursor bo into the GTT\n"); - intel_runtime_pm_put(dev_priv); - goto fail_locked; - } - - ret = i915_gem_object_put_fence(obj); - if (ret) { - DRM_DEBUG_KMS("failed to release fence for cursor"); - intel_runtime_pm_put(dev_priv); - goto fail_unpin; - } - - addr = i915_gem_obj_ggtt_offset(obj); - - intel_runtime_pm_put(dev_priv); - } else { - int align = IS_I830(dev) ? 16 * 1024 : 256; - ret = i915_gem_object_attach_phys(obj, align); - if (ret) { - DRM_DEBUG_KMS("failed to attach phys object\n"); - goto fail_locked; - } - addr = obj->phys_handle->busaddr; - } - - finish: - if (intel_crtc->cursor_bo) { - if (!INTEL_INFO(dev)->cursor_needs_physical) - i915_gem_object_unpin_from_display_plane(intel_crtc->cursor_bo); - } - - i915_gem_track_fb(intel_crtc->cursor_bo, obj, - INTEL_FRONTBUFFER_CURSOR(pipe)); - mutex_unlock(&dev->struct_mutex); - - old_width = intel_crtc->cursor_width; - - intel_crtc->cursor_addr = addr; - intel_crtc->cursor_bo = obj; - intel_crtc->cursor_width = width; - intel_crtc->cursor_height = height; - - if (intel_crtc->active) { - if (old_width != width) - intel_update_watermarks(crtc); - intel_crtc_update_cursor(crtc, intel_crtc->cursor_bo != NULL); - - intel_frontbuffer_flip(dev, INTEL_FRONTBUFFER_CURSOR(pipe)); - } - - return 0; -fail_unpin: - i915_gem_object_unpin_from_display_plane(obj); -fail_locked: - mutex_unlock(&dev->struct_mutex); - return ret; -} - static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, u16 *blue, uint32_t start, uint32_t size) { @@ -8730,7 +8665,7 @@ retry: intel_crtc = to_intel_crtc(crtc); intel_crtc->new_enabled = true; - intel_crtc->new_config = &intel_crtc->config; + intel_crtc->new_config = intel_crtc->config; old->dpms_mode = connector->dpms; old->load_detect_temp = true; old->release_fb = NULL; @@ -8771,7 +8706,7 @@ retry: fail: intel_crtc->new_enabled = crtc->enabled; if (intel_crtc->new_enabled) - intel_crtc->new_config = &intel_crtc->config; + intel_crtc->new_config = intel_crtc->config; else intel_crtc->new_config = NULL; fail_unlock: @@ -8817,7 +8752,7 @@ void intel_release_load_detect_pipe(struct drm_connector *connector, } static int i9xx_pll_refclk(struct drm_device *dev, - const struct intel_crtc_config *pipe_config) + const struct intel_crtc_state *pipe_config) { struct drm_i915_private *dev_priv = dev->dev_private; u32 dpll = pipe_config->dpll_hw_state.dpll; @@ -8834,7 +8769,7 @@ static int i9xx_pll_refclk(struct drm_device *dev, /* 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 intel_crtc_state *pipe_config) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -8941,7 +8876,7 @@ int intel_dotclock_calculate(int link_freq, } static void ironlake_pch_clock_get(struct intel_crtc *crtc, - struct intel_crtc_config *pipe_config) + struct intel_crtc_state *pipe_config) { struct drm_device *dev = crtc->base.dev; @@ -8954,7 +8889,7 @@ static void ironlake_pch_clock_get(struct intel_crtc *crtc, * agree once we know their relationship in the encoder's * get_config() function. */ - pipe_config->adjusted_mode.crtc_clock = + pipe_config->base.adjusted_mode.crtc_clock = intel_dotclock_calculate(intel_fdi_link_freq(dev) * 10000, &pipe_config->fdi_m_n); } @@ -8965,9 +8900,9 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *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; + enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder; struct drm_display_mode *mode; - struct intel_crtc_config pipe_config; + struct intel_crtc_state pipe_config; int htot = I915_READ(HTOTAL(cpu_transcoder)); int hsync = I915_READ(HSYNC(cpu_transcoder)); int vtot = I915_READ(VTOTAL(cpu_transcoder)); @@ -9082,6 +9017,14 @@ out: intel_runtime_pm_put(dev_priv); } +static void intel_crtc_set_state(struct intel_crtc *crtc, + struct intel_crtc_state *crtc_state) +{ + kfree(crtc->config); + crtc->config = crtc_state; + crtc->base.state = &crtc_state->base; +} + static void intel_crtc_destroy(struct drm_crtc *crtc) { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); @@ -9098,6 +9041,7 @@ static void intel_crtc_destroy(struct drm_crtc *crtc) kfree(work); } + intel_crtc_set_state(intel_crtc, NULL); drm_crtc_cleanup(crtc); kfree(intel_crtc); @@ -9115,7 +9059,10 @@ static void intel_unpin_work_fn(struct work_struct *__work) drm_gem_object_unreference(&work->pending_flip_obj->base); drm_gem_object_unreference(&work->old_fb_obj->base); - intel_update_fbc(dev); + intel_fbc_update(dev); + + if (work->flip_queued_req) + i915_gem_request_assign(&work->flip_queued_req, NULL); mutex_unlock(&dev->struct_mutex); intel_frontbuffer_flip_complete(dev, INTEL_FRONTBUFFER_PRIMARY(pipe)); @@ -9511,25 +9458,53 @@ static bool use_mmio_flip(struct intel_engine_cs *ring, else if (i915.enable_execlists) return true; else - return ring != obj->ring; + return ring != i915_gem_request_get_ring(obj->last_read_req); } -static void intel_do_mmio_flip(struct intel_crtc *intel_crtc) +static void skl_do_mmio_flip(struct intel_crtc *intel_crtc) +{ + struct drm_device *dev = intel_crtc->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_framebuffer *fb = intel_crtc->base.primary->fb; + struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); + struct drm_i915_gem_object *obj = intel_fb->obj; + const enum pipe pipe = intel_crtc->pipe; + u32 ctl, stride; + + ctl = I915_READ(PLANE_CTL(pipe, 0)); + ctl &= ~PLANE_CTL_TILED_MASK; + if (obj->tiling_mode == I915_TILING_X) + ctl |= PLANE_CTL_TILED_X; + + /* + * The stride is either expressed as a multiple of 64 bytes chunks for + * linear buffers or in number of tiles for tiled buffers. + */ + stride = fb->pitches[0] >> 6; + if (obj->tiling_mode == I915_TILING_X) + stride = fb->pitches[0] >> 9; /* X tiles are 512 bytes wide */ + + /* + * Both PLANE_CTL and PLANE_STRIDE are not updated on vblank but on + * PLANE_SURF updates, the update is then guaranteed to be atomic. + */ + I915_WRITE(PLANE_CTL(pipe, 0), ctl); + I915_WRITE(PLANE_STRIDE(pipe, 0), stride); + + I915_WRITE(PLANE_SURF(pipe, 0), intel_crtc->unpin_work->gtt_offset); + POSTING_READ(PLANE_SURF(pipe, 0)); +} + +static void ilk_do_mmio_flip(struct intel_crtc *intel_crtc) { struct drm_device *dev = intel_crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_framebuffer *intel_fb = to_intel_framebuffer(intel_crtc->base.primary->fb); struct drm_i915_gem_object *obj = intel_fb->obj; - bool atomic_update; - u32 start_vbl_count; u32 dspcntr; u32 reg; - intel_mark_page_flip_active(intel_crtc); - - atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count); - reg = DSPCNTR(intel_crtc->plane); dspcntr = I915_READ(reg); @@ -9544,26 +9519,50 @@ static void intel_do_mmio_flip(struct intel_crtc *intel_crtc) intel_crtc->unpin_work->gtt_offset); POSTING_READ(DSPSURF(intel_crtc->plane)); +} + +/* + * XXX: This is the temporary way to update the plane registers until we get + * around to using the usual plane update functions for MMIO flips + */ +static void intel_do_mmio_flip(struct intel_crtc *intel_crtc) +{ + struct drm_device *dev = intel_crtc->base.dev; + bool atomic_update; + u32 start_vbl_count; + + intel_mark_page_flip_active(intel_crtc); + + atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count); + + if (INTEL_INFO(dev)->gen >= 9) + skl_do_mmio_flip(intel_crtc); + else + /* use_mmio_flip() retricts MMIO flips to ilk+ */ + ilk_do_mmio_flip(intel_crtc); + if (atomic_update) intel_pipe_update_end(intel_crtc, start_vbl_count); } static void intel_mmio_flip_work_func(struct work_struct *work) { - struct intel_crtc *intel_crtc = + struct intel_crtc *crtc = container_of(work, struct intel_crtc, mmio_flip.work); - struct intel_engine_cs *ring; - uint32_t seqno; + struct intel_mmio_flip *mmio_flip; - seqno = intel_crtc->mmio_flip.seqno; - ring = intel_crtc->mmio_flip.ring; + mmio_flip = &crtc->mmio_flip; + if (mmio_flip->req) + WARN_ON(__i915_wait_request(mmio_flip->req, + crtc->reset_counter, + false, NULL, NULL) != 0); - if (seqno) - WARN_ON(__i915_wait_seqno(ring, seqno, - intel_crtc->reset_counter, - false, NULL, NULL) != 0); - - intel_do_mmio_flip(intel_crtc); + intel_do_mmio_flip(crtc); + if (mmio_flip->req) { + mutex_lock(&crtc->base.dev->struct_mutex); + i915_gem_request_assign(&mmio_flip->req, NULL); + mutex_unlock(&crtc->base.dev->struct_mutex); + } } static int intel_queue_mmio_flip(struct drm_device *dev, @@ -9575,8 +9574,8 @@ static int intel_queue_mmio_flip(struct drm_device *dev, { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - intel_crtc->mmio_flip.seqno = obj->last_write_seqno; - intel_crtc->mmio_flip.ring = obj->ring; + i915_gem_request_assign(&intel_crtc->mmio_flip.req, + obj->last_write_req); schedule_work(&intel_crtc->mmio_flip.work); @@ -9671,9 +9670,8 @@ static bool __intel_pageflip_stall_check(struct drm_device *dev, return false; if (work->flip_ready_vblank == 0) { - if (work->flip_queued_ring && - !i915_seqno_passed(work->flip_queued_ring->get_seqno(work->flip_queued_ring, true), - work->flip_queued_seqno)) + if (work->flip_queued_req && + !i915_gem_request_completed(work->flip_queued_req, true)) return false; work->flip_ready_vblank = drm_vblank_count(dev, intel_crtc->pipe); @@ -9726,6 +9724,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *old_fb = crtc->primary->fb; struct drm_i915_gem_object *obj = intel_fb_obj(fb); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct drm_plane *primary = crtc->primary; enum pipe pipe = intel_crtc->pipe; struct intel_unpin_work *work; struct intel_engine_cs *ring; @@ -9818,7 +9817,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, } else if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) { ring = &dev_priv->ring[BCS]; } else if (INTEL_INFO(dev)->gen >= 7) { - ring = obj->ring; + ring = i915_gem_request_get_ring(obj->last_read_req); if (ring == NULL || ring->id != RCS) ring = &dev_priv->ring[BCS]; } else { @@ -9838,16 +9837,16 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, if (ret) goto cleanup_unpin; - work->flip_queued_seqno = obj->last_write_seqno; - work->flip_queued_ring = obj->ring; + i915_gem_request_assign(&work->flip_queued_req, + obj->last_write_req); } else { ret = dev_priv->display.queue_flip(dev, crtc, fb, obj, ring, page_flip_flags); if (ret) goto cleanup_unpin; - work->flip_queued_seqno = intel_ring_get_seqno(ring); - work->flip_queued_ring = ring; + i915_gem_request_assign(&work->flip_queued_req, + intel_ring_get_request(ring)); } work->flip_queued_vblank = drm_vblank_count(dev, intel_crtc->pipe); @@ -9856,7 +9855,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, i915_gem_track_fb(work->old_fb_obj, obj, INTEL_FRONTBUFFER_PRIMARY(pipe)); - intel_disable_fbc(dev); + intel_fbc_disable(dev); intel_frontbuffer_flip_prepare(dev, INTEL_FRONTBUFFER_PRIMARY(pipe)); mutex_unlock(&dev->struct_mutex); @@ -9884,8 +9883,7 @@ free_work: if (ret == -EIO) { out_hang: - intel_crtc_wait_for_pending_flips(crtc); - ret = intel_pipe_set_base(crtc, crtc->x, crtc->y, fb); + ret = intel_plane_restore(primary); if (ret == 0 && event) { spin_lock_irq(&dev->event_lock); drm_send_vblank_event(dev, pipe, event); @@ -9898,6 +9896,8 @@ out_hang: static struct drm_crtc_helper_funcs intel_helper_funcs = { .mode_set_base_atomic = intel_pipe_set_base_atomic, .load_lut = intel_crtc_load_lut, + .atomic_begin = intel_begin_crtc_commit, + .atomic_flush = intel_finish_crtc_commit, }; /** @@ -9927,7 +9927,7 @@ static void intel_modeset_update_staged_output_state(struct drm_device *dev) crtc->new_enabled = crtc->base.enabled; if (crtc->new_enabled) - crtc->new_config = &crtc->config; + crtc->new_config = crtc->config; else crtc->new_config = NULL; } @@ -9960,7 +9960,7 @@ static void intel_modeset_commit_output_state(struct drm_device *dev) static void connected_sink_compute_bpp(struct intel_connector *connector, - struct intel_crtc_config *pipe_config) + struct intel_crtc_state *pipe_config) { int bpp = pipe_config->pipe_bpp; @@ -9987,7 +9987,7 @@ connected_sink_compute_bpp(struct intel_connector *connector, static int compute_baseline_pipe_bpp(struct intel_crtc *crtc, struct drm_framebuffer *fb, - struct intel_crtc_config *pipe_config) + struct intel_crtc_state *pipe_config) { struct drm_device *dev = crtc->base.dev; struct intel_connector *connector; @@ -10056,7 +10056,7 @@ static void intel_dump_crtc_timings(const struct drm_display_mode *mode) } static void intel_dump_pipe_config(struct intel_crtc *crtc, - struct intel_crtc_config *pipe_config, + struct intel_crtc_state *pipe_config, const char *context) { DRM_DEBUG_KMS("[CRTC:%d]%s config for pipe %c\n", crtc->base.base.id, @@ -10090,10 +10090,10 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc, pipe_config->has_infoframe); DRM_DEBUG_KMS("requested mode:\n"); - drm_mode_debug_printmodeline(&pipe_config->requested_mode); + drm_mode_debug_printmodeline(&pipe_config->base.mode); DRM_DEBUG_KMS("adjusted mode:\n"); - drm_mode_debug_printmodeline(&pipe_config->adjusted_mode); - intel_dump_crtc_timings(&pipe_config->adjusted_mode); + drm_mode_debug_printmodeline(&pipe_config->base.adjusted_mode); + intel_dump_crtc_timings(&pipe_config->base.adjusted_mode); DRM_DEBUG_KMS("port clock: %d\n", pipe_config->port_clock); DRM_DEBUG_KMS("pipe src size: %dx%d\n", pipe_config->pipe_src_w, pipe_config->pipe_src_h); @@ -10192,14 +10192,14 @@ static bool check_digital_port_conflicts(struct drm_device *dev) return true; } -static struct intel_crtc_config * +static struct intel_crtc_state * 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; + struct intel_crtc_state *pipe_config; int plane_bpp, ret = -EINVAL; bool retry = true; @@ -10217,8 +10217,8 @@ intel_modeset_pipe_config(struct drm_crtc *crtc, if (!pipe_config) return ERR_PTR(-ENOMEM); - drm_mode_copy(&pipe_config->adjusted_mode, mode); - drm_mode_copy(&pipe_config->requested_mode, mode); + drm_mode_copy(&pipe_config->base.adjusted_mode, mode); + drm_mode_copy(&pipe_config->base.mode, mode); pipe_config->cpu_transcoder = (enum transcoder) to_intel_crtc(crtc)->pipe; @@ -10229,13 +10229,13 @@ intel_modeset_pipe_config(struct drm_crtc *crtc, * positive or negative polarity is requested, treat this as meaning * negative polarity. */ - if (!(pipe_config->adjusted_mode.flags & + if (!(pipe_config->base.adjusted_mode.flags & (DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NHSYNC))) - pipe_config->adjusted_mode.flags |= DRM_MODE_FLAG_NHSYNC; + pipe_config->base.adjusted_mode.flags |= DRM_MODE_FLAG_NHSYNC; - if (!(pipe_config->adjusted_mode.flags & + if (!(pipe_config->base.adjusted_mode.flags & (DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC))) - pipe_config->adjusted_mode.flags |= DRM_MODE_FLAG_NVSYNC; + pipe_config->base.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 @@ -10254,9 +10254,9 @@ intel_modeset_pipe_config(struct drm_crtc *crtc, * computation to clearly distinguish it from the adjusted mode, which * can be changed by the connectors in the below retry loop. */ - drm_mode_set_crtcinfo(&pipe_config->requested_mode, CRTC_STEREO_DOUBLE); - pipe_config->pipe_src_w = pipe_config->requested_mode.crtc_hdisplay; - pipe_config->pipe_src_h = pipe_config->requested_mode.crtc_vdisplay; + drm_crtc_get_hv_timing(&pipe_config->base.mode, + &pipe_config->pipe_src_w, + &pipe_config->pipe_src_h); encoder_retry: /* Ensure the port clock defaults are reset when retrying. */ @@ -10264,7 +10264,8 @@ encoder_retry: pipe_config->pixel_multiplier = 1; /* Fill in default crtc timings, allow encoders to overwrite them. */ - drm_mode_set_crtcinfo(&pipe_config->adjusted_mode, CRTC_STEREO_DOUBLE); + drm_mode_set_crtcinfo(&pipe_config->base.adjusted_mode, + CRTC_STEREO_DOUBLE); /* 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 @@ -10284,7 +10285,7 @@ encoder_retry: /* 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.crtc_clock + pipe_config->port_clock = pipe_config->base.adjusted_mode.crtc_clock * pipe_config->pixel_multiplier; ret = intel_crtc_compute_config(to_intel_crtc(crtc), pipe_config); @@ -10441,7 +10442,7 @@ intel_modeset_update_state(struct drm_device *dev, unsigned prepare_pipes) for_each_intel_crtc(dev, intel_crtc) { WARN_ON(intel_crtc->base.enabled != intel_crtc_in_use(&intel_crtc->base)); WARN_ON(intel_crtc->new_config && - intel_crtc->new_config != &intel_crtc->config); + intel_crtc->new_config != intel_crtc->config); WARN_ON(intel_crtc->base.enabled != !!intel_crtc->new_config); } @@ -10493,8 +10494,8 @@ static bool intel_fuzzy_clock_check(int clock1, int clock2) static bool intel_pipe_config_compare(struct drm_device *dev, - struct intel_crtc_config *current_config, - struct intel_crtc_config *pipe_config) + struct intel_crtc_state *current_config, + struct intel_crtc_state *pipe_config) { #define PIPE_CONF_CHECK_X(name) \ if (current_config->name != pipe_config->name) { \ @@ -10585,19 +10586,19 @@ intel_pipe_config_compare(struct drm_device *dev, PIPE_CONF_CHECK_I_ALT(dp_m_n.tu, dp_m2_n2.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(base.adjusted_mode.crtc_hdisplay); + PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_htotal); + PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_hblank_start); + PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_hblank_end); + PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_hsync_start); + PIPE_CONF_CHECK_I(base.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(base.adjusted_mode.crtc_vdisplay); + PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_vtotal); + PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_vblank_start); + PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_vblank_end); + PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_vsync_start); + PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_vsync_end); PIPE_CONF_CHECK_I(pixel_multiplier); PIPE_CONF_CHECK_I(has_hdmi_sink); @@ -10608,17 +10609,17 @@ intel_pipe_config_compare(struct drm_device *dev, PIPE_CONF_CHECK_I(has_audio); - PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags, + PIPE_CONF_CHECK_FLAGS(base.adjusted_mode.flags, DRM_MODE_FLAG_INTERLACE); if (!PIPE_CONF_QUIRK(PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS)) { - PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags, + PIPE_CONF_CHECK_FLAGS(base.adjusted_mode.flags, DRM_MODE_FLAG_PHSYNC); - PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags, + PIPE_CONF_CHECK_FLAGS(base.adjusted_mode.flags, DRM_MODE_FLAG_NHSYNC); - PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags, + PIPE_CONF_CHECK_FLAGS(base.adjusted_mode.flags, DRM_MODE_FLAG_PVSYNC); - PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags, + PIPE_CONF_CHECK_FLAGS(base.adjusted_mode.flags, DRM_MODE_FLAG_NVSYNC); } @@ -10668,7 +10669,7 @@ intel_pipe_config_compare(struct drm_device *dev, if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) PIPE_CONF_CHECK_I(pipe_bpp); - PIPE_CONF_CHECK_CLOCK_FUZZY(adjusted_mode.crtc_clock); + PIPE_CONF_CHECK_CLOCK_FUZZY(base.adjusted_mode.crtc_clock); PIPE_CONF_CHECK_CLOCK_FUZZY(port_clock); #undef PIPE_CONF_CHECK_X @@ -10742,7 +10743,7 @@ check_connector_state(struct drm_device *dev) * ->get_hw_state callbacks. */ intel_connector_check_state(connector); - WARN(&connector->new_encoder->base != connector->base.encoder, + I915_STATE_WARN(&connector->new_encoder->base != connector->base.encoder, "connector's staged encoder doesn't match current encoder\n"); } } @@ -10762,9 +10763,9 @@ check_encoder_state(struct drm_device *dev) encoder->base.base.id, encoder->base.name); - WARN(&encoder->new_crtc->base != encoder->base.crtc, + I915_STATE_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, + I915_STATE_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, @@ -10783,19 +10784,19 @@ check_encoder_state(struct drm_device *dev) if (!enabled && encoder->base.encoder_type == DRM_MODE_ENCODER_DPMST) continue; - WARN(!!encoder->base.crtc != enabled, + I915_STATE_WARN(!!encoder->base.crtc != enabled, "encoder's enabled state mismatch " "(expected %i, found %i)\n", !!encoder->base.crtc, enabled); - WARN(active && !encoder->base.crtc, + I915_STATE_WARN(active && !encoder->base.crtc, "active encoder with no crtc\n"); - WARN(encoder->connectors_active != active, + I915_STATE_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, + I915_STATE_WARN(active != encoder->connectors_active, "encoder's hw state doesn't match sw tracking " "(expected %i, found %i)\n", encoder->connectors_active, active); @@ -10804,7 +10805,7 @@ check_encoder_state(struct drm_device *dev) continue; tracked_pipe = to_intel_crtc(encoder->base.crtc)->pipe; - WARN(active && pipe != tracked_pipe, + I915_STATE_WARN(active && pipe != tracked_pipe, "active encoder's pipe doesn't match" "(expected %i, found %i)\n", tracked_pipe, pipe); @@ -10818,7 +10819,7 @@ check_crtc_state(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *crtc; struct intel_encoder *encoder; - struct intel_crtc_config pipe_config; + struct intel_crtc_state pipe_config; for_each_intel_crtc(dev, crtc) { bool enabled = false; @@ -10829,7 +10830,7 @@ check_crtc_state(struct drm_device *dev) DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.base.id); - WARN(crtc->active && !crtc->base.enabled, + I915_STATE_WARN(crtc->active && !crtc->base.enabled, "active crtc, but not enabled in sw tracking\n"); for_each_intel_encoder(dev, encoder) { @@ -10840,10 +10841,10 @@ check_crtc_state(struct drm_device *dev) active = true; } - WARN(active != crtc->active, + I915_STATE_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, + I915_STATE_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); @@ -10863,16 +10864,16 @@ check_crtc_state(struct drm_device *dev) encoder->get_config(encoder, &pipe_config); } - WARN(crtc->active != active, + I915_STATE_WARN(crtc->active != active, "crtc active state doesn't match with hw state " "(expected %i, found %i)\n", crtc->active, active); if (active && - !intel_pipe_config_compare(dev, &crtc->config, &pipe_config)) { - WARN(1, "pipe state doesn't match!\n"); + !intel_pipe_config_compare(dev, crtc->config, &pipe_config)) { + I915_STATE_WARN(1, "pipe state doesn't match!\n"); intel_dump_pipe_config(crtc, &pipe_config, "[hw state]"); - intel_dump_pipe_config(crtc, &crtc->config, + intel_dump_pipe_config(crtc, crtc->config, "[sw state]"); } } @@ -10897,14 +10898,14 @@ check_shared_dpll_state(struct drm_device *dev) active = pll->get_hw_state(dev_priv, pll, &dpll_hw_state); - WARN(pll->active > hweight32(pll->config.crtc_mask), + I915_STATE_WARN(pll->active > hweight32(pll->config.crtc_mask), "more active pll users than references: %i vs %i\n", pll->active, hweight32(pll->config.crtc_mask)); - WARN(pll->active && !pll->on, + I915_STATE_WARN(pll->active && !pll->on, "pll in active use but not on in sw tracking\n"); - WARN(pll->on && !pll->active, + I915_STATE_WARN(pll->on && !pll->active, "pll in on but not on in use in sw tracking\n"); - WARN(pll->on != active, + I915_STATE_WARN(pll->on != active, "pll on state mismatch (expected %i, found %i)\n", pll->on, active); @@ -10914,14 +10915,14 @@ check_shared_dpll_state(struct drm_device *dev) if (crtc->active && intel_crtc_to_shared_dpll(crtc) == pll) active_crtcs++; } - WARN(pll->active != active_crtcs, + I915_STATE_WARN(pll->active != active_crtcs, "pll active crtcs mismatch (expected %i, found %i)\n", pll->active, active_crtcs); - WARN(hweight32(pll->config.crtc_mask) != enabled_crtcs, + I915_STATE_WARN(hweight32(pll->config.crtc_mask) != enabled_crtcs, "pll enabled crtcs mismatch (expected %i, found %i)\n", hweight32(pll->config.crtc_mask), enabled_crtcs); - WARN(pll->on && memcmp(&pll->config.hw_state, &dpll_hw_state, + I915_STATE_WARN(pll->on && memcmp(&pll->config.hw_state, &dpll_hw_state, sizeof(dpll_hw_state)), "pll hw state mismatch\n"); } @@ -10937,16 +10938,16 @@ intel_modeset_check_state(struct drm_device *dev) check_shared_dpll_state(dev); } -void ironlake_check_encoder_dotclock(const struct intel_crtc_config *pipe_config, +void ironlake_check_encoder_dotclock(const struct intel_crtc_state *pipe_config, int dotclock) { /* * FDI already provided one idea for the dotclock. * Yell if the encoder disagrees. */ - WARN(!intel_fuzzy_clock_check(pipe_config->adjusted_mode.crtc_clock, dotclock), + WARN(!intel_fuzzy_clock_check(pipe_config->base.adjusted_mode.crtc_clock, dotclock), "FDI dotclock and encoder dotclock mismatch, fdi: %i, encoder: %i\n", - pipe_config->adjusted_mode.crtc_clock, dotclock); + pipe_config->base.adjusted_mode.crtc_clock, dotclock); } static void update_scanline_offset(struct intel_crtc *crtc) @@ -10972,7 +10973,7 @@ static void update_scanline_offset(struct intel_crtc *crtc) * one to the value. */ if (IS_GEN2(dev)) { - const struct drm_display_mode *mode = &crtc->config.adjusted_mode; + const struct drm_display_mode *mode = &crtc->config->base.adjusted_mode; int vtotal; vtotal = mode->crtc_vtotal; @@ -10987,7 +10988,7 @@ static void update_scanline_offset(struct intel_crtc *crtc) crtc->scanline_offset = 1; } -static struct intel_crtc_config * +static struct intel_crtc_state * intel_modeset_compute_config(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_framebuffer *fb, @@ -10995,7 +10996,7 @@ intel_modeset_compute_config(struct drm_crtc *crtc, unsigned *prepare_pipes, unsigned *disable_pipes) { - struct intel_crtc_config *pipe_config = NULL; + struct intel_crtc_state *pipe_config = NULL; intel_modeset_affected_pipes(crtc, modeset_pipes, prepare_pipes, disable_pipes); @@ -11020,10 +11021,40 @@ out: return pipe_config; } +static int __intel_set_mode_setup_plls(struct drm_device *dev, + unsigned modeset_pipes, + unsigned disable_pipes) +{ + struct drm_i915_private *dev_priv = to_i915(dev); + unsigned clear_pipes = modeset_pipes | disable_pipes; + struct intel_crtc *intel_crtc; + int ret = 0; + + if (!dev_priv->display.crtc_compute_clock) + return 0; + + ret = intel_shared_dpll_start_config(dev_priv, clear_pipes); + if (ret) + goto done; + + for_each_intel_crtc_masked(dev, modeset_pipes, intel_crtc) { + struct intel_crtc_state *state = intel_crtc->new_config; + ret = dev_priv->display.crtc_compute_clock(intel_crtc, + state); + if (ret) { + intel_shared_dpll_abort_config(dev_priv); + goto done; + } + } + +done: + return ret; +} + static int __intel_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, int x, int y, struct drm_framebuffer *fb, - struct intel_crtc_config *pipe_config, + struct intel_crtc_state *pipe_config, unsigned modeset_pipes, unsigned prepare_pipes, unsigned disable_pipes) @@ -11057,21 +11088,9 @@ static int __intel_set_mode(struct drm_crtc *crtc, prepare_pipes &= ~disable_pipes; } - if (dev_priv->display.crtc_compute_clock) { - unsigned clear_pipes = modeset_pipes | disable_pipes; - - ret = intel_shared_dpll_start_config(dev_priv, clear_pipes); - if (ret) - goto done; - - for_each_intel_crtc_masked(dev, modeset_pipes, intel_crtc) { - ret = dev_priv->display.crtc_compute_clock(intel_crtc); - if (ret) { - intel_shared_dpll_abort_config(dev_priv); - goto done; - } - } - } + ret = __intel_set_mode_setup_plls(dev, modeset_pipes, disable_pipes); + if (ret) + goto done; for_each_intel_crtc_masked(dev, disable_pipes, intel_crtc) intel_crtc_disable(&intel_crtc->base); @@ -11092,8 +11111,7 @@ static int __intel_set_mode(struct drm_crtc *crtc, crtc->mode = *mode; /* mode_set/enable/disable functions rely on a correct pipe * config. */ - to_intel_crtc(crtc)->config = *pipe_config; - to_intel_crtc(crtc)->new_config = &to_intel_crtc(crtc)->config; + intel_crtc_set_state(to_intel_crtc(crtc), pipe_config); /* * Calculate and store various constants which @@ -11101,7 +11119,7 @@ static int __intel_set_mode(struct drm_crtc *crtc, * timestamping. They are derived from true hwmode. */ drm_calc_timestamping_constants(crtc, - &pipe_config->adjusted_mode); + &pipe_config->base.adjusted_mode); } /* Only after disabling all output pipelines that will be changed can we @@ -11114,26 +11132,15 @@ static int __intel_set_mode(struct drm_crtc *crtc, * on the DPLL. */ for_each_intel_crtc_masked(dev, modeset_pipes, intel_crtc) { - struct drm_framebuffer *old_fb = crtc->primary->fb; - struct drm_i915_gem_object *old_obj = intel_fb_obj(old_fb); - struct drm_i915_gem_object *obj = intel_fb_obj(fb); - - mutex_lock(&dev->struct_mutex); - ret = intel_pin_and_fence_fb_obj(crtc->primary, fb, NULL); - if (ret != 0) { - DRM_ERROR("pin & fence failed\n"); - mutex_unlock(&dev->struct_mutex); - goto done; - } - if (old_fb) - intel_unpin_fb_obj(old_obj); - i915_gem_track_fb(old_obj, obj, - INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe)); - mutex_unlock(&dev->struct_mutex); + struct drm_plane *primary = intel_crtc->base.primary; + int vdisplay, hdisplay; - crtc->primary->fb = fb; - crtc->x = x; - crtc->y = y; + drm_crtc_get_hv_timing(mode, &hdisplay, &vdisplay); + ret = primary->funcs->update_plane(primary, &intel_crtc->base, + fb, 0, 0, + hdisplay, vdisplay, + x << 16, y << 16, + hdisplay << 16, vdisplay << 16); } /* Now enable the clocks, plane, pipe, and connectors that we set up. */ @@ -11148,7 +11155,6 @@ done: if (ret && crtc->enabled) crtc->mode = *saved_mode; - kfree(pipe_config); kfree(saved_mode); return ret; } @@ -11156,7 +11162,7 @@ done: static int intel_set_mode_pipes(struct drm_crtc *crtc, struct drm_display_mode *mode, int x, int y, struct drm_framebuffer *fb, - struct intel_crtc_config *pipe_config, + struct intel_crtc_state *pipe_config, unsigned modeset_pipes, unsigned prepare_pipes, unsigned disable_pipes) @@ -11176,7 +11182,7 @@ static int intel_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, int x, int y, struct drm_framebuffer *fb) { - struct intel_crtc_config *pipe_config; + struct intel_crtc_state *pipe_config; unsigned modeset_pipes, prepare_pipes, disable_pipes; pipe_config = intel_modeset_compute_config(crtc, mode, fb, @@ -11271,7 +11277,7 @@ static void intel_set_config_restore_state(struct drm_device *dev, crtc->new_enabled = config->save_crtc_enabled[count++]; if (crtc->new_enabled) - crtc->new_config = &crtc->config; + crtc->new_config = crtc->config; else crtc->new_config = NULL; } @@ -11483,7 +11489,7 @@ intel_modeset_stage_output_state(struct drm_device *dev, } if (crtc->new_enabled) - crtc->new_config = &crtc->config; + crtc->new_config = crtc->config; else crtc->new_config = NULL; } @@ -11520,7 +11526,7 @@ 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; - struct intel_crtc_config *pipe_config; + struct intel_crtc_state *pipe_config; unsigned modeset_pipes, prepare_pipes, disable_pipes; int ret; @@ -11577,7 +11583,7 @@ static int intel_crtc_set_config(struct drm_mode_set *set) goto fail; } else if (pipe_config) { if (pipe_config->has_audio != - to_intel_crtc(set->crtc)->config.has_audio) + to_intel_crtc(set->crtc)->config->has_audio) config->mode_changed = true; /* @@ -11601,11 +11607,14 @@ static int intel_crtc_set_config(struct drm_mode_set *set) disable_pipes); } else if (config->fb_changed) { struct intel_crtc *intel_crtc = to_intel_crtc(set->crtc); + struct drm_plane *primary = set->crtc->primary; + int vdisplay, hdisplay; - intel_crtc_wait_for_pending_flips(set->crtc); - - ret = intel_pipe_set_base(set->crtc, - set->x, set->y, set->fb); + drm_crtc_get_hv_timing(set->mode, &hdisplay, &vdisplay); + ret = primary->funcs->update_plane(primary, set->crtc, set->fb, + 0, 0, hdisplay, vdisplay, + set->x << 16, set->y << 16, + hdisplay << 16, vdisplay << 16); /* * We need to make sure the primary plane is re-enabled if it @@ -11660,6 +11669,8 @@ static const struct drm_crtc_funcs intel_crtc_funcs = { .set_config = intel_crtc_set_config, .destroy = intel_crtc_destroy, .page_flip = intel_crtc_page_flip, + .atomic_duplicate_state = intel_crtc_duplicate_state, + .atomic_destroy_state = intel_crtc_destroy_state, }; static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv, @@ -11762,93 +11773,149 @@ static void intel_shared_dpll_init(struct drm_device *dev) BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS); } -static int -intel_primary_plane_disable(struct drm_plane *plane) +/** + * intel_prepare_plane_fb - Prepare fb for usage on plane + * @plane: drm plane to prepare for + * @fb: framebuffer to prepare for presentation + * + * Prepares a framebuffer for usage on a display plane. Generally this + * involves pinning the underlying object and updating the frontbuffer tracking + * bits. Some older platforms need special physical address handling for + * cursor planes. + * + * Returns 0 on success, negative error code on failure. + */ +int +intel_prepare_plane_fb(struct drm_plane *plane, + struct drm_framebuffer *fb) { struct drm_device *dev = plane->dev; - struct intel_crtc *intel_crtc; + struct intel_plane *intel_plane = to_intel_plane(plane); + enum pipe pipe = intel_plane->pipe; + struct drm_i915_gem_object *obj = intel_fb_obj(fb); + struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb); + unsigned frontbuffer_bits = 0; + int ret = 0; - if (!plane->fb) + if (!obj) return 0; - BUG_ON(!plane->crtc); + switch (plane->type) { + case DRM_PLANE_TYPE_PRIMARY: + frontbuffer_bits = INTEL_FRONTBUFFER_PRIMARY(pipe); + break; + case DRM_PLANE_TYPE_CURSOR: + frontbuffer_bits = INTEL_FRONTBUFFER_CURSOR(pipe); + break; + case DRM_PLANE_TYPE_OVERLAY: + frontbuffer_bits = INTEL_FRONTBUFFER_SPRITE(pipe); + break; + } - intel_crtc = to_intel_crtc(plane->crtc); + mutex_lock(&dev->struct_mutex); - /* - * Even though we checked plane->fb above, it's still possible that - * the primary plane has been implicitly disabled because the crtc - * coordinates given weren't visible, or because we detected - * that it was 100% covered by a sprite plane. Or, the CRTC may be - * off and we've set a fb, but haven't actually turned on the CRTC yet. - * In either case, we need to unpin the FB and let the fb pointer get - * updated, but otherwise we don't need to touch the hardware. - */ - if (!intel_crtc->primary_enabled) - goto disable_unpin; + if (plane->type == DRM_PLANE_TYPE_CURSOR && + INTEL_INFO(dev)->cursor_needs_physical) { + int align = IS_I830(dev) ? 16 * 1024 : 256; + ret = i915_gem_object_attach_phys(obj, align); + if (ret) + DRM_DEBUG_KMS("failed to attach phys object\n"); + } else { + ret = intel_pin_and_fence_fb_obj(plane, fb, NULL); + } - intel_crtc_wait_for_pending_flips(plane->crtc); - intel_disable_primary_hw_plane(plane, plane->crtc); + if (ret == 0) + i915_gem_track_fb(old_obj, obj, frontbuffer_bits); -disable_unpin: - mutex_lock(&dev->struct_mutex); - i915_gem_track_fb(intel_fb_obj(plane->fb), NULL, - INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe)); - intel_unpin_fb_obj(intel_fb_obj(plane->fb)); mutex_unlock(&dev->struct_mutex); - plane->fb = NULL; - return 0; + return ret; +} + +/** + * intel_cleanup_plane_fb - Cleans up an fb after plane use + * @plane: drm plane to clean up for + * @fb: old framebuffer that was on plane + * + * Cleans up a framebuffer that has just been removed from a plane. + */ +void +intel_cleanup_plane_fb(struct drm_plane *plane, + struct drm_framebuffer *fb) +{ + struct drm_device *dev = plane->dev; + struct drm_i915_gem_object *obj = intel_fb_obj(fb); + + if (WARN_ON(!obj)) + return; + + if (plane->type != DRM_PLANE_TYPE_CURSOR || + !INTEL_INFO(dev)->cursor_needs_physical) { + mutex_lock(&dev->struct_mutex); + intel_unpin_fb_obj(obj); + mutex_unlock(&dev->struct_mutex); + } } static int intel_check_primary_plane(struct drm_plane *plane, struct intel_plane_state *state) { - struct drm_crtc *crtc = state->crtc; - struct drm_framebuffer *fb = state->fb; + struct drm_device *dev = plane->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_crtc *crtc = state->base.crtc; + struct intel_crtc *intel_crtc; + struct drm_framebuffer *fb = state->base.fb; struct drm_rect *dest = &state->dst; struct drm_rect *src = &state->src; const struct drm_rect *clip = &state->clip; + int ret; - return drm_plane_helper_check_update(plane, crtc, fb, - src, dest, clip, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, - false, true, &state->visible); -} + crtc = crtc ? crtc : plane->crtc; + intel_crtc = to_intel_crtc(crtc); -static int -intel_prepare_primary_plane(struct drm_plane *plane, - struct intel_plane_state *state) -{ - struct drm_crtc *crtc = state->crtc; - struct drm_framebuffer *fb = state->fb; - struct drm_device *dev = crtc->dev; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - enum pipe pipe = intel_crtc->pipe; - struct drm_i915_gem_object *obj = intel_fb_obj(fb); - struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb); - int ret; + ret = drm_plane_helper_check_update(plane, crtc, fb, + src, dest, clip, + DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_HELPER_NO_SCALING, + false, true, &state->visible); + if (ret) + return ret; - intel_crtc_wait_for_pending_flips(crtc); + if (intel_crtc->active) { + intel_crtc->atomic.wait_for_flips = true; - if (intel_crtc_has_pending_flip(crtc)) { - DRM_ERROR("pipe is still busy with an old pageflip\n"); - return -EBUSY; - } + /* + * FBC does not work on some platforms for rotated + * planes, so disable it when rotation is not 0 and + * update it when rotation is set back to 0. + * + * FIXME: This is redundant with the fbc update done in + * the primary plane enable function except that that + * one is done too late. We eventually need to unify + * this. + */ + if (intel_crtc->primary_enabled && + INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev) && + dev_priv->fbc.plane == intel_crtc->plane && + state->base.rotation != BIT(DRM_ROTATE_0)) { + intel_crtc->atomic.disable_fbc = true; + } - if (old_obj != obj) { - mutex_lock(&dev->struct_mutex); - ret = intel_pin_and_fence_fb_obj(plane, fb, NULL); - if (ret == 0) - i915_gem_track_fb(old_obj, obj, - INTEL_FRONTBUFFER_PRIMARY(pipe)); - mutex_unlock(&dev->struct_mutex); - if (ret != 0) { - DRM_DEBUG_KMS("pin & fence failed\n"); - return ret; + if (state->visible) { + /* + * BDW signals flip done immediately if the plane + * is disabled, even if the plane enable is already + * armed to occur at the next vblank :( + */ + if (IS_BROADWELL(dev) && !intel_crtc->primary_enabled) + intel_crtc->atomic.wait_vblank = true; } + + intel_crtc->atomic.fb_bits |= + INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe); + + intel_crtc->atomic.update_fbc = true; } return 0; @@ -11858,53 +11925,26 @@ static void intel_commit_primary_plane(struct drm_plane *plane, struct intel_plane_state *state) { - struct drm_crtc *crtc = state->crtc; - struct drm_framebuffer *fb = state->fb; - struct drm_device *dev = crtc->dev; + struct drm_crtc *crtc = state->base.crtc; + struct drm_framebuffer *fb = state->base.fb; + struct drm_device *dev = plane->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; - struct drm_framebuffer *old_fb = plane->fb; + struct intel_crtc *intel_crtc; struct drm_i915_gem_object *obj = intel_fb_obj(fb); - struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb); struct intel_plane *intel_plane = to_intel_plane(plane); struct drm_rect *src = &state->src; - crtc->primary->fb = fb; + crtc = crtc ? crtc : plane->crtc; + intel_crtc = to_intel_crtc(crtc); + + plane->fb = fb; crtc->x = src->x1 >> 16; crtc->y = src->y1 >> 16; - intel_plane->crtc_x = state->orig_dst.x1; - intel_plane->crtc_y = state->orig_dst.y1; - intel_plane->crtc_w = drm_rect_width(&state->orig_dst); - intel_plane->crtc_h = drm_rect_height(&state->orig_dst); - intel_plane->src_x = state->orig_src.x1; - intel_plane->src_y = state->orig_src.y1; - intel_plane->src_w = drm_rect_width(&state->orig_src); - intel_plane->src_h = drm_rect_height(&state->orig_src); intel_plane->obj = obj; if (intel_crtc->active) { - /* - * FBC does not work on some platforms for rotated - * planes, so disable it when rotation is not 0 and - * update it when rotation is set back to 0. - * - * FIXME: This is redundant with the fbc update done in - * the primary plane enable function except that that - * one is done too late. We eventually need to unify - * this. - */ - if (intel_crtc->primary_enabled && - INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev) && - dev_priv->fbc.plane == intel_crtc->plane && - intel_plane->rotation != BIT(DRM_ROTATE_0)) { - intel_disable_fbc(dev); - } - if (state->visible) { - bool was_enabled = intel_crtc->primary_enabled; - /* FIXME: kill this fastboot hack */ intel_update_pipe_size(intel_crtc); @@ -11912,14 +11952,6 @@ intel_commit_primary_plane(struct drm_plane *plane, dev_priv->display.update_primary_plane(crtc, plane->fb, crtc->x, crtc->y); - - /* - * BDW signals flip done immediately if the plane - * is disabled, even if the plane enable is already - * armed to occur at the next vblank :( - */ - if (IS_BROADWELL(dev) && !was_enabled) - intel_wait_for_vblank(dev, intel_crtc->pipe); } else { /* * If clipping results in a non-visible primary plane, @@ -11930,90 +11962,129 @@ intel_commit_primary_plane(struct drm_plane *plane, */ intel_disable_primary_hw_plane(plane, crtc); } + } +} - intel_frontbuffer_flip(dev, INTEL_FRONTBUFFER_PRIMARY(pipe)); +static void intel_begin_crtc_commit(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_plane *intel_plane; + struct drm_plane *p; + unsigned fb_bits = 0; + + /* Track fb's for any planes being disabled */ + list_for_each_entry(p, &dev->mode_config.plane_list, head) { + intel_plane = to_intel_plane(p); + + if (intel_crtc->atomic.disabled_planes & + (1 << drm_plane_index(p))) { + switch (p->type) { + case DRM_PLANE_TYPE_PRIMARY: + fb_bits = INTEL_FRONTBUFFER_PRIMARY(intel_plane->pipe); + break; + case DRM_PLANE_TYPE_CURSOR: + fb_bits = INTEL_FRONTBUFFER_CURSOR(intel_plane->pipe); + break; + case DRM_PLANE_TYPE_OVERLAY: + fb_bits = INTEL_FRONTBUFFER_SPRITE(intel_plane->pipe); + break; + } - mutex_lock(&dev->struct_mutex); - intel_update_fbc(dev); - mutex_unlock(&dev->struct_mutex); + mutex_lock(&dev->struct_mutex); + i915_gem_track_fb(intel_fb_obj(p->fb), NULL, fb_bits); + mutex_unlock(&dev->struct_mutex); + } } - if (old_fb && old_fb != fb) { - if (intel_crtc->active) - intel_wait_for_vblank(dev, intel_crtc->pipe); + if (intel_crtc->atomic.wait_for_flips) + intel_crtc_wait_for_pending_flips(crtc); - mutex_lock(&dev->struct_mutex); - intel_unpin_fb_obj(old_obj); - mutex_unlock(&dev->struct_mutex); - } + if (intel_crtc->atomic.disable_fbc) + intel_fbc_disable(dev); + + if (intel_crtc->atomic.pre_disable_primary) + intel_pre_disable_primary(crtc); + + if (intel_crtc->atomic.update_wm) + intel_update_watermarks(crtc); + + intel_runtime_pm_get(dev_priv); + + /* Perform vblank evasion around commit operation */ + if (intel_crtc->active) + intel_crtc->atomic.evade = + intel_pipe_update_start(intel_crtc, + &intel_crtc->atomic.start_vbl_count); } -static int -intel_primary_plane_setplane(struct drm_plane *plane, struct drm_crtc *crtc, - struct drm_framebuffer *fb, int crtc_x, int crtc_y, - unsigned int crtc_w, unsigned int crtc_h, - uint32_t src_x, uint32_t src_y, - uint32_t src_w, uint32_t src_h) +static void intel_finish_crtc_commit(struct drm_crtc *crtc) { - struct intel_plane_state state; + 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; + struct drm_plane *p; - state.crtc = crtc; - state.fb = fb; + if (intel_crtc->atomic.evade) + intel_pipe_update_end(intel_crtc, + intel_crtc->atomic.start_vbl_count); - /* sample coordinates in 16.16 fixed point */ - state.src.x1 = src_x; - state.src.x2 = src_x + src_w; - state.src.y1 = src_y; - state.src.y2 = src_y + src_h; - - /* integer pixels */ - state.dst.x1 = crtc_x; - state.dst.x2 = crtc_x + crtc_w; - state.dst.y1 = crtc_y; - state.dst.y2 = crtc_y + crtc_h; + intel_runtime_pm_put(dev_priv); - state.clip.x1 = 0; - state.clip.y1 = 0; - state.clip.x2 = intel_crtc->active ? intel_crtc->config.pipe_src_w : 0; - state.clip.y2 = intel_crtc->active ? intel_crtc->config.pipe_src_h : 0; + if (intel_crtc->atomic.wait_vblank) + intel_wait_for_vblank(dev, intel_crtc->pipe); - state.orig_src = state.src; - state.orig_dst = state.dst; + intel_frontbuffer_flip(dev, intel_crtc->atomic.fb_bits); - ret = intel_check_primary_plane(plane, &state); - if (ret) - return ret; + if (intel_crtc->atomic.update_fbc) { + mutex_lock(&dev->struct_mutex); + intel_fbc_update(dev); + mutex_unlock(&dev->struct_mutex); + } - ret = intel_prepare_primary_plane(plane, &state); - if (ret) - return ret; + if (intel_crtc->atomic.post_enable_primary) + intel_post_enable_primary(crtc); - intel_commit_primary_plane(plane, &state); + drm_for_each_legacy_plane(p, &dev->mode_config.plane_list) + if (intel_crtc->atomic.update_sprite_watermarks & drm_plane_index(p)) + intel_update_sprite_watermarks(p, crtc, 0, 0, 0, + false, false); - return 0; + memset(&intel_crtc->atomic, 0, sizeof(intel_crtc->atomic)); } -/* Common destruction function for both primary and cursor planes */ -static void intel_plane_destroy(struct drm_plane *plane) +/** + * intel_plane_destroy - destroy a plane + * @plane: plane to destroy + * + * Common destruction function for all types of planes (primary, cursor, + * sprite). + */ +void intel_plane_destroy(struct drm_plane *plane) { struct intel_plane *intel_plane = to_intel_plane(plane); drm_plane_cleanup(plane); kfree(intel_plane); } -static const struct drm_plane_funcs intel_primary_plane_funcs = { - .update_plane = intel_primary_plane_setplane, - .disable_plane = intel_primary_plane_disable, +const struct drm_plane_funcs intel_plane_funcs = { + .update_plane = drm_plane_helper_update, + .disable_plane = drm_plane_helper_disable, .destroy = intel_plane_destroy, - .set_property = intel_plane_set_property + .set_property = drm_atomic_helper_plane_set_property, + .atomic_get_property = intel_plane_atomic_get_property, + .atomic_set_property = intel_plane_atomic_set_property, + .atomic_duplicate_state = intel_plane_duplicate_state, + .atomic_destroy_state = intel_plane_destroy_state, + }; static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, int pipe) { struct intel_plane *primary; + struct intel_plane_state *state; const uint32_t *intel_primary_formats; int num_formats; @@ -12021,11 +12092,19 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, if (primary == NULL) return NULL; + state = intel_create_plane_state(&primary->base); + if (!state) { + kfree(primary); + return NULL; + } + primary->base.state = &state->base; + primary->can_scale = false; primary->max_downscale = 1; primary->pipe = pipe; primary->plane = pipe; - primary->rotation = BIT(DRM_ROTATE_0); + primary->check_plane = intel_check_primary_plane; + primary->commit_plane = intel_commit_primary_plane; if (HAS_FBC(dev) && INTEL_INFO(dev)->gen < 4) primary->plane = !pipe; @@ -12038,7 +12117,7 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, } drm_universal_plane_init(dev, &primary->base, 0, - &intel_primary_plane_funcs, + &intel_plane_funcs, intel_primary_formats, num_formats, DRM_PLANE_TYPE_PRIMARY); @@ -12051,38 +12130,32 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, if (dev->mode_config.rotation_property) drm_object_attach_property(&primary->base.base, dev->mode_config.rotation_property, - primary->rotation); + state->base.rotation); } - return &primary->base; -} - -static int -intel_cursor_plane_disable(struct drm_plane *plane) -{ - if (!plane->fb) - return 0; - - BUG_ON(!plane->crtc); + drm_plane_helper_add(&primary->base, &intel_plane_helper_funcs); - return intel_crtc_cursor_set_obj(plane->crtc, NULL, 0, 0); + return &primary->base; } static int intel_check_cursor_plane(struct drm_plane *plane, struct intel_plane_state *state) { - struct drm_crtc *crtc = state->crtc; - struct drm_device *dev = crtc->dev; - struct drm_framebuffer *fb = state->fb; + struct drm_crtc *crtc = state->base.crtc; + struct drm_device *dev = plane->dev; + struct drm_framebuffer *fb = state->base.fb; struct drm_rect *dest = &state->dst; struct drm_rect *src = &state->src; const struct drm_rect *clip = &state->clip; struct drm_i915_gem_object *obj = intel_fb_obj(fb); - int crtc_w, crtc_h; + struct intel_crtc *intel_crtc; unsigned stride; int ret; + crtc = crtc ? crtc : plane->crtc; + intel_crtc = to_intel_crtc(crtc); + ret = drm_plane_helper_check_update(plane, crtc, fb, src, dest, clip, DRM_PLANE_HELPER_NO_SCALING, @@ -12094,18 +12167,17 @@ intel_check_cursor_plane(struct drm_plane *plane, /* if we want to turn off the cursor ignore width and height */ if (!obj) - return 0; + goto finish; /* Check for which cursor types we support */ - crtc_w = drm_rect_width(&state->orig_dst); - crtc_h = drm_rect_height(&state->orig_dst); - if (!cursor_size_ok(dev, crtc_w, crtc_h)) { - DRM_DEBUG("Cursor dimension not supported\n"); + if (!cursor_size_ok(dev, state->base.crtc_w, state->base.crtc_h)) { + DRM_DEBUG("Cursor dimension %dx%d not supported\n", + state->base.crtc_w, state->base.crtc_h); return -EINVAL; } - stride = roundup_pow_of_two(crtc_w) * 4; - if (obj->base.size < stride * crtc_h) { + stride = roundup_pow_of_two(state->base.crtc_w) * 4; + if (obj->base.size < stride * state->base.crtc_h) { DRM_DEBUG_KMS("buffer is too small\n"); return -ENOMEM; } @@ -12121,113 +12193,84 @@ intel_check_cursor_plane(struct drm_plane *plane, } mutex_unlock(&dev->struct_mutex); +finish: + if (intel_crtc->active) { + if (intel_crtc->cursor_width != state->base.crtc_w) + intel_crtc->atomic.update_wm = true; + + intel_crtc->atomic.fb_bits |= + INTEL_FRONTBUFFER_CURSOR(intel_crtc->pipe); + } + return ret; } -static int +static void intel_commit_cursor_plane(struct drm_plane *plane, struct intel_plane_state *state) { - struct drm_crtc *crtc = state->crtc; - struct drm_framebuffer *fb = state->fb; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct drm_crtc *crtc = state->base.crtc; + struct drm_device *dev = plane->dev; + struct intel_crtc *intel_crtc; struct intel_plane *intel_plane = to_intel_plane(plane); - struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); - struct drm_i915_gem_object *obj = intel_fb->obj; - int crtc_w, crtc_h; - - crtc->cursor_x = state->orig_dst.x1; - crtc->cursor_y = state->orig_dst.y1; - - intel_plane->crtc_x = state->orig_dst.x1; - intel_plane->crtc_y = state->orig_dst.y1; - intel_plane->crtc_w = drm_rect_width(&state->orig_dst); - intel_plane->crtc_h = drm_rect_height(&state->orig_dst); - intel_plane->src_x = state->orig_src.x1; - intel_plane->src_y = state->orig_src.y1; - intel_plane->src_w = drm_rect_width(&state->orig_src); - intel_plane->src_h = drm_rect_height(&state->orig_src); - intel_plane->obj = obj; - - if (fb != crtc->cursor->fb) { - crtc_w = drm_rect_width(&state->orig_dst); - crtc_h = drm_rect_height(&state->orig_dst); - return intel_crtc_cursor_set_obj(crtc, obj, crtc_w, crtc_h); - } else { - intel_crtc_update_cursor(crtc, state->visible); - - intel_frontbuffer_flip(crtc->dev, - INTEL_FRONTBUFFER_CURSOR(intel_crtc->pipe)); - - return 0; - } -} - -static int -intel_cursor_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, - struct drm_framebuffer *fb, int crtc_x, int crtc_y, - unsigned int crtc_w, unsigned int crtc_h, - uint32_t src_x, uint32_t src_y, - uint32_t src_w, uint32_t src_h) -{ - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct intel_plane_state state; - int ret; + struct drm_i915_gem_object *obj = intel_fb_obj(state->base.fb); + uint32_t addr; - state.crtc = crtc; - state.fb = fb; + crtc = crtc ? crtc : plane->crtc; + intel_crtc = to_intel_crtc(crtc); - /* sample coordinates in 16.16 fixed point */ - state.src.x1 = src_x; - state.src.x2 = src_x + src_w; - state.src.y1 = src_y; - state.src.y2 = src_y + src_h; + plane->fb = state->base.fb; + crtc->cursor_x = state->base.crtc_x; + crtc->cursor_y = state->base.crtc_y; - /* integer pixels */ - state.dst.x1 = crtc_x; - state.dst.x2 = crtc_x + crtc_w; - state.dst.y1 = crtc_y; - state.dst.y2 = crtc_y + crtc_h; + intel_plane->obj = obj; - state.clip.x1 = 0; - state.clip.y1 = 0; - state.clip.x2 = intel_crtc->active ? intel_crtc->config.pipe_src_w : 0; - state.clip.y2 = intel_crtc->active ? intel_crtc->config.pipe_src_h : 0; + if (intel_crtc->cursor_bo == obj) + goto update; - state.orig_src = state.src; - state.orig_dst = state.dst; + if (!obj) + addr = 0; + else if (!INTEL_INFO(dev)->cursor_needs_physical) + addr = i915_gem_obj_ggtt_offset(obj); + else + addr = obj->phys_handle->busaddr; - ret = intel_check_cursor_plane(plane, &state); - if (ret) - return ret; + intel_crtc->cursor_addr = addr; + intel_crtc->cursor_bo = obj; +update: + intel_crtc->cursor_width = state->base.crtc_w; + intel_crtc->cursor_height = state->base.crtc_h; - return intel_commit_cursor_plane(plane, &state); + if (intel_crtc->active) + intel_crtc_update_cursor(crtc, state->visible); } -static const struct drm_plane_funcs intel_cursor_plane_funcs = { - .update_plane = intel_cursor_plane_update, - .disable_plane = intel_cursor_plane_disable, - .destroy = intel_plane_destroy, - .set_property = intel_plane_set_property, -}; - static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev, int pipe) { struct intel_plane *cursor; + struct intel_plane_state *state; cursor = kzalloc(sizeof(*cursor), GFP_KERNEL); if (cursor == NULL) return NULL; + state = intel_create_plane_state(&cursor->base); + if (!state) { + kfree(cursor); + return NULL; + } + cursor->base.state = &state->base; + cursor->can_scale = false; cursor->max_downscale = 1; cursor->pipe = pipe; cursor->plane = pipe; - cursor->rotation = BIT(DRM_ROTATE_0); + cursor->check_plane = intel_check_cursor_plane; + cursor->commit_plane = intel_commit_cursor_plane; drm_universal_plane_init(dev, &cursor->base, 0, - &intel_cursor_plane_funcs, + &intel_plane_funcs, intel_cursor_formats, ARRAY_SIZE(intel_cursor_formats), DRM_PLANE_TYPE_CURSOR); @@ -12241,9 +12284,11 @@ static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev, if (dev->mode_config.rotation_property) drm_object_attach_property(&cursor->base.base, dev->mode_config.rotation_property, - cursor->rotation); + state->base.rotation); } + drm_plane_helper_add(&cursor->base, &intel_plane_helper_funcs); + return &cursor->base; } @@ -12251,6 +12296,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc; + struct intel_crtc_state *crtc_state = NULL; struct drm_plane *primary = NULL; struct drm_plane *cursor = NULL; int i, ret; @@ -12259,6 +12305,11 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) if (intel_crtc == NULL) return; + crtc_state = kzalloc(sizeof(*crtc_state), GFP_KERNEL); + if (!crtc_state) + goto fail; + intel_crtc_set_state(intel_crtc, crtc_state); + primary = intel_primary_plane_create(dev, pipe); if (!primary) goto fail; @@ -12311,6 +12362,7 @@ fail: drm_plane_cleanup(primary); if (cursor) drm_plane_cleanup(cursor); + kfree(crtc_state); kfree(intel_crtc); } @@ -12383,28 +12435,6 @@ static bool has_edp_a(struct drm_device *dev) return true; } -const char *intel_output_name(int output) -{ - static const char *names[] = { - [INTEL_OUTPUT_UNUSED] = "Unused", - [INTEL_OUTPUT_ANALOG] = "Analog", - [INTEL_OUTPUT_DVO] = "DVO", - [INTEL_OUTPUT_SDVO] = "SDVO", - [INTEL_OUTPUT_LVDS] = "LVDS", - [INTEL_OUTPUT_TVOUT] = "TV", - [INTEL_OUTPUT_HDMI] = "HDMI", - [INTEL_OUTPUT_DISPLAYPORT] = "DisplayPort", - [INTEL_OUTPUT_EDP] = "eDP", - [INTEL_OUTPUT_DSI] = "DSI", - [INTEL_OUTPUT_UNKNOWN] = "Unknown", - }; - - if (output < 0 || output >= ARRAY_SIZE(names) || !names[output]) - return "Invalid"; - - return names[output]; -} - static bool intel_crt_present(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -12428,6 +12458,7 @@ static void intel_setup_outputs(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_encoder *encoder; + struct drm_connector *connector; bool dpd_is_edp = false; intel_lvds_init(dev); @@ -12491,14 +12522,16 @@ static void intel_setup_outputs(struct drm_device *dev) * eDP ports. Consult the VBT as well as DP_DETECTED to * detect eDP ports. */ - if (I915_READ(VLV_DISPLAY_BASE + GEN4_HDMIB) & SDVO_DETECTED) + if (I915_READ(VLV_DISPLAY_BASE + GEN4_HDMIB) & SDVO_DETECTED && + !intel_dp_is_edp(dev, PORT_B)) intel_hdmi_init(dev, VLV_DISPLAY_BASE + GEN4_HDMIB, PORT_B); if (I915_READ(VLV_DISPLAY_BASE + DP_B) & DP_DETECTED || intel_dp_is_edp(dev, PORT_B)) intel_dp_init(dev, VLV_DISPLAY_BASE + DP_B, PORT_B); - if (I915_READ(VLV_DISPLAY_BASE + GEN4_HDMIC) & SDVO_DETECTED) + if (I915_READ(VLV_DISPLAY_BASE + GEN4_HDMIC) & SDVO_DETECTED && + !intel_dp_is_edp(dev, PORT_C)) intel_hdmi_init(dev, VLV_DISPLAY_BASE + GEN4_HDMIC, PORT_C); if (I915_READ(VLV_DISPLAY_BASE + DP_C) & DP_DETECTED || @@ -12556,6 +12589,37 @@ static void intel_setup_outputs(struct drm_device *dev) if (SUPPORTS_TV(dev)) intel_tv_init(dev); + /* + * FIXME: We don't have full atomic support yet, but we want to be + * able to enable/test plane updates via the atomic interface in the + * meantime. However as soon as we flip DRIVER_ATOMIC on, the DRM core + * will take some atomic codepaths to lookup properties during + * drmModeGetConnector() that unconditionally dereference + * connector->state. + * + * We create a dummy connector state here for each connector to ensure + * the DRM core doesn't try to dereference a NULL connector->state. + * The actual connector properties will never be updated or contain + * useful information, but since we're doing this specifically for + * testing/debug of the plane operations (and only when a specific + * kernel module option is given), that shouldn't really matter. + * + * Once atomic support for crtc's + connectors lands, this loop should + * be removed since we'll be setting up real connector state, which + * will contain Intel-specific properties. + */ + if (drm_core_check_feature(dev, DRIVER_ATOMIC)) { + list_for_each_entry(connector, + &dev->mode_config.connector_list, + head) { + if (!WARN_ON(connector->state)) { + connector->state = + kzalloc(sizeof(*connector->state), + GFP_KERNEL); + } + } + } + intel_psr_init(dev); for_each_intel_encoder(dev, encoder) { @@ -12696,8 +12760,8 @@ static int intel_framebuffer_init(struct drm_device *dev, if (mode_cmd->offsets[0] != 0) return -EINVAL; - aligned_height = intel_align_height(dev, mode_cmd->height, - obj->tiling_mode); + aligned_height = intel_fb_align_height(dev, mode_cmd->height, + obj->tiling_mode); /* FIXME drm helper for size checks (especially planar formats)? */ if (obj->base.size < aligned_height * mode_cmd->pitches[0]) return -EINVAL; @@ -12739,6 +12803,8 @@ static inline void intel_fbdev_output_poll_changed(struct drm_device *dev) static const struct drm_mode_config_funcs intel_mode_funcs = { .fb_create = intel_user_framebuffer_create, .output_poll_changed = intel_fbdev_output_poll_changed, + .atomic_check = intel_atomic_check, + .atomic_commit = intel_atomic_commit, }; /* Set up chip specific display functions */ @@ -12757,23 +12823,32 @@ static void intel_init_display(struct drm_device *dev) else dev_priv->display.find_dpll = i9xx_find_best_dpll; - if (HAS_DDI(dev)) { + if (INTEL_INFO(dev)->gen >= 9) { dev_priv->display.get_pipe_config = haswell_get_pipe_config; - dev_priv->display.get_plane_config = ironlake_get_plane_config; + dev_priv->display.get_initial_plane_config = + skylake_get_initial_plane_config; dev_priv->display.crtc_compute_clock = haswell_crtc_compute_clock; dev_priv->display.crtc_enable = haswell_crtc_enable; dev_priv->display.crtc_disable = haswell_crtc_disable; dev_priv->display.off = ironlake_crtc_off; - if (INTEL_INFO(dev)->gen >= 9) - dev_priv->display.update_primary_plane = - skylake_update_primary_plane; - else - dev_priv->display.update_primary_plane = - ironlake_update_primary_plane; + dev_priv->display.update_primary_plane = + skylake_update_primary_plane; + } else if (HAS_DDI(dev)) { + dev_priv->display.get_pipe_config = haswell_get_pipe_config; + dev_priv->display.get_initial_plane_config = + ironlake_get_initial_plane_config; + dev_priv->display.crtc_compute_clock = + haswell_crtc_compute_clock; + dev_priv->display.crtc_enable = haswell_crtc_enable; + dev_priv->display.crtc_disable = haswell_crtc_disable; + dev_priv->display.off = ironlake_crtc_off; + dev_priv->display.update_primary_plane = + ironlake_update_primary_plane; } else if (HAS_PCH_SPLIT(dev)) { dev_priv->display.get_pipe_config = ironlake_get_pipe_config; - dev_priv->display.get_plane_config = ironlake_get_plane_config; + dev_priv->display.get_initial_plane_config = + ironlake_get_initial_plane_config; dev_priv->display.crtc_compute_clock = ironlake_crtc_compute_clock; dev_priv->display.crtc_enable = ironlake_crtc_enable; @@ -12783,7 +12858,8 @@ static void intel_init_display(struct drm_device *dev) ironlake_update_primary_plane; } else if (IS_VALLEYVIEW(dev)) { dev_priv->display.get_pipe_config = i9xx_get_pipe_config; - dev_priv->display.get_plane_config = i9xx_get_plane_config; + dev_priv->display.get_initial_plane_config = + i9xx_get_initial_plane_config; dev_priv->display.crtc_compute_clock = i9xx_crtc_compute_clock; dev_priv->display.crtc_enable = valleyview_crtc_enable; dev_priv->display.crtc_disable = i9xx_crtc_disable; @@ -12792,7 +12868,8 @@ static void intel_init_display(struct drm_device *dev) i9xx_update_primary_plane; } else { dev_priv->display.get_pipe_config = i9xx_get_pipe_config; - dev_priv->display.get_plane_config = i9xx_get_plane_config; + dev_priv->display.get_initial_plane_config = + i9xx_get_initial_plane_config; dev_priv->display.crtc_compute_clock = i9xx_crtc_compute_clock; dev_priv->display.crtc_enable = i9xx_crtc_enable; dev_priv->display.crtc_disable = i9xx_crtc_disable; @@ -13147,7 +13224,7 @@ void intel_modeset_init(struct drm_device *dev) intel_setup_outputs(dev); /* Just in case the BIOS is doing something questionable. */ - intel_disable_fbc(dev); + intel_fbc_disable(dev); drm_modeset_lock_all(dev); intel_modeset_setup_hw_state(dev, false); @@ -13164,8 +13241,8 @@ void intel_modeset_init(struct drm_device *dev) * can even allow for smooth boot transitions if the BIOS * fb is large enough for the active pipe configuration. */ - if (dev_priv->display.get_plane_config) { - dev_priv->display.get_plane_config(crtc, + if (dev_priv->display.get_initial_plane_config) { + dev_priv->display.get_initial_plane_config(crtc, &crtc->plane_config); /* * If the fb is shared between multiple heads, we'll @@ -13229,7 +13306,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc) u32 reg; /* Clear any frame start delays used for debugging left by the BIOS */ - reg = PIPECONF(crtc->config.cpu_transcoder); + reg = PIPECONF(crtc->config->cpu_transcoder); I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK); /* restore vblank interrupts to correct state */ @@ -13433,12 +13510,12 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) int i; for_each_intel_crtc(dev, crtc) { - memset(&crtc->config, 0, sizeof(crtc->config)); + memset(crtc->config, 0, sizeof(*crtc->config)); - crtc->config.quirks |= PIPE_CONFIG_QUIRK_INHERITED_MODE; + crtc->config->quirks |= PIPE_CONFIG_QUIRK_INHERITED_MODE; crtc->active = dev_priv->display.get_pipe_config(crtc, - &crtc->config); + crtc->config); crtc->base.enabled = crtc->active; crtc->primary_enabled = primary_get_hw_state(crtc); @@ -13475,7 +13552,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) if (encoder->get_hw_state(encoder, &pipe)) { crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); encoder->base.crtc = &crtc->base; - encoder->get_config(encoder, &crtc->config); + encoder->get_config(encoder, crtc->config); } else { encoder->base.crtc = NULL; } @@ -13525,7 +13602,8 @@ void intel_modeset_setup_hw_state(struct drm_device *dev, */ for_each_intel_crtc(dev, crtc) { if (crtc->active && i915.fastboot) { - intel_mode_from_pipe_config(&crtc->base.mode, &crtc->config); + intel_mode_from_pipe_config(&crtc->base.mode, + crtc->config); DRM_DEBUG_KMS("[CRTC:%d] found active mode: ", crtc->base.base.id); drm_mode_debug_printmodeline(&crtc->base.mode); @@ -13540,7 +13618,8 @@ void intel_modeset_setup_hw_state(struct drm_device *dev, for_each_pipe(dev_priv, 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]"); + intel_dump_pipe_config(crtc, crtc->config, + "[setup_hw_state]"); } for (i = 0; i < dev_priv->num_shared_dpll; i++) { @@ -13664,7 +13743,7 @@ void intel_modeset_cleanup(struct drm_device *dev) intel_unregister_dsm_handler(); - intel_disable_fbc(dev); + intel_fbc_disable(dev); ironlake_teardown_rc6(dev); |