diff mbox series

[v4] drm/i915/display/icl: HW state readout for transcoder port sync config

Message ID 20190924195007.15870-1-manasi.d.navare@intel.com (mailing list archive)
State New, archived
Headers show
Series [v4] drm/i915/display/icl: HW state readout for transcoder port sync config | expand

Commit Message

Navare, Manasi Sept. 24, 2019, 7:50 p.m. UTC
After the state is committed, we readout the HW registers and compare
the HW state with the SW state that we just committed.
For Transcdoer port sync, we add master_transcoder and the
salves bitmask to the crtc_state, hence we need to read those during
the HW state readout to avoid pipe state mismatch.

v5:
* Add return INVALID in defaut case (Maarten)
v4:
* Get power domains in master loop for get_config (Ville)
v3:
* Add TRANSCODER_D (Maarten)
* v3 Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
v2:
* Add Transcoder_D and MISSING_CASE (Maarten)

Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Matt Roper <matthew.d.roper@intel.com>
Cc: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Manasi Navare <manasi.d.navare@intel.com>
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_display.c | 68 ++++++++++++++++++++
 1 file changed, 68 insertions(+)
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 2099fed3713a..84a0a83e9e05 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -10506,6 +10506,71 @@  static void haswell_get_ddi_port_state(struct intel_crtc *crtc,
 	}
 }
 
+static enum transcoder transcoder_master(struct drm_i915_private *dev_priv,
+					 enum transcoder cpu_transcoder)
+{
+	u32 trans_port_sync, master_select;
+
+	trans_port_sync = I915_READ(TRANS_DDI_FUNC_CTL2(cpu_transcoder));
+
+	if ((trans_port_sync & PORT_SYNC_MODE_ENABLE) == 0)
+		return INVALID_TRANSCODER;
+
+	master_select = trans_port_sync &
+			PORT_SYNC_MODE_MASTER_SELECT_MASK;
+	switch (master_select) {
+	case 1:
+		return TRANSCODER_A;
+	case 2:
+		return TRANSCODER_B;
+	case 3:
+		return TRANSCODER_C;
+	case 4:
+		return TRANSCODER_D;
+	default:
+		MISSING_CASE(master_select);
+		return INVALID_TRANSCODER;
+	}
+}
+
+static void icelake_get_trans_port_sync_config(struct intel_crtc *crtc,
+					       struct intel_crtc_state *pipe_config)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	u32 transcoders;
+	enum transcoder cpu_transcoder;
+
+	pipe_config->master_transcoder = transcoder_master(dev_priv,
+							   pipe_config->cpu_transcoder);
+	if (pipe_config->master_transcoder != INVALID_TRANSCODER) {
+		pipe_config->sync_mode_slaves_mask = 0;
+		return;
+	}
+
+	transcoders = BIT(TRANSCODER_A) |
+		BIT(TRANSCODER_B) |
+		BIT(TRANSCODER_C) |
+		BIT(TRANSCODER_D);
+	for_each_cpu_transcoder_masked(dev_priv, cpu_transcoder, transcoders) {
+		enum intel_display_power_domain power_domain;
+		intel_wakeref_t trans_wakeref;
+
+		power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder);
+		trans_wakeref = intel_display_power_get_if_enabled(dev_priv,
+								   power_domain);
+
+		if (!trans_wakeref)
+			continue;
+
+		if (transcoder_master(dev_priv, cpu_transcoder) ==
+		    pipe_config->cpu_transcoder)
+			pipe_config->sync_mode_slaves_mask |= BIT(cpu_transcoder);
+
+		intel_display_power_put(dev_priv, power_domain, trans_wakeref);
+	}
+}
+
 static bool haswell_get_pipe_config(struct intel_crtc *crtc,
 				    struct intel_crtc_state *pipe_config)
 {
@@ -10625,6 +10690,9 @@  static bool haswell_get_pipe_config(struct intel_crtc *crtc,
 		pipe_config->pixel_multiplier = 1;
 	}
 
+	if (INTEL_GEN(dev_priv) >= 11)
+		icelake_get_trans_port_sync_config(crtc, pipe_config);
+
 out:
 	for_each_power_domain(power_domain, power_domain_mask)
 		intel_display_power_put(dev_priv,