Commit 5b616a29 authored by Jani Nikula's avatar Jani Nikula
Browse files

drm/i915/mso: add splitter state readout for platforms that support it



Add splitter configuration to crtc state, and read it where
supported. Also add splitter state dumping. The stream splitter will be
required for eDP MSO.

v4:
- Catch invalid splitter configuration (Uma)

v3:
- Convert segment timings to full panel timings.
- Refer to splitter instead of mso in crtc state.
- Dump splitter state.

v2: Add warning for mso being enabled on pipes other than A.

Cc: Nischal Varide <nischal.varide@intel.com>
Cc: Uma Shankar <uma.shankar@intel.com>
Reviewed-by: default avatarUma Shankar <uma.shankar@intel.com>
Signed-off-by: default avatarJani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/95cbe1c9d45edf3e3ec252e49fb49055def98155.1614682842.git.jani.nikula@intel.com
parent a49388bd
Loading
Loading
Loading
Loading
+41 −0
Original line number Diff line number Diff line
@@ -2136,6 +2136,45 @@ static void intel_ddi_power_up_lanes(struct intel_encoder *encoder,
	}
}

static void intel_ddi_mso_get_config(struct intel_encoder *encoder,
				     struct intel_crtc_state *pipe_config)
{
	struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
	struct drm_i915_private *i915 = to_i915(crtc->base.dev);
	enum pipe pipe = crtc->pipe;
	u32 dss1;

	if (!HAS_MSO(i915))
		return;

	dss1 = intel_de_read(i915, ICL_PIPE_DSS_CTL1(pipe));

	pipe_config->splitter.enable = dss1 & SPLITTER_ENABLE;
	if (!pipe_config->splitter.enable)
		return;

	/* Splitter enable is supported for pipe A only. */
	if (drm_WARN_ON(&i915->drm, pipe != PIPE_A)) {
		pipe_config->splitter.enable = false;
		return;
	}

	switch (dss1 & SPLITTER_CONFIGURATION_MASK) {
	default:
		drm_WARN(&i915->drm, true,
			 "Invalid splitter configuration, dss1=0x%08x\n", dss1);
		fallthrough;
	case SPLITTER_CONFIGURATION_2_SEGMENT:
		pipe_config->splitter.link_count = 2;
		break;
	case SPLITTER_CONFIGURATION_4_SEGMENT:
		pipe_config->splitter.link_count = 4;
		break;
	}

	pipe_config->splitter.pixel_overlap = REG_FIELD_GET(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,
@@ -3316,6 +3355,8 @@ void intel_ddi_get_config(struct intel_encoder *encoder,
		intel_ddi_read_func_ctl(encoder, pipe_config);
	}

	intel_ddi_mso_get_config(encoder, pipe_config);

	pipe_config->has_audio =
		intel_ddi_is_audio_enabled(dev_priv, cpu_transcoder);

+29 −2
Original line number Diff line number Diff line
@@ -4862,8 +4862,30 @@ static void intel_crtc_readout_derived_state(struct intel_crtc_state *crtc_state
		pipe_mode->crtc_clock /= 2;
	}

	if (crtc_state->splitter.enable) {
		int n = crtc_state->splitter.link_count;
		int overlap = crtc_state->splitter.pixel_overlap;

		/*
		 * eDP MSO uses segment timings from EDID for transcoder
		 * timings, but full mode for everything else.
		 *
		 * h_full = (h_segment - pixel_overlap) * link_count
		 */
		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);
		intel_mode_from_crtc_timings(adjusted_mode, pipe_mode);
	} else {
		intel_mode_from_crtc_timings(pipe_mode, pipe_mode);
		intel_mode_from_crtc_timings(adjusted_mode, adjusted_mode);
	}

	intel_crtc_compute_pixel_rate(crtc_state);

@@ -8272,6 +8294,11 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config,
		    pipe_config->bigjoiner_slave ? "slave" :
		    pipe_config->bigjoiner ? "master" : "no");

	drm_dbg_kms(&dev_priv->drm, "splitter: %s, link count %d, overlap %d\n",
		    enableddisabled(pipe_config->splitter.enable),
		    pipe_config->splitter.link_count,
		    pipe_config->splitter.pixel_overlap);

	if (pipe_config->has_pch_encoder)
		intel_dump_m_n_config(pipe_config, "fdi",
				      pipe_config->fdi_lanes,
+7 −0
Original line number Diff line number Diff line
@@ -1169,6 +1169,13 @@ struct intel_crtc_state {
		u8 pipeline_full;
		u16 flipline, vmin, vmax;
	} vrr;

	/* Stream Splitter for eDP MSO */
	struct {
		bool enable;
		u8 link_count;
		u8 pixel_overlap;
	} splitter;
};

enum intel_pipe_crc_source {
+2 −0
Original line number Diff line number Diff line
@@ -1705,6 +1705,8 @@ tgl_stepping_get(struct drm_i915_private *dev_priv)

#define HAS_CSR(dev_priv)	(INTEL_INFO(dev_priv)->display.has_csr)

#define HAS_MSO(i915)		(INTEL_GEN(i915) >= 12)

#define HAS_RUNTIME_PM(dev_priv) (INTEL_INFO(dev_priv)->has_runtime_pm)
#define HAS_64BIT_RELOC(dev_priv) (INTEL_INFO(dev_priv)->has_64bit_reloc)