diff options
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_display.c')
-rw-r--r-- | drivers/gpu/drm/i915/display/intel_display.c | 979 |
1 files changed, 369 insertions, 610 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 7f512f9e9e5c..80b19c304c43 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -74,6 +74,7 @@ #include "g4x_dp.h" #include "g4x_hdmi.h" +#include "hsw_ips.h" #include "i915_drv.h" #include "icl_dsi.h" #include "intel_acpi.h" @@ -112,9 +113,10 @@ #include "i9xx_plane.h" #include "skl_scaler.h" #include "skl_universal_plane.h" +#include "vlv_dsi.h" #include "vlv_dsi_pll.h" +#include "vlv_dsi_regs.h" #include "vlv_sideband.h" -#include "vlv_dsi.h" static void intel_set_transcoder_timings(const struct intel_crtc_state *crtc_state); static void intel_set_pipe_src_size(const struct intel_crtc_state *crtc_state); @@ -337,10 +339,38 @@ is_trans_port_sync_mode(const struct intel_crtc_state *crtc_state) is_trans_port_sync_slave(crtc_state); } -static struct intel_crtc *intel_master_crtc(const struct intel_crtc_state *crtc_state) +static enum pipe bigjoiner_master_pipe(const struct intel_crtc_state *crtc_state) +{ + return ffs(crtc_state->bigjoiner_pipes) - 1; +} + +u8 intel_crtc_bigjoiner_slave_pipes(const struct intel_crtc_state *crtc_state) +{ + return crtc_state->bigjoiner_pipes & ~BIT(bigjoiner_master_pipe(crtc_state)); +} + +bool intel_crtc_is_bigjoiner_slave(const struct intel_crtc_state *crtc_state) { - if (crtc_state->bigjoiner_slave) - return crtc_state->bigjoiner_linked_crtc; + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + + return crtc_state->bigjoiner_pipes && + crtc->pipe != bigjoiner_master_pipe(crtc_state); +} + +bool intel_crtc_is_bigjoiner_master(const struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + + return crtc_state->bigjoiner_pipes && + crtc->pipe == bigjoiner_master_pipe(crtc_state); +} + +struct intel_crtc *intel_master_crtc(const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + + if (intel_crtc_is_bigjoiner_slave(crtc_state)) + return intel_crtc_for_pipe(i915, bigjoiner_master_pipe(crtc_state)); else return to_intel_crtc(crtc_state->uapi.crtc); } @@ -752,8 +782,11 @@ void intel_plane_disable_noatomic(struct intel_crtc *crtc, crtc_state->data_rate[plane->id] = 0; crtc_state->min_cdclk[plane->id] = 0; - if (plane->id == PLANE_PRIMARY) - hsw_disable_ips(crtc_state); + if ((crtc_state->active_planes & ~BIT(PLANE_CURSOR)) == 0 && + hsw_ips_disable(crtc_state)) { + crtc_state->ips_enabled = false; + intel_crtc_wait_for_next_vblank(crtc); + } /* * Vblank time updates from the shadow to live plane control register @@ -1090,72 +1123,6 @@ static void ilk_pfit_enable(const struct intel_crtc_state *crtc_state) intel_de_write(dev_priv, PF_WIN_SZ(pipe), width << 16 | height); } -void hsw_enable_ips(const struct intel_crtc_state *crtc_state) -{ - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); - - if (!crtc_state->ips_enabled) - return; - - /* - * We can only enable IPS after we enable a plane and wait for a vblank - * This function is called from post_plane_update, which is run after - * a vblank wait. - */ - drm_WARN_ON(dev, !(crtc_state->active_planes & ~BIT(PLANE_CURSOR))); - - if (IS_BROADWELL(dev_priv)) { - drm_WARN_ON(dev, snb_pcode_write(dev_priv, DISPLAY_IPS_CONTROL, - IPS_ENABLE | IPS_PCODE_CONTROL)); - /* Quoting Art Runyan: "its not safe to expect any particular - * value in IPS_CTL bit 31 after enabling IPS through the - * mailbox." Moreover, the mailbox may return a bogus state, - * so we need to just enable it and continue on. - */ - } else { - intel_de_write(dev_priv, IPS_CTL, IPS_ENABLE); - /* The bit only becomes 1 in the next vblank, so this wait here - * is essentially intel_wait_for_vblank. If we don't have this - * and don't wait for vblanks until the end of crtc_enable, then - * the HW state readout code will complain that the expected - * IPS_CTL value is not the one we read. */ - if (intel_de_wait_for_set(dev_priv, IPS_CTL, IPS_ENABLE, 50)) - drm_err(&dev_priv->drm, - "Timed out waiting for IPS enable\n"); - } -} - -void hsw_disable_ips(const struct intel_crtc_state *crtc_state) -{ - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); - - if (!crtc_state->ips_enabled) - return; - - if (IS_BROADWELL(dev_priv)) { - drm_WARN_ON(dev, - snb_pcode_write(dev_priv, DISPLAY_IPS_CONTROL, 0)); - /* - * Wait for PCODE to finish disabling IPS. The BSpec specified - * 42ms timeout value leads to occasional timeouts so use 100ms - * instead. - */ - if (intel_de_wait_for_clear(dev_priv, IPS_CTL, IPS_ENABLE, 100)) - drm_err(&dev_priv->drm, - "Timed out waiting for IPS disable\n"); - } else { - intel_de_write(dev_priv, IPS_CTL, 0); - intel_de_posting_read(dev_priv, IPS_CTL); - } - - /* We need to wait for a vblank before we can disable the plane. */ - intel_crtc_wait_for_next_vblank(crtc); -} - static void intel_crtc_dpms_overlay_disable(struct intel_crtc *crtc) { if (crtc->overlay) @@ -1166,67 +1133,6 @@ static void intel_crtc_dpms_overlay_disable(struct intel_crtc *crtc) */ } -static bool hsw_pre_update_disable_ips(const struct intel_crtc_state *old_crtc_state, - const struct intel_crtc_state *new_crtc_state) -{ - struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - - if (!old_crtc_state->ips_enabled) - return false; - - if (intel_crtc_needs_modeset(new_crtc_state)) - return true; - - /* - * 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. - * - * Disable IPS before we program the LUT. - */ - if (IS_HASWELL(dev_priv) && - (new_crtc_state->uapi.color_mgmt_changed || - new_crtc_state->update_pipe) && - new_crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT) - return true; - - return !new_crtc_state->ips_enabled; -} - -static bool hsw_post_update_enable_ips(const struct intel_crtc_state *old_crtc_state, - const struct intel_crtc_state *new_crtc_state) -{ - struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - - if (!new_crtc_state->ips_enabled) - return false; - - if (intel_crtc_needs_modeset(new_crtc_state)) - return true; - - /* - * 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. - * - * Re-enable IPS after the LUT has been programmed. - */ - if (IS_HASWELL(dev_priv) && - (new_crtc_state->uapi.color_mgmt_changed || - new_crtc_state->update_pipe) && - new_crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT) - return true; - - /* - * We can't read out IPS on broadwell, assume the worst and - * forcibly enable IPS on the first fastset. - */ - if (new_crtc_state->update_pipe && old_crtc_state->inherited) - return true; - - return !old_crtc_state->ips_enabled; -} - static bool needs_nv12_wa(const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); @@ -1321,9 +1227,7 @@ static void intel_post_plane_update(struct intel_atomic_state *state, if (new_crtc_state->update_wm_post && new_crtc_state->hw.active) intel_update_watermarks(dev_priv); - if (hsw_post_update_enable_ips(old_crtc_state, new_crtc_state)) - hsw_enable_ips(new_crtc_state); - + hsw_ips_post_update(state, crtc); intel_fbc_post_update(state, crtc); intel_drrs_page_flip(state, crtc); @@ -1426,8 +1330,8 @@ static void intel_pre_plane_update(struct intel_atomic_state *state, intel_psr_pre_plane_update(state, crtc); - if (hsw_pre_update_disable_ips(old_crtc_state, new_crtc_state)) - hsw_disable_ips(old_crtc_state); + if (hsw_ips_pre_update(state, crtc)) + intel_crtc_wait_for_next_vblank(crtc); if (intel_fbc_pre_update(state, crtc)) intel_crtc_wait_for_next_vblank(crtc); @@ -1905,12 +1809,6 @@ static void ilk_crtc_enable(struct intel_atomic_state *state, intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, true); } -/* IPS only exists on ULT machines and is tied to pipe A. */ -static bool hsw_crtc_supports_ips(struct intel_crtc *crtc) -{ - return HAS_IPS(to_i915(crtc->base.dev)) && crtc->pipe == PIPE_A; -} - static void glk_pipe_scaler_clock_gating_wa(struct drm_i915_private *dev_priv, enum pipe pipe, bool apply) { @@ -1974,34 +1872,18 @@ static void hsw_set_frame_start_delay(const struct intel_crtc_state *crtc_state) static void icl_ddi_bigjoiner_pre_enable(struct intel_atomic_state *state, const struct intel_crtc_state *crtc_state) { - struct intel_crtc_state *master_crtc_state; - struct intel_crtc *master_crtc; - struct drm_connector_state *conn_state; - struct drm_connector *conn; - struct intel_encoder *encoder = NULL; - int i; - - master_crtc = intel_master_crtc(crtc_state); - master_crtc_state = intel_atomic_get_new_crtc_state(state, master_crtc); - - for_each_new_connector_in_state(&state->base, conn, conn_state, i) { - if (conn_state->crtc != &master_crtc->base) - continue; - - encoder = to_intel_encoder(conn_state->best_encoder); - break; - } + struct intel_crtc *master_crtc = intel_master_crtc(crtc_state); /* * Enable sequence steps 1-7 on bigjoiner master */ - if (crtc_state->bigjoiner_slave) + if (intel_crtc_is_bigjoiner_slave(crtc_state)) intel_encoders_pre_pll_enable(state, master_crtc); if (crtc_state->shared_dpll) intel_enable_shared_dpll(crtc_state); - if (crtc_state->bigjoiner_slave) + if (intel_crtc_is_bigjoiner_slave(crtc_state)) intel_encoders_pre_enable(state, master_crtc); } @@ -2065,7 +1947,8 @@ static void hsw_crtc_enable(struct intel_atomic_state *state, if (DISPLAY_VER(dev_priv) >= 9 || IS_BROADWELL(dev_priv)) bdw_set_pipemisc(new_crtc_state); - if (!new_crtc_state->bigjoiner_slave && !transcoder_is_dsi(cpu_transcoder)) + if (!intel_crtc_is_bigjoiner_slave(new_crtc_state) && + !transcoder_is_dsi(cpu_transcoder)) hsw_configure_cpu_transcoder(new_crtc_state); crtc->active = true; @@ -2105,7 +1988,7 @@ static void hsw_crtc_enable(struct intel_atomic_state *state, icl_pipe_mbus_enable(crtc, dbuf_state->joined_mbus); } - if (new_crtc_state->bigjoiner_slave) + if (intel_crtc_is_bigjoiner_slave(new_crtc_state)) intel_crtc_vblank_on(new_crtc_state); intel_encoders_enable(state, crtc); @@ -2190,7 +2073,7 @@ static void hsw_crtc_disable(struct intel_atomic_state *state, * FIXME collapse everything to one hook. * Need care with mst->ddi interactions. */ - if (!old_crtc_state->bigjoiner_slave) { + if (!intel_crtc_is_bigjoiner_slave(old_crtc_state)) { intel_encoders_disable(state, crtc); intel_encoders_post_disable(state, crtc); } @@ -2778,77 +2661,6 @@ static void intel_connector_verify_state(struct intel_crtc_state *crtc_state, } } -bool hsw_crtc_state_ips_capable(const struct intel_crtc_state *crtc_state) -{ - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - - /* IPS only exists on ULT machines and is tied to pipe A. */ - if (!hsw_crtc_supports_ips(crtc)) - return false; - - if (!dev_priv->params.enable_ips) - return false; - - if (crtc_state->pipe_bpp > 24) - return false; - - /* - * We compare against max which means we must take - * the increased cdclk requirement into account when - * calculating the new cdclk. - * - * Should measure whether using a lower cdclk w/o IPS - */ - if (IS_BROADWELL(dev_priv) && - crtc_state->pixel_rate > dev_priv->max_cdclk_freq * 95 / 100) - return false; - - return true; -} - -static int hsw_compute_ips_config(struct intel_crtc_state *crtc_state) -{ - struct drm_i915_private *dev_priv = - to_i915(crtc_state->uapi.crtc->dev); - struct intel_atomic_state *state = - to_intel_atomic_state(crtc_state->uapi.state); - - crtc_state->ips_enabled = false; - - if (!hsw_crtc_state_ips_capable(crtc_state)) - return 0; - - /* - * When IPS gets enabled, the pipe CRC changes. Since IPS gets - * enabled and disabled dynamically based on package C states, - * user space can't make reliable use of the CRCs, so let's just - * completely disable it. - */ - if (crtc_state->crc_enabled) - return 0; - - /* IPS should be fine as long as at least one plane is enabled. */ - if (!(crtc_state->active_planes & ~BIT(PLANE_CURSOR))) - return 0; - - if (IS_BROADWELL(dev_priv)) { - const struct intel_cdclk_state *cdclk_state; - - cdclk_state = intel_atomic_get_cdclk_state(state); - if (IS_ERR(cdclk_state)) - return PTR_ERR(cdclk_state); - - /* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */ - if (crtc_state->pixel_rate > cdclk_state->logical.cdclk * 95 / 100) - return 0; - } - - crtc_state->ips_enabled = true; - - return 0; -} - static bool intel_crtc_supports_double_wide(const struct intel_crtc *crtc) { const struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); @@ -3347,13 +3159,11 @@ static void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - u32 pipeconf; - - pipeconf = 0; + u32 pipeconf = 0; /* we keep both pipes enabled on 830 */ if (IS_I830(dev_priv)) - pipeconf |= intel_de_read(dev_priv, PIPECONF(crtc->pipe)) & PIPECONF_ENABLE; + pipeconf |= PIPECONF_ENABLE; if (crtc_state->double_wide) pipeconf |= PIPECONF_DOUBLE_WIDE; @@ -4069,19 +3879,20 @@ static bool transcoder_ddi_func_is_enabled(struct drm_i915_private *dev_priv, return tmp & TRANS_DDI_FUNC_ENABLE; } -static u8 enabled_bigjoiner_pipes(struct drm_i915_private *dev_priv) +static void enabled_bigjoiner_pipes(struct drm_i915_private *dev_priv, + u8 *master_pipes, u8 *slave_pipes) { - u8 master_pipes = 0, slave_pipes = 0; struct intel_crtc *crtc; - for_each_intel_crtc(&dev_priv->drm, crtc) { + *master_pipes = 0; + *slave_pipes = 0; + + for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, crtc, + bigjoiner_pipes(dev_priv)) { enum intel_display_power_domain power_domain; enum pipe pipe = crtc->pipe; intel_wakeref_t wakeref; - if ((bigjoiner_pipes(dev_priv) & BIT(pipe)) == 0) - continue; - power_domain = intel_dsc_power_domain(crtc, (enum transcoder) pipe); with_intel_display_power_if_enabled(dev_priv, power_domain, wakeref) { u32 tmp = intel_de_read(dev_priv, ICL_PIPE_DSS_CTL1(pipe)); @@ -4090,9 +3901,9 @@ static u8 enabled_bigjoiner_pipes(struct drm_i915_private *dev_priv) continue; if (tmp & MASTER_BIG_JOINER_ENABLE) - master_pipes |= BIT(pipe); + *master_pipes |= BIT(pipe); else - slave_pipes |= BIT(pipe); + *slave_pipes |= BIT(pipe); } if (DISPLAY_VER(dev_priv) < 13) @@ -4103,18 +3914,47 @@ static u8 enabled_bigjoiner_pipes(struct drm_i915_private *dev_priv) u32 tmp = intel_de_read(dev_priv, ICL_PIPE_DSS_CTL1(pipe)); if (tmp & UNCOMPRESSED_JOINER_MASTER) - master_pipes |= BIT(pipe); + *master_pipes |= BIT(pipe); if (tmp & UNCOMPRESSED_JOINER_SLAVE) - slave_pipes |= BIT(pipe); + *slave_pipes |= BIT(pipe); } } /* Bigjoiner pipes should always be consecutive master and slave */ - drm_WARN(&dev_priv->drm, slave_pipes != master_pipes << 1, + drm_WARN(&dev_priv->drm, *slave_pipes != *master_pipes << 1, "Bigjoiner misconfigured (master pipes 0x%x, slave pipes 0x%x)\n", - master_pipes, slave_pipes); + *master_pipes, *slave_pipes); +} - return slave_pipes; +static enum pipe get_bigjoiner_master_pipe(enum pipe pipe, u8 master_pipes, u8 slave_pipes) +{ + if ((slave_pipes & BIT(pipe)) == 0) + return pipe; + + /* ignore everything above our pipe */ + master_pipes &= ~GENMASK(7, pipe); + + /* highest remaining bit should be our master pipe */ + return fls(master_pipes) - 1; +} + +static u8 get_bigjoiner_slave_pipes(enum pipe pipe, u8 master_pipes, u8 slave_pipes) +{ + enum pipe master_pipe, next_master_pipe; + + master_pipe = get_bigjoiner_master_pipe(pipe, master_pipes, slave_pipes); + + if ((master_pipes & BIT(master_pipe)) == 0) + return 0; + + /* ignore our master pipe and everything below it */ + master_pipes &= ~GENMASK(master_pipe, 0); + /* make sure a high bit is set for the ffs() */ + master_pipes |= BIT(7); + /* lowest remaining bit should be the next master pipe */ + next_master_pipe = ffs(master_pipes) - 1; + + return slave_pipes & GENMASK(next_master_pipe - 1, master_pipe); } static u8 hsw_panel_transcoders(struct drm_i915_private *i915) @@ -4133,6 +3973,7 @@ static u8 hsw_enabled_transcoders(struct intel_crtc *crtc) struct drm_i915_private *dev_priv = to_i915(dev); u8 panel_transcoder_mask = hsw_panel_transcoders(dev_priv); enum transcoder cpu_transcoder; + u8 master_pipes, slave_pipes; u8 enabled_transcoders = 0; /* @@ -4184,8 +4025,10 @@ static u8 hsw_enabled_transcoders(struct intel_crtc *crtc) enabled_transcoders |= BIT(cpu_transcoder); /* bigjoiner slave -> consider the master pipe's transcoder as well */ - if (enabled_bigjoiner_pipes(dev_priv) & BIT(crtc->pipe)) { - cpu_transcoder = (enum transcoder) crtc->pipe - 1; + enabled_bigjoiner_pipes(dev_priv, &master_pipes, &slave_pipes); + if (slave_pipes & BIT(crtc->pipe)) { + cpu_transcoder = (enum transcoder) + get_bigjoiner_master_pipe(crtc->pipe, master_pipes, slave_pipes); if (transcoder_ddi_func_is_enabled(dev_priv, cpu_transcoder)) enabled_transcoders |= BIT(cpu_transcoder); } @@ -4310,6 +4153,24 @@ static bool bxt_get_dsi_transcoder_state(struct intel_crtc *crtc, return transcoder_is_dsi(pipe_config->cpu_transcoder); } +static void intel_bigjoiner_get_config(struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + u8 master_pipes, slave_pipes; + enum pipe pipe = crtc->pipe; + + enabled_bigjoiner_pipes(i915, &master_pipes, &slave_pipes); + + if (((master_pipes | slave_pipes) & BIT(pipe)) == 0) + return; + + crtc_state->bigjoiner = true; + crtc_state->bigjoiner_pipes = + BIT(get_bigjoiner_master_pipe(pipe, master_pipes, slave_pipes)) | + get_bigjoiner_slave_pipes(pipe, master_pipes, slave_pipes); +} + static bool hsw_get_pipe_config(struct intel_crtc *crtc, struct intel_crtc_state *pipe_config) { @@ -4336,8 +4197,7 @@ static bool hsw_get_pipe_config(struct intel_crtc *crtc, goto out; intel_dsc_get_config(pipe_config); - if (DISPLAY_VER(dev_priv) >= 13 && !pipe_config->dsc.compression_enable) - intel_uncompressed_joiner_get_config(pipe_config); + intel_bigjoiner_get_config(pipe_config); if (!transcoder_is_dsi(pipe_config->cpu_transcoder) || DISPLAY_VER(dev_priv) >= 11) @@ -4395,19 +4255,7 @@ static bool hsw_get_pipe_config(struct intel_crtc *crtc, ilk_get_pfit_config(pipe_config); } - if (hsw_crtc_supports_ips(crtc)) { - if (IS_HASWELL(dev_priv)) - pipe_config->ips_enabled = intel_de_read(dev_priv, - IPS_CTL) & IPS_ENABLE; - else { - /* - * We cannot readout IPS state on broadwell, set to - * true so we can set it to a defined state on first - * commit. - */ - pipe_config->ips_enabled = true; - } - } + hsw_ips_get_config(pipe_config); if (pipe_config->cpu_transcoder != TRANSCODER_EDP && !transcoder_is_dsi(pipe_config->cpu_transcoder)) { @@ -4819,194 +4667,6 @@ intel_encoder_current_mode(struct intel_encoder *encoder) return mode; } -/** - * intel_wm_need_update - Check whether watermarks need updating - * @cur: current plane state - * @new: new plane state - * - * Check current plane state versus the new one to determine whether - * watermarks need to be recalculated. - * - * Returns true or false. - */ -static bool intel_wm_need_update(const struct intel_plane_state *cur, - struct intel_plane_state *new) -{ - /* Update watermarks on tiling or size changes. */ - if (new->uapi.visible != cur->uapi.visible) - return true; - - if (!cur->hw.fb || !new->hw.fb) - return false; - - if (cur->hw.fb->modifier != new->hw.fb->modifier || - cur->hw.rotation != new->hw.rotation || - drm_rect_width(&new->uapi.src) != drm_rect_width(&cur->uapi.src) || - drm_rect_height(&new->uapi.src) != drm_rect_height(&cur->uapi.src) || - drm_rect_width(&new->uapi.dst) != drm_rect_width(&cur->uapi.dst) || - drm_rect_height(&new->uapi.dst) != drm_rect_height(&cur->uapi.dst)) - return true; - - return false; -} - -static bool needs_scaling(const struct intel_plane_state *state) -{ - int src_w = drm_rect_width(&state->uapi.src) >> 16; - int src_h = drm_rect_height(&state->uapi.src) >> 16; - int dst_w = drm_rect_width(&state->uapi.dst); - int dst_h = drm_rect_height(&state->uapi.dst); - - return (src_w != dst_w || src_h != dst_h); -} - -static bool intel_plane_do_async_flip(struct intel_plane *plane, - const struct intel_crtc_state *old_crtc_state, - const struct intel_crtc_state *new_crtc_state) -{ - struct drm_i915_private *i915 = to_i915(plane->base.dev); - - if (!plane->async_flip) - return false; - - if (!new_crtc_state->uapi.async_flip) - return false; - - /* - * In platforms after DISPLAY13, we might need to override - * first async flip in order to change watermark levels - * as part of optimization. - * So for those, we are checking if this is a first async flip. - * For platforms earlier than DISPLAY13 we always do async flip. - */ - return DISPLAY_VER(i915) < 13 || old_crtc_state->uapi.async_flip; -} - -int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_crtc_state, - struct intel_crtc_state *new_crtc_state, - const struct intel_plane_state *old_plane_state, - struct intel_plane_state *new_plane_state) -{ - struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); - struct intel_plane *plane = to_intel_plane(new_plane_state->uapi.plane); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - bool mode_changed = intel_crtc_needs_modeset(new_crtc_state); - bool was_crtc_enabled = old_crtc_state->hw.active; - bool is_crtc_enabled = new_crtc_state->hw.active; - bool turn_off, turn_on, visible, was_visible; - int ret; - - if (DISPLAY_VER(dev_priv) >= 9 && plane->id != PLANE_CURSOR) { - ret = skl_update_scaler_plane(new_crtc_state, new_plane_state); - if (ret) - return ret; - } - - was_visible = old_plane_state->uapi.visible; - visible = new_plane_state->uapi.visible; - - if (!was_crtc_enabled && drm_WARN_ON(&dev_priv->drm, was_visible)) - was_visible = false; - - /* - * Visibility is calculated as if the crtc was on, but - * after scaler setup everything depends on it being off - * when the crtc isn't active. - * - * FIXME this is wrong for watermarks. Watermarks should also - * be computed as if the pipe would be active. Perhaps move - * per-plane wm computation to the .check_plane() hook, and - * only combine the results from all planes in the current place? - */ - if (!is_crtc_enabled) { - intel_plane_set_invisible(new_crtc_state, new_plane_state); - visible = false; - } - - if (!was_visible && !visible) - return 0; - - turn_off = was_visible && (!visible || mode_changed); - turn_on = visible && (!was_visible || mode_changed); - - drm_dbg_atomic(&dev_priv->drm, - "[CRTC:%d:%s] with [PLANE:%d:%s] visible %i -> %i, off %i, on %i, ms %i\n", - crtc->base.base.id, crtc->base.name, - plane->base.base.id, plane->base.name, - was_visible, visible, - turn_off, turn_on, mode_changed); - - if (turn_on) { - if (DISPLAY_VER(dev_priv) < 5 && !IS_G4X(dev_priv)) - new_crtc_state->update_wm_pre = true; - - /* must disable cxsr around plane enable/disable */ - if (plane->id != PLANE_CURSOR) - new_crtc_state->disable_cxsr = true; - } else if (turn_off) { - if (DISPLAY_VER(dev_priv) < 5 && !IS_G4X(dev_priv)) - new_crtc_state->update_wm_post = true; - - /* must disable cxsr around plane enable/disable */ - if (plane->id != PLANE_CURSOR) - new_crtc_state->disable_cxsr = true; - } else if (intel_wm_need_update(old_plane_state, new_plane_state)) { - if (DISPLAY_VER(dev_priv) < 5 && !IS_G4X(dev_priv)) { - /* FIXME bollocks */ - new_crtc_state->update_wm_pre = true; - new_crtc_state->update_wm_post = true; - } - } - - if (visible || was_visible) - new_crtc_state->fb_bits |= plane->frontbuffer_bit; - - /* - * ILK/SNB DVSACNTR/Sprite Enable - * IVB SPR_CTL/Sprite Enable - * "When in Self Refresh Big FIFO mode, a write to enable the - * plane will be internally buffered and delayed while Big FIFO - * mode is exiting." - * - * Which means that enabling the sprite can take an extra frame - * when we start in big FIFO mode (LP1+). Thus we need to drop - * down to LP0 and wait for vblank in order to make sure the - * sprite gets enabled on the next vblank after the register write. - * Doing otherwise would risk enabling the sprite one frame after - * we've already signalled flip completion. We can resume LP1+ - * once the sprite has been enabled. - * - * - * WaCxSRDisabledForSpriteScaling:ivb - * IVB SPR_SCALE/Scaling Enable - * "Low Power watermarks must be disabled for at least one - * frame before enabling sprite scaling, and kept disabled - * until sprite scaling is disabled." - * - * ILK/SNB DVSASCALE/Scaling Enable - * "When in Self Refresh Big FIFO mode, scaling enable will be - * masked off while Big FIFO mode is exiting." - * - * Despite the w/a only being listed for IVB we assume that - * the ILK/SNB note has similar ramifications, hence we apply - * the w/a on all three platforms. - * - * With experimental results seems this is needed also for primary - * plane, not only sprite plane. - */ - if (plane->id != PLANE_CURSOR && - (IS_IRONLAKE(dev_priv) || IS_SANDYBRIDGE(dev_priv) || - IS_IVYBRIDGE(dev_priv)) && - (turn_on || (!needs_scaling(old_plane_state) && - needs_scaling(new_plane_state)))) - new_crtc_state->disable_lp_wm = true; - - if (intel_plane_do_async_flip(plane, old_crtc_state, new_crtc_state)) - new_plane_state->do_async_flip = true; - - return 0; -} - static bool encoders_cloneable(const struct intel_encoder *a, const struct intel_encoder *b) { @@ -5266,7 +4926,7 @@ static int intel_crtc_atomic_check(struct intel_atomic_state *state, if (mode_changed && crtc_state->hw.enable && !drm_WARN_ON(&dev_priv->drm, crtc_state->shared_dpll)) { - ret = dev_priv->dpll_funcs->crtc_compute_clock(crtc_state); + ret = intel_dpll_crtc_compute_clock(crtc_state); if (ret) return ret; } @@ -5317,7 +4977,7 @@ static int intel_crtc_atomic_check(struct intel_atomic_state *state, } if (HAS_IPS(dev_priv)) { - ret = hsw_compute_ips_config(crtc_state); + ret = hsw_ips_compute_config(state, crtc); if (ret) return ret; } @@ -5619,9 +5279,10 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config, transcoder_name(pipe_config->master_transcoder), pipe_config->sync_mode_slaves_mask); - drm_dbg_kms(&dev_priv->drm, "bigjoiner: %s\n", - pipe_config->bigjoiner_slave ? "slave" : - pipe_config->bigjoiner ? "master" : "no"); + drm_dbg_kms(&dev_priv->drm, "bigjoiner: %s, pipes: 0x%x\n", + intel_crtc_is_bigjoiner_slave(pipe_config) ? "slave" : + intel_crtc_is_bigjoiner_master(pipe_config) ? "master" : "no", + pipe_config->bigjoiner_pipes); drm_dbg_kms(&dev_priv->drm, "splitter: %s, link count %d, overlap %d\n", enableddisabled(pipe_config->splitter.enable), @@ -5818,35 +5479,42 @@ static bool check_digital_port_conflicts(struct intel_atomic_state *state) static void intel_crtc_copy_uapi_to_hw_state_nomodeset(struct intel_atomic_state *state, - struct intel_crtc_state *crtc_state) + struct intel_crtc *crtc) { - const struct intel_crtc_state *master_crtc_state; - struct intel_crtc *master_crtc; + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); - master_crtc = intel_master_crtc(crtc_state); - master_crtc_state = intel_atomic_get_new_crtc_state(state, master_crtc); + WARN_ON(intel_crtc_is_bigjoiner_slave(crtc_state)); - /* No need to copy state if the master state is unchanged */ - if (master_crtc_state) - intel_crtc_copy_color_blobs(crtc_state, master_crtc_state); + drm_property_replace_blob(&crtc_state->hw.degamma_lut, + crtc_state->uapi.degamma_lut); + drm_property_replace_blob(&crtc_state->hw.gamma_lut, + crtc_state->uapi.gamma_lut); + drm_property_replace_blob(&crtc_state->hw.ctm, + crtc_state->uapi.ctm); } static void -intel_crtc_copy_uapi_to_hw_state(struct intel_atomic_state *state, - struct intel_crtc_state *crtc_state) +intel_crtc_copy_uapi_to_hw_state_modeset(struct intel_atomic_state *state, + struct intel_crtc *crtc) { + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); + + WARN_ON(intel_crtc_is_bigjoiner_slave(crtc_state)); + crtc_state->hw.enable = crtc_state->uapi.enable; crtc_state->hw.active = crtc_state->uapi.active; crtc_state->hw.mode = crtc_state->uapi.mode; crtc_state->hw.adjusted_mode = crtc_state->uapi.adjusted_mode; crtc_state->hw.scaling_filter = crtc_state->uapi.scaling_filter; - intel_crtc_copy_uapi_to_hw_state_nomodeset(state, crtc_state); + intel_crtc_copy_uapi_to_hw_state_nomodeset(state, crtc); } static void intel_crtc_copy_hw_to_uapi_state(struct intel_crtc_state *crtc_state) { - if (crtc_state->bigjoiner_slave) + if (intel_crtc_is_bigjoiner_slave(crtc_state)) return; crtc_state->uapi.enable = crtc_state->hw.enable; @@ -5857,7 +5525,6 @@ static void intel_crtc_copy_hw_to_uapi_state(struct intel_crtc_state *crtc_state crtc_state->uapi.adjusted_mode = crtc_state->hw.adjusted_mode; crtc_state->uapi.scaling_filter = crtc_state->hw.scaling_filter; - /* copy color blobs to uapi */ drm_property_replace_blob(&crtc_state->uapi.degamma_lut, crtc_state->hw.degamma_lut); drm_property_replace_blob(&crtc_state->uapi.gamma_lut, @@ -5866,51 +5533,79 @@ static void intel_crtc_copy_hw_to_uapi_state(struct intel_crtc_state *crtc_state crtc_state->hw.ctm); } +static void +copy_bigjoiner_crtc_state_nomodeset(struct intel_atomic_state *state, + struct intel_crtc *slave_crtc) +{ + struct intel_crtc_state *slave_crtc_state = + intel_atomic_get_new_crtc_state(state, slave_crtc); + struct intel_crtc *master_crtc = intel_master_crtc(slave_crtc_state); + const struct intel_crtc_state *master_crtc_state = + intel_atomic_get_new_crtc_state(state, master_crtc); + + drm_property_replace_blob(&slave_crtc_state->hw.degamma_lut, + master_crtc_state->hw.degamma_lut); + drm_property_replace_blob(&slave_crtc_state->hw.gamma_lut, + master_crtc_state->hw.gamma_lut); + drm_property_replace_blob(&slave_crtc_state->hw.ctm, + master_crtc_state->hw.ctm); + + slave_crtc_state->uapi.color_mgmt_changed = master_crtc_state->uapi.color_mgmt_changed; +} + static int -copy_bigjoiner_crtc_state(struct intel_crtc_state *crtc_state, - const struct intel_crtc_state *from_crtc_state) +copy_bigjoiner_crtc_state_modeset(struct intel_atomic_state *state, + struct intel_crtc *slave_crtc) { + struct intel_crtc_state *slave_crtc_state = + intel_atomic_get_new_crtc_state(state, slave_crtc); + struct intel_crtc *master_crtc = intel_master_crtc(slave_crtc_state); + const struct intel_crtc_state *master_crtc_state = + intel_atomic_get_new_crtc_state(state, master_crtc); struct intel_crtc_state *saved_state; - saved_state = kmemdup(from_crtc_state, sizeof(*saved_state), GFP_KERNEL); + saved_state = kmemdup(master_crtc_state, sizeof(*saved_state), GFP_KERNEL); if (!saved_state) return -ENOMEM; - saved_state->uapi = crtc_state->uapi; - saved_state->scaler_state = crtc_state->scaler_state; - saved_state->shared_dpll = crtc_state->shared_dpll; - saved_state->dpll_hw_state = crtc_state->dpll_hw_state; - saved_state->crc_enabled = crtc_state->crc_enabled; + /* preserve some things from the slave's original crtc state */ + saved_state->uapi = slave_crtc_state->uapi; + saved_state->scaler_state = slave_crtc_state->scaler_state; + saved_state->shared_dpll = slave_crtc_state->shared_dpll; + saved_state->dpll_hw_state = slave_crtc_state->dpll_hw_state; + saved_state->crc_enabled = slave_crtc_state->crc_enabled; - intel_crtc_free_hw_state(crtc_state); - memcpy(crtc_state, saved_state, sizeof(*crtc_state)); + intel_crtc_free_hw_state(slave_crtc_state); + memcpy(slave_crtc_state, saved_state, sizeof(*slave_crtc_state)); kfree(saved_state); /* Re-init hw state */ - memset(&crtc_state->hw, 0, sizeof(saved_state->hw)); - crtc_state->hw.enable = from_crtc_state->hw.enable; - crtc_state->hw.active = from_crtc_state->hw.active; - crtc_state->hw.pipe_mode = from_crtc_state->hw.pipe_mode; - crtc_state->hw.adjusted_mode = from_crtc_state->hw.adjusted_mode; + memset(&slave_crtc_state->hw, 0, sizeof(slave_crtc_state->hw)); + slave_crtc_state->hw.enable = master_crtc_state->hw.enable; + slave_crtc_state->hw.active = master_crtc_state->hw.active; + slave_crtc_state->hw.mode = master_crtc_state->hw.mode; + slave_crtc_state->hw.pipe_mode = master_crtc_state->hw.pipe_mode; + slave_crtc_state->hw.adjusted_mode = master_crtc_state->hw.adjusted_mode; + slave_crtc_state->hw.scaling_filter = master_crtc_state->hw.scaling_filter; + + copy_bigjoiner_crtc_state_nomodeset(state, slave_crtc); /* Some fixups */ - crtc_state->uapi.mode_changed = from_crtc_state->uapi.mode_changed; - crtc_state->uapi.connectors_changed = from_crtc_state->uapi.connectors_changed; - crtc_state->uapi.active_changed = from_crtc_state->uapi.active_changed; - crtc_state->nv12_planes = crtc_state->c8_planes = crtc_state->update_planes = 0; - crtc_state->bigjoiner_linked_crtc = to_intel_crtc(from_crtc_state->uapi.crtc); - crtc_state->bigjoiner_slave = true; - crtc_state->cpu_transcoder = from_crtc_state->cpu_transcoder; - crtc_state->has_audio = from_crtc_state->has_audio; + slave_crtc_state->uapi.mode_changed = master_crtc_state->uapi.mode_changed; + slave_crtc_state->uapi.connectors_changed = master_crtc_state->uapi.connectors_changed; + slave_crtc_state->uapi.active_changed = master_crtc_state->uapi.active_changed; + slave_crtc_state->cpu_transcoder = master_crtc_state->cpu_transcoder; + slave_crtc_state->has_audio = master_crtc_state->has_audio; return 0; } static int intel_crtc_prepare_cleared_state(struct intel_atomic_state *state, - struct intel_crtc_state *crtc_state) + struct intel_crtc *crtc) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct intel_crtc_state *saved_state; @@ -5940,7 +5635,7 @@ intel_crtc_prepare_cleared_state(struct intel_atomic_state *state, memcpy(crtc_state, saved_state, sizeof(*crtc_state)); kfree(saved_state); - intel_crtc_copy_uapi_to_hw_state(state, crtc_state); + intel_crtc_copy_uapi_to_hw_state_modeset(state, crtc); return 0; } @@ -6618,6 +6313,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr1); PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr2); PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr0); + PIPE_CONF_CHECK_X(dpll_hw_state.div0); PIPE_CONF_CHECK_X(dpll_hw_state.ebb0); PIPE_CONF_CHECK_X(dpll_hw_state.ebb4); PIPE_CONF_CHECK_X(dpll_hw_state.pll0); @@ -6669,8 +6365,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_X(sync_mode_slaves_mask); PIPE_CONF_CHECK_I(master_transcoder); PIPE_CONF_CHECK_BOOL(bigjoiner); - PIPE_CONF_CHECK_BOOL(bigjoiner_slave); - PIPE_CONF_CHECK_P(bigjoiner_linked_crtc); + PIPE_CONF_CHECK_X(bigjoiner_pipes); PIPE_CONF_CHECK_I(dsc.compression_enable); PIPE_CONF_CHECK_I(dsc.dsc_split); @@ -7456,20 +7151,25 @@ static int intel_crtc_add_bigjoiner_planes(struct intel_atomic_state *state, static int intel_bigjoiner_add_affected_planes(struct intel_atomic_state *state) { + struct drm_i915_private *i915 = to_i915(state->base.dev); const struct intel_crtc_state *crtc_state; struct intel_crtc *crtc; int i; for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { - int ret; + struct intel_crtc *other; - if (!crtc_state->bigjoiner) - continue; + for_each_intel_crtc_in_pipe_mask(&i915->drm, other, + crtc_state->bigjoiner_pipes) { + int ret; - ret = intel_crtc_add_bigjoiner_planes(state, crtc, - crtc_state->bigjoiner_linked_crtc); - if (ret) - return ret; + if (crtc == other) + continue; + + ret = intel_crtc_add_bigjoiner_planes(state, crtc, other); + if (ret) + return ret; + } } return 0; @@ -7571,71 +7271,123 @@ static bool intel_cpu_transcoders_need_modeset(struct intel_atomic_state *state, return false; } +static bool intel_pipes_need_modeset(struct intel_atomic_state *state, + u8 pipes) +{ + const struct intel_crtc_state *new_crtc_state; + struct intel_crtc *crtc; + int i; + + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { + if (new_crtc_state->hw.enable && + pipes & BIT(crtc->pipe) && + intel_crtc_needs_modeset(new_crtc_state)) + return true; + } + + return false; +} + static int intel_atomic_check_bigjoiner(struct intel_atomic_state *state, - struct intel_crtc *crtc, - struct intel_crtc_state *old_crtc_state, - struct intel_crtc_state *new_crtc_state) + struct intel_crtc *master_crtc) { struct drm_i915_private *i915 = to_i915(state->base.dev); - struct intel_crtc_state *slave_crtc_state, *master_crtc_state; - struct intel_crtc *slave_crtc, *master_crtc; + struct intel_crtc_state *master_crtc_state = + intel_atomic_get_new_crtc_state(state, master_crtc); + struct intel_crtc *slave_crtc; + u8 slave_pipes; - /* slave being enabled, is master is still claiming this crtc? */ - if (old_crtc_state->bigjoiner_slave) { - slave_crtc = crtc; - master_crtc = old_crtc_state->bigjoiner_linked_crtc; - master_crtc_state = intel_atomic_get_new_crtc_state(state, master_crtc); - if (!master_crtc_state || !intel_crtc_needs_modeset(master_crtc_state)) - goto claimed; - } + /* + * TODO: encoder.compute_config() may be the best + * place to populate the bitmask for the master crtc. + * For now encoder.compute_config() just flags things + * as needing bigjoiner and we populate the bitmask + * here. + */ + WARN_ON(master_crtc_state->bigjoiner_pipes); - if (!new_crtc_state->bigjoiner) + if (!master_crtc_state->bigjoiner) return 0; - slave_crtc = intel_dsc_get_bigjoiner_secondary(crtc); - if (!slave_crtc) { + slave_pipes = BIT(master_crtc->pipe + 1); + + if (slave_pipes & ~bigjoiner_pipes(i915)) { drm_dbg_kms(&i915->drm, - "[CRTC:%d:%s] Big joiner configuration requires " - "CRTC + 1 to be used, doesn't exist\n", - crtc->base.base.id, crtc->base.name); + "[CRTC:%d:%s] Cannot act as big joiner master " + "(need 0x%x as slave pipes, only 0x%x possible)\n", + master_crtc->base.base.id, master_crtc->base.name, + slave_pipes, bigjoiner_pipes(i915)); return -EINVAL; } - new_crtc_state->bigjoiner_linked_crtc = slave_crtc; - slave_crtc_state = intel_atomic_get_crtc_state(&state->base, slave_crtc); - master_crtc = crtc; - if (IS_ERR(slave_crtc_state)) - return PTR_ERR(slave_crtc_state); + for_each_intel_crtc_in_pipe_mask(&i915->drm, slave_crtc, slave_pipes) { + struct intel_crtc_state *slave_crtc_state; + int ret; - /* master being enabled, slave was already configured? */ - if (slave_crtc_state->uapi.enable) - goto claimed; + slave_crtc_state = intel_atomic_get_crtc_state(&state->base, slave_crtc); + if (IS_ERR(slave_crtc_state)) + return PTR_ERR(slave_crtc_state); - drm_dbg_kms(&i915->drm, - "[CRTC:%d:%s] Used as slave for big joiner\n", - slave_crtc->base.base.id, slave_crtc->base.name); + /* master being enabled, slave was already configured? */ + if (slave_crtc_state->uapi.enable) { + drm_dbg_kms(&i915->drm, + "[CRTC:%d:%s] Slave is enabled as normal CRTC, but " + "[CRTC:%d:%s] claiming this CRTC for bigjoiner.\n", + slave_crtc->base.base.id, slave_crtc->base.name, + master_crtc->base.base.id, master_crtc->base.name); + return -EINVAL; + } - return copy_bigjoiner_crtc_state(slave_crtc_state, new_crtc_state); + /* + * The state copy logic assumes the master crtc gets processed + * before the slave crtc during the main compute_config loop. + * This works because the crtcs are created in pipe order, + * and the hardware requires master pipe < slave pipe as well. + * Should that change we need to rethink the logic. + */ + if (WARN_ON(drm_crtc_index(&master_crtc->base) > + drm_crtc_index(&slave_crtc->base))) + return -EINVAL; -claimed: - drm_dbg_kms(&i915->drm, - "[CRTC:%d:%s] Slave is enabled as normal CRTC, but " - "[CRTC:%d:%s] claiming this CRTC for bigjoiner.\n", - slave_crtc->base.base.id, slave_crtc->base.name, - master_crtc->base.base.id, master_crtc->base.name); - return -EINVAL; + drm_dbg_kms(&i915->drm, + "[CRTC:%d:%s] Used as slave for big joiner master [CRTC:%d:%s]\n", + slave_crtc->base.base.id, slave_crtc->base.name, + master_crtc->base.base.id, master_crtc->base.name); + + master_crtc_state->bigjoiner_pipes = + BIT(master_crtc->pipe) | BIT(slave_crtc->pipe); + slave_crtc_state->bigjoiner_pipes = + BIT(master_crtc->pipe) | BIT(slave_crtc->pipe); + + ret = copy_bigjoiner_crtc_state_modeset(state, slave_crtc); + if (ret) + return ret; + } + + return 0; } static void kill_bigjoiner_slave(struct intel_atomic_state *state, - struct intel_crtc_state *master_crtc_state) + struct intel_crtc *master_crtc) { - struct intel_crtc_state *slave_crtc_state = - intel_atomic_get_new_crtc_state(state, master_crtc_state->bigjoiner_linked_crtc); + struct drm_i915_private *i915 = to_i915(state->base.dev); + struct intel_crtc_state *master_crtc_state = + intel_atomic_get_new_crtc_state(state, master_crtc); + struct intel_crtc *slave_crtc; + + for_each_intel_crtc_in_pipe_mask(&i915->drm, slave_crtc, + intel_crtc_bigjoiner_slave_pipes(master_crtc_state)) { + struct intel_crtc_state *slave_crtc_state = + intel_atomic_get_new_crtc_state(state, slave_crtc); - slave_crtc_state->bigjoiner = master_crtc_state->bigjoiner = false; - slave_crtc_state->bigjoiner_slave = master_crtc_state->bigjoiner_slave = false; - slave_crtc_state->bigjoiner_linked_crtc = master_crtc_state->bigjoiner_linked_crtc = NULL; - intel_crtc_copy_uapi_to_hw_state(state, slave_crtc_state); + slave_crtc_state->bigjoiner = false; + slave_crtc_state->bigjoiner_pipes = 0; + + intel_crtc_copy_uapi_to_hw_state_modeset(state, slave_crtc); + } + + master_crtc_state->bigjoiner = false; + master_crtc_state->bigjoiner_pipes = 0; } /** @@ -7785,34 +7537,37 @@ static int intel_atomic_check_async(struct intel_atomic_state *state, struct int static int intel_bigjoiner_add_affected_crtcs(struct intel_atomic_state *state) { + struct drm_i915_private *i915 = to_i915(state->base.dev); struct intel_crtc_state *crtc_state; struct intel_crtc *crtc; + u8 affected_pipes = 0; + u8 modeset_pipes = 0; int i; for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { - struct intel_crtc_state *linked_crtc_state; - struct intel_crtc *linked_crtc; - int ret; + affected_pipes |= crtc_state->bigjoiner_pipes; + if (intel_crtc_needs_modeset(crtc_state)) + modeset_pipes |= crtc_state->bigjoiner_pipes; + } - if (!crtc_state->bigjoiner) - continue; + for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, affected_pipes) { + crtc_state = intel_atomic_get_crtc_state(&state->base, crtc); + if (IS_ERR(crtc_state)) + return PTR_ERR(crtc_state); + } - linked_crtc = crtc_state->bigjoiner_linked_crtc; - linked_crtc_state = intel_atomic_get_crtc_state(&state->base, linked_crtc); - if (IS_ERR(linked_crtc_state)) - return PTR_ERR(linked_crtc_state); + for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, modeset_pipes) { + int ret; - if (!intel_crtc_needs_modeset(crtc_state)) - continue; + crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - linked_crtc_state->uapi.mode_changed = true; + crtc_state->uapi.mode_changed = true; - ret = drm_atomic_add_affected_connectors(&state->base, - &linked_crtc->base); + ret = drm_atomic_add_affected_connectors(&state->base, &crtc->base); if (ret) return ret; - ret = intel_atomic_add_affected_planes(state, linked_crtc); + ret = intel_atomic_add_affected_planes(state, crtc); if (ret) return ret; } @@ -7820,8 +7575,8 @@ static int intel_bigjoiner_add_affected_crtcs(struct intel_atomic_state *state) for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { /* Kill old bigjoiner link, we may re-establish afterwards */ if (intel_crtc_needs_modeset(crtc_state) && - crtc_state->bigjoiner && !crtc_state->bigjoiner_slave) - kill_bigjoiner_slave(state, crtc_state); + intel_crtc_is_bigjoiner_master(crtc_state)) + kill_bigjoiner_slave(state, crtc); } return 0; @@ -7846,6 +7601,10 @@ static int intel_atomic_check(struct drm_device *dev, new_crtc_state, i) { if (new_crtc_state->inherited != old_crtc_state->inherited) new_crtc_state->uapi.mode_changed = true; + + if (new_crtc_state->uapi.scaling_filter != + old_crtc_state->uapi.scaling_filter) + new_crtc_state->uapi.mode_changed = true; } intel_vrr_check_modeset(state); @@ -7861,30 +7620,30 @@ static int intel_atomic_check(struct drm_device *dev, for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { if (!intel_crtc_needs_modeset(new_crtc_state)) { - /* Light copy */ - intel_crtc_copy_uapi_to_hw_state_nomodeset(state, new_crtc_state); - + if (intel_crtc_is_bigjoiner_slave(new_crtc_state)) + copy_bigjoiner_crtc_state_nomodeset(state, crtc); + else + intel_crtc_copy_uapi_to_hw_state_nomodeset(state, crtc); continue; } - if (!new_crtc_state->uapi.enable) { - if (!new_crtc_state->bigjoiner_slave) { - intel_crtc_copy_uapi_to_hw_state(state, new_crtc_state); - any_ms = true; - } + if (intel_crtc_is_bigjoiner_slave(new_crtc_state)) { + drm_WARN_ON(&dev_priv->drm, new_crtc_state->uapi.enable); continue; } - ret = intel_crtc_prepare_cleared_state(state, new_crtc_state); + ret = intel_crtc_prepare_cleared_state(state, crtc); if (ret) goto fail; + if (!new_crtc_state->hw.enable) + continue; + ret = intel_modeset_pipe_config(state, new_crtc_state); if (ret) goto fail; - ret = intel_atomic_check_bigjoiner(state, crtc, old_crtc_state, - new_crtc_state); + ret = intel_atomic_check_bigjoiner(state, crtc); if (ret) goto fail; } @@ -7938,10 +7697,7 @@ static int intel_atomic_check(struct drm_device *dev, } if (new_crtc_state->bigjoiner) { - struct intel_crtc_state *linked_crtc_state = - intel_atomic_get_new_crtc_state(state, new_crtc_state->bigjoiner_linked_crtc); - - if (intel_crtc_needs_modeset(linked_crtc_state)) { + if (intel_pipes_need_modeset(state, new_crtc_state->bigjoiner_pipes)) { new_crtc_state->uapi.mode_changed = true; new_crtc_state->update_pipe = false; } @@ -8121,9 +7877,6 @@ static void intel_pipe_fastset(const struct intel_crtc_state *old_crtc_state, if (DISPLAY_VER(dev_priv) >= 9 || IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) hsw_set_linetime_wm(new_crtc_state); - - if (DISPLAY_VER(dev_priv) >= 11) - icl_set_pipe_chicken(new_crtc_state); } static void commit_pipe_pre_planes(struct intel_atomic_state *state, @@ -8188,7 +7941,7 @@ static void intel_enable_crtc(struct intel_atomic_state *state, dev_priv->display->crtc_enable(state, crtc); - if (new_crtc_state->bigjoiner_slave) + if (intel_crtc_is_bigjoiner_slave(new_crtc_state)) return; /* vblanks work again, re-enable pipe CRC. */ @@ -8198,7 +7951,7 @@ static void intel_enable_crtc(struct intel_atomic_state *state, static void intel_update_crtc(struct intel_atomic_state *state, struct intel_crtc *crtc) { - struct drm_i915_private *dev_priv = to_i915(state->base.dev); + struct drm_i915_private *i915 = to_i915(state->base.dev); const struct intel_crtc_state *old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc); struct intel_crtc_state *new_crtc_state = @@ -8215,21 +7968,22 @@ static void intel_update_crtc(struct intel_atomic_state *state, if (new_crtc_state->update_pipe) intel_encoders_update_pipe(state, crtc); + + if (DISPLAY_VER(i915) >= 11 && + new_crtc_state->update_pipe) + icl_set_pipe_chicken(new_crtc_state); } intel_fbc_update(state, crtc); - intel_update_planes_on_crtc(state, crtc); + intel_crtc_planes_update_noarm(state, crtc); /* Perform vblank evasion around commit operation */ intel_pipe_update_start(new_crtc_state); commit_pipe_pre_planes(state, crtc); - if (DISPLAY_VER(dev_priv) >= 9) - skl_arm_planes_on_crtc(state, crtc); - else - i9xx_arm_planes_on_crtc(state, crtc); + intel_crtc_planes_update_arm(state, crtc); commit_pipe_post_planes(state, crtc); @@ -8305,7 +8059,7 @@ static void intel_commit_modeset_disables(struct intel_atomic_state *state) */ if (!is_trans_port_sync_slave(old_crtc_state) && !intel_dp_mst_is_slave_trans(old_crtc_state) && - !old_crtc_state->bigjoiner_slave) + !intel_crtc_is_bigjoiner_slave(old_crtc_state)) continue; intel_old_crtc_state_disables(state, old_crtc_state, @@ -8420,7 +8174,7 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) if (intel_dp_mst_is_slave_trans(new_crtc_state) || is_trans_port_sync_master(new_crtc_state) || - (new_crtc_state->bigjoiner && !new_crtc_state->bigjoiner_slave)) + intel_crtc_is_bigjoiner_master(new_crtc_state)) continue; modeset_pipes &= ~BIT(pipe); @@ -8947,10 +8701,8 @@ static u32 intel_encoder_possible_crtcs(struct intel_encoder *encoder) struct intel_crtc *crtc; u32 possible_crtcs = 0; - for_each_intel_crtc(dev, crtc) { - if (encoder->pipe_mask & BIT(crtc->pipe)) - possible_crtcs |= drm_crtc_mask(&crtc->base); - } + for_each_intel_crtc_in_pipe_mask(dev, crtc, encoder->pipe_mask) + possible_crtcs |= drm_crtc_mask(&crtc->base); return possible_crtcs; } @@ -9006,6 +8758,7 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv) intel_ddi_init(dev_priv, PORT_B); intel_ddi_init(dev_priv, PORT_C); intel_ddi_init(dev_priv, PORT_D_XELPD); + intel_ddi_init(dev_priv, PORT_TC1); } else if (IS_ALDERLAKE_P(dev_priv)) { intel_ddi_init(dev_priv, PORT_A); intel_ddi_init(dev_priv, PORT_B); @@ -10132,7 +9885,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc, /* Adjust the state of the output pipe according to whether we * have active connectors/encoders. */ if (crtc_state->hw.active && !intel_crtc_has_encoders(crtc) && - !crtc_state->bigjoiner_slave) + !intel_crtc_is_bigjoiner_slave(crtc_state)) intel_crtc_disable_noatomic(crtc, ctx); if (crtc_state->hw.active || HAS_GMCH(dev_priv)) { @@ -10345,12 +10098,18 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) /* read out to slave crtc as well for bigjoiner */ if (crtc_state->bigjoiner) { + struct intel_crtc *slave_crtc; + /* encoder should read be linked to bigjoiner master */ - WARN_ON(crtc_state->bigjoiner_slave); + WARN_ON(intel_crtc_is_bigjoiner_slave(crtc_state)); - crtc = crtc_state->bigjoiner_linked_crtc; - crtc_state = to_intel_crtc_state(crtc->base.state); - intel_encoder_get_config(encoder, crtc_state); + for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, slave_crtc, + intel_crtc_bigjoiner_slave_pipes(crtc_state)) { + struct intel_crtc_state *slave_crtc_state; + + slave_crtc_state = to_intel_crtc_state(slave_crtc->base.state); + intel_encoder_get_config(encoder, slave_crtc_state); + } } } else { encoder->base.crtc = NULL; |