* [PATCH 0/4] Ultrajoiner basic functionality series
@ 2024-06-26 8:18 Stanislav Lisovskiy
2024-06-26 8:18 ` [PATCH 1/4] drm/i915: Add some essential functionality for joiners Stanislav Lisovskiy
` (5 more replies)
0 siblings, 6 replies; 15+ messages in thread
From: Stanislav Lisovskiy @ 2024-06-26 8:18 UTC (permalink / raw)
To: intel-gfx; +Cc: jani.saarinen, ville.syrjala
This patch series attempts to implement basic support
for Ultrajoiner functionality.
Stanislav Lisovskiy (4):
drm/i915: Add some essential functionality for joiners
drm/i915: Implement hw state readout for ultrajoiner
drm/i915: Compute config and mode valid changes for ultrajoiner
drm/i915: Add new abstraction layer to handle pipe order for different
joiners
.../gpu/drm/i915/display/intel_atomic_plane.c | 2 +-
drivers/gpu/drm/i915/display/intel_ddi.c | 19 +-
drivers/gpu/drm/i915/display/intel_display.c | 316 +++++++++++++++---
drivers/gpu/drm/i915/display/intel_display.h | 18 +-
drivers/gpu/drm/i915/display/intel_dp.c | 117 +++++--
drivers/gpu/drm/i915/display/intel_dp.h | 18 +-
drivers/gpu/drm/i915/display/intel_dp_mst.c | 54 +--
drivers/gpu/drm/i915/display/intel_dsi.c | 2 +-
drivers/gpu/drm/i915/display/intel_hdmi.c | 14 +-
.../drm/i915/display/intel_modeset_verify.c | 2 +-
drivers/gpu/drm/i915/display/intel_vdsc.c | 29 +-
.../gpu/drm/i915/display/intel_vdsc_regs.h | 3 +
12 files changed, 469 insertions(+), 125 deletions(-)
--
2.37.3
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 1/4] drm/i915: Add some essential functionality for joiners
2024-06-26 8:18 [PATCH 0/4] Ultrajoiner basic functionality series Stanislav Lisovskiy
@ 2024-06-26 8:18 ` Stanislav Lisovskiy
2024-06-26 10:23 ` Jani Nikula
2024-06-26 8:18 ` [PATCH 2/4] drm/i915: Implement hw state readout for ultrajoiner Stanislav Lisovskiy
` (4 subsequent siblings)
5 siblings, 1 reply; 15+ messages in thread
From: Stanislav Lisovskiy @ 2024-06-26 8:18 UTC (permalink / raw)
To: intel-gfx; +Cc: jani.saarinen, ville.syrjala
In most of the cases we now try to avoid mentioning things like
"bigjoiner" or "ultrajoiner" trying to unify the API and refer
mostly to all this functionality as "joiner".
In majority cases that should be way to go.
However in some cases we still need to distinguish between
bigjoiner primaries and secondaries(such as DSC register programming).
Create correspondent helper functions and start using them,
in order be prepared for adding ultrajoiner functionality.
Signed-off-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
---
.../gpu/drm/i915/display/intel_atomic_plane.c | 2 +-
drivers/gpu/drm/i915/display/intel_display.c | 76 ++++++++++++++++---
drivers/gpu/drm/i915/display/intel_display.h | 8 +-
.../drm/i915/display/intel_modeset_verify.c | 2 +-
drivers/gpu/drm/i915/display/intel_vdsc.c | 4 +-
5 files changed, 77 insertions(+), 15 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c
index 8ec1bab1b15d..966f8d0fd231 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c
+++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c
@@ -723,7 +723,7 @@ int intel_plane_atomic_check(struct intel_atomic_state *state,
if (new_crtc_state && intel_crtc_is_joiner_secondary(new_crtc_state)) {
struct intel_crtc *primary_crtc =
- intel_primary_crtc(new_crtc_state);
+ intel_joiner_primary_crtc(new_crtc_state);
struct intel_plane *primary_crtc_plane =
intel_crtc_get_plane(primary_crtc, plane->id);
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 7bc4f3de691e..5bc867ff81e1 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -251,6 +251,69 @@ static enum pipe joiner_primary_pipe(const struct intel_crtc_state *crtc_state)
return ffs(crtc_state->joiner_pipes) - 1;
}
+static int intel_joiner_num_pipes(const struct intel_crtc_state *crtc_state)
+{
+ return hweight8(crtc_state->joiner_pipes);
+}
+
+bool intel_crtc_is_ultrajoiner(const struct intel_crtc_state *crtc_state)
+{
+ return intel_joiner_num_pipes(crtc_state) == 4;
+}
+
+static bool intel_is_joiner(const struct intel_crtc_state *crtc_state)
+{
+ return intel_joiner_num_pipes(crtc_state) > 1;
+}
+
+static u8 bigjoiner_primary_pipes(const struct intel_crtc_state *crtc_state)
+{
+ int lsb = ffs(crtc_state->joiner_pipes) - 1;
+ int msb = fls(crtc_state->joiner_pipes) - 1;
+ int i;
+ u8 bigjoiner_primary_mask = 0;
+
+ for (i = lsb; i < msb; i += 4)
+ {
+ /*
+ * Regardless of how joiner_pipes mask is set, currently
+ * we always assume, that primary pipe bit goes before secondary
+ * pipe bit. So in each set of 2 bits, least significant bit is
+ * bigjoiner primary pipe and most significant bit is secondary pipe.
+ */
+ bigjoiner_primary_mask |=
+ ((BIT(0) | BIT(2)) << i) & crtc_state->joiner_pipes;
+ }
+
+ return bigjoiner_primary_mask;
+}
+
+bool intel_crtc_is_bigjoiner_primary(const struct intel_crtc_state *crtc_state)
+{
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+
+ if (!intel_is_joiner(crtc_state))
+ return false;
+
+ return BIT(crtc->pipe) & bigjoiner_primary_pipes(crtc_state);
+}
+
+bool intel_crtc_is_bigjoiner_secondary(const struct intel_crtc_state *crtc_state)
+{
+ if (!intel_is_joiner(crtc_state))
+ return false;
+
+ return !intel_crtc_is_bigjoiner_primary(crtc_state);
+}
+
+bool intel_crtc_is_ultrajoiner_primary(const struct intel_crtc_state *crtc_state)
+{
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+
+ return intel_crtc_is_ultrajoiner(crtc_state) &&
+ (crtc->pipe == joiner_primary_pipe(crtc_state));
+}
+
u8 intel_crtc_joiner_secondary_pipes(const struct intel_crtc_state *crtc_state)
{
if (crtc_state->joiner_pipes)
@@ -275,11 +338,6 @@ bool intel_crtc_is_joiner_primary(const struct intel_crtc_state *crtc_state)
crtc->pipe == joiner_primary_pipe(crtc_state);
}
-static int intel_joiner_num_pipes(const struct intel_crtc_state *crtc_state)
-{
- return hweight8(crtc_state->joiner_pipes);
-}
-
u8 intel_crtc_joined_pipe_mask(const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
@@ -287,7 +345,7 @@ u8 intel_crtc_joined_pipe_mask(const struct intel_crtc_state *crtc_state)
return BIT(crtc->pipe) | crtc_state->joiner_pipes;
}
-struct intel_crtc *intel_primary_crtc(const struct intel_crtc_state *crtc_state)
+struct intel_crtc *intel_joiner_primary_crtc(const struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
@@ -807,7 +865,7 @@ intel_get_crtc_new_encoder(const struct intel_atomic_state *state,
int num_encoders = 0;
int i;
- primary_crtc = intel_primary_crtc(crtc_state);
+ primary_crtc = intel_joiner_primary_crtc(crtc_state);
for_each_new_connector_in_state(&state->base, connector, connector_state, i) {
if (connector_state->crtc != &primary_crtc->base)
@@ -4516,7 +4574,7 @@ copy_joiner_crtc_state_nomodeset(struct intel_atomic_state *state,
{
struct intel_crtc_state *secondary_crtc_state =
intel_atomic_get_new_crtc_state(state, secondary_crtc);
- struct intel_crtc *primary_crtc = intel_primary_crtc(secondary_crtc_state);
+ struct intel_crtc *primary_crtc = intel_joiner_primary_crtc(secondary_crtc_state);
const struct intel_crtc_state *primary_crtc_state =
intel_atomic_get_new_crtc_state(state, primary_crtc);
@@ -4536,7 +4594,7 @@ copy_joiner_crtc_state_modeset(struct intel_atomic_state *state,
{
struct intel_crtc_state *secondary_crtc_state =
intel_atomic_get_new_crtc_state(state, secondary_crtc);
- struct intel_crtc *primary_crtc = intel_primary_crtc(secondary_crtc_state);
+ struct intel_crtc *primary_crtc = intel_joiner_primary_crtc(secondary_crtc_state);
const struct intel_crtc_state *primary_crtc_state =
intel_atomic_get_new_crtc_state(state, primary_crtc);
struct intel_crtc_state *saved_state;
diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
index b0cf6ca70952..bac81b7ab764 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -423,10 +423,14 @@ enum phy intel_port_to_phy(struct drm_i915_private *i915, enum port port);
bool is_trans_port_sync_mode(const struct intel_crtc_state *state);
bool is_trans_port_sync_master(const struct intel_crtc_state *state);
u8 intel_crtc_joined_pipe_mask(const struct intel_crtc_state *crtc_state);
-bool intel_crtc_is_joiner_secondary(const struct intel_crtc_state *crtc_state);
bool intel_crtc_is_joiner_primary(const struct intel_crtc_state *crtc_state);
+bool intel_crtc_is_joiner_secondary(const struct intel_crtc_state *crtc_state);
+bool intel_crtc_is_bigjoiner_primary(const struct intel_crtc_state *crtc_state);
+bool intel_crtc_is_bigjoiner_secondary(const struct intel_crtc_state *crtc_state);
+bool intel_crtc_is_ultrajoiner(const struct intel_crtc_state *crtc_state);
+bool intel_crtc_is_ultrajoiner_primary(const struct intel_crtc_state *crtc_state);
u8 intel_crtc_joiner_secondary_pipes(const struct intel_crtc_state *crtc_state);
-struct intel_crtc *intel_primary_crtc(const struct intel_crtc_state *crtc_state);
+struct intel_crtc *intel_joiner_primary_crtc(const struct intel_crtc_state *crtc_state);
bool intel_crtc_get_pipe_config(struct intel_crtc_state *crtc_state);
bool intel_pipe_config_compare(const struct intel_crtc_state *current_config,
const struct intel_crtc_state *pipe_config,
diff --git a/drivers/gpu/drm/i915/display/intel_modeset_verify.c b/drivers/gpu/drm/i915/display/intel_modeset_verify.c
index 3491db5cad31..b53b810c6470 100644
--- a/drivers/gpu/drm/i915/display/intel_modeset_verify.c
+++ b/drivers/gpu/drm/i915/display/intel_modeset_verify.c
@@ -193,7 +193,7 @@ verify_crtc_state(struct intel_atomic_state *state,
"transitional active state does not match atomic hw state (expected %i, found %i)\n",
sw_crtc_state->hw.active, crtc->active);
- primary_crtc = intel_primary_crtc(sw_crtc_state);
+ primary_crtc = intel_joiner_primary_crtc(sw_crtc_state);
for_each_encoder_on_crtc(dev, &primary_crtc->base, encoder) {
enum pipe pipe;
diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c
index b9687b7692b8..11058bb37d5a 100644
--- a/drivers/gpu/drm/i915/display/intel_vdsc.c
+++ b/drivers/gpu/drm/i915/display/intel_vdsc.c
@@ -761,7 +761,7 @@ void intel_uncompressed_joiner_enable(const struct intel_crtc_state *crtc_state)
u32 dss_ctl1_val = 0;
if (crtc_state->joiner_pipes && !crtc_state->dsc.compression_enable) {
- if (intel_crtc_is_joiner_secondary(crtc_state))
+ if (intel_crtc_is_bigjoiner_secondary(crtc_state))
dss_ctl1_val |= UNCOMPRESSED_JOINER_SECONDARY;
else
dss_ctl1_val |= UNCOMPRESSED_JOINER_PRIMARY;
@@ -790,7 +790,7 @@ void intel_dsc_enable(const struct intel_crtc_state *crtc_state)
}
if (crtc_state->joiner_pipes) {
dss_ctl1_val |= BIG_JOINER_ENABLE;
- if (!intel_crtc_is_joiner_secondary(crtc_state))
+ if (intel_crtc_is_bigjoiner_primary(crtc_state))
dss_ctl1_val |= PRIMARY_BIG_JOINER_ENABLE;
}
intel_de_write(dev_priv, dss_ctl1_reg(crtc, crtc_state->cpu_transcoder), dss_ctl1_val);
--
2.37.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 2/4] drm/i915: Implement hw state readout for ultrajoiner
2024-06-26 8:18 [PATCH 0/4] Ultrajoiner basic functionality series Stanislav Lisovskiy
2024-06-26 8:18 ` [PATCH 1/4] drm/i915: Add some essential functionality for joiners Stanislav Lisovskiy
@ 2024-06-26 8:18 ` Stanislav Lisovskiy
2024-07-01 19:17 ` Ville Syrjälä
2024-06-26 8:18 ` [PATCH 3/4] drm/i915: Compute config and mode valid changes " Stanislav Lisovskiy
` (3 subsequent siblings)
5 siblings, 1 reply; 15+ messages in thread
From: Stanislav Lisovskiy @ 2024-06-26 8:18 UTC (permalink / raw)
To: intel-gfx; +Cc: jani.saarinen, ville.syrjala
Ultrajoiner mode has some new bits and states to be
read out from the hw. Lets make changes accordingly.
v2: - Split enabled_joiner_pipes readout procedure into
3 parts, each of them taking care of uncompressed joiner,
bigjoiner and ultrajoiner respectively and then do
some sanity check(for example all the pipes which are used
in ultrajoiner, should also belong to bigjoiner)
SIgned-off-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
---
drivers/gpu/drm/i915/display/intel_display.c | 162 +++++++++++++++---
.../gpu/drm/i915/display/intel_vdsc_regs.h | 3 +
2 files changed, 142 insertions(+), 23 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 5bc867ff81e1..f702ead9b5f3 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -3580,8 +3580,42 @@ static bool transcoder_ddi_func_is_enabled(struct drm_i915_private *dev_priv,
return tmp & TRANS_DDI_FUNC_ENABLE;
}
-static void enabled_joiner_pipes(struct drm_i915_private *dev_priv,
- u8 *primary_pipes, u8 *secondary_pipes)
+static void enabled_uncompressed_joiner_pipes(struct drm_i915_private *dev_priv,
+ u8 *primary_pipes, u8 *secondary_pipes)
+{
+ struct intel_crtc *crtc;
+
+ *primary_pipes = 0;
+ *secondary_pipes = 0;
+
+ for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, crtc,
+ joiner_pipes(dev_priv)) {
+ enum intel_display_power_domain power_domain;
+ enum pipe pipe = crtc->pipe;
+ intel_wakeref_t wakeref;
+
+ if (DISPLAY_VER(dev_priv) < 13)
+ continue;
+
+ power_domain = POWER_DOMAIN_PIPE(pipe);
+ with_intel_display_power_if_enabled(dev_priv, power_domain, wakeref) {
+ u32 tmp = intel_de_read(dev_priv, ICL_PIPE_DSS_CTL1(pipe));
+
+ if (tmp & UNCOMPRESSED_JOINER_PRIMARY)
+ *primary_pipes |= BIT(pipe);
+ if (tmp & UNCOMPRESSED_JOINER_SECONDARY)
+ *secondary_pipes |= BIT(pipe);
+ }
+ }
+
+ /* Joiner pipes should always be consecutive primary and secondary */
+ drm_WARN(&dev_priv->drm, *secondary_pipes != *primary_pipes << 1,
+ "Uncompressed joiner misconfigured (primary pipes 0x%x, secondary pipes 0x%x)\n",
+ *primary_pipes, *secondary_pipes);
+}
+
+static void enabled_bigjoiner_pipes(struct drm_i915_private *dev_priv,
+ u8 *primary_pipes, u8 *secondary_pipes)
{
struct intel_crtc *crtc;
@@ -3606,28 +3640,95 @@ static void enabled_joiner_pipes(struct drm_i915_private *dev_priv,
else
*secondary_pipes |= BIT(pipe);
}
+ }
- if (DISPLAY_VER(dev_priv) < 13)
- continue;
+ /* Joiner pipes should always be consecutive primary and secondary */
+ drm_WARN(&dev_priv->drm, *secondary_pipes != *primary_pipes << 1,
+ "Bigjoiner misconfigured (primary pipes 0x%x, secondary pipes 0x%x)\n",
+ *primary_pipes, *secondary_pipes);
+}
- power_domain = POWER_DOMAIN_PIPE(pipe);
+static void enabled_ultrajoiner_pipes(struct drm_i915_private *dev_priv,
+ u8 *primary_pipes, u8 *secondary_pipes)
+{
+ struct intel_crtc *crtc;
+
+ *primary_pipes = 0;
+ *secondary_pipes = 0;
+
+ for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, crtc,
+ joiner_pipes(dev_priv)) {
+ enum intel_display_power_domain power_domain;
+ enum pipe pipe = crtc->pipe;
+ intel_wakeref_t wakeref;
+
+ power_domain = intel_dsc_power_domain(crtc, (enum transcoder) pipe);
with_intel_display_power_if_enabled(dev_priv, power_domain, wakeref) {
u32 tmp = intel_de_read(dev_priv, ICL_PIPE_DSS_CTL1(pipe));
- if (tmp & UNCOMPRESSED_JOINER_PRIMARY)
+ if (!(tmp & ULTRA_JOINER_ENABLE))
+ continue;
+
+ /*
+ * As of now we always assume primary master to be PIPE A.
+ * Otherwise we need a new field in crtc_state to track
+ * primary master as well.
+ */
+ drm_WARN(&dev_priv->drm,
+ (tmp & PRIMARY_ULTRA_JOINER_ENABLE) && crtc->pipe != PIPE_A,
+ "Ultrajoiner primary master isn't PIPE A(pipe %c)",
+ pipe_name(crtc->pipe));
+
+ if (tmp & PRIMARY_ULTRA_JOINER_ENABLE)
*primary_pipes |= BIT(pipe);
- if (tmp & UNCOMPRESSED_JOINER_SECONDARY)
+ else
*secondary_pipes |= BIT(pipe);
}
}
+}
- /* Joiner pipes should always be consecutive primary and secondary */
- drm_WARN(&dev_priv->drm, *secondary_pipes != *primary_pipes << 1,
- "Joiner misconfigured (primary pipes 0x%x, secondary pipes 0x%x)\n",
- *primary_pipes, *secondary_pipes);
+static void enabled_joiner_pipes(struct drm_i915_private *dev_priv,
+ u8 *primary_pipes, u8 *secondary_pipes,
+ bool *ultrajoiner_used)
+{
+ u8 primary_uncompressed_joiner_pipes, primary_bigjoiner_pipes;
+ u8 primary_ultrajoiner_pipes;
+ u8 secondary_uncompressed_joiner_pipes, secondary_bigjoiner_pipes;
+ u8 secondary_ultrajoiner_pipes;
+ u8 ultrajoiner_pipes, bigjoiner_pipes;
+
+ enabled_uncompressed_joiner_pipes(dev_priv, &primary_uncompressed_joiner_pipes,
+ &secondary_uncompressed_joiner_pipes);
+
+ enabled_bigjoiner_pipes(dev_priv, &primary_bigjoiner_pipes,
+ &secondary_bigjoiner_pipes);
+
+ enabled_ultrajoiner_pipes(dev_priv, &primary_ultrajoiner_pipes,
+ &secondary_ultrajoiner_pipes);
+
+ *primary_pipes = 0;
+ *secondary_pipes = 0;
+ *ultrajoiner_used = primary_ultrajoiner_pipes && secondary_ultrajoiner_pipes;
+ ultrajoiner_pipes = primary_ultrajoiner_pipes | secondary_ultrajoiner_pipes;
+ bigjoiner_pipes = primary_bigjoiner_pipes | secondary_bigjoiner_pipes;
+
+ drm_WARN(&dev_priv->drm,
+ (ultrajoiner_pipes & bigjoiner_pipes) == ultrajoiner_pipes,
+ "Ultrajoiner/Bigjoiner misconfigured:"
+ "Ultrajoiner pipes: 0x%x(primary) 0x%x(secondary),"
+ "Bigjoiner pipes: 0x%x(primary) 0x%x(secondary)",
+ primary_ultrajoiner_pipes, secondary_ultrajoiner_pipes,
+ primary_bigjoiner_pipes, secondary_bigjoiner_pipes);
+
+ *primary_pipes = primary_uncompressed_joiner_pipes | primary_bigjoiner_pipes |
+ primary_ultrajoiner_pipes;
+
+ *secondary_pipes = secondary_uncompressed_joiner_pipes | secondary_bigjoiner_pipes |
+ secondary_ultrajoiner_pipes;
}
-static enum pipe get_joiner_primary_pipe(enum pipe pipe, u8 primary_pipes, u8 secondary_pipes)
+static enum pipe get_joiner_primary_pipe(enum pipe pipe, u8 primary_pipes,
+ u8 secondary_pipes, bool ultrajoiner_used)
{
if ((secondary_pipes & BIT(pipe)) == 0)
return pipe;
@@ -3635,15 +3736,22 @@ static enum pipe get_joiner_primary_pipe(enum pipe pipe, u8 primary_pipes, u8 se
/* ignore everything above our pipe */
primary_pipes &= ~GENMASK(7, pipe);
- /* highest remaining bit should be our primary pipe */
- return fls(primary_pipes) - 1;
+ if (!ultrajoiner_used) {
+ /* highest remaining bit should be our master pipe */
+ return fls(primary_pipes) - 1;
+ } else {
+ /* lowest remaining bit should be our primary master pipe */
+ return ffs(primary_pipes) - 1;
+ }
}
-static u8 get_joiner_secondary_pipes(enum pipe pipe, u8 primary_pipes, u8 secondary_pipes)
+static u8 get_joiner_secondary_pipes(enum pipe pipe, u8 primary_pipes,
+ u8 secondary_pipes, bool ultrajoiner_used)
{
enum pipe primary_pipe, next_primary_pipe;
- primary_pipe = get_joiner_primary_pipe(pipe, primary_pipes, secondary_pipes);
+ primary_pipe = get_joiner_primary_pipe(pipe, primary_pipes,
+ secondary_pipes, ultrajoiner_used);
if ((primary_pipes & BIT(primary_pipe)) == 0)
return 0;
@@ -3655,7 +3763,10 @@ static u8 get_joiner_secondary_pipes(enum pipe pipe, u8 primary_pipes, u8 second
/* lowest remaining bit should be the next primary pipe */
next_primary_pipe = ffs(primary_pipes) - 1;
- return secondary_pipes & GENMASK(next_primary_pipe - 1, primary_pipe);
+ if (!ultrajoiner_used)
+ return secondary_pipes & GENMASK(next_primary_pipe - 1, primary_pipe);
+ else
+ return (secondary_pipes | primary_pipes) & ~BIT(primary_pipe);
}
static u8 hsw_panel_transcoders(struct drm_i915_private *i915)
@@ -3676,6 +3787,7 @@ static u8 hsw_enabled_transcoders(struct intel_crtc *crtc)
enum transcoder cpu_transcoder;
u8 primary_pipes, secondary_pipes;
u8 enabled_transcoders = 0;
+ bool ultrajoiner_used;
/*
* XXX: Do intel_display_power_get_if_enabled before reading this (for
@@ -3726,11 +3838,12 @@ static u8 hsw_enabled_transcoders(struct intel_crtc *crtc)
if (transcoder_ddi_func_is_enabled(dev_priv, cpu_transcoder))
enabled_transcoders |= BIT(cpu_transcoder);
- /* joiner secondary -> consider the primary pipe's transcoder as well */
- enabled_joiner_pipes(dev_priv, &primary_pipes, &secondary_pipes);
+ /* joiner slave -> consider the master pipe's transcoder as well */
+ enabled_joiner_pipes(dev_priv, &primary_pipes, &secondary_pipes, &ultrajoiner_used);
if (secondary_pipes & BIT(crtc->pipe)) {
cpu_transcoder = (enum transcoder)
- get_joiner_primary_pipe(crtc->pipe, primary_pipes, secondary_pipes);
+ get_joiner_primary_pipe(crtc->pipe, primary_pipes,
+ secondary_pipes, ultrajoiner_used);
if (transcoder_ddi_func_is_enabled(dev_priv, cpu_transcoder))
enabled_transcoders |= BIT(cpu_transcoder);
}
@@ -3863,15 +3976,18 @@ static void intel_joiner_get_config(struct intel_crtc_state *crtc_state)
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
u8 primary_pipes, secondary_pipes;
enum pipe pipe = crtc->pipe;
+ bool ultrajoiner_used;
- enabled_joiner_pipes(i915, &primary_pipes, &secondary_pipes);
+ enabled_joiner_pipes(i915, &primary_pipes, &secondary_pipes, &ultrajoiner_used);
if (((primary_pipes | secondary_pipes) & BIT(pipe)) == 0)
return;
crtc_state->joiner_pipes =
- BIT(get_joiner_primary_pipe(pipe, primary_pipes, secondary_pipes)) |
- get_joiner_secondary_pipes(pipe, primary_pipes, secondary_pipes);
+ BIT(get_joiner_primary_pipe(pipe, primary_pipes,
+ secondary_pipes, ultrajoiner_used)) |
+ get_joiner_secondary_pipes(pipe, primary_pipes,
+ secondary_pipes, ultrajoiner_used);
}
static bool hsw_get_pipe_config(struct intel_crtc *crtc,
diff --git a/drivers/gpu/drm/i915/display/intel_vdsc_regs.h b/drivers/gpu/drm/i915/display/intel_vdsc_regs.h
index f921ad67b587..016d7ce48215 100644
--- a/drivers/gpu/drm/i915/display/intel_vdsc_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_vdsc_regs.h
@@ -37,6 +37,9 @@
#define SPLITTER_CONFIGURATION_MASK REG_GENMASK(26, 25)
#define SPLITTER_CONFIGURATION_2_SEGMENT REG_FIELD_PREP(SPLITTER_CONFIGURATION_MASK, 0)
#define SPLITTER_CONFIGURATION_4_SEGMENT REG_FIELD_PREP(SPLITTER_CONFIGURATION_MASK, 1)
+
+#define ULTRA_JOINER_ENABLE (1 << 23)
+#define PRIMARY_ULTRA_JOINER_ENABLE (1 << 22)
#define UNCOMPRESSED_JOINER_PRIMARY (1 << 21)
#define UNCOMPRESSED_JOINER_SECONDARY (1 << 20)
--
2.37.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 3/4] drm/i915: Compute config and mode valid changes for ultrajoiner
2024-06-26 8:18 [PATCH 0/4] Ultrajoiner basic functionality series Stanislav Lisovskiy
2024-06-26 8:18 ` [PATCH 1/4] drm/i915: Add some essential functionality for joiners Stanislav Lisovskiy
2024-06-26 8:18 ` [PATCH 2/4] drm/i915: Implement hw state readout for ultrajoiner Stanislav Lisovskiy
@ 2024-06-26 8:18 ` Stanislav Lisovskiy
2024-07-03 8:51 ` Nautiyal, Ankit K
2024-07-03 8:59 ` Nautiyal, Ankit K
2024-06-26 8:18 ` [PATCH 4/4] drm/i915: Add new abstraction layer to handle pipe order for different joiners Stanislav Lisovskiy
` (2 subsequent siblings)
5 siblings, 2 replies; 15+ messages in thread
From: Stanislav Lisovskiy @ 2024-06-26 8:18 UTC (permalink / raw)
To: intel-gfx; +Cc: jani.saarinen, ville.syrjala
Implement required changes for mode validation and compute config,
to support Ultrajoiner.
This also includes required DSC changes and checks.
Signed-off-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
---
drivers/gpu/drm/i915/display/intel_display.c | 5 +-
drivers/gpu/drm/i915/display/intel_display.h | 3 +-
drivers/gpu/drm/i915/display/intel_dp.c | 117 ++++++++++++++-----
drivers/gpu/drm/i915/display/intel_dp.h | 18 ++-
drivers/gpu/drm/i915/display/intel_dp_mst.c | 35 +++---
drivers/gpu/drm/i915/display/intel_dsi.c | 2 +-
drivers/gpu/drm/i915/display/intel_hdmi.c | 14 ++-
drivers/gpu/drm/i915/display/intel_vdsc.c | 25 +++-
8 files changed, 164 insertions(+), 55 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index f702ead9b5f3..4c934f07ead7 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -8246,7 +8246,8 @@ enum drm_mode_status intel_cpu_transcoder_mode_valid(struct drm_i915_private *de
enum drm_mode_status
intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv,
const struct drm_display_mode *mode,
- bool joiner)
+ bool bigjoiner,
+ bool ultrajoiner)
{
int plane_width_max, plane_height_max;
@@ -8263,7 +8264,7 @@ intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv,
* too big for that.
*/
if (DISPLAY_VER(dev_priv) >= 11) {
- plane_width_max = 5120 << joiner;
+ plane_width_max = (5120 << bigjoiner) << ultrajoiner;
plane_height_max = 4320;
} else {
plane_width_max = 5120;
diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
index bac81b7ab764..0a51f24af405 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -415,7 +415,8 @@ u32 intel_plane_fb_max_stride(struct drm_i915_private *dev_priv,
enum drm_mode_status
intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv,
const struct drm_display_mode *mode,
- bool joiner);
+ bool bigjoiner,
+ bool ultrajoiner);
enum drm_mode_status
intel_cpu_transcoder_mode_valid(struct drm_i915_private *i915,
const struct drm_display_mode *mode);
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 3903f6ead6e6..1ea1e89d8f45 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -760,33 +760,41 @@ u32 intel_dp_dsc_nearest_valid_bpp(struct drm_i915_private *i915, u32 bpp, u32 p
static
u32 get_max_compressed_bpp_with_joiner(struct drm_i915_private *i915,
u32 mode_clock, u32 mode_hdisplay,
- bool bigjoiner)
+ bool bigjoiner, bool ultrajoiner)
{
u32 max_bpp_small_joiner_ram;
+ u32 max_bpp_joiner;
/* Small Joiner Check: output bpp <= joiner RAM (bits) / Horiz. width */
- max_bpp_small_joiner_ram = small_joiner_ram_size_bits(i915) / mode_hdisplay;
+ max_bpp_joiner = max_bpp_small_joiner_ram =
+ small_joiner_ram_size_bits(i915) / mode_hdisplay;
- if (bigjoiner) {
- int bigjoiner_interface_bits = DISPLAY_VER(i915) >= 14 ? 36 : 24;
- /* With bigjoiner multiple dsc engines are used in parallel so PPC is 2 */
+ /* if ultra joiner is enabled, we have 2 bigjoiners enabled */
+ if (bigjoiner || ultrajoiner) {
+ int joiner_interface_bits = DISPLAY_VER(i915) >= 14 ? 36 : 24;
+ /* With joiner multiple dsc engines are used in parallel so PPC is 2 */
int ppc = 2;
- u32 max_bpp_bigjoiner =
- i915->display.cdclk.max_cdclk_freq * ppc * bigjoiner_interface_bits /
+ max_bpp_joiner =
+ i915->display.cdclk.max_cdclk_freq * ppc * joiner_interface_bits /
intel_dp_mode_to_fec_clock(mode_clock);
max_bpp_small_joiner_ram *= 2;
+ }
- return min(max_bpp_small_joiner_ram, max_bpp_bigjoiner);
+ if (ultrajoiner) {
+ /* both get multiplied by 2, because ram bits/ppc now doubled */
+ max_bpp_small_joiner_ram *= 2;
+ max_bpp_joiner *= 2;
}
- return max_bpp_small_joiner_ram;
+ return min(max_bpp_small_joiner_ram, max_bpp_joiner);
}
u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915,
u32 link_clock, u32 lane_count,
u32 mode_clock, u32 mode_hdisplay,
bool bigjoiner,
+ bool ultrajoiner,
enum intel_output_format output_format,
u32 pipe_bpp,
u32 timeslots)
@@ -832,7 +840,7 @@ u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915,
intel_dp_mode_to_fec_clock(mode_clock));
joiner_max_bpp = get_max_compressed_bpp_with_joiner(i915, mode_clock,
- mode_hdisplay, bigjoiner);
+ mode_hdisplay, bigjoiner, ultrajoiner);
bits_per_pixel = min(bits_per_pixel, joiner_max_bpp);
bits_per_pixel = intel_dp_dsc_nearest_valid_bpp(i915, bits_per_pixel, pipe_bpp);
@@ -842,7 +850,8 @@ u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915,
u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
int mode_clock, int mode_hdisplay,
- bool bigjoiner)
+ bool bigjoiner,
+ bool ultrajoiner)
{
struct drm_i915_private *i915 = to_i915(connector->base.dev);
u8 min_slice_count, i;
@@ -876,7 +885,7 @@ u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
/* Find the closest match to the valid slice count values */
for (i = 0; i < ARRAY_SIZE(valid_dsc_slicecount); i++) {
- u8 test_slice_count = valid_dsc_slicecount[i] << bigjoiner;
+ u8 test_slice_count = (valid_dsc_slicecount[i] << bigjoiner) << ultrajoiner;
if (test_slice_count >
drm_dp_dsc_sink_max_slice_count(connector->dp.dsc_dpcd, false))
@@ -886,6 +895,10 @@ u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
if (bigjoiner && test_slice_count < 4)
continue;
+ /* ultrajoiner needs 2 bigjoiners to be enabled */
+ if (ultrajoiner && test_slice_count < 8)
+ continue;
+
if (min_slice_count <= test_slice_count)
return test_slice_count;
}
@@ -1162,9 +1175,9 @@ intel_dp_mode_valid_downstream(struct intel_connector *connector,
return MODE_OK;
}
-bool intel_dp_need_joiner(struct intel_dp *intel_dp,
- struct intel_connector *connector,
- int hdisplay, int clock)
+bool intel_dp_need_bigjoiner(struct intel_dp *intel_dp,
+ struct intel_connector *connector,
+ int hdisplay, int clock)
{
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
@@ -1195,6 +1208,35 @@ bool intel_dp_has_dsc(const struct intel_connector *connector)
return true;
}
+static
+bool intel_can_ultrajoiner(const struct intel_encoder *encoder)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+ return IS_DGFX(i915) && DISPLAY_VER(i915) >= 14;
+}
+
+bool intel_dp_need_ultrajoiner(struct intel_dp *dp, int clock)
+{
+ const struct intel_encoder *encoder = &dp_to_dig_port(dp)->base;
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+ if (!intel_can_ultrajoiner(encoder))
+ return false;
+
+ return clock > (i915->display.cdclk.max_dotclk_freq * 2);
+}
+
+bool intel_is_bigjoiner(const struct intel_crtc_state *pipe_config)
+{
+ return hweight8(pipe_config->joiner_pipes) == 2;
+}
+
+bool intel_is_ultrajoiner(const struct intel_crtc_state *pipe_config)
+{
+ return hweight8(pipe_config->joiner_pipes) == 4;
+}
+
static enum drm_mode_status
intel_dp_mode_valid(struct drm_connector *_connector,
struct drm_display_mode *mode)
@@ -1209,7 +1251,7 @@ intel_dp_mode_valid(struct drm_connector *_connector,
u16 dsc_max_compressed_bpp = 0;
u8 dsc_slice_count = 0;
enum drm_mode_status status;
- bool dsc = false, joiner = false;
+ bool dsc = false, bigjoiner = false, ultrajoiner = false;
status = intel_cpu_transcoder_mode_valid(dev_priv, mode);
if (status != MODE_OK)
@@ -1230,11 +1272,16 @@ intel_dp_mode_valid(struct drm_connector *_connector,
target_clock = fixed_mode->clock;
}
- if (intel_dp_need_joiner(intel_dp, connector,
- mode->hdisplay, target_clock)) {
- joiner = true;
+ if (intel_dp_need_ultrajoiner(intel_dp, target_clock)) {
+ ultrajoiner = true;
+ max_dotclk *= 4;
+ }
+ else if (intel_dp_need_bigjoiner(intel_dp, connector,
+ mode->hdisplay, target_clock)) {
+ bigjoiner = true;
max_dotclk *= 2;
}
+
if (target_clock > max_dotclk)
return MODE_CLOCK_HIGH;
@@ -1278,20 +1325,22 @@ intel_dp_mode_valid(struct drm_connector *_connector,
max_lanes,
target_clock,
mode->hdisplay,
- joiner,
+ bigjoiner,
+ ultrajoiner,
output_format,
pipe_bpp, 64);
dsc_slice_count =
intel_dp_dsc_get_slice_count(connector,
target_clock,
mode->hdisplay,
- joiner);
+ bigjoiner,
+ ultrajoiner);
}
dsc = dsc_max_compressed_bpp && dsc_slice_count;
}
- if (intel_dp_joiner_needs_dsc(dev_priv, joiner) && !dsc)
+ if (intel_dp_joiner_needs_dsc(dev_priv, bigjoiner, ultrajoiner) && !dsc)
return MODE_CLOCK_HIGH;
if (mode_rate > max_rate && !dsc)
@@ -1301,7 +1350,7 @@ intel_dp_mode_valid(struct drm_connector *_connector,
if (status != MODE_OK)
return status;
- return intel_mode_valid_max_plane_size(dev_priv, mode, joiner);
+ return intel_mode_valid_max_plane_size(dev_priv, mode, bigjoiner, ultrajoiner);
}
bool intel_dp_source_supports_tps3(struct drm_i915_private *i915)
@@ -2015,7 +2064,8 @@ static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp,
dsc_joiner_max_bpp = get_max_compressed_bpp_with_joiner(i915, adjusted_mode->clock,
adjusted_mode->hdisplay,
- pipe_config->joiner_pipes);
+ intel_is_bigjoiner(pipe_config),
+ intel_is_ultrajoiner(pipe_config));
dsc_max_bpp = min(dsc_max_bpp, dsc_joiner_max_bpp);
dsc_max_bpp = min(dsc_max_bpp, to_bpp_int(limits->link.max_bpp_x16));
@@ -2249,7 +2299,8 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
intel_dp_dsc_get_slice_count(connector,
adjusted_mode->crtc_clock,
adjusted_mode->crtc_hdisplay,
- pipe_config->joiner_pipes);
+ intel_is_bigjoiner(pipe_config),
+ intel_is_ultrajoiner(pipe_config));
if (!dsc_dp_slice_count) {
drm_dbg_kms(&dev_priv->drm,
"Compressed Slice Count not supported\n");
@@ -2399,14 +2450,15 @@ int intel_dp_config_required_rate(const struct intel_crtc_state *crtc_state)
return intel_dp_link_required(adjusted_mode->crtc_clock, bpp);
}
-bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915, bool use_joiner)
+bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915, bool bigjoiner, bool ultrajoiner)
{
/*
* Pipe joiner needs compression up to display 12 due to bandwidth
* limitation. DG2 onwards pipe joiner can be enabled without
* compression.
+ * Ultrajoiner always needs compression.
*/
- return DISPLAY_VER(i915) < 13 && use_joiner;
+ return (DISPLAY_VER(i915) < 13 && bigjoiner) || ultrajoiner;
}
static int
@@ -2424,18 +2476,21 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
struct link_config_limits limits;
bool dsc_needed, joiner_needs_dsc;
+ bool bigjoiner = false, ultrajoiner = false;
int ret = 0;
if (pipe_config->fec_enable &&
!intel_dp_supports_fec(intel_dp, connector, pipe_config))
return -EINVAL;
- if (intel_dp_need_joiner(intel_dp, connector,
- adjusted_mode->crtc_hdisplay,
- adjusted_mode->crtc_clock))
+ if (intel_dp_need_ultrajoiner(intel_dp, adjusted_mode->crtc_clock))
+ pipe_config->joiner_pipes = GENMASK(crtc->pipe + 3, crtc->pipe);
+ else if (intel_dp_need_bigjoiner(intel_dp, connector,
+ adjusted_mode->crtc_hdisplay,
+ adjusted_mode->crtc_clock))
pipe_config->joiner_pipes = GENMASK(crtc->pipe + 1, crtc->pipe);
- joiner_needs_dsc = intel_dp_joiner_needs_dsc(i915, pipe_config->joiner_pipes);
+ joiner_needs_dsc = intel_dp_joiner_needs_dsc(i915, bigjoiner, ultrajoiner);
dsc_needed = joiner_needs_dsc || intel_dp->force_dsc_en ||
!intel_dp_compute_config_limits(intel_dp, pipe_config,
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
index a0f990a95ecc..6a3615757c95 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -122,7 +122,7 @@ int intel_dp_effective_data_rate(int pixel_clock, int bpp_x16,
int bw_overhead);
int intel_dp_max_link_data_rate(struct intel_dp *intel_dp,
int max_dprx_rate, int max_dprx_lanes);
-bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915, bool use_joiner);
+bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915, bool use_bigjoiner, bool use_ultrajoiner);
bool intel_dp_has_joiner(struct intel_dp *intel_dp);
bool intel_dp_needs_vsc_sdp(const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state);
@@ -142,6 +142,7 @@ u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915,
u32 link_clock, u32 lane_count,
u32 mode_clock, u32 mode_hdisplay,
bool bigjoiner,
+ bool ultrajoiner,
enum intel_output_format output_format,
u32 pipe_bpp,
u32 timeslots);
@@ -151,10 +152,17 @@ int intel_dp_dsc_sink_max_compressed_bpp(const struct intel_connector *connector
int bpc);
u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
int mode_clock, int mode_hdisplay,
- bool bigjoiner);
-bool intel_dp_need_joiner(struct intel_dp *intel_dp,
- struct intel_connector *connector,
- int hdisplay, int clock);
+ bool bigjoiner, bool ultrajoiner);
+bool intel_dp_need_bigjoiner(struct intel_dp *intel_dp,
+ struct intel_connector *connector,
+ int hdisplay, int clock);
+bool intel_dp_need_ultrajoiner(struct intel_dp *intel_dp, int clock);
+bool intel_is_bigjoiner(const struct intel_crtc_state *pipe_config);
+bool intel_is_ultrajoiner(const struct intel_crtc_state *pipe_config);
+bool intel_crtc_is_bigjoiner_slave(const struct intel_crtc_state *crtc_state);
+bool intel_crtc_is_bigjoiner_master(const struct intel_crtc_state *crtc_state);
+bool intel_crtc_is_joiner_primary_master(const struct intel_crtc_state *crtc_state);
+enum pipe intel_crtc_master_pipe(const struct intel_crtc_state *crtc_state);
static inline unsigned int intel_dp_unused_lane_mask(int lane_count)
{
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 27ce5c3f5951..13828c011d9c 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -105,7 +105,8 @@ static int intel_dp_mst_bw_overhead(const struct intel_crtc_state *crtc_state,
dsc_slice_count = intel_dp_dsc_get_slice_count(connector,
adjusted_mode->clock,
adjusted_mode->hdisplay,
- crtc_state->joiner_pipes);
+ intel_is_bigjoiner(crtc_state),
+ intel_is_ultrajoiner(crtc_state));
}
overhead = drm_dp_bw_overhead(crtc_state->lane_count,
@@ -576,16 +577,19 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
return -EINVAL;
- if (intel_dp_need_joiner(intel_dp, connector,
- adjusted_mode->crtc_hdisplay,
- adjusted_mode->crtc_clock))
+ if (intel_dp_need_ultrajoiner(intel_dp, adjusted_mode->crtc_clock))
+ pipe_config->joiner_pipes = GENMASK(crtc->pipe + 3, crtc->pipe);
+ else if (intel_dp_need_bigjoiner(intel_dp, connector,
+ adjusted_mode->crtc_hdisplay,
+ adjusted_mode->crtc_clock))
pipe_config->joiner_pipes = GENMASK(crtc->pipe + 1, crtc->pipe);
pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
pipe_config->has_pch_encoder = false;
- joiner_needs_dsc = intel_dp_joiner_needs_dsc(dev_priv, pipe_config->joiner_pipes);
+ joiner_needs_dsc = intel_dp_joiner_needs_dsc(dev_priv, intel_is_bigjoiner(pipe_config),
+ intel_is_ultrajoiner(pipe_config));
dsc_needed = joiner_needs_dsc || intel_dp->force_dsc_en ||
!intel_dp_mst_compute_config_limits(intel_dp,
@@ -1388,7 +1392,7 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
int max_dotclk = to_i915(connector->dev)->display.cdclk.max_dotclk_freq;
int max_rate, mode_rate, max_lanes, max_link_clock;
int ret;
- bool dsc = false, joiner = false;
+ bool dsc = false, bigjoiner = false, ultrajoiner = false;
u16 dsc_max_compressed_bpp = 0;
u8 dsc_slice_count = 0;
int target_clock = mode->clock;
@@ -1431,9 +1435,12 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
* corresponding link capabilities of the sink) in case the
* stream is uncompressed for it by the last branch device.
*/
- if (intel_dp_need_joiner(intel_dp, intel_connector,
- mode->hdisplay, target_clock)) {
- joiner = true;
+ if (intel_dp_need_ultrajoiner(intel_dp, target_clock)) {
+ ultrajoiner = true;
+ max_dotclk *= 4;
+ } else if (intel_dp_need_bigjoiner(intel_dp, intel_connector,
+ mode->hdisplay, target_clock)) {
+ bigjoiner = true;
max_dotclk *= 2;
}
@@ -1461,20 +1468,22 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
max_lanes,
target_clock,
mode->hdisplay,
- joiner,
+ bigjoiner,
+ ultrajoiner,
INTEL_OUTPUT_FORMAT_RGB,
pipe_bpp, 64);
dsc_slice_count =
intel_dp_dsc_get_slice_count(intel_connector,
target_clock,
mode->hdisplay,
- joiner);
+ bigjoiner,
+ ultrajoiner);
}
dsc = dsc_max_compressed_bpp && dsc_slice_count;
}
- if (intel_dp_joiner_needs_dsc(dev_priv, joiner) && !dsc) {
+ if (intel_dp_joiner_needs_dsc(dev_priv, bigjoiner, ultrajoiner) && !dsc) {
*status = MODE_CLOCK_HIGH;
return 0;
}
@@ -1484,7 +1493,7 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
return 0;
}
- *status = intel_mode_valid_max_plane_size(dev_priv, mode, joiner);
+ *status = intel_mode_valid_max_plane_size(dev_priv, mode, bigjoiner, ultrajoiner);
return 0;
}
diff --git a/drivers/gpu/drm/i915/display/intel_dsi.c b/drivers/gpu/drm/i915/display/intel_dsi.c
index bd5888ce4852..1a7e9a56fccd 100644
--- a/drivers/gpu/drm/i915/display/intel_dsi.c
+++ b/drivers/gpu/drm/i915/display/intel_dsi.c
@@ -76,7 +76,7 @@ enum drm_mode_status intel_dsi_mode_valid(struct drm_connector *connector,
if (fixed_mode->clock > max_dotclk)
return MODE_CLOCK_HIGH;
- return intel_mode_valid_max_plane_size(dev_priv, mode, false);
+ return intel_mode_valid_max_plane_size(dev_priv, mode, false, false);
}
struct intel_dsi_host *intel_dsi_host_init(struct intel_dsi *intel_dsi,
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
index 19498ee455fa..35be89050512 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -2048,7 +2048,7 @@ intel_hdmi_mode_valid(struct drm_connector *connector,
return status;
}
- return intel_mode_valid_max_plane_size(dev_priv, mode, false);
+ return intel_mode_valid_max_plane_size(dev_priv, mode, false, false);
}
bool intel_hdmi_bpc_possible(const struct intel_crtc_state *crtc_state,
@@ -2341,6 +2341,18 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder,
return ret;
}
+ if (adjusted_mode->crtc_clock > dev_priv->display.cdclk.max_dotclk_freq ||
+ pipe_config->joiner_pipes) {
+ if (pipe_config->dsc.slice_count < 2) {
+ drm_dbg_kms(&dev_priv->drm,
+ "Cannot split stream to use 2 VDSC instances\n");
+ return -EINVAL;
+ }
+
+ pipe_config->dsc.dsc_split = true;
+ }
+
+
if (intel_hdmi_is_ycbcr420(pipe_config)) {
ret = intel_panel_fitting(pipe_config, conn_state);
if (ret)
diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c
index 11058bb37d5a..206b3e77e0d5 100644
--- a/drivers/gpu/drm/i915/display/intel_vdsc.c
+++ b/drivers/gpu/drm/i915/display/intel_vdsc.c
@@ -13,6 +13,7 @@
#include "intel_crtc.h"
#include "intel_de.h"
#include "intel_display_types.h"
+#include "intel_dp.h"
#include "intel_dsi.h"
#include "intel_qp_tables.h"
#include "intel_vdsc.h"
@@ -379,7 +380,9 @@ int intel_dsc_get_num_vdsc_instances(const struct intel_crtc_state *crtc_state)
{
int num_vdsc_instances = intel_dsc_get_vdsc_per_pipe(crtc_state);
- if (crtc_state->joiner_pipes)
+ if (intel_is_ultrajoiner(crtc_state))
+ num_vdsc_instances *= 4;
+ else if (intel_is_bigjoiner(crtc_state))
num_vdsc_instances *= 2;
return num_vdsc_instances;
@@ -770,6 +773,13 @@ void intel_uncompressed_joiner_enable(const struct intel_crtc_state *crtc_state)
}
}
+static bool intel_crtc_ultrajoiner_enable_needed(const struct intel_crtc_state *crtc_state)
+{
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+
+ return intel_is_ultrajoiner(crtc_state) && crtc->pipe != PIPE_D;
+}
+
void intel_dsc_enable(const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
@@ -788,8 +798,21 @@ void intel_dsc_enable(const struct intel_crtc_state *crtc_state)
dss_ctl2_val |= RIGHT_BRANCH_VDSC_ENABLE;
dss_ctl1_val |= JOINER_ENABLE;
}
+
if (crtc_state->joiner_pipes) {
+ /*
+ * This bit doesn't seem to follow master/slave logic or
+ * any other logic, so lets just add helper function to
+ * at least hide this hassle..
+ */
+ if (intel_crtc_ultrajoiner_enable_needed(crtc_state))
+ dss_ctl1_val |= ULTRA_JOINER_ENABLE;
+
+ if (intel_crtc_is_ultrajoiner_primary(crtc_state))
+ dss_ctl1_val |= PRIMARY_ULTRA_JOINER_ENABLE;;
+
dss_ctl1_val |= BIG_JOINER_ENABLE;
+
if (intel_crtc_is_bigjoiner_primary(crtc_state))
dss_ctl1_val |= PRIMARY_BIG_JOINER_ENABLE;
}
--
2.37.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 4/4] drm/i915: Add new abstraction layer to handle pipe order for different joiners
2024-06-26 8:18 [PATCH 0/4] Ultrajoiner basic functionality series Stanislav Lisovskiy
` (2 preceding siblings ...)
2024-06-26 8:18 ` [PATCH 3/4] drm/i915: Compute config and mode valid changes " Stanislav Lisovskiy
@ 2024-06-26 8:18 ` Stanislav Lisovskiy
2024-06-26 8:58 ` ✗ Fi.CI.CHECKPATCH: warning for Ultrajoiner basic functionality series (rev4) Patchwork
2024-06-26 9:06 ` ✗ Fi.CI.BAT: failure " Patchwork
5 siblings, 0 replies; 15+ messages in thread
From: Stanislav Lisovskiy @ 2024-06-26 8:18 UTC (permalink / raw)
To: intel-gfx; +Cc: jani.saarinen, ville.syrjala
Ultrajoiner case requires special treatment where both reverse and staight order
iteration doesn't work(for instance disabling case requires order to be:
primary master, slaves, secondary master).
Lets unify our approach by using not only pipe masks for iterating required
pipes based on joiner type used, but also using different "priority" arrays
for each of those.
Signed-off-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
---
drivers/gpu/drm/i915/display/intel_ddi.c | 19 ++---
drivers/gpu/drm/i915/display/intel_display.c | 73 +++++++++++++++-----
drivers/gpu/drm/i915/display/intel_display.h | 7 ++
drivers/gpu/drm/i915/display/intel_dp_mst.c | 19 ++---
4 files changed, 86 insertions(+), 32 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
index bb13a3ca8c7c..cee5381ce5bf 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -3113,10 +3113,11 @@ static void intel_ddi_post_disable_hdmi_or_sst(struct intel_atomic_state *state,
const struct drm_connector_state *old_conn_state)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- struct intel_crtc *pipe_crtc;
+ struct intel_crtc *pipe_crtc; enum pipe pipe;
- for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, pipe_crtc,
- intel_crtc_joined_pipe_mask(old_crtc_state)) {
+ for_each_intel_crtc_in_mask_priority(dev_priv, pipe_crtc, pipe,
+ intel_crtc_joined_pipe_mask(old_crtc_state),
+ intel_get_pipe_order_disable(old_crtc_state)) {
const struct intel_crtc_state *old_pipe_crtc_state =
intel_atomic_get_old_crtc_state(state, pipe_crtc);
@@ -3127,8 +3128,9 @@ static void intel_ddi_post_disable_hdmi_or_sst(struct intel_atomic_state *state,
intel_ddi_disable_transcoder_func(old_crtc_state);
- for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, pipe_crtc,
- intel_crtc_joined_pipe_mask(old_crtc_state)) {
+ for_each_intel_crtc_in_mask_priority(dev_priv, pipe_crtc, pipe,
+ intel_crtc_joined_pipe_mask(old_crtc_state),
+ intel_get_pipe_order_disable(old_crtc_state)) {
const struct intel_crtc_state *old_pipe_crtc_state =
intel_atomic_get_old_crtc_state(state, pipe_crtc);
@@ -3380,7 +3382,7 @@ static void intel_enable_ddi(struct intel_atomic_state *state,
const struct drm_connector_state *conn_state)
{
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
- struct intel_crtc *pipe_crtc;
+ struct intel_crtc *pipe_crtc; enum pipe pipe;
intel_ddi_enable_transcoder_func(encoder, crtc_state);
@@ -3391,8 +3393,9 @@ static void intel_enable_ddi(struct intel_atomic_state *state,
intel_ddi_wait_for_fec_status(encoder, crtc_state, true);
- for_each_intel_crtc_in_pipe_mask_reverse(&i915->drm, pipe_crtc,
- intel_crtc_joined_pipe_mask(crtc_state)) {
+ for_each_intel_crtc_in_mask_priority(i915, pipe_crtc, pipe,
+ intel_crtc_joined_pipe_mask(crtc_state),
+ intel_get_pipe_order_enable(crtc_state)) {
const struct intel_crtc_state *pipe_crtc_state =
intel_atomic_get_new_crtc_state(state, pipe_crtc);
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 4c934f07ead7..6a27f125c958 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -1720,6 +1720,40 @@ static void hsw_configure_cpu_transcoder(const struct intel_crtc_state *crtc_sta
hsw_set_transconf(crtc_state);
}
+
+
+const enum pipe *intel_get_pipe_order_enable(const struct intel_crtc_state *crtc_state)
+{
+ static const enum pipe ultrajoiner_pipe_order_enable[I915_MAX_PIPES] =
+ { PIPE_B, PIPE_D, PIPE_C, PIPE_A };
+ static const enum pipe bigjoiner_pipe_order_enable[I915_MAX_PIPES] =
+ { PIPE_B, PIPE_A, PIPE_D, PIPE_C };
+ static const enum pipe nojoiner_pipe_order_enable[I915_MAX_PIPES] =
+ { PIPE_A, PIPE_B, PIPE_C, PIPE_D };
+
+ if (intel_is_ultrajoiner(crtc_state))
+ return ultrajoiner_pipe_order_enable;
+ else if (intel_is_bigjoiner(crtc_state))
+ return bigjoiner_pipe_order_enable;
+ return nojoiner_pipe_order_enable;
+}
+
+const enum pipe *intel_get_pipe_order_disable(const struct intel_crtc_state *crtc_state)
+{
+ static const enum pipe ultrajoiner_pipe_order_disable[I915_MAX_PIPES] =
+ { PIPE_A, PIPE_B, PIPE_D, PIPE_C };
+ static const enum pipe bigjoiner_pipe_order_disable[I915_MAX_PIPES] =
+ { PIPE_A, PIPE_B, PIPE_C, PIPE_D };
+ static const enum pipe nojoiner_pipe_order_disable[I915_MAX_PIPES] =
+ { PIPE_A, PIPE_B, PIPE_C, PIPE_D };
+
+ if (intel_is_ultrajoiner(crtc_state))
+ return ultrajoiner_pipe_order_disable;
+ else if (intel_is_bigjoiner(crtc_state))
+ return bigjoiner_pipe_order_disable;
+ return nojoiner_pipe_order_disable;
+}
+
static void hsw_crtc_enable(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
@@ -1727,19 +1761,21 @@ static void hsw_crtc_enable(struct intel_atomic_state *state,
intel_atomic_get_new_crtc_state(state, crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum transcoder cpu_transcoder = new_crtc_state->cpu_transcoder;
- struct intel_crtc *pipe_crtc;
+ struct intel_crtc *pipe_crtc; enum pipe pipe;
if (drm_WARN_ON(&dev_priv->drm, crtc->active))
return;
- for_each_intel_crtc_in_pipe_mask_reverse(&dev_priv->drm, pipe_crtc,
- intel_crtc_joined_pipe_mask(new_crtc_state))
+ for_each_intel_crtc_in_mask_priority(dev_priv, pipe_crtc, pipe,
+ intel_crtc_joined_pipe_mask(new_crtc_state),
+ intel_get_pipe_order_enable(new_crtc_state))
intel_dmc_enable_pipe(dev_priv, pipe_crtc->pipe);
intel_encoders_pre_pll_enable(state, crtc);
- for_each_intel_crtc_in_pipe_mask_reverse(&dev_priv->drm, pipe_crtc,
- intel_crtc_joined_pipe_mask(new_crtc_state)) {
+ for_each_intel_crtc_in_mask_priority(dev_priv, pipe_crtc, pipe,
+ intel_crtc_joined_pipe_mask(new_crtc_state),
+ intel_get_pipe_order_enable(new_crtc_state)) {
const struct intel_crtc_state *pipe_crtc_state =
intel_atomic_get_new_crtc_state(state, pipe_crtc);
@@ -1749,8 +1785,9 @@ static void hsw_crtc_enable(struct intel_atomic_state *state,
intel_encoders_pre_enable(state, crtc);
- for_each_intel_crtc_in_pipe_mask_reverse(&dev_priv->drm, pipe_crtc,
- intel_crtc_joined_pipe_mask(new_crtc_state)) {
+ for_each_intel_crtc_in_mask_priority(dev_priv, pipe_crtc, pipe,
+ intel_crtc_joined_pipe_mask(new_crtc_state),
+ intel_get_pipe_order_enable(new_crtc_state)) {
const struct intel_crtc_state *pipe_crtc_state =
intel_atomic_get_new_crtc_state(state, pipe_crtc);
@@ -1768,8 +1805,9 @@ static void hsw_crtc_enable(struct intel_atomic_state *state,
if (!transcoder_is_dsi(cpu_transcoder))
hsw_configure_cpu_transcoder(new_crtc_state);
- for_each_intel_crtc_in_pipe_mask_reverse(&dev_priv->drm, pipe_crtc,
- intel_crtc_joined_pipe_mask(new_crtc_state)) {
+ for_each_intel_crtc_in_mask_priority(dev_priv, pipe_crtc, pipe,
+ intel_crtc_joined_pipe_mask(new_crtc_state),
+ intel_get_pipe_order_enable(new_crtc_state)) {
const struct intel_crtc_state *pipe_crtc_state =
intel_atomic_get_new_crtc_state(state, pipe_crtc);
@@ -1804,8 +1842,9 @@ static void hsw_crtc_enable(struct intel_atomic_state *state,
intel_encoders_enable(state, crtc);
- for_each_intel_crtc_in_pipe_mask_reverse(&dev_priv->drm, pipe_crtc,
- intel_crtc_joined_pipe_mask(new_crtc_state)) {
+ for_each_intel_crtc_in_mask_priority(dev_priv, pipe_crtc, pipe,
+ intel_crtc_joined_pipe_mask(new_crtc_state),
+ intel_get_pipe_order_enable(new_crtc_state)) {
const struct intel_crtc_state *pipe_crtc_state =
intel_atomic_get_new_crtc_state(state, pipe_crtc);
enum pipe hsw_workaround_pipe;
@@ -1890,7 +1929,7 @@ static void hsw_crtc_disable(struct intel_atomic_state *state,
const struct intel_crtc_state *old_crtc_state =
intel_atomic_get_old_crtc_state(state, crtc);
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
- struct intel_crtc *pipe_crtc;
+ struct intel_crtc *pipe_crtc; enum pipe pipe;
/*
* FIXME collapse everything to one hook.
@@ -1899,8 +1938,9 @@ static void hsw_crtc_disable(struct intel_atomic_state *state,
intel_encoders_disable(state, crtc);
intel_encoders_post_disable(state, crtc);
- for_each_intel_crtc_in_pipe_mask(&i915->drm, pipe_crtc,
- intel_crtc_joined_pipe_mask(old_crtc_state)) {
+ for_each_intel_crtc_in_mask_priority(i915, pipe_crtc, pipe,
+ intel_crtc_joined_pipe_mask(old_crtc_state),
+ intel_get_pipe_order_disable(old_crtc_state)) {
const struct intel_crtc_state *old_pipe_crtc_state =
intel_atomic_get_old_crtc_state(state, pipe_crtc);
@@ -1909,8 +1949,9 @@ static void hsw_crtc_disable(struct intel_atomic_state *state,
intel_encoders_post_pll_disable(state, crtc);
- for_each_intel_crtc_in_pipe_mask(&i915->drm, pipe_crtc,
- intel_crtc_joined_pipe_mask(old_crtc_state))
+ for_each_intel_crtc_in_mask_priority(i915, pipe_crtc, pipe,
+ intel_crtc_joined_pipe_mask(old_crtc_state),
+ intel_get_pipe_order_disable(old_crtc_state))
intel_dmc_disable_pipe(i915, pipe_crtc->pipe);
}
diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
index 0a51f24af405..70e18003112a 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -274,6 +274,11 @@ enum phy_fia {
&(dev)->mode_config.crtc_list, \
base.head)
+#define for_each_intel_crtc_in_mask_priority(__dev_priv, intel_crtc, __p, __mask, __priolist) \
+ for_each_pipe(__dev_priv, __p) \
+ for_each_if((__mask) & BIT(__priolist[__p])) \
+ for_each_if(intel_crtc = intel_crtc_for_pipe(__dev_priv, __priolist[__p]))
+
#define for_each_intel_crtc_in_pipe_mask(dev, intel_crtc, pipe_mask) \
list_for_each_entry(intel_crtc, \
&(dev)->mode_config.crtc_list, \
@@ -432,6 +437,8 @@ bool intel_crtc_is_ultrajoiner(const struct intel_crtc_state *crtc_state);
bool intel_crtc_is_ultrajoiner_primary(const struct intel_crtc_state *crtc_state);
u8 intel_crtc_joiner_secondary_pipes(const struct intel_crtc_state *crtc_state);
struct intel_crtc *intel_joiner_primary_crtc(const struct intel_crtc_state *crtc_state);
+const enum pipe *intel_get_pipe_order_enable(const struct intel_crtc_state *crtc_state);
+const enum pipe *intel_get_pipe_order_disable(const struct intel_crtc_state *crtc_state);
bool intel_crtc_get_pipe_config(struct intel_crtc_state *crtc_state);
bool intel_pipe_config_compare(const struct intel_crtc_state *current_config,
const struct intel_crtc_state *pipe_config,
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 13828c011d9c..291bfc3e22f9 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -1002,7 +1002,7 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state,
struct drm_dp_mst_atomic_payload *new_payload =
drm_atomic_get_mst_payload_state(new_mst_state, connector->port);
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
- struct intel_crtc *pipe_crtc;
+ struct intel_crtc *pipe_crtc; enum pipe pipe;
bool last_mst_stream;
intel_dp->active_mst_links--;
@@ -1011,8 +1011,9 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state,
DISPLAY_VER(dev_priv) >= 12 && last_mst_stream &&
!intel_dp_mst_is_master_trans(old_crtc_state));
- for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, pipe_crtc,
- intel_crtc_joined_pipe_mask(old_crtc_state)) {
+ for_each_intel_crtc_in_mask_priority(dev_priv, pipe_crtc, pipe,
+ intel_crtc_joined_pipe_mask(old_crtc_state),
+ intel_get_pipe_order_disable(old_crtc_state)) {
const struct intel_crtc_state *old_pipe_crtc_state =
intel_atomic_get_old_crtc_state(state, pipe_crtc);
@@ -1036,8 +1037,9 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state,
intel_ddi_disable_transcoder_func(old_crtc_state);
- for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, pipe_crtc,
- intel_crtc_joined_pipe_mask(old_crtc_state)) {
+ for_each_intel_crtc_in_mask_priority(dev_priv, pipe_crtc, pipe,
+ intel_crtc_joined_pipe_mask(old_crtc_state),
+ intel_get_pipe_order_disable(old_crtc_state)) {
const struct intel_crtc_state *old_pipe_crtc_state =
intel_atomic_get_old_crtc_state(state, pipe_crtc);
@@ -1226,7 +1228,7 @@ static void intel_mst_enable_dp(struct intel_atomic_state *state,
drm_atomic_get_new_mst_topology_state(&state->base, &intel_dp->mst_mgr);
enum transcoder trans = pipe_config->cpu_transcoder;
bool first_mst_stream = intel_dp->active_mst_links == 1;
- struct intel_crtc *pipe_crtc;
+ struct intel_crtc *pipe_crtc; enum pipe pipe;
drm_WARN_ON(&dev_priv->drm, pipe_config->has_pch_encoder);
@@ -1270,8 +1272,9 @@ static void intel_mst_enable_dp(struct intel_atomic_state *state,
intel_enable_transcoder(pipe_config);
- for_each_intel_crtc_in_pipe_mask_reverse(&dev_priv->drm, pipe_crtc,
- intel_crtc_joined_pipe_mask(pipe_config)) {
+ for_each_intel_crtc_in_mask_priority(dev_priv, pipe_crtc, pipe,
+ intel_crtc_joined_pipe_mask(pipe_config),
+ intel_get_pipe_order_enable(pipe_config)) {
const struct intel_crtc_state *pipe_crtc_state =
intel_atomic_get_new_crtc_state(state, pipe_crtc);
--
2.37.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* ✗ Fi.CI.CHECKPATCH: warning for Ultrajoiner basic functionality series (rev4)
2024-06-26 8:18 [PATCH 0/4] Ultrajoiner basic functionality series Stanislav Lisovskiy
` (3 preceding siblings ...)
2024-06-26 8:18 ` [PATCH 4/4] drm/i915: Add new abstraction layer to handle pipe order for different joiners Stanislav Lisovskiy
@ 2024-06-26 8:58 ` Patchwork
2024-06-26 9:06 ` ✗ Fi.CI.BAT: failure " Patchwork
5 siblings, 0 replies; 15+ messages in thread
From: Patchwork @ 2024-06-26 8:58 UTC (permalink / raw)
To: Stanislav Lisovskiy; +Cc: intel-gfx
== Series Details ==
Series: Ultrajoiner basic functionality series (rev4)
URL : https://patchwork.freedesktop.org/series/133800/
State : warning
== Summary ==
Error: dim checkpatch failed
89c7a081cd07 drm/i915: Add some essential functionality for joiners
-:61: ERROR:OPEN_BRACE: that open brace { should be on the previous line
#61: FILE: drivers/gpu/drm/i915/display/intel_display.c:277:
+ for (i = lsb; i < msb; i += 4)
+ {
total: 1 errors, 0 warnings, 0 checks, 160 lines checked
13a76717f0ea drm/i915: Implement hw state readout for ultrajoiner
-:15: WARNING:BAD_SIGN_OFF: 'Signed-off-by:' is the preferred signature form
#15:
SIgned-off-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
-:95: CHECK:SPACING: No space is necessary after a cast
#95: FILE: drivers/gpu/drm/i915/display/intel_display.c:3666:
+ power_domain = intel_dsc_power_domain(crtc, (enum transcoder) pipe);
-:152: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#152: FILE: drivers/gpu/drm/i915/display/intel_display.c:3717:
+ drm_WARN(&dev_priv->drm,
+ (ultrajoiner_pipes & bigjoiner_pipes) == ultrajoiner_pipes,
-:181: WARNING:UNNECESSARY_ELSE: else is not generally useful after a break or return
#181: FILE: drivers/gpu/drm/i915/display/intel_display.c:3743:
+ return fls(primary_pipes) - 1;
+ } else {
-:231: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#231: FILE: drivers/gpu/drm/i915/display/intel_display.c:3847:
+ get_joiner_primary_pipe(crtc->pipe, primary_pipes,
+ secondary_pipes, ultrajoiner_used);
total: 0 errors, 2 warnings, 3 checks, 238 lines checked
70a12a4c8a8f drm/i915: Compute config and mode valid changes for ultrajoiner
-:66: CHECK:MULTIPLE_ASSIGNMENTS: multiple assignments should be avoided
#66: FILE: drivers/gpu/drm/i915/display/intel_dp.c:769:
+ max_bpp_joiner = max_bpp_small_joiner_ram =
-:213: ERROR:ELSE_AFTER_BRACE: else should follow close brace '}'
#213: FILE: drivers/gpu/drm/i915/display/intel_dp.c:1279:
+ }
+ else if (intel_dp_need_bigjoiner(intel_dp, connector,
-:214: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#214: FILE: drivers/gpu/drm/i915/display/intel_dp.c:1280:
+ else if (intel_dp_need_bigjoiner(intel_dp, connector,
+ mode->hdisplay, target_clock)) {
-:330: WARNING:LONG_LINE: line length of 104 exceeds 100 columns
#330: FILE: drivers/gpu/drm/i915/display/intel_dp.h:125:
+bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915, bool use_bigjoiner, bool use_ultrajoiner);
-:388: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#388: FILE: drivers/gpu/drm/i915/display/intel_dp_mst.c:583:
+ else if (intel_dp_need_bigjoiner(intel_dp, connector,
+ adjusted_mode->crtc_hdisplay,
-:503: CHECK:LINE_SPACING: Please don't use multiple blank lines
#503: FILE: drivers/gpu/drm/i915/display/intel_hdmi.c:2355:
+
+
-:559: WARNING:ONE_SEMICOLON: Statements terminations use 1 semicolon
#559: FILE: drivers/gpu/drm/i915/display/intel_vdsc.c:812:
+ dss_ctl1_val |= PRIMARY_ULTRA_JOINER_ENABLE;;
total: 1 errors, 2 warnings, 4 checks, 487 lines checked
808815fb696e drm/i915: Add new abstraction layer to handle pipe order for different joiners
-:7: WARNING:COMMIT_LOG_LONG_LINE: Prefer a maximum 75 chars per line (possible unwrapped commit description?)
#7:
Ultrajoiner case requires special treatment where both reverse and staight order
-:77: CHECK:LINE_SPACING: Please don't use multiple blank lines
#77: FILE: drivers/gpu/drm/i915/display/intel_display.c:1724:
+
-:82: ERROR:OPEN_BRACE: that open brace { should be on the previous line
#82: FILE: drivers/gpu/drm/i915/display/intel_display.c:1729:
+ static const enum pipe ultrajoiner_pipe_order_enable[I915_MAX_PIPES] =
+ { PIPE_B, PIPE_D, PIPE_C, PIPE_A };
-:84: ERROR:OPEN_BRACE: that open brace { should be on the previous line
#84: FILE: drivers/gpu/drm/i915/display/intel_display.c:1731:
+ static const enum pipe bigjoiner_pipe_order_enable[I915_MAX_PIPES] =
+ { PIPE_B, PIPE_A, PIPE_D, PIPE_C };
-:86: ERROR:OPEN_BRACE: that open brace { should be on the previous line
#86: FILE: drivers/gpu/drm/i915/display/intel_display.c:1733:
+ static const enum pipe nojoiner_pipe_order_enable[I915_MAX_PIPES] =
+ { PIPE_A, PIPE_B, PIPE_C, PIPE_D };
-:98: ERROR:OPEN_BRACE: that open brace { should be on the previous line
#98: FILE: drivers/gpu/drm/i915/display/intel_display.c:1745:
+ static const enum pipe ultrajoiner_pipe_order_disable[I915_MAX_PIPES] =
+ { PIPE_A, PIPE_B, PIPE_D, PIPE_C };
-:100: ERROR:OPEN_BRACE: that open brace { should be on the previous line
#100: FILE: drivers/gpu/drm/i915/display/intel_display.c:1747:
+ static const enum pipe bigjoiner_pipe_order_disable[I915_MAX_PIPES] =
+ { PIPE_A, PIPE_B, PIPE_C, PIPE_D };
-:102: ERROR:OPEN_BRACE: that open brace { should be on the previous line
#102: FILE: drivers/gpu/drm/i915/display/intel_display.c:1749:
+ static const enum pipe nojoiner_pipe_order_disable[I915_MAX_PIPES] =
+ { PIPE_A, PIPE_B, PIPE_C, PIPE_D };
-:218: ERROR:COMPLEX_MACRO: Macros with complex values should be enclosed in parentheses
#218: FILE: drivers/gpu/drm/i915/display/intel_display.h:277:
+#define for_each_intel_crtc_in_mask_priority(__dev_priv, intel_crtc, __p, __mask, __priolist) \
+ for_each_pipe(__dev_priv, __p) \
+ for_each_if((__mask) & BIT(__priolist[__p])) \
+ for_each_if(intel_crtc = intel_crtc_for_pipe(__dev_priv, __priolist[__p]))
-:218: CHECK:MACRO_ARG_REUSE: Macro argument reuse '__dev_priv' - possible side-effects?
#218: FILE: drivers/gpu/drm/i915/display/intel_display.h:277:
+#define for_each_intel_crtc_in_mask_priority(__dev_priv, intel_crtc, __p, __mask, __priolist) \
+ for_each_pipe(__dev_priv, __p) \
+ for_each_if((__mask) & BIT(__priolist[__p])) \
+ for_each_if(intel_crtc = intel_crtc_for_pipe(__dev_priv, __priolist[__p]))
-:218: CHECK:MACRO_ARG_REUSE: Macro argument reuse '__p' - possible side-effects?
#218: FILE: drivers/gpu/drm/i915/display/intel_display.h:277:
+#define for_each_intel_crtc_in_mask_priority(__dev_priv, intel_crtc, __p, __mask, __priolist) \
+ for_each_pipe(__dev_priv, __p) \
+ for_each_if((__mask) & BIT(__priolist[__p])) \
+ for_each_if(intel_crtc = intel_crtc_for_pipe(__dev_priv, __priolist[__p]))
-:218: CHECK:MACRO_ARG_REUSE: Macro argument reuse '__priolist' - possible side-effects?
#218: FILE: drivers/gpu/drm/i915/display/intel_display.h:277:
+#define for_each_intel_crtc_in_mask_priority(__dev_priv, intel_crtc, __p, __mask, __priolist) \
+ for_each_pipe(__dev_priv, __p) \
+ for_each_if((__mask) & BIT(__priolist[__p])) \
+ for_each_if(intel_crtc = intel_crtc_for_pipe(__dev_priv, __priolist[__p]))
total: 7 errors, 1 warnings, 4 checks, 241 lines checked
^ permalink raw reply [flat|nested] 15+ messages in thread
* ✗ Fi.CI.BAT: failure for Ultrajoiner basic functionality series (rev4)
2024-06-26 8:18 [PATCH 0/4] Ultrajoiner basic functionality series Stanislav Lisovskiy
` (4 preceding siblings ...)
2024-06-26 8:58 ` ✗ Fi.CI.CHECKPATCH: warning for Ultrajoiner basic functionality series (rev4) Patchwork
@ 2024-06-26 9:06 ` Patchwork
5 siblings, 0 replies; 15+ messages in thread
From: Patchwork @ 2024-06-26 9:06 UTC (permalink / raw)
To: Stanislav Lisovskiy; +Cc: intel-gfx
[-- Attachment #1: Type: text/plain, Size: 11052 bytes --]
== Series Details ==
Series: Ultrajoiner basic functionality series (rev4)
URL : https://patchwork.freedesktop.org/series/133800/
State : failure
== Summary ==
CI Bug Log - changes from CI_DRM_15002 -> Patchwork_133800v4
====================================================
Summary
-------
**FAILURE**
Serious unknown changes coming with Patchwork_133800v4 absolutely need to be
verified manually.
If you think the reported changes have nothing to do with the changes
introduced in Patchwork_133800v4, please notify your bug team (I915-ci-infra@lists.freedesktop.org) to allow them
to document this new failure mode, which will reduce false positives in CI.
External URL: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_133800v4/index.html
Participating hosts (43 -> 41)
------------------------------
Missing (2): fi-snb-2520m fi-kbl-8809g
Possible new issues
-------------------
Here are the unknown changes that may have been introduced in Patchwork_133800v4:
### IGT changes ###
#### Possible regressions ####
* igt@i915_module_load@load:
- bat-jsl-1: [PASS][1] -> [ABORT][2]
[1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_15002/bat-jsl-1/igt@i915_module_load@load.html
[2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_133800v4/bat-jsl-1/igt@i915_module_load@load.html
- bat-arls-1: [PASS][3] -> [ABORT][4]
[3]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_15002/bat-arls-1/igt@i915_module_load@load.html
[4]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_133800v4/bat-arls-1/igt@i915_module_load@load.html
- bat-adlp-6: [PASS][5] -> [ABORT][6]
[5]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_15002/bat-adlp-6/igt@i915_module_load@load.html
[6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_133800v4/bat-adlp-6/igt@i915_module_load@load.html
- bat-arlh-2: [PASS][7] -> [ABORT][8]
[7]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_15002/bat-arlh-2/igt@i915_module_load@load.html
[8]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_133800v4/bat-arlh-2/igt@i915_module_load@load.html
- fi-rkl-11600: [PASS][9] -> [ABORT][10]
[9]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_15002/fi-rkl-11600/igt@i915_module_load@load.html
[10]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_133800v4/fi-rkl-11600/igt@i915_module_load@load.html
- bat-dg1-7: [PASS][11] -> [ABORT][12]
[11]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_15002/bat-dg1-7/igt@i915_module_load@load.html
[12]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_133800v4/bat-dg1-7/igt@i915_module_load@load.html
- bat-dg2-13: [PASS][13] -> [ABORT][14]
[13]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_15002/bat-dg2-13/igt@i915_module_load@load.html
[14]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_133800v4/bat-dg2-13/igt@i915_module_load@load.html
- bat-jsl-3: [PASS][15] -> [ABORT][16]
[15]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_15002/bat-jsl-3/igt@i915_module_load@load.html
[16]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_133800v4/bat-jsl-3/igt@i915_module_load@load.html
- fi-glk-j4005: [PASS][17] -> [ABORT][18]
[17]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_15002/fi-glk-j4005/igt@i915_module_load@load.html
[18]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_133800v4/fi-glk-j4005/igt@i915_module_load@load.html
- bat-adlp-9: [PASS][19] -> [ABORT][20]
[19]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_15002/bat-adlp-9/igt@i915_module_load@load.html
[20]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_133800v4/bat-adlp-9/igt@i915_module_load@load.html
- bat-dg2-11: [PASS][21] -> [ABORT][22]
[21]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_15002/bat-dg2-11/igt@i915_module_load@load.html
[22]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_133800v4/bat-dg2-11/igt@i915_module_load@load.html
- fi-kbl-7567u: [PASS][23] -> [ABORT][24]
[23]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_15002/fi-kbl-7567u/igt@i915_module_load@load.html
[24]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_133800v4/fi-kbl-7567u/igt@i915_module_load@load.html
- bat-adln-1: [PASS][25] -> [ABORT][26]
[25]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_15002/bat-adln-1/igt@i915_module_load@load.html
[26]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_133800v4/bat-adln-1/igt@i915_module_load@load.html
- fi-cfl-8700k: [PASS][27] -> [ABORT][28]
[27]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_15002/fi-cfl-8700k/igt@i915_module_load@load.html
[28]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_133800v4/fi-cfl-8700k/igt@i915_module_load@load.html
- bat-dg2-14: [PASS][29] -> [ABORT][30]
[29]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_15002/bat-dg2-14/igt@i915_module_load@load.html
[30]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_133800v4/bat-dg2-14/igt@i915_module_load@load.html
- bat-kbl-2: [PASS][31] -> [ABORT][32]
[31]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_15002/bat-kbl-2/igt@i915_module_load@load.html
[32]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_133800v4/bat-kbl-2/igt@i915_module_load@load.html
- bat-arls-5: [PASS][33] -> [ABORT][34]
[33]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_15002/bat-arls-5/igt@i915_module_load@load.html
[34]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_133800v4/bat-arls-5/igt@i915_module_load@load.html
- bat-adlm-1: [PASS][35] -> [ABORT][36]
[35]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_15002/bat-adlm-1/igt@i915_module_load@load.html
[36]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_133800v4/bat-adlm-1/igt@i915_module_load@load.html
- bat-rplp-1: [PASS][37] -> [ABORT][38]
[37]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_15002/bat-rplp-1/igt@i915_module_load@load.html
[38]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_133800v4/bat-rplp-1/igt@i915_module_load@load.html
- fi-tgl-1115g4: [PASS][39] -> [ABORT][40]
[39]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_15002/fi-tgl-1115g4/igt@i915_module_load@load.html
[40]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_133800v4/fi-tgl-1115g4/igt@i915_module_load@load.html
- bat-arlh-1: [PASS][41] -> [ABORT][42]
[41]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_15002/bat-arlh-1/igt@i915_module_load@load.html
[42]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_133800v4/bat-arlh-1/igt@i915_module_load@load.html
- fi-cfl-guc: [PASS][43] -> [ABORT][44]
[43]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_15002/fi-cfl-guc/igt@i915_module_load@load.html
[44]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_133800v4/fi-cfl-guc/igt@i915_module_load@load.html
- bat-mtlp-6: [PASS][45] -> [ABORT][46]
[45]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_15002/bat-mtlp-6/igt@i915_module_load@load.html
[46]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_133800v4/bat-mtlp-6/igt@i915_module_load@load.html
- bat-dg2-9: [PASS][47] -> [ABORT][48]
[47]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_15002/bat-dg2-9/igt@i915_module_load@load.html
[48]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_133800v4/bat-dg2-9/igt@i915_module_load@load.html
- fi-kbl-x1275: [PASS][49] -> [ABORT][50]
[49]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_15002/fi-kbl-x1275/igt@i915_module_load@load.html
[50]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_133800v4/fi-kbl-x1275/igt@i915_module_load@load.html
- bat-adlp-11: [PASS][51] -> [ABORT][52]
[51]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_15002/bat-adlp-11/igt@i915_module_load@load.html
[52]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_133800v4/bat-adlp-11/igt@i915_module_load@load.html
- fi-cfl-8109u: [PASS][53] -> [ABORT][54]
[53]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_15002/fi-cfl-8109u/igt@i915_module_load@load.html
[54]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_133800v4/fi-cfl-8109u/igt@i915_module_load@load.html
- bat-arls-2: [PASS][55] -> [ABORT][56]
[55]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_15002/bat-arls-2/igt@i915_module_load@load.html
[56]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_133800v4/bat-arls-2/igt@i915_module_load@load.html
- bat-dg2-8: [PASS][57] -> [ABORT][58]
[57]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_15002/bat-dg2-8/igt@i915_module_load@load.html
[58]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_133800v4/bat-dg2-8/igt@i915_module_load@load.html
- fi-kbl-guc: [PASS][59] -> [ABORT][60]
[59]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_15002/fi-kbl-guc/igt@i915_module_load@load.html
[60]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_133800v4/fi-kbl-guc/igt@i915_module_load@load.html
- bat-adls-6: [PASS][61] -> [ABORT][62]
[61]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_15002/bat-adls-6/igt@i915_module_load@load.html
[62]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_133800v4/bat-adls-6/igt@i915_module_load@load.html
#### Suppressed ####
The following results come from untrusted machines, tests, or statuses.
They do not affect the overall result.
* igt@i915_module_load@load:
- {bat-rpls-4}: [PASS][63] -> [ABORT][64]
[63]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_15002/bat-rpls-4/igt@i915_module_load@load.html
[64]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_133800v4/bat-rpls-4/igt@i915_module_load@load.html
- {bat-twl-1}: [PASS][65] -> [ABORT][66]
[65]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_15002/bat-twl-1/igt@i915_module_load@load.html
[66]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_133800v4/bat-twl-1/igt@i915_module_load@load.html
- {bat-apl-1}: [PASS][67] -> [ABORT][68]
[67]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_15002/bat-apl-1/igt@i915_module_load@load.html
[68]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_133800v4/bat-apl-1/igt@i915_module_load@load.html
{name}: This element is suppressed. This means it is ignored when computing
the status of the difference (SUCCESS, WARNING, or FAILURE).
Build changes
-------------
* Linux: CI_DRM_15002 -> Patchwork_133800v4
CI-20190529: 20190529
CI_DRM_15002: eeab54efcc91d572f99ea6ee3d9f562bb79a08d1 @ git://anongit.freedesktop.org/gfx-ci/linux
IGT_7901: dceed442a14a0abd09065cbade94cefe11e00422 @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
Patchwork_133800v4: eeab54efcc91d572f99ea6ee3d9f562bb79a08d1 @ git://anongit.freedesktop.org/gfx-ci/linux
== Logs ==
For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_133800v4/index.html
[-- Attachment #2: Type: text/html, Size: 11841 bytes --]
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/4] drm/i915: Add some essential functionality for joiners
2024-06-26 8:18 ` [PATCH 1/4] drm/i915: Add some essential functionality for joiners Stanislav Lisovskiy
@ 2024-06-26 10:23 ` Jani Nikula
0 siblings, 0 replies; 15+ messages in thread
From: Jani Nikula @ 2024-06-26 10:23 UTC (permalink / raw)
To: Stanislav Lisovskiy, intel-gfx; +Cc: jani.saarinen, ville.syrjala
On Wed, 26 Jun 2024, Stanislav Lisovskiy <stanislav.lisovskiy@intel.com> wrote:
> diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
> index b0cf6ca70952..bac81b7ab764 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.h
> +++ b/drivers/gpu/drm/i915/display/intel_display.h
> @@ -423,10 +423,14 @@ enum phy intel_port_to_phy(struct drm_i915_private *i915, enum port port);
> bool is_trans_port_sync_mode(const struct intel_crtc_state *state);
> bool is_trans_port_sync_master(const struct intel_crtc_state *state);
> u8 intel_crtc_joined_pipe_mask(const struct intel_crtc_state *crtc_state);
> -bool intel_crtc_is_joiner_secondary(const struct intel_crtc_state *crtc_state);
> bool intel_crtc_is_joiner_primary(const struct intel_crtc_state *crtc_state);
> +bool intel_crtc_is_joiner_secondary(const struct intel_crtc_state *crtc_state);
> +bool intel_crtc_is_bigjoiner_primary(const struct intel_crtc_state *crtc_state);
> +bool intel_crtc_is_bigjoiner_secondary(const struct intel_crtc_state *crtc_state);
> +bool intel_crtc_is_ultrajoiner(const struct intel_crtc_state *crtc_state);
> +bool intel_crtc_is_ultrajoiner_primary(const struct intel_crtc_state *crtc_state);
> u8 intel_crtc_joiner_secondary_pipes(const struct intel_crtc_state *crtc_state);
> -struct intel_crtc *intel_primary_crtc(const struct intel_crtc_state *crtc_state);
> +struct intel_crtc *intel_joiner_primary_crtc(const struct intel_crtc_state *crtc_state);
> bool intel_crtc_get_pipe_config(struct intel_crtc_state *crtc_state);
> bool intel_pipe_config_compare(const struct intel_crtc_state *current_config,
> const struct intel_crtc_state *pipe_config,
Makes you wonder why most of the joiner stuff has ended up in
intel_display.[ch].
Maybe we should have a dedicated file for the stream splitter/joiner,
with the related things (uncompressed joiner, etc.) moved there from
intel_vdsc.c, leaving that purely for compression.
BR,
Jani.
--
Jani Nikula, Intel
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/4] drm/i915: Implement hw state readout for ultrajoiner
2024-06-26 8:18 ` [PATCH 2/4] drm/i915: Implement hw state readout for ultrajoiner Stanislav Lisovskiy
@ 2024-07-01 19:17 ` Ville Syrjälä
0 siblings, 0 replies; 15+ messages in thread
From: Ville Syrjälä @ 2024-07-01 19:17 UTC (permalink / raw)
To: Stanislav Lisovskiy; +Cc: intel-gfx, jani.saarinen
On Wed, Jun 26, 2024 at 11:18:40AM +0300, Stanislav Lisovskiy wrote:
> Ultrajoiner mode has some new bits and states to be
> read out from the hw. Lets make changes accordingly.
>
> v2: - Split enabled_joiner_pipes readout procedure into
> 3 parts, each of them taking care of uncompressed joiner,
> bigjoiner and ultrajoiner respectively and then do
> some sanity check(for example all the pipes which are used
> in ultrajoiner, should also belong to bigjoiner)
>
> SIgned-off-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
> ---
> drivers/gpu/drm/i915/display/intel_display.c | 162 +++++++++++++++---
> .../gpu/drm/i915/display/intel_vdsc_regs.h | 3 +
> 2 files changed, 142 insertions(+), 23 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index 5bc867ff81e1..f702ead9b5f3 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -3580,8 +3580,42 @@ static bool transcoder_ddi_func_is_enabled(struct drm_i915_private *dev_priv,
> return tmp & TRANS_DDI_FUNC_ENABLE;
> }
>
> -static void enabled_joiner_pipes(struct drm_i915_private *dev_priv,
> - u8 *primary_pipes, u8 *secondary_pipes)
> +static void enabled_uncompressed_joiner_pipes(struct drm_i915_private *dev_priv,
> + u8 *primary_pipes, u8 *secondary_pipes)
> +{
> + struct intel_crtc *crtc;
> +
> + *primary_pipes = 0;
> + *secondary_pipes = 0;
> +
> + for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, crtc,
> + joiner_pipes(dev_priv)) {
> + enum intel_display_power_domain power_domain;
> + enum pipe pipe = crtc->pipe;
> + intel_wakeref_t wakeref;
> +
> + if (DISPLAY_VER(dev_priv) < 13)
> + continue;
That check can be done before the loop.
> +
> + power_domain = POWER_DOMAIN_PIPE(pipe);
> + with_intel_display_power_if_enabled(dev_priv, power_domain, wakeref) {
> + u32 tmp = intel_de_read(dev_priv, ICL_PIPE_DSS_CTL1(pipe));
> +
> + if (tmp & UNCOMPRESSED_JOINER_PRIMARY)
> + *primary_pipes |= BIT(pipe);
> + if (tmp & UNCOMPRESSED_JOINER_SECONDARY)
> + *secondary_pipes |= BIT(pipe);
> + }
> + }
> +
> + /* Joiner pipes should always be consecutive primary and secondary */
> + drm_WARN(&dev_priv->drm, *secondary_pipes != *primary_pipes << 1,
> + "Uncompressed joiner misconfigured (primary pipes 0x%x, secondary pipes 0x%x)\n",
> + *primary_pipes, *secondary_pipes);
We should move these checks into the caller.
> +}
> +
> +static void enabled_bigjoiner_pipes(struct drm_i915_private *dev_priv,
> + u8 *primary_pipes, u8 *secondary_pipes)
> {
> struct intel_crtc *crtc;
>
> @@ -3606,28 +3640,95 @@ static void enabled_joiner_pipes(struct drm_i915_private *dev_priv,
> else
> *secondary_pipes |= BIT(pipe);
> }
> + }
>
> - if (DISPLAY_VER(dev_priv) < 13)
> - continue;
> + /* Joiner pipes should always be consecutive primary and secondary */
> + drm_WARN(&dev_priv->drm, *secondary_pipes != *primary_pipes << 1,
> + "Bigjoiner misconfigured (primary pipes 0x%x, secondary pipes 0x%x)\n",
> + *primary_pipes, *secondary_pipes);
> +}
>
> - power_domain = POWER_DOMAIN_PIPE(pipe);
> +static void enabled_ultrajoiner_pipes(struct drm_i915_private *dev_priv,
> + u8 *primary_pipes, u8 *secondary_pipes)
> +{
> + struct intel_crtc *crtc;
> +
> + *primary_pipes = 0;
> + *secondary_pipes = 0;
Needs a platform/feature check of some sort.
Please split this patch into smaller parts:
1) split the bigjoiner/uncompressed joiners readouts
2) add more asserts relevant for bigjoiner/uncompressed joiner
3..n) bigjoiner stuff
> +
> + for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, crtc,
> + joiner_pipes(dev_priv)) {
> + enum intel_display_power_domain power_domain;
> + enum pipe pipe = crtc->pipe;
> + intel_wakeref_t wakeref;
> +
> + power_domain = intel_dsc_power_domain(crtc, (enum transcoder) pipe);
> with_intel_display_power_if_enabled(dev_priv, power_domain, wakeref) {
> u32 tmp = intel_de_read(dev_priv, ICL_PIPE_DSS_CTL1(pipe));
>
> - if (tmp & UNCOMPRESSED_JOINER_PRIMARY)
> + if (!(tmp & ULTRA_JOINER_ENABLE))
> + continue;
> +
> + /*
> + * As of now we always assume primary master to be PIPE A.
> + * Otherwise we need a new field in crtc_state to track
> + * primary master as well.
> + */
> + drm_WARN(&dev_priv->drm,
> + (tmp & PRIMARY_ULTRA_JOINER_ENABLE) && crtc->pipe != PIPE_A,
> + "Ultrajoiner primary master isn't PIPE A(pipe %c)",
> + pipe_name(crtc->pipe));
This feels rather misplaced. I think all the asserts should be in
the caller.
Could also write it more like this:
WARN((ultrajoiner_primaries & possible_ultrajoiner_primaries()) != 0)
which makes it trivial to add more pipes to the set of possible
ultrajoiner primaries in the future.
> +
> + if (tmp & PRIMARY_ULTRA_JOINER_ENABLE)
> *primary_pipes |= BIT(pipe);
> - if (tmp & UNCOMPRESSED_JOINER_SECONDARY)
> + else
> *secondary_pipes |= BIT(pipe);
> }
> }
> +}
>
> - /* Joiner pipes should always be consecutive primary and secondary */
> - drm_WARN(&dev_priv->drm, *secondary_pipes != *primary_pipes << 1,
> - "Joiner misconfigured (primary pipes 0x%x, secondary pipes 0x%x)\n",
> - *primary_pipes, *secondary_pipes);
> +static void enabled_joiner_pipes(struct drm_i915_private *dev_priv,
> + u8 *primary_pipes, u8 *secondary_pipes,
> + bool *ultrajoiner_used)
> +{
> + u8 primary_uncompressed_joiner_pipes, primary_bigjoiner_pipes;
> + u8 primary_ultrajoiner_pipes;
> + u8 secondary_uncompressed_joiner_pipes, secondary_bigjoiner_pipes;
> + u8 secondary_ultrajoiner_pipes;
> + u8 ultrajoiner_pipes, bigjoiner_pipes;
> +
> + enabled_uncompressed_joiner_pipes(dev_priv, &primary_uncompressed_joiner_pipes,
> + &secondary_uncompressed_joiner_pipes);
> +
> + enabled_bigjoiner_pipes(dev_priv, &primary_bigjoiner_pipes,
> + &secondary_bigjoiner_pipes);
> +
> + enabled_ultrajoiner_pipes(dev_priv, &primary_ultrajoiner_pipes,
> + &secondary_ultrajoiner_pipes);
> +
> + *primary_pipes = 0;
> + *secondary_pipes = 0;
> + *ultrajoiner_used = primary_ultrajoiner_pipes && secondary_ultrajoiner_pipes;
> + ultrajoiner_pipes = primary_ultrajoiner_pipes | secondary_ultrajoiner_pipes;
> + bigjoiner_pipes = primary_bigjoiner_pipes | secondary_bigjoiner_pipes;
> +
> + drm_WARN(&dev_priv->drm,
> + (ultrajoiner_pipes & bigjoiner_pipes) == ultrajoiner_pipes,
!=
> + "Ultrajoiner/Bigjoiner misconfigured:"
> + "Ultrajoiner pipes: 0x%x(primary) 0x%x(secondary),"
> + "Bigjoiner pipes: 0x%x(primary) 0x%x(secondary)",
> + primary_ultrajoiner_pipes, secondary_ultrajoiner_pipes,
> + primary_bigjoiner_pipes, secondary_bigjoiner_pipes);
Some additional checks we could have:
Make sure the ultrajoiner primaries are also bigjoiner primaries:
WARN((ultrajoiner_primaries & bigjoiner_primaries) != ultrajoiner_primaries)
Make sure bigjoiner and uncompressed joiner don't conflict:
WARN((uncompressed_pipes & bigjoiner_pipes) != 0);
And something validate that the ultrajoiner primaries vs. secondaries are
correct, Basically the same as what we already had for bigjoiner and
uncompressed joiner, but constructing the expected secondaries from the
primaries is a bit move involved than the simple <<1 we used in those
cases.
I guess we could have something like this to generate the secondaries
masks from the primaries masks:
expected_secondaries(primaries, num_pipes)
{
secondaries = 0;
for (i = 1 ; i < num_pipes; i++)
secondaries |= primaries << i;
return secondaries;
}
and then we could write all those checks like so:
WARN(bigjoiner_secondaries != expected_secondaries(bigjoiner_primaries, 2));
WARN(uncompressed_secondaries != expected_secondaries(uncompressed_primaries, 2));
WARN(ultrajoiner_secondaries != expected_secondaries(ultrajoiner_primaries, 4));
And we should probably also check for conflicts between each primary
and secondary masks:
WARN((foo_secondaries & foo_primaries) != 0);
Only really possible with uncompressed joiner due to the way the bits
work, but no real harm in asserting it for all the joiner types.
> +
> + *primary_pipes = primary_uncompressed_joiner_pipes | primary_bigjoiner_pipes |
> + primary_ultrajoiner_pipes;
> +
> + *secondary_pipes = secondary_uncompressed_joiner_pipes | secondary_bigjoiner_pipes |
> + secondary_ultrajoiner_pipes;
> }
>
> -static enum pipe get_joiner_primary_pipe(enum pipe pipe, u8 primary_pipes, u8 secondary_pipes)
> +static enum pipe get_joiner_primary_pipe(enum pipe pipe, u8 primary_pipes,
> + u8 secondary_pipes, bool ultrajoiner_used)
> {
> if ((secondary_pipes & BIT(pipe)) == 0)
> return pipe;
> @@ -3635,15 +3736,22 @@ static enum pipe get_joiner_primary_pipe(enum pipe pipe, u8 primary_pipes, u8 se
> /* ignore everything above our pipe */
> primary_pipes &= ~GENMASK(7, pipe);
>
> - /* highest remaining bit should be our primary pipe */
> - return fls(primary_pipes) - 1;
> + if (!ultrajoiner_used) {
> + /* highest remaining bit should be our master pipe */
> + return fls(primary_pipes) - 1;
> + } else {
> + /* lowest remaining bit should be our primary master pipe */
> + return ffs(primary_pipes) - 1;
> + }
> }
>
> -static u8 get_joiner_secondary_pipes(enum pipe pipe, u8 primary_pipes, u8 secondary_pipes)
> +static u8 get_joiner_secondary_pipes(enum pipe pipe, u8 primary_pipes,
> + u8 secondary_pipes, bool ultrajoiner_used)
> {
> enum pipe primary_pipe, next_primary_pipe;
>
> - primary_pipe = get_joiner_primary_pipe(pipe, primary_pipes, secondary_pipes);
> + primary_pipe = get_joiner_primary_pipe(pipe, primary_pipes,
> + secondary_pipes, ultrajoiner_used);
>
> if ((primary_pipes & BIT(primary_pipe)) == 0)
> return 0;
> @@ -3655,7 +3763,10 @@ static u8 get_joiner_secondary_pipes(enum pipe pipe, u8 primary_pipes, u8 second
> /* lowest remaining bit should be the next primary pipe */
> next_primary_pipe = ffs(primary_pipes) - 1;
>
> - return secondary_pipes & GENMASK(next_primary_pipe - 1, primary_pipe);
> + if (!ultrajoiner_used)
> + return secondary_pipes & GENMASK(next_primary_pipe - 1, primary_pipe);
> + else
> + return (secondary_pipes | primary_pipes) & ~BIT(primary_pipe);
> }
>
> static u8 hsw_panel_transcoders(struct drm_i915_private *i915)
> @@ -3676,6 +3787,7 @@ static u8 hsw_enabled_transcoders(struct intel_crtc *crtc)
> enum transcoder cpu_transcoder;
> u8 primary_pipes, secondary_pipes;
> u8 enabled_transcoders = 0;
> + bool ultrajoiner_used;
>
> /*
> * XXX: Do intel_display_power_get_if_enabled before reading this (for
> @@ -3726,11 +3838,12 @@ static u8 hsw_enabled_transcoders(struct intel_crtc *crtc)
> if (transcoder_ddi_func_is_enabled(dev_priv, cpu_transcoder))
> enabled_transcoders |= BIT(cpu_transcoder);
>
> - /* joiner secondary -> consider the primary pipe's transcoder as well */
> - enabled_joiner_pipes(dev_priv, &primary_pipes, &secondary_pipes);
> + /* joiner slave -> consider the master pipe's transcoder as well */
> + enabled_joiner_pipes(dev_priv, &primary_pipes, &secondary_pipes, &ultrajoiner_used);
> if (secondary_pipes & BIT(crtc->pipe)) {
> cpu_transcoder = (enum transcoder)
> - get_joiner_primary_pipe(crtc->pipe, primary_pipes, secondary_pipes);
> + get_joiner_primary_pipe(crtc->pipe, primary_pipes,
> + secondary_pipes, ultrajoiner_used);
> if (transcoder_ddi_func_is_enabled(dev_priv, cpu_transcoder))
> enabled_transcoders |= BIT(cpu_transcoder);
> }
> @@ -3863,15 +3976,18 @@ static void intel_joiner_get_config(struct intel_crtc_state *crtc_state)
> struct drm_i915_private *i915 = to_i915(crtc->base.dev);
> u8 primary_pipes, secondary_pipes;
> enum pipe pipe = crtc->pipe;
> + bool ultrajoiner_used;
>
> - enabled_joiner_pipes(i915, &primary_pipes, &secondary_pipes);
> + enabled_joiner_pipes(i915, &primary_pipes, &secondary_pipes, &ultrajoiner_used);
>
> if (((primary_pipes | secondary_pipes) & BIT(pipe)) == 0)
> return;
>
> crtc_state->joiner_pipes =
> - BIT(get_joiner_primary_pipe(pipe, primary_pipes, secondary_pipes)) |
> - get_joiner_secondary_pipes(pipe, primary_pipes, secondary_pipes);
> + BIT(get_joiner_primary_pipe(pipe, primary_pipes,
> + secondary_pipes, ultrajoiner_used)) |
> + get_joiner_secondary_pipes(pipe, primary_pipes,
> + secondary_pipes, ultrajoiner_used);
> }
>
> static bool hsw_get_pipe_config(struct intel_crtc *crtc,
> diff --git a/drivers/gpu/drm/i915/display/intel_vdsc_regs.h b/drivers/gpu/drm/i915/display/intel_vdsc_regs.h
> index f921ad67b587..016d7ce48215 100644
> --- a/drivers/gpu/drm/i915/display/intel_vdsc_regs.h
> +++ b/drivers/gpu/drm/i915/display/intel_vdsc_regs.h
> @@ -37,6 +37,9 @@
> #define SPLITTER_CONFIGURATION_MASK REG_GENMASK(26, 25)
> #define SPLITTER_CONFIGURATION_2_SEGMENT REG_FIELD_PREP(SPLITTER_CONFIGURATION_MASK, 0)
> #define SPLITTER_CONFIGURATION_4_SEGMENT REG_FIELD_PREP(SPLITTER_CONFIGURATION_MASK, 1)
> +
> +#define ULTRA_JOINER_ENABLE (1 << 23)
> +#define PRIMARY_ULTRA_JOINER_ENABLE (1 << 22)
> #define UNCOMPRESSED_JOINER_PRIMARY (1 << 21)
> #define UNCOMPRESSED_JOINER_SECONDARY (1 << 20)
>
> --
> 2.37.3
--
Ville Syrjälä
Intel
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 3/4] drm/i915: Compute config and mode valid changes for ultrajoiner
2024-06-26 8:18 ` [PATCH 3/4] drm/i915: Compute config and mode valid changes " Stanislav Lisovskiy
@ 2024-07-03 8:51 ` Nautiyal, Ankit K
2024-07-03 10:02 ` Lisovskiy, Stanislav
2024-07-10 8:37 ` Lisovskiy, Stanislav
2024-07-03 8:59 ` Nautiyal, Ankit K
1 sibling, 2 replies; 15+ messages in thread
From: Nautiyal, Ankit K @ 2024-07-03 8:51 UTC (permalink / raw)
To: Stanislav Lisovskiy, intel-gfx; +Cc: jani.saarinen, ville.syrjala
On 6/26/2024 1:48 PM, Stanislav Lisovskiy wrote:
> Implement required changes for mode validation and compute config,
> to support Ultrajoiner.
> This also includes required DSC changes and checks.
>
> Signed-off-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
> ---
> drivers/gpu/drm/i915/display/intel_display.c | 5 +-
> drivers/gpu/drm/i915/display/intel_display.h | 3 +-
> drivers/gpu/drm/i915/display/intel_dp.c | 117 ++++++++++++++-----
> drivers/gpu/drm/i915/display/intel_dp.h | 18 ++-
> drivers/gpu/drm/i915/display/intel_dp_mst.c | 35 +++---
> drivers/gpu/drm/i915/display/intel_dsi.c | 2 +-
> drivers/gpu/drm/i915/display/intel_hdmi.c | 14 ++-
> drivers/gpu/drm/i915/display/intel_vdsc.c | 25 +++-
> 8 files changed, 164 insertions(+), 55 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index f702ead9b5f3..4c934f07ead7 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -8246,7 +8246,8 @@ enum drm_mode_status intel_cpu_transcoder_mode_valid(struct drm_i915_private *de
> enum drm_mode_status
> intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv,
> const struct drm_display_mode *mode,
> - bool joiner)
> + bool bigjoiner,
> + bool ultrajoiner)
> {
> int plane_width_max, plane_height_max;
>
> @@ -8263,7 +8264,7 @@ intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv,
> * too big for that.
> */
> if (DISPLAY_VER(dev_priv) >= 11) {
> - plane_width_max = 5120 << joiner;
> + plane_width_max = (5120 << bigjoiner) << ultrajoiner;
> plane_height_max = 4320;
> } else {
> plane_width_max = 5120;
> diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
> index bac81b7ab764..0a51f24af405 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.h
> +++ b/drivers/gpu/drm/i915/display/intel_display.h
> @@ -415,7 +415,8 @@ u32 intel_plane_fb_max_stride(struct drm_i915_private *dev_priv,
> enum drm_mode_status
> intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv,
> const struct drm_display_mode *mode,
> - bool joiner);
> + bool bigjoiner,
> + bool ultrajoiner);
Can we use joined_pipes here and in other places instead of 2 separate
variables?
So we pass joined_pipes as either 0, 2, 4 for no-joiner, big-joiner, and
ultra-joiner.
This will help simplifying the computations for example for slice count
(mentioned inline).
We can perhaps have a patch only with this change, just replacing
'joiner' with joined_pipes and later just send joined_pipes with 4 for
ultra joiner in another patch?
> enum drm_mode_status
> intel_cpu_transcoder_mode_valid(struct drm_i915_private *i915,
> const struct drm_display_mode *mode);
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
> index 3903f6ead6e6..1ea1e89d8f45 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -760,33 +760,41 @@ u32 intel_dp_dsc_nearest_valid_bpp(struct drm_i915_private *i915, u32 bpp, u32 p
> static
> u32 get_max_compressed_bpp_with_joiner(struct drm_i915_private *i915,
> u32 mode_clock, u32 mode_hdisplay,
> - bool bigjoiner)
> + bool bigjoiner, bool ultrajoiner)
> {
> u32 max_bpp_small_joiner_ram;
> + u32 max_bpp_joiner;
>
> /* Small Joiner Check: output bpp <= joiner RAM (bits) / Horiz. width */
> - max_bpp_small_joiner_ram = small_joiner_ram_size_bits(i915) / mode_hdisplay;
> + max_bpp_joiner = max_bpp_small_joiner_ram =
> + small_joiner_ram_size_bits(i915) / mode_hdisplay;
>
> - if (bigjoiner) {
> - int bigjoiner_interface_bits = DISPLAY_VER(i915) >= 14 ? 36 : 24;
> - /* With bigjoiner multiple dsc engines are used in parallel so PPC is 2 */
> + /* if ultra joiner is enabled, we have 2 bigjoiners enabled */
> + if (bigjoiner || ultrajoiner) {
> + int joiner_interface_bits = DISPLAY_VER(i915) >= 14 ? 36 : 24;
> + /* With joiner multiple dsc engines are used in parallel so PPC is 2 */
> int ppc = 2;
> - u32 max_bpp_bigjoiner =
> - i915->display.cdclk.max_cdclk_freq * ppc * bigjoiner_interface_bits /
> + max_bpp_joiner =
> + i915->display.cdclk.max_cdclk_freq * ppc * joiner_interface_bits /
> intel_dp_mode_to_fec_clock(mode_clock);
>
> max_bpp_small_joiner_ram *= 2;
> + }
>
> - return min(max_bpp_small_joiner_ram, max_bpp_bigjoiner);
> + if (ultrajoiner) {
> + /* both get multiplied by 2, because ram bits/ppc now doubled */
> + max_bpp_small_joiner_ram *= 2;
> + max_bpp_joiner *= 2;
> }
>
> - return max_bpp_small_joiner_ram;
> + return min(max_bpp_small_joiner_ram, max_bpp_joiner);
> }
>
> u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915,
> u32 link_clock, u32 lane_count,
> u32 mode_clock, u32 mode_hdisplay,
> bool bigjoiner,
> + bool ultrajoiner,
> enum intel_output_format output_format,
> u32 pipe_bpp,
> u32 timeslots)
> @@ -832,7 +840,7 @@ u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915,
> intel_dp_mode_to_fec_clock(mode_clock));
>
> joiner_max_bpp = get_max_compressed_bpp_with_joiner(i915, mode_clock,
> - mode_hdisplay, bigjoiner);
> + mode_hdisplay, bigjoiner, ultrajoiner);
> bits_per_pixel = min(bits_per_pixel, joiner_max_bpp);
>
> bits_per_pixel = intel_dp_dsc_nearest_valid_bpp(i915, bits_per_pixel, pipe_bpp);
> @@ -842,7 +850,8 @@ u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915,
>
> u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
> int mode_clock, int mode_hdisplay,
> - bool bigjoiner)
> + bool bigjoiner,
> + bool ultrajoiner)
> {
> struct drm_i915_private *i915 = to_i915(connector->base.dev);
> u8 min_slice_count, i;
> @@ -876,7 +885,7 @@ u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
>
> /* Find the closest match to the valid slice count values */
> for (i = 0; i < ARRAY_SIZE(valid_dsc_slicecount); i++) {
> - u8 test_slice_count = valid_dsc_slicecount[i] << bigjoiner;
> + u8 test_slice_count = (valid_dsc_slicecount[i] << bigjoiner) << ultrajoiner;
If we use joined_pipes as mentioned earlier, we can perhaps just use:
u8 test_slice_count = valid_dsc_slicecount[i] << (joined_pipes / 2);
Regards,
Ankit
>
> if (test_slice_count >
> drm_dp_dsc_sink_max_slice_count(connector->dp.dsc_dpcd, false))
> @@ -886,6 +895,10 @@ u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
> if (bigjoiner && test_slice_count < 4)
> continue;
>
> + /* ultrajoiner needs 2 bigjoiners to be enabled */
> + if (ultrajoiner && test_slice_count < 8)
> + continue;
> +
> if (min_slice_count <= test_slice_count)
> return test_slice_count;
> }
> @@ -1162,9 +1175,9 @@ intel_dp_mode_valid_downstream(struct intel_connector *connector,
> return MODE_OK;
> }
>
> -bool intel_dp_need_joiner(struct intel_dp *intel_dp,
> - struct intel_connector *connector,
> - int hdisplay, int clock)
> +bool intel_dp_need_bigjoiner(struct intel_dp *intel_dp,
> + struct intel_connector *connector,
> + int hdisplay, int clock)
> {
> struct drm_i915_private *i915 = dp_to_i915(intel_dp);
>
> @@ -1195,6 +1208,35 @@ bool intel_dp_has_dsc(const struct intel_connector *connector)
> return true;
> }
>
> +static
> +bool intel_can_ultrajoiner(const struct intel_encoder *encoder)
> +{
> + struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> +
> + return IS_DGFX(i915) && DISPLAY_VER(i915) >= 14;
> +}
> +
> +bool intel_dp_need_ultrajoiner(struct intel_dp *dp, int clock)
> +{
> + const struct intel_encoder *encoder = &dp_to_dig_port(dp)->base;
> + struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> +
> + if (!intel_can_ultrajoiner(encoder))
> + return false;
> +
> + return clock > (i915->display.cdclk.max_dotclk_freq * 2);
> +}
> +
> +bool intel_is_bigjoiner(const struct intel_crtc_state *pipe_config)
> +{
> + return hweight8(pipe_config->joiner_pipes) == 2;
> +}
> +
> +bool intel_is_ultrajoiner(const struct intel_crtc_state *pipe_config)
> +{
> + return hweight8(pipe_config->joiner_pipes) == 4;
> +}
> +
> static enum drm_mode_status
> intel_dp_mode_valid(struct drm_connector *_connector,
> struct drm_display_mode *mode)
> @@ -1209,7 +1251,7 @@ intel_dp_mode_valid(struct drm_connector *_connector,
> u16 dsc_max_compressed_bpp = 0;
> u8 dsc_slice_count = 0;
> enum drm_mode_status status;
> - bool dsc = false, joiner = false;
> + bool dsc = false, bigjoiner = false, ultrajoiner = false;
>
> status = intel_cpu_transcoder_mode_valid(dev_priv, mode);
> if (status != MODE_OK)
> @@ -1230,11 +1272,16 @@ intel_dp_mode_valid(struct drm_connector *_connector,
> target_clock = fixed_mode->clock;
> }
>
> - if (intel_dp_need_joiner(intel_dp, connector,
> - mode->hdisplay, target_clock)) {
> - joiner = true;
> + if (intel_dp_need_ultrajoiner(intel_dp, target_clock)) {
> + ultrajoiner = true;
> + max_dotclk *= 4;
> + }
> + else if (intel_dp_need_bigjoiner(intel_dp, connector,
> + mode->hdisplay, target_clock)) {
> + bigjoiner = true;
> max_dotclk *= 2;
> }
> +
> if (target_clock > max_dotclk)
> return MODE_CLOCK_HIGH;
>
> @@ -1278,20 +1325,22 @@ intel_dp_mode_valid(struct drm_connector *_connector,
> max_lanes,
> target_clock,
> mode->hdisplay,
> - joiner,
> + bigjoiner,
> + ultrajoiner,
> output_format,
> pipe_bpp, 64);
> dsc_slice_count =
> intel_dp_dsc_get_slice_count(connector,
> target_clock,
> mode->hdisplay,
> - joiner);
> + bigjoiner,
> + ultrajoiner);
> }
>
> dsc = dsc_max_compressed_bpp && dsc_slice_count;
> }
>
> - if (intel_dp_joiner_needs_dsc(dev_priv, joiner) && !dsc)
> + if (intel_dp_joiner_needs_dsc(dev_priv, bigjoiner, ultrajoiner) && !dsc)
> return MODE_CLOCK_HIGH;
>
> if (mode_rate > max_rate && !dsc)
> @@ -1301,7 +1350,7 @@ intel_dp_mode_valid(struct drm_connector *_connector,
> if (status != MODE_OK)
> return status;
>
> - return intel_mode_valid_max_plane_size(dev_priv, mode, joiner);
> + return intel_mode_valid_max_plane_size(dev_priv, mode, bigjoiner, ultrajoiner);
> }
>
> bool intel_dp_source_supports_tps3(struct drm_i915_private *i915)
> @@ -2015,7 +2064,8 @@ static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp,
>
> dsc_joiner_max_bpp = get_max_compressed_bpp_with_joiner(i915, adjusted_mode->clock,
> adjusted_mode->hdisplay,
> - pipe_config->joiner_pipes);
> + intel_is_bigjoiner(pipe_config),
> + intel_is_ultrajoiner(pipe_config));
> dsc_max_bpp = min(dsc_max_bpp, dsc_joiner_max_bpp);
> dsc_max_bpp = min(dsc_max_bpp, to_bpp_int(limits->link.max_bpp_x16));
>
> @@ -2249,7 +2299,8 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
> intel_dp_dsc_get_slice_count(connector,
> adjusted_mode->crtc_clock,
> adjusted_mode->crtc_hdisplay,
> - pipe_config->joiner_pipes);
> + intel_is_bigjoiner(pipe_config),
> + intel_is_ultrajoiner(pipe_config));
> if (!dsc_dp_slice_count) {
> drm_dbg_kms(&dev_priv->drm,
> "Compressed Slice Count not supported\n");
> @@ -2399,14 +2450,15 @@ int intel_dp_config_required_rate(const struct intel_crtc_state *crtc_state)
> return intel_dp_link_required(adjusted_mode->crtc_clock, bpp);
> }
>
> -bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915, bool use_joiner)
> +bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915, bool bigjoiner, bool ultrajoiner)
> {
> /*
> * Pipe joiner needs compression up to display 12 due to bandwidth
> * limitation. DG2 onwards pipe joiner can be enabled without
> * compression.
> + * Ultrajoiner always needs compression.
> */
> - return DISPLAY_VER(i915) < 13 && use_joiner;
> + return (DISPLAY_VER(i915) < 13 && bigjoiner) || ultrajoiner;
> }
>
> static int
> @@ -2424,18 +2476,21 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
> struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> struct link_config_limits limits;
> bool dsc_needed, joiner_needs_dsc;
> + bool bigjoiner = false, ultrajoiner = false;
> int ret = 0;
>
> if (pipe_config->fec_enable &&
> !intel_dp_supports_fec(intel_dp, connector, pipe_config))
> return -EINVAL;
>
> - if (intel_dp_need_joiner(intel_dp, connector,
> - adjusted_mode->crtc_hdisplay,
> - adjusted_mode->crtc_clock))
> + if (intel_dp_need_ultrajoiner(intel_dp, adjusted_mode->crtc_clock))
> + pipe_config->joiner_pipes = GENMASK(crtc->pipe + 3, crtc->pipe);
> + else if (intel_dp_need_bigjoiner(intel_dp, connector,
> + adjusted_mode->crtc_hdisplay,
> + adjusted_mode->crtc_clock))
> pipe_config->joiner_pipes = GENMASK(crtc->pipe + 1, crtc->pipe);
>
> - joiner_needs_dsc = intel_dp_joiner_needs_dsc(i915, pipe_config->joiner_pipes);
> + joiner_needs_dsc = intel_dp_joiner_needs_dsc(i915, bigjoiner, ultrajoiner);
>
> dsc_needed = joiner_needs_dsc || intel_dp->force_dsc_en ||
> !intel_dp_compute_config_limits(intel_dp, pipe_config,
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
> index a0f990a95ecc..6a3615757c95 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.h
> +++ b/drivers/gpu/drm/i915/display/intel_dp.h
> @@ -122,7 +122,7 @@ int intel_dp_effective_data_rate(int pixel_clock, int bpp_x16,
> int bw_overhead);
> int intel_dp_max_link_data_rate(struct intel_dp *intel_dp,
> int max_dprx_rate, int max_dprx_lanes);
> -bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915, bool use_joiner);
> +bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915, bool use_bigjoiner, bool use_ultrajoiner);
> bool intel_dp_has_joiner(struct intel_dp *intel_dp);
> bool intel_dp_needs_vsc_sdp(const struct intel_crtc_state *crtc_state,
> const struct drm_connector_state *conn_state);
> @@ -142,6 +142,7 @@ u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915,
> u32 link_clock, u32 lane_count,
> u32 mode_clock, u32 mode_hdisplay,
> bool bigjoiner,
> + bool ultrajoiner,
> enum intel_output_format output_format,
> u32 pipe_bpp,
> u32 timeslots);
> @@ -151,10 +152,17 @@ int intel_dp_dsc_sink_max_compressed_bpp(const struct intel_connector *connector
> int bpc);
> u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
> int mode_clock, int mode_hdisplay,
> - bool bigjoiner);
> -bool intel_dp_need_joiner(struct intel_dp *intel_dp,
> - struct intel_connector *connector,
> - int hdisplay, int clock);
> + bool bigjoiner, bool ultrajoiner);
> +bool intel_dp_need_bigjoiner(struct intel_dp *intel_dp,
> + struct intel_connector *connector,
> + int hdisplay, int clock);
> +bool intel_dp_need_ultrajoiner(struct intel_dp *intel_dp, int clock);
> +bool intel_is_bigjoiner(const struct intel_crtc_state *pipe_config);
> +bool intel_is_ultrajoiner(const struct intel_crtc_state *pipe_config);
> +bool intel_crtc_is_bigjoiner_slave(const struct intel_crtc_state *crtc_state);
> +bool intel_crtc_is_bigjoiner_master(const struct intel_crtc_state *crtc_state);
> +bool intel_crtc_is_joiner_primary_master(const struct intel_crtc_state *crtc_state);
> +enum pipe intel_crtc_master_pipe(const struct intel_crtc_state *crtc_state);
>
> static inline unsigned int intel_dp_unused_lane_mask(int lane_count)
> {
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> index 27ce5c3f5951..13828c011d9c 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> @@ -105,7 +105,8 @@ static int intel_dp_mst_bw_overhead(const struct intel_crtc_state *crtc_state,
> dsc_slice_count = intel_dp_dsc_get_slice_count(connector,
> adjusted_mode->clock,
> adjusted_mode->hdisplay,
> - crtc_state->joiner_pipes);
> + intel_is_bigjoiner(crtc_state),
> + intel_is_ultrajoiner(crtc_state));
> }
>
> overhead = drm_dp_bw_overhead(crtc_state->lane_count,
> @@ -576,16 +577,19 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
> if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
> return -EINVAL;
>
> - if (intel_dp_need_joiner(intel_dp, connector,
> - adjusted_mode->crtc_hdisplay,
> - adjusted_mode->crtc_clock))
> + if (intel_dp_need_ultrajoiner(intel_dp, adjusted_mode->crtc_clock))
> + pipe_config->joiner_pipes = GENMASK(crtc->pipe + 3, crtc->pipe);
> + else if (intel_dp_need_bigjoiner(intel_dp, connector,
> + adjusted_mode->crtc_hdisplay,
> + adjusted_mode->crtc_clock))
> pipe_config->joiner_pipes = GENMASK(crtc->pipe + 1, crtc->pipe);
>
> pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
> pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
> pipe_config->has_pch_encoder = false;
>
> - joiner_needs_dsc = intel_dp_joiner_needs_dsc(dev_priv, pipe_config->joiner_pipes);
> + joiner_needs_dsc = intel_dp_joiner_needs_dsc(dev_priv, intel_is_bigjoiner(pipe_config),
> + intel_is_ultrajoiner(pipe_config));
>
> dsc_needed = joiner_needs_dsc || intel_dp->force_dsc_en ||
> !intel_dp_mst_compute_config_limits(intel_dp,
> @@ -1388,7 +1392,7 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
> int max_dotclk = to_i915(connector->dev)->display.cdclk.max_dotclk_freq;
> int max_rate, mode_rate, max_lanes, max_link_clock;
> int ret;
> - bool dsc = false, joiner = false;
> + bool dsc = false, bigjoiner = false, ultrajoiner = false;
> u16 dsc_max_compressed_bpp = 0;
> u8 dsc_slice_count = 0;
> int target_clock = mode->clock;
> @@ -1431,9 +1435,12 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
> * corresponding link capabilities of the sink) in case the
> * stream is uncompressed for it by the last branch device.
> */
> - if (intel_dp_need_joiner(intel_dp, intel_connector,
> - mode->hdisplay, target_clock)) {
> - joiner = true;
> + if (intel_dp_need_ultrajoiner(intel_dp, target_clock)) {
> + ultrajoiner = true;
> + max_dotclk *= 4;
> + } else if (intel_dp_need_bigjoiner(intel_dp, intel_connector,
> + mode->hdisplay, target_clock)) {
> + bigjoiner = true;
> max_dotclk *= 2;
> }
>
> @@ -1461,20 +1468,22 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
> max_lanes,
> target_clock,
> mode->hdisplay,
> - joiner,
> + bigjoiner,
> + ultrajoiner,
> INTEL_OUTPUT_FORMAT_RGB,
> pipe_bpp, 64);
> dsc_slice_count =
> intel_dp_dsc_get_slice_count(intel_connector,
> target_clock,
> mode->hdisplay,
> - joiner);
> + bigjoiner,
> + ultrajoiner);
> }
>
> dsc = dsc_max_compressed_bpp && dsc_slice_count;
> }
>
> - if (intel_dp_joiner_needs_dsc(dev_priv, joiner) && !dsc) {
> + if (intel_dp_joiner_needs_dsc(dev_priv, bigjoiner, ultrajoiner) && !dsc) {
> *status = MODE_CLOCK_HIGH;
> return 0;
> }
> @@ -1484,7 +1493,7 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
> return 0;
> }
>
> - *status = intel_mode_valid_max_plane_size(dev_priv, mode, joiner);
> + *status = intel_mode_valid_max_plane_size(dev_priv, mode, bigjoiner, ultrajoiner);
> return 0;
> }
>
> diff --git a/drivers/gpu/drm/i915/display/intel_dsi.c b/drivers/gpu/drm/i915/display/intel_dsi.c
> index bd5888ce4852..1a7e9a56fccd 100644
> --- a/drivers/gpu/drm/i915/display/intel_dsi.c
> +++ b/drivers/gpu/drm/i915/display/intel_dsi.c
> @@ -76,7 +76,7 @@ enum drm_mode_status intel_dsi_mode_valid(struct drm_connector *connector,
> if (fixed_mode->clock > max_dotclk)
> return MODE_CLOCK_HIGH;
>
> - return intel_mode_valid_max_plane_size(dev_priv, mode, false);
> + return intel_mode_valid_max_plane_size(dev_priv, mode, false, false);
> }
>
> struct intel_dsi_host *intel_dsi_host_init(struct intel_dsi *intel_dsi,
> diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
> index 19498ee455fa..35be89050512 100644
> --- a/drivers/gpu/drm/i915/display/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
> @@ -2048,7 +2048,7 @@ intel_hdmi_mode_valid(struct drm_connector *connector,
> return status;
> }
>
> - return intel_mode_valid_max_plane_size(dev_priv, mode, false);
> + return intel_mode_valid_max_plane_size(dev_priv, mode, false, false);
> }
>
> bool intel_hdmi_bpc_possible(const struct intel_crtc_state *crtc_state,
> @@ -2341,6 +2341,18 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder,
> return ret;
> }
>
> + if (adjusted_mode->crtc_clock > dev_priv->display.cdclk.max_dotclk_freq ||
> + pipe_config->joiner_pipes) {
> + if (pipe_config->dsc.slice_count < 2) {
> + drm_dbg_kms(&dev_priv->drm,
> + "Cannot split stream to use 2 VDSC instances\n");
> + return -EINVAL;
> + }
> +
> + pipe_config->dsc.dsc_split = true;
> + }
> +
> +
> if (intel_hdmi_is_ycbcr420(pipe_config)) {
> ret = intel_panel_fitting(pipe_config, conn_state);
> if (ret)
> diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c
> index 11058bb37d5a..206b3e77e0d5 100644
> --- a/drivers/gpu/drm/i915/display/intel_vdsc.c
> +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c
> @@ -13,6 +13,7 @@
> #include "intel_crtc.h"
> #include "intel_de.h"
> #include "intel_display_types.h"
> +#include "intel_dp.h"
> #include "intel_dsi.h"
> #include "intel_qp_tables.h"
> #include "intel_vdsc.h"
> @@ -379,7 +380,9 @@ int intel_dsc_get_num_vdsc_instances(const struct intel_crtc_state *crtc_state)
> {
> int num_vdsc_instances = intel_dsc_get_vdsc_per_pipe(crtc_state);
>
> - if (crtc_state->joiner_pipes)
> + if (intel_is_ultrajoiner(crtc_state))
> + num_vdsc_instances *= 4;
> + else if (intel_is_bigjoiner(crtc_state))
> num_vdsc_instances *= 2;
>
> return num_vdsc_instances;
> @@ -770,6 +773,13 @@ void intel_uncompressed_joiner_enable(const struct intel_crtc_state *crtc_state)
> }
> }
>
> +static bool intel_crtc_ultrajoiner_enable_needed(const struct intel_crtc_state *crtc_state)
> +{
> + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> +
> + return intel_is_ultrajoiner(crtc_state) && crtc->pipe != PIPE_D;
> +}
> +
> void intel_dsc_enable(const struct intel_crtc_state *crtc_state)
> {
> struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> @@ -788,8 +798,21 @@ void intel_dsc_enable(const struct intel_crtc_state *crtc_state)
> dss_ctl2_val |= RIGHT_BRANCH_VDSC_ENABLE;
> dss_ctl1_val |= JOINER_ENABLE;
> }
> +
> if (crtc_state->joiner_pipes) {
> + /*
> + * This bit doesn't seem to follow master/slave logic or
> + * any other logic, so lets just add helper function to
> + * at least hide this hassle..
> + */
> + if (intel_crtc_ultrajoiner_enable_needed(crtc_state))
> + dss_ctl1_val |= ULTRA_JOINER_ENABLE;
> +
> + if (intel_crtc_is_ultrajoiner_primary(crtc_state))
> + dss_ctl1_val |= PRIMARY_ULTRA_JOINER_ENABLE;;
> +
> dss_ctl1_val |= BIG_JOINER_ENABLE;
> +
> if (intel_crtc_is_bigjoiner_primary(crtc_state))
> dss_ctl1_val |= PRIMARY_BIG_JOINER_ENABLE;
> }
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 3/4] drm/i915: Compute config and mode valid changes for ultrajoiner
2024-06-26 8:18 ` [PATCH 3/4] drm/i915: Compute config and mode valid changes " Stanislav Lisovskiy
2024-07-03 8:51 ` Nautiyal, Ankit K
@ 2024-07-03 8:59 ` Nautiyal, Ankit K
1 sibling, 0 replies; 15+ messages in thread
From: Nautiyal, Ankit K @ 2024-07-03 8:59 UTC (permalink / raw)
To: Stanislav Lisovskiy, intel-gfx; +Cc: jani.saarinen, ville.syrjala
On 6/26/2024 1:48 PM, Stanislav Lisovskiy wrote:
> Implement required changes for mode validation and compute config,
> to support Ultrajoiner.
> This also includes required DSC changes and checks.
>
> Signed-off-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
> ---
> drivers/gpu/drm/i915/display/intel_display.c | 5 +-
> drivers/gpu/drm/i915/display/intel_display.h | 3 +-
> drivers/gpu/drm/i915/display/intel_dp.c | 117 ++++++++++++++-----
> drivers/gpu/drm/i915/display/intel_dp.h | 18 ++-
> drivers/gpu/drm/i915/display/intel_dp_mst.c | 35 +++---
> drivers/gpu/drm/i915/display/intel_dsi.c | 2 +-
> drivers/gpu/drm/i915/display/intel_hdmi.c | 14 ++-
> drivers/gpu/drm/i915/display/intel_vdsc.c | 25 +++-
> 8 files changed, 164 insertions(+), 55 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index f702ead9b5f3..4c934f07ead7 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -8246,7 +8246,8 @@ enum drm_mode_status intel_cpu_transcoder_mode_valid(struct drm_i915_private *de
> enum drm_mode_status
> intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv,
> const struct drm_display_mode *mode,
> - bool joiner)
> + bool bigjoiner,
> + bool ultrajoiner)
> {
> int plane_width_max, plane_height_max;
>
> @@ -8263,7 +8264,7 @@ intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv,
> * too big for that.
> */
> if (DISPLAY_VER(dev_priv) >= 11) {
> - plane_width_max = 5120 << joiner;
> + plane_width_max = (5120 << bigjoiner) << ultrajoiner;
> plane_height_max = 4320;
> } else {
> plane_width_max = 5120;
> diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
> index bac81b7ab764..0a51f24af405 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.h
> +++ b/drivers/gpu/drm/i915/display/intel_display.h
> @@ -415,7 +415,8 @@ u32 intel_plane_fb_max_stride(struct drm_i915_private *dev_priv,
> enum drm_mode_status
> intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv,
> const struct drm_display_mode *mode,
> - bool joiner);
> + bool bigjoiner,
> + bool ultrajoiner);
> enum drm_mode_status
> intel_cpu_transcoder_mode_valid(struct drm_i915_private *i915,
> const struct drm_display_mode *mode);
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
> index 3903f6ead6e6..1ea1e89d8f45 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -760,33 +760,41 @@ u32 intel_dp_dsc_nearest_valid_bpp(struct drm_i915_private *i915, u32 bpp, u32 p
> static
> u32 get_max_compressed_bpp_with_joiner(struct drm_i915_private *i915,
> u32 mode_clock, u32 mode_hdisplay,
> - bool bigjoiner)
> + bool bigjoiner, bool ultrajoiner)
> {
> u32 max_bpp_small_joiner_ram;
> + u32 max_bpp_joiner;
>
> /* Small Joiner Check: output bpp <= joiner RAM (bits) / Horiz. width */
> - max_bpp_small_joiner_ram = small_joiner_ram_size_bits(i915) / mode_hdisplay;
> + max_bpp_joiner = max_bpp_small_joiner_ram =
> + small_joiner_ram_size_bits(i915) / mode_hdisplay;
>
> - if (bigjoiner) {
> - int bigjoiner_interface_bits = DISPLAY_VER(i915) >= 14 ? 36 : 24;
> - /* With bigjoiner multiple dsc engines are used in parallel so PPC is 2 */
> + /* if ultra joiner is enabled, we have 2 bigjoiners enabled */
> + if (bigjoiner || ultrajoiner) {
> + int joiner_interface_bits = DISPLAY_VER(i915) >= 14 ? 36 : 24;
> + /* With joiner multiple dsc engines are used in parallel so PPC is 2 */
> int ppc = 2;
> - u32 max_bpp_bigjoiner =
> - i915->display.cdclk.max_cdclk_freq * ppc * bigjoiner_interface_bits /
> + max_bpp_joiner =
> + i915->display.cdclk.max_cdclk_freq * ppc * joiner_interface_bits /
> intel_dp_mode_to_fec_clock(mode_clock);
>
> max_bpp_small_joiner_ram *= 2;
> + }
>
> - return min(max_bpp_small_joiner_ram, max_bpp_bigjoiner);
> + if (ultrajoiner) {
> + /* both get multiplied by 2, because ram bits/ppc now doubled */
> + max_bpp_small_joiner_ram *= 2;
> + max_bpp_joiner *= 2;
> }
>
> - return max_bpp_small_joiner_ram;
> + return min(max_bpp_small_joiner_ram, max_bpp_joiner);
> }
>
> u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915,
> u32 link_clock, u32 lane_count,
> u32 mode_clock, u32 mode_hdisplay,
> bool bigjoiner,
> + bool ultrajoiner,
> enum intel_output_format output_format,
> u32 pipe_bpp,
> u32 timeslots)
> @@ -832,7 +840,7 @@ u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915,
> intel_dp_mode_to_fec_clock(mode_clock));
>
> joiner_max_bpp = get_max_compressed_bpp_with_joiner(i915, mode_clock,
> - mode_hdisplay, bigjoiner);
> + mode_hdisplay, bigjoiner, ultrajoiner);
> bits_per_pixel = min(bits_per_pixel, joiner_max_bpp);
>
> bits_per_pixel = intel_dp_dsc_nearest_valid_bpp(i915, bits_per_pixel, pipe_bpp);
> @@ -842,7 +850,8 @@ u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915,
>
> u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
> int mode_clock, int mode_hdisplay,
> - bool bigjoiner)
> + bool bigjoiner,
> + bool ultrajoiner)
> {
> struct drm_i915_private *i915 = to_i915(connector->base.dev);
> u8 min_slice_count, i;
> @@ -876,7 +885,7 @@ u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
>
> /* Find the closest match to the valid slice count values */
> for (i = 0; i < ARRAY_SIZE(valid_dsc_slicecount); i++) {
> - u8 test_slice_count = valid_dsc_slicecount[i] << bigjoiner;
> + u8 test_slice_count = (valid_dsc_slicecount[i] << bigjoiner) << ultrajoiner;
>
> if (test_slice_count >
> drm_dp_dsc_sink_max_slice_count(connector->dp.dsc_dpcd, false))
> @@ -886,6 +895,10 @@ u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
> if (bigjoiner && test_slice_count < 4)
> continue;
>
> + /* ultrajoiner needs 2 bigjoiners to be enabled */
> + if (ultrajoiner && test_slice_count < 8)
> + continue;
> +
> if (min_slice_count <= test_slice_count)
> return test_slice_count;
> }
> @@ -1162,9 +1175,9 @@ intel_dp_mode_valid_downstream(struct intel_connector *connector,
> return MODE_OK;
> }
>
> -bool intel_dp_need_joiner(struct intel_dp *intel_dp,
> - struct intel_connector *connector,
> - int hdisplay, int clock)
> +bool intel_dp_need_bigjoiner(struct intel_dp *intel_dp,
> + struct intel_connector *connector,
> + int hdisplay, int clock)
> {
> struct drm_i915_private *i915 = dp_to_i915(intel_dp);
>
> @@ -1195,6 +1208,35 @@ bool intel_dp_has_dsc(const struct intel_connector *connector)
> return true;
> }
>
> +static
> +bool intel_can_ultrajoiner(const struct intel_encoder *encoder)
> +{
> + struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> +
> + return IS_DGFX(i915) && DISPLAY_VER(i915) >= 14;
> +}
> +
> +bool intel_dp_need_ultrajoiner(struct intel_dp *dp, int clock)
> +{
> + const struct intel_encoder *encoder = &dp_to_dig_port(dp)->base;
> + struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> +
> + if (!intel_can_ultrajoiner(encoder))
> + return false;
> +
> + return clock > (i915->display.cdclk.max_dotclk_freq * 2);
> +}
> +
> +bool intel_is_bigjoiner(const struct intel_crtc_state *pipe_config)
> +{
> + return hweight8(pipe_config->joiner_pipes) == 2;
> +}
> +
> +bool intel_is_ultrajoiner(const struct intel_crtc_state *pipe_config)
> +{
> + return hweight8(pipe_config->joiner_pipes) == 4;
> +}
> +
> static enum drm_mode_status
> intel_dp_mode_valid(struct drm_connector *_connector,
> struct drm_display_mode *mode)
> @@ -1209,7 +1251,7 @@ intel_dp_mode_valid(struct drm_connector *_connector,
> u16 dsc_max_compressed_bpp = 0;
> u8 dsc_slice_count = 0;
> enum drm_mode_status status;
> - bool dsc = false, joiner = false;
> + bool dsc = false, bigjoiner = false, ultrajoiner = false;
>
> status = intel_cpu_transcoder_mode_valid(dev_priv, mode);
> if (status != MODE_OK)
> @@ -1230,11 +1272,16 @@ intel_dp_mode_valid(struct drm_connector *_connector,
> target_clock = fixed_mode->clock;
> }
>
> - if (intel_dp_need_joiner(intel_dp, connector,
> - mode->hdisplay, target_clock)) {
> - joiner = true;
> + if (intel_dp_need_ultrajoiner(intel_dp, target_clock)) {
> + ultrajoiner = true;
> + max_dotclk *= 4;
> + }
> + else if (intel_dp_need_bigjoiner(intel_dp, connector,
> + mode->hdisplay, target_clock)) {
> + bigjoiner = true;
> max_dotclk *= 2;
> }
> +
> if (target_clock > max_dotclk)
> return MODE_CLOCK_HIGH;
>
> @@ -1278,20 +1325,22 @@ intel_dp_mode_valid(struct drm_connector *_connector,
> max_lanes,
> target_clock,
> mode->hdisplay,
> - joiner,
> + bigjoiner,
> + ultrajoiner,
> output_format,
> pipe_bpp, 64);
> dsc_slice_count =
> intel_dp_dsc_get_slice_count(connector,
> target_clock,
> mode->hdisplay,
> - joiner);
> + bigjoiner,
> + ultrajoiner);
> }
>
> dsc = dsc_max_compressed_bpp && dsc_slice_count;
> }
>
> - if (intel_dp_joiner_needs_dsc(dev_priv, joiner) && !dsc)
> + if (intel_dp_joiner_needs_dsc(dev_priv, bigjoiner, ultrajoiner) && !dsc)
> return MODE_CLOCK_HIGH;
>
> if (mode_rate > max_rate && !dsc)
> @@ -1301,7 +1350,7 @@ intel_dp_mode_valid(struct drm_connector *_connector,
> if (status != MODE_OK)
> return status;
>
> - return intel_mode_valid_max_plane_size(dev_priv, mode, joiner);
> + return intel_mode_valid_max_plane_size(dev_priv, mode, bigjoiner, ultrajoiner);
> }
>
> bool intel_dp_source_supports_tps3(struct drm_i915_private *i915)
> @@ -2015,7 +2064,8 @@ static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp,
>
> dsc_joiner_max_bpp = get_max_compressed_bpp_with_joiner(i915, adjusted_mode->clock,
> adjusted_mode->hdisplay,
> - pipe_config->joiner_pipes);
> + intel_is_bigjoiner(pipe_config),
> + intel_is_ultrajoiner(pipe_config));
> dsc_max_bpp = min(dsc_max_bpp, dsc_joiner_max_bpp);
> dsc_max_bpp = min(dsc_max_bpp, to_bpp_int(limits->link.max_bpp_x16));
>
> @@ -2249,7 +2299,8 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
> intel_dp_dsc_get_slice_count(connector,
> adjusted_mode->crtc_clock,
> adjusted_mode->crtc_hdisplay,
> - pipe_config->joiner_pipes);
> + intel_is_bigjoiner(pipe_config),
> + intel_is_ultrajoiner(pipe_config));
> if (!dsc_dp_slice_count) {
> drm_dbg_kms(&dev_priv->drm,
> "Compressed Slice Count not supported\n");
> @@ -2399,14 +2450,15 @@ int intel_dp_config_required_rate(const struct intel_crtc_state *crtc_state)
> return intel_dp_link_required(adjusted_mode->crtc_clock, bpp);
> }
>
> -bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915, bool use_joiner)
> +bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915, bool bigjoiner, bool ultrajoiner)
> {
> /*
> * Pipe joiner needs compression up to display 12 due to bandwidth
> * limitation. DG2 onwards pipe joiner can be enabled without
> * compression.
> + * Ultrajoiner always needs compression.
> */
> - return DISPLAY_VER(i915) < 13 && use_joiner;
> + return (DISPLAY_VER(i915) < 13 && bigjoiner) || ultrajoiner;
> }
>
> static int
> @@ -2424,18 +2476,21 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
> struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> struct link_config_limits limits;
> bool dsc_needed, joiner_needs_dsc;
> + bool bigjoiner = false, ultrajoiner = false;
> int ret = 0;
>
> if (pipe_config->fec_enable &&
> !intel_dp_supports_fec(intel_dp, connector, pipe_config))
> return -EINVAL;
>
> - if (intel_dp_need_joiner(intel_dp, connector,
> - adjusted_mode->crtc_hdisplay,
> - adjusted_mode->crtc_clock))
> + if (intel_dp_need_ultrajoiner(intel_dp, adjusted_mode->crtc_clock))
> + pipe_config->joiner_pipes = GENMASK(crtc->pipe + 3, crtc->pipe);
> + else if (intel_dp_need_bigjoiner(intel_dp, connector,
> + adjusted_mode->crtc_hdisplay,
> + adjusted_mode->crtc_clock))
> pipe_config->joiner_pipes = GENMASK(crtc->pipe + 1, crtc->pipe);
>
> - joiner_needs_dsc = intel_dp_joiner_needs_dsc(i915, pipe_config->joiner_pipes);
> + joiner_needs_dsc = intel_dp_joiner_needs_dsc(i915, bigjoiner, ultrajoiner);
>
> dsc_needed = joiner_needs_dsc || intel_dp->force_dsc_en ||
> !intel_dp_compute_config_limits(intel_dp, pipe_config,
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
> index a0f990a95ecc..6a3615757c95 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.h
> +++ b/drivers/gpu/drm/i915/display/intel_dp.h
> @@ -122,7 +122,7 @@ int intel_dp_effective_data_rate(int pixel_clock, int bpp_x16,
> int bw_overhead);
> int intel_dp_max_link_data_rate(struct intel_dp *intel_dp,
> int max_dprx_rate, int max_dprx_lanes);
> -bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915, bool use_joiner);
> +bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915, bool use_bigjoiner, bool use_ultrajoiner);
> bool intel_dp_has_joiner(struct intel_dp *intel_dp);
> bool intel_dp_needs_vsc_sdp(const struct intel_crtc_state *crtc_state,
> const struct drm_connector_state *conn_state);
> @@ -142,6 +142,7 @@ u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915,
> u32 link_clock, u32 lane_count,
> u32 mode_clock, u32 mode_hdisplay,
> bool bigjoiner,
> + bool ultrajoiner,
> enum intel_output_format output_format,
> u32 pipe_bpp,
> u32 timeslots);
> @@ -151,10 +152,17 @@ int intel_dp_dsc_sink_max_compressed_bpp(const struct intel_connector *connector
> int bpc);
> u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
> int mode_clock, int mode_hdisplay,
> - bool bigjoiner);
> -bool intel_dp_need_joiner(struct intel_dp *intel_dp,
> - struct intel_connector *connector,
> - int hdisplay, int clock);
> + bool bigjoiner, bool ultrajoiner);
> +bool intel_dp_need_bigjoiner(struct intel_dp *intel_dp,
> + struct intel_connector *connector,
> + int hdisplay, int clock);
> +bool intel_dp_need_ultrajoiner(struct intel_dp *intel_dp, int clock);
> +bool intel_is_bigjoiner(const struct intel_crtc_state *pipe_config);
> +bool intel_is_ultrajoiner(const struct intel_crtc_state *pipe_config);
> +bool intel_crtc_is_bigjoiner_slave(const struct intel_crtc_state *crtc_state);
> +bool intel_crtc_is_bigjoiner_master(const struct intel_crtc_state *crtc_state);
> +bool intel_crtc_is_joiner_primary_master(const struct intel_crtc_state *crtc_state);
> +enum pipe intel_crtc_master_pipe(const struct intel_crtc_state *crtc_state);
>
> static inline unsigned int intel_dp_unused_lane_mask(int lane_count)
> {
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> index 27ce5c3f5951..13828c011d9c 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> @@ -105,7 +105,8 @@ static int intel_dp_mst_bw_overhead(const struct intel_crtc_state *crtc_state,
> dsc_slice_count = intel_dp_dsc_get_slice_count(connector,
> adjusted_mode->clock,
> adjusted_mode->hdisplay,
> - crtc_state->joiner_pipes);
> + intel_is_bigjoiner(crtc_state),
> + intel_is_ultrajoiner(crtc_state));
> }
>
> overhead = drm_dp_bw_overhead(crtc_state->lane_count,
> @@ -576,16 +577,19 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
> if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
> return -EINVAL;
>
> - if (intel_dp_need_joiner(intel_dp, connector,
> - adjusted_mode->crtc_hdisplay,
> - adjusted_mode->crtc_clock))
> + if (intel_dp_need_ultrajoiner(intel_dp, adjusted_mode->crtc_clock))
> + pipe_config->joiner_pipes = GENMASK(crtc->pipe + 3, crtc->pipe);
> + else if (intel_dp_need_bigjoiner(intel_dp, connector,
> + adjusted_mode->crtc_hdisplay,
> + adjusted_mode->crtc_clock))
> pipe_config->joiner_pipes = GENMASK(crtc->pipe + 1, crtc->pipe);
>
> pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
> pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
> pipe_config->has_pch_encoder = false;
>
> - joiner_needs_dsc = intel_dp_joiner_needs_dsc(dev_priv, pipe_config->joiner_pipes);
> + joiner_needs_dsc = intel_dp_joiner_needs_dsc(dev_priv, intel_is_bigjoiner(pipe_config),
> + intel_is_ultrajoiner(pipe_config));
>
> dsc_needed = joiner_needs_dsc || intel_dp->force_dsc_en ||
> !intel_dp_mst_compute_config_limits(intel_dp,
> @@ -1388,7 +1392,7 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
> int max_dotclk = to_i915(connector->dev)->display.cdclk.max_dotclk_freq;
> int max_rate, mode_rate, max_lanes, max_link_clock;
> int ret;
> - bool dsc = false, joiner = false;
> + bool dsc = false, bigjoiner = false, ultrajoiner = false;
> u16 dsc_max_compressed_bpp = 0;
> u8 dsc_slice_count = 0;
> int target_clock = mode->clock;
> @@ -1431,9 +1435,12 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
> * corresponding link capabilities of the sink) in case the
> * stream is uncompressed for it by the last branch device.
> */
> - if (intel_dp_need_joiner(intel_dp, intel_connector,
> - mode->hdisplay, target_clock)) {
> - joiner = true;
> + if (intel_dp_need_ultrajoiner(intel_dp, target_clock)) {
> + ultrajoiner = true;
> + max_dotclk *= 4;
> + } else if (intel_dp_need_bigjoiner(intel_dp, intel_connector,
> + mode->hdisplay, target_clock)) {
> + bigjoiner = true;
> max_dotclk *= 2;
> }
>
> @@ -1461,20 +1468,22 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
> max_lanes,
> target_clock,
> mode->hdisplay,
> - joiner,
> + bigjoiner,
> + ultrajoiner,
> INTEL_OUTPUT_FORMAT_RGB,
> pipe_bpp, 64);
> dsc_slice_count =
> intel_dp_dsc_get_slice_count(intel_connector,
> target_clock,
> mode->hdisplay,
> - joiner);
> + bigjoiner,
> + ultrajoiner);
> }
>
> dsc = dsc_max_compressed_bpp && dsc_slice_count;
> }
>
> - if (intel_dp_joiner_needs_dsc(dev_priv, joiner) && !dsc) {
> + if (intel_dp_joiner_needs_dsc(dev_priv, bigjoiner, ultrajoiner) && !dsc) {
> *status = MODE_CLOCK_HIGH;
> return 0;
> }
> @@ -1484,7 +1493,7 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
> return 0;
> }
>
> - *status = intel_mode_valid_max_plane_size(dev_priv, mode, joiner);
> + *status = intel_mode_valid_max_plane_size(dev_priv, mode, bigjoiner, ultrajoiner);
> return 0;
> }
>
> diff --git a/drivers/gpu/drm/i915/display/intel_dsi.c b/drivers/gpu/drm/i915/display/intel_dsi.c
> index bd5888ce4852..1a7e9a56fccd 100644
> --- a/drivers/gpu/drm/i915/display/intel_dsi.c
> +++ b/drivers/gpu/drm/i915/display/intel_dsi.c
> @@ -76,7 +76,7 @@ enum drm_mode_status intel_dsi_mode_valid(struct drm_connector *connector,
> if (fixed_mode->clock > max_dotclk)
> return MODE_CLOCK_HIGH;
>
> - return intel_mode_valid_max_plane_size(dev_priv, mode, false);
> + return intel_mode_valid_max_plane_size(dev_priv, mode, false, false);
> }
>
> struct intel_dsi_host *intel_dsi_host_init(struct intel_dsi *intel_dsi,
> diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
> index 19498ee455fa..35be89050512 100644
> --- a/drivers/gpu/drm/i915/display/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
> @@ -2048,7 +2048,7 @@ intel_hdmi_mode_valid(struct drm_connector *connector,
> return status;
> }
>
> - return intel_mode_valid_max_plane_size(dev_priv, mode, false);
> + return intel_mode_valid_max_plane_size(dev_priv, mode, false, false);
> }
>
> bool intel_hdmi_bpc_possible(const struct intel_crtc_state *crtc_state,
> @@ -2341,6 +2341,18 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder,
> return ret;
> }
>
> + if (adjusted_mode->crtc_clock > dev_priv->display.cdclk.max_dotclk_freq ||
> + pipe_config->joiner_pipes) {
> + if (pipe_config->dsc.slice_count < 2) {
> + drm_dbg_kms(&dev_priv->drm,
> + "Cannot split stream to use 2 VDSC instances\n");
> + return -EINVAL;
> + }
> +
> + pipe_config->dsc.dsc_split = true;
> + }
> +
I think we can skip the HDMI part, since we are not supporting
bigjoiner/dsc yet.
Regards,
Ankit
> +
> if (intel_hdmi_is_ycbcr420(pipe_config)) {
> ret = intel_panel_fitting(pipe_config, conn_state);
> if (ret)
> diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c
> index 11058bb37d5a..206b3e77e0d5 100644
> --- a/drivers/gpu/drm/i915/display/intel_vdsc.c
> +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c
> @@ -13,6 +13,7 @@
> #include "intel_crtc.h"
> #include "intel_de.h"
> #include "intel_display_types.h"
> +#include "intel_dp.h"
> #include "intel_dsi.h"
> #include "intel_qp_tables.h"
> #include "intel_vdsc.h"
> @@ -379,7 +380,9 @@ int intel_dsc_get_num_vdsc_instances(const struct intel_crtc_state *crtc_state)
> {
> int num_vdsc_instances = intel_dsc_get_vdsc_per_pipe(crtc_state);
>
> - if (crtc_state->joiner_pipes)
> + if (intel_is_ultrajoiner(crtc_state))
> + num_vdsc_instances *= 4;
> + else if (intel_is_bigjoiner(crtc_state))
> num_vdsc_instances *= 2;
>
> return num_vdsc_instances;
> @@ -770,6 +773,13 @@ void intel_uncompressed_joiner_enable(const struct intel_crtc_state *crtc_state)
> }
> }
>
> +static bool intel_crtc_ultrajoiner_enable_needed(const struct intel_crtc_state *crtc_state)
> +{
> + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> +
> + return intel_is_ultrajoiner(crtc_state) && crtc->pipe != PIPE_D;
> +}
> +
> void intel_dsc_enable(const struct intel_crtc_state *crtc_state)
> {
> struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> @@ -788,8 +798,21 @@ void intel_dsc_enable(const struct intel_crtc_state *crtc_state)
> dss_ctl2_val |= RIGHT_BRANCH_VDSC_ENABLE;
> dss_ctl1_val |= JOINER_ENABLE;
> }
> +
> if (crtc_state->joiner_pipes) {
> + /*
> + * This bit doesn't seem to follow master/slave logic or
> + * any other logic, so lets just add helper function to
> + * at least hide this hassle..
> + */
> + if (intel_crtc_ultrajoiner_enable_needed(crtc_state))
> + dss_ctl1_val |= ULTRA_JOINER_ENABLE;
> +
> + if (intel_crtc_is_ultrajoiner_primary(crtc_state))
> + dss_ctl1_val |= PRIMARY_ULTRA_JOINER_ENABLE;;
> +
> dss_ctl1_val |= BIG_JOINER_ENABLE;
> +
> if (intel_crtc_is_bigjoiner_primary(crtc_state))
> dss_ctl1_val |= PRIMARY_BIG_JOINER_ENABLE;
> }
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 3/4] drm/i915: Compute config and mode valid changes for ultrajoiner
2024-07-03 8:51 ` Nautiyal, Ankit K
@ 2024-07-03 10:02 ` Lisovskiy, Stanislav
2024-07-10 8:37 ` Lisovskiy, Stanislav
1 sibling, 0 replies; 15+ messages in thread
From: Lisovskiy, Stanislav @ 2024-07-03 10:02 UTC (permalink / raw)
To: Nautiyal, Ankit K; +Cc: intel-gfx, jani.saarinen, ville.syrjala
On Wed, Jul 03, 2024 at 02:21:48PM +0530, Nautiyal, Ankit K wrote:
>
> On 6/26/2024 1:48 PM, Stanislav Lisovskiy wrote:
> > Implement required changes for mode validation and compute config,
> > to support Ultrajoiner.
> > This also includes required DSC changes and checks.
> >
> > Signed-off-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
> > ---
> > drivers/gpu/drm/i915/display/intel_display.c | 5 +-
> > drivers/gpu/drm/i915/display/intel_display.h | 3 +-
> > drivers/gpu/drm/i915/display/intel_dp.c | 117 ++++++++++++++-----
> > drivers/gpu/drm/i915/display/intel_dp.h | 18 ++-
> > drivers/gpu/drm/i915/display/intel_dp_mst.c | 35 +++---
> > drivers/gpu/drm/i915/display/intel_dsi.c | 2 +-
> > drivers/gpu/drm/i915/display/intel_hdmi.c | 14 ++-
> > drivers/gpu/drm/i915/display/intel_vdsc.c | 25 +++-
> > 8 files changed, 164 insertions(+), 55 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> > index f702ead9b5f3..4c934f07ead7 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display.c
> > +++ b/drivers/gpu/drm/i915/display/intel_display.c
> > @@ -8246,7 +8246,8 @@ enum drm_mode_status intel_cpu_transcoder_mode_valid(struct drm_i915_private *de
> > enum drm_mode_status
> > intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv,
> > const struct drm_display_mode *mode,
> > - bool joiner)
> > + bool bigjoiner,
> > + bool ultrajoiner)
> > {
> > int plane_width_max, plane_height_max;
> > @@ -8263,7 +8264,7 @@ intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv,
> > * too big for that.
> > */
> > if (DISPLAY_VER(dev_priv) >= 11) {
> > - plane_width_max = 5120 << joiner;
> > + plane_width_max = (5120 << bigjoiner) << ultrajoiner;
> > plane_height_max = 4320;
> > } else {
> > plane_width_max = 5120;
> > diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
> > index bac81b7ab764..0a51f24af405 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display.h
> > +++ b/drivers/gpu/drm/i915/display/intel_display.h
> > @@ -415,7 +415,8 @@ u32 intel_plane_fb_max_stride(struct drm_i915_private *dev_priv,
> > enum drm_mode_status
> > intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv,
> > const struct drm_display_mode *mode,
> > - bool joiner);
> > + bool bigjoiner,
> > + bool ultrajoiner);
>
> Can we use joined_pipes here and in other places instead of 2 separate
> variables?
>
> So we pass joined_pipes as either 0, 2, 4 for no-joiner, big-joiner, and
> ultra-joiner.
>
> This will help simplifying the computations for example for slice count
> (mentioned inline).
>
> We can perhaps have a patch only with this change, just replacing 'joiner'
> with joined_pipes and later just send joined_pipes with 4 for ultra joiner
> in another patch?
I remember I was actually thinking about that. Having bigjoiner/ultrajoiner
also seems a bit weird, also for me, don't remember why decided to go with those
still.
Will check again, probably yep we just need to pass joined_pipes, and then use
some helper to question if its a bigjoiner and etc..
>
>
> > enum drm_mode_status
> > intel_cpu_transcoder_mode_valid(struct drm_i915_private *i915,
> > const struct drm_display_mode *mode);
> > diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
> > index 3903f6ead6e6..1ea1e89d8f45 100644
> > --- a/drivers/gpu/drm/i915/display/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> > @@ -760,33 +760,41 @@ u32 intel_dp_dsc_nearest_valid_bpp(struct drm_i915_private *i915, u32 bpp, u32 p
> > static
> > u32 get_max_compressed_bpp_with_joiner(struct drm_i915_private *i915,
> > u32 mode_clock, u32 mode_hdisplay,
> > - bool bigjoiner)
> > + bool bigjoiner, bool ultrajoiner)
> > {
> > u32 max_bpp_small_joiner_ram;
> > + u32 max_bpp_joiner;
> > /* Small Joiner Check: output bpp <= joiner RAM (bits) / Horiz. width */
> > - max_bpp_small_joiner_ram = small_joiner_ram_size_bits(i915) / mode_hdisplay;
> > + max_bpp_joiner = max_bpp_small_joiner_ram =
> > + small_joiner_ram_size_bits(i915) / mode_hdisplay;
> > - if (bigjoiner) {
> > - int bigjoiner_interface_bits = DISPLAY_VER(i915) >= 14 ? 36 : 24;
> > - /* With bigjoiner multiple dsc engines are used in parallel so PPC is 2 */
> > + /* if ultra joiner is enabled, we have 2 bigjoiners enabled */
> > + if (bigjoiner || ultrajoiner) {
> > + int joiner_interface_bits = DISPLAY_VER(i915) >= 14 ? 36 : 24;
> > + /* With joiner multiple dsc engines are used in parallel so PPC is 2 */
> > int ppc = 2;
> > - u32 max_bpp_bigjoiner =
> > - i915->display.cdclk.max_cdclk_freq * ppc * bigjoiner_interface_bits /
> > + max_bpp_joiner =
> > + i915->display.cdclk.max_cdclk_freq * ppc * joiner_interface_bits /
> > intel_dp_mode_to_fec_clock(mode_clock);
> > max_bpp_small_joiner_ram *= 2;
> > + }
> > - return min(max_bpp_small_joiner_ram, max_bpp_bigjoiner);
> > + if (ultrajoiner) {
> > + /* both get multiplied by 2, because ram bits/ppc now doubled */
> > + max_bpp_small_joiner_ram *= 2;
> > + max_bpp_joiner *= 2;
> > }
> > - return max_bpp_small_joiner_ram;
> > + return min(max_bpp_small_joiner_ram, max_bpp_joiner);
> > }
> > u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915,
> > u32 link_clock, u32 lane_count,
> > u32 mode_clock, u32 mode_hdisplay,
> > bool bigjoiner,
> > + bool ultrajoiner,
> > enum intel_output_format output_format,
> > u32 pipe_bpp,
> > u32 timeslots)
> > @@ -832,7 +840,7 @@ u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915,
> > intel_dp_mode_to_fec_clock(mode_clock));
> > joiner_max_bpp = get_max_compressed_bpp_with_joiner(i915, mode_clock,
> > - mode_hdisplay, bigjoiner);
> > + mode_hdisplay, bigjoiner, ultrajoiner);
> > bits_per_pixel = min(bits_per_pixel, joiner_max_bpp);
> > bits_per_pixel = intel_dp_dsc_nearest_valid_bpp(i915, bits_per_pixel, pipe_bpp);
> > @@ -842,7 +850,8 @@ u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915,
> > u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
> > int mode_clock, int mode_hdisplay,
> > - bool bigjoiner)
> > + bool bigjoiner,
> > + bool ultrajoiner)
> > {
> > struct drm_i915_private *i915 = to_i915(connector->base.dev);
> > u8 min_slice_count, i;
> > @@ -876,7 +885,7 @@ u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
> > /* Find the closest match to the valid slice count values */
> > for (i = 0; i < ARRAY_SIZE(valid_dsc_slicecount); i++) {
> > - u8 test_slice_count = valid_dsc_slicecount[i] << bigjoiner;
> > + u8 test_slice_count = (valid_dsc_slicecount[i] << bigjoiner) << ultrajoiner;
>
> If we use joined_pipes as mentioned earlier, we can perhaps just use:
>
> u8 test_slice_count = valid_dsc_slicecount[i] << (joined_pipes / 2);
Yep, that is shorter, but bit unclear in terms of readability..
If we apply this, I would add some comment explaining that formula.
>
>
> Regards,
>
> Ankit
>
>
>
> > if (test_slice_count >
> > drm_dp_dsc_sink_max_slice_count(connector->dp.dsc_dpcd, false))
> > @@ -886,6 +895,10 @@ u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
> > if (bigjoiner && test_slice_count < 4)
> > continue;
> > + /* ultrajoiner needs 2 bigjoiners to be enabled */
> > + if (ultrajoiner && test_slice_count < 8)
> > + continue;
> > +
> > if (min_slice_count <= test_slice_count)
> > return test_slice_count;
> > }
> > @@ -1162,9 +1175,9 @@ intel_dp_mode_valid_downstream(struct intel_connector *connector,
> > return MODE_OK;
> > }
> > -bool intel_dp_need_joiner(struct intel_dp *intel_dp,
> > - struct intel_connector *connector,
> > - int hdisplay, int clock)
> > +bool intel_dp_need_bigjoiner(struct intel_dp *intel_dp,
> > + struct intel_connector *connector,
> > + int hdisplay, int clock)
> > {
> > struct drm_i915_private *i915 = dp_to_i915(intel_dp);
> > @@ -1195,6 +1208,35 @@ bool intel_dp_has_dsc(const struct intel_connector *connector)
> > return true;
> > }
> > +static
> > +bool intel_can_ultrajoiner(const struct intel_encoder *encoder)
> > +{
> > + struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> > +
> > + return IS_DGFX(i915) && DISPLAY_VER(i915) >= 14;
> > +}
> > +
> > +bool intel_dp_need_ultrajoiner(struct intel_dp *dp, int clock)
> > +{
> > + const struct intel_encoder *encoder = &dp_to_dig_port(dp)->base;
> > + struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> > +
> > + if (!intel_can_ultrajoiner(encoder))
> > + return false;
> > +
> > + return clock > (i915->display.cdclk.max_dotclk_freq * 2);
> > +}
> > +
> > +bool intel_is_bigjoiner(const struct intel_crtc_state *pipe_config)
> > +{
> > + return hweight8(pipe_config->joiner_pipes) == 2;
> > +}
> > +
> > +bool intel_is_ultrajoiner(const struct intel_crtc_state *pipe_config)
> > +{
> > + return hweight8(pipe_config->joiner_pipes) == 4;
> > +}
> > +
> > static enum drm_mode_status
> > intel_dp_mode_valid(struct drm_connector *_connector,
> > struct drm_display_mode *mode)
> > @@ -1209,7 +1251,7 @@ intel_dp_mode_valid(struct drm_connector *_connector,
> > u16 dsc_max_compressed_bpp = 0;
> > u8 dsc_slice_count = 0;
> > enum drm_mode_status status;
> > - bool dsc = false, joiner = false;
> > + bool dsc = false, bigjoiner = false, ultrajoiner = false;
> > status = intel_cpu_transcoder_mode_valid(dev_priv, mode);
> > if (status != MODE_OK)
> > @@ -1230,11 +1272,16 @@ intel_dp_mode_valid(struct drm_connector *_connector,
> > target_clock = fixed_mode->clock;
> > }
> > - if (intel_dp_need_joiner(intel_dp, connector,
> > - mode->hdisplay, target_clock)) {
> > - joiner = true;
> > + if (intel_dp_need_ultrajoiner(intel_dp, target_clock)) {
> > + ultrajoiner = true;
> > + max_dotclk *= 4;
> > + }
> > + else if (intel_dp_need_bigjoiner(intel_dp, connector,
> > + mode->hdisplay, target_clock)) {
> > + bigjoiner = true;
> > max_dotclk *= 2;
> > }
> > +
> > if (target_clock > max_dotclk)
> > return MODE_CLOCK_HIGH;
> > @@ -1278,20 +1325,22 @@ intel_dp_mode_valid(struct drm_connector *_connector,
> > max_lanes,
> > target_clock,
> > mode->hdisplay,
> > - joiner,
> > + bigjoiner,
> > + ultrajoiner,
> > output_format,
> > pipe_bpp, 64);
> > dsc_slice_count =
> > intel_dp_dsc_get_slice_count(connector,
> > target_clock,
> > mode->hdisplay,
> > - joiner);
> > + bigjoiner,
> > + ultrajoiner);
> > }
> > dsc = dsc_max_compressed_bpp && dsc_slice_count;
> > }
> > - if (intel_dp_joiner_needs_dsc(dev_priv, joiner) && !dsc)
> > + if (intel_dp_joiner_needs_dsc(dev_priv, bigjoiner, ultrajoiner) && !dsc)
> > return MODE_CLOCK_HIGH;
> > if (mode_rate > max_rate && !dsc)
> > @@ -1301,7 +1350,7 @@ intel_dp_mode_valid(struct drm_connector *_connector,
> > if (status != MODE_OK)
> > return status;
> > - return intel_mode_valid_max_plane_size(dev_priv, mode, joiner);
> > + return intel_mode_valid_max_plane_size(dev_priv, mode, bigjoiner, ultrajoiner);
> > }
> > bool intel_dp_source_supports_tps3(struct drm_i915_private *i915)
> > @@ -2015,7 +2064,8 @@ static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp,
> > dsc_joiner_max_bpp = get_max_compressed_bpp_with_joiner(i915, adjusted_mode->clock,
> > adjusted_mode->hdisplay,
> > - pipe_config->joiner_pipes);
> > + intel_is_bigjoiner(pipe_config),
> > + intel_is_ultrajoiner(pipe_config));
> > dsc_max_bpp = min(dsc_max_bpp, dsc_joiner_max_bpp);
> > dsc_max_bpp = min(dsc_max_bpp, to_bpp_int(limits->link.max_bpp_x16));
> > @@ -2249,7 +2299,8 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
> > intel_dp_dsc_get_slice_count(connector,
> > adjusted_mode->crtc_clock,
> > adjusted_mode->crtc_hdisplay,
> > - pipe_config->joiner_pipes);
> > + intel_is_bigjoiner(pipe_config),
> > + intel_is_ultrajoiner(pipe_config));
> > if (!dsc_dp_slice_count) {
> > drm_dbg_kms(&dev_priv->drm,
> > "Compressed Slice Count not supported\n");
> > @@ -2399,14 +2450,15 @@ int intel_dp_config_required_rate(const struct intel_crtc_state *crtc_state)
> > return intel_dp_link_required(adjusted_mode->crtc_clock, bpp);
> > }
> > -bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915, bool use_joiner)
> > +bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915, bool bigjoiner, bool ultrajoiner)
> > {
> > /*
> > * Pipe joiner needs compression up to display 12 due to bandwidth
> > * limitation. DG2 onwards pipe joiner can be enabled without
> > * compression.
> > + * Ultrajoiner always needs compression.
> > */
> > - return DISPLAY_VER(i915) < 13 && use_joiner;
> > + return (DISPLAY_VER(i915) < 13 && bigjoiner) || ultrajoiner;
> > }
> > static int
> > @@ -2424,18 +2476,21 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
> > struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> > struct link_config_limits limits;
> > bool dsc_needed, joiner_needs_dsc;
> > + bool bigjoiner = false, ultrajoiner = false;
> > int ret = 0;
> > if (pipe_config->fec_enable &&
> > !intel_dp_supports_fec(intel_dp, connector, pipe_config))
> > return -EINVAL;
> > - if (intel_dp_need_joiner(intel_dp, connector,
> > - adjusted_mode->crtc_hdisplay,
> > - adjusted_mode->crtc_clock))
> > + if (intel_dp_need_ultrajoiner(intel_dp, adjusted_mode->crtc_clock))
> > + pipe_config->joiner_pipes = GENMASK(crtc->pipe + 3, crtc->pipe);
> > + else if (intel_dp_need_bigjoiner(intel_dp, connector,
> > + adjusted_mode->crtc_hdisplay,
> > + adjusted_mode->crtc_clock))
> > pipe_config->joiner_pipes = GENMASK(crtc->pipe + 1, crtc->pipe);
> > - joiner_needs_dsc = intel_dp_joiner_needs_dsc(i915, pipe_config->joiner_pipes);
> > + joiner_needs_dsc = intel_dp_joiner_needs_dsc(i915, bigjoiner, ultrajoiner);
> > dsc_needed = joiner_needs_dsc || intel_dp->force_dsc_en ||
> > !intel_dp_compute_config_limits(intel_dp, pipe_config,
> > diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
> > index a0f990a95ecc..6a3615757c95 100644
> > --- a/drivers/gpu/drm/i915/display/intel_dp.h
> > +++ b/drivers/gpu/drm/i915/display/intel_dp.h
> > @@ -122,7 +122,7 @@ int intel_dp_effective_data_rate(int pixel_clock, int bpp_x16,
> > int bw_overhead);
> > int intel_dp_max_link_data_rate(struct intel_dp *intel_dp,
> > int max_dprx_rate, int max_dprx_lanes);
> > -bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915, bool use_joiner);
> > +bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915, bool use_bigjoiner, bool use_ultrajoiner);
> > bool intel_dp_has_joiner(struct intel_dp *intel_dp);
> > bool intel_dp_needs_vsc_sdp(const struct intel_crtc_state *crtc_state,
> > const struct drm_connector_state *conn_state);
> > @@ -142,6 +142,7 @@ u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915,
> > u32 link_clock, u32 lane_count,
> > u32 mode_clock, u32 mode_hdisplay,
> > bool bigjoiner,
> > + bool ultrajoiner,
> > enum intel_output_format output_format,
> > u32 pipe_bpp,
> > u32 timeslots);
> > @@ -151,10 +152,17 @@ int intel_dp_dsc_sink_max_compressed_bpp(const struct intel_connector *connector
> > int bpc);
> > u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
> > int mode_clock, int mode_hdisplay,
> > - bool bigjoiner);
> > -bool intel_dp_need_joiner(struct intel_dp *intel_dp,
> > - struct intel_connector *connector,
> > - int hdisplay, int clock);
> > + bool bigjoiner, bool ultrajoiner);
> > +bool intel_dp_need_bigjoiner(struct intel_dp *intel_dp,
> > + struct intel_connector *connector,
> > + int hdisplay, int clock);
> > +bool intel_dp_need_ultrajoiner(struct intel_dp *intel_dp, int clock);
> > +bool intel_is_bigjoiner(const struct intel_crtc_state *pipe_config);
> > +bool intel_is_ultrajoiner(const struct intel_crtc_state *pipe_config);
> > +bool intel_crtc_is_bigjoiner_slave(const struct intel_crtc_state *crtc_state);
> > +bool intel_crtc_is_bigjoiner_master(const struct intel_crtc_state *crtc_state);
> > +bool intel_crtc_is_joiner_primary_master(const struct intel_crtc_state *crtc_state);
> > +enum pipe intel_crtc_master_pipe(const struct intel_crtc_state *crtc_state);
> > static inline unsigned int intel_dp_unused_lane_mask(int lane_count)
> > {
> > diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > index 27ce5c3f5951..13828c011d9c 100644
> > --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > @@ -105,7 +105,8 @@ static int intel_dp_mst_bw_overhead(const struct intel_crtc_state *crtc_state,
> > dsc_slice_count = intel_dp_dsc_get_slice_count(connector,
> > adjusted_mode->clock,
> > adjusted_mode->hdisplay,
> > - crtc_state->joiner_pipes);
> > + intel_is_bigjoiner(crtc_state),
> > + intel_is_ultrajoiner(crtc_state));
> > }
> > overhead = drm_dp_bw_overhead(crtc_state->lane_count,
> > @@ -576,16 +577,19 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
> > if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
> > return -EINVAL;
> > - if (intel_dp_need_joiner(intel_dp, connector,
> > - adjusted_mode->crtc_hdisplay,
> > - adjusted_mode->crtc_clock))
> > + if (intel_dp_need_ultrajoiner(intel_dp, adjusted_mode->crtc_clock))
> > + pipe_config->joiner_pipes = GENMASK(crtc->pipe + 3, crtc->pipe);
> > + else if (intel_dp_need_bigjoiner(intel_dp, connector,
> > + adjusted_mode->crtc_hdisplay,
> > + adjusted_mode->crtc_clock))
> > pipe_config->joiner_pipes = GENMASK(crtc->pipe + 1, crtc->pipe);
> > pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
> > pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
> > pipe_config->has_pch_encoder = false;
> > - joiner_needs_dsc = intel_dp_joiner_needs_dsc(dev_priv, pipe_config->joiner_pipes);
> > + joiner_needs_dsc = intel_dp_joiner_needs_dsc(dev_priv, intel_is_bigjoiner(pipe_config),
> > + intel_is_ultrajoiner(pipe_config));
> > dsc_needed = joiner_needs_dsc || intel_dp->force_dsc_en ||
> > !intel_dp_mst_compute_config_limits(intel_dp,
> > @@ -1388,7 +1392,7 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
> > int max_dotclk = to_i915(connector->dev)->display.cdclk.max_dotclk_freq;
> > int max_rate, mode_rate, max_lanes, max_link_clock;
> > int ret;
> > - bool dsc = false, joiner = false;
> > + bool dsc = false, bigjoiner = false, ultrajoiner = false;
> > u16 dsc_max_compressed_bpp = 0;
> > u8 dsc_slice_count = 0;
> > int target_clock = mode->clock;
> > @@ -1431,9 +1435,12 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
> > * corresponding link capabilities of the sink) in case the
> > * stream is uncompressed for it by the last branch device.
> > */
> > - if (intel_dp_need_joiner(intel_dp, intel_connector,
> > - mode->hdisplay, target_clock)) {
> > - joiner = true;
> > + if (intel_dp_need_ultrajoiner(intel_dp, target_clock)) {
> > + ultrajoiner = true;
> > + max_dotclk *= 4;
> > + } else if (intel_dp_need_bigjoiner(intel_dp, intel_connector,
> > + mode->hdisplay, target_clock)) {
> > + bigjoiner = true;
> > max_dotclk *= 2;
> > }
> > @@ -1461,20 +1468,22 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
> > max_lanes,
> > target_clock,
> > mode->hdisplay,
> > - joiner,
> > + bigjoiner,
> > + ultrajoiner,
> > INTEL_OUTPUT_FORMAT_RGB,
> > pipe_bpp, 64);
> > dsc_slice_count =
> > intel_dp_dsc_get_slice_count(intel_connector,
> > target_clock,
> > mode->hdisplay,
> > - joiner);
> > + bigjoiner,
> > + ultrajoiner);
> > }
> > dsc = dsc_max_compressed_bpp && dsc_slice_count;
> > }
> > - if (intel_dp_joiner_needs_dsc(dev_priv, joiner) && !dsc) {
> > + if (intel_dp_joiner_needs_dsc(dev_priv, bigjoiner, ultrajoiner) && !dsc) {
> > *status = MODE_CLOCK_HIGH;
> > return 0;
> > }
> > @@ -1484,7 +1493,7 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
> > return 0;
> > }
> > - *status = intel_mode_valid_max_plane_size(dev_priv, mode, joiner);
> > + *status = intel_mode_valid_max_plane_size(dev_priv, mode, bigjoiner, ultrajoiner);
> > return 0;
> > }
> > diff --git a/drivers/gpu/drm/i915/display/intel_dsi.c b/drivers/gpu/drm/i915/display/intel_dsi.c
> > index bd5888ce4852..1a7e9a56fccd 100644
> > --- a/drivers/gpu/drm/i915/display/intel_dsi.c
> > +++ b/drivers/gpu/drm/i915/display/intel_dsi.c
> > @@ -76,7 +76,7 @@ enum drm_mode_status intel_dsi_mode_valid(struct drm_connector *connector,
> > if (fixed_mode->clock > max_dotclk)
> > return MODE_CLOCK_HIGH;
> > - return intel_mode_valid_max_plane_size(dev_priv, mode, false);
> > + return intel_mode_valid_max_plane_size(dev_priv, mode, false, false);
> > }
> > struct intel_dsi_host *intel_dsi_host_init(struct intel_dsi *intel_dsi,
> > diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
> > index 19498ee455fa..35be89050512 100644
> > --- a/drivers/gpu/drm/i915/display/intel_hdmi.c
> > +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
> > @@ -2048,7 +2048,7 @@ intel_hdmi_mode_valid(struct drm_connector *connector,
> > return status;
> > }
> > - return intel_mode_valid_max_plane_size(dev_priv, mode, false);
> > + return intel_mode_valid_max_plane_size(dev_priv, mode, false, false);
> > }
> > bool intel_hdmi_bpc_possible(const struct intel_crtc_state *crtc_state,
> > @@ -2341,6 +2341,18 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder,
> > return ret;
> > }
> > + if (adjusted_mode->crtc_clock > dev_priv->display.cdclk.max_dotclk_freq ||
> > + pipe_config->joiner_pipes) {
> > + if (pipe_config->dsc.slice_count < 2) {
> > + drm_dbg_kms(&dev_priv->drm,
> > + "Cannot split stream to use 2 VDSC instances\n");
> > + return -EINVAL;
> > + }
> > +
> > + pipe_config->dsc.dsc_split = true;
> > + }
> > +
> > +
> > if (intel_hdmi_is_ycbcr420(pipe_config)) {
> > ret = intel_panel_fitting(pipe_config, conn_state);
> > if (ret)
> > diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c
> > index 11058bb37d5a..206b3e77e0d5 100644
> > --- a/drivers/gpu/drm/i915/display/intel_vdsc.c
> > +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c
> > @@ -13,6 +13,7 @@
> > #include "intel_crtc.h"
> > #include "intel_de.h"
> > #include "intel_display_types.h"
> > +#include "intel_dp.h"
> > #include "intel_dsi.h"
> > #include "intel_qp_tables.h"
> > #include "intel_vdsc.h"
> > @@ -379,7 +380,9 @@ int intel_dsc_get_num_vdsc_instances(const struct intel_crtc_state *crtc_state)
> > {
> > int num_vdsc_instances = intel_dsc_get_vdsc_per_pipe(crtc_state);
> > - if (crtc_state->joiner_pipes)
> > + if (intel_is_ultrajoiner(crtc_state))
> > + num_vdsc_instances *= 4;
> > + else if (intel_is_bigjoiner(crtc_state))
> > num_vdsc_instances *= 2;
> > return num_vdsc_instances;
> > @@ -770,6 +773,13 @@ void intel_uncompressed_joiner_enable(const struct intel_crtc_state *crtc_state)
> > }
> > }
> > +static bool intel_crtc_ultrajoiner_enable_needed(const struct intel_crtc_state *crtc_state)
> > +{
> > + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> > +
> > + return intel_is_ultrajoiner(crtc_state) && crtc->pipe != PIPE_D;
> > +}
> > +
> > void intel_dsc_enable(const struct intel_crtc_state *crtc_state)
> > {
> > struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> > @@ -788,8 +798,21 @@ void intel_dsc_enable(const struct intel_crtc_state *crtc_state)
> > dss_ctl2_val |= RIGHT_BRANCH_VDSC_ENABLE;
> > dss_ctl1_val |= JOINER_ENABLE;
> > }
> > +
> > if (crtc_state->joiner_pipes) {
> > + /*
> > + * This bit doesn't seem to follow master/slave logic or
> > + * any other logic, so lets just add helper function to
> > + * at least hide this hassle..
> > + */
> > + if (intel_crtc_ultrajoiner_enable_needed(crtc_state))
> > + dss_ctl1_val |= ULTRA_JOINER_ENABLE;
> > +
> > + if (intel_crtc_is_ultrajoiner_primary(crtc_state))
> > + dss_ctl1_val |= PRIMARY_ULTRA_JOINER_ENABLE;;
> > +
> > dss_ctl1_val |= BIG_JOINER_ENABLE;
> > +
> > if (intel_crtc_is_bigjoiner_primary(crtc_state))
> > dss_ctl1_val |= PRIMARY_BIG_JOINER_ENABLE;
> > }
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 3/4] drm/i915: Compute config and mode valid changes for ultrajoiner
2024-07-03 8:51 ` Nautiyal, Ankit K
2024-07-03 10:02 ` Lisovskiy, Stanislav
@ 2024-07-10 8:37 ` Lisovskiy, Stanislav
2024-07-10 13:28 ` Nautiyal, Ankit K
1 sibling, 1 reply; 15+ messages in thread
From: Lisovskiy, Stanislav @ 2024-07-10 8:37 UTC (permalink / raw)
To: Nautiyal, Ankit K; +Cc: intel-gfx, jani.saarinen, ville.syrjala
On Wed, Jul 03, 2024 at 02:21:48PM +0530, Nautiyal, Ankit K wrote:
>
> On 6/26/2024 1:48 PM, Stanislav Lisovskiy wrote:
> > Implement required changes for mode validation and compute config,
> > to support Ultrajoiner.
> > This also includes required DSC changes and checks.
> >
> > Signed-off-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
> > ---
> > drivers/gpu/drm/i915/display/intel_display.c | 5 +-
> > drivers/gpu/drm/i915/display/intel_display.h | 3 +-
> > drivers/gpu/drm/i915/display/intel_dp.c | 117 ++++++++++++++-----
> > drivers/gpu/drm/i915/display/intel_dp.h | 18 ++-
> > drivers/gpu/drm/i915/display/intel_dp_mst.c | 35 +++---
> > drivers/gpu/drm/i915/display/intel_dsi.c | 2 +-
> > drivers/gpu/drm/i915/display/intel_hdmi.c | 14 ++-
> > drivers/gpu/drm/i915/display/intel_vdsc.c | 25 +++-
> > 8 files changed, 164 insertions(+), 55 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> > index f702ead9b5f3..4c934f07ead7 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display.c
> > +++ b/drivers/gpu/drm/i915/display/intel_display.c
> > @@ -8246,7 +8246,8 @@ enum drm_mode_status intel_cpu_transcoder_mode_valid(struct drm_i915_private *de
> > enum drm_mode_status
> > intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv,
> > const struct drm_display_mode *mode,
> > - bool joiner)
> > + bool bigjoiner,
> > + bool ultrajoiner)
> > {
> > int plane_width_max, plane_height_max;
> > @@ -8263,7 +8264,7 @@ intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv,
> > * too big for that.
> > */
> > if (DISPLAY_VER(dev_priv) >= 11) {
> > - plane_width_max = 5120 << joiner;
> > + plane_width_max = (5120 << bigjoiner) << ultrajoiner;
> > plane_height_max = 4320;
> > } else {
> > plane_width_max = 5120;
> > diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
> > index bac81b7ab764..0a51f24af405 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display.h
> > +++ b/drivers/gpu/drm/i915/display/intel_display.h
> > @@ -415,7 +415,8 @@ u32 intel_plane_fb_max_stride(struct drm_i915_private *dev_priv,
> > enum drm_mode_status
> > intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv,
> > const struct drm_display_mode *mode,
> > - bool joiner);
> > + bool bigjoiner,
> > + bool ultrajoiner);
>
> Can we use joined_pipes here and in other places instead of 2 separate
> variables?
>
> So we pass joined_pipes as either 0, 2, 4 for no-joiner, big-joiner, and
> ultra-joiner.
>
> This will help simplifying the computations for example for slice count
> (mentioned inline).
>
> We can perhaps have a patch only with this change, just replacing 'joiner'
> with joined_pipes and later just send joined_pipes with 4 for ultra joiner
> in another patch?
One more thing to consider regarding using joiner_pipes instead of those booleans here:
In many places, we might not have joiner_pipes yet calculated, because we calculate it
only when intel_dp_compute_link_config is called.
For instance at intel_dp_mode_valid call site of intel_mode_valid_max_plane_size, I think
we don't have it yet calculated, so the booleans are coming from correspondent
intel_dp_need_ultra/bigjoiner functions, however joiner_pipes would probably be 0 yet.
So could be we won't be able to use joiner_pipes everywhere still.
Need to think a bit more on this thing.
Stan
>
>
> > enum drm_mode_status
> > intel_cpu_transcoder_mode_valid(struct drm_i915_private *i915,
> > const struct drm_display_mode *mode);
> > diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
> > index 3903f6ead6e6..1ea1e89d8f45 100644
> > --- a/drivers/gpu/drm/i915/display/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> > @@ -760,33 +760,41 @@ u32 intel_dp_dsc_nearest_valid_bpp(struct drm_i915_private *i915, u32 bpp, u32 p
> > static
> > u32 get_max_compressed_bpp_with_joiner(struct drm_i915_private *i915,
> > u32 mode_clock, u32 mode_hdisplay,
> > - bool bigjoiner)
> > + bool bigjoiner, bool ultrajoiner)
> > {
> > u32 max_bpp_small_joiner_ram;
> > + u32 max_bpp_joiner;
> > /* Small Joiner Check: output bpp <= joiner RAM (bits) / Horiz. width */
> > - max_bpp_small_joiner_ram = small_joiner_ram_size_bits(i915) / mode_hdisplay;
> > + max_bpp_joiner = max_bpp_small_joiner_ram =
> > + small_joiner_ram_size_bits(i915) / mode_hdisplay;
> > - if (bigjoiner) {
> > - int bigjoiner_interface_bits = DISPLAY_VER(i915) >= 14 ? 36 : 24;
> > - /* With bigjoiner multiple dsc engines are used in parallel so PPC is 2 */
> > + /* if ultra joiner is enabled, we have 2 bigjoiners enabled */
> > + if (bigjoiner || ultrajoiner) {
> > + int joiner_interface_bits = DISPLAY_VER(i915) >= 14 ? 36 : 24;
> > + /* With joiner multiple dsc engines are used in parallel so PPC is 2 */
> > int ppc = 2;
> > - u32 max_bpp_bigjoiner =
> > - i915->display.cdclk.max_cdclk_freq * ppc * bigjoiner_interface_bits /
> > + max_bpp_joiner =
> > + i915->display.cdclk.max_cdclk_freq * ppc * joiner_interface_bits /
> > intel_dp_mode_to_fec_clock(mode_clock);
> > max_bpp_small_joiner_ram *= 2;
> > + }
> > - return min(max_bpp_small_joiner_ram, max_bpp_bigjoiner);
> > + if (ultrajoiner) {
> > + /* both get multiplied by 2, because ram bits/ppc now doubled */
> > + max_bpp_small_joiner_ram *= 2;
> > + max_bpp_joiner *= 2;
> > }
> > - return max_bpp_small_joiner_ram;
> > + return min(max_bpp_small_joiner_ram, max_bpp_joiner);
> > }
> > u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915,
> > u32 link_clock, u32 lane_count,
> > u32 mode_clock, u32 mode_hdisplay,
> > bool bigjoiner,
> > + bool ultrajoiner,
> > enum intel_output_format output_format,
> > u32 pipe_bpp,
> > u32 timeslots)
> > @@ -832,7 +840,7 @@ u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915,
> > intel_dp_mode_to_fec_clock(mode_clock));
> > joiner_max_bpp = get_max_compressed_bpp_with_joiner(i915, mode_clock,
> > - mode_hdisplay, bigjoiner);
> > + mode_hdisplay, bigjoiner, ultrajoiner);
> > bits_per_pixel = min(bits_per_pixel, joiner_max_bpp);
> > bits_per_pixel = intel_dp_dsc_nearest_valid_bpp(i915, bits_per_pixel, pipe_bpp);
> > @@ -842,7 +850,8 @@ u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915,
> > u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
> > int mode_clock, int mode_hdisplay,
> > - bool bigjoiner)
> > + bool bigjoiner,
> > + bool ultrajoiner)
> > {
> > struct drm_i915_private *i915 = to_i915(connector->base.dev);
> > u8 min_slice_count, i;
> > @@ -876,7 +885,7 @@ u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
> > /* Find the closest match to the valid slice count values */
> > for (i = 0; i < ARRAY_SIZE(valid_dsc_slicecount); i++) {
> > - u8 test_slice_count = valid_dsc_slicecount[i] << bigjoiner;
> > + u8 test_slice_count = (valid_dsc_slicecount[i] << bigjoiner) << ultrajoiner;
>
> If we use joined_pipes as mentioned earlier, we can perhaps just use:
>
> u8 test_slice_count = valid_dsc_slicecount[i] << (joined_pipes / 2);
>
>
> Regards,
>
> Ankit
>
>
>
> > if (test_slice_count >
> > drm_dp_dsc_sink_max_slice_count(connector->dp.dsc_dpcd, false))
> > @@ -886,6 +895,10 @@ u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
> > if (bigjoiner && test_slice_count < 4)
> > continue;
> > + /* ultrajoiner needs 2 bigjoiners to be enabled */
> > + if (ultrajoiner && test_slice_count < 8)
> > + continue;
> > +
> > if (min_slice_count <= test_slice_count)
> > return test_slice_count;
> > }
> > @@ -1162,9 +1175,9 @@ intel_dp_mode_valid_downstream(struct intel_connector *connector,
> > return MODE_OK;
> > }
> > -bool intel_dp_need_joiner(struct intel_dp *intel_dp,
> > - struct intel_connector *connector,
> > - int hdisplay, int clock)
> > +bool intel_dp_need_bigjoiner(struct intel_dp *intel_dp,
> > + struct intel_connector *connector,
> > + int hdisplay, int clock)
> > {
> > struct drm_i915_private *i915 = dp_to_i915(intel_dp);
> > @@ -1195,6 +1208,35 @@ bool intel_dp_has_dsc(const struct intel_connector *connector)
> > return true;
> > }
> > +static
> > +bool intel_can_ultrajoiner(const struct intel_encoder *encoder)
> > +{
> > + struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> > +
> > + return IS_DGFX(i915) && DISPLAY_VER(i915) >= 14;
> > +}
> > +
> > +bool intel_dp_need_ultrajoiner(struct intel_dp *dp, int clock)
> > +{
> > + const struct intel_encoder *encoder = &dp_to_dig_port(dp)->base;
> > + struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> > +
> > + if (!intel_can_ultrajoiner(encoder))
> > + return false;
> > +
> > + return clock > (i915->display.cdclk.max_dotclk_freq * 2);
> > +}
> > +
> > +bool intel_is_bigjoiner(const struct intel_crtc_state *pipe_config)
> > +{
> > + return hweight8(pipe_config->joiner_pipes) == 2;
> > +}
> > +
> > +bool intel_is_ultrajoiner(const struct intel_crtc_state *pipe_config)
> > +{
> > + return hweight8(pipe_config->joiner_pipes) == 4;
> > +}
> > +
> > static enum drm_mode_status
> > intel_dp_mode_valid(struct drm_connector *_connector,
> > struct drm_display_mode *mode)
> > @@ -1209,7 +1251,7 @@ intel_dp_mode_valid(struct drm_connector *_connector,
> > u16 dsc_max_compressed_bpp = 0;
> > u8 dsc_slice_count = 0;
> > enum drm_mode_status status;
> > - bool dsc = false, joiner = false;
> > + bool dsc = false, bigjoiner = false, ultrajoiner = false;
> > status = intel_cpu_transcoder_mode_valid(dev_priv, mode);
> > if (status != MODE_OK)
> > @@ -1230,11 +1272,16 @@ intel_dp_mode_valid(struct drm_connector *_connector,
> > target_clock = fixed_mode->clock;
> > }
> > - if (intel_dp_need_joiner(intel_dp, connector,
> > - mode->hdisplay, target_clock)) {
> > - joiner = true;
> > + if (intel_dp_need_ultrajoiner(intel_dp, target_clock)) {
> > + ultrajoiner = true;
> > + max_dotclk *= 4;
> > + }
> > + else if (intel_dp_need_bigjoiner(intel_dp, connector,
> > + mode->hdisplay, target_clock)) {
> > + bigjoiner = true;
> > max_dotclk *= 2;
> > }
> > +
> > if (target_clock > max_dotclk)
> > return MODE_CLOCK_HIGH;
> > @@ -1278,20 +1325,22 @@ intel_dp_mode_valid(struct drm_connector *_connector,
> > max_lanes,
> > target_clock,
> > mode->hdisplay,
> > - joiner,
> > + bigjoiner,
> > + ultrajoiner,
> > output_format,
> > pipe_bpp, 64);
> > dsc_slice_count =
> > intel_dp_dsc_get_slice_count(connector,
> > target_clock,
> > mode->hdisplay,
> > - joiner);
> > + bigjoiner,
> > + ultrajoiner);
> > }
> > dsc = dsc_max_compressed_bpp && dsc_slice_count;
> > }
> > - if (intel_dp_joiner_needs_dsc(dev_priv, joiner) && !dsc)
> > + if (intel_dp_joiner_needs_dsc(dev_priv, bigjoiner, ultrajoiner) && !dsc)
> > return MODE_CLOCK_HIGH;
> > if (mode_rate > max_rate && !dsc)
> > @@ -1301,7 +1350,7 @@ intel_dp_mode_valid(struct drm_connector *_connector,
> > if (status != MODE_OK)
> > return status;
> > - return intel_mode_valid_max_plane_size(dev_priv, mode, joiner);
> > + return intel_mode_valid_max_plane_size(dev_priv, mode, bigjoiner, ultrajoiner);
> > }
> > bool intel_dp_source_supports_tps3(struct drm_i915_private *i915)
> > @@ -2015,7 +2064,8 @@ static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp,
> > dsc_joiner_max_bpp = get_max_compressed_bpp_with_joiner(i915, adjusted_mode->clock,
> > adjusted_mode->hdisplay,
> > - pipe_config->joiner_pipes);
> > + intel_is_bigjoiner(pipe_config),
> > + intel_is_ultrajoiner(pipe_config));
> > dsc_max_bpp = min(dsc_max_bpp, dsc_joiner_max_bpp);
> > dsc_max_bpp = min(dsc_max_bpp, to_bpp_int(limits->link.max_bpp_x16));
> > @@ -2249,7 +2299,8 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
> > intel_dp_dsc_get_slice_count(connector,
> > adjusted_mode->crtc_clock,
> > adjusted_mode->crtc_hdisplay,
> > - pipe_config->joiner_pipes);
> > + intel_is_bigjoiner(pipe_config),
> > + intel_is_ultrajoiner(pipe_config));
> > if (!dsc_dp_slice_count) {
> > drm_dbg_kms(&dev_priv->drm,
> > "Compressed Slice Count not supported\n");
> > @@ -2399,14 +2450,15 @@ int intel_dp_config_required_rate(const struct intel_crtc_state *crtc_state)
> > return intel_dp_link_required(adjusted_mode->crtc_clock, bpp);
> > }
> > -bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915, bool use_joiner)
> > +bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915, bool bigjoiner, bool ultrajoiner)
> > {
> > /*
> > * Pipe joiner needs compression up to display 12 due to bandwidth
> > * limitation. DG2 onwards pipe joiner can be enabled without
> > * compression.
> > + * Ultrajoiner always needs compression.
> > */
> > - return DISPLAY_VER(i915) < 13 && use_joiner;
> > + return (DISPLAY_VER(i915) < 13 && bigjoiner) || ultrajoiner;
> > }
> > static int
> > @@ -2424,18 +2476,21 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
> > struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> > struct link_config_limits limits;
> > bool dsc_needed, joiner_needs_dsc;
> > + bool bigjoiner = false, ultrajoiner = false;
> > int ret = 0;
> > if (pipe_config->fec_enable &&
> > !intel_dp_supports_fec(intel_dp, connector, pipe_config))
> > return -EINVAL;
> > - if (intel_dp_need_joiner(intel_dp, connector,
> > - adjusted_mode->crtc_hdisplay,
> > - adjusted_mode->crtc_clock))
> > + if (intel_dp_need_ultrajoiner(intel_dp, adjusted_mode->crtc_clock))
> > + pipe_config->joiner_pipes = GENMASK(crtc->pipe + 3, crtc->pipe);
> > + else if (intel_dp_need_bigjoiner(intel_dp, connector,
> > + adjusted_mode->crtc_hdisplay,
> > + adjusted_mode->crtc_clock))
> > pipe_config->joiner_pipes = GENMASK(crtc->pipe + 1, crtc->pipe);
> > - joiner_needs_dsc = intel_dp_joiner_needs_dsc(i915, pipe_config->joiner_pipes);
> > + joiner_needs_dsc = intel_dp_joiner_needs_dsc(i915, bigjoiner, ultrajoiner);
> > dsc_needed = joiner_needs_dsc || intel_dp->force_dsc_en ||
> > !intel_dp_compute_config_limits(intel_dp, pipe_config,
> > diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
> > index a0f990a95ecc..6a3615757c95 100644
> > --- a/drivers/gpu/drm/i915/display/intel_dp.h
> > +++ b/drivers/gpu/drm/i915/display/intel_dp.h
> > @@ -122,7 +122,7 @@ int intel_dp_effective_data_rate(int pixel_clock, int bpp_x16,
> > int bw_overhead);
> > int intel_dp_max_link_data_rate(struct intel_dp *intel_dp,
> > int max_dprx_rate, int max_dprx_lanes);
> > -bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915, bool use_joiner);
> > +bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915, bool use_bigjoiner, bool use_ultrajoiner);
> > bool intel_dp_has_joiner(struct intel_dp *intel_dp);
> > bool intel_dp_needs_vsc_sdp(const struct intel_crtc_state *crtc_state,
> > const struct drm_connector_state *conn_state);
> > @@ -142,6 +142,7 @@ u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915,
> > u32 link_clock, u32 lane_count,
> > u32 mode_clock, u32 mode_hdisplay,
> > bool bigjoiner,
> > + bool ultrajoiner,
> > enum intel_output_format output_format,
> > u32 pipe_bpp,
> > u32 timeslots);
> > @@ -151,10 +152,17 @@ int intel_dp_dsc_sink_max_compressed_bpp(const struct intel_connector *connector
> > int bpc);
> > u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
> > int mode_clock, int mode_hdisplay,
> > - bool bigjoiner);
> > -bool intel_dp_need_joiner(struct intel_dp *intel_dp,
> > - struct intel_connector *connector,
> > - int hdisplay, int clock);
> > + bool bigjoiner, bool ultrajoiner);
> > +bool intel_dp_need_bigjoiner(struct intel_dp *intel_dp,
> > + struct intel_connector *connector,
> > + int hdisplay, int clock);
> > +bool intel_dp_need_ultrajoiner(struct intel_dp *intel_dp, int clock);
> > +bool intel_is_bigjoiner(const struct intel_crtc_state *pipe_config);
> > +bool intel_is_ultrajoiner(const struct intel_crtc_state *pipe_config);
> > +bool intel_crtc_is_bigjoiner_slave(const struct intel_crtc_state *crtc_state);
> > +bool intel_crtc_is_bigjoiner_master(const struct intel_crtc_state *crtc_state);
> > +bool intel_crtc_is_joiner_primary_master(const struct intel_crtc_state *crtc_state);
> > +enum pipe intel_crtc_master_pipe(const struct intel_crtc_state *crtc_state);
> > static inline unsigned int intel_dp_unused_lane_mask(int lane_count)
> > {
> > diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > index 27ce5c3f5951..13828c011d9c 100644
> > --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > @@ -105,7 +105,8 @@ static int intel_dp_mst_bw_overhead(const struct intel_crtc_state *crtc_state,
> > dsc_slice_count = intel_dp_dsc_get_slice_count(connector,
> > adjusted_mode->clock,
> > adjusted_mode->hdisplay,
> > - crtc_state->joiner_pipes);
> > + intel_is_bigjoiner(crtc_state),
> > + intel_is_ultrajoiner(crtc_state));
> > }
> > overhead = drm_dp_bw_overhead(crtc_state->lane_count,
> > @@ -576,16 +577,19 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
> > if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
> > return -EINVAL;
> > - if (intel_dp_need_joiner(intel_dp, connector,
> > - adjusted_mode->crtc_hdisplay,
> > - adjusted_mode->crtc_clock))
> > + if (intel_dp_need_ultrajoiner(intel_dp, adjusted_mode->crtc_clock))
> > + pipe_config->joiner_pipes = GENMASK(crtc->pipe + 3, crtc->pipe);
> > + else if (intel_dp_need_bigjoiner(intel_dp, connector,
> > + adjusted_mode->crtc_hdisplay,
> > + adjusted_mode->crtc_clock))
> > pipe_config->joiner_pipes = GENMASK(crtc->pipe + 1, crtc->pipe);
> > pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
> > pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
> > pipe_config->has_pch_encoder = false;
> > - joiner_needs_dsc = intel_dp_joiner_needs_dsc(dev_priv, pipe_config->joiner_pipes);
> > + joiner_needs_dsc = intel_dp_joiner_needs_dsc(dev_priv, intel_is_bigjoiner(pipe_config),
> > + intel_is_ultrajoiner(pipe_config));
> > dsc_needed = joiner_needs_dsc || intel_dp->force_dsc_en ||
> > !intel_dp_mst_compute_config_limits(intel_dp,
> > @@ -1388,7 +1392,7 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
> > int max_dotclk = to_i915(connector->dev)->display.cdclk.max_dotclk_freq;
> > int max_rate, mode_rate, max_lanes, max_link_clock;
> > int ret;
> > - bool dsc = false, joiner = false;
> > + bool dsc = false, bigjoiner = false, ultrajoiner = false;
> > u16 dsc_max_compressed_bpp = 0;
> > u8 dsc_slice_count = 0;
> > int target_clock = mode->clock;
> > @@ -1431,9 +1435,12 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
> > * corresponding link capabilities of the sink) in case the
> > * stream is uncompressed for it by the last branch device.
> > */
> > - if (intel_dp_need_joiner(intel_dp, intel_connector,
> > - mode->hdisplay, target_clock)) {
> > - joiner = true;
> > + if (intel_dp_need_ultrajoiner(intel_dp, target_clock)) {
> > + ultrajoiner = true;
> > + max_dotclk *= 4;
> > + } else if (intel_dp_need_bigjoiner(intel_dp, intel_connector,
> > + mode->hdisplay, target_clock)) {
> > + bigjoiner = true;
> > max_dotclk *= 2;
> > }
> > @@ -1461,20 +1468,22 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
> > max_lanes,
> > target_clock,
> > mode->hdisplay,
> > - joiner,
> > + bigjoiner,
> > + ultrajoiner,
> > INTEL_OUTPUT_FORMAT_RGB,
> > pipe_bpp, 64);
> > dsc_slice_count =
> > intel_dp_dsc_get_slice_count(intel_connector,
> > target_clock,
> > mode->hdisplay,
> > - joiner);
> > + bigjoiner,
> > + ultrajoiner);
> > }
> > dsc = dsc_max_compressed_bpp && dsc_slice_count;
> > }
> > - if (intel_dp_joiner_needs_dsc(dev_priv, joiner) && !dsc) {
> > + if (intel_dp_joiner_needs_dsc(dev_priv, bigjoiner, ultrajoiner) && !dsc) {
> > *status = MODE_CLOCK_HIGH;
> > return 0;
> > }
> > @@ -1484,7 +1493,7 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
> > return 0;
> > }
> > - *status = intel_mode_valid_max_plane_size(dev_priv, mode, joiner);
> > + *status = intel_mode_valid_max_plane_size(dev_priv, mode, bigjoiner, ultrajoiner);
> > return 0;
> > }
> > diff --git a/drivers/gpu/drm/i915/display/intel_dsi.c b/drivers/gpu/drm/i915/display/intel_dsi.c
> > index bd5888ce4852..1a7e9a56fccd 100644
> > --- a/drivers/gpu/drm/i915/display/intel_dsi.c
> > +++ b/drivers/gpu/drm/i915/display/intel_dsi.c
> > @@ -76,7 +76,7 @@ enum drm_mode_status intel_dsi_mode_valid(struct drm_connector *connector,
> > if (fixed_mode->clock > max_dotclk)
> > return MODE_CLOCK_HIGH;
> > - return intel_mode_valid_max_plane_size(dev_priv, mode, false);
> > + return intel_mode_valid_max_plane_size(dev_priv, mode, false, false);
> > }
> > struct intel_dsi_host *intel_dsi_host_init(struct intel_dsi *intel_dsi,
> > diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
> > index 19498ee455fa..35be89050512 100644
> > --- a/drivers/gpu/drm/i915/display/intel_hdmi.c
> > +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
> > @@ -2048,7 +2048,7 @@ intel_hdmi_mode_valid(struct drm_connector *connector,
> > return status;
> > }
> > - return intel_mode_valid_max_plane_size(dev_priv, mode, false);
> > + return intel_mode_valid_max_plane_size(dev_priv, mode, false, false);
> > }
> > bool intel_hdmi_bpc_possible(const struct intel_crtc_state *crtc_state,
> > @@ -2341,6 +2341,18 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder,
> > return ret;
> > }
> > + if (adjusted_mode->crtc_clock > dev_priv->display.cdclk.max_dotclk_freq ||
> > + pipe_config->joiner_pipes) {
> > + if (pipe_config->dsc.slice_count < 2) {
> > + drm_dbg_kms(&dev_priv->drm,
> > + "Cannot split stream to use 2 VDSC instances\n");
> > + return -EINVAL;
> > + }
> > +
> > + pipe_config->dsc.dsc_split = true;
> > + }
> > +
> > +
> > if (intel_hdmi_is_ycbcr420(pipe_config)) {
> > ret = intel_panel_fitting(pipe_config, conn_state);
> > if (ret)
> > diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c
> > index 11058bb37d5a..206b3e77e0d5 100644
> > --- a/drivers/gpu/drm/i915/display/intel_vdsc.c
> > +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c
> > @@ -13,6 +13,7 @@
> > #include "intel_crtc.h"
> > #include "intel_de.h"
> > #include "intel_display_types.h"
> > +#include "intel_dp.h"
> > #include "intel_dsi.h"
> > #include "intel_qp_tables.h"
> > #include "intel_vdsc.h"
> > @@ -379,7 +380,9 @@ int intel_dsc_get_num_vdsc_instances(const struct intel_crtc_state *crtc_state)
> > {
> > int num_vdsc_instances = intel_dsc_get_vdsc_per_pipe(crtc_state);
> > - if (crtc_state->joiner_pipes)
> > + if (intel_is_ultrajoiner(crtc_state))
> > + num_vdsc_instances *= 4;
> > + else if (intel_is_bigjoiner(crtc_state))
> > num_vdsc_instances *= 2;
> > return num_vdsc_instances;
> > @@ -770,6 +773,13 @@ void intel_uncompressed_joiner_enable(const struct intel_crtc_state *crtc_state)
> > }
> > }
> > +static bool intel_crtc_ultrajoiner_enable_needed(const struct intel_crtc_state *crtc_state)
> > +{
> > + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> > +
> > + return intel_is_ultrajoiner(crtc_state) && crtc->pipe != PIPE_D;
> > +}
> > +
> > void intel_dsc_enable(const struct intel_crtc_state *crtc_state)
> > {
> > struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> > @@ -788,8 +798,21 @@ void intel_dsc_enable(const struct intel_crtc_state *crtc_state)
> > dss_ctl2_val |= RIGHT_BRANCH_VDSC_ENABLE;
> > dss_ctl1_val |= JOINER_ENABLE;
> > }
> > +
> > if (crtc_state->joiner_pipes) {
> > + /*
> > + * This bit doesn't seem to follow master/slave logic or
> > + * any other logic, so lets just add helper function to
> > + * at least hide this hassle..
> > + */
> > + if (intel_crtc_ultrajoiner_enable_needed(crtc_state))
> > + dss_ctl1_val |= ULTRA_JOINER_ENABLE;
> > +
> > + if (intel_crtc_is_ultrajoiner_primary(crtc_state))
> > + dss_ctl1_val |= PRIMARY_ULTRA_JOINER_ENABLE;;
> > +
> > dss_ctl1_val |= BIG_JOINER_ENABLE;
> > +
> > if (intel_crtc_is_bigjoiner_primary(crtc_state))
> > dss_ctl1_val |= PRIMARY_BIG_JOINER_ENABLE;
> > }
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 3/4] drm/i915: Compute config and mode valid changes for ultrajoiner
2024-07-10 8:37 ` Lisovskiy, Stanislav
@ 2024-07-10 13:28 ` Nautiyal, Ankit K
2024-07-11 8:12 ` Lisovskiy, Stanislav
0 siblings, 1 reply; 15+ messages in thread
From: Nautiyal, Ankit K @ 2024-07-10 13:28 UTC (permalink / raw)
To: Lisovskiy, Stanislav; +Cc: intel-gfx, jani.saarinen, ville.syrjala
On 7/10/2024 2:07 PM, Lisovskiy, Stanislav wrote:
> On Wed, Jul 03, 2024 at 02:21:48PM +0530, Nautiyal, Ankit K wrote:
>> On 6/26/2024 1:48 PM, Stanislav Lisovskiy wrote:
>>> Implement required changes for mode validation and compute config,
>>> to support Ultrajoiner.
>>> This also includes required DSC changes and checks.
>>>
>>> Signed-off-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
>>> ---
>>> drivers/gpu/drm/i915/display/intel_display.c | 5 +-
>>> drivers/gpu/drm/i915/display/intel_display.h | 3 +-
>>> drivers/gpu/drm/i915/display/intel_dp.c | 117 ++++++++++++++-----
>>> drivers/gpu/drm/i915/display/intel_dp.h | 18 ++-
>>> drivers/gpu/drm/i915/display/intel_dp_mst.c | 35 +++---
>>> drivers/gpu/drm/i915/display/intel_dsi.c | 2 +-
>>> drivers/gpu/drm/i915/display/intel_hdmi.c | 14 ++-
>>> drivers/gpu/drm/i915/display/intel_vdsc.c | 25 +++-
>>> 8 files changed, 164 insertions(+), 55 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
>>> index f702ead9b5f3..4c934f07ead7 100644
>>> --- a/drivers/gpu/drm/i915/display/intel_display.c
>>> +++ b/drivers/gpu/drm/i915/display/intel_display.c
>>> @@ -8246,7 +8246,8 @@ enum drm_mode_status intel_cpu_transcoder_mode_valid(struct drm_i915_private *de
>>> enum drm_mode_status
>>> intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv,
>>> const struct drm_display_mode *mode,
>>> - bool joiner)
>>> + bool bigjoiner,
>>> + bool ultrajoiner)
>>> {
>>> int plane_width_max, plane_height_max;
>>> @@ -8263,7 +8264,7 @@ intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv,
>>> * too big for that.
>>> */
>>> if (DISPLAY_VER(dev_priv) >= 11) {
>>> - plane_width_max = 5120 << joiner;
>>> + plane_width_max = (5120 << bigjoiner) << ultrajoiner;
>>> plane_height_max = 4320;
>>> } else {
>>> plane_width_max = 5120;
>>> diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
>>> index bac81b7ab764..0a51f24af405 100644
>>> --- a/drivers/gpu/drm/i915/display/intel_display.h
>>> +++ b/drivers/gpu/drm/i915/display/intel_display.h
>>> @@ -415,7 +415,8 @@ u32 intel_plane_fb_max_stride(struct drm_i915_private *dev_priv,
>>> enum drm_mode_status
>>> intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv,
>>> const struct drm_display_mode *mode,
>>> - bool joiner);
>>> + bool bigjoiner,
>>> + bool ultrajoiner);
>> Can we use joined_pipes here and in other places instead of 2 separate
>> variables?
>>
>> So we pass joined_pipes as either 0, 2, 4 for no-joiner, big-joiner, and
>> ultra-joiner.
>>
>> This will help simplifying the computations for example for slice count
>> (mentioned inline).
>>
>> We can perhaps have a patch only with this change, just replacing 'joiner'
>> with joined_pipes and later just send joined_pipes with 4 for ultra joiner
>> in another patch?
> One more thing to consider regarding using joiner_pipes instead of those booleans here:
> In many places, we might not have joiner_pipes yet calculated, because we calculate it
> only when intel_dp_compute_link_config is called.
> For instance at intel_dp_mode_valid call site of intel_mode_valid_max_plane_size, I think
> we don't have it yet calculated, so the booleans are coming from correspondent
> intel_dp_need_ultra/bigjoiner functions, however joiner_pipes would probably be 0 yet.
>
> So could be we won't be able to use joiner_pipes everywhere still.
> Need to think a bit more on this thing.
Hmm I was thinking if we can use macros like JOINER_PIPES_NONE,
JOINER_PIPES_BIG, JOINER_PIPES_ULTRA which can be passed in all places.
Regards,
Ankit
> Stan
>
>>
>>> enum drm_mode_status
>>> intel_cpu_transcoder_mode_valid(struct drm_i915_private *i915,
>>> const struct drm_display_mode *mode);
>>> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
>>> index 3903f6ead6e6..1ea1e89d8f45 100644
>>> --- a/drivers/gpu/drm/i915/display/intel_dp.c
>>> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
>>> @@ -760,33 +760,41 @@ u32 intel_dp_dsc_nearest_valid_bpp(struct drm_i915_private *i915, u32 bpp, u32 p
>>> static
>>> u32 get_max_compressed_bpp_with_joiner(struct drm_i915_private *i915,
>>> u32 mode_clock, u32 mode_hdisplay,
>>> - bool bigjoiner)
>>> + bool bigjoiner, bool ultrajoiner)
>>> {
>>> u32 max_bpp_small_joiner_ram;
>>> + u32 max_bpp_joiner;
>>> /* Small Joiner Check: output bpp <= joiner RAM (bits) / Horiz. width */
>>> - max_bpp_small_joiner_ram = small_joiner_ram_size_bits(i915) / mode_hdisplay;
>>> + max_bpp_joiner = max_bpp_small_joiner_ram =
>>> + small_joiner_ram_size_bits(i915) / mode_hdisplay;
>>> - if (bigjoiner) {
>>> - int bigjoiner_interface_bits = DISPLAY_VER(i915) >= 14 ? 36 : 24;
>>> - /* With bigjoiner multiple dsc engines are used in parallel so PPC is 2 */
>>> + /* if ultra joiner is enabled, we have 2 bigjoiners enabled */
>>> + if (bigjoiner || ultrajoiner) {
>>> + int joiner_interface_bits = DISPLAY_VER(i915) >= 14 ? 36 : 24;
>>> + /* With joiner multiple dsc engines are used in parallel so PPC is 2 */
>>> int ppc = 2;
>>> - u32 max_bpp_bigjoiner =
>>> - i915->display.cdclk.max_cdclk_freq * ppc * bigjoiner_interface_bits /
>>> + max_bpp_joiner =
>>> + i915->display.cdclk.max_cdclk_freq * ppc * joiner_interface_bits /
>>> intel_dp_mode_to_fec_clock(mode_clock);
>>> max_bpp_small_joiner_ram *= 2;
>>> + }
>>> - return min(max_bpp_small_joiner_ram, max_bpp_bigjoiner);
>>> + if (ultrajoiner) {
>>> + /* both get multiplied by 2, because ram bits/ppc now doubled */
>>> + max_bpp_small_joiner_ram *= 2;
>>> + max_bpp_joiner *= 2;
>>> }
>>> - return max_bpp_small_joiner_ram;
>>> + return min(max_bpp_small_joiner_ram, max_bpp_joiner);
>>> }
>>> u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915,
>>> u32 link_clock, u32 lane_count,
>>> u32 mode_clock, u32 mode_hdisplay,
>>> bool bigjoiner,
>>> + bool ultrajoiner,
>>> enum intel_output_format output_format,
>>> u32 pipe_bpp,
>>> u32 timeslots)
>>> @@ -832,7 +840,7 @@ u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915,
>>> intel_dp_mode_to_fec_clock(mode_clock));
>>> joiner_max_bpp = get_max_compressed_bpp_with_joiner(i915, mode_clock,
>>> - mode_hdisplay, bigjoiner);
>>> + mode_hdisplay, bigjoiner, ultrajoiner);
>>> bits_per_pixel = min(bits_per_pixel, joiner_max_bpp);
>>> bits_per_pixel = intel_dp_dsc_nearest_valid_bpp(i915, bits_per_pixel, pipe_bpp);
>>> @@ -842,7 +850,8 @@ u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915,
>>> u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
>>> int mode_clock, int mode_hdisplay,
>>> - bool bigjoiner)
>>> + bool bigjoiner,
>>> + bool ultrajoiner)
>>> {
>>> struct drm_i915_private *i915 = to_i915(connector->base.dev);
>>> u8 min_slice_count, i;
>>> @@ -876,7 +885,7 @@ u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
>>> /* Find the closest match to the valid slice count values */
>>> for (i = 0; i < ARRAY_SIZE(valid_dsc_slicecount); i++) {
>>> - u8 test_slice_count = valid_dsc_slicecount[i] << bigjoiner;
>>> + u8 test_slice_count = (valid_dsc_slicecount[i] << bigjoiner) << ultrajoiner;
>> If we use joined_pipes as mentioned earlier, we can perhaps just use:
>>
>> u8 test_slice_count = valid_dsc_slicecount[i] << (joined_pipes / 2);
>>
>>
>> Regards,
>>
>> Ankit
>>
>>
>>
>>> if (test_slice_count >
>>> drm_dp_dsc_sink_max_slice_count(connector->dp.dsc_dpcd, false))
>>> @@ -886,6 +895,10 @@ u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
>>> if (bigjoiner && test_slice_count < 4)
>>> continue;
>>> + /* ultrajoiner needs 2 bigjoiners to be enabled */
>>> + if (ultrajoiner && test_slice_count < 8)
>>> + continue;
>>> +
>>> if (min_slice_count <= test_slice_count)
>>> return test_slice_count;
>>> }
>>> @@ -1162,9 +1175,9 @@ intel_dp_mode_valid_downstream(struct intel_connector *connector,
>>> return MODE_OK;
>>> }
>>> -bool intel_dp_need_joiner(struct intel_dp *intel_dp,
>>> - struct intel_connector *connector,
>>> - int hdisplay, int clock)
>>> +bool intel_dp_need_bigjoiner(struct intel_dp *intel_dp,
>>> + struct intel_connector *connector,
>>> + int hdisplay, int clock)
>>> {
>>> struct drm_i915_private *i915 = dp_to_i915(intel_dp);
>>> @@ -1195,6 +1208,35 @@ bool intel_dp_has_dsc(const struct intel_connector *connector)
>>> return true;
>>> }
>>> +static
>>> +bool intel_can_ultrajoiner(const struct intel_encoder *encoder)
>>> +{
>>> + struct drm_i915_private *i915 = to_i915(encoder->base.dev);
>>> +
>>> + return IS_DGFX(i915) && DISPLAY_VER(i915) >= 14;
>>> +}
>>> +
>>> +bool intel_dp_need_ultrajoiner(struct intel_dp *dp, int clock)
>>> +{
>>> + const struct intel_encoder *encoder = &dp_to_dig_port(dp)->base;
>>> + struct drm_i915_private *i915 = to_i915(encoder->base.dev);
>>> +
>>> + if (!intel_can_ultrajoiner(encoder))
>>> + return false;
>>> +
>>> + return clock > (i915->display.cdclk.max_dotclk_freq * 2);
>>> +}
>>> +
>>> +bool intel_is_bigjoiner(const struct intel_crtc_state *pipe_config)
>>> +{
>>> + return hweight8(pipe_config->joiner_pipes) == 2;
>>> +}
>>> +
>>> +bool intel_is_ultrajoiner(const struct intel_crtc_state *pipe_config)
>>> +{
>>> + return hweight8(pipe_config->joiner_pipes) == 4;
>>> +}
>>> +
>>> static enum drm_mode_status
>>> intel_dp_mode_valid(struct drm_connector *_connector,
>>> struct drm_display_mode *mode)
>>> @@ -1209,7 +1251,7 @@ intel_dp_mode_valid(struct drm_connector *_connector,
>>> u16 dsc_max_compressed_bpp = 0;
>>> u8 dsc_slice_count = 0;
>>> enum drm_mode_status status;
>>> - bool dsc = false, joiner = false;
>>> + bool dsc = false, bigjoiner = false, ultrajoiner = false;
>>> status = intel_cpu_transcoder_mode_valid(dev_priv, mode);
>>> if (status != MODE_OK)
>>> @@ -1230,11 +1272,16 @@ intel_dp_mode_valid(struct drm_connector *_connector,
>>> target_clock = fixed_mode->clock;
>>> }
>>> - if (intel_dp_need_joiner(intel_dp, connector,
>>> - mode->hdisplay, target_clock)) {
>>> - joiner = true;
>>> + if (intel_dp_need_ultrajoiner(intel_dp, target_clock)) {
>>> + ultrajoiner = true;
>>> + max_dotclk *= 4;
>>> + }
>>> + else if (intel_dp_need_bigjoiner(intel_dp, connector,
>>> + mode->hdisplay, target_clock)) {
>>> + bigjoiner = true;
>>> max_dotclk *= 2;
>>> }
>>> +
>>> if (target_clock > max_dotclk)
>>> return MODE_CLOCK_HIGH;
>>> @@ -1278,20 +1325,22 @@ intel_dp_mode_valid(struct drm_connector *_connector,
>>> max_lanes,
>>> target_clock,
>>> mode->hdisplay,
>>> - joiner,
>>> + bigjoiner,
>>> + ultrajoiner,
>>> output_format,
>>> pipe_bpp, 64);
>>> dsc_slice_count =
>>> intel_dp_dsc_get_slice_count(connector,
>>> target_clock,
>>> mode->hdisplay,
>>> - joiner);
>>> + bigjoiner,
>>> + ultrajoiner);
>>> }
>>> dsc = dsc_max_compressed_bpp && dsc_slice_count;
>>> }
>>> - if (intel_dp_joiner_needs_dsc(dev_priv, joiner) && !dsc)
>>> + if (intel_dp_joiner_needs_dsc(dev_priv, bigjoiner, ultrajoiner) && !dsc)
>>> return MODE_CLOCK_HIGH;
>>> if (mode_rate > max_rate && !dsc)
>>> @@ -1301,7 +1350,7 @@ intel_dp_mode_valid(struct drm_connector *_connector,
>>> if (status != MODE_OK)
>>> return status;
>>> - return intel_mode_valid_max_plane_size(dev_priv, mode, joiner);
>>> + return intel_mode_valid_max_plane_size(dev_priv, mode, bigjoiner, ultrajoiner);
>>> }
>>> bool intel_dp_source_supports_tps3(struct drm_i915_private *i915)
>>> @@ -2015,7 +2064,8 @@ static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp,
>>> dsc_joiner_max_bpp = get_max_compressed_bpp_with_joiner(i915, adjusted_mode->clock,
>>> adjusted_mode->hdisplay,
>>> - pipe_config->joiner_pipes);
>>> + intel_is_bigjoiner(pipe_config),
>>> + intel_is_ultrajoiner(pipe_config));
>>> dsc_max_bpp = min(dsc_max_bpp, dsc_joiner_max_bpp);
>>> dsc_max_bpp = min(dsc_max_bpp, to_bpp_int(limits->link.max_bpp_x16));
>>> @@ -2249,7 +2299,8 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
>>> intel_dp_dsc_get_slice_count(connector,
>>> adjusted_mode->crtc_clock,
>>> adjusted_mode->crtc_hdisplay,
>>> - pipe_config->joiner_pipes);
>>> + intel_is_bigjoiner(pipe_config),
>>> + intel_is_ultrajoiner(pipe_config));
>>> if (!dsc_dp_slice_count) {
>>> drm_dbg_kms(&dev_priv->drm,
>>> "Compressed Slice Count not supported\n");
>>> @@ -2399,14 +2450,15 @@ int intel_dp_config_required_rate(const struct intel_crtc_state *crtc_state)
>>> return intel_dp_link_required(adjusted_mode->crtc_clock, bpp);
>>> }
>>> -bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915, bool use_joiner)
>>> +bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915, bool bigjoiner, bool ultrajoiner)
>>> {
>>> /*
>>> * Pipe joiner needs compression up to display 12 due to bandwidth
>>> * limitation. DG2 onwards pipe joiner can be enabled without
>>> * compression.
>>> + * Ultrajoiner always needs compression.
>>> */
>>> - return DISPLAY_VER(i915) < 13 && use_joiner;
>>> + return (DISPLAY_VER(i915) < 13 && bigjoiner) || ultrajoiner;
>>> }
>>> static int
>>> @@ -2424,18 +2476,21 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
>>> struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
>>> struct link_config_limits limits;
>>> bool dsc_needed, joiner_needs_dsc;
>>> + bool bigjoiner = false, ultrajoiner = false;
>>> int ret = 0;
>>> if (pipe_config->fec_enable &&
>>> !intel_dp_supports_fec(intel_dp, connector, pipe_config))
>>> return -EINVAL;
>>> - if (intel_dp_need_joiner(intel_dp, connector,
>>> - adjusted_mode->crtc_hdisplay,
>>> - adjusted_mode->crtc_clock))
>>> + if (intel_dp_need_ultrajoiner(intel_dp, adjusted_mode->crtc_clock))
>>> + pipe_config->joiner_pipes = GENMASK(crtc->pipe + 3, crtc->pipe);
>>> + else if (intel_dp_need_bigjoiner(intel_dp, connector,
>>> + adjusted_mode->crtc_hdisplay,
>>> + adjusted_mode->crtc_clock))
>>> pipe_config->joiner_pipes = GENMASK(crtc->pipe + 1, crtc->pipe);
>>> - joiner_needs_dsc = intel_dp_joiner_needs_dsc(i915, pipe_config->joiner_pipes);
>>> + joiner_needs_dsc = intel_dp_joiner_needs_dsc(i915, bigjoiner, ultrajoiner);
>>> dsc_needed = joiner_needs_dsc || intel_dp->force_dsc_en ||
>>> !intel_dp_compute_config_limits(intel_dp, pipe_config,
>>> diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
>>> index a0f990a95ecc..6a3615757c95 100644
>>> --- a/drivers/gpu/drm/i915/display/intel_dp.h
>>> +++ b/drivers/gpu/drm/i915/display/intel_dp.h
>>> @@ -122,7 +122,7 @@ int intel_dp_effective_data_rate(int pixel_clock, int bpp_x16,
>>> int bw_overhead);
>>> int intel_dp_max_link_data_rate(struct intel_dp *intel_dp,
>>> int max_dprx_rate, int max_dprx_lanes);
>>> -bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915, bool use_joiner);
>>> +bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915, bool use_bigjoiner, bool use_ultrajoiner);
>>> bool intel_dp_has_joiner(struct intel_dp *intel_dp);
>>> bool intel_dp_needs_vsc_sdp(const struct intel_crtc_state *crtc_state,
>>> const struct drm_connector_state *conn_state);
>>> @@ -142,6 +142,7 @@ u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915,
>>> u32 link_clock, u32 lane_count,
>>> u32 mode_clock, u32 mode_hdisplay,
>>> bool bigjoiner,
>>> + bool ultrajoiner,
>>> enum intel_output_format output_format,
>>> u32 pipe_bpp,
>>> u32 timeslots);
>>> @@ -151,10 +152,17 @@ int intel_dp_dsc_sink_max_compressed_bpp(const struct intel_connector *connector
>>> int bpc);
>>> u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
>>> int mode_clock, int mode_hdisplay,
>>> - bool bigjoiner);
>>> -bool intel_dp_need_joiner(struct intel_dp *intel_dp,
>>> - struct intel_connector *connector,
>>> - int hdisplay, int clock);
>>> + bool bigjoiner, bool ultrajoiner);
>>> +bool intel_dp_need_bigjoiner(struct intel_dp *intel_dp,
>>> + struct intel_connector *connector,
>>> + int hdisplay, int clock);
>>> +bool intel_dp_need_ultrajoiner(struct intel_dp *intel_dp, int clock);
>>> +bool intel_is_bigjoiner(const struct intel_crtc_state *pipe_config);
>>> +bool intel_is_ultrajoiner(const struct intel_crtc_state *pipe_config);
>>> +bool intel_crtc_is_bigjoiner_slave(const struct intel_crtc_state *crtc_state);
>>> +bool intel_crtc_is_bigjoiner_master(const struct intel_crtc_state *crtc_state);
>>> +bool intel_crtc_is_joiner_primary_master(const struct intel_crtc_state *crtc_state);
>>> +enum pipe intel_crtc_master_pipe(const struct intel_crtc_state *crtc_state);
>>> static inline unsigned int intel_dp_unused_lane_mask(int lane_count)
>>> {
>>> diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
>>> index 27ce5c3f5951..13828c011d9c 100644
>>> --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
>>> +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
>>> @@ -105,7 +105,8 @@ static int intel_dp_mst_bw_overhead(const struct intel_crtc_state *crtc_state,
>>> dsc_slice_count = intel_dp_dsc_get_slice_count(connector,
>>> adjusted_mode->clock,
>>> adjusted_mode->hdisplay,
>>> - crtc_state->joiner_pipes);
>>> + intel_is_bigjoiner(crtc_state),
>>> + intel_is_ultrajoiner(crtc_state));
>>> }
>>> overhead = drm_dp_bw_overhead(crtc_state->lane_count,
>>> @@ -576,16 +577,19 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
>>> if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
>>> return -EINVAL;
>>> - if (intel_dp_need_joiner(intel_dp, connector,
>>> - adjusted_mode->crtc_hdisplay,
>>> - adjusted_mode->crtc_clock))
>>> + if (intel_dp_need_ultrajoiner(intel_dp, adjusted_mode->crtc_clock))
>>> + pipe_config->joiner_pipes = GENMASK(crtc->pipe + 3, crtc->pipe);
>>> + else if (intel_dp_need_bigjoiner(intel_dp, connector,
>>> + adjusted_mode->crtc_hdisplay,
>>> + adjusted_mode->crtc_clock))
>>> pipe_config->joiner_pipes = GENMASK(crtc->pipe + 1, crtc->pipe);
>>> pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
>>> pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
>>> pipe_config->has_pch_encoder = false;
>>> - joiner_needs_dsc = intel_dp_joiner_needs_dsc(dev_priv, pipe_config->joiner_pipes);
>>> + joiner_needs_dsc = intel_dp_joiner_needs_dsc(dev_priv, intel_is_bigjoiner(pipe_config),
>>> + intel_is_ultrajoiner(pipe_config));
>>> dsc_needed = joiner_needs_dsc || intel_dp->force_dsc_en ||
>>> !intel_dp_mst_compute_config_limits(intel_dp,
>>> @@ -1388,7 +1392,7 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
>>> int max_dotclk = to_i915(connector->dev)->display.cdclk.max_dotclk_freq;
>>> int max_rate, mode_rate, max_lanes, max_link_clock;
>>> int ret;
>>> - bool dsc = false, joiner = false;
>>> + bool dsc = false, bigjoiner = false, ultrajoiner = false;
>>> u16 dsc_max_compressed_bpp = 0;
>>> u8 dsc_slice_count = 0;
>>> int target_clock = mode->clock;
>>> @@ -1431,9 +1435,12 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
>>> * corresponding link capabilities of the sink) in case the
>>> * stream is uncompressed for it by the last branch device.
>>> */
>>> - if (intel_dp_need_joiner(intel_dp, intel_connector,
>>> - mode->hdisplay, target_clock)) {
>>> - joiner = true;
>>> + if (intel_dp_need_ultrajoiner(intel_dp, target_clock)) {
>>> + ultrajoiner = true;
>>> + max_dotclk *= 4;
>>> + } else if (intel_dp_need_bigjoiner(intel_dp, intel_connector,
>>> + mode->hdisplay, target_clock)) {
>>> + bigjoiner = true;
>>> max_dotclk *= 2;
>>> }
>>> @@ -1461,20 +1468,22 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
>>> max_lanes,
>>> target_clock,
>>> mode->hdisplay,
>>> - joiner,
>>> + bigjoiner,
>>> + ultrajoiner,
>>> INTEL_OUTPUT_FORMAT_RGB,
>>> pipe_bpp, 64);
>>> dsc_slice_count =
>>> intel_dp_dsc_get_slice_count(intel_connector,
>>> target_clock,
>>> mode->hdisplay,
>>> - joiner);
>>> + bigjoiner,
>>> + ultrajoiner);
>>> }
>>> dsc = dsc_max_compressed_bpp && dsc_slice_count;
>>> }
>>> - if (intel_dp_joiner_needs_dsc(dev_priv, joiner) && !dsc) {
>>> + if (intel_dp_joiner_needs_dsc(dev_priv, bigjoiner, ultrajoiner) && !dsc) {
>>> *status = MODE_CLOCK_HIGH;
>>> return 0;
>>> }
>>> @@ -1484,7 +1493,7 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
>>> return 0;
>>> }
>>> - *status = intel_mode_valid_max_plane_size(dev_priv, mode, joiner);
>>> + *status = intel_mode_valid_max_plane_size(dev_priv, mode, bigjoiner, ultrajoiner);
>>> return 0;
>>> }
>>> diff --git a/drivers/gpu/drm/i915/display/intel_dsi.c b/drivers/gpu/drm/i915/display/intel_dsi.c
>>> index bd5888ce4852..1a7e9a56fccd 100644
>>> --- a/drivers/gpu/drm/i915/display/intel_dsi.c
>>> +++ b/drivers/gpu/drm/i915/display/intel_dsi.c
>>> @@ -76,7 +76,7 @@ enum drm_mode_status intel_dsi_mode_valid(struct drm_connector *connector,
>>> if (fixed_mode->clock > max_dotclk)
>>> return MODE_CLOCK_HIGH;
>>> - return intel_mode_valid_max_plane_size(dev_priv, mode, false);
>>> + return intel_mode_valid_max_plane_size(dev_priv, mode, false, false);
>>> }
>>> struct intel_dsi_host *intel_dsi_host_init(struct intel_dsi *intel_dsi,
>>> diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
>>> index 19498ee455fa..35be89050512 100644
>>> --- a/drivers/gpu/drm/i915/display/intel_hdmi.c
>>> +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
>>> @@ -2048,7 +2048,7 @@ intel_hdmi_mode_valid(struct drm_connector *connector,
>>> return status;
>>> }
>>> - return intel_mode_valid_max_plane_size(dev_priv, mode, false);
>>> + return intel_mode_valid_max_plane_size(dev_priv, mode, false, false);
>>> }
>>> bool intel_hdmi_bpc_possible(const struct intel_crtc_state *crtc_state,
>>> @@ -2341,6 +2341,18 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder,
>>> return ret;
>>> }
>>> + if (adjusted_mode->crtc_clock > dev_priv->display.cdclk.max_dotclk_freq ||
>>> + pipe_config->joiner_pipes) {
>>> + if (pipe_config->dsc.slice_count < 2) {
>>> + drm_dbg_kms(&dev_priv->drm,
>>> + "Cannot split stream to use 2 VDSC instances\n");
>>> + return -EINVAL;
>>> + }
>>> +
>>> + pipe_config->dsc.dsc_split = true;
>>> + }
>>> +
>>> +
>>> if (intel_hdmi_is_ycbcr420(pipe_config)) {
>>> ret = intel_panel_fitting(pipe_config, conn_state);
>>> if (ret)
>>> diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c
>>> index 11058bb37d5a..206b3e77e0d5 100644
>>> --- a/drivers/gpu/drm/i915/display/intel_vdsc.c
>>> +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c
>>> @@ -13,6 +13,7 @@
>>> #include "intel_crtc.h"
>>> #include "intel_de.h"
>>> #include "intel_display_types.h"
>>> +#include "intel_dp.h"
>>> #include "intel_dsi.h"
>>> #include "intel_qp_tables.h"
>>> #include "intel_vdsc.h"
>>> @@ -379,7 +380,9 @@ int intel_dsc_get_num_vdsc_instances(const struct intel_crtc_state *crtc_state)
>>> {
>>> int num_vdsc_instances = intel_dsc_get_vdsc_per_pipe(crtc_state);
>>> - if (crtc_state->joiner_pipes)
>>> + if (intel_is_ultrajoiner(crtc_state))
>>> + num_vdsc_instances *= 4;
>>> + else if (intel_is_bigjoiner(crtc_state))
>>> num_vdsc_instances *= 2;
>>> return num_vdsc_instances;
>>> @@ -770,6 +773,13 @@ void intel_uncompressed_joiner_enable(const struct intel_crtc_state *crtc_state)
>>> }
>>> }
>>> +static bool intel_crtc_ultrajoiner_enable_needed(const struct intel_crtc_state *crtc_state)
>>> +{
>>> + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
>>> +
>>> + return intel_is_ultrajoiner(crtc_state) && crtc->pipe != PIPE_D;
>>> +}
>>> +
>>> void intel_dsc_enable(const struct intel_crtc_state *crtc_state)
>>> {
>>> struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
>>> @@ -788,8 +798,21 @@ void intel_dsc_enable(const struct intel_crtc_state *crtc_state)
>>> dss_ctl2_val |= RIGHT_BRANCH_VDSC_ENABLE;
>>> dss_ctl1_val |= JOINER_ENABLE;
>>> }
>>> +
>>> if (crtc_state->joiner_pipes) {
>>> + /*
>>> + * This bit doesn't seem to follow master/slave logic or
>>> + * any other logic, so lets just add helper function to
>>> + * at least hide this hassle..
>>> + */
>>> + if (intel_crtc_ultrajoiner_enable_needed(crtc_state))
>>> + dss_ctl1_val |= ULTRA_JOINER_ENABLE;
>>> +
>>> + if (intel_crtc_is_ultrajoiner_primary(crtc_state))
>>> + dss_ctl1_val |= PRIMARY_ULTRA_JOINER_ENABLE;;
>>> +
>>> dss_ctl1_val |= BIG_JOINER_ENABLE;
>>> +
>>> if (intel_crtc_is_bigjoiner_primary(crtc_state))
>>> dss_ctl1_val |= PRIMARY_BIG_JOINER_ENABLE;
>>> }
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 3/4] drm/i915: Compute config and mode valid changes for ultrajoiner
2024-07-10 13:28 ` Nautiyal, Ankit K
@ 2024-07-11 8:12 ` Lisovskiy, Stanislav
0 siblings, 0 replies; 15+ messages in thread
From: Lisovskiy, Stanislav @ 2024-07-11 8:12 UTC (permalink / raw)
To: Nautiyal, Ankit K; +Cc: intel-gfx, jani.saarinen, ville.syrjala
On Wed, Jul 10, 2024 at 06:58:14PM +0530, Nautiyal, Ankit K wrote:
>
> On 7/10/2024 2:07 PM, Lisovskiy, Stanislav wrote:
> > On Wed, Jul 03, 2024 at 02:21:48PM +0530, Nautiyal, Ankit K wrote:
> > > On 6/26/2024 1:48 PM, Stanislav Lisovskiy wrote:
> > > > Implement required changes for mode validation and compute config,
> > > > to support Ultrajoiner.
> > > > This also includes required DSC changes and checks.
> > > >
> > > > Signed-off-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
> > > > ---
> > > > drivers/gpu/drm/i915/display/intel_display.c | 5 +-
> > > > drivers/gpu/drm/i915/display/intel_display.h | 3 +-
> > > > drivers/gpu/drm/i915/display/intel_dp.c | 117 ++++++++++++++-----
> > > > drivers/gpu/drm/i915/display/intel_dp.h | 18 ++-
> > > > drivers/gpu/drm/i915/display/intel_dp_mst.c | 35 +++---
> > > > drivers/gpu/drm/i915/display/intel_dsi.c | 2 +-
> > > > drivers/gpu/drm/i915/display/intel_hdmi.c | 14 ++-
> > > > drivers/gpu/drm/i915/display/intel_vdsc.c | 25 +++-
> > > > 8 files changed, 164 insertions(+), 55 deletions(-)
> > > >
> > > > diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> > > > index f702ead9b5f3..4c934f07ead7 100644
> > > > --- a/drivers/gpu/drm/i915/display/intel_display.c
> > > > +++ b/drivers/gpu/drm/i915/display/intel_display.c
> > > > @@ -8246,7 +8246,8 @@ enum drm_mode_status intel_cpu_transcoder_mode_valid(struct drm_i915_private *de
> > > > enum drm_mode_status
> > > > intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv,
> > > > const struct drm_display_mode *mode,
> > > > - bool joiner)
> > > > + bool bigjoiner,
> > > > + bool ultrajoiner)
> > > > {
> > > > int plane_width_max, plane_height_max;
> > > > @@ -8263,7 +8264,7 @@ intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv,
> > > > * too big for that.
> > > > */
> > > > if (DISPLAY_VER(dev_priv) >= 11) {
> > > > - plane_width_max = 5120 << joiner;
> > > > + plane_width_max = (5120 << bigjoiner) << ultrajoiner;
> > > > plane_height_max = 4320;
> > > > } else {
> > > > plane_width_max = 5120;
> > > > diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
> > > > index bac81b7ab764..0a51f24af405 100644
> > > > --- a/drivers/gpu/drm/i915/display/intel_display.h
> > > > +++ b/drivers/gpu/drm/i915/display/intel_display.h
> > > > @@ -415,7 +415,8 @@ u32 intel_plane_fb_max_stride(struct drm_i915_private *dev_priv,
> > > > enum drm_mode_status
> > > > intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv,
> > > > const struct drm_display_mode *mode,
> > > > - bool joiner);
> > > > + bool bigjoiner,
> > > > + bool ultrajoiner);
> > > Can we use joined_pipes here and in other places instead of 2 separate
> > > variables?
> > >
> > > So we pass joined_pipes as either 0, 2, 4 for no-joiner, big-joiner, and
> > > ultra-joiner.
> > >
> > > This will help simplifying the computations for example for slice count
> > > (mentioned inline).
> > >
> > > We can perhaps have a patch only with this change, just replacing 'joiner'
> > > with joined_pipes and later just send joined_pipes with 4 for ultra joiner
> > > in another patch?
> > One more thing to consider regarding using joiner_pipes instead of those booleans here:
> > In many places, we might not have joiner_pipes yet calculated, because we calculate it
> > only when intel_dp_compute_link_config is called.
> > For instance at intel_dp_mode_valid call site of intel_mode_valid_max_plane_size, I think
> > we don't have it yet calculated, so the booleans are coming from correspondent
> > intel_dp_need_ultra/bigjoiner functions, however joiner_pipes would probably be 0 yet.
> >
> > So could be we won't be able to use joiner_pipes everywhere still.
> > Need to think a bit more on this thing.
>
>
> Hmm I was thinking if we can use macros like JOINER_PIPES_NONE,
> JOINER_PIPES_BIG, JOINER_PIPES_ULTRA which can be passed in all places.
Probably enum would be better then.
Something like:
enum joiner_type
{
no_joiner,
bigjoiner,
ultrajoiner
};
Stan
>
> Regards,
>
> Ankit
>
>
> > Stan
> >
> > >
> > > > enum drm_mode_status
> > > > intel_cpu_transcoder_mode_valid(struct drm_i915_private *i915,
> > > > const struct drm_display_mode *mode);
> > > > diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
> > > > index 3903f6ead6e6..1ea1e89d8f45 100644
> > > > --- a/drivers/gpu/drm/i915/display/intel_dp.c
> > > > +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> > > > @@ -760,33 +760,41 @@ u32 intel_dp_dsc_nearest_valid_bpp(struct drm_i915_private *i915, u32 bpp, u32 p
> > > > static
> > > > u32 get_max_compressed_bpp_with_joiner(struct drm_i915_private *i915,
> > > > u32 mode_clock, u32 mode_hdisplay,
> > > > - bool bigjoiner)
> > > > + bool bigjoiner, bool ultrajoiner)
> > > > {
> > > > u32 max_bpp_small_joiner_ram;
> > > > + u32 max_bpp_joiner;
> > > > /* Small Joiner Check: output bpp <= joiner RAM (bits) / Horiz. width */
> > > > - max_bpp_small_joiner_ram = small_joiner_ram_size_bits(i915) / mode_hdisplay;
> > > > + max_bpp_joiner = max_bpp_small_joiner_ram =
> > > > + small_joiner_ram_size_bits(i915) / mode_hdisplay;
> > > > - if (bigjoiner) {
> > > > - int bigjoiner_interface_bits = DISPLAY_VER(i915) >= 14 ? 36 : 24;
> > > > - /* With bigjoiner multiple dsc engines are used in parallel so PPC is 2 */
> > > > + /* if ultra joiner is enabled, we have 2 bigjoiners enabled */
> > > > + if (bigjoiner || ultrajoiner) {
> > > > + int joiner_interface_bits = DISPLAY_VER(i915) >= 14 ? 36 : 24;
> > > > + /* With joiner multiple dsc engines are used in parallel so PPC is 2 */
> > > > int ppc = 2;
> > > > - u32 max_bpp_bigjoiner =
> > > > - i915->display.cdclk.max_cdclk_freq * ppc * bigjoiner_interface_bits /
> > > > + max_bpp_joiner =
> > > > + i915->display.cdclk.max_cdclk_freq * ppc * joiner_interface_bits /
> > > > intel_dp_mode_to_fec_clock(mode_clock);
> > > > max_bpp_small_joiner_ram *= 2;
> > > > + }
> > > > - return min(max_bpp_small_joiner_ram, max_bpp_bigjoiner);
> > > > + if (ultrajoiner) {
> > > > + /* both get multiplied by 2, because ram bits/ppc now doubled */
> > > > + max_bpp_small_joiner_ram *= 2;
> > > > + max_bpp_joiner *= 2;
> > > > }
> > > > - return max_bpp_small_joiner_ram;
> > > > + return min(max_bpp_small_joiner_ram, max_bpp_joiner);
> > > > }
> > > > u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915,
> > > > u32 link_clock, u32 lane_count,
> > > > u32 mode_clock, u32 mode_hdisplay,
> > > > bool bigjoiner,
> > > > + bool ultrajoiner,
> > > > enum intel_output_format output_format,
> > > > u32 pipe_bpp,
> > > > u32 timeslots)
> > > > @@ -832,7 +840,7 @@ u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915,
> > > > intel_dp_mode_to_fec_clock(mode_clock));
> > > > joiner_max_bpp = get_max_compressed_bpp_with_joiner(i915, mode_clock,
> > > > - mode_hdisplay, bigjoiner);
> > > > + mode_hdisplay, bigjoiner, ultrajoiner);
> > > > bits_per_pixel = min(bits_per_pixel, joiner_max_bpp);
> > > > bits_per_pixel = intel_dp_dsc_nearest_valid_bpp(i915, bits_per_pixel, pipe_bpp);
> > > > @@ -842,7 +850,8 @@ u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915,
> > > > u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
> > > > int mode_clock, int mode_hdisplay,
> > > > - bool bigjoiner)
> > > > + bool bigjoiner,
> > > > + bool ultrajoiner)
> > > > {
> > > > struct drm_i915_private *i915 = to_i915(connector->base.dev);
> > > > u8 min_slice_count, i;
> > > > @@ -876,7 +885,7 @@ u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
> > > > /* Find the closest match to the valid slice count values */
> > > > for (i = 0; i < ARRAY_SIZE(valid_dsc_slicecount); i++) {
> > > > - u8 test_slice_count = valid_dsc_slicecount[i] << bigjoiner;
> > > > + u8 test_slice_count = (valid_dsc_slicecount[i] << bigjoiner) << ultrajoiner;
> > > If we use joined_pipes as mentioned earlier, we can perhaps just use:
> > >
> > > u8 test_slice_count = valid_dsc_slicecount[i] << (joined_pipes / 2);
> > >
> > >
> > > Regards,
> > >
> > > Ankit
> > >
> > >
> > >
> > > > if (test_slice_count >
> > > > drm_dp_dsc_sink_max_slice_count(connector->dp.dsc_dpcd, false))
> > > > @@ -886,6 +895,10 @@ u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
> > > > if (bigjoiner && test_slice_count < 4)
> > > > continue;
> > > > + /* ultrajoiner needs 2 bigjoiners to be enabled */
> > > > + if (ultrajoiner && test_slice_count < 8)
> > > > + continue;
> > > > +
> > > > if (min_slice_count <= test_slice_count)
> > > > return test_slice_count;
> > > > }
> > > > @@ -1162,9 +1175,9 @@ intel_dp_mode_valid_downstream(struct intel_connector *connector,
> > > > return MODE_OK;
> > > > }
> > > > -bool intel_dp_need_joiner(struct intel_dp *intel_dp,
> > > > - struct intel_connector *connector,
> > > > - int hdisplay, int clock)
> > > > +bool intel_dp_need_bigjoiner(struct intel_dp *intel_dp,
> > > > + struct intel_connector *connector,
> > > > + int hdisplay, int clock)
> > > > {
> > > > struct drm_i915_private *i915 = dp_to_i915(intel_dp);
> > > > @@ -1195,6 +1208,35 @@ bool intel_dp_has_dsc(const struct intel_connector *connector)
> > > > return true;
> > > > }
> > > > +static
> > > > +bool intel_can_ultrajoiner(const struct intel_encoder *encoder)
> > > > +{
> > > > + struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> > > > +
> > > > + return IS_DGFX(i915) && DISPLAY_VER(i915) >= 14;
> > > > +}
> > > > +
> > > > +bool intel_dp_need_ultrajoiner(struct intel_dp *dp, int clock)
> > > > +{
> > > > + const struct intel_encoder *encoder = &dp_to_dig_port(dp)->base;
> > > > + struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> > > > +
> > > > + if (!intel_can_ultrajoiner(encoder))
> > > > + return false;
> > > > +
> > > > + return clock > (i915->display.cdclk.max_dotclk_freq * 2);
> > > > +}
> > > > +
> > > > +bool intel_is_bigjoiner(const struct intel_crtc_state *pipe_config)
> > > > +{
> > > > + return hweight8(pipe_config->joiner_pipes) == 2;
> > > > +}
> > > > +
> > > > +bool intel_is_ultrajoiner(const struct intel_crtc_state *pipe_config)
> > > > +{
> > > > + return hweight8(pipe_config->joiner_pipes) == 4;
> > > > +}
> > > > +
> > > > static enum drm_mode_status
> > > > intel_dp_mode_valid(struct drm_connector *_connector,
> > > > struct drm_display_mode *mode)
> > > > @@ -1209,7 +1251,7 @@ intel_dp_mode_valid(struct drm_connector *_connector,
> > > > u16 dsc_max_compressed_bpp = 0;
> > > > u8 dsc_slice_count = 0;
> > > > enum drm_mode_status status;
> > > > - bool dsc = false, joiner = false;
> > > > + bool dsc = false, bigjoiner = false, ultrajoiner = false;
> > > > status = intel_cpu_transcoder_mode_valid(dev_priv, mode);
> > > > if (status != MODE_OK)
> > > > @@ -1230,11 +1272,16 @@ intel_dp_mode_valid(struct drm_connector *_connector,
> > > > target_clock = fixed_mode->clock;
> > > > }
> > > > - if (intel_dp_need_joiner(intel_dp, connector,
> > > > - mode->hdisplay, target_clock)) {
> > > > - joiner = true;
> > > > + if (intel_dp_need_ultrajoiner(intel_dp, target_clock)) {
> > > > + ultrajoiner = true;
> > > > + max_dotclk *= 4;
> > > > + }
> > > > + else if (intel_dp_need_bigjoiner(intel_dp, connector,
> > > > + mode->hdisplay, target_clock)) {
> > > > + bigjoiner = true;
> > > > max_dotclk *= 2;
> > > > }
> > > > +
> > > > if (target_clock > max_dotclk)
> > > > return MODE_CLOCK_HIGH;
> > > > @@ -1278,20 +1325,22 @@ intel_dp_mode_valid(struct drm_connector *_connector,
> > > > max_lanes,
> > > > target_clock,
> > > > mode->hdisplay,
> > > > - joiner,
> > > > + bigjoiner,
> > > > + ultrajoiner,
> > > > output_format,
> > > > pipe_bpp, 64);
> > > > dsc_slice_count =
> > > > intel_dp_dsc_get_slice_count(connector,
> > > > target_clock,
> > > > mode->hdisplay,
> > > > - joiner);
> > > > + bigjoiner,
> > > > + ultrajoiner);
> > > > }
> > > > dsc = dsc_max_compressed_bpp && dsc_slice_count;
> > > > }
> > > > - if (intel_dp_joiner_needs_dsc(dev_priv, joiner) && !dsc)
> > > > + if (intel_dp_joiner_needs_dsc(dev_priv, bigjoiner, ultrajoiner) && !dsc)
> > > > return MODE_CLOCK_HIGH;
> > > > if (mode_rate > max_rate && !dsc)
> > > > @@ -1301,7 +1350,7 @@ intel_dp_mode_valid(struct drm_connector *_connector,
> > > > if (status != MODE_OK)
> > > > return status;
> > > > - return intel_mode_valid_max_plane_size(dev_priv, mode, joiner);
> > > > + return intel_mode_valid_max_plane_size(dev_priv, mode, bigjoiner, ultrajoiner);
> > > > }
> > > > bool intel_dp_source_supports_tps3(struct drm_i915_private *i915)
> > > > @@ -2015,7 +2064,8 @@ static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp,
> > > > dsc_joiner_max_bpp = get_max_compressed_bpp_with_joiner(i915, adjusted_mode->clock,
> > > > adjusted_mode->hdisplay,
> > > > - pipe_config->joiner_pipes);
> > > > + intel_is_bigjoiner(pipe_config),
> > > > + intel_is_ultrajoiner(pipe_config));
> > > > dsc_max_bpp = min(dsc_max_bpp, dsc_joiner_max_bpp);
> > > > dsc_max_bpp = min(dsc_max_bpp, to_bpp_int(limits->link.max_bpp_x16));
> > > > @@ -2249,7 +2299,8 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
> > > > intel_dp_dsc_get_slice_count(connector,
> > > > adjusted_mode->crtc_clock,
> > > > adjusted_mode->crtc_hdisplay,
> > > > - pipe_config->joiner_pipes);
> > > > + intel_is_bigjoiner(pipe_config),
> > > > + intel_is_ultrajoiner(pipe_config));
> > > > if (!dsc_dp_slice_count) {
> > > > drm_dbg_kms(&dev_priv->drm,
> > > > "Compressed Slice Count not supported\n");
> > > > @@ -2399,14 +2450,15 @@ int intel_dp_config_required_rate(const struct intel_crtc_state *crtc_state)
> > > > return intel_dp_link_required(adjusted_mode->crtc_clock, bpp);
> > > > }
> > > > -bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915, bool use_joiner)
> > > > +bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915, bool bigjoiner, bool ultrajoiner)
> > > > {
> > > > /*
> > > > * Pipe joiner needs compression up to display 12 due to bandwidth
> > > > * limitation. DG2 onwards pipe joiner can be enabled without
> > > > * compression.
> > > > + * Ultrajoiner always needs compression.
> > > > */
> > > > - return DISPLAY_VER(i915) < 13 && use_joiner;
> > > > + return (DISPLAY_VER(i915) < 13 && bigjoiner) || ultrajoiner;
> > > > }
> > > > static int
> > > > @@ -2424,18 +2476,21 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
> > > > struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> > > > struct link_config_limits limits;
> > > > bool dsc_needed, joiner_needs_dsc;
> > > > + bool bigjoiner = false, ultrajoiner = false;
> > > > int ret = 0;
> > > > if (pipe_config->fec_enable &&
> > > > !intel_dp_supports_fec(intel_dp, connector, pipe_config))
> > > > return -EINVAL;
> > > > - if (intel_dp_need_joiner(intel_dp, connector,
> > > > - adjusted_mode->crtc_hdisplay,
> > > > - adjusted_mode->crtc_clock))
> > > > + if (intel_dp_need_ultrajoiner(intel_dp, adjusted_mode->crtc_clock))
> > > > + pipe_config->joiner_pipes = GENMASK(crtc->pipe + 3, crtc->pipe);
> > > > + else if (intel_dp_need_bigjoiner(intel_dp, connector,
> > > > + adjusted_mode->crtc_hdisplay,
> > > > + adjusted_mode->crtc_clock))
> > > > pipe_config->joiner_pipes = GENMASK(crtc->pipe + 1, crtc->pipe);
> > > > - joiner_needs_dsc = intel_dp_joiner_needs_dsc(i915, pipe_config->joiner_pipes);
> > > > + joiner_needs_dsc = intel_dp_joiner_needs_dsc(i915, bigjoiner, ultrajoiner);
> > > > dsc_needed = joiner_needs_dsc || intel_dp->force_dsc_en ||
> > > > !intel_dp_compute_config_limits(intel_dp, pipe_config,
> > > > diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
> > > > index a0f990a95ecc..6a3615757c95 100644
> > > > --- a/drivers/gpu/drm/i915/display/intel_dp.h
> > > > +++ b/drivers/gpu/drm/i915/display/intel_dp.h
> > > > @@ -122,7 +122,7 @@ int intel_dp_effective_data_rate(int pixel_clock, int bpp_x16,
> > > > int bw_overhead);
> > > > int intel_dp_max_link_data_rate(struct intel_dp *intel_dp,
> > > > int max_dprx_rate, int max_dprx_lanes);
> > > > -bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915, bool use_joiner);
> > > > +bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915, bool use_bigjoiner, bool use_ultrajoiner);
> > > > bool intel_dp_has_joiner(struct intel_dp *intel_dp);
> > > > bool intel_dp_needs_vsc_sdp(const struct intel_crtc_state *crtc_state,
> > > > const struct drm_connector_state *conn_state);
> > > > @@ -142,6 +142,7 @@ u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915,
> > > > u32 link_clock, u32 lane_count,
> > > > u32 mode_clock, u32 mode_hdisplay,
> > > > bool bigjoiner,
> > > > + bool ultrajoiner,
> > > > enum intel_output_format output_format,
> > > > u32 pipe_bpp,
> > > > u32 timeslots);
> > > > @@ -151,10 +152,17 @@ int intel_dp_dsc_sink_max_compressed_bpp(const struct intel_connector *connector
> > > > int bpc);
> > > > u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
> > > > int mode_clock, int mode_hdisplay,
> > > > - bool bigjoiner);
> > > > -bool intel_dp_need_joiner(struct intel_dp *intel_dp,
> > > > - struct intel_connector *connector,
> > > > - int hdisplay, int clock);
> > > > + bool bigjoiner, bool ultrajoiner);
> > > > +bool intel_dp_need_bigjoiner(struct intel_dp *intel_dp,
> > > > + struct intel_connector *connector,
> > > > + int hdisplay, int clock);
> > > > +bool intel_dp_need_ultrajoiner(struct intel_dp *intel_dp, int clock);
> > > > +bool intel_is_bigjoiner(const struct intel_crtc_state *pipe_config);
> > > > +bool intel_is_ultrajoiner(const struct intel_crtc_state *pipe_config);
> > > > +bool intel_crtc_is_bigjoiner_slave(const struct intel_crtc_state *crtc_state);
> > > > +bool intel_crtc_is_bigjoiner_master(const struct intel_crtc_state *crtc_state);
> > > > +bool intel_crtc_is_joiner_primary_master(const struct intel_crtc_state *crtc_state);
> > > > +enum pipe intel_crtc_master_pipe(const struct intel_crtc_state *crtc_state);
> > > > static inline unsigned int intel_dp_unused_lane_mask(int lane_count)
> > > > {
> > > > diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > index 27ce5c3f5951..13828c011d9c 100644
> > > > --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > @@ -105,7 +105,8 @@ static int intel_dp_mst_bw_overhead(const struct intel_crtc_state *crtc_state,
> > > > dsc_slice_count = intel_dp_dsc_get_slice_count(connector,
> > > > adjusted_mode->clock,
> > > > adjusted_mode->hdisplay,
> > > > - crtc_state->joiner_pipes);
> > > > + intel_is_bigjoiner(crtc_state),
> > > > + intel_is_ultrajoiner(crtc_state));
> > > > }
> > > > overhead = drm_dp_bw_overhead(crtc_state->lane_count,
> > > > @@ -576,16 +577,19 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
> > > > if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
> > > > return -EINVAL;
> > > > - if (intel_dp_need_joiner(intel_dp, connector,
> > > > - adjusted_mode->crtc_hdisplay,
> > > > - adjusted_mode->crtc_clock))
> > > > + if (intel_dp_need_ultrajoiner(intel_dp, adjusted_mode->crtc_clock))
> > > > + pipe_config->joiner_pipes = GENMASK(crtc->pipe + 3, crtc->pipe);
> > > > + else if (intel_dp_need_bigjoiner(intel_dp, connector,
> > > > + adjusted_mode->crtc_hdisplay,
> > > > + adjusted_mode->crtc_clock))
> > > > pipe_config->joiner_pipes = GENMASK(crtc->pipe + 1, crtc->pipe);
> > > > pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
> > > > pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
> > > > pipe_config->has_pch_encoder = false;
> > > > - joiner_needs_dsc = intel_dp_joiner_needs_dsc(dev_priv, pipe_config->joiner_pipes);
> > > > + joiner_needs_dsc = intel_dp_joiner_needs_dsc(dev_priv, intel_is_bigjoiner(pipe_config),
> > > > + intel_is_ultrajoiner(pipe_config));
> > > > dsc_needed = joiner_needs_dsc || intel_dp->force_dsc_en ||
> > > > !intel_dp_mst_compute_config_limits(intel_dp,
> > > > @@ -1388,7 +1392,7 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
> > > > int max_dotclk = to_i915(connector->dev)->display.cdclk.max_dotclk_freq;
> > > > int max_rate, mode_rate, max_lanes, max_link_clock;
> > > > int ret;
> > > > - bool dsc = false, joiner = false;
> > > > + bool dsc = false, bigjoiner = false, ultrajoiner = false;
> > > > u16 dsc_max_compressed_bpp = 0;
> > > > u8 dsc_slice_count = 0;
> > > > int target_clock = mode->clock;
> > > > @@ -1431,9 +1435,12 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
> > > > * corresponding link capabilities of the sink) in case the
> > > > * stream is uncompressed for it by the last branch device.
> > > > */
> > > > - if (intel_dp_need_joiner(intel_dp, intel_connector,
> > > > - mode->hdisplay, target_clock)) {
> > > > - joiner = true;
> > > > + if (intel_dp_need_ultrajoiner(intel_dp, target_clock)) {
> > > > + ultrajoiner = true;
> > > > + max_dotclk *= 4;
> > > > + } else if (intel_dp_need_bigjoiner(intel_dp, intel_connector,
> > > > + mode->hdisplay, target_clock)) {
> > > > + bigjoiner = true;
> > > > max_dotclk *= 2;
> > > > }
> > > > @@ -1461,20 +1468,22 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
> > > > max_lanes,
> > > > target_clock,
> > > > mode->hdisplay,
> > > > - joiner,
> > > > + bigjoiner,
> > > > + ultrajoiner,
> > > > INTEL_OUTPUT_FORMAT_RGB,
> > > > pipe_bpp, 64);
> > > > dsc_slice_count =
> > > > intel_dp_dsc_get_slice_count(intel_connector,
> > > > target_clock,
> > > > mode->hdisplay,
> > > > - joiner);
> > > > + bigjoiner,
> > > > + ultrajoiner);
> > > > }
> > > > dsc = dsc_max_compressed_bpp && dsc_slice_count;
> > > > }
> > > > - if (intel_dp_joiner_needs_dsc(dev_priv, joiner) && !dsc) {
> > > > + if (intel_dp_joiner_needs_dsc(dev_priv, bigjoiner, ultrajoiner) && !dsc) {
> > > > *status = MODE_CLOCK_HIGH;
> > > > return 0;
> > > > }
> > > > @@ -1484,7 +1493,7 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
> > > > return 0;
> > > > }
> > > > - *status = intel_mode_valid_max_plane_size(dev_priv, mode, joiner);
> > > > + *status = intel_mode_valid_max_plane_size(dev_priv, mode, bigjoiner, ultrajoiner);
> > > > return 0;
> > > > }
> > > > diff --git a/drivers/gpu/drm/i915/display/intel_dsi.c b/drivers/gpu/drm/i915/display/intel_dsi.c
> > > > index bd5888ce4852..1a7e9a56fccd 100644
> > > > --- a/drivers/gpu/drm/i915/display/intel_dsi.c
> > > > +++ b/drivers/gpu/drm/i915/display/intel_dsi.c
> > > > @@ -76,7 +76,7 @@ enum drm_mode_status intel_dsi_mode_valid(struct drm_connector *connector,
> > > > if (fixed_mode->clock > max_dotclk)
> > > > return MODE_CLOCK_HIGH;
> > > > - return intel_mode_valid_max_plane_size(dev_priv, mode, false);
> > > > + return intel_mode_valid_max_plane_size(dev_priv, mode, false, false);
> > > > }
> > > > struct intel_dsi_host *intel_dsi_host_init(struct intel_dsi *intel_dsi,
> > > > diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
> > > > index 19498ee455fa..35be89050512 100644
> > > > --- a/drivers/gpu/drm/i915/display/intel_hdmi.c
> > > > +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
> > > > @@ -2048,7 +2048,7 @@ intel_hdmi_mode_valid(struct drm_connector *connector,
> > > > return status;
> > > > }
> > > > - return intel_mode_valid_max_plane_size(dev_priv, mode, false);
> > > > + return intel_mode_valid_max_plane_size(dev_priv, mode, false, false);
> > > > }
> > > > bool intel_hdmi_bpc_possible(const struct intel_crtc_state *crtc_state,
> > > > @@ -2341,6 +2341,18 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder,
> > > > return ret;
> > > > }
> > > > + if (adjusted_mode->crtc_clock > dev_priv->display.cdclk.max_dotclk_freq ||
> > > > + pipe_config->joiner_pipes) {
> > > > + if (pipe_config->dsc.slice_count < 2) {
> > > > + drm_dbg_kms(&dev_priv->drm,
> > > > + "Cannot split stream to use 2 VDSC instances\n");
> > > > + return -EINVAL;
> > > > + }
> > > > +
> > > > + pipe_config->dsc.dsc_split = true;
> > > > + }
> > > > +
> > > > +
> > > > if (intel_hdmi_is_ycbcr420(pipe_config)) {
> > > > ret = intel_panel_fitting(pipe_config, conn_state);
> > > > if (ret)
> > > > diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c
> > > > index 11058bb37d5a..206b3e77e0d5 100644
> > > > --- a/drivers/gpu/drm/i915/display/intel_vdsc.c
> > > > +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c
> > > > @@ -13,6 +13,7 @@
> > > > #include "intel_crtc.h"
> > > > #include "intel_de.h"
> > > > #include "intel_display_types.h"
> > > > +#include "intel_dp.h"
> > > > #include "intel_dsi.h"
> > > > #include "intel_qp_tables.h"
> > > > #include "intel_vdsc.h"
> > > > @@ -379,7 +380,9 @@ int intel_dsc_get_num_vdsc_instances(const struct intel_crtc_state *crtc_state)
> > > > {
> > > > int num_vdsc_instances = intel_dsc_get_vdsc_per_pipe(crtc_state);
> > > > - if (crtc_state->joiner_pipes)
> > > > + if (intel_is_ultrajoiner(crtc_state))
> > > > + num_vdsc_instances *= 4;
> > > > + else if (intel_is_bigjoiner(crtc_state))
> > > > num_vdsc_instances *= 2;
> > > > return num_vdsc_instances;
> > > > @@ -770,6 +773,13 @@ void intel_uncompressed_joiner_enable(const struct intel_crtc_state *crtc_state)
> > > > }
> > > > }
> > > > +static bool intel_crtc_ultrajoiner_enable_needed(const struct intel_crtc_state *crtc_state)
> > > > +{
> > > > + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> > > > +
> > > > + return intel_is_ultrajoiner(crtc_state) && crtc->pipe != PIPE_D;
> > > > +}
> > > > +
> > > > void intel_dsc_enable(const struct intel_crtc_state *crtc_state)
> > > > {
> > > > struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> > > > @@ -788,8 +798,21 @@ void intel_dsc_enable(const struct intel_crtc_state *crtc_state)
> > > > dss_ctl2_val |= RIGHT_BRANCH_VDSC_ENABLE;
> > > > dss_ctl1_val |= JOINER_ENABLE;
> > > > }
> > > > +
> > > > if (crtc_state->joiner_pipes) {
> > > > + /*
> > > > + * This bit doesn't seem to follow master/slave logic or
> > > > + * any other logic, so lets just add helper function to
> > > > + * at least hide this hassle..
> > > > + */
> > > > + if (intel_crtc_ultrajoiner_enable_needed(crtc_state))
> > > > + dss_ctl1_val |= ULTRA_JOINER_ENABLE;
> > > > +
> > > > + if (intel_crtc_is_ultrajoiner_primary(crtc_state))
> > > > + dss_ctl1_val |= PRIMARY_ULTRA_JOINER_ENABLE;;
> > > > +
> > > > dss_ctl1_val |= BIG_JOINER_ENABLE;
> > > > +
> > > > if (intel_crtc_is_bigjoiner_primary(crtc_state))
> > > > dss_ctl1_val |= PRIMARY_BIG_JOINER_ENABLE;
> > > > }
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2024-07-11 8:12 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-06-26 8:18 [PATCH 0/4] Ultrajoiner basic functionality series Stanislav Lisovskiy
2024-06-26 8:18 ` [PATCH 1/4] drm/i915: Add some essential functionality for joiners Stanislav Lisovskiy
2024-06-26 10:23 ` Jani Nikula
2024-06-26 8:18 ` [PATCH 2/4] drm/i915: Implement hw state readout for ultrajoiner Stanislav Lisovskiy
2024-07-01 19:17 ` Ville Syrjälä
2024-06-26 8:18 ` [PATCH 3/4] drm/i915: Compute config and mode valid changes " Stanislav Lisovskiy
2024-07-03 8:51 ` Nautiyal, Ankit K
2024-07-03 10:02 ` Lisovskiy, Stanislav
2024-07-10 8:37 ` Lisovskiy, Stanislav
2024-07-10 13:28 ` Nautiyal, Ankit K
2024-07-11 8:12 ` Lisovskiy, Stanislav
2024-07-03 8:59 ` Nautiyal, Ankit K
2024-06-26 8:18 ` [PATCH 4/4] drm/i915: Add new abstraction layer to handle pipe order for different joiners Stanislav Lisovskiy
2024-06-26 8:58 ` ✗ Fi.CI.CHECKPATCH: warning for Ultrajoiner basic functionality series (rev4) Patchwork
2024-06-26 9:06 ` ✗ Fi.CI.BAT: failure " Patchwork
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).