diff mbox series

[15/15] UBUNTU: SAUCE: drm/i915/edp: enable eDP MSO during link training

Message ID 20210326073009.515253-16-aaron.ma@canonical.com
State New
Headers show
Series UBUNTU: SAUCE: add support of MSO panel | expand

Commit Message

Aaron Ma March 26, 2021, 7:30 a.m. UTC
From: Jani Nikula <jani.nikula@intel.com>

BugLink: https://bugs.launchpad.net/bugs/1921318

If the source and sink support MSO, enable it during link training.

v4: Divide DRRS pixel clock by link count before M/N calculation

v3: Adjust timings, refer to splitter

v2: Limit MSO to pipe A using ->pipe_mask

Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/2711
Cc: Nischal Varide <nischal.varide@intel.com>
Reviewed-by: Uma Shankar <uma.shankar@intel.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/66da48b4b3c5ccffaac7989097cd96d6c6af8243.1614682842.git.jani.nikula@intel.com
(backported from commit bc71194e889741eb54a3dcc35fc79215fa9449d2
https://anongit.freedesktop.org/git/drm-intel.git drm-intel-next)
Signed-off-by: Aaron Ma <aaron.ma@canonical.com>
---
 drivers/gpu/drm/i915/display/intel_ddi.c     | 37 +++++++++++++++++
 drivers/gpu/drm/i915/display/intel_display.c | 13 ++++++
 drivers/gpu/drm/i915/display/intel_dp.c      | 43 ++++++++++++++++++--
 3 files changed, 89 insertions(+), 4 deletions(-)

Comments

Aaron Ma March 26, 2021, 8:51 a.m. UTC | #1
BugLink: https://bugs.launchpad.net/bugs/1921318

[Impact]
New panel with MSO feature can't be light up.

[Fix]
This series enables eDP MSO on TGL+.
Patch set:
https://patchwork.freedesktop.org/series/86992/
https://patchwork.freedesktop.org/series/87536/
It depends on another patch set:
https://patchwork.freedesktop.org/series/83780/

[Test Case]
Verified on the target platform and other 2 laptops without MSO feature,
internal display good;
external monitor good;
external monitor good via dock;
no errors after GPU benchmark;

[Where problems could occur]
Intel GPU may lose the output.
Due to the concern of the big change, target to oem-5.10 only.

Jani Nikula (9):
   drm/dp: add MSO related DPCD registers
   drm/i915/edp: reject modes with dimensions other than fixed mode
   drm/i915/edp: always add fixed mode to probed modes in ->get_modes()
   drm/i915/edp: read sink MSO configuration for eDP 1.4+
   drm/i915/reg: add stream splitter configuration definitions
   drm/i915/mso: add splitter state readout for platforms that support it
   drm/i915/mso: add splitter state check
   drm/i915/edp: modify fixed and downclock modes for MSO
   drm/i915/edp: enable eDP MSO during link training

Maarten Lankhorst (1):
   drm/i915: Add hw.pipe_mode to allow bigjoiner pipe/transcoder split

Manasi Navare (2):
   drm/i915: Move encoder->get_config to a new function
   drm/i915: Add a wrapper function around get_pipe_config

Ville Syrjälä (3):
   drm/i915: Move hw.active assignment into intel_crtc_get_pipe_config()
   drm/i915: s/intel_mode_from_pipe_config/intel_mode_from_crtc_timings/
   drm/i915: Introduce intel_crtc_readout_derived_state()

  drivers/gpu/drm/i915/display/intel_ddi.c      |  78 ++++++
  drivers/gpu/drm/i915/display/intel_display.c  | 224 ++++++++++++------
  drivers/gpu/drm/i915/display/intel_display.h  |   2 -
  .../drm/i915/display/intel_display_types.h    |  20 +-
  drivers/gpu/drm/i915/display/intel_dp.c       | 121 +++++++++-
  drivers/gpu/drm/i915/i915_drv.h               |   2 +
  drivers/gpu/drm/i915/i915_reg.h               |   3 +
  drivers/gpu/drm/i915/intel_pm.c               |  76 +++---
  include/drm/drm_dp_helper.h                   |   5 +
  9 files changed, 410 insertions(+), 121 deletions(-)
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 9e6726f46773..2edd91120e3f 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -3402,6 +3402,34 @@  static void intel_ddi_mso_get_config(struct intel_encoder *encoder,
 	pipe_config->splitter.pixel_overlap = REG_FIELD_GET(OVERLAP_PIXELS_MASK, dss1);
 }
 
+static void intel_ddi_mso_configure(const struct intel_crtc_state *crtc_state)
+{
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+	struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+	enum pipe pipe = crtc->pipe;
+	u32 dss1 = 0;
+
+	if (!HAS_MSO(i915))
+		return;
+
+	if (crtc_state->splitter.enable) {
+		/* Splitter enable is supported for pipe A only. */
+		if (drm_WARN_ON(&i915->drm, pipe != PIPE_A))
+			return;
+
+		dss1 |= SPLITTER_ENABLE;
+		dss1 |= OVERLAP_PIXELS(crtc_state->splitter.pixel_overlap);
+		if (crtc_state->splitter.link_count == 2)
+			dss1 |= SPLITTER_CONFIGURATION_2_SEGMENT;
+		else
+			dss1 |= SPLITTER_CONFIGURATION_4_SEGMENT;
+	}
+
+	intel_de_rmw(i915, ICL_PIPE_DSS_CTL1(pipe),
+		     SPLITTER_ENABLE | SPLITTER_CONFIGURATION_MASK |
+		     OVERLAP_PIXELS_MASK, dss1);
+}
+
 static void tgl_ddi_pre_enable_dp(struct intel_atomic_state *state,
 				  struct intel_encoder *encoder,
 				  const struct intel_crtc_state *crtc_state,
@@ -3497,6 +3525,11 @@  static void tgl_ddi_pre_enable_dp(struct intel_atomic_state *state,
 	 */
 	intel_ddi_power_up_lanes(encoder, crtc_state);
 
+	/*
+	 * 7.g Program CoG/MSO configuration bits in DSS_CTL1 if selected.
+	 */
+	intel_ddi_mso_configure(crtc_state);
+
 	/*
 	 * 7.g Configure and enable DDI_BUF_CTL
 	 * 7.h Wait for DDI_BUF_CTL DDI Idle Status = 0b (Not Idle), timeout
@@ -5298,6 +5331,10 @@  void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
 			goto err;
 
 		dig_port->hpd_pulse = intel_dp_hpd_pulse;
+
+		/* Splitter enable for eDP MSO is supported for pipe A only. */
+		if (dig_port->dp.mso_link_count)
+			encoder->pipe_mask = BIT(PIPE_A);
 	}
 
 	/* In theory we don't need the encoder->type check, but leave it just in
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 5bf0fc48b57a..c55e3c504c6d 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -8143,6 +8143,19 @@  static int intel_crtc_compute_config(struct intel_crtc *crtc,
 	int clock_limit = dev_priv->max_dotclk_freq;
 
 	drm_mode_copy(pipe_mode, &pipe_config->hw.adjusted_mode);
+	if (pipe_config->splitter.enable) {
+		int n = pipe_config->splitter.link_count;
+		int overlap = pipe_config->splitter.pixel_overlap;
+
+		pipe_mode->crtc_hdisplay = (pipe_mode->crtc_hdisplay - overlap) * n;
+		pipe_mode->crtc_hblank_start = (pipe_mode->crtc_hblank_start - overlap) * n;
+		pipe_mode->crtc_hblank_end = (pipe_mode->crtc_hblank_end - overlap) * n;
+		pipe_mode->crtc_hsync_start = (pipe_mode->crtc_hsync_start - overlap) * n;
+		pipe_mode->crtc_hsync_end = (pipe_mode->crtc_hsync_end - overlap) * n;
+		pipe_mode->crtc_htotal = (pipe_mode->crtc_htotal - overlap) * n;
+		pipe_mode->crtc_clock *= n;
+	}
+
 	intel_mode_from_crtc_timings(pipe_mode, pipe_mode);
 
 	if (INTEL_GEN(dev_priv) < 4) {
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 9a26ad896d01..12f3e4e4f568 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2685,6 +2685,7 @@  intel_dp_drrs_compute_config(struct intel_dp *intel_dp,
 {
 	struct intel_connector *intel_connector = intel_dp->attached_connector;
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+	int pixel_clock;
 
 	/*
 	 * DRRS and PSR can't be enable together, so giving preference to PSR
@@ -2700,10 +2701,18 @@  intel_dp_drrs_compute_config(struct intel_dp *intel_dp,
 		return;
 
 	pipe_config->has_drrs = true;
-	intel_link_compute_m_n(output_bpp, pipe_config->lane_count,
-			       intel_connector->panel.downclock_mode->clock,
+
+	pixel_clock = intel_connector->panel.downclock_mode->clock;
+	if (pipe_config->splitter.enable)
+		pixel_clock /= pipe_config->splitter.link_count;
+
+	intel_link_compute_m_n(output_bpp, pipe_config->lane_count, pixel_clock,
 			       pipe_config->port_clock, &pipe_config->dp_m2_n2,
 			       constant_n, pipe_config->fec_enable);
+
+	/* FIXME: abstract this better */
+	if (pipe_config->splitter.enable)
+		pipe_config->dp_m2_n2.gmch_m *= pipe_config->splitter.link_count;
 }
 
 int
@@ -2780,6 +2789,26 @@  intel_dp_compute_config(struct intel_encoder *encoder,
 	else
 		output_bpp = intel_dp_output_bpp(pipe_config, pipe_config->pipe_bpp);
 
+	if (intel_dp->mso_link_count) {
+		int n = intel_dp->mso_link_count;
+		int overlap = intel_dp->mso_pixel_overlap;
+
+		pipe_config->splitter.enable = true;
+		pipe_config->splitter.link_count = n;
+		pipe_config->splitter.pixel_overlap = overlap;
+
+		drm_dbg_kms(&dev_priv->drm, "MSO link count %d, pixel overlap %d\n",
+			    n, overlap);
+
+		adjusted_mode->crtc_hdisplay = adjusted_mode->crtc_hdisplay / n + overlap;
+		adjusted_mode->crtc_hblank_start = adjusted_mode->crtc_hblank_start / n + overlap;
+		adjusted_mode->crtc_hblank_end = adjusted_mode->crtc_hblank_end / n + overlap;
+		adjusted_mode->crtc_hsync_start = adjusted_mode->crtc_hsync_start / n + overlap;
+		adjusted_mode->crtc_hsync_end = adjusted_mode->crtc_hsync_end / n + overlap;
+		adjusted_mode->crtc_htotal = adjusted_mode->crtc_htotal / n + overlap;
+		adjusted_mode->crtc_clock /= n;
+	}
+
 	intel_link_compute_m_n(output_bpp,
 			       pipe_config->lane_count,
 			       adjusted_mode->crtc_clock,
@@ -2787,6 +2816,10 @@  intel_dp_compute_config(struct intel_encoder *encoder,
 			       &pipe_config->dp_m_n,
 			       constant_n, pipe_config->fec_enable);
 
+	/* FIXME: abstract this better */
+	if (pipe_config->splitter.enable)
+		pipe_config->dp_m_n.gmch_m *= pipe_config->splitter.link_count;
+
 	if (!HAS_DDI(dev_priv))
 		intel_dp_set_clock(encoder, pipe_config);
 
@@ -4787,8 +4820,10 @@  static void intel_edp_mso_init(struct intel_dp *intel_dp)
 	if (mso) {
 		drm_dbg_kms(&i915->drm, "Sink MSO %ux%u configuration\n",
 			    mso, drm_dp_max_lane_count(intel_dp->dpcd) / mso);
-		drm_err(&i915->drm, "No source MSO support, disabling\n");
-		mso = 0;
+		if (!HAS_MSO(i915)) {
+			drm_err(&i915->drm, "No source MSO support, disabling\n");
+			mso = 0;
+		}
 	}
 
 	intel_dp->mso_link_count = mso;