[PATCH 14/25] drm/i915: Enable big joiner support in enable and disable sequences.

Maarten Lankhorst maarten.lankhorst at linux.intel.com
Fri Aug 30 15:08:25 UTC 2019


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.

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 at linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_ddi.c      |  54 ++++--
 drivers/gpu/drm/i915/display/intel_display.c  | 181 ++++++++++++------
 .../drm/i915/display/intel_display_types.h    |   1 +
 drivers/gpu/drm/i915/display/intel_vdsc.c     | 115 +++++++----
 drivers/gpu/drm/i915/display/intel_vdsc.h     |   3 +
 5 files changed, 250 insertions(+), 104 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
index 90779210e4fd..8ed44e59a039 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -1206,12 +1206,16 @@ static void intel_ddi_init_dp_buf_reg(struct intel_encoder *encoder)
 }
 
 static struct intel_encoder *
-intel_ddi_get_crtc_encoder(struct intel_crtc *crtc)
+intel_ddi_get_crtc_encoder(const struct intel_crtc_state *crtc_state)
 {
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
 	struct drm_device *dev = crtc->base.dev;
 	struct intel_encoder *encoder, *ret = NULL;
 	int num_encoders = 0;
 
+	if (crtc_state->bigjoiner_slave)
+		crtc = crtc_state->bigjoiner_linked_crtc;
+
 	for_each_encoder_on_crtc(dev, &crtc->base, encoder) {
 		ret = encoder;
 		num_encoders++;
@@ -1479,6 +1483,9 @@ static void ddi_dotclock_get(struct intel_crtc_state *pipe_config)
 	if (pipe_config->pixel_multiplier)
 		dotclock /= pipe_config->pixel_multiplier;
 
+	if (pipe_config->bigjoiner)
+		dotclock /= 2;
+
 	pipe_config->hw.adjusted_mode.crtc_clock = dotclock;
 }
 
@@ -1771,7 +1778,7 @@ static u32
 intel_ddi_transcoder_func_reg_val_get(const struct intel_crtc_state *crtc_state)
 {
 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
-	struct intel_encoder *encoder = intel_ddi_get_crtc_encoder(crtc);
+	struct intel_encoder *encoder = intel_ddi_get_crtc_encoder(crtc_state);
 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 	enum pipe pipe = crtc->pipe;
 	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
@@ -2182,7 +2189,7 @@ void intel_ddi_enable_pipe_clock(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);
-	struct intel_encoder *encoder = intel_ddi_get_crtc_encoder(crtc);
+	struct intel_encoder *encoder = intel_ddi_get_crtc_encoder(crtc_state);
 	enum port port = encoder->port;
 	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
 
@@ -3341,7 +3348,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,
@@ -3953,19 +3961,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);
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 	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
@@ -4034,6 +4041,30 @@ 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);
+	intel_dsc_get_config(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);
@@ -4058,7 +4089,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 1cbd9f29097c..e48177b3568e 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -6419,6 +6419,46 @@ 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 above */
+		intel_dsc_enable(encoder, crtc_state);
+	} else {
+		/*
+		 * Enable sequence steps 1-7 on bigjoiner 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);
+
+		/* transcoder port select + DSC on slave */
+		intel_ddi_enable_pipe_clock(crtc_state);
+		intel_dsc_enable(NULL, crtc_state);
+	}
+}
+
 static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
 				struct intel_atomic_state *state)
 {
@@ -6432,12 +6472,16 @@ 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);
@@ -6491,6 +6535,7 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
 		icl_set_pipe_chicken(intel_crtc);
 
 	intel_ddi_set_pipe_settings(pipe_config);
+
 	if (!transcoder_is_dsi(cpu_transcoder))
 		intel_ddi_enable_transcoder_func(pipe_config);
 
@@ -6633,9 +6678,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)
@@ -8250,10 +8313,12 @@ 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;
+	int hmult = pipe_config->bigjoiner ? 2 : 1;
+
+	mode->hdisplay = pipe_config->hw.adjusted_mode.crtc_hdisplay * hmult;
+	mode->htotal = pipe_config->hw.adjusted_mode.crtc_htotal * hmult;
+	mode->hsync_start = pipe_config->hw.adjusted_mode.crtc_hsync_start * hmult;
+	mode->hsync_end = pipe_config->hw.adjusted_mode.crtc_hsync_end * hmult;
 
 	mode->vdisplay = pipe_config->hw.adjusted_mode.crtc_vdisplay;
 	mode->vtotal = pipe_config->hw.adjusted_mode.crtc_vtotal;
@@ -8263,7 +8328,7 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode,
 	mode->flags = pipe_config->hw.adjusted_mode.flags;
 	mode->type = DRM_MODE_TYPE_DRIVER;
 
-	mode->clock = pipe_config->hw.adjusted_mode.crtc_clock;
+	mode->clock = pipe_config->hw.adjusted_mode.crtc_clock * hmult;
 
 	mode->hsync = drm_mode_hsync(mode);
 	mode->vrefresh = drm_mode_vrefresh(mode);
@@ -8517,36 +8582,6 @@ static int vlv_crtc_compute_clock(struct intel_crtc *crtc,
 	return 0;
 }
 
-static int intel_crtc_compute_clock_bigjoiner(struct intel_atomic_state *state,
-					      struct intel_crtc_state *crtc_state)
-{
-	struct drm_connector *conn;
-	struct drm_connector_state *conn_state;
-	int i;
-	struct intel_crtc *master = crtc_state->bigjoiner_linked_crtc;
-	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
-
-	for_each_new_connector_in_state(&state->base, conn, conn_state, i) {
-		struct intel_encoder *encoder =
-			to_intel_encoder(conn_state->best_encoder);
-
-		if (conn_state->crtc != &master->base)
-			continue;
-
-		if (!intel_reserve_shared_dplls(state, crtc, encoder)) {
-			DRM_DEBUG_KMS("[CRTC:%d:%s] Could not reserve shared dpll for bigjoiner\n",
-				      crtc->base.base.id, crtc->base.name);
-			return -EINVAL;
-		}
-
-		return 0;
-	}
-
-	DRM_ERROR("[CRTC:%d:%s] Could not find master encoder for calculating slave clock\n",
-		  crtc->base.base.id, crtc->base.name);
-	return -EINVAL;
-}
-
 static bool i9xx_has_pfit(struct drm_i915_private *dev_priv)
 {
 	if (IS_I830(dev_priv))
@@ -10380,6 +10415,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);
@@ -11797,13 +11834,10 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc,
 
 	if (mode_changed && pipe_config->hw.enable &&
 	    dev_priv->display.crtc_compute_clock &&
-	    !WARN_ON(pipe_config->shared_dpll)) {
-		if (pipe_config->bigjoiner_slave)
-			ret = intel_crtc_compute_clock_bigjoiner(state,
-								 pipe_config);
-		else
-			ret = dev_priv->display.crtc_compute_clock(intel_crtc,
-								   pipe_config);
+	    !WARN_ON(pipe_config->shared_dpll) &&
+	    !pipe_config->bigjoiner_slave) {
+		ret = dev_priv->display.crtc_compute_clock(intel_crtc,
+							   pipe_config);
 		if (ret)
 			return ret;
 	}
@@ -12869,7 +12903,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))
@@ -12921,10 +12956,12 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
 	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);
+	if (!PIPE_CONF_QUIRK(PIPE_CONFIG_QUIRK_BIGJOINER_SLAVE)) {
+		PIPE_CONF_CHECK_CLOCK_FUZZY(hw.adjusted_mode.crtc_clock);
 
-	PIPE_CONF_CHECK_I(min_voltage_level);
+		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);
@@ -12933,6 +12970,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
@@ -13186,6 +13229,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;
@@ -13215,7 +13259,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);
@@ -13224,7 +13271,7 @@ 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));
 
@@ -13986,6 +14033,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.adjusted_mode);
 		dev_priv->display.crtc_enable(new_crtc_state, state);
 
 		/* vblanks work again, re-enable pipe CRC. */
@@ -14070,7 +14118,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);
@@ -14080,6 +14128,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);
+		}
 	}
 }
 
@@ -16950,6 +17011,16 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
 
 			encoder->base.crtc = &crtc->base;
 			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);
+				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 054f3acbc28a..98c3d24f0b88 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 */
diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c
index 38c181499505..3cfbd3250df5 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,13 +901,31 @@ 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;
 
@@ -916,57 +936,76 @@ void intel_dsc_enable(struct intel_encoder *encoder,
 	intel_display_power_get(dev_priv,
 				intel_dsc_power_domain(crtc_state));
 
-	intel_configure_pps_for_dsc_encoder(encoder, crtc_state);
+	intel_configure_pps_for_dsc_encoder(crtc_state);
 
-	intel_dp_write_dsc_pps_sdp(encoder, crtc_state);
+	if (!crtc_state->bigjoiner_slave)
+		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);
-	}
-	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);
+	I915_WRITE(dss_ctl1_reg(old_crtc_state), 0);
+	I915_WRITE(dss_ctl2_reg(old_crtc_state), 0);
 
 	/* Disable Power wells for VDSC/joining */
 	intel_display_power_put_unchecked(dev_priv,
 					  intel_dsc_power_domain(old_crtc_state));
 }
+
+void intel_dsc_get_config(struct intel_encoder *encoder,
+			  struct intel_crtc_state *crtc_state)
+{
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+	u32 dss_ctl1_val, dss_ctl2_val;
+	intel_wakeref_t wakeref;
+
+	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;
+
+		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);
+			crtc_state->quirks |= PIPE_CONFIG_QUIRK_BIGJOINER_SLAVE;
+		} else {
+			if (!WARN_ON(INTEL_INFO(dev_priv)->num_pipes == crtc->pipe + 1))
+				crtc_state->bigjoiner_linked_crtc =
+					intel_get_crtc_for_pipe(dev_priv, crtc->pipe + 1);
+		}
+	}
+
+	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..8ba4356a9e4a 100644
--- a/drivers/gpu/drm/i915/display/intel_vdsc.h
+++ b/drivers/gpu/drm/i915/display/intel_vdsc.h
@@ -15,6 +15,9 @@ 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_encoder *encoder,
+			  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



More information about the Intel-gfx-trybot mailing list