All of lore.kernel.org
 help / color / mirror / Atom feed
From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
To: Matt Roper <matthew.d.roper@intel.com>
Cc: intel-gfx@lists.freedesktop.org
Subject: Re: [PATCH 12/23] drm/i915: Enable big joiner support in enable and disable sequences.
Date: Fri, 27 Sep 2019 10:25:28 +0200	[thread overview]
Message-ID: <ad75784e-dca4-40f8-238f-e1064d076325@linux.intel.com> (raw)
In-Reply-To: <20190926235435.GZ1869@mdroper-desk1.amr.corp.intel.com>

Op 27-09-2019 om 01:54 schreef Matt Roper:
> On Wed, Sep 25, 2019 at 10:18:19PM -0700, Matt Roper wrote:
>> On Fri, Sep 20, 2019 at 01:42:24PM +0200, Maarten Lankhorst wrote:
>>> Make vdsc work when no output is enabled. The big joiner needs VDSC
>>> on the slave, so enable it and set the appropriate bits.
>>> Also update timestamping constants, because slave crtc's are not
>>> updated in drm_atomic_helper_update_legacy_modeset_state().
>>>
>>> This should be enough to bring up CRTC's in a big joiner configuration,
>>> without any plane configuration on the second pipe yet.
>>>
>>> HOWEVER, we bring up the crtc's in the wrong order. We need to make
>>> sure that the master crtc is brought up after the slave crtc, we
>>> don't do that yet. This is done correctly later in this series.
>>>
>>> The next steps are to add atomic commit, and make sure we enable and
>>> update both master and slave in the correct order.
>>>
>>> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
>> A couple minor comments inline below, but I didn't see any clear
>> problems with this patch so
>>
>> Acked-by: Matt Roper <matthew.d.roper@intel.com>
>>
>> However there's a lot of pretty complicated changes here in areas that
>> I'm only vaguely familiar with, so I think it would be good if someone
>> like Manasi who's more familiar with this area of the code could look it
>> over.
>>
>>
>> Matt
>>
>>
>>> ---
>>>  drivers/gpu/drm/i915/display/intel_ddi.c      |  55 ++-
>>>  drivers/gpu/drm/i915/display/intel_display.c  | 402 ++++++++++++------
>>>  .../drm/i915/display/intel_display_types.h    |  17 +
>>>  drivers/gpu/drm/i915/display/intel_dp.c       |  18 +-
>>>  drivers/gpu/drm/i915/display/intel_vdsc.c     | 122 ++++--
>>>  drivers/gpu/drm/i915/display/intel_vdsc.h     |   2 +
>>>  6 files changed, 418 insertions(+), 198 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
>>> index c775fd205915..a26155f90261 100644
>>> --- a/drivers/gpu/drm/i915/display/intel_ddi.c
>>> +++ b/drivers/gpu/drm/i915/display/intel_ddi.c
>>> @@ -1694,6 +1694,13 @@ static void intel_ddi_clock_get(struct intel_encoder *encoder,
>>>  		skl_ddi_clock_get(encoder, pipe_config);
>>>  	else if (INTEL_GEN(dev_priv) <= 8)
>>>  		hsw_ddi_clock_get(encoder, pipe_config);
>>> +
>>> +	if (pipe_config->bigjoiner) {
>>> +		pipe_config->hw.transcoder_mode.crtc_clock =
>>> +			pipe_config->hw.adjusted_mode.crtc_clock;
>>> +
>>> +		pipe_config->hw.adjusted_mode.crtc_clock /= 2;
>>> +	}
>>>  }
>>>  
>>>  void intel_ddi_set_pipe_settings(const struct intel_crtc_state *crtc_state)
>>> @@ -2176,13 +2183,6 @@ static void intel_ddi_get_power_domains(struct intel_encoder *encoder,
>>>  	    intel_phy_is_tc(dev_priv, phy))
>>>  		intel_display_power_get(dev_priv,
>>>  					intel_ddi_main_link_aux_domain(dig_port));
>>> -
>>> -	/*
>>> -	 * VDSC power is needed when DSC is enabled
>>> -	 */
>>> -	if (crtc_state->dsc_params.compression_enable)
>>> -		intel_display_power_get(dev_priv,
>>> -					intel_dsc_power_domain(crtc_state));
>>>  }
>>>  
>>>  void intel_ddi_enable_pipe_clock(const struct intel_crtc_state *crtc_state)
>>> @@ -3290,7 +3290,8 @@ static void tgl_ddi_pre_enable_dp(struct intel_encoder *encoder,
>>>  
>>>  	/* 7.l */
>>>  	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_encoder *encoder,
>>> @@ -3361,7 +3362,8 @@ static void hsw_ddi_pre_enable_dp(struct intel_encoder *encoder,
>>>  	if (!is_mst)
>>>  		intel_ddi_enable_pipe_clock(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_encoder *encoder,
>>> @@ -3972,19 +3974,18 @@ void intel_ddi_compute_min_voltage_level(struct drm_i915_private *dev_priv,
>>>  		crtc_state->min_voltage_level = 2;
>>>  }
>>>  
>>> -void intel_ddi_get_config(struct intel_encoder *encoder,
>>> -			  struct intel_crtc_state *pipe_config)
>>> +static void intel_ddi_read_func_ctl(struct intel_encoder *encoder,
>>> +				    struct intel_crtc_state *pipe_config)
>>>  {
>>>  	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>>>  	struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->uapi.crtc);
>>>  	enum transcoder cpu_transcoder = pipe_config->cpu_transcoder;
>>>  	u32 temp, flags = 0;
>>>  
>>> -	/* XXX: DSI transcoder paranoia */
>>> -	if (WARN_ON(transcoder_is_dsi(cpu_transcoder)))
>>> +	temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
>>> +	if (!(temp & TRANS_DDI_FUNC_ENABLE))
>>>  		return;
>>>  
>>> -	temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
>>>  	if (temp & TRANS_DDI_PHSYNC)
>>>  		flags |= DRM_MODE_FLAG_PHSYNC;
>>>  	else
>>> @@ -4066,6 +4067,29 @@ void intel_ddi_get_config(struct intel_encoder *encoder,
>>>  	default:
>>>  		break;
>>>  	}
>>> +}
>>> +
>>> +void intel_ddi_get_config(struct intel_encoder *encoder,
>>> +			  struct intel_crtc_state *pipe_config)
>>> +{
>>> +	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>>> +	enum transcoder cpu_transcoder = pipe_config->cpu_transcoder;
>>> +
>>> +	/* XXX: DSI transcoder paranoia */
>>> +	if (WARN_ON(transcoder_is_dsi(cpu_transcoder)))
>>> +		return;
>>> +
>>> +	intel_ddi_read_func_ctl(encoder, pipe_config);
>>> +	if (pipe_config->bigjoiner_slave) {
>>> +		/* read out pipe settings from master */
>>> +		enum transcoder save = pipe_config->cpu_transcoder;
>>> +
>>> +		 /* Our own transcoder needs to be disabled when reading it in intel_ddi_read_func_ctl() */
>>> +		WARN_ON(pipe_config->output_types);
>>> +		pipe_config->cpu_transcoder = (enum transcoder)pipe_config->bigjoiner_linked_crtc->pipe;
>>> +		intel_ddi_read_func_ctl(encoder, pipe_config);
>>> +		pipe_config->cpu_transcoder = save;
>>> +	}
>>>  
>>>  	pipe_config->has_audio =
>>>  		intel_ddi_is_audio_enabled(dev_priv, cpu_transcoder);
>>> @@ -4090,7 +4114,8 @@ void intel_ddi_get_config(struct intel_encoder *encoder,
>>>  		dev_priv->vbt.edp.bpp = pipe_config->pipe_bpp;
>>>  	}
>>>  
>>> -	intel_ddi_clock_get(encoder, pipe_config);
>>> +	if (!pipe_config->bigjoiner_slave)
>>> +		intel_ddi_clock_get(encoder, pipe_config);
>>>  
>>>  	if (IS_GEN9_LP(dev_priv))
>>>  		pipe_config->lane_lat_optim_mask =
>>> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
>>> index 143d531c4c81..8c08c4914c9b 100644
>>> --- a/drivers/gpu/drm/i915/display/intel_display.c
>>> +++ b/drivers/gpu/drm/i915/display/intel_display.c
>>> @@ -6449,6 +6449,45 @@ static void icl_pipe_mbus_enable(struct intel_crtc *crtc)
>>>  	I915_WRITE(PIPE_MBUS_DBOX_CTL(pipe), val);
>>>  }
>>>  
>>> +static void icl_ddi_bigjoiner_pre_enable(struct intel_atomic_state *state,
>>> +					 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
>>> +		 */
>> I'd extend this comment to indicate that we do this on the slave (using
>> the master's state, transcoder, and DDI) because the [will] program the
>> slave CRTC before the master.
>>
>>> +		intel_encoders_pre_pll_enable(master, master_crtc_state, state);
>>> +		intel_enable_shared_dpll(master_crtc_state);
>>> +		intel_encoders_pre_enable(master, master_crtc_state, state);
>>> +
>>> +		/* and DSC on slave */
>>> +		intel_dsc_enable(NULL, crtc_state);
>>> +	}
>>> +}
>>> +
>>>  static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
>>>  				struct intel_atomic_state *state)
>>>  {
>>> @@ -6462,37 +6501,38 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
>>>  	if (WARN_ON(intel_crtc->active))
>>>  		return;
>>>  
>>> -	intel_encoders_pre_pll_enable(intel_crtc, pipe_config, state);
>>> +	if (!pipe_config->bigjoiner) {
>>> +		intel_encoders_pre_pll_enable(intel_crtc, pipe_config, state);
>>>  
>>> -	if (pipe_config->shared_dpll)
>>> -		intel_enable_shared_dpll(pipe_config);
>>> +		if (pipe_config->shared_dpll)
>>> +			intel_enable_shared_dpll(pipe_config);
>>>  
>>> -	intel_encoders_pre_enable(intel_crtc, pipe_config, state);
>>> +		intel_encoders_pre_enable(intel_crtc, pipe_config, state);
>>> +	} else {
>>> +		icl_ddi_bigjoiner_pre_enable(state, pipe_config);
>>> +	}
>>>  
>>> -	if (intel_crtc_has_dp_encoder(pipe_config))
>>> -		intel_dp_set_m_n(pipe_config, M1_N1);
>>> +	intel_set_pipe_src_size(pipe_config);
>>> +	if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
>>> +		bdw_set_pipemisc(pipe_config);
>>>  
>>> -	if (!transcoder_is_dsi(cpu_transcoder))
>>> -		intel_set_pipe_timings(pipe_config);
>>> +	if (!pipe_config->bigjoiner_slave && !transcoder_is_dsi(cpu_transcoder)) {
>>> +		if (intel_crtc_has_dp_encoder(pipe_config))
>>> +			intel_dp_set_m_n(pipe_config, M1_N1);
>>>  
>>> -	intel_set_pipe_src_size(pipe_config);
>>> +		intel_set_pipe_timings(pipe_config);
>>>  
>>> -	if (cpu_transcoder != TRANSCODER_EDP &&
>>> -	    !transcoder_is_dsi(cpu_transcoder)) {
>>> -		I915_WRITE(PIPE_MULT(cpu_transcoder),
>>> -			   pipe_config->pixel_multiplier - 1);
>>> -	}
>>> +		if (cpu_transcoder != TRANSCODER_EDP)
>>> +			I915_WRITE(PIPE_MULT(cpu_transcoder),
>>> +				  pipe_config->pixel_multiplier - 1);
>>>  
>>> -	if (pipe_config->has_pch_encoder) {
>>> -		intel_cpu_transcoder_set_m_n(pipe_config,
>>> -					     &pipe_config->fdi_m_n, NULL);
>>> -	}
>>> +		if (pipe_config->has_pch_encoder) {
>>> +			intel_cpu_transcoder_set_m_n(pipe_config,
>>> +						    &pipe_config->fdi_m_n, NULL);
>>> +		}
>>>  
>>> -	if (!transcoder_is_dsi(cpu_transcoder))
>>>  		haswell_set_pipeconf(pipe_config);
>>> -
>>> -	if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
>>> -		bdw_set_pipemisc(pipe_config);
>>> +	}
>>>  
>>>  	intel_crtc->active = true;
>>>  
>>> @@ -6520,9 +6560,11 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
>>>  	if (INTEL_GEN(dev_priv) >= 11)
>>>  		icl_set_pipe_chicken(intel_crtc);
>>>  
>>> -	intel_ddi_set_pipe_settings(pipe_config);
>>> -	if (!transcoder_is_dsi(cpu_transcoder))
>>> +	if (!pipe_config->bigjoiner_slave && !transcoder_is_dsi(cpu_transcoder)) {
>>> +		intel_ddi_set_pipe_settings(pipe_config);
>>> +
>>>  		intel_ddi_enable_transcoder_func(pipe_config);
>>> +	}
>>>  
>>>  	if (dev_priv->display.initial_watermarks != NULL)
>>>  		dev_priv->display.initial_watermarks(state, pipe_config);
>>> @@ -6531,8 +6573,10 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
>>>  		icl_pipe_mbus_enable(intel_crtc);
>>>  
>>>  	/* XXX: Do the pipe assertions at the right place for BXT DSI. */
>>> -	if (!transcoder_is_dsi(cpu_transcoder))
>>> +	if (!pipe_config->bigjoiner_slave && !transcoder_is_dsi(cpu_transcoder))
>>>  		intel_enable_pipe(pipe_config);
>>> +	else
>>> +		trace_intel_pipe_enable(intel_crtc);
>>>  
>>>  	if (pipe_config->has_pch_encoder)
>>>  		lpt_pch_enable(state, pipe_config);
>>> @@ -6663,9 +6707,27 @@ static void haswell_crtc_disable(struct intel_crtc_state *old_crtc_state,
>>>  	else
>>>  		ironlake_pfit_disable(old_crtc_state);
>>>  
>>> -	intel_encoders_post_disable(intel_crtc, old_crtc_state, state);
>>> +	if (old_crtc_state->bigjoiner) {
>>> +		struct intel_crtc *master;
>>> +		struct intel_crtc_state *master_crtc_state;
>>>  
>>> -	intel_encoders_post_pll_disable(intel_crtc, old_crtc_state, state);
>>> +		/* ports are disabled from the slave, after it deconfigures */
>>> +		if (!old_crtc_state->bigjoiner_slave)
>>> +			return;
>>> +
>>> +		master = old_crtc_state->bigjoiner_linked_crtc;
>>> +		master_crtc_state = intel_atomic_get_old_crtc_state(state, master);
>>> +
>>> +		intel_ddi_disable_pipe_clock(old_crtc_state);
>>> +
>>> +		/* disable ports on the master crtc */
>>> +		intel_encoders_post_disable(master, master_crtc_state, state);
>>> +		intel_encoders_post_pll_disable(master, master_crtc_state, state);
>>> +	} else {
>>> +		intel_encoders_post_disable(intel_crtc, old_crtc_state, state);
>>> +
>>> +		intel_encoders_post_pll_disable(intel_crtc, old_crtc_state, state);
>>> +	}
>>>  }
>>>  
>>>  static void i9xx_pfit_enable(const struct intel_crtc_state *crtc_state)
>>> @@ -6829,6 +6891,9 @@ static u64 get_crtc_power_domains(struct intel_crtc_state *crtc_state)
>>>  	if (crtc_state->shared_dpll)
>>>  		mask |= BIT_ULL(POWER_DOMAIN_DISPLAY_CORE);
>>>  
>>> +	if (crtc_state->dsc_params.compression_enable)
>>> +		mask |= BIT_ULL(intel_dsc_power_domain(crtc_state));
>>> +
>>>  	return mask;
>>>  }
>>>  
>>> @@ -7417,6 +7482,19 @@ static u32 ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config)
>>>  	return pixel_rate;
>>>  }
>>>  
>>> +static void intel_encoder_get_config(struct intel_encoder *encoder,
>>> +				     struct intel_crtc_state *crtc_state)
>>> +{
>>> +	encoder->get_config(encoder, crtc_state);
>>> +
>>> +	crtc_state->hw.transcoder_mode.flags = crtc_state->hw.adjusted_mode.flags;
>>> +
>>> +	/* if transcoder clock is not set, assume same as adjusted_mode clock */
>>> +	if (!crtc_state->hw.transcoder_mode.crtc_clock)
>>> +		crtc_state->hw.transcoder_mode.crtc_clock =
>>> +			crtc_state->hw.adjusted_mode.crtc_clock;
>>> +}
>>> +
>>>  static void intel_crtc_compute_pixel_rate(struct intel_crtc_state *crtc_state)
>>>  {
>>>  	struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
>>> @@ -8265,6 +8343,24 @@ static void intel_get_pipe_timings(struct intel_crtc *crtc,
>>>  		pipe_config->hw.adjusted_mode.crtc_vtotal += 1;
>>>  		pipe_config->hw.adjusted_mode.crtc_vblank_end += 1;
>>>  	}
>>> +
>>> +	pipe_config->hw.transcoder_mode = pipe_config->hw.adjusted_mode;
>>> +	if (pipe_config->bigjoiner) {
>>> +		struct drm_display_mode *adjusted_mode =
>>> +			&pipe_config->hw.adjusted_mode;
>>> +
>>> +		/*
>>> +		  * transcoder is programmed to the full mode,
>>> +		  * but pipje timings are half of the transcoder mode
>>> +		  */
>>> +		adjusted_mode->crtc_hdisplay /= 2;
>>> +		adjusted_mode->crtc_hblank_start /= 2;
>>> +		adjusted_mode->crtc_hblank_end /= 2;
>>> +		adjusted_mode->crtc_hsync_start /= 2;
>>> +		adjusted_mode->crtc_hsync_end /= 2;
>>> +		adjusted_mode->crtc_htotal /= 2;
>>> +		adjusted_mode->crtc_hskew /= 2;
>>> +	}
>>>  }
>>>  
>>>  static void intel_get_pipe_src_size(struct intel_crtc *crtc,
>>> @@ -8285,20 +8381,22 @@ static void intel_get_pipe_src_size(struct intel_crtc *crtc,
>>>  void intel_mode_from_pipe_config(struct drm_display_mode *mode,
>>>  				 struct intel_crtc_state *pipe_config)
>>>  {
>>> -	mode->hdisplay = pipe_config->hw.adjusted_mode.crtc_hdisplay;
>>> -	mode->htotal = pipe_config->hw.adjusted_mode.crtc_htotal;
>>> -	mode->hsync_start = pipe_config->hw.adjusted_mode.crtc_hsync_start;
>>> -	mode->hsync_end = pipe_config->hw.adjusted_mode.crtc_hsync_end;
>>> +	struct drm_display_mode *hw_mode = &pipe_config->hw.transcoder_mode;
>>>  
>>> -	mode->vdisplay = pipe_config->hw.adjusted_mode.crtc_vdisplay;
>>> -	mode->vtotal = pipe_config->hw.adjusted_mode.crtc_vtotal;
>>> -	mode->vsync_start = pipe_config->hw.adjusted_mode.crtc_vsync_start;
>>> -	mode->vsync_end = pipe_config->hw.adjusted_mode.crtc_vsync_end;
>>> +	mode->hdisplay = hw_mode->crtc_hdisplay;
>>> +	mode->htotal = hw_mode->crtc_htotal;
>>> +	mode->hsync_start = hw_mode->crtc_hsync_start;
>>> +	mode->hsync_end = hw_mode->crtc_hsync_end;
>>>  
>>> -	mode->flags = pipe_config->hw.adjusted_mode.flags;
>>> +	mode->vdisplay = hw_mode->crtc_vdisplay;
>>> +	mode->vtotal = hw_mode->crtc_vtotal;
>>> +	mode->vsync_start = hw_mode->crtc_vsync_start;
>>> +	mode->vsync_end = hw_mode->crtc_vsync_end;
>>> +
>>> +	mode->flags = hw_mode->flags;
>>>  	mode->type = DRM_MODE_TYPE_DRIVER;
>>>  
>>> -	mode->clock = pipe_config->hw.adjusted_mode.crtc_clock;
>>> +	mode->clock = hw_mode->crtc_clock;
>>>  
>>>  	mode->hsync = drm_mode_hsync(mode);
>>>  	mode->vrefresh = drm_mode_vrefresh(mode);
>>> @@ -10385,6 +10483,8 @@ static void haswell_get_ddi_port_state(struct intel_crtc *crtc,
>>>  	u32 tmp;
>>>  
>>>  	tmp = I915_READ(TRANS_DDI_FUNC_CTL(pipe_config->cpu_transcoder));
>>> +	if (!(tmp & TRANS_DDI_FUNC_ENABLE))
>>> +		return;
>>>  
>>>  	if (INTEL_GEN(dev_priv) >= 12)
>>>  		port = TGL_TRANS_DDI_FUNC_CTL_VAL_TO_PORT(tmp);
>>> @@ -10455,11 +10555,19 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
>>>  		WARN_ON(active);
>>>  		active = true;
>>>  	}
>>> +	intel_dsc_get_config(pipe_config);
>>>  
>>> -	if (!active)
>>> -		goto out;
>>> +	if (!active) {
>>> +		/* bigjoiner slave doesn't enable transcoder */
>>> +		if (!pipe_config->bigjoiner_slave)
>>> +			goto out;
>>> +
>>> +		active = true;
>>> +		pipe_config->pixel_multiplier = 1;
>>>  
>>> -	if (!transcoder_is_dsi(pipe_config->cpu_transcoder) ||
>>> +		/* we cannot read out most state, so don't bother.. */
>>> +		pipe_config->quirks |= PIPE_CONFIG_QUIRK_BIGJOINER_SLAVE;
>>> +	} else if (!transcoder_is_dsi(pipe_config->cpu_transcoder) ||
>>>  	    INTEL_GEN(dev_priv) >= 11) {
>>>  		haswell_get_ddi_port_state(crtc, pipe_config);
>>>  		intel_get_pipe_timings(crtc, pipe_config);
>>> @@ -10513,7 +10621,10 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
>>>  		}
>>>  	}
>>>  
>>> -	if (pipe_config->cpu_transcoder != TRANSCODER_EDP &&
>>> +	if (pipe_config->bigjoiner_slave) {
>>> +		/* Cannot be read out as a slave, set to 0. */
>>> +		pipe_config->pixel_multiplier = 0;
>>> +	} else if (pipe_config->cpu_transcoder != TRANSCODER_EDP &&
>>>  	    !transcoder_is_dsi(pipe_config->cpu_transcoder)) {
>>>  		pipe_config->pixel_multiplier =
>>>  			I915_READ(PIPE_MULT(pipe_config->cpu_transcoder)) + 1;
>>> @@ -11468,7 +11579,7 @@ intel_encoder_current_mode(struct intel_encoder *encoder)
>>>  		return NULL;
>>>  	}
>>>  
>>> -	encoder->get_config(encoder, crtc_state);
>>> +	intel_encoder_get_config(encoder, crtc_state);
>>>  
>>>  	intel_mode_from_pipe_config(mode, crtc_state);
>>>  
>>> @@ -12285,9 +12396,11 @@ static void copy_uapi_to_hw_state(struct intel_crtc_state *crtc_state)
>>>  
>>>  static void copy_hw_to_uapi_state(struct intel_crtc_state *crtc_state)
>>>  {
>>> -	crtc_state->uapi.enable = crtc_state->hw.enable;
>>> -	crtc_state->uapi.active = crtc_state->hw.active;
>>> -	crtc_state->uapi.mode = crtc_state->hw.mode;
>>> +	if (!crtc_state->bigjoiner_slave) {
>>> +		crtc_state->uapi.enable = crtc_state->hw.enable;
>>> +		crtc_state->uapi.active = crtc_state->hw.active;
>>> +		crtc_state->uapi.mode = crtc_state->hw.mode;
>>> +	}
>>>  	crtc_state->uapi.adjusted_mode = crtc_state->hw.transcoder_mode;
>>>  }
>>>  
>>> @@ -12318,6 +12431,7 @@ copy_bigjoiner_crtc_state(struct intel_crtc_state *crtc_state,
>>>  	crtc_state->hw.active = from_crtc_state->hw.active;
>>>  	crtc_state->hw.mode = from_crtc_state->hw.mode;
>>>  	crtc_state->hw.adjusted_mode = from_crtc_state->hw.adjusted_mode;
>>> +	crtc_state->hw.transcoder_mode = from_crtc_state->hw.transcoder_mode;
>>>  
>>>  	/* Some fixups */
>>>  	crtc_state->uapi.mode_changed = from_crtc_state->uapi.mode_changed;
>>> @@ -12833,19 +12947,41 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
>>>  
>>>  	PIPE_CONF_CHECK_X(output_types);
>>>  
>>> -	PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hdisplay);
>>> -	PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_htotal);
>>> -	PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hblank_start);
>>> -	PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hblank_end);
>>> -	PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hsync_start);
>>> -	PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hsync_end);
>>> -
>>> -	PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vdisplay);
>>> -	PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vtotal);
>>> -	PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vblank_start);
>>> -	PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vblank_end);
>>> -	PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vsync_start);
>>> -	PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vsync_end);
>>> +	if (!PIPE_CONF_QUIRK(PIPE_CONFIG_QUIRK_BIGJOINER_SLAVE)) {
>>> +		/* bigjoiner mode = transcoder mode / 2, for calculations */
>>> +		PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hdisplay);
>>> +		PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_htotal);
>>> +		PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vdisplay);
>>> +		PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vtotal);
>>> +
>>> +		PIPE_CONF_CHECK_I(hw.transcoder_mode.crtc_hdisplay);
>>> +		PIPE_CONF_CHECK_I(hw.transcoder_mode.crtc_htotal);
>>> +		PIPE_CONF_CHECK_I(hw.transcoder_mode.crtc_hblank_start);
>>> +		PIPE_CONF_CHECK_I(hw.transcoder_mode.crtc_hblank_end);
>>> +		PIPE_CONF_CHECK_I(hw.transcoder_mode.crtc_hsync_start);
>>> +		PIPE_CONF_CHECK_I(hw.transcoder_mode.crtc_hsync_end);
>>> +
>>> +		PIPE_CONF_CHECK_I(hw.transcoder_mode.crtc_vdisplay);
>>> +		PIPE_CONF_CHECK_I(hw.transcoder_mode.crtc_vtotal);
>>> +		PIPE_CONF_CHECK_I(hw.transcoder_mode.crtc_vblank_start);
>>> +		PIPE_CONF_CHECK_I(hw.transcoder_mode.crtc_vblank_end);
>>> +		PIPE_CONF_CHECK_I(hw.transcoder_mode.crtc_vsync_start);
>>> +		PIPE_CONF_CHECK_I(hw.transcoder_mode.crtc_vsync_end);
>>> +
>>> +		PIPE_CONF_CHECK_FLAGS(hw.transcoder_mode.flags,
>>> +				      DRM_MODE_FLAG_INTERLACE);
>>> +
>>> +		if (!PIPE_CONF_QUIRK(PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS)) {
>>> +			PIPE_CONF_CHECK_FLAGS(hw.transcoder_mode.flags,
>>> +					      DRM_MODE_FLAG_PHSYNC);
>>> +			PIPE_CONF_CHECK_FLAGS(hw.transcoder_mode.flags,
>>> +					      DRM_MODE_FLAG_NHSYNC);
>>> +			PIPE_CONF_CHECK_FLAGS(hw.transcoder_mode.flags,
>>> +					      DRM_MODE_FLAG_PVSYNC);
>>> +			PIPE_CONF_CHECK_FLAGS(hw.transcoder_mode.flags,
>>> +					      DRM_MODE_FLAG_NVSYNC);
>>> +		}
>>> +	}
>>>  
>>>  	PIPE_CONF_CHECK_I(pixel_multiplier);
>>>  	PIPE_CONF_CHECK_I(output_format);
>>> @@ -12857,24 +12993,11 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
>>>  	PIPE_CONF_CHECK_BOOL(hdmi_scrambling);
>>>  	PIPE_CONF_CHECK_BOOL(hdmi_high_tmds_clock_ratio);
>>>  	PIPE_CONF_CHECK_BOOL(has_infoframe);
>>> -	PIPE_CONF_CHECK_BOOL(fec_enable);
>>> +	if (!PIPE_CONF_QUIRK(PIPE_CONFIG_QUIRK_BIGJOINER_SLAVE))
>>> +		PIPE_CONF_CHECK_BOOL(fec_enable);
>>>  
>>>  	PIPE_CONF_CHECK_BOOL_INCOMPLETE(has_audio);
>>>  
>>> -	PIPE_CONF_CHECK_FLAGS(hw.adjusted_mode.flags,
>>> -			      DRM_MODE_FLAG_INTERLACE);
>>> -
>>> -	if (!PIPE_CONF_QUIRK(PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS)) {
>>> -		PIPE_CONF_CHECK_FLAGS(hw.adjusted_mode.flags,
>>> -				      DRM_MODE_FLAG_PHSYNC);
>>> -		PIPE_CONF_CHECK_FLAGS(hw.adjusted_mode.flags,
>>> -				      DRM_MODE_FLAG_NHSYNC);
>>> -		PIPE_CONF_CHECK_FLAGS(hw.adjusted_mode.flags,
>>> -				      DRM_MODE_FLAG_PVSYNC);
>>> -		PIPE_CONF_CHECK_FLAGS(hw.adjusted_mode.flags,
>>> -				      DRM_MODE_FLAG_NVSYNC);
>>> -	}
>>> -
>>>  	PIPE_CONF_CHECK_X(gmch_pfit.control);
>>>  	/* pfit ratios are autocomputed by the hw on gen4+ */
>>>  	if (INTEL_GEN(dev_priv) < 4)
>>> @@ -12898,7 +13021,8 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
>>>  		}
>>>  
>>>  		PIPE_CONF_CHECK_I(scaler_state.scaler_id);
>>> -		PIPE_CONF_CHECK_CLOCK_FUZZY(pixel_rate);
>>> +		if (!PIPE_CONF_QUIRK(PIPE_CONFIG_QUIRK_BIGJOINER_SLAVE))
>>> +			PIPE_CONF_CHECK_CLOCK_FUZZY(pixel_rate);
>>>  
>>>  		PIPE_CONF_CHECK_X(gamma_mode);
>>>  		if (IS_CHERRYVIEW(dev_priv))
>>> @@ -12917,48 +13041,50 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
>>>  	PIPE_CONF_CHECK_BOOL(double_wide);
>>>  
>>>  	PIPE_CONF_CHECK_P(shared_dpll);
>>> +	if (!PIPE_CONF_QUIRK(PIPE_CONFIG_QUIRK_BIGJOINER_SLAVE)) {
>>>  	PIPE_CONF_CHECK_X(dpll_hw_state.dpll);
>> Missing indent on this line?
>>
>>> -	PIPE_CONF_CHECK_X(dpll_hw_state.dpll_md);
>>> -	PIPE_CONF_CHECK_X(dpll_hw_state.fp0);
>>> -	PIPE_CONF_CHECK_X(dpll_hw_state.fp1);
>>> -	PIPE_CONF_CHECK_X(dpll_hw_state.wrpll);
>>> -	PIPE_CONF_CHECK_X(dpll_hw_state.spll);
>>> -	PIPE_CONF_CHECK_X(dpll_hw_state.ctrl1);
>>> -	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.ebb0);
>>> -	PIPE_CONF_CHECK_X(dpll_hw_state.ebb4);
>>> -	PIPE_CONF_CHECK_X(dpll_hw_state.pll0);
>>> -	PIPE_CONF_CHECK_X(dpll_hw_state.pll1);
>>> -	PIPE_CONF_CHECK_X(dpll_hw_state.pll2);
>>> -	PIPE_CONF_CHECK_X(dpll_hw_state.pll3);
>>> -	PIPE_CONF_CHECK_X(dpll_hw_state.pll6);
>>> -	PIPE_CONF_CHECK_X(dpll_hw_state.pll8);
>>> -	PIPE_CONF_CHECK_X(dpll_hw_state.pll9);
>>> -	PIPE_CONF_CHECK_X(dpll_hw_state.pll10);
>>> -	PIPE_CONF_CHECK_X(dpll_hw_state.pcsdw12);
>>> -	PIPE_CONF_CHECK_X(dpll_hw_state.mg_refclkin_ctl);
>>> -	PIPE_CONF_CHECK_X(dpll_hw_state.mg_clktop2_coreclkctl1);
>>> -	PIPE_CONF_CHECK_X(dpll_hw_state.mg_clktop2_hsclkctl);
>>> -	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_div0);
>>> -	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_div1);
>>> -	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_lf);
>>> -	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_frac_lock);
>>> -	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_ssc);
>>> -	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_bias);
>>> -	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_tdc_coldst_bias);
>>> -
>>> -	PIPE_CONF_CHECK_X(dsi_pll.ctrl);
>>> -	PIPE_CONF_CHECK_X(dsi_pll.div);
>>> -
>>> -	if (IS_G4X(dev_priv) || INTEL_GEN(dev_priv) >= 5)
>>> -		PIPE_CONF_CHECK_I(pipe_bpp);
>>> -
>>> -	PIPE_CONF_CHECK_CLOCK_FUZZY(hw.adjusted_mode.crtc_clock);
>>> -	PIPE_CONF_CHECK_CLOCK_FUZZY(port_clock);
>>> -
>>> -	PIPE_CONF_CHECK_I(min_voltage_level);
>>> +		PIPE_CONF_CHECK_X(dpll_hw_state.dpll_md);
>>> +		PIPE_CONF_CHECK_X(dpll_hw_state.fp0);
>>> +		PIPE_CONF_CHECK_X(dpll_hw_state.fp1);
>>> +		PIPE_CONF_CHECK_X(dpll_hw_state.wrpll);
>>> +		PIPE_CONF_CHECK_X(dpll_hw_state.spll);
>>> +		PIPE_CONF_CHECK_X(dpll_hw_state.ctrl1);
>>> +		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.ebb0);
>>> +		PIPE_CONF_CHECK_X(dpll_hw_state.ebb4);
>>> +		PIPE_CONF_CHECK_X(dpll_hw_state.pll0);
>>> +		PIPE_CONF_CHECK_X(dpll_hw_state.pll1);
>>> +		PIPE_CONF_CHECK_X(dpll_hw_state.pll2);
>>> +		PIPE_CONF_CHECK_X(dpll_hw_state.pll3);
>>> +		PIPE_CONF_CHECK_X(dpll_hw_state.pll6);
>>> +		PIPE_CONF_CHECK_X(dpll_hw_state.pll8);
>>> +		PIPE_CONF_CHECK_X(dpll_hw_state.pll9);
>>> +		PIPE_CONF_CHECK_X(dpll_hw_state.pll10);
>>> +		PIPE_CONF_CHECK_X(dpll_hw_state.pcsdw12);
>>> +		PIPE_CONF_CHECK_X(dpll_hw_state.mg_refclkin_ctl);
>>> +		PIPE_CONF_CHECK_X(dpll_hw_state.mg_clktop2_coreclkctl1);
>>> +		PIPE_CONF_CHECK_X(dpll_hw_state.mg_clktop2_hsclkctl);
>>> +		PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_div0);
>>> +		PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_div1);
>>> +		PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_lf);
>>> +		PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_frac_lock);
>>> +		PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_ssc);
>>> +		PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_bias);
>>> +		PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_tdc_coldst_bias);
>>> +
>>> +		PIPE_CONF_CHECK_X(dsi_pll.ctrl);
>>> +		PIPE_CONF_CHECK_X(dsi_pll.div);
>>> +
>>> +		if (IS_G4X(dev_priv) || INTEL_GEN(dev_priv) >= 5)
>>> +			PIPE_CONF_CHECK_I(pipe_bpp);
>>> +
>>> +		PIPE_CONF_CHECK_CLOCK_FUZZY(hw.adjusted_mode.crtc_clock);
>>> +		PIPE_CONF_CHECK_CLOCK_FUZZY(port_clock);
>>> +
>>> +		PIPE_CONF_CHECK_I(min_voltage_level);
>>> +	}
>>>  
>>>  	PIPE_CONF_CHECK_X(infoframes.enable);
>>>  	PIPE_CONF_CHECK_X(infoframes.gcp);
>>> @@ -12967,6 +13093,12 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
>>>  	PIPE_CONF_CHECK_INFOFRAME(hdmi);
>>>  	PIPE_CONF_CHECK_INFOFRAME(drm);
>>>  
>>> +	PIPE_CONF_CHECK_BOOL(bigjoiner);
>>> +	PIPE_CONF_CHECK_BOOL(bigjoiner_slave);
>>> +	PIPE_CONF_CHECK_P(bigjoiner_linked_crtc);
>>> +	PIPE_CONF_CHECK_BOOL(dsc_params.compression_enable);
>>> +	PIPE_CONF_CHECK_BOOL(dsc_params.dsc_split);
>>> +
>>>  #undef PIPE_CONF_CHECK_X
>>>  #undef PIPE_CONF_CHECK_I
>>>  #undef PIPE_CONF_CHECK_BOOL
>>> @@ -13221,6 +13353,7 @@ verify_crtc_state(struct intel_crtc *crtc,
>>>  	struct intel_encoder *encoder;
>>>  	struct intel_crtc_state *pipe_config;
>>>  	struct drm_atomic_state *state;
>>> +	struct intel_crtc *master = crtc;
>>>  	bool active;
>>>  
>>>  	state = old_crtc_state->uapi.state;
>>> @@ -13250,7 +13383,10 @@ verify_crtc_state(struct intel_crtc *crtc,
>>>  			"(expected %i, found %i)\n",
>>>  			new_crtc_state->hw.active, crtc->active);
>>>  
>>> -	for_each_encoder_on_crtc(dev, &crtc->base, encoder) {
>>> +	if (new_crtc_state->bigjoiner_slave)
>>> +		master = new_crtc_state->bigjoiner_linked_crtc;
>>> +
>>> +	for_each_encoder_on_crtc(dev, &master->base, encoder) {
>>>  		enum pipe pipe;
>>>  
>>>  		active = encoder->get_hw_state(encoder, &pipe);
>>> @@ -13259,12 +13395,12 @@ verify_crtc_state(struct intel_crtc *crtc,
>>>  				encoder->base.base.id, active,
>>>  				new_crtc_state->hw.active);
>>>  
>>> -		I915_STATE_WARN(active && crtc->pipe != pipe,
>>> +		I915_STATE_WARN(active && master->pipe != pipe,
>>>  				"Encoder connected to wrong pipe %c\n",
>>>  				pipe_name(pipe));
>>>  
>>>  		if (active)
>>> -			encoder->get_config(encoder, pipe_config);
>>> +			intel_encoder_get_config(encoder, pipe_config);
>>>  	}
>>>  
>>>  	intel_crtc_compute_pixel_rate(pipe_config);
>>> @@ -13906,6 +14042,7 @@ static void intel_update_crtc(struct intel_crtc *crtc,
>>>  
>>>  	if (modeset) {
>>>  		update_scanline_offset(new_crtc_state);
>>> +		drm_calc_timestamping_constants(&crtc->base, &new_crtc_state->hw.transcoder_mode);
>>>  		dev_priv->display.crtc_enable(new_crtc_state, state);
>>>  
>>>  		/* vblanks work again, re-enable pipe CRC. */
>>> @@ -13990,7 +14127,7 @@ static void intel_commit_modeset_disables(struct intel_atomic_state *state)
>>>  	 */
>>>  	for_each_oldnew_intel_crtc_in_state_reverse(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_slave)
>>>  			continue;
>>>  
>>>  		intel_pre_plane_update(old_crtc_state, new_crtc_state);
>>> @@ -14000,6 +14137,19 @@ static void intel_commit_modeset_disables(struct intel_atomic_state *state)
>>>  						      old_crtc_state,
>>>  						      new_crtc_state,
>>>  						      crtc);
>>> +
>>> +		if (old_crtc_state->bigjoiner) {
>>> +			struct intel_crtc *slave = old_crtc_state->bigjoiner_linked_crtc;
>>> +			struct intel_crtc_state *old_slave_crtc_state =
>>> +				intel_atomic_get_crtc_state(&state->base, slave);
>>> +			struct intel_crtc_state *new_slave_crtc_state =
>>> +				intel_atomic_get_crtc_state(&state->base, slave);
>>> +
>>> +			intel_old_crtc_state_disables(state,
>>> +						      old_slave_crtc_state,
>>> +						      new_slave_crtc_state,
>>> +						      slave);
>>> +		}
>>>  	}
>>>  }
>>>  
>>> @@ -16433,7 +16583,7 @@ int intel_modeset_init(struct drm_device *dev)
>>>  	for_each_intel_crtc(dev, crtc) {
>>>  		struct intel_initial_plane_config plane_config = {};
>>>  
>>> -		if (!crtc->active)
>>> +		if (!to_intel_crtc_state(crtc->base.state)->uapi.active)
>>>  			continue;
>>>  
>>>  		/*
>>> @@ -16923,7 +17073,17 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
>>>  			crtc_state = to_intel_crtc_state(crtc->base.state);
>>>  
>>>  			encoder->base.crtc = &crtc->base;
>>> -			encoder->get_config(encoder, crtc_state);
>>> +			intel_encoder_get_config(encoder, crtc_state);
>>> +
>>> +			/* read out to slave crtc as well for bigjoiner */
>>> +			if (crtc_state->bigjoiner) {
>>> +				/* encoder should read be linked to bigjoiner master */
>>> +				WARN_ON(crtc_state->bigjoiner_slave);
>>> +
>>> +				crtc = crtc_state->bigjoiner_linked_crtc;
>>> +				crtc_state = to_intel_crtc_state(crtc->base.state);
>>> +				intel_encoder_get_config(encoder, crtc_state);
>>> +			}
>>>  		} else {
>>>  			encoder->base.crtc = NULL;
>>>  		}
>>> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
>>> index dd0329a4b9ff..7e06c61447e6 100644
>>> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
>>> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
>>> @@ -786,6 +786,7 @@ struct intel_crtc_state {
>>>  	 * accordingly.
>>>  	 */
>>>  #define PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS	(1<<0) /* unreliable sync mode.flags */
>>> +#define PIPE_CONFIG_QUIRK_BIGJOINER_SLAVE	(1<<1) /* bigjoiner slave, partial readout */
>>>  	unsigned long quirks;
>>>  
>>>  	unsigned fb_bits; /* framebuffers to flip */
>>> @@ -1572,4 +1573,20 @@ static inline u32 intel_plane_ggtt_offset(const struct intel_plane_state *state)
>>>  	return i915_ggtt_offset(state->vma);
>>>  }
>>>  
>>> +static inline bool
>>> +intel_crtc_supports_dsc(const struct intel_crtc_state *pipe_config)
>>> +{
>>> +	struct drm_i915_private *dev_priv = to_i915(pipe_config->uapi.crtc->dev);
>>> +
>>> +	/* On TGL, DSC is supported on all Pipes */
>>> +	if (INTEL_GEN(dev_priv) >= 12)
>>> +		return true;
>>> +
>>> +	if (INTEL_GEN(dev_priv) >= 10 &&
>>> +	    pipe_config->cpu_transcoder != TRANSCODER_A)
>>> +		return true;
>>> +
>>> +	return false;
>>> +}
>>> +
>>>  #endif /*  __INTEL_DISPLAY_TYPES_H__ */
>>> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
>>> index 3d487ce16151..234be1c31958 100644
>>> --- a/drivers/gpu/drm/i915/display/intel_dp.c
>>> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
>>> @@ -1907,22 +1907,6 @@ static bool intel_dp_supports_fec(struct intel_dp *intel_dp,
>>>  		drm_dp_sink_supports_fec(intel_dp->fec_capable);
>>>  }
>>>  
>>> -static bool intel_dp_source_supports_dsc(struct intel_dp *intel_dp,
>>> -					 const struct intel_crtc_state *pipe_config)
>>> -{
>>> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
>>> -
>>> -	/* On TGL, DSC is supported on all Pipes */
>>> -	if (INTEL_GEN(dev_priv) >= 12)
>>> -		return true;
>>> -
>>> -	if (INTEL_GEN(dev_priv) >= 10 &&
>>> -	    pipe_config->cpu_transcoder != TRANSCODER_A)
>>> -		return true;
>>> -
>>> -	return false;
>>> -}
>>> -
>>>  static bool intel_dp_supports_dsc(struct intel_dp *intel_dp,
>>>  				  const struct intel_crtc_state *pipe_config)
>>>  {
>>> @@ -1930,7 +1914,7 @@ static bool intel_dp_supports_dsc(struct intel_dp *intel_dp,
>>>  	if (!intel_dp_is_edp(intel_dp) && !pipe_config->fec_enable && 0)
>>>  		return false;
>>>  
>>> -	return intel_dp_source_supports_dsc(intel_dp, pipe_config) &&
>>> +	return intel_crtc_supports_dsc(pipe_config) &&
>>>  		drm_dp_sink_supports_dsc(intel_dp->dsc_dpcd);
>>>  }
>>>  
>>> diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c
>>> index 38c181499505..11d4da9734a0 100644
>>> --- a/drivers/gpu/drm/i915/display/intel_vdsc.c
>>> +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c
>>> @@ -480,11 +480,10 @@ intel_dsc_power_domain(const struct intel_crtc_state *crtc_state)
>>>  		return POWER_DOMAIN_TRANSCODER(cpu_transcoder);
>>>  }
>>>  
>>> -static void intel_configure_pps_for_dsc_encoder(struct intel_encoder *encoder,
>>> -						const struct intel_crtc_state *crtc_state)
>>> +static void intel_configure_pps_for_dsc_encoder(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(encoder->base.dev);
>>> +	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
>>>  	const struct drm_dsc_config *vdsc_cfg = &crtc_state->dp_dsc_cfg;
>>>  	enum pipe pipe = crtc->pipe;
>>>  	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
>>> @@ -494,6 +493,9 @@ static void intel_configure_pps_for_dsc_encoder(struct intel_encoder *encoder,
>>>  	u8 num_vdsc_instances = (crtc_state->dsc_params.dsc_split) ? 2 : 1;
>>>  	int i = 0;
>>>  
>>> +	if (crtc_state->bigjoiner)
>>> +		num_vdsc_instances *= 2;
>>> +
>>>  	/* Populate PICTURE_PARAMETER_SET_0 registers */
>>>  	pps_val = DSC_VER_MAJ | vdsc_cfg->dsc_version_minor <<
>>>  		DSC_VER_MIN_SHIFT |
>>> @@ -899,74 +901,104 @@ static void intel_dp_write_dsc_pps_sdp(struct intel_encoder *encoder,
>>>  					sizeof(dp_dsc_pps_sdp));
>>>  }
>>>  
>>> +static i915_reg_t dss_ctl1_reg(const struct intel_crtc_state *crtc_state)
>>> +{
>>> +	enum pipe pipe = to_intel_crtc(crtc_state->uapi.crtc)->pipe;
>>> +
>>> +	if (crtc_state->cpu_transcoder == TRANSCODER_EDP)
>>> +		return DSS_CTL1;
>>> +
>>> +	return ICL_PIPE_DSS_CTL1(pipe);
>>> +}
>>> +
>>> +static i915_reg_t dss_ctl2_reg(const struct intel_crtc_state *crtc_state)
>>> +{
>>> +	enum pipe pipe = to_intel_crtc(crtc_state->uapi.crtc)->pipe;
>>> +
>>> +	if (crtc_state->cpu_transcoder == TRANSCODER_EDP)
>>> +		return DSS_CTL2;
>>> +
>>> +	return ICL_PIPE_DSS_CTL2(pipe);
>>> +}
>>> +
>>>  void intel_dsc_enable(struct intel_encoder *encoder,
>>>  		      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(encoder->base.dev);
>>> -	enum pipe pipe = crtc->pipe;
>>> -	i915_reg_t dss_ctl1_reg, dss_ctl2_reg;
>>> +	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
>>>  	u32 dss_ctl1_val = 0;
>>>  	u32 dss_ctl2_val = 0;
>>>  
>>>  	if (!crtc_state->dsc_params.compression_enable)
>>>  		return;
>>>  
>>> -	/* Enable Power wells for VDSC/joining */
>>> -	intel_display_power_get(dev_priv,
>>> -				intel_dsc_power_domain(crtc_state));
>>> +	intel_configure_pps_for_dsc_encoder(crtc_state);
>>>  
>>> -	intel_configure_pps_for_dsc_encoder(encoder, crtc_state);
>>> +	if (!crtc_state->bigjoiner_slave)
>>> +		intel_dp_write_dsc_pps_sdp(encoder, crtc_state);
>>>  
>>> -	intel_dp_write_dsc_pps_sdp(encoder, crtc_state);
>>> -
>>> -	if (crtc_state->cpu_transcoder == TRANSCODER_EDP) {
>>> -		dss_ctl1_reg = DSS_CTL1;
>>> -		dss_ctl2_reg = DSS_CTL2;
>>> -	} else {
>>> -		dss_ctl1_reg = ICL_PIPE_DSS_CTL1(pipe);
>>> -		dss_ctl2_reg = ICL_PIPE_DSS_CTL2(pipe);
>>> -	}
>>>  	dss_ctl2_val |= LEFT_BRANCH_VDSC_ENABLE;
>>>  	if (crtc_state->dsc_params.dsc_split) {
>>>  		dss_ctl2_val |= RIGHT_BRANCH_VDSC_ENABLE;
>>>  		dss_ctl1_val |= JOINER_ENABLE;
>>>  	}
>>> -	I915_WRITE(dss_ctl1_reg, dss_ctl1_val);
>>> -	I915_WRITE(dss_ctl2_reg, dss_ctl2_val);
>>> +	if (crtc_state->bigjoiner) {
>>> +		dss_ctl1_val |= BIG_JOINER_ENABLE;
>>> +		if (!crtc_state->bigjoiner_slave)
>>> +			dss_ctl1_val |= MASTER_BIG_JOINER_ENABLE;
>>> +	}
>>> +	I915_WRITE(dss_ctl1_reg(crtc_state), dss_ctl1_val);
>>> +	I915_WRITE(dss_ctl2_reg(crtc_state), dss_ctl2_val);
>>>  }
>>>  
>>>  void intel_dsc_disable(const struct intel_crtc_state *old_crtc_state)
>>>  {
>>>  	struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);
>>>  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
>>> -	enum pipe pipe = crtc->pipe;
>>> -	i915_reg_t dss_ctl1_reg, dss_ctl2_reg;
>>> -	u32 dss_ctl1_val = 0, dss_ctl2_val = 0;
>>>  
>>>  	if (!old_crtc_state->dsc_params.compression_enable)
>>>  		return;
>>>  
>>> -	if (old_crtc_state->cpu_transcoder == TRANSCODER_EDP) {
>>> -		dss_ctl1_reg = DSS_CTL1;
>>> -		dss_ctl2_reg = DSS_CTL2;
>>> -	} else {
>>> -		dss_ctl1_reg = ICL_PIPE_DSS_CTL1(pipe);
>>> -		dss_ctl2_reg = ICL_PIPE_DSS_CTL2(pipe);
>>> +	I915_WRITE(dss_ctl1_reg(old_crtc_state), 0);
>>> +	I915_WRITE(dss_ctl2_reg(old_crtc_state), 0);
>>> +}
>>> +
>>> +void intel_dsc_get_config(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 dss_ctl1_val, dss_ctl2_val;
>>> +	intel_wakeref_t wakeref;
>>> +
>>> +	if (!intel_crtc_supports_dsc(crtc_state))
>>> +		return;
>>> +
>>> +	wakeref = intel_display_power_get_if_enabled(dev_priv, intel_dsc_power_domain(crtc_state));
>>> +	if (!wakeref)
>>> +		return;
>>> +
>>> +	dss_ctl1_val = I915_READ(dss_ctl1_reg(crtc_state));
>>> +	dss_ctl2_val = I915_READ(dss_ctl2_reg(crtc_state));
>>> +	if (dss_ctl2_val & LEFT_BRANCH_VDSC_ENABLE)
>>> +		crtc_state->dsc_params.compression_enable = true;
>>> +
>>> +	if ((dss_ctl1_val & JOINER_ENABLE) && (dss_ctl2_val & RIGHT_BRANCH_VDSC_ENABLE))
>>> +		crtc_state->dsc_params.dsc_split = true;
>>> +
>>> +	if (dss_ctl1_val & BIG_JOINER_ENABLE) {
>>> +		crtc_state->bigjoiner = true;
> Is crtc_state->bigjoiner supposed to be set on both master and slave or
> just on the master?  I thought we only set it for the master based on
> what I see in intel_dp_dsc_compute_config, but this appears to set in on
> both during readout (my interpretation of bspec #50174 is that bit 29 is
> set on both master and slave, whereas bit 28 is only set on the master).
> Should this be testing against MASTER_BIG_JOINER_ENABLE instead?
This is correct, we copy the entire crtc_state to the slave, including the bigjoiner flag.
>
> Matt
>
>>> +
>>> +		if (!(dss_ctl1_val & MASTER_BIG_JOINER_ENABLE)) {
>>> +			crtc_state->bigjoiner_slave = true;
>>> +			if (!WARN_ON(crtc->pipe == PIPE_A))
>>> +				crtc_state->bigjoiner_linked_crtc =
>>> +					intel_get_crtc_for_pipe(dev_priv, crtc->pipe - 1);
>>> +		} else {
>>> +			if (!WARN_ON(INTEL_NUM_PIPES(dev_priv) == crtc->pipe + 1))
>>> +				crtc_state->bigjoiner_linked_crtc =
>>> +					intel_get_crtc_for_pipe(dev_priv, crtc->pipe + 1);
>>> +		}
>>>  	}
>>> -	dss_ctl1_val = I915_READ(dss_ctl1_reg);
>>> -	if (dss_ctl1_val & JOINER_ENABLE)
>>> -		dss_ctl1_val &= ~JOINER_ENABLE;
>>> -	I915_WRITE(dss_ctl1_reg, dss_ctl1_val);
>>> -
>>> -	dss_ctl2_val = I915_READ(dss_ctl2_reg);
>>> -	if (dss_ctl2_val & LEFT_BRANCH_VDSC_ENABLE ||
>>> -	    dss_ctl2_val & RIGHT_BRANCH_VDSC_ENABLE)
>>> -		dss_ctl2_val &= ~(LEFT_BRANCH_VDSC_ENABLE |
>>> -				  RIGHT_BRANCH_VDSC_ENABLE);
>>> -	I915_WRITE(dss_ctl2_reg, dss_ctl2_val);
>>> -
>>> -	/* Disable Power wells for VDSC/joining */
>>> -	intel_display_power_put_unchecked(dev_priv,
>>> -					  intel_dsc_power_domain(old_crtc_state));
>>> +
>>> +	intel_display_power_put(dev_priv, intel_dsc_power_domain(crtc_state), wakeref);
>>>  }
>>> diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.h b/drivers/gpu/drm/i915/display/intel_vdsc.h
>>> index 90d3f6017fcb..569cf17402ba 100644
>>> --- a/drivers/gpu/drm/i915/display/intel_vdsc.h
>>> +++ b/drivers/gpu/drm/i915/display/intel_vdsc.h
>>> @@ -15,6 +15,8 @@ void intel_dsc_enable(struct intel_encoder *encoder,
>>>  void intel_dsc_disable(const struct intel_crtc_state *crtc_state);
>>>  int intel_dp_compute_dsc_params(struct intel_dp *intel_dp,
>>>  				struct intel_crtc_state *pipe_config);
>>> +void intel_dsc_get_config(struct intel_crtc_state *crtc_state);
>>> +
>>>  enum intel_display_power_domain
>>>  intel_dsc_power_domain(const struct intel_crtc_state *crtc_state);
>>>  
>>> -- 
>>> 2.20.1
>>>
>>> _______________________________________________
>>> Intel-gfx mailing list
>>> Intel-gfx@lists.freedesktop.org
>>> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
>> -- 
>> Matt Roper
>> Graphics Software Engineer
>> VTT-OSGC Platform Enablement
>> Intel Corporation
>> (916) 356-2795
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/intel-gfx


_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

  reply	other threads:[~2019-09-27  8:25 UTC|newest]

Thread overview: 82+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-09-20 11:42 [PATCH 01/23] drm/i915/dp: Fix dsc bpp calculations, v2 Maarten Lankhorst
2019-09-20 11:42 ` [PATCH 02/23] HAX drm/i915: Disable FEC entirely for now Maarten Lankhorst
2019-09-23 13:08   ` Maarten Lankhorst
2019-09-20 11:42 ` [PATCH 03/23] drm/i915: Prepare to split crtc state in uapi and hw state Maarten Lankhorst
2019-09-24 23:40   ` Matt Roper
2019-09-25  9:09     ` Maarten Lankhorst
2019-09-20 11:42 ` [PATCH 04/23] drm/i915: Handle a few more cases for hw/sw split Maarten Lankhorst
2019-09-24 23:40   ` Matt Roper
2019-09-20 11:42 ` [PATCH 05/23] drm/i915: Complete sw/hw split Maarten Lankhorst
2019-09-24 23:41   ` Matt Roper
2019-09-25  9:29     ` Maarten Lankhorst
2019-09-25 13:01   ` Ville Syrjälä
2019-09-25 14:12     ` Maarten Lankhorst
2019-09-25 14:18     ` Maarten Lankhorst
2019-09-25 14:54       ` Ville Syrjälä
2019-09-20 11:42 ` [PATCH 06/23] drm/i915: Get rid of crtc_state->fb_changed Maarten Lankhorst
2019-09-24 23:44   ` Matt Roper
2019-09-20 11:42 ` [PATCH 07/23] drm/i915: Remove begin/finish_crtc_commit Maarten Lankhorst
2019-09-25  4:17   ` Matt Roper
2019-09-25 14:14     ` Maarten Lankhorst
2019-09-25 22:14   ` Manasi Navare
2019-09-20 11:42 ` [PATCH 08/23] drm/i915: Rename planar linked plane variables Maarten Lankhorst
2019-09-25  4:30   ` Matt Roper
2019-09-20 11:42 ` [PATCH 09/23] drm/i915: Do not add all planes when checking scalers on glk+ Maarten Lankhorst
2019-09-25  4:55   ` Matt Roper
2019-09-25 12:45     ` Maarten Lankhorst
2019-09-25 13:02     ` Ville Syrjälä
2019-09-20 11:42 ` [PATCH 10/23] drm/i915/dp: Allow big joiner modes in intel_dp_mode_valid() Maarten Lankhorst
2019-09-25  5:30   ` Matt Roper
2019-09-25  5:56     ` Matt Roper
2019-09-25 22:09     ` Manasi Navare
2019-09-26 16:00       ` Maarten Lankhorst
2019-09-20 11:42 ` [PATCH 11/23] drm/i915: Try to make bigjoiner work in atomic check Maarten Lankhorst
2019-09-26  3:48   ` Matt Roper
2019-09-30 14:12     ` Maarten Lankhorst
2019-09-20 11:42 ` [PATCH 12/23] drm/i915: Enable big joiner support in enable and disable sequences Maarten Lankhorst
2019-09-26  5:18   ` Matt Roper
2019-09-26 23:54     ` Matt Roper
2019-09-27  8:25       ` Maarten Lankhorst [this message]
2019-09-20 11:42 ` [PATCH 13/23] drm/i915: Make hardware readout work on i915 Maarten Lankhorst
2019-09-27  0:49   ` Matt Roper
2019-09-20 11:42 ` [PATCH 14/23] drm/i915: Prepare update_slave() for bigjoiner plane updates Maarten Lankhorst
2019-09-27  3:18   ` Matt Roper
2019-09-20 11:42 ` [PATCH 15/23] drm/i915: Link planes in a bigjoiner configuration Maarten Lankhorst
2019-10-01 16:44   ` Matt Roper
2019-10-01 17:21     ` Ville Syrjälä
2019-09-20 11:42 ` [PATCH 16/23] drm/i915: Program planes in bigjoiner mode Maarten Lankhorst
2019-09-26 13:06   ` Ville Syrjälä
2019-09-26 15:50     ` Maarten Lankhorst
2019-09-26 16:09       ` Ville Syrjälä
2019-09-26 16:13         ` Maarten Lankhorst
2019-09-26 16:26           ` Ville Syrjälä
2019-09-26 19:11         ` Ville Syrjälä
2019-09-27  8:56           ` Maarten Lankhorst
2019-09-27 14:41             ` Ville Syrjälä
2019-09-27 15:00               ` Ville Syrjälä
2019-09-20 11:42 ` [PATCH 17/23] drm/i915: Add intel_update_bigjoiner handling Maarten Lankhorst
2019-09-20 11:42 ` [PATCH 18/23] drm/i915: Disable FBC in bigjoiner configuration Maarten Lankhorst
2019-09-20 11:42 ` [PATCH 19/23] drm/i915: Prepare atomic plane check for bigjoiner planes Maarten Lankhorst
2019-09-20 11:42 ` [PATCH 20/23] drm/i915: Make prepare_plane_fb() work with " Maarten Lankhorst
2019-09-20 11:42 ` [PATCH 21/23] drm/i915: Make sure watermarks work correctly with bigjoiner as well Maarten Lankhorst
2019-09-20 11:42 ` [PATCH 22/23] drm/i915: Add debugfs dumping for bigjoiner Maarten Lankhorst
2019-09-20 11:42 ` [PATCH 23/23] HAX to make it work on the icelake test system Maarten Lankhorst
2019-09-20 14:52 ` ✗ Fi.CI.CHECKPATCH: warning for series starting with [01/23] drm/i915/dp: Fix dsc bpp calculations, v2 Patchwork
2019-09-20 14:59 ` ✗ Fi.CI.SPARSE: " Patchwork
2019-09-20 15:16 ` ✓ Fi.CI.BAT: success " Patchwork
2019-09-20 16:38 ` [Intel-gfx] [PATCH 01/23] " Ville Syrjälä
2019-09-23 12:52   ` [PATCH] drm/i915/dp: Fix dsc bpp calculations, v3 Maarten Lankhorst
2019-09-23 13:03     ` Ville Syrjälä
2019-09-23 13:03       ` Ville Syrjälä
2019-09-23 14:49       ` [PATCH] drm/i915/dp: Fix dsc bpp calculations, v4 Maarten Lankhorst
2019-09-23 14:50         ` Maarten Lankhorst
2019-09-23 14:57         ` Ville Syrjälä
2019-09-23 15:56           ` Manasi Navare
2019-09-23 15:56           ` [Intel-gfx] " Ville Syrjälä
2019-09-23 14:22     ` [Intel-gfx] [PATCH] drm/i915/dp: Fix dsc bpp calculations, v3 kbuild test robot
2019-09-23 14:22       ` kbuild test robot
2019-09-23 15:53     ` Manasi Navare
2019-09-21 12:06 ` [PATCH 01/23] drm/i915/dp: Fix dsc bpp calculations, v2 Sasha Levin
2019-09-21 15:22 ` ✗ Fi.CI.IGT: failure for series starting with [01/23] " Patchwork
2019-09-23 10:43   ` Maarten Lankhorst
2019-09-23 19:10 ` ✗ Fi.CI.BUILD: failure for series starting with drm/i915/dp: Fix dsc bpp calculations, v4. (rev3) Patchwork

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ad75784e-dca4-40f8-238f-e1064d076325@linux.intel.com \
    --to=maarten.lankhorst@linux.intel.com \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=matthew.d.roper@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.