diff mbox series

[v11,08/12] drm/i915/dp: Master/Slave enable/disable sequence for bigjoiner

Message ID 20201022054223.25071-9-manasi.d.navare@intel.com (mailing list archive)
State New, archived
Headers show
Series Big joiner enabling | expand

Commit Message

Navare, Manasi Oct. 22, 2020, 5:42 a.m. UTC
Enabling is done in a special sequence and so should plane updates
be. Ideally the end user never notices the second pipe is used.

This way ideally everything will be tear free, and updates are
really atomic as userspace expects it.

This uses generic modeset_enables() calls like trans port sync
but still has special handling for disable since for slave we
should not disable things like encoder, plls that are not enabled
for  slave.

Signed-off-by: Manasi Navare <manasi.d.navare@intel.com>
---
 drivers/gpu/drm/i915/display/intel_ddi.c     |  25 +++-
 drivers/gpu/drm/i915/display/intel_display.c | 118 +++++++++++++++----
 2 files changed, 118 insertions(+), 25 deletions(-)

Comments

Dan Carpenter Oct. 23, 2020, 7:57 a.m. UTC | #1
Hi Manasi,

url:    https://github.com/0day-ci/linux/commits/Manasi-Navare/Big-joiner-enabling/20201022-134216
base:   git://anongit.freedesktop.org/drm/drm-tip drm-tip
config: x86_64-randconfig-m001-20201022 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-15) 9.3.0

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>

New smatch warnings:
drivers/gpu/drm/i915/display/intel_display.c:7303 hsw_crtc_enable() warn: if statement not indented

Old smatch warnings:
drivers/gpu/drm/i915/display/intel_display.c:6237 skl_update_scaler_plane() error: we previously assumed 'fb' could be null (see line 6221)
drivers/gpu/drm/i915/display/intel_display.c:15236 kill_bigjoiner_slave() warn: inconsistent indenting

vim +7303 drivers/gpu/drm/i915/display/intel_display.c

1e98f88cea0ff5 drivers/gpu/drm/i915/display/intel_display.c Lucas De Marchi   2019-12-24  7274  static void hsw_crtc_enable(struct intel_atomic_state *state,
7451a074bf2f26 drivers/gpu/drm/i915/display/intel_display.c Ville Syrjälä     2019-11-18  7275  			    struct intel_crtc *crtc)
6be4a6078e41a8 drivers/gpu/drm/i915/intel_display.c         Jesse Barnes      2010-09-10  7276  {
7451a074bf2f26 drivers/gpu/drm/i915/display/intel_display.c Ville Syrjälä     2019-11-18  7277  	const struct intel_crtc_state *new_crtc_state =
7451a074bf2f26 drivers/gpu/drm/i915/display/intel_display.c Ville Syrjälä     2019-11-18  7278  		intel_atomic_get_new_crtc_state(state, crtc);
e44c84a14469d3 drivers/gpu/drm/i915/display/intel_display.c Ville Syrjälä     2019-11-18  7279  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
e44c84a14469d3 drivers/gpu/drm/i915/display/intel_display.c Ville Syrjälä     2019-11-18  7280  	enum pipe pipe = crtc->pipe, hsw_workaround_pipe;
502d871459d25e drivers/gpu/drm/i915/display/intel_display.c Ville Syrjälä     2019-11-18  7281  	enum transcoder cpu_transcoder = new_crtc_state->cpu_transcoder;
ed69cd40685c94 drivers/gpu/drm/i915/intel_display.c         Imre Deak         2017-10-02  7282  	bool psl_clkgate_wa;
2c07245fb8f7f0 drivers/gpu/drm/i915/intel_display.c         Zhenyu Wang       2009-06-05  7283  
e57291c2d39522 drivers/gpu/drm/i915/display/intel_display.c Pankaj Bharadiya  2020-02-20  7284  	if (drm_WARN_ON(&dev_priv->drm, crtc->active))
f7abfe8b281991 drivers/gpu/drm/i915/intel_display.c         Chris Wilson      2010-09-13  7285  		return;
f7abfe8b281991 drivers/gpu/drm/i915/intel_display.c         Chris Wilson      2010-09-13  7286  
9587d0b839b5fd drivers/gpu/drm/i915/display/intel_display.c Manasi Navare     2020-10-21  7287  	if (!new_crtc_state->bigjoiner) {
e44c84a14469d3 drivers/gpu/drm/i915/display/intel_display.c Ville Syrjälä     2019-11-18  7288  		intel_encoders_pre_pll_enable(state, crtc);
95a7a2ae46652f drivers/gpu/drm/i915/intel_display.c         Imre Deak         2016-06-13  7289  
502d871459d25e drivers/gpu/drm/i915/display/intel_display.c Ville Syrjälä     2019-11-18  7290  		if (new_crtc_state->shared_dpll)
502d871459d25e drivers/gpu/drm/i915/display/intel_display.c Ville Syrjälä     2019-11-18  7291  			intel_enable_shared_dpll(new_crtc_state);
df8ad70ca34f9b drivers/gpu/drm/i915/intel_display.c         Daniel Vetter     2014-06-25  7292  
e44c84a14469d3 drivers/gpu/drm/i915/display/intel_display.c Ville Syrjälä     2019-11-18  7293  		intel_encoders_pre_enable(state, crtc);
9587d0b839b5fd drivers/gpu/drm/i915/display/intel_display.c Manasi Navare     2020-10-21  7294  	} else {
9587d0b839b5fd drivers/gpu/drm/i915/display/intel_display.c Manasi Navare     2020-10-21  7295  		icl_ddi_bigjoiner_pre_enable(state, new_crtc_state);
9587d0b839b5fd drivers/gpu/drm/i915/display/intel_display.c Manasi Navare     2020-10-21  7296  	}
9587d0b839b5fd drivers/gpu/drm/i915/display/intel_display.c Manasi Navare     2020-10-21  7297  
9587d0b839b5fd drivers/gpu/drm/i915/display/intel_display.c Manasi Navare     2020-10-21  7298  	intel_set_pipe_src_size(new_crtc_state);
9587d0b839b5fd drivers/gpu/drm/i915/display/intel_display.c Manasi Navare     2020-10-21  7299  	if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
9587d0b839b5fd drivers/gpu/drm/i915/display/intel_display.c Manasi Navare     2020-10-21  7300  		bdw_set_pipemisc(new_crtc_state);
c8af5274c3cbac drivers/gpu/drm/i915/intel_display.c         Paulo Zanoni      2018-05-02  7301  
9587d0b839b5fd drivers/gpu/drm/i915/display/intel_display.c Manasi Navare     2020-10-21  7302  	if (!new_crtc_state->bigjoiner_slave || !transcoder_is_dsi(cpu_transcoder)){
d7edc4e57bfefc drivers/gpu/drm/i915/intel_display.c         Ville Syrjälä     2016-06-22 @7303  		if (!transcoder_is_dsi(cpu_transcoder))
e7fc3f902d76f1 drivers/gpu/drm/i915/display/intel_display.c Manasi Navare     2020-10-08  7304  		intel_set_transcoder_timings(new_crtc_state);
                                                                                                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This looks correct, only the indenting is wrong.

4d1de975683218 drivers/gpu/drm/i915/intel_display.c         Jani Nikula       2016-03-18  7305  
4d1de975683218 drivers/gpu/drm/i915/intel_display.c         Jani Nikula       2016-03-18  7306  		if (cpu_transcoder != TRANSCODER_EDP &&
502d871459d25e drivers/gpu/drm/i915/display/intel_display.c Ville Syrjälä     2019-11-18  7307  		    !transcoder_is_dsi(cpu_transcoder))
dc008bf0aa091c drivers/gpu/drm/i915/display/intel_display.c Jani Nikula       2020-01-27  7308  			intel_de_write(dev_priv, PIPE_MULT(cpu_transcoder),
502d871459d25e drivers/gpu/drm/i915/display/intel_display.c Ville Syrjälä     2019-11-18  7309  				       new_crtc_state->pixel_multiplier - 1);
ebb69c95175609 drivers/gpu/drm/i915/intel_display.c         Clint Taylor      2014-09-30  7310  
502d871459d25e drivers/gpu/drm/i915/display/intel_display.c Ville Syrjälä     2019-11-18  7311  		if (new_crtc_state->has_pch_encoder)
502d871459d25e drivers/gpu/drm/i915/display/intel_display.c Ville Syrjälä     2019-11-18  7312  			intel_cpu_transcoder_set_m_n(new_crtc_state,
502d871459d25e drivers/gpu/drm/i915/display/intel_display.c Ville Syrjälä     2019-11-18  7313  						     &new_crtc_state->fdi_m_n, NULL);
229fca97437310 drivers/gpu/drm/i915/intel_display.c         Daniel Vetter     2014-04-24  7314  
502d871459d25e drivers/gpu/drm/i915/display/intel_display.c Ville Syrjälä     2019-11-18  7315  		hsw_set_frame_start_delay(new_crtc_state);
cc7a4cffea2195 drivers/gpu/drm/i915/display/intel_display.c Ville Syrjälä     2019-10-24  7316  	}
4d1de975683218 drivers/gpu/drm/i915/intel_display.c         Jani Nikula       2016-03-18  7317  
9587d0b839b5fd drivers/gpu/drm/i915/display/intel_display.c Manasi Navare     2020-10-21  7318  	if (!transcoder_is_dsi(cpu_transcoder))
9587d0b839b5fd drivers/gpu/drm/i915/display/intel_display.c Manasi Navare     2020-10-21  7319  		hsw_set_pipeconf(new_crtc_state);
229fca97437310 drivers/gpu/drm/i915/intel_display.c         Daniel Vetter     2014-04-24  7320  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
Navare, Manasi Oct. 26, 2020, 9:57 p.m. UTC | #2
@Ville, Addressed your review comments from prev review
and assuming your Ack on this

Manasi

On Wed, Oct 21, 2020 at 10:42:19PM -0700, Manasi Navare wrote:
> Enabling is done in a special sequence and so should plane updates
> be. Ideally the end user never notices the second pipe is used.
> 
> This way ideally everything will be tear free, and updates are
> really atomic as userspace expects it.
> 
> This uses generic modeset_enables() calls like trans port sync
> but still has special handling for disable since for slave we
> should not disable things like encoder, plls that are not enabled
> for  slave.
> 
> Signed-off-by: Manasi Navare <manasi.d.navare@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_ddi.c     |  25 +++-
>  drivers/gpu/drm/i915/display/intel_display.c | 118 +++++++++++++++----
>  2 files changed, 118 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
> index 59db465ea7df..050891a130c1 100644
> --- a/drivers/gpu/drm/i915/display/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/display/intel_ddi.c
> @@ -28,6 +28,7 @@
>  #include <drm/drm_scdc_helper.h>
>  
>  #include "i915_drv.h"
> +#include "i915_trace.h"
>  #include "intel_audio.h"
>  #include "intel_combo_phy.h"
>  #include "intel_connector.h"
> @@ -3500,7 +3501,8 @@ static void tgl_ddi_pre_enable_dp(struct intel_atomic_state *state,
>  
>  	/* 7.l Configure and enable FEC if needed */
>  	intel_ddi_enable_fec(encoder, crtc_state);
> -	intel_dsc_enable(encoder, crtc_state);
> +	if (!crtc_state->bigjoiner)
> +		intel_dsc_enable(encoder, crtc_state);
>  }
>  
>  static void hsw_ddi_pre_enable_dp(struct intel_atomic_state *state,
> @@ -3572,7 +3574,8 @@ static void hsw_ddi_pre_enable_dp(struct intel_atomic_state *state,
>  	if (!is_mst)
>  		intel_ddi_enable_pipe_clock(encoder, crtc_state);
>  
> -	intel_dsc_enable(encoder, crtc_state);
> +	if (!crtc_state->bigjoiner)
> +		intel_dsc_enable(encoder, crtc_state);
>  }
>  
>  static void intel_ddi_pre_enable_dp(struct intel_atomic_state *state,
> @@ -3821,6 +3824,21 @@ static void intel_ddi_post_disable(struct intel_atomic_state *state,
>  			ilk_pfit_disable(old_crtc_state);
>  	}
>  
> +	if (old_crtc_state->bigjoiner_linked_crtc) {
> +		struct intel_atomic_state *state =
> +			to_intel_atomic_state(old_crtc_state->uapi.state);
> +		struct intel_crtc *slave =
> +			old_crtc_state->bigjoiner_linked_crtc;
> +		const struct intel_crtc_state *old_slave_crtc_state =
> +			intel_atomic_get_old_crtc_state(state, slave);
> +
> +		intel_crtc_vblank_off(old_slave_crtc_state);
> +		trace_intel_pipe_disable(slave);
> +
> +		intel_dsc_disable(old_slave_crtc_state);
> +		skl_scaler_disable(old_slave_crtc_state);
> +	}
> +
>  	/*
>  	 * When called from DP MST code:
>  	 * - old_conn_state will be NULL
> @@ -4037,7 +4055,8 @@ static void intel_enable_ddi(struct intel_atomic_state *state,
>  {
>  	drm_WARN_ON(state->base.dev, crtc_state->has_pch_encoder);
>  
> -	intel_ddi_enable_transcoder_func(encoder, crtc_state);
> +	if (!crtc_state->bigjoiner_slave)
> +		intel_ddi_enable_transcoder_func(encoder, crtc_state);
>  
>  	intel_enable_pipe(crtc_state);
>  
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index 338fa48a144d..1be77ba2f9cf 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -7232,6 +7232,45 @@ static void hsw_set_frame_start_delay(const struct intel_crtc_state *crtc_state)
>  	intel_de_write(dev_priv, reg, val);
>  }
>  
> +static void icl_ddi_bigjoiner_pre_enable(struct intel_atomic_state *state,
> +					 const struct intel_crtc_state *crtc_state)
> +{
> +	struct intel_crtc *master = to_intel_crtc(crtc_state->uapi.crtc);
> +	struct intel_crtc_state *master_crtc_state;
> +	struct drm_connector_state *conn_state;
> +	struct drm_connector *conn;
> +	struct intel_encoder *encoder = NULL;
> +	int i;
> +
> +	if (crtc_state->bigjoiner_slave)
> +		master = crtc_state->bigjoiner_linked_crtc;
> +
> +	master_crtc_state = intel_atomic_get_new_crtc_state(state, master);
> +
> +	for_each_new_connector_in_state(&state->base, conn, conn_state, i) {
> +		if (conn_state->crtc != &master->base)
> +			continue;
> +
> +		encoder = to_intel_encoder(conn_state->best_encoder);
> +		break;
> +	}
> +
> +	if (!crtc_state->bigjoiner_slave) {
> +		/* need to enable VDSC, which we skipped in pre-enable */
> +		intel_dsc_enable(encoder, crtc_state);
> +	} else {
> +		/*
> +                 * Enable sequence steps 1-7 on bigjoiner master
> +                 */
> +		intel_encoders_pre_pll_enable(state, master);
> +		intel_enable_shared_dpll(master_crtc_state);
> +		intel_encoders_pre_enable(state, master);
> +
> +		/* and DSC on slave */
> +		intel_dsc_enable(NULL, crtc_state);
> +	}
> +}
> +
>  static void hsw_crtc_enable(struct intel_atomic_state *state,
>  			    struct intel_crtc *crtc)
>  {
> @@ -7245,34 +7284,39 @@ static void hsw_crtc_enable(struct intel_atomic_state *state,
>  	if (drm_WARN_ON(&dev_priv->drm, crtc->active))
>  		return;
>  
> -	intel_encoders_pre_pll_enable(state, crtc);
> +	if (!new_crtc_state->bigjoiner) {
> +		intel_encoders_pre_pll_enable(state, crtc);
>  
> -	if (new_crtc_state->shared_dpll)
> -		intel_enable_shared_dpll(new_crtc_state);
> -
> -	intel_encoders_pre_enable(state, crtc);
> +		if (new_crtc_state->shared_dpll)
> +			intel_enable_shared_dpll(new_crtc_state);
>  
> -	if (!transcoder_is_dsi(cpu_transcoder))
> -		intel_set_transcoder_timings(new_crtc_state);
> +		intel_encoders_pre_enable(state, crtc);
> +	} else {
> +		icl_ddi_bigjoiner_pre_enable(state, new_crtc_state);
> +	}
>  
>  	intel_set_pipe_src_size(new_crtc_state);
> +	if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
> +		bdw_set_pipemisc(new_crtc_state);
>  
> -	if (cpu_transcoder != TRANSCODER_EDP &&
> -	    !transcoder_is_dsi(cpu_transcoder))
> -		intel_de_write(dev_priv, PIPE_MULT(cpu_transcoder),
> -			       new_crtc_state->pixel_multiplier - 1);
> +	if (!new_crtc_state->bigjoiner_slave || !transcoder_is_dsi(cpu_transcoder)){
> +		if (!transcoder_is_dsi(cpu_transcoder))
> +		intel_set_transcoder_timings(new_crtc_state);
>  
> -	if (new_crtc_state->has_pch_encoder)
> -		intel_cpu_transcoder_set_m_n(new_crtc_state,
> -					     &new_crtc_state->fdi_m_n, NULL);
> +		if (cpu_transcoder != TRANSCODER_EDP &&
> +		    !transcoder_is_dsi(cpu_transcoder))
> +			intel_de_write(dev_priv, PIPE_MULT(cpu_transcoder),
> +				       new_crtc_state->pixel_multiplier - 1);
> +
> +		if (new_crtc_state->has_pch_encoder)
> +			intel_cpu_transcoder_set_m_n(new_crtc_state,
> +						     &new_crtc_state->fdi_m_n, NULL);
>  
> -	if (!transcoder_is_dsi(cpu_transcoder)) {
>  		hsw_set_frame_start_delay(new_crtc_state);
> -		hsw_set_pipeconf(new_crtc_state);
>  	}
>  
> -	if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
> -		bdw_set_pipemisc(new_crtc_state);
> +	if (!transcoder_is_dsi(cpu_transcoder))
> +		hsw_set_pipeconf(new_crtc_state);
>  
>  	crtc->active = true;
>  
> @@ -7308,6 +7352,11 @@ static void hsw_crtc_enable(struct intel_atomic_state *state,
>  	if (INTEL_GEN(dev_priv) >= 11)
>  		icl_pipe_mbus_enable(crtc);
>  
> +	if (new_crtc_state->bigjoiner_slave) {
> +		trace_intel_pipe_enable(crtc);
> +		intel_crtc_vblank_on(new_crtc_state);
> +	}
> +
>  	intel_encoders_enable(state, crtc);
>  
>  	if (psl_clkgate_wa) {
> @@ -15683,6 +15732,9 @@ static void intel_enable_crtc(struct intel_atomic_state *state,
>  
>  	dev_priv->display.crtc_enable(state, crtc);
>  
> +	if (new_crtc_state->bigjoiner_slave)
> +		return;
> +
>  	/* vblanks work again, re-enable pipe CRC. */
>  	intel_crtc_enable_pipe_crc(crtc);
>  }
> @@ -15747,8 +15799,21 @@ static void intel_old_crtc_state_disables(struct intel_atomic_state *state,
>  {
>  	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
>  
> +	drm_WARN_ON(&dev_priv->drm, old_crtc_state->bigjoiner_slave);
> +
>  	intel_crtc_disable_planes(state, crtc);
>  
> +	/*
> +	 * We still need special handling for disabling bigjoiner master
> +	 * and slaves since for slave we do not have encoder or plls
> +	 * so we dont need to disable those.
> +	 */
> +	if (old_crtc_state->bigjoiner) {
> +		intel_crtc_disable_planes(state,
> +					  old_crtc_state->bigjoiner_linked_crtc);
> +		old_crtc_state->bigjoiner_linked_crtc->active = false;
> +	}
> +
>  	/*
>  	 * We need to disable pipe CRC before disabling the pipe,
>  	 * or we race against vblank off.
> @@ -15777,7 +15842,7 @@ static void intel_commit_modeset_disables(struct intel_atomic_state *state)
>  	/* Only disable port sync and MST slaves */
>  	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
>  					    new_crtc_state, i) {
> -		if (!needs_modeset(new_crtc_state))
> +		if (!needs_modeset(new_crtc_state) || old_crtc_state->bigjoiner)
>  			continue;
>  
>  		if (!old_crtc_state->hw.active)
> @@ -15802,10 +15867,18 @@ static void intel_commit_modeset_disables(struct intel_atomic_state *state)
>  	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
>  					    new_crtc_state, i) {
>  		if (!needs_modeset(new_crtc_state) ||
> -		    (handled & BIT(crtc->pipe)))
> +		    (handled & BIT(crtc->pipe)) ||
> +		    old_crtc_state->bigjoiner_slave)
>  			continue;
>  
>  		intel_pre_plane_update(state, crtc);
> +		if (old_crtc_state->bigjoiner) {
> +			struct intel_crtc *slave =
> +				old_crtc_state->bigjoiner_linked_crtc;
> +
> +			intel_pre_plane_update(state, slave);
> +		}
> +
>  		if (old_crtc_state->hw.active)
>  			intel_old_crtc_state_disables(state, old_crtc_state,
>  						      new_crtc_state, crtc);
> @@ -15903,7 +15976,8 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)
>  			continue;
>  
>  		if (intel_dp_mst_is_slave_trans(new_crtc_state) ||
> -		    is_trans_port_sync_master(new_crtc_state))
> +		    is_trans_port_sync_master(new_crtc_state) ||
> +		    (new_crtc_state->bigjoiner && !new_crtc_state->bigjoiner_slave))
>  			continue;
>  
>  		modeset_pipes &= ~BIT(pipe);
> @@ -15913,7 +15987,7 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)
>  
>  	/*
>  	 * Then we enable all remaining pipes that depend on other
> -	 * pipes: MST slaves and port sync masters.
> +	 * pipes: MST slaves and port sync masters, big joiner master
>  	 */
>  	for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
>  		enum pipe pipe = crtc->pipe;
> -- 
> 2.19.1
>
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
index 59db465ea7df..050891a130c1 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -28,6 +28,7 @@ 
 #include <drm/drm_scdc_helper.h>
 
 #include "i915_drv.h"
+#include "i915_trace.h"
 #include "intel_audio.h"
 #include "intel_combo_phy.h"
 #include "intel_connector.h"
@@ -3500,7 +3501,8 @@  static void tgl_ddi_pre_enable_dp(struct intel_atomic_state *state,
 
 	/* 7.l Configure and enable FEC if needed */
 	intel_ddi_enable_fec(encoder, crtc_state);
-	intel_dsc_enable(encoder, crtc_state);
+	if (!crtc_state->bigjoiner)
+		intel_dsc_enable(encoder, crtc_state);
 }
 
 static void hsw_ddi_pre_enable_dp(struct intel_atomic_state *state,
@@ -3572,7 +3574,8 @@  static void hsw_ddi_pre_enable_dp(struct intel_atomic_state *state,
 	if (!is_mst)
 		intel_ddi_enable_pipe_clock(encoder, crtc_state);
 
-	intel_dsc_enable(encoder, crtc_state);
+	if (!crtc_state->bigjoiner)
+		intel_dsc_enable(encoder, crtc_state);
 }
 
 static void intel_ddi_pre_enable_dp(struct intel_atomic_state *state,
@@ -3821,6 +3824,21 @@  static void intel_ddi_post_disable(struct intel_atomic_state *state,
 			ilk_pfit_disable(old_crtc_state);
 	}
 
+	if (old_crtc_state->bigjoiner_linked_crtc) {
+		struct intel_atomic_state *state =
+			to_intel_atomic_state(old_crtc_state->uapi.state);
+		struct intel_crtc *slave =
+			old_crtc_state->bigjoiner_linked_crtc;
+		const struct intel_crtc_state *old_slave_crtc_state =
+			intel_atomic_get_old_crtc_state(state, slave);
+
+		intel_crtc_vblank_off(old_slave_crtc_state);
+		trace_intel_pipe_disable(slave);
+
+		intel_dsc_disable(old_slave_crtc_state);
+		skl_scaler_disable(old_slave_crtc_state);
+	}
+
 	/*
 	 * When called from DP MST code:
 	 * - old_conn_state will be NULL
@@ -4037,7 +4055,8 @@  static void intel_enable_ddi(struct intel_atomic_state *state,
 {
 	drm_WARN_ON(state->base.dev, crtc_state->has_pch_encoder);
 
-	intel_ddi_enable_transcoder_func(encoder, crtc_state);
+	if (!crtc_state->bigjoiner_slave)
+		intel_ddi_enable_transcoder_func(encoder, crtc_state);
 
 	intel_enable_pipe(crtc_state);
 
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 338fa48a144d..1be77ba2f9cf 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -7232,6 +7232,45 @@  static void hsw_set_frame_start_delay(const struct intel_crtc_state *crtc_state)
 	intel_de_write(dev_priv, reg, val);
 }
 
+static void icl_ddi_bigjoiner_pre_enable(struct intel_atomic_state *state,
+					 const struct intel_crtc_state *crtc_state)
+{
+	struct intel_crtc *master = to_intel_crtc(crtc_state->uapi.crtc);
+	struct intel_crtc_state *master_crtc_state;
+	struct drm_connector_state *conn_state;
+	struct drm_connector *conn;
+	struct intel_encoder *encoder = NULL;
+	int i;
+
+	if (crtc_state->bigjoiner_slave)
+		master = crtc_state->bigjoiner_linked_crtc;
+
+	master_crtc_state = intel_atomic_get_new_crtc_state(state, master);
+
+	for_each_new_connector_in_state(&state->base, conn, conn_state, i) {
+		if (conn_state->crtc != &master->base)
+			continue;
+
+		encoder = to_intel_encoder(conn_state->best_encoder);
+		break;
+	}
+
+	if (!crtc_state->bigjoiner_slave) {
+		/* need to enable VDSC, which we skipped in pre-enable */
+		intel_dsc_enable(encoder, crtc_state);
+	} else {
+		/*
+                 * Enable sequence steps 1-7 on bigjoiner master
+                 */
+		intel_encoders_pre_pll_enable(state, master);
+		intel_enable_shared_dpll(master_crtc_state);
+		intel_encoders_pre_enable(state, master);
+
+		/* and DSC on slave */
+		intel_dsc_enable(NULL, crtc_state);
+	}
+}
+
 static void hsw_crtc_enable(struct intel_atomic_state *state,
 			    struct intel_crtc *crtc)
 {
@@ -7245,34 +7284,39 @@  static void hsw_crtc_enable(struct intel_atomic_state *state,
 	if (drm_WARN_ON(&dev_priv->drm, crtc->active))
 		return;
 
-	intel_encoders_pre_pll_enable(state, crtc);
+	if (!new_crtc_state->bigjoiner) {
+		intel_encoders_pre_pll_enable(state, crtc);
 
-	if (new_crtc_state->shared_dpll)
-		intel_enable_shared_dpll(new_crtc_state);
-
-	intel_encoders_pre_enable(state, crtc);
+		if (new_crtc_state->shared_dpll)
+			intel_enable_shared_dpll(new_crtc_state);
 
-	if (!transcoder_is_dsi(cpu_transcoder))
-		intel_set_transcoder_timings(new_crtc_state);
+		intel_encoders_pre_enable(state, crtc);
+	} else {
+		icl_ddi_bigjoiner_pre_enable(state, new_crtc_state);
+	}
 
 	intel_set_pipe_src_size(new_crtc_state);
+	if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
+		bdw_set_pipemisc(new_crtc_state);
 
-	if (cpu_transcoder != TRANSCODER_EDP &&
-	    !transcoder_is_dsi(cpu_transcoder))
-		intel_de_write(dev_priv, PIPE_MULT(cpu_transcoder),
-			       new_crtc_state->pixel_multiplier - 1);
+	if (!new_crtc_state->bigjoiner_slave || !transcoder_is_dsi(cpu_transcoder)){
+		if (!transcoder_is_dsi(cpu_transcoder))
+		intel_set_transcoder_timings(new_crtc_state);
 
-	if (new_crtc_state->has_pch_encoder)
-		intel_cpu_transcoder_set_m_n(new_crtc_state,
-					     &new_crtc_state->fdi_m_n, NULL);
+		if (cpu_transcoder != TRANSCODER_EDP &&
+		    !transcoder_is_dsi(cpu_transcoder))
+			intel_de_write(dev_priv, PIPE_MULT(cpu_transcoder),
+				       new_crtc_state->pixel_multiplier - 1);
+
+		if (new_crtc_state->has_pch_encoder)
+			intel_cpu_transcoder_set_m_n(new_crtc_state,
+						     &new_crtc_state->fdi_m_n, NULL);
 
-	if (!transcoder_is_dsi(cpu_transcoder)) {
 		hsw_set_frame_start_delay(new_crtc_state);
-		hsw_set_pipeconf(new_crtc_state);
 	}
 
-	if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
-		bdw_set_pipemisc(new_crtc_state);
+	if (!transcoder_is_dsi(cpu_transcoder))
+		hsw_set_pipeconf(new_crtc_state);
 
 	crtc->active = true;
 
@@ -7308,6 +7352,11 @@  static void hsw_crtc_enable(struct intel_atomic_state *state,
 	if (INTEL_GEN(dev_priv) >= 11)
 		icl_pipe_mbus_enable(crtc);
 
+	if (new_crtc_state->bigjoiner_slave) {
+		trace_intel_pipe_enable(crtc);
+		intel_crtc_vblank_on(new_crtc_state);
+	}
+
 	intel_encoders_enable(state, crtc);
 
 	if (psl_clkgate_wa) {
@@ -15683,6 +15732,9 @@  static void intel_enable_crtc(struct intel_atomic_state *state,
 
 	dev_priv->display.crtc_enable(state, crtc);
 
+	if (new_crtc_state->bigjoiner_slave)
+		return;
+
 	/* vblanks work again, re-enable pipe CRC. */
 	intel_crtc_enable_pipe_crc(crtc);
 }
@@ -15747,8 +15799,21 @@  static void intel_old_crtc_state_disables(struct intel_atomic_state *state,
 {
 	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
 
+	drm_WARN_ON(&dev_priv->drm, old_crtc_state->bigjoiner_slave);
+
 	intel_crtc_disable_planes(state, crtc);
 
+	/*
+	 * We still need special handling for disabling bigjoiner master
+	 * and slaves since for slave we do not have encoder or plls
+	 * so we dont need to disable those.
+	 */
+	if (old_crtc_state->bigjoiner) {
+		intel_crtc_disable_planes(state,
+					  old_crtc_state->bigjoiner_linked_crtc);
+		old_crtc_state->bigjoiner_linked_crtc->active = false;
+	}
+
 	/*
 	 * We need to disable pipe CRC before disabling the pipe,
 	 * or we race against vblank off.
@@ -15777,7 +15842,7 @@  static void intel_commit_modeset_disables(struct intel_atomic_state *state)
 	/* Only disable port sync and MST slaves */
 	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
 					    new_crtc_state, i) {
-		if (!needs_modeset(new_crtc_state))
+		if (!needs_modeset(new_crtc_state) || old_crtc_state->bigjoiner)
 			continue;
 
 		if (!old_crtc_state->hw.active)
@@ -15802,10 +15867,18 @@  static void intel_commit_modeset_disables(struct intel_atomic_state *state)
 	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
 					    new_crtc_state, i) {
 		if (!needs_modeset(new_crtc_state) ||
-		    (handled & BIT(crtc->pipe)))
+		    (handled & BIT(crtc->pipe)) ||
+		    old_crtc_state->bigjoiner_slave)
 			continue;
 
 		intel_pre_plane_update(state, crtc);
+		if (old_crtc_state->bigjoiner) {
+			struct intel_crtc *slave =
+				old_crtc_state->bigjoiner_linked_crtc;
+
+			intel_pre_plane_update(state, slave);
+		}
+
 		if (old_crtc_state->hw.active)
 			intel_old_crtc_state_disables(state, old_crtc_state,
 						      new_crtc_state, crtc);
@@ -15903,7 +15976,8 @@  static void skl_commit_modeset_enables(struct intel_atomic_state *state)
 			continue;
 
 		if (intel_dp_mst_is_slave_trans(new_crtc_state) ||
-		    is_trans_port_sync_master(new_crtc_state))
+		    is_trans_port_sync_master(new_crtc_state) ||
+		    (new_crtc_state->bigjoiner && !new_crtc_state->bigjoiner_slave))
 			continue;
 
 		modeset_pipes &= ~BIT(pipe);
@@ -15913,7 +15987,7 @@  static void skl_commit_modeset_enables(struct intel_atomic_state *state)
 
 	/*
 	 * Then we enable all remaining pipes that depend on other
-	 * pipes: MST slaves and port sync masters.
+	 * pipes: MST slaves and port sync masters, big joiner master
 	 */
 	for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
 		enum pipe pipe = crtc->pipe;