diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 448 |
1 files changed, 257 insertions, 191 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index dee3a8e659f1..17c590b42fd7 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1202,7 +1202,7 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv, enum pipe pipe) { i915_reg_t pp_reg; u32 val; - enum pipe panel_pipe = PIPE_A; + enum pipe panel_pipe = INVALID_PIPE; bool locked = true; if (WARN_ON(HAS_DDI(dev_priv))) @@ -1214,18 +1214,35 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv, enum pipe pipe) pp_reg = PP_CONTROL(0); port_sel = I915_READ(PP_ON_DELAYS(0)) & PANEL_PORT_SELECT_MASK; - if (port_sel == PANEL_PORT_SELECT_LVDS && - I915_READ(PCH_LVDS) & LVDS_PIPEB_SELECT) - panel_pipe = PIPE_B; - /* XXX: else fix for eDP */ + switch (port_sel) { + case PANEL_PORT_SELECT_LVDS: + intel_lvds_port_enabled(dev_priv, PCH_LVDS, &panel_pipe); + break; + case PANEL_PORT_SELECT_DPA: + intel_dp_port_enabled(dev_priv, DP_A, PORT_A, &panel_pipe); + break; + case PANEL_PORT_SELECT_DPC: + intel_dp_port_enabled(dev_priv, PCH_DP_C, PORT_C, &panel_pipe); + break; + case PANEL_PORT_SELECT_DPD: + intel_dp_port_enabled(dev_priv, PCH_DP_D, PORT_D, &panel_pipe); + break; + default: + MISSING_CASE(port_sel); + break; + } } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { /* presumably write lock depends on pipe, not port select */ pp_reg = PP_CONTROL(pipe); panel_pipe = pipe; } else { + u32 port_sel; + pp_reg = PP_CONTROL(0); - if (I915_READ(LVDS) & LVDS_PIPEB_SELECT) - panel_pipe = PIPE_B; + port_sel = I915_READ(PP_ON_DELAYS(0)) & PANEL_PORT_SELECT_MASK; + + WARN_ON(port_sel != PANEL_PORT_SELECT_LVDS); + intel_lvds_port_enabled(dev_priv, LVDS, &panel_pipe); } val = I915_READ(pp_reg); @@ -1267,7 +1284,10 @@ void assert_pipe(struct drm_i915_private *dev_priv, static void assert_plane(struct intel_plane *plane, bool state) { - bool cur_state = plane->get_hw_state(plane); + enum pipe pipe; + bool cur_state; + + cur_state = plane->get_hw_state(plane, &pipe); I915_STATE_WARN(cur_state != state, "%s assertion failure (expected %s, current %s)\n", @@ -1305,125 +1325,64 @@ void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv, pipe_name(pipe)); } -static bool dp_pipe_enabled(struct drm_i915_private *dev_priv, - enum pipe pipe, u32 port_sel, u32 val) +static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv, + enum pipe pipe, enum port port, + i915_reg_t dp_reg) { - if ((val & DP_PORT_EN) == 0) - return false; + enum pipe port_pipe; + bool state; - if (HAS_PCH_CPT(dev_priv)) { - u32 trans_dp_ctl = I915_READ(TRANS_DP_CTL(pipe)); - if ((trans_dp_ctl & TRANS_DP_PORT_SEL_MASK) != port_sel) - return false; - } else if (IS_CHERRYVIEW(dev_priv)) { - if ((val & DP_PIPE_MASK_CHV) != DP_PIPE_SELECT_CHV(pipe)) - return false; - } else { - if ((val & DP_PIPE_MASK) != (pipe << 30)) - return false; - } - return true; -} + state = intel_dp_port_enabled(dev_priv, dp_reg, port, &port_pipe); -static bool hdmi_pipe_enabled(struct drm_i915_private *dev_priv, - enum pipe pipe, u32 val) -{ - if ((val & SDVO_ENABLE) == 0) - return false; + I915_STATE_WARN(state && port_pipe == pipe, + "PCH DP %c enabled on transcoder %c, should be disabled\n", + port_name(port), pipe_name(pipe)); - if (HAS_PCH_CPT(dev_priv)) { - if ((val & SDVO_PIPE_SEL_MASK_CPT) != SDVO_PIPE_SEL_CPT(pipe)) - return false; - } else if (IS_CHERRYVIEW(dev_priv)) { - if ((val & SDVO_PIPE_SEL_MASK_CHV) != SDVO_PIPE_SEL_CHV(pipe)) - return false; - } else { - if ((val & SDVO_PIPE_SEL_MASK) != SDVO_PIPE_SEL(pipe)) - return false; - } - return true; + I915_STATE_WARN(HAS_PCH_IBX(dev_priv) && !state && port_pipe == PIPE_B, + "IBX PCH DP %c still using transcoder B\n", + port_name(port)); } -static bool lvds_pipe_enabled(struct drm_i915_private *dev_priv, - enum pipe pipe, u32 val) -{ - if ((val & LVDS_PORT_EN) == 0) - return false; - - if (HAS_PCH_CPT(dev_priv)) { - if ((val & PORT_TRANS_SEL_MASK) != PORT_TRANS_SEL_CPT(pipe)) - return false; - } else { - if ((val & LVDS_PIPE_MASK) != LVDS_PIPE(pipe)) - return false; - } - return true; -} - -static bool adpa_pipe_enabled(struct drm_i915_private *dev_priv, - enum pipe pipe, u32 val) -{ - if ((val & ADPA_DAC_ENABLE) == 0) - return false; - if (HAS_PCH_CPT(dev_priv)) { - if ((val & PORT_TRANS_SEL_MASK) != PORT_TRANS_SEL_CPT(pipe)) - return false; - } else { - if ((val & ADPA_PIPE_SELECT_MASK) != ADPA_PIPE_SELECT(pipe)) - return false; - } - return true; -} - -static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv, - enum pipe pipe, i915_reg_t reg, - u32 port_sel) +static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv, + enum pipe pipe, enum port port, + i915_reg_t hdmi_reg) { - u32 val = I915_READ(reg); - I915_STATE_WARN(dp_pipe_enabled(dev_priv, pipe, port_sel, val), - "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n", - i915_mmio_reg_offset(reg), pipe_name(pipe)); + enum pipe port_pipe; + bool state; - I915_STATE_WARN(HAS_PCH_IBX(dev_priv) && (val & DP_PORT_EN) == 0 - && (val & DP_PIPEB_SELECT), - "IBX PCH dp port still using transcoder B\n"); -} + state = intel_sdvo_port_enabled(dev_priv, hdmi_reg, &port_pipe); -static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv, - enum pipe pipe, i915_reg_t reg) -{ - u32 val = I915_READ(reg); - I915_STATE_WARN(hdmi_pipe_enabled(dev_priv, pipe, val), - "PCH HDMI (0x%08x) enabled on transcoder %c, should be disabled\n", - i915_mmio_reg_offset(reg), pipe_name(pipe)); + I915_STATE_WARN(state && port_pipe == pipe, + "PCH HDMI %c enabled on transcoder %c, should be disabled\n", + port_name(port), pipe_name(pipe)); - I915_STATE_WARN(HAS_PCH_IBX(dev_priv) && (val & SDVO_ENABLE) == 0 - && (val & SDVO_PIPE_B_SELECT), - "IBX PCH hdmi port still using transcoder B\n"); + I915_STATE_WARN(HAS_PCH_IBX(dev_priv) && !state && port_pipe == PIPE_B, + "IBX PCH HDMI %c still using transcoder B\n", + port_name(port)); } static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv, enum pipe pipe) { - u32 val; + enum pipe port_pipe; - assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_B, TRANS_DP_PORT_SEL_B); - assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_C, TRANS_DP_PORT_SEL_C); - assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_D, TRANS_DP_PORT_SEL_D); + assert_pch_dp_disabled(dev_priv, pipe, PORT_B, PCH_DP_B); + assert_pch_dp_disabled(dev_priv, pipe, PORT_C, PCH_DP_C); + assert_pch_dp_disabled(dev_priv, pipe, PORT_D, PCH_DP_D); - val = I915_READ(PCH_ADPA); - I915_STATE_WARN(adpa_pipe_enabled(dev_priv, pipe, val), - "PCH VGA enabled on transcoder %c, should be disabled\n", - pipe_name(pipe)); + I915_STATE_WARN(intel_crt_port_enabled(dev_priv, PCH_ADPA, &port_pipe) && + port_pipe == pipe, + "PCH VGA enabled on transcoder %c, should be disabled\n", + pipe_name(pipe)); - val = I915_READ(PCH_LVDS); - I915_STATE_WARN(lvds_pipe_enabled(dev_priv, pipe, val), - "PCH LVDS enabled on transcoder %c, should be disabled\n", - pipe_name(pipe)); + I915_STATE_WARN(intel_lvds_port_enabled(dev_priv, PCH_LVDS, &port_pipe) && + port_pipe == pipe, + "PCH LVDS enabled on transcoder %c, should be disabled\n", + pipe_name(pipe)); - assert_pch_hdmi_disabled(dev_priv, pipe, PCH_HDMIB); - assert_pch_hdmi_disabled(dev_priv, pipe, PCH_HDMIC); - assert_pch_hdmi_disabled(dev_priv, pipe, PCH_HDMID); + assert_pch_hdmi_disabled(dev_priv, pipe, PORT_B, PCH_HDMIB); + assert_pch_hdmi_disabled(dev_priv, pipe, PORT_C, PCH_HDMIC); + assert_pch_hdmi_disabled(dev_priv, pipe, PORT_D, PCH_HDMID); } static void _vlv_enable_pll(struct intel_crtc *crtc, @@ -2521,6 +2480,7 @@ intel_fill_fb_info(struct drm_i915_private *dev_priv, { struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); struct intel_rotation_info *rot_info = &intel_fb->rot_info; + struct drm_i915_gem_object *obj = intel_fb_obj(fb); u32 gtt_offset_rotated = 0; unsigned int max_size = 0; int i, num_planes = fb->format->num_planes; @@ -2585,7 +2545,7 @@ intel_fill_fb_info(struct drm_i915_private *dev_priv, * fb layout agrees with the fence layout. We already check that the * fb stride matches the fence stride elsewhere. */ - if (i == 0 && i915_gem_object_is_tiled(intel_fb->obj) && + if (i == 0 && i915_gem_object_is_tiled(obj) && (x + width) * cpp > fb->pitches[i]) { DRM_DEBUG_KMS("bad fb plane %d offset: 0x%x\n", i, fb->offsets[i]); @@ -2670,9 +2630,9 @@ intel_fill_fb_info(struct drm_i915_private *dev_priv, max_size = max(max_size, offset + size); } - if (max_size * tile_size > intel_fb->obj->base.size) { + if (max_size * tile_size > obj->base.size) { DRM_DEBUG_KMS("fb too big for bo (need %u bytes, have %zu bytes)\n", - max_size * tile_size, intel_fb->obj->base.size); + max_size * tile_size, obj->base.size); return -EINVAL; } @@ -3430,24 +3390,33 @@ static void i9xx_disable_plane(struct intel_plane *plane, spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } -static bool i9xx_plane_get_hw_state(struct intel_plane *plane) +static bool i9xx_plane_get_hw_state(struct intel_plane *plane, + enum pipe *pipe) { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum intel_display_power_domain power_domain; enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; - enum pipe pipe = plane->pipe; bool ret; + u32 val; /* * Not 100% correct for planes that can move between pipes, * but that's only the case for gen2-4 which don't have any * display power wells. */ - power_domain = POWER_DOMAIN_PIPE(pipe); + power_domain = POWER_DOMAIN_PIPE(plane->pipe); if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) return false; - ret = I915_READ(DSPCNTR(i9xx_plane)) & DISPLAY_PLANE_ENABLE; + val = I915_READ(DSPCNTR(i9xx_plane)); + + ret = val & DISPLAY_PLANE_ENABLE; + + if (INTEL_GEN(dev_priv) >= 5) + *pipe = plane->pipe; + else + *pipe = (val & DISPPLANE_SEL_PIPE_MASK) >> + DISPPLANE_SEL_PIPE_SHIFT; intel_display_power_put(dev_priv, power_domain); @@ -4631,20 +4600,33 @@ static void ivybridge_update_fdi_bc_bifurcation(struct intel_crtc *intel_crtc) } } -/* Return which DP Port should be selected for Transcoder DP control */ -static enum port -intel_trans_dp_port_sel(struct intel_crtc *crtc) +/* + * Finds the encoder associated with the given CRTC. This can only be + * used when we know that the CRTC isn't feeding multiple encoders! + */ +static struct intel_encoder * +intel_get_crtc_new_encoder(const struct intel_atomic_state *state, + const struct intel_crtc_state *crtc_state) { - struct drm_device *dev = crtc->base.dev; - struct intel_encoder *encoder; + struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + const struct drm_connector_state *connector_state; + const struct drm_connector *connector; + struct intel_encoder *encoder = NULL; + int num_encoders = 0; + int i; + + for_each_new_connector_in_state(&state->base, connector, connector_state, i) { + if (connector_state->crtc != &crtc->base) + continue; - for_each_encoder_on_crtc(dev, &crtc->base, encoder) { - if (encoder->type == INTEL_OUTPUT_DP || - encoder->type == INTEL_OUTPUT_EDP) - return encoder->port; + encoder = to_intel_encoder(connector_state->best_encoder); + num_encoders++; } - return -1; + WARN(num_encoders != 1, "%d encoders for pipe %c\n", + num_encoders, pipe_name(crtc->pipe)); + + return encoder; } /* @@ -4655,7 +4637,8 @@ intel_trans_dp_port_sel(struct intel_crtc *crtc) * - DP transcoding bits * - transcoder */ -static void ironlake_pch_enable(const struct intel_crtc_state *crtc_state) +static void ironlake_pch_enable(const struct intel_atomic_state *state, + const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); struct drm_device *dev = crtc->base.dev; @@ -4714,6 +4697,8 @@ static void ironlake_pch_enable(const struct intel_crtc_state *crtc_state) &crtc_state->base.adjusted_mode; u32 bpc = (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) >> 5; i915_reg_t reg = TRANS_DP_CTL(pipe); + enum port port; + temp = I915_READ(reg); temp &= ~(TRANS_DP_PORT_SEL_MASK | TRANS_DP_SYNC_MASK | @@ -4726,19 +4711,9 @@ static void ironlake_pch_enable(const struct intel_crtc_state *crtc_state) if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) temp |= TRANS_DP_VSYNC_ACTIVE_HIGH; - switch (intel_trans_dp_port_sel(crtc)) { - case PORT_B: - temp |= TRANS_DP_PORT_SEL_B; - break; - case PORT_C: - temp |= TRANS_DP_PORT_SEL_C; - break; - case PORT_D: - temp |= TRANS_DP_PORT_SEL_D; - break; - default: - BUG(); - } + port = intel_get_crtc_new_encoder(state, crtc_state)->port; + WARN_ON(port < PORT_B || port > PORT_D); + temp |= TRANS_DP_PORT_SEL(port); I915_WRITE(reg, temp); } @@ -4746,7 +4721,8 @@ static void ironlake_pch_enable(const struct intel_crtc_state *crtc_state) ironlake_enable_pch_transcoder(dev_priv, pipe); } -static void lpt_pch_enable(const struct intel_crtc_state *crtc_state) +static void lpt_pch_enable(const struct intel_atomic_state *state, + const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); @@ -4776,6 +4752,39 @@ static void cpt_verify_modeset(struct drm_device *dev, int pipe) } } +/* + * The hardware phase 0.0 refers to the center of the pixel. + * We want to start from the top/left edge which is phase + * -0.5. That matches how the hardware calculates the scaling + * factors (from top-left of the first pixel to bottom-right + * of the last pixel, as opposed to the pixel centers). + * + * For 4:2:0 subsampled chroma planes we obviously have to + * adjust that so that the chroma sample position lands in + * the right spot. + * + * Note that for packed YCbCr 4:2:2 formats there is no way to + * control chroma siting. The hardware simply replicates the + * chroma samples for both of the luma samples, and thus we don't + * actually get the expected MPEG2 chroma siting convention :( + * The same behaviour is observed on pre-SKL platforms as well. + */ +u16 skl_scaler_calc_phase(int sub, bool chroma_cosited) +{ + int phase = -0x8000; + u16 trip = 0; + + if (chroma_cosited) + phase += (sub - 1) * 0x8000 / sub; + + if (phase < 0) + phase = 0x10000 + phase; + else + trip = PS_PHASE_TRIP; + + return ((phase >> 2) & PS_PHASE_MASK) | trip; +} + static int skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, unsigned int scaler_user, int *scaler_id, @@ -4975,14 +4984,22 @@ static void skylake_pfit_enable(struct intel_crtc *crtc) &crtc->config->scaler_state; if (crtc->config->pch_pfit.enabled) { + u16 uv_rgb_hphase, uv_rgb_vphase; int id; if (WARN_ON(crtc->config->scaler_state.scaler_id < 0)) return; + uv_rgb_hphase = skl_scaler_calc_phase(1, false); + uv_rgb_vphase = skl_scaler_calc_phase(1, false); + id = scaler_state->scaler_id; I915_WRITE(SKL_PS_CTRL(pipe, id), PS_SCALER_EN | PS_FILTER_MEDIUM | scaler_state->scalers[id].mode); + I915_WRITE_FW(SKL_PS_VPHASE(pipe, id), + PS_Y_PHASE(0) | PS_UV_RGB_PHASE(uv_rgb_vphase)); + I915_WRITE_FW(SKL_PS_HPHASE(pipe, id), + PS_Y_PHASE(0) | PS_UV_RGB_PHASE(uv_rgb_hphase)); I915_WRITE(SKL_PS_WIN_POS(pipe, id), crtc->config->pch_pfit.pos); I915_WRITE(SKL_PS_WIN_SZ(pipe, id), crtc->config->pch_pfit.size); } @@ -5501,10 +5518,8 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config, * * Spurious PCH underruns also occur during PCH enabling. */ - if (intel_crtc->config->has_pch_encoder || IS_GEN5(dev_priv)) - intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); - if (intel_crtc->config->has_pch_encoder) - intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, false); + intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); + intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, false); if (intel_crtc->config->has_pch_encoder) intel_prepare_shared_dpll(intel_crtc); @@ -5549,7 +5564,7 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config, intel_enable_pipe(pipe_config); if (intel_crtc->config->has_pch_encoder) - ironlake_pch_enable(pipe_config); + ironlake_pch_enable(old_intel_state, pipe_config); assert_vblank_disabled(crtc); drm_crtc_vblank_on(crtc); @@ -5559,9 +5574,16 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config, if (HAS_PCH_CPT(dev_priv)) cpt_verify_modeset(dev, intel_crtc->pipe); - /* Must wait for vblank to avoid spurious PCH FIFO underruns */ - if (intel_crtc->config->has_pch_encoder) + /* + * Must wait for vblank to avoid spurious PCH FIFO underruns. + * And a second vblank wait is needed at least on ILK with + * some interlaced HDMI modes. Let's do the double wait always + * in case there are more corner cases we don't know about. + */ + if (intel_crtc->config->has_pch_encoder) { + intel_wait_for_vblank(dev_priv, pipe); intel_wait_for_vblank(dev_priv, pipe); + } intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, true); } @@ -5623,6 +5645,11 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, if (INTEL_GEN(dev_priv) >= 11) icl_map_plls_to_ports(crtc, pipe_config, old_state); + intel_encoders_pre_enable(crtc, pipe_config, old_state); + + if (!transcoder_is_dsi(cpu_transcoder)) + intel_ddi_enable_pipe_clock(pipe_config); + if (intel_crtc_has_dp_encoder(intel_crtc->config)) intel_dp_set_m_n(intel_crtc, M1_N1); @@ -5651,11 +5678,6 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, intel_crtc->active = true; - intel_encoders_pre_enable(crtc, pipe_config, old_state); - - if (!transcoder_is_dsi(cpu_transcoder)) - intel_ddi_enable_pipe_clock(pipe_config); - /* Display WA #1180: WaDisableScalarClockGating: glk, cnl */ psl_clkgate_wa = (IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) && intel_crtc->config->pch_pfit.enabled; @@ -5688,7 +5710,7 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, intel_enable_pipe(pipe_config); if (intel_crtc->config->has_pch_encoder) - lpt_pch_enable(pipe_config); + lpt_pch_enable(old_intel_state, pipe_config); if (intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DP_MST)) intel_ddi_set_vc_payload_alloc(pipe_config, true); @@ -5741,10 +5763,8 @@ static void ironlake_crtc_disable(struct intel_crtc_state *old_crtc_state, * pipe is already disabled, but FDI RX/TX is still enabled. * Happens at least with VGA+HDMI cloning. Suppress them. */ - if (intel_crtc->config->has_pch_encoder) { - intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); - intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, false); - } + intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); + intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, false); intel_encoders_disable(crtc, old_crtc_state, old_state); @@ -5849,6 +5869,22 @@ static void i9xx_pfit_enable(struct intel_crtc *crtc) I915_WRITE(BCLRPAT(crtc->pipe), 0); } +bool intel_port_is_tc(struct drm_i915_private *dev_priv, enum port port) +{ + if (IS_ICELAKE(dev_priv)) + return port >= PORT_C && port <= PORT_F; + + return false; +} + +enum tc_port intel_port_to_tc(struct drm_i915_private *dev_priv, enum port port) +{ + if (!intel_port_is_tc(dev_priv, port)) + return PORT_TC_NONE; + + return port - PORT_C; +} + enum intel_display_power_domain intel_port_to_power_domain(enum port port) { switch (port) { @@ -7675,16 +7711,18 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc, struct drm_i915_private *dev_priv = to_i915(dev); struct intel_plane *plane = to_intel_plane(crtc->base.primary); enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; - enum pipe pipe = crtc->pipe; + enum pipe pipe; u32 val, base, offset; int fourcc, pixel_format; unsigned int aligned_height; struct drm_framebuffer *fb; struct intel_framebuffer *intel_fb; - if (!plane->get_hw_state(plane)) + if (!plane->get_hw_state(plane, &pipe)) return; + WARN_ON(pipe != crtc->pipe); + intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL); if (!intel_fb) { DRM_DEBUG_KMS("failed to alloc fb\n"); @@ -8705,16 +8743,18 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc, struct drm_i915_private *dev_priv = to_i915(dev); struct intel_plane *plane = to_intel_plane(crtc->base.primary); enum plane_id plane_id = plane->id; - enum pipe pipe = crtc->pipe; + enum pipe pipe; u32 val, base, offset, stride_mult, tiling, alpha; int fourcc, pixel_format; unsigned int aligned_height; struct drm_framebuffer *fb; struct intel_framebuffer *intel_fb; - if (!plane->get_hw_state(plane)) + if (!plane->get_hw_state(plane, &pipe)) return; + WARN_ON(pipe != crtc->pipe); + intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL); if (!intel_fb) { DRM_DEBUG_KMS("failed to alloc fb\n"); @@ -9142,9 +9182,12 @@ void hsw_disable_pc8(struct drm_i915_private *dev_priv) static int haswell_crtc_compute_clock(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state) { + struct intel_atomic_state *state = + to_intel_atomic_state(crtc_state->base.state); + if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI)) { struct intel_encoder *encoder = - intel_ddi_get_crtc_new_encoder(crtc_state); + intel_get_crtc_new_encoder(state, crtc_state); if (!intel_get_shared_dpll(crtc, crtc_state, encoder)) { DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n", @@ -9692,7 +9735,8 @@ static void i845_disable_cursor(struct intel_plane *plane, i845_update_cursor(plane, NULL, NULL); } -static bool i845_cursor_get_hw_state(struct intel_plane *plane) +static bool i845_cursor_get_hw_state(struct intel_plane *plane, + enum pipe *pipe) { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum intel_display_power_domain power_domain; @@ -9704,6 +9748,8 @@ static bool i845_cursor_get_hw_state(struct intel_plane *plane) ret = I915_READ(CURCNTR(PIPE_A)) & CURSOR_ENABLE; + *pipe = PIPE_A; + intel_display_power_put(dev_priv, power_domain); return ret; @@ -9715,25 +9761,30 @@ static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state, struct drm_i915_private *dev_priv = to_i915(plane_state->base.plane->dev); struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); - u32 cntl; + u32 cntl = 0; - cntl = MCURSOR_GAMMA_ENABLE; + if (IS_GEN6(dev_priv) || IS_IVYBRIDGE(dev_priv)) + cntl |= MCURSOR_TRICKLE_FEED_DISABLE; - if (HAS_DDI(dev_priv)) - cntl |= CURSOR_PIPE_CSC_ENABLE; + if (INTEL_GEN(dev_priv) <= 10) { + cntl |= MCURSOR_GAMMA_ENABLE; + + if (HAS_DDI(dev_priv)) + cntl |= MCURSOR_PIPE_CSC_ENABLE; + } if (INTEL_GEN(dev_priv) < 5 && !IS_G4X(dev_priv)) cntl |= MCURSOR_PIPE_SELECT(crtc->pipe); switch (plane_state->base.crtc_w) { case 64: - cntl |= CURSOR_MODE_64_ARGB_AX; + cntl |= MCURSOR_MODE_64_ARGB_AX; break; case 128: - cntl |= CURSOR_MODE_128_ARGB_AX; + cntl |= MCURSOR_MODE_128_ARGB_AX; break; case 256: - cntl |= CURSOR_MODE_256_ARGB_AX; + cntl |= MCURSOR_MODE_256_ARGB_AX; break; default: MISSING_CASE(plane_state->base.crtc_w); @@ -9741,7 +9792,7 @@ static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state, } if (plane_state->base.rotation & DRM_MODE_ROTATE_180) - cntl |= CURSOR_ROTATE_180; + cntl |= MCURSOR_ROTATE_180; return cntl; } @@ -9903,23 +9954,32 @@ static void i9xx_disable_cursor(struct intel_plane *plane, i9xx_update_cursor(plane, NULL, NULL); } -static bool i9xx_cursor_get_hw_state(struct intel_plane *plane) +static bool i9xx_cursor_get_hw_state(struct intel_plane *plane, + enum pipe *pipe) { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum intel_display_power_domain power_domain; - enum pipe pipe = plane->pipe; bool ret; + u32 val; /* * Not 100% correct for planes that can move between pipes, * but that's only the case for gen2-3 which don't have any * display power wells. */ - power_domain = POWER_DOMAIN_PIPE(pipe); + power_domain = POWER_DOMAIN_PIPE(plane->pipe); if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) return false; - ret = I915_READ(CURCNTR(pipe)) & CURSOR_MODE; + val = I915_READ(CURCNTR(plane->pipe)); + + ret = val & MCURSOR_MODE; + + if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) + *pipe = plane->pipe; + else + *pipe = (val & MCURSOR_PIPE_SELECT_MASK) >> + MCURSOR_PIPE_SELECT_SHIFT; intel_display_power_put(dev_priv, power_domain); @@ -14124,14 +14184,15 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv) static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb) { struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); + struct drm_i915_gem_object *obj = intel_fb_obj(fb); drm_framebuffer_cleanup(fb); - i915_gem_object_lock(intel_fb->obj); - WARN_ON(!intel_fb->obj->framebuffer_references--); - i915_gem_object_unlock(intel_fb->obj); + i915_gem_object_lock(obj); + WARN_ON(!obj->framebuffer_references--); + i915_gem_object_unlock(obj); - i915_gem_object_put(intel_fb->obj); + i915_gem_object_put(obj); kfree(intel_fb); } @@ -14140,8 +14201,7 @@ static int intel_user_framebuffer_create_handle(struct drm_framebuffer *fb, struct drm_file *file, unsigned int *handle) { - struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); - struct drm_i915_gem_object *obj = intel_fb->obj; + struct drm_i915_gem_object *obj = intel_fb_obj(fb); if (obj->userptr.mm) { DRM_DEBUG("attempting to use a userptr for a framebuffer, denied\n"); @@ -14411,9 +14471,9 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb, i, fb->pitches[i], stride_alignment); goto err; } - } - intel_fb->obj = obj; + fb->obj[i] = &obj->base; + } ret = intel_fill_fb_info(dev_priv, fb); if (ret) @@ -15095,8 +15155,8 @@ void i830_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe) WARN_ON(I915_READ(DSPCNTR(PLANE_A)) & DISPLAY_PLANE_ENABLE); WARN_ON(I915_READ(DSPCNTR(PLANE_B)) & DISPLAY_PLANE_ENABLE); WARN_ON(I915_READ(DSPCNTR(PLANE_C)) & DISPLAY_PLANE_ENABLE); - WARN_ON(I915_READ(CURCNTR(PIPE_A)) & CURSOR_MODE); - WARN_ON(I915_READ(CURCNTR(PIPE_B)) & CURSOR_MODE); + WARN_ON(I915_READ(CURCNTR(PIPE_A)) & MCURSOR_MODE); + WARN_ON(I915_READ(CURCNTR(PIPE_B)) & MCURSOR_MODE); I915_WRITE(PIPECONF(pipe), 0); POSTING_READ(PIPECONF(pipe)); @@ -15110,12 +15170,12 @@ void i830_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe) static bool intel_plane_mapping_ok(struct intel_crtc *crtc, struct intel_plane *plane) { - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; - u32 val = I915_READ(DSPCNTR(i9xx_plane)); + enum pipe pipe; - return (val & DISPLAY_PLANE_ENABLE) == 0 || - (val & DISPPLANE_SEL_PIPE_MASK) == DISPPLANE_SEL_PIPE(crtc->pipe); + if (!plane->get_hw_state(plane, &pipe)) + return true; + + return pipe == crtc->pipe; } static void @@ -15274,6 +15334,9 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder) connector->base.dpms = DRM_MODE_DPMS_OFF; connector->base.encoder = NULL; } + + /* notify opregion of the sanitized encoder state */ + intel_opregion_notify_encoder(encoder, connector && has_active_crtc); } void i915_redisable_vga_power_on(struct drm_i915_private *dev_priv) @@ -15314,7 +15377,10 @@ static void readout_plane_state(struct intel_crtc *crtc) for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane) { struct intel_plane_state *plane_state = to_intel_plane_state(plane->base.state); - bool visible = plane->get_hw_state(plane); + enum pipe pipe; + bool visible; + + visible = plane->get_hw_state(plane, &pipe); intel_set_plane_visible(crtc_state, plane_state, visible); } |