diff options
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_display.c')
| -rw-r--r-- | drivers/gpu/drm/i915/display/intel_display.c | 383 | 
1 files changed, 172 insertions, 211 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index fc5d94862ef3..dd008ba8afe3 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -41,7 +41,6 @@  #include <drm/drm_damage_helper.h>  #include <drm/drm_edid.h>  #include <drm/drm_fourcc.h> -#include <drm/drm_plane_helper.h>  #include <drm/drm_privacy_screen_consumer.h>  #include <drm/drm_probe_helper.h>  #include <drm/drm_rect.h> @@ -92,6 +91,7 @@  #include "intel_dmc.h"  #include "intel_dp_link_training.h"  #include "intel_dpt.h" +#include "intel_dsb.h"  #include "intel_fbc.h"  #include "intel_fbdev.h"  #include "intel_fdi.h" @@ -118,6 +118,7 @@  #include "i9xx_plane.h"  #include "skl_scaler.h"  #include "skl_universal_plane.h" +#include "skl_watermark.h"  #include "vlv_dsi.h"  #include "vlv_dsi_pll.h"  #include "vlv_dsi_regs.h" @@ -164,16 +165,16 @@ static void ilk_pfit_enable(const struct intel_crtc_state *crtc_state);   */  void intel_update_watermarks(struct drm_i915_private *dev_priv)  { -	if (dev_priv->wm_disp->update_wm) -		dev_priv->wm_disp->update_wm(dev_priv); +	if (dev_priv->display.funcs.wm->update_wm) +		dev_priv->display.funcs.wm->update_wm(dev_priv);  }  static int intel_compute_pipe_wm(struct intel_atomic_state *state,  				 struct intel_crtc *crtc)  {  	struct drm_i915_private *dev_priv = to_i915(state->base.dev); -	if (dev_priv->wm_disp->compute_pipe_wm) -		return dev_priv->wm_disp->compute_pipe_wm(state, crtc); +	if (dev_priv->display.funcs.wm->compute_pipe_wm) +		return dev_priv->display.funcs.wm->compute_pipe_wm(state, crtc);  	return 0;  } @@ -181,20 +182,20 @@ static int intel_compute_intermediate_wm(struct intel_atomic_state *state,  					 struct intel_crtc *crtc)  {  	struct drm_i915_private *dev_priv = to_i915(state->base.dev); -	if (!dev_priv->wm_disp->compute_intermediate_wm) +	if (!dev_priv->display.funcs.wm->compute_intermediate_wm)  		return 0;  	if (drm_WARN_ON(&dev_priv->drm, -			!dev_priv->wm_disp->compute_pipe_wm)) +			!dev_priv->display.funcs.wm->compute_pipe_wm))  		return 0; -	return dev_priv->wm_disp->compute_intermediate_wm(state, crtc); +	return dev_priv->display.funcs.wm->compute_intermediate_wm(state, crtc);  }  static bool intel_initial_watermarks(struct intel_atomic_state *state,  				     struct intel_crtc *crtc)  {  	struct drm_i915_private *dev_priv = to_i915(state->base.dev); -	if (dev_priv->wm_disp->initial_watermarks) { -		dev_priv->wm_disp->initial_watermarks(state, crtc); +	if (dev_priv->display.funcs.wm->initial_watermarks) { +		dev_priv->display.funcs.wm->initial_watermarks(state, crtc);  		return true;  	}  	return false; @@ -204,23 +205,23 @@ static void intel_atomic_update_watermarks(struct intel_atomic_state *state,  					   struct intel_crtc *crtc)  {  	struct drm_i915_private *dev_priv = to_i915(state->base.dev); -	if (dev_priv->wm_disp->atomic_update_watermarks) -		dev_priv->wm_disp->atomic_update_watermarks(state, crtc); +	if (dev_priv->display.funcs.wm->atomic_update_watermarks) +		dev_priv->display.funcs.wm->atomic_update_watermarks(state, crtc);  }  static void intel_optimize_watermarks(struct intel_atomic_state *state,  				      struct intel_crtc *crtc)  {  	struct drm_i915_private *dev_priv = to_i915(state->base.dev); -	if (dev_priv->wm_disp->optimize_watermarks) -		dev_priv->wm_disp->optimize_watermarks(state, crtc); +	if (dev_priv->display.funcs.wm->optimize_watermarks) +		dev_priv->display.funcs.wm->optimize_watermarks(state, crtc);  }  static int intel_compute_global_watermarks(struct intel_atomic_state *state)  {  	struct drm_i915_private *dev_priv = to_i915(state->base.dev); -	if (dev_priv->wm_disp->compute_global_watermarks) -		return dev_priv->wm_disp->compute_global_watermarks(state); +	if (dev_priv->display.funcs.wm->compute_global_watermarks) +		return dev_priv->display.funcs.wm->compute_global_watermarks(state);  	return 0;  } @@ -619,7 +620,10 @@ void intel_disable_transcoder(const struct intel_crtc_state *old_crtc_state)  	if (!IS_I830(dev_priv))  		val &= ~PIPECONF_ENABLE; -	if (DISPLAY_VER(dev_priv) >= 12) +	if (DISPLAY_VER(dev_priv) >= 14) +		intel_de_rmw(dev_priv, MTL_CHICKEN_TRANS(cpu_transcoder), +			     FECSTALL_DIS_DPTSTREAM_DPTTG, 0); +	else if (DISPLAY_VER(dev_priv) >= 12)  		intel_de_rmw(dev_priv, CHICKEN_TRANS(cpu_transcoder),  			     FECSTALL_DIS_DPTSTREAM_DPTTG, 0); @@ -671,7 +675,7 @@ bool intel_plane_uses_fence(const struct intel_plane_state *plane_state)  	return DISPLAY_VER(dev_priv) < 4 ||  		(plane->fbc && -		 plane_state->view.gtt.type == I915_GGTT_VIEW_NORMAL); +		 plane_state->view.gtt.type == I915_GTT_VIEW_NORMAL);  }  /* @@ -1487,7 +1491,7 @@ static void intel_encoders_update_prepare(struct intel_atomic_state *state)  	 * Make sure the DPLL state is up-to-date for fastset TypeC ports after non-blocking commits.  	 * TODO: Update the DPLL state for all cases in the encoder->update_prepare() hook.  	 */ -	if (i915->dpll.mgr) { +	if (i915->display.dpll.mgr) {  		for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {  			if (intel_crtc_needs_modeset(new_crtc_state))  				continue; @@ -1839,7 +1843,9 @@ static void hsw_set_frame_start_delay(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); -	i915_reg_t reg = CHICKEN_TRANS(crtc_state->cpu_transcoder); +	enum transcoder transcoder = crtc_state->cpu_transcoder; +	i915_reg_t reg = DISPLAY_VER(dev_priv) >= 14 ? MTL_CHICKEN_TRANS(transcoder) : +			 CHICKEN_TRANS(transcoder);  	u32 val;  	val = intel_de_read(dev_priv, reg); @@ -2081,22 +2087,20 @@ bool intel_phy_is_combo(struct drm_i915_private *dev_priv, enum phy phy)  {  	if (phy == PHY_NONE)  		return false; -	else if (IS_DG2(dev_priv)) -		/* -		 * DG2 outputs labelled as "combo PHY" in the bspec use -		 * SNPS PHYs with completely different programming, -		 * hence we always return false here. -		 */ -		return false;  	else if (IS_ALDERLAKE_S(dev_priv))  		return phy <= PHY_E;  	else if (IS_DG1(dev_priv) || IS_ROCKETLAKE(dev_priv))  		return phy <= PHY_D;  	else if (IS_JSL_EHL(dev_priv))  		return phy <= PHY_C; -	else if (DISPLAY_VER(dev_priv) >= 11) +	else if (IS_ALDERLAKE_P(dev_priv) || IS_DISPLAY_VER(dev_priv, 11, 12))  		return phy <= PHY_B;  	else +		/* +		 * DG2 outputs labelled as "combo PHY" in the bspec use +		 * SNPS PHYs with completely different programming, +		 * hence we always return false here. +		 */  		return false;  } @@ -2402,7 +2406,7 @@ static void i9xx_crtc_disable(struct intel_atomic_state *state,  	if (DISPLAY_VER(dev_priv) != 2)  		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); -	if (!dev_priv->wm_disp->initial_watermarks) +	if (!dev_priv->display.funcs.wm->initial_watermarks)  		intel_update_watermarks(dev_priv);  	/* clock the pipe down to 640x480@60 to potentially save power */ @@ -2661,7 +2665,7 @@ static int intel_crtc_compute_pipe_mode(struct intel_crtc_state *crtc_state)  	intel_mode_from_crtc_timings(pipe_mode, pipe_mode);  	if (DISPLAY_VER(i915) < 4) { -		clock_limit = i915->max_cdclk_freq * 9 / 10; +		clock_limit = i915->display.cdclk.max_cdclk_freq * 9 / 10;  		/*  		 * Enable double wide mode when the dot clock @@ -2693,6 +2697,10 @@ static int intel_crtc_compute_config(struct intel_atomic_state *state,  		intel_atomic_get_new_crtc_state(state, crtc);  	int ret; +	ret = intel_dpll_crtc_compute_clock(state, crtc); +	if (ret) +		return ret; +  	ret = intel_crtc_compute_pipe_src(crtc_state);  	if (ret)  		return ret; @@ -2719,19 +2727,11 @@ intel_reduce_m_n_ratio(u32 *num, u32 *den)  	}  } -static void compute_m_n(unsigned int m, unsigned int n, -			u32 *ret_m, u32 *ret_n, -			bool constant_n) +static void compute_m_n(u32 *ret_m, u32 *ret_n, +			u32 m, u32 n, u32 constant_n)  { -	/* -	 * Several DP dongles in particular seem to be fussy about -	 * too large link M/N values. Give N value as 0x8000 that -	 * should be acceptable by specific devices. 0x8000 is the -	 * specified fixed N value for asynchronous clock mode, -	 * which the devices expect also in synchronous clock mode. -	 */  	if (constant_n) -		*ret_n = DP_LINK_CONSTANT_N_VALUE; +		*ret_n = constant_n;  	else  		*ret_n = min_t(unsigned int, roundup_pow_of_two(n), DATA_LINK_N_MAX); @@ -2743,22 +2743,28 @@ void  intel_link_compute_m_n(u16 bits_per_pixel, int nlanes,  		       int pixel_clock, int link_clock,  		       struct intel_link_m_n *m_n, -		       bool constant_n, bool fec_enable) +		       bool fec_enable)  {  	u32 data_clock = bits_per_pixel * pixel_clock;  	if (fec_enable)  		data_clock = intel_dp_mode_to_fec_clock(data_clock); +	/* +	 * Windows/BIOS uses fixed M/N values always. Follow suit. +	 * +	 * Also several DP dongles in particular seem to be fussy +	 * about too large link M/N values. Presumably the 20bit +	 * value used by Windows/BIOS is acceptable to everyone. +	 */  	m_n->tu = 64; -	compute_m_n(data_clock, -		    link_clock * nlanes * 8, -		    &m_n->data_m, &m_n->data_n, -		    constant_n); +	compute_m_n(&m_n->data_m, &m_n->data_n, +		    data_clock, link_clock * nlanes * 8, +		    0x8000000); -	compute_m_n(pixel_clock, link_clock, -		    &m_n->link_m, &m_n->link_n, -		    constant_n); +	compute_m_n(&m_n->link_m, &m_n->link_n, +		    pixel_clock, link_clock, +		    0x80000);  }  static void intel_panel_sanitize_ssc(struct drm_i915_private *dev_priv) @@ -2774,12 +2780,12 @@ static void intel_panel_sanitize_ssc(struct drm_i915_private *dev_priv)  						       PCH_DREF_CONTROL) &  			DREF_SSC1_ENABLE; -		if (dev_priv->vbt.lvds_use_ssc != bios_lvds_use_ssc) { +		if (dev_priv->display.vbt.lvds_use_ssc != bios_lvds_use_ssc) {  			drm_dbg_kms(&dev_priv->drm,  				    "SSC %s by BIOS, overriding VBT which says %s\n",  				    str_enabled_disabled(bios_lvds_use_ssc), -				    str_enabled_disabled(dev_priv->vbt.lvds_use_ssc)); -			dev_priv->vbt.lvds_use_ssc = bios_lvds_use_ssc; +				    str_enabled_disabled(dev_priv->display.vbt.lvds_use_ssc)); +			dev_priv->display.vbt.lvds_use_ssc = bios_lvds_use_ssc;  		}  	}  } @@ -4127,7 +4133,9 @@ static bool hsw_get_pipe_config(struct intel_crtc *crtc,  	}  	if (!transcoder_is_dsi(pipe_config->cpu_transcoder)) { -		tmp = intel_de_read(dev_priv, CHICKEN_TRANS(pipe_config->cpu_transcoder)); +		tmp = intel_de_read(dev_priv, DISPLAY_VER(dev_priv) >= 14 ? +				    MTL_CHICKEN_TRANS(pipe_config->cpu_transcoder) : +				    CHICKEN_TRANS(pipe_config->cpu_transcoder));  		pipe_config->framestart_delay = REG_FIELD_GET(HSW_FRAME_START_DELAY_MASK, tmp) + 1;  	} else { @@ -4146,7 +4154,7 @@ bool intel_crtc_get_pipe_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); -	if (!i915->display->get_pipe_config(crtc, crtc_state)) +	if (!i915->display.funcs.display->get_pipe_config(crtc, crtc_state))  		return false;  	crtc_state->hw.active = true; @@ -4375,7 +4383,7 @@ static int i9xx_pll_refclk(struct drm_device *dev,  	u32 dpll = pipe_config->dpll_hw_state.dpll;  	if ((dpll & PLL_REF_INPUT_MASK) == PLLB_REF_INPUT_SPREADSPECTRUMIN) -		return dev_priv->vbt.lvds_ssc_freq; +		return dev_priv->display.vbt.lvds_ssc_freq;  	else if (HAS_PCH_SPLIT(dev_priv))  		return 120000;  	else if (DISPLAY_VER(dev_priv) != 2) @@ -4493,7 +4501,31 @@ int intel_dotclock_calculate(int link_freq,  	if (!m_n->link_n)  		return 0; -	return div_u64(mul_u32_u32(m_n->link_m, link_freq), m_n->link_n); +	return DIV_ROUND_UP_ULL(mul_u32_u32(m_n->link_m, link_freq), +				m_n->link_n); +} + +int intel_crtc_dotclock(const struct intel_crtc_state *pipe_config) +{ +	int dotclock; + +	if (intel_crtc_has_dp_encoder(pipe_config)) +		dotclock = intel_dotclock_calculate(pipe_config->port_clock, +						    &pipe_config->dp_m_n); +	else if (pipe_config->has_hdmi_sink && pipe_config->pipe_bpp > 24) +		dotclock = DIV_ROUND_CLOSEST(pipe_config->port_clock * 24, +					     pipe_config->pipe_bpp); +	else +		dotclock = pipe_config->port_clock; + +	if (pipe_config->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 && +	    !intel_crtc_has_dp_encoder(pipe_config)) +		dotclock *= 2; + +	if (pipe_config->pixel_multiplier) +		dotclock /= pipe_config->pixel_multiplier; + +	return dotclock;  }  /* Returns the currently programmed mode of the given encoder. */ @@ -4754,7 +4786,7 @@ static u16 skl_linetime_wm(const struct intel_crtc_state *crtc_state)  	/* Display WA #1135: BXT:ALL GLK:ALL */  	if ((IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) && -	    dev_priv->ipc_enabled) +	    skl_watermark_ipc_enabled(dev_priv))  		linetime_wm /= 2;  	return min(linetime_wm, 0x1ff); @@ -4800,10 +4832,6 @@ static int intel_crtc_atomic_check(struct intel_atomic_state *state,  		crtc_state->update_wm_post = true;  	if (mode_changed) { -		ret = intel_dpll_crtc_compute_clock(state, crtc); -		if (ret) -			return ret; -  		ret = intel_dpll_crtc_get_shared_dpll(state, crtc);  		if (ret)  			return ret; @@ -5368,46 +5396,14 @@ bool intel_fuzzy_clock_check(int clock1, int clock2)  }  static bool -intel_compare_m_n(unsigned int m, unsigned int n, -		  unsigned int m2, unsigned int n2, -		  bool exact) -{ -	if (m == m2 && n == n2) -		return true; - -	if (exact || !m || !n || !m2 || !n2) -		return false; - -	BUILD_BUG_ON(DATA_LINK_M_N_MASK > INT_MAX); - -	if (n > n2) { -		while (n > n2) { -			m2 <<= 1; -			n2 <<= 1; -		} -	} else if (n < n2) { -		while (n < n2) { -			m <<= 1; -			n <<= 1; -		} -	} - -	if (n != n2) -		return false; - -	return intel_fuzzy_clock_check(m, m2); -} - -static bool  intel_compare_link_m_n(const struct intel_link_m_n *m_n, -		       const struct intel_link_m_n *m2_n2, -		       bool exact) +		       const struct intel_link_m_n *m2_n2)  {  	return m_n->tu == m2_n2->tu && -		intel_compare_m_n(m_n->data_m, m_n->data_n, -				  m2_n2->data_m, m2_n2->data_n, exact) && -		intel_compare_m_n(m_n->link_m, m_n->link_n, -				  m2_n2->link_m, m2_n2->link_n, exact); +		m_n->data_m == m2_n2->data_m && +		m_n->data_n == m2_n2->data_n && +		m_n->link_m == m2_n2->link_m && +		m_n->link_n == m2_n2->link_n;  }  static bool @@ -5601,8 +5597,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,  #define PIPE_CONF_CHECK_M_N(name) do { \  	if (!intel_compare_link_m_n(¤t_config->name, \ -				    &pipe_config->name,\ -				    !fastset)) { \ +				    &pipe_config->name)) { \  		pipe_config_mismatch(fastset, crtc, __stringify(name), \  				     "(expected tu %i data %i/%i link %i/%i, " \  				     "found tu %i, data %i/%i link %i/%i)", \ @@ -5649,9 +5644,9 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,   */  #define PIPE_CONF_CHECK_M_N_ALT(name, alt_name) do { \  	if (!intel_compare_link_m_n(¤t_config->name, \ -				    &pipe_config->name, !fastset) && \ +				    &pipe_config->name) && \  	    !intel_compare_link_m_n(¤t_config->alt_name, \ -				    &pipe_config->name, !fastset)) { \ +				    &pipe_config->name)) { \  		pipe_config_mismatch(fastset, crtc, __stringify(name), \  				     "(expected tu %i data %i/%i link %i/%i, " \  				     "or tu %i data %i/%i link %i/%i, " \ @@ -5686,16 +5681,6 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,  	} \  } while (0) -#define PIPE_CONF_CHECK_CLOCK_FUZZY(name) do { \ -	if (!intel_fuzzy_clock_check(current_config->name, pipe_config->name)) { \ -		pipe_config_mismatch(fastset, crtc, __stringify(name), \ -				     "(expected %i, found %i)", \ -				     current_config->name, \ -				     pipe_config->name); \ -		ret = false; \ -	} \ -} while (0) -  #define PIPE_CONF_CHECK_INFOFRAME(name) do { \  	if (!intel_compare_infoframe(¤t_config->infoframes.name, \  				     &pipe_config->infoframes.name)) { \ @@ -5751,8 +5736,9 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,  	PIPE_CONF_CHECK_I(lane_count);  	PIPE_CONF_CHECK_X(lane_lat_optim_mask); -	if (DISPLAY_VER(dev_priv) >= 9 || IS_BROADWELL(dev_priv)) { -		PIPE_CONF_CHECK_M_N_ALT(dp_m_n, dp_m2_n2); +	if (HAS_DOUBLE_BUFFERED_M_N(dev_priv)) { +		if (!fastset || !pipe_config->seamless_m_n) +			PIPE_CONF_CHECK_M_N_ALT(dp_m_n, dp_m2_n2);  	} else {  		PIPE_CONF_CHECK_M_N(dp_m_n);  		PIPE_CONF_CHECK_M_N(dp_m2_n2); @@ -5814,7 +5800,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,  		PIPE_CONF_CHECK_RECT(pch_pfit.dst);  		PIPE_CONF_CHECK_I(scaler_state.scaler_id); -		PIPE_CONF_CHECK_CLOCK_FUZZY(pixel_rate); +		PIPE_CONF_CHECK_I(pixel_rate);  		PIPE_CONF_CHECK_X(gamma_mode);  		if (IS_CHERRYVIEW(dev_priv)) @@ -5841,7 +5827,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,  	PIPE_CONF_CHECK_BOOL(double_wide); -	if (dev_priv->dpll.mgr) { +	if (dev_priv->display.dpll.mgr) {  		PIPE_CONF_CHECK_P(shared_dpll);  		PIPE_CONF_CHECK_X(dpll_hw_state.dpll); @@ -5884,9 +5870,11 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,  	if (IS_G4X(dev_priv) || DISPLAY_VER(dev_priv) >= 5)  		PIPE_CONF_CHECK_I(pipe_bpp); -	PIPE_CONF_CHECK_CLOCK_FUZZY(hw.pipe_mode.crtc_clock); -	PIPE_CONF_CHECK_CLOCK_FUZZY(hw.adjusted_mode.crtc_clock); -	PIPE_CONF_CHECK_CLOCK_FUZZY(port_clock); +	if (!fastset || !pipe_config->seamless_m_n) { +		PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_clock); +		PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_clock); +	} +	PIPE_CONF_CHECK_I(port_clock);  	PIPE_CONF_CHECK_I(min_voltage_level); @@ -5928,7 +5916,6 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,  #undef PIPE_CONF_CHECK_BOOL_INCOMPLETE  #undef PIPE_CONF_CHECK_P  #undef PIPE_CONF_CHECK_FLAGS -#undef PIPE_CONF_CHECK_CLOCK_FUZZY  #undef PIPE_CONF_CHECK_COLOR_LUT  #undef PIPE_CONF_CHECK_TIMINGS  #undef PIPE_CONF_CHECK_RECT @@ -6050,20 +6037,6 @@ void intel_crtc_update_active_timings(const struct intel_crtc_state *crtc_state)  	}  } -static void intel_modeset_clear_plls(struct intel_atomic_state *state) -{ -	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 (!intel_crtc_needs_modeset(new_crtc_state)) -			continue; - -		intel_release_shared_dplls(state, crtc); -	} -} -  /*   * This implements the workaround described in the "notes" section of the mode   * set sequence documentation. When going from no pipes or single pipe to @@ -6164,23 +6137,6 @@ static void intel_crtc_check_fastset(const struct intel_crtc_state *old_crtc_sta  	new_crtc_state->update_pipe = true;  } -static void intel_crtc_copy_fastset(const struct intel_crtc_state *old_crtc_state, -				    struct intel_crtc_state *new_crtc_state) -{ -	/* -	 * If we're not doing the full modeset we want to -	 * keep the current M/N values as they may be -	 * sufficiently different to the computed values -	 * to cause problems. -	 * -	 * FIXME: should really copy more fuzzy state here -	 */ -	new_crtc_state->fdi_m_n = old_crtc_state->fdi_m_n; -	new_crtc_state->dp_m_n = old_crtc_state->dp_m_n; -	new_crtc_state->dp_m2_n2 = old_crtc_state->dp_m2_n2; -	new_crtc_state->has_drrs = old_crtc_state->has_drrs; -} -  static int intel_crtc_add_planes_to_state(struct intel_atomic_state *state,  					  struct intel_crtc *crtc,  					  u8 plane_ids_mask) @@ -6837,9 +6793,11 @@ static int intel_atomic_check(struct drm_device *dev,  		if (!intel_crtc_needs_modeset(new_crtc_state))  			continue; -		ret = intel_modeset_pipe_config_late(state, crtc); -		if (ret) -			goto fail; +		if (new_crtc_state->hw.enable) { +			ret = intel_modeset_pipe_config_late(state, crtc); +			if (ret) +				goto fail; +		}  		intel_crtc_check_fastset(old_crtc_state, new_crtc_state);  	} @@ -6890,15 +6848,12 @@ 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)) { -			any_ms = true; +		if (!intel_crtc_needs_modeset(new_crtc_state))  			continue; -		} -		if (!new_crtc_state->update_pipe) -			continue; +		any_ms = true; -		intel_crtc_copy_fastset(old_crtc_state, new_crtc_state); +		intel_release_shared_dplls(state, crtc);  	}  	if (any_ms && !check_digital_port_conflicts(state)) { @@ -6939,8 +6894,6 @@ static int intel_atomic_check(struct drm_device *dev,  		ret = intel_modeset_calc_cdclk(state);  		if (ret)  			return ret; - -		intel_modeset_clear_plls(state);  	}  	ret = intel_atomic_check_crtcs(state); @@ -7059,6 +7012,10 @@ 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 (new_crtc_state->seamless_m_n) +		intel_cpu_transcoder_set_m1_n1(crtc, new_crtc_state->cpu_transcoder, +					       &new_crtc_state->dp_m_n);  }  static void commit_pipe_pre_planes(struct intel_atomic_state *state, @@ -7121,7 +7078,7 @@ static void intel_enable_crtc(struct intel_atomic_state *state,  	intel_crtc_update_active_timings(new_crtc_state); -	dev_priv->display->crtc_enable(state, crtc); +	dev_priv->display.funcs.display->crtc_enable(state, crtc);  	if (intel_crtc_is_bigjoiner_slave(new_crtc_state))  		return; @@ -7200,7 +7157,7 @@ static void intel_old_crtc_state_disables(struct intel_atomic_state *state,  	 */  	intel_crtc_disable_pipe_crc(crtc); -	dev_priv->display->crtc_disable(state, crtc); +	dev_priv->display.funcs.display->crtc_disable(state, crtc);  	crtc->active = false;  	intel_fbc_disable(crtc);  	intel_disable_shared_dpll(old_crtc_state); @@ -7411,7 +7368,7 @@ static void intel_atomic_helper_free_state(struct drm_i915_private *dev_priv)  	struct intel_atomic_state *state, *next;  	struct llist_node *freed; -	freed = llist_del_all(&dev_priv->atomic_helper.free_list); +	freed = llist_del_all(&dev_priv->display.atomic_helper.free_list);  	llist_for_each_entry_safe(state, next, freed, freed)  		drm_atomic_state_put(&state->base);  } @@ -7419,7 +7376,7 @@ static void intel_atomic_helper_free_state(struct drm_i915_private *dev_priv)  static void intel_atomic_helper_free_state_worker(struct work_struct *work)  {  	struct drm_i915_private *dev_priv = -		container_of(work, typeof(*dev_priv), atomic_helper.free_work); +		container_of(work, typeof(*dev_priv), display.atomic_helper.free_work);  	intel_atomic_helper_free_state(dev_priv);  } @@ -7532,6 +7489,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)  	intel_atomic_commit_fence_wait(state);  	drm_atomic_helper_wait_for_dependencies(&state->base); +	drm_dp_mst_atomic_wait_for_dependencies(&state->base);  	if (state->modeset)  		wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_MODESET); @@ -7588,7 +7546,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)  	}  	/* Now enable the clocks, plane, pipe, and connectors that we set up. */ -	dev_priv->display->commit_modeset_enables(state); +	dev_priv->display.funcs.display->commit_modeset_enables(state);  	intel_encoders_update_complete(state); @@ -7711,7 +7669,7 @@ intel_atomic_commit_ready(struct i915_sw_fence *fence,  	case FENCE_FREE:  		{  			struct intel_atomic_helper *helper = -				&to_i915(state->base.dev)->atomic_helper; +				&to_i915(state->base.dev)->display.atomic_helper;  			if (llist_add(&state->freed, &helper->free_list))  				schedule_work(&helper->free_work); @@ -7814,12 +7772,12 @@ static int intel_atomic_commit(struct drm_device *dev,  	i915_sw_fence_commit(&state->commit_ready);  	if (nonblock && state->modeset) { -		queue_work(dev_priv->modeset_wq, &state->base.commit_work); +		queue_work(dev_priv->display.wq.modeset, &state->base.commit_work);  	} else if (nonblock) { -		queue_work(dev_priv->flip_wq, &state->base.commit_work); +		queue_work(dev_priv->display.wq.flip, &state->base.commit_work);  	} else {  		if (state->modeset) -			flush_workqueue(dev_priv->modeset_wq); +			flush_workqueue(dev_priv->display.wq.modeset);  		intel_atomic_commit_tail(state);  	} @@ -7925,7 +7883,7 @@ static bool intel_ddi_crt_present(struct drm_i915_private *dev_priv)  	if (intel_de_read(dev_priv, DDI_BUF_CTL(PORT_A)) & DDI_A_4_LANES)  		return false; -	if (!dev_priv->vbt.int_crt_support) +	if (!dev_priv->display.vbt.int_crt_support)  		return false;  	return true; @@ -8060,7 +8018,7 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)  	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {  		bool has_edp, has_port; -		if (IS_VALLEYVIEW(dev_priv) && dev_priv->vbt.int_crt_support) +		if (IS_VALLEYVIEW(dev_priv) && dev_priv->display.vbt.int_crt_support)  			intel_crt_init(dev_priv);  		/* @@ -8319,7 +8277,7 @@ static const struct drm_mode_config_funcs intel_mode_funcs = {  	.atomic_state_free = intel_atomic_state_free,  }; -static const struct drm_i915_display_funcs skl_display_funcs = { +static const struct intel_display_funcs skl_display_funcs = {  	.get_pipe_config = hsw_get_pipe_config,  	.crtc_enable = hsw_crtc_enable,  	.crtc_disable = hsw_crtc_disable, @@ -8327,7 +8285,7 @@ static const struct drm_i915_display_funcs skl_display_funcs = {  	.get_initial_plane_config = skl_get_initial_plane_config,  }; -static const struct drm_i915_display_funcs ddi_display_funcs = { +static const struct intel_display_funcs ddi_display_funcs = {  	.get_pipe_config = hsw_get_pipe_config,  	.crtc_enable = hsw_crtc_enable,  	.crtc_disable = hsw_crtc_disable, @@ -8335,7 +8293,7 @@ static const struct drm_i915_display_funcs ddi_display_funcs = {  	.get_initial_plane_config = i9xx_get_initial_plane_config,  }; -static const struct drm_i915_display_funcs pch_split_display_funcs = { +static const struct intel_display_funcs pch_split_display_funcs = {  	.get_pipe_config = ilk_get_pipe_config,  	.crtc_enable = ilk_crtc_enable,  	.crtc_disable = ilk_crtc_disable, @@ -8343,7 +8301,7 @@ static const struct drm_i915_display_funcs pch_split_display_funcs = {  	.get_initial_plane_config = i9xx_get_initial_plane_config,  }; -static const struct drm_i915_display_funcs vlv_display_funcs = { +static const struct intel_display_funcs vlv_display_funcs = {  	.get_pipe_config = i9xx_get_pipe_config,  	.crtc_enable = valleyview_crtc_enable,  	.crtc_disable = i9xx_crtc_disable, @@ -8351,7 +8309,7 @@ static const struct drm_i915_display_funcs vlv_display_funcs = {  	.get_initial_plane_config = i9xx_get_initial_plane_config,  }; -static const struct drm_i915_display_funcs i9xx_display_funcs = { +static const struct intel_display_funcs i9xx_display_funcs = {  	.get_pipe_config = i9xx_get_pipe_config,  	.crtc_enable = i9xx_crtc_enable,  	.crtc_disable = i9xx_crtc_disable, @@ -8374,16 +8332,16 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv)  	intel_dpll_init_clock_hook(dev_priv);  	if (DISPLAY_VER(dev_priv) >= 9) { -		dev_priv->display = &skl_display_funcs; +		dev_priv->display.funcs.display = &skl_display_funcs;  	} else if (HAS_DDI(dev_priv)) { -		dev_priv->display = &ddi_display_funcs; +		dev_priv->display.funcs.display = &ddi_display_funcs;  	} else if (HAS_PCH_SPLIT(dev_priv)) { -		dev_priv->display = &pch_split_display_funcs; +		dev_priv->display.funcs.display = &pch_split_display_funcs;  	} else if (IS_CHERRYVIEW(dev_priv) ||  		   IS_VALLEYVIEW(dev_priv)) { -		dev_priv->display = &vlv_display_funcs; +		dev_priv->display.funcs.display = &vlv_display_funcs;  	} else { -		dev_priv->display = &i9xx_display_funcs; +		dev_priv->display.funcs.display = &i9xx_display_funcs;  	}  	intel_fdi_init_hook(dev_priv); @@ -8396,11 +8354,11 @@ void intel_modeset_init_hw(struct drm_i915_private *i915)  	if (!HAS_DISPLAY(i915))  		return; -	cdclk_state = to_intel_cdclk_state(i915->cdclk.obj.state); +	cdclk_state = to_intel_cdclk_state(i915->display.cdclk.obj.state);  	intel_update_cdclk(i915); -	intel_cdclk_dump_config(i915, &i915->cdclk.hw, "Current CDCLK"); -	cdclk_state->logical = cdclk_state->actual = i915->cdclk.hw; +	intel_cdclk_dump_config(i915, &i915->display.cdclk.hw, "Current CDCLK"); +	cdclk_state->logical = cdclk_state->actual = i915->display.cdclk.hw;  }  static int sanitize_watermarks_add_affected(struct drm_atomic_state *state) @@ -8456,7 +8414,7 @@ static void sanitize_watermarks(struct drm_i915_private *dev_priv)  	int i;  	/* Only supported on platforms that use atomic watermark design */ -	if (!dev_priv->wm_disp->optimize_watermarks) +	if (!dev_priv->display.funcs.wm->optimize_watermarks)  		return;  	state = drm_atomic_state_alloc(&dev_priv->drm); @@ -8600,6 +8558,10 @@ out:  	return ret;  } +static const struct drm_mode_config_helper_funcs intel_mode_config_funcs = { +	.atomic_commit_setup = drm_dp_mst_atomic_setup_commit, +}; +  static void intel_mode_config_init(struct drm_i915_private *i915)  {  	struct drm_mode_config *mode_config = &i915->drm.mode_config; @@ -8614,6 +8576,7 @@ static void intel_mode_config_init(struct drm_i915_private *i915)  	mode_config->prefer_shadow = 1;  	mode_config->funcs = &intel_mode_funcs; +	mode_config->helper_private = &intel_mode_config_funcs;  	mode_config->async_page_flip = HAS_ASYNC_FLIPS(i915); @@ -8683,11 +8646,9 @@ int intel_modeset_init_noirq(struct drm_i915_private *i915)  	intel_dmc_ucode_init(i915); -	i915->modeset_wq = alloc_ordered_workqueue("i915_modeset", 0); -	i915->flip_wq = alloc_workqueue("i915_flip", WQ_HIGHPRI | -					WQ_UNBOUND, WQ_UNBOUND_MAX_ACTIVE); - -	i915->window2_delay = 0; /* No DSB so no window2 delay */ +	i915->display.wq.modeset = alloc_ordered_workqueue("i915_modeset", 0); +	i915->display.wq.flip = alloc_workqueue("i915_flip", WQ_HIGHPRI | +						WQ_UNBOUND, WQ_UNBOUND_MAX_ACTIVE);  	intel_mode_config_init(i915); @@ -8703,8 +8664,8 @@ int intel_modeset_init_noirq(struct drm_i915_private *i915)  	if (ret)  		goto cleanup_vga_client_pw_domain_dmc; -	init_llist_head(&i915->atomic_helper.free_list); -	INIT_WORK(&i915->atomic_helper.free_work, +	init_llist_head(&i915->display.atomic_helper.free_list); +	INIT_WORK(&i915->display.atomic_helper.free_work,  		  intel_atomic_helper_free_state_worker);  	intel_init_quirks(i915); @@ -8764,7 +8725,7 @@ int intel_modeset_init_nogem(struct drm_i915_private *i915)  	intel_hdcp_component_init(i915); -	if (i915->max_cdclk_freq == 0) +	if (i915->display.cdclk.max_cdclk_freq == 0)  		intel_update_max_cdclk(i915);  	/* @@ -8828,7 +8789,7 @@ int intel_modeset_init(struct drm_i915_private *i915)  	intel_hpd_init(i915);  	intel_hpd_poll_disable(i915); -	intel_init_ipc(i915); +	skl_watermark_ipc_init(i915);  	return 0;  } @@ -8959,7 +8920,7 @@ void intel_display_resume(struct drm_device *dev)  	if (!ret)  		ret = __intel_display_resume(i915, state, &ctx); -	intel_enable_ipc(i915); +	skl_watermark_ipc_update(i915);  	drm_modeset_drop_locks(&ctx);  	drm_modeset_acquire_fini(&ctx); @@ -8994,11 +8955,18 @@ void intel_modeset_driver_remove(struct drm_i915_private *i915)  	if (!HAS_DISPLAY(i915))  		return; -	flush_workqueue(i915->flip_wq); -	flush_workqueue(i915->modeset_wq); +	flush_workqueue(i915->display.wq.flip); +	flush_workqueue(i915->display.wq.modeset); + +	flush_work(&i915->display.atomic_helper.free_work); +	drm_WARN_ON(&i915->drm, !llist_empty(&i915->display.atomic_helper.free_list)); -	flush_work(&i915->atomic_helper.free_work); -	drm_WARN_ON(&i915->drm, !llist_empty(&i915->atomic_helper.free_list)); +	/* +	 * MST topology needs to be suspended so we don't have any calls to +	 * fbdev after it's finalized. MST will be destroyed later as part of +	 * drm_mode_config_cleanup() +	 */ +	intel_dp_mst_suspend(i915);  }  /* part #2: call after irq uninstall */ @@ -9013,13 +8981,6 @@ void intel_modeset_driver_remove_noirq(struct drm_i915_private *i915)  	 */  	intel_hpd_poll_fini(i915); -	/* -	 * MST topology needs to be suspended so we don't have any calls to -	 * fbdev after it's finalized. MST will be destroyed later as part of -	 * drm_mode_config_cleanup() -	 */ -	intel_dp_mst_suspend(i915); -  	/* poll work can call into fbdev, hence clean that up afterwards */  	intel_fbdev_fini(i915); @@ -9036,8 +8997,8 @@ void intel_modeset_driver_remove_noirq(struct drm_i915_private *i915)  	intel_gmbus_teardown(i915); -	destroy_workqueue(i915->flip_wq); -	destroy_workqueue(i915->modeset_wq); +	destroy_workqueue(i915->display.wq.flip); +	destroy_workqueue(i915->display.wq.modeset);  	intel_fbc_cleanup(i915);  } @@ -9084,7 +9045,7 @@ void intel_display_driver_register(struct drm_i915_private *i915)  	/* Must be done after probing outputs */  	intel_opregion_register(i915); -	acpi_video_register(); +	intel_acpi_video_register(i915);  	intel_audio_init(i915);  |