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

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
...@@ -2136,6 +2136,45 @@ static void intel_ddi_power_up_lanes(struct intel_encoder *encoder, ...@@ -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, static void tgl_ddi_pre_enable_dp(struct intel_atomic_state *state,
struct intel_encoder *encoder, struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state, const struct intel_crtc_state *crtc_state,
...@@ -3316,6 +3355,8 @@ void intel_ddi_get_config(struct intel_encoder *encoder, ...@@ -3316,6 +3355,8 @@ void intel_ddi_get_config(struct intel_encoder *encoder,
intel_ddi_read_func_ctl(encoder, pipe_config); intel_ddi_read_func_ctl(encoder, pipe_config);
} }
intel_ddi_mso_get_config(encoder, pipe_config);
pipe_config->has_audio = pipe_config->has_audio =
intel_ddi_is_audio_enabled(dev_priv, cpu_transcoder); intel_ddi_is_audio_enabled(dev_priv, cpu_transcoder);
......
...@@ -4862,8 +4862,30 @@ static void intel_crtc_readout_derived_state(struct intel_crtc_state *crtc_state ...@@ -4862,8 +4862,30 @@ static void intel_crtc_readout_derived_state(struct intel_crtc_state *crtc_state
pipe_mode->crtc_clock /= 2; pipe_mode->crtc_clock /= 2;
} }
intel_mode_from_crtc_timings(pipe_mode, pipe_mode); if (crtc_state->splitter.enable) {
intel_mode_from_crtc_timings(adjusted_mode, adjusted_mode); 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); intel_crtc_compute_pixel_rate(crtc_state);
...@@ -8272,6 +8294,11 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config, ...@@ -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_slave ? "slave" :
pipe_config->bigjoiner ? "master" : "no"); 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) if (pipe_config->has_pch_encoder)
intel_dump_m_n_config(pipe_config, "fdi", intel_dump_m_n_config(pipe_config, "fdi",
pipe_config->fdi_lanes, pipe_config->fdi_lanes,
......
...@@ -1169,6 +1169,13 @@ struct intel_crtc_state { ...@@ -1169,6 +1169,13 @@ struct intel_crtc_state {
u8 pipeline_full; u8 pipeline_full;
u16 flipline, vmin, vmax; u16 flipline, vmin, vmax;
} vrr; } vrr;
/* Stream Splitter for eDP MSO */
struct {
bool enable;
u8 link_count;
u8 pixel_overlap;
} splitter;
}; };
enum intel_pipe_crc_source { enum intel_pipe_crc_source {
......
...@@ -1705,6 +1705,8 @@ tgl_stepping_get(struct drm_i915_private *dev_priv) ...@@ -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_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_RUNTIME_PM(dev_priv) (INTEL_INFO(dev_priv)->has_runtime_pm)
#define HAS_64BIT_RELOC(dev_priv) (INTEL_INFO(dev_priv)->has_64bit_reloc) #define HAS_64BIT_RELOC(dev_priv) (INTEL_INFO(dev_priv)->has_64bit_reloc)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment