[PATCH 06/10] drm/i915/display: Disable PSR before disabling VRR

2024-07-22 Thread Ankit Nautiyal
As per bspec 49268: Disable PSR before disabling VRR.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_display.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index ecfd77c0b741..95fe58613bf6 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -1192,6 +1192,8 @@ static void intel_pre_plane_update(struct 
intel_atomic_state *state,
intel_atomic_get_new_crtc_state(state, crtc);
enum pipe pipe = crtc->pipe;
 
+   intel_psr_pre_plane_update(state, crtc);
+
if (intel_crtc_vrr_disabling(state, crtc)) {
intel_vrr_disable(old_crtc_state);
intel_crtc_update_active_timings(old_crtc_state, false);
@@ -1202,8 +1204,6 @@ static void intel_pre_plane_update(struct 
intel_atomic_state *state,
 
intel_drrs_deactivate(old_crtc_state);
 
-   intel_psr_pre_plane_update(state, crtc);
-
if (hsw_ips_pre_update(state, crtc))
intel_crtc_wait_for_next_vblank(crtc);
 
-- 
2.45.2



[PATCH 07/10] drm/i915/psr: Allow PSR for fixed refrsh rate with VRR TG

2024-07-22 Thread Ankit Nautiyal
At the moment PSR/PSR2 are not supported with variable refresh rate.
However it can be supported with fixed refresh rate while running with
VRR timing generator.
Enable PSR for fixed refresh rate when using the VRR timing generator.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_psr.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index 9cb1cdaaeefa..5a228d8e93b5 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -1523,7 +1523,7 @@ static bool _psr_compute_config(struct intel_dp *intel_dp,
 * Current PSR panels don't work reliably with VRR enabled
 * So if VRR is enabled, do not enable PSR.
 */
-   if (crtc_state->vrr.enable)
+   if (crtc_state->vrr.enable && !crtc_state->vrr.fixed_rr)
return false;
 
if (!CAN_PSR(intel_dp))
-- 
2.45.2



[PATCH 10/10] drm/i915/vrr: Always use VRR timing generator for XELPD+

2024-07-22 Thread Ankit Nautiyal
Currently VRR timing generator is used only when VRR is enabled by
userspace. From XELPD+, gradually move away from older timing
generator and use VRR timing generator for fixed refresh rate also.
In such a case, Flipline VMin and VMax all are set to the Vtotal of the
mode, which effectively makes the VRR timing generator work in
fixed refresh rate mode.

v2: Use VRR Timing Generator from XELPD+ instead of MTL as it needs
Wa_14015406119.

v3: Set vrr.fixed during vrr_get_config (Mitul)

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_vrr.c | 63 +++-
 1 file changed, 41 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c 
b/drivers/gpu/drm/i915/display/intel_vrr.c
index 50ac2770a42d..ef965c273a9e 100644
--- a/drivers/gpu/drm/i915/display/intel_vrr.c
+++ b/drivers/gpu/drm/i915/display/intel_vrr.c
@@ -174,41 +174,56 @@ intel_vrr_compute_config(struct intel_crtc_state 
*crtc_state,
if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
return;
 
-   crtc_state->vrr.in_range =
-   intel_vrr_is_in_range(connector, 
drm_mode_vrefresh(adjusted_mode));
-   if (!crtc_state->vrr.in_range)
-   return;
-
if (HAS_LRR(i915))
crtc_state->update_lrr = true;
 
-   vmin = DIV_ROUND_UP(adjusted_mode->crtc_clock * 1000,
-   adjusted_mode->crtc_htotal * 
info->monitor_range.max_vfreq);
-   vmax = adjusted_mode->crtc_clock * 1000 /
-   (adjusted_mode->crtc_htotal * info->monitor_range.min_vfreq);
+   if (!crtc_state->uapi.vrr_enabled && DISPLAY_VER(i915) >= 20) {
+   /*
+* for XELPD+ always go for VRR timing generator even for
+* fixed refresh rate.
+*/
+   crtc_state->vrr.vmin = adjusted_mode->crtc_vtotal;
+   crtc_state->vrr.vmax = adjusted_mode->crtc_vtotal;
+   crtc_state->vrr.flipline = adjusted_mode->crtc_vtotal;
+   crtc_state->vrr.fixed_rr = true;
+   } else {
 
-   vmin = max_t(int, vmin, adjusted_mode->crtc_vtotal);
-   vmax = max_t(int, vmax, adjusted_mode->crtc_vtotal);
+   crtc_state->vrr.in_range =
+   intel_vrr_is_in_range(connector, 
drm_mode_vrefresh(adjusted_mode));
 
-   if (vmin >= vmax)
-   return;
+   if (!crtc_state->vrr.in_range)
+   return;
 
-   /*
-* flipline determines the min vblank length the hardware will
-* generate, and flipline>=vmin+1, hence we reduce vmin by one
-* to make sure we can get the actual min vblank length.
-*/
-   crtc_state->vrr.vmin = vmin - 1;
-   crtc_state->vrr.vmax = vmax;
 
-   crtc_state->vrr.flipline = crtc_state->vrr.vmin + 1;
+   vmin = DIV_ROUND_UP(adjusted_mode->crtc_clock * 1000,
+   adjusted_mode->crtc_htotal * 
info->monitor_range.max_vfreq);
+   vmax = adjusted_mode->crtc_clock * 1000 /
+   (adjusted_mode->crtc_htotal * 
info->monitor_range.min_vfreq);
+
+   vmin = max_t(int, vmin, adjusted_mode->crtc_vtotal);
+   vmax = max_t(int, vmax, adjusted_mode->crtc_vtotal);
+
+   if (vmin >= vmax)
+   return;
+
+   /*
+* flipline determines the min vblank length the hardware will
+* generate, and flipline>=vmin+1, hence we reduce vmin by one
+* to make sure we can get the actual min vblank length.
+*/
+   crtc_state->vrr.vmin = vmin - 1;
+   crtc_state->vrr.vmax = vmax;
+
+   crtc_state->vrr.flipline = crtc_state->vrr.vmin + 1;
+   crtc_state->vrr.fixed_rr = false;
+   }
 
/*
 * When panel is VRR capable and userspace has
 * not enabled adaptive sync mode then Fixed Average
 * Vtotal mode should be enabled.
 */
-   if (crtc_state->uapi.vrr_enabled) {
+   if (crtc_state->uapi.vrr_enabled || crtc_state->vrr.fixed_rr) {
crtc_state->vrr.enable = true;
crtc_state->mode_flags |= I915_MODE_FLAG_VRR;
} else if (is_cmrr_frac_required(crtc_state) && is_edp) {
@@ -426,6 +441,10 @@ void intel_vrr_get_config(struct intel_crtc_state 
*crtc_state)
 TRANS_VRR_VMAX(dev_priv, 
cpu_transcoder)) + 1;
crtc_state->vrr.vmin = intel_de_read(dev_priv,
 TRANS_VRR_VMIN(dev_priv, 
cpu_transcoder)) + 1;
+
+   if (crtc_state->vrr.vmax == crtc_state->vrr.flipline &&
+   crtc_state->vrr.vmin == crtc_state->vrr.flipline)
+   crtc_state->vrr.fixed_rr = true;
}
 
if (crtc_state->vrr.enable) {
-- 
2.45.2



[PATCH 08/10] drm/i915/vrr: Avoid sending PUSH when VRR TG is used with Fixed refresh rate

2024-07-22 Thread Ankit Nautiyal
As per Bspec:68925: Push enable must be set if not configuring for a
fixed refresh rate (i.e Vmin == Flipline == Vmax is not true).

Signed-off-by: Ankit Nautiyal 
Reviewed-by: Mitul Golani 
---
 drivers/gpu/drm/i915/display/intel_vrr.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c 
b/drivers/gpu/drm/i915/display/intel_vrr.c
index 5a80a8eae087..e60a8833bd7b 100644
--- a/drivers/gpu/drm/i915/display/intel_vrr.c
+++ b/drivers/gpu/drm/i915/display/intel_vrr.c
@@ -316,7 +316,7 @@ void intel_vrr_send_push(const struct intel_crtc_state 
*crtc_state)
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
 
-   if (!crtc_state->vrr.enable)
+   if (!crtc_state->vrr.enable || crtc_state->vrr.fixed_rr)
return;
 
intel_de_write(dev_priv, TRANS_PUSH(dev_priv, cpu_transcoder),
@@ -329,7 +329,7 @@ bool intel_vrr_is_push_sent(const struct intel_crtc_state 
*crtc_state)
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
 
-   if (!crtc_state->vrr.enable)
+   if (!crtc_state->vrr.enable || crtc_state->vrr.fixed_rr)
return false;
 
return intel_de_read(dev_priv, TRANS_PUSH(dev_priv, cpu_transcoder)) & 
TRANS_PUSH_SEND;
@@ -343,8 +343,9 @@ void intel_vrr_enable(const struct intel_crtc_state 
*crtc_state)
if (!crtc_state->vrr.enable)
return;
 
-   intel_de_write(dev_priv, TRANS_PUSH(dev_priv, cpu_transcoder),
-  TRANS_PUSH_EN);
+   if (!crtc_state->vrr.fixed_rr)
+   intel_de_write(dev_priv, TRANS_PUSH(dev_priv, cpu_transcoder),
+  TRANS_PUSH_EN);
 
if (HAS_AS_SDP(dev_priv))
intel_de_write(dev_priv,
-- 
2.45.2



[PATCH 09/10] drm/i915/vrr: Handle joiner with vrr

2024-07-22 Thread Ankit Nautiyal
Do not program transcoder registers for VRR for the secondary pipe of
the joiner. Remove check to skip VRR for joiner case.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_vrr.c | 19 ---
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c 
b/drivers/gpu/drm/i915/display/intel_vrr.c
index e60a8833bd7b..50ac2770a42d 100644
--- a/drivers/gpu/drm/i915/display/intel_vrr.c
+++ b/drivers/gpu/drm/i915/display/intel_vrr.c
@@ -171,13 +171,6 @@ intel_vrr_compute_config(struct intel_crtc_state 
*crtc_state,
const struct drm_display_info *info = >base.display_info;
int vmin, vmax;
 
-   /*
-* FIXME all joined pipes share the same transcoder.
-* Need to account for that during VRR toggle/push/etc.
-*/
-   if (crtc_state->joiner_pipes)
-   return;
-
if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
return;
 
@@ -274,6 +267,9 @@ void intel_vrr_set_transcoder_timings(const struct 
intel_crtc_state *crtc_state)
struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
 
+   if (intel_crtc_is_joiner_secondary(crtc_state))
+   return;
+
/*
 * This bit seems to have two meanings depending on the platform:
 * TGL: generate VRR "safe window" for DSB vblank waits
@@ -316,6 +312,9 @@ void intel_vrr_send_push(const struct intel_crtc_state 
*crtc_state)
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
 
+   if (intel_crtc_is_joiner_secondary(crtc_state))
+   return;
+
if (!crtc_state->vrr.enable || crtc_state->vrr.fixed_rr)
return;
 
@@ -340,6 +339,9 @@ void intel_vrr_enable(const struct intel_crtc_state 
*crtc_state)
struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
 
+   if (intel_crtc_is_joiner_secondary(crtc_state))
+   return;
+
if (!crtc_state->vrr.enable)
return;
 
@@ -369,6 +371,9 @@ void intel_vrr_disable(const struct intel_crtc_state 
*old_crtc_state)
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder;
 
+   if (intel_crtc_is_joiner_secondary(old_crtc_state))
+   return;
+
if (!old_crtc_state->vrr.enable)
return;
 
-- 
2.45.2



[PATCH 05/10] drm/i915/hdmi: Use VRR Timing generator for HDMI

2024-07-22 Thread Ankit Nautiyal
Add support for using VRR Timing generator for HDMI panels.

Signed-off-by: Ankit Nautiyal 
Reviewed-by: Mitul Golani 
---
 drivers/gpu/drm/i915/display/intel_hdmi.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c 
b/drivers/gpu/drm/i915/display/intel_hdmi.c
index 19498ee455fa..c8442772bacf 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -59,6 +59,7 @@
 #include "intel_lspcon.h"
 #include "intel_panel.h"
 #include "intel_snps_phy.h"
+#include "intel_vrr.h"
 
 inline struct drm_i915_private *intel_hdmi_to_i915(struct intel_hdmi 
*intel_hdmi)
 {
@@ -2366,6 +2367,8 @@ int intel_hdmi_compute_config(struct intel_encoder 
*encoder,
}
}
 
+   intel_vrr_compute_config(pipe_config, conn_state);
+
intel_hdmi_compute_gcp_infoframe(encoder, pipe_config,
 conn_state);
 
-- 
2.45.2



[PATCH 04/10] drm/i915/vrr: Compute vrr vsync if platforms support it

2024-07-22 Thread Ankit Nautiyal
Previously, TRANS_VRR_VSYNC was exclusively used for panels with
adaptive-sync SDP support in VRR scenarios. However, to drive fixed refresh
rates using the VRR Timing generator, we now need to program
TRANS_VRR_VSYNC regardless of adaptive sync SDP support. Therefore, let's
remove the adaptive sync SDP check and program TRANS_VRR_VSYNC for
platforms where VRR timing generator is used.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_vrr.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c 
b/drivers/gpu/drm/i915/display/intel_vrr.c
index 7e1d9c718214..5a80a8eae087 100644
--- a/drivers/gpu/drm/i915/display/intel_vrr.c
+++ b/drivers/gpu/drm/i915/display/intel_vrr.c
@@ -233,7 +233,7 @@ intel_vrr_compute_config(struct intel_crtc_state 
*crtc_state,
crtc_state->mode_flags |= I915_MODE_FLAG_VRR;
}
 
-   if (intel_dp->as_sdp_supported && crtc_state->vrr.enable) {
+   if (HAS_AS_SDP(i915) && crtc_state->vrr.enable) {
crtc_state->vrr.vsync_start =
(crtc_state->hw.adjusted_mode.crtc_vtotal -
 crtc_state->hw.adjusted_mode.vsync_start);
-- 
2.45.2



[PATCH 03/10] drm/i915/dp: Set FAVT mode in DP SDP with fixed refresh rate

2024-07-22 Thread Ankit Nautiyal
While running with fixed refresh rate and VRR timing generator set FAVT
mode (Fixed Vtotal) in DP Adaptive Sync SDP to intimate the panel
about Fixed refresh rate.

Signed-off-by: Ankit Nautiyal 
Reviewed-by: Mitul Golani 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 59fc72b533de..9c632f569f62 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2633,6 +2633,10 @@ static void intel_dp_compute_as_sdp(struct intel_dp 
*intel_dp,
as_sdp->target_rr = drm_mode_vrefresh(adjusted_mode);
as_sdp->target_rr_divider = true;
} else {
+   if (crtc_state->vrr.fixed_rr)
+   as_sdp->mode = DP_AS_SDP_AVT_FIXED_VTOTAL;
+   else
+   as_sdp->mode = DP_AS_SDP_AVT_DYNAMIC_VTOTAL;
as_sdp->mode = DP_AS_SDP_AVT_DYNAMIC_VTOTAL;
as_sdp->vtotal = adjusted_mode->vtotal;
as_sdp->target_rr = 0;
-- 
2.45.2



[PATCH 02/10] drm/i915/display: Add member fixed_rr to denote Fixed refresh rate with VRRTG

2024-07-22 Thread Ankit Nautiyal
Add fixed_rr member to struct vrr to represent the case where a
fixed refresh rate with VRR timing generator is required.

v2: Move get_config change where vrr.fixed is actually set. (Mitul)

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_display.c   | 4 +++-
 drivers/gpu/drm/i915/display/intel_display_types.h | 2 +-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 01a5faa3fea5..ecfd77c0b741 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -1004,7 +1004,8 @@ static bool vrr_params_changed(const struct 
intel_crtc_state *old_crtc_state,
old_crtc_state->vrr.vmin != new_crtc_state->vrr.vmin ||
old_crtc_state->vrr.vmax != new_crtc_state->vrr.vmax ||
old_crtc_state->vrr.guardband != new_crtc_state->vrr.guardband 
||
-   old_crtc_state->vrr.pipeline_full != 
new_crtc_state->vrr.pipeline_full;
+   old_crtc_state->vrr.pipeline_full != 
new_crtc_state->vrr.pipeline_full ||
+   old_crtc_state->vrr.fixed_rr != new_crtc_state->vrr.fixed_rr;
 }
 
 static bool cmrr_params_changed(const struct intel_crtc_state *old_crtc_state,
@@ -5479,6 +5480,7 @@ intel_pipe_config_compare(const struct intel_crtc_state 
*current_config,
 
if (!fastset) {
PIPE_CONF_CHECK_BOOL(vrr.enable);
+   PIPE_CONF_CHECK_BOOL(vrr.fixed_rr);
PIPE_CONF_CHECK_I(vrr.vmin);
PIPE_CONF_CHECK_I(vrr.vmax);
PIPE_CONF_CHECK_I(vrr.flipline);
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index a9d2acdc51a4..4c0a18143c23 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1407,7 +1407,7 @@ struct intel_crtc_state {
 
/* Variable Refresh Rate state */
struct {
-   bool enable, in_range;
+   bool enable, in_range, fixed_rr;
u8 pipeline_full;
u16 flipline, vmin, vmax, guardband;
u32 vsync_end, vsync_start;
-- 
2.45.2



[PATCH 01/10] drm/i915/dp: fix the Adaptive sync Operation mode for SDP

2024-07-22 Thread Ankit Nautiyal
Currently we support Adaptive sync operation mode with dynamic frame
rate, but instead the operation mode with fixed rate is set.
This was initially set correctly in the earlier version of changes but
later got changed, while defining a macro for the same.

Fixes: a5bd5991cb8a ("drm/i915/display: Compute AS SDP parameters")
Cc: Mitul Golani 
Cc: Ankit Nautiyal 
Cc: Jani Nikula 
Reviewed-by: Mitul Golani 
Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index d4b1b18453dc..59fc72b533de 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2622,7 +2622,6 @@ static void intel_dp_compute_as_sdp(struct intel_dp 
*intel_dp,
 
crtc_state->infoframes.enable |= 
intel_hdmi_infoframe_enable(DP_SDP_ADAPTIVE_SYNC);
 
-   /* Currently only DP_AS_SDP_AVT_FIXED_VTOTAL mode supported */
as_sdp->sdp_type = DP_SDP_ADAPTIVE_SYNC;
as_sdp->length = 0x9;
as_sdp->duration_incr_ms = 0;
@@ -2634,7 +2633,7 @@ static void intel_dp_compute_as_sdp(struct intel_dp 
*intel_dp,
as_sdp->target_rr = drm_mode_vrefresh(adjusted_mode);
as_sdp->target_rr_divider = true;
} else {
-   as_sdp->mode = DP_AS_SDP_AVT_FIXED_VTOTAL;
+   as_sdp->mode = DP_AS_SDP_AVT_DYNAMIC_VTOTAL;
as_sdp->vtotal = adjusted_mode->vtotal;
as_sdp->target_rr = 0;
}
-- 
2.45.2



[PATCH 00/10] Use VRR timing generator for fixed refresh rate modes

2024-07-22 Thread Ankit Nautiyal
Even though the VRR timing generator (TG) is primarily used for
variable refresh rates, it can be used for fixed refresh rates as
well. For a fixed refresh rate the Flip Line and Vmax must be equal
(TRANS_VRR_FLIPLINE = TRANS_VRR_VMAX). Beyond that, there are some
dependencies between the VRR timings and the legacy timing generator
registers.

This series is an attempt to use VRR TG for fixed refresh rate.
For platforms XELPD+, always go with VRR timing generator for both fixed and
variable refresh rate cases.

Rev2:
-Added support from MTL+ and for HDMI too.
-Changed VRR VSYNC programming which is required for HDMI.
-Modified vrr compute config for bigjoiner case. (Still to be tested).

Rev3:
-Start support from XELPD+ as MTL needs a WA to have PSR +VRR (fixed
refresh rate)
-Add changes to enable PSR with VRR with fixed refresh rate.

Rev4:
-Addressed review comments from Mitul and rebased.

Ankit Nautiyal (10):
  drm/i915/dp: fix the Adaptive sync Operation mode for SDP
  drm/i915/display: Add member fixed_rr to denote Fixed refresh rate
with VRRTG
  drm/i915/dp: Set FAVT mode in DP SDP with fixed refresh rate
  drm/i915/vrr: Compute vrr vsync if platforms support it
  drm/i915/hdmi: Use VRR Timing generator for HDMI
  drm/i915/display: Disable PSR before disabling VRR
  drm/i915/psr: Allow PSR for fixed refrsh rate with VRR TG
  drm/i915/vrr: Avoid sending PUSH when VRR TG is used with Fixed
refresh rate
  drm/i915/vrr: Handle joiner with vrr
  drm/i915/vrr: Always use VRR timing generator for XELPD+

 drivers/gpu/drm/i915/display/intel_display.c  |  8 +-
 .../drm/i915/display/intel_display_types.h|  2 +-
 drivers/gpu/drm/i915/display/intel_dp.c   |  7 +-
 drivers/gpu/drm/i915/display/intel_hdmi.c |  3 +
 drivers/gpu/drm/i915/display/intel_psr.c  |  2 +-
 drivers/gpu/drm/i915/display/intel_vrr.c  | 93 ---
 6 files changed, 74 insertions(+), 41 deletions(-)

-- 
2.45.2



[PATCH 10/12] drm/i915: Compute config and mode valid changes for ultrajoiner

2024-07-18 Thread Ankit Nautiyal
From: Stanislav Lisovskiy 

Implement required changes for mode validation and compute config,
to support Ultrajoiner.
This also includes required DSC changes and checks.

v2:
-Use enum for Ultrajoiner pipes.
-Drop changes for HDMI.
-Separate out DSC changes into another patch.

Signed-off-by: Stanislav Lisovskiy 
Signed-off-by: Ankit Nautiyal 
---
 .../drm/i915/display/intel_display_types.h|  1 +
 drivers/gpu/drm/i915/display/intel_dp.c   | 70 +++
 drivers/gpu/drm/i915/display/intel_dp.h   |  7 +-
 drivers/gpu/drm/i915/display/intel_dp_mst.c   | 15 ++--
 4 files changed, 70 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index 14c78b18ffa1..a36881b047e3 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -616,6 +616,7 @@ struct intel_hdcp {
 enum intel_joiner_pipe_count {
INTEL_PIPE_JOINER_NONE = 0,
INTEL_PIPE_JOINER_BIG = 2,
+   INTEL_PIPE_JOINER_ULTRA = 4,
INTEL_PIPE_JOINER_INVALID,
 };
 
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index ff4c123de0ed..c0a1f2603274 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -755,24 +755,33 @@ u32 get_max_compressed_bpp_with_joiner(struct 
drm_i915_private *i915,
   enum intel_joiner_pipe_count 
joined_pipes)
 {
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;
 
-   if (joined_pipes == INTEL_PIPE_JOINER_BIG) {
-   int bigjoiner_interface_bits = DISPLAY_VER(i915) >= 14 ? 36 : 
24;
+   /* if ultra joiner is enabled, we have 2 bigjoiners enabled */
+   if (joined_pipes == INTEL_PIPE_JOINER_BIG ||
+   joined_pipes == INTEL_PIPE_JOINER_ULTRA) {
+   int joiner_interface_bits = DISPLAY_VER(i915) >= 14 ? 36 : 24;
/* With bigjoiner 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);
+   return min(max_bpp_small_joiner_ram, max_bpp_joiner);
+   }
+   if (joined_pipes == INTEL_PIPE_JOINER_ULTRA) {
+   /* 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,
@@ -878,6 +887,10 @@ u8 intel_dp_dsc_get_slice_count(const struct 
intel_connector *connector,
if (joined_pipes == INTEL_PIPE_JOINER_BIG && test_slice_count < 
4)
continue;
 
+   /* ultrajoiner needs 2 bigjoiners to be enabled */
+   if (joined_pipes == INTEL_PIPE_JOINER_ULTRA && test_slice_count 
< 8)
+   continue;
+
if (min_slice_count <= test_slice_count)
return test_slice_count;
}
@@ -1154,9 +1167,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);
 
@@ -1187,6 +1200,25 @@ 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 = _to_dig_port(dp)->base;
+   struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+   if (!intel_can_ultrajoiner(encoder))
+   return false;
+

[PATCH 12/12] drm/i915/intel_dp: Add support for forcing ultrajoiner

2024-07-18 Thread Ankit Nautiyal
Allow forcing ultrajoiner through debugfs.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 11 +++
 drivers/gpu/drm/i915/display/intel_dp.h |  4 +++-
 drivers/gpu/drm/i915/display/intel_dp_mst.c |  6 --
 3 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index c0a1f2603274..da6d8acf710a 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1208,7 +1208,9 @@ bool intel_can_ultrajoiner(const struct intel_encoder 
*encoder)
return IS_DGFX(i915) && DISPLAY_VER(i915) >= 14;
 }
 
-bool intel_dp_need_ultrajoiner(struct intel_dp *dp, int clock)
+bool intel_dp_need_ultrajoiner(struct intel_dp *dp,
+  struct intel_connector *connector,
+  int clock)
 {
const struct intel_encoder *encoder = _to_dig_port(dp)->base;
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
@@ -1216,7 +1218,8 @@ bool intel_dp_need_ultrajoiner(struct intel_dp *dp, int 
clock)
if (!intel_can_ultrajoiner(encoder))
return false;
 
-   return clock > (i915->display.cdclk.max_dotclk_freq * 2);
+   return clock > (i915->display.cdclk.max_dotclk_freq * 2) ||
+  connector->force_joined_pipes == INTEL_PIPE_JOINER_ULTRA;
 }
 
 static enum drm_mode_status
@@ -1255,7 +1258,7 @@ intel_dp_mode_valid(struct drm_connector *_connector,
target_clock = fixed_mode->clock;
}
 
-   if (intel_dp_need_ultrajoiner(intel_dp, target_clock)) {
+   if (intel_dp_need_ultrajoiner(intel_dp, connector, target_clock)) {
joined_pipes = INTEL_PIPE_JOINER_ULTRA;
max_dotclk *= INTEL_PIPE_JOINER_ULTRA;
} else if (intel_dp_need_bigjoiner(intel_dp, connector,
@@ -2465,7 +2468,7 @@ intel_dp_compute_link_config(struct intel_encoder 
*encoder,
!intel_dp_supports_fec(intel_dp, connector, pipe_config))
return -EINVAL;
 
-   if (intel_dp_need_ultrajoiner(intel_dp, adjusted_mode->crtc_clock))
+   if (intel_dp_need_ultrajoiner(intel_dp, connector, 
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,
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h 
b/drivers/gpu/drm/i915/display/intel_dp.h
index 6c607a218fbc..b23db3eb477a 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -156,7 +156,9 @@ u8 intel_dp_dsc_get_slice_count(const struct 
intel_connector *connector,
 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_dp_need_ultrajoiner(struct intel_dp *intel_dp,
+  struct intel_connector *connector,
+  int clock);
 
 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 d4fc4439ce2b..b4351d37b963 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -579,7 +579,8 @@ 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_ultrajoiner(intel_dp, adjusted_mode->crtc_clock))
+   if (intel_dp_need_ultrajoiner(intel_dp, connector,
+ 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,
@@ -1444,7 +1445,8 @@ 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_ultrajoiner(intel_dp, target_clock)) {
+   if (intel_dp_need_ultrajoiner(intel_dp, intel_connector,
+ target_clock)) {
joined_pipes = INTEL_PIPE_JOINER_BIG;
max_dotclk *= INTEL_PIPE_JOINER_BIG;
} else if (intel_dp_need_bigjoiner(intel_dp, intel_connector,
-- 
2.45.2



[PATCH 11/12] drm/i915: Add new abstraction layer to handle pipe order for different joiners

2024-07-18 Thread Ankit Nautiyal
From: Stanislav Lisovskiy 

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.

v2: Fix checkpatch warnings. (Ankit)

Signed-off-by: Stanislav Lisovskiy 
Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_ddi.c | 19 +++--
 drivers/gpu/drm/i915/display/intel_display.c | 89 
 drivers/gpu/drm/i915/display/intel_display.h |  7 ++
 drivers/gpu/drm/i915/display/intel_dp_mst.c  | 19 +++--
 4 files changed, 102 insertions(+), 32 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
b/drivers/gpu/drm/i915/display/intel_ddi.c
index a07aca96e551..d54c9e51209e 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -3116,10 +3116,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(_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);
 
@@ -3130,8 +3131,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(_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);
 
@@ -3383,7 +3385,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);
 
@@ -3394,8 +3396,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(>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 d032fd8011d5..b6896058a594 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -1730,6 +1730,56 @@ static void hsw_configure_cpu_transcoder(const struct 
intel_crtc_state *crtc_sta
hsw_set_transconf(crtc_state);
 }
 
+static
+bool intel_is_bigjoiner(const struct intel_crtc_state *pipe_config)
+{
+   return hweight8(pipe_config->joiner_pipes) == 2;
+}
+
+static
+bool intel_is_ultrajoiner(const struct intel_crtc_state *pipe_config)
+{
+   return hweight8(pipe_config->joiner_pipes) == 4;
+}
+
+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] = {
+  

[PATCH 09/12] drm/i915/display/vdsc: Add ultrajoiner support with DSC

2024-07-18 Thread Ankit Nautiyal
From: Stanislav Lisovskiy 

Add changes to DSC which are required for Ultrajoiner.

Signed-off-by: Stanislav Lisovskiy 
Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_vdsc.c | 26 +--
 1 file changed, 24 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c 
b/drivers/gpu/drm/i915/display/intel_vdsc.c
index 11058bb37d5a..815fbffc2d97 100644
--- a/drivers/gpu/drm/i915/display/intel_vdsc.c
+++ b/drivers/gpu/drm/i915/display/intel_vdsc.c
@@ -378,8 +378,11 @@ static int intel_dsc_get_vdsc_per_pipe(const struct 
intel_crtc_state *crtc_state
 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);
+   int joined_pipes = intel_joiner_num_pipes(crtc_state);
 
-   if (crtc_state->joiner_pipes)
+   if (joined_pipes == 4)
+   num_vdsc_instances *= 4;
+   else if (joined_pipes == 2)
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_joiner_num_pipes(crtc_state) == 4 && 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);
@@ -789,8 +799,20 @@ void intel_dsc_enable(const struct intel_crtc_state 
*crtc_state)
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))
+
+   if (!intel_crtc_is_joiner_secondary(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.45.2



[PATCH 08/12] drm/i915: Implement hw state readout and checks for ultrajoiner

2024-07-18 Thread Ankit Nautiyal
From: Stanislav Lisovskiy 

Ultrajoiner mode has some new bits and states to be
read out from the hw. Lets make changes accordingly.

v2: Fix checkpatch warnings. (Ankit)

Signed-off-by: Stanislav Lisovskiy 
Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_display.c  | 127 ++
 .../gpu/drm/i915/display/intel_vdsc_regs.h|   3 +
 2 files changed, 101 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 59cb0d2f773b..d032fd8011d5 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -3648,17 +3648,55 @@ static void enabled_bigjoiner_pipes(struct 
drm_i915_private *dev_priv,
}
 }
 
-static u8 expected_secondary_pipes(u8 primary_pipes)
+static void enabled_ultrajoiner_pipes(struct drm_i915_private *i915,
+ u8 *primary_pipes, u8 *secondary_pipes)
 {
-   return primary_pipes << 1;
+   struct intel_crtc *crtc;
+
+   *primary_pipes = 0;
+   *secondary_pipes = 0;
+
+   if (DISPLAY_VER(i915) < 14)
+   return;
+
+   for_each_intel_crtc_in_pipe_mask(>drm, crtc,
+joiner_pipes(i915)) {
+   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(i915, power_domain, 
wakeref) {
+   u32 tmp = intel_de_read(i915, ICL_PIPE_DSS_CTL1(pipe));
+
+   if (!(tmp & ULTRA_JOINER_ENABLE))
+   continue;
+
+   if (tmp & PRIMARY_ULTRA_JOINER_ENABLE)
+   *primary_pipes |= BIT(pipe);
+   else
+   *secondary_pipes |= BIT(pipe);
+   }
+   }
+}
+
+static u8 expected_secondary_pipes(u8 primary_pipes, bool ultrajoiner_used)
+{
+   if (!ultrajoiner_used)
+   return primary_pipes << 1;
+   else
+   return GENMASK(3, primary_pipes + 1);
 }
 
 static void enabled_joiner_pipes(struct drm_i915_private *dev_priv,
-u8 *primary_pipes, u8 *secondary_pipes)
+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 uncompressed_joiner_pipes, bigjoiner_pipes;
+   u8 secondary_ultrajoiner_pipes;
+   u8 uncompressed_joiner_pipes, bigjoiner_pipes, ultrajoiner_pipes;
 
enabled_uncompressed_joiner_pipes(dev_priv, 
_uncompressed_joiner_pipes,
  _uncompressed_joiner_pipes);
@@ -3666,32 +3704,49 @@ static void enabled_joiner_pipes(struct 
drm_i915_private *dev_priv,
enabled_bigjoiner_pipes(dev_priv, _bigjoiner_pipes,
_bigjoiner_pipes);
 
+   enabled_ultrajoiner_pipes(dev_priv, _ultrajoiner_pipes,
+ _ultrajoiner_pipes);
+
uncompressed_joiner_pipes = primary_uncompressed_joiner_pipes |
secondary_uncompressed_joiner_pipes;
bigjoiner_pipes = primary_bigjoiner_pipes | secondary_bigjoiner_pipes;
+   ultrajoiner_pipes = primary_ultrajoiner_pipes | 
secondary_ultrajoiner_pipes;
+   *ultrajoiner_used = ultrajoiner_pipes != 0;
 
drm_WARN(_priv->drm, (uncompressed_joiner_pipes & bigjoiner_pipes) 
!= 0,
 "Uncomressed joiner pipes(%x) and bigjoiner pipes(%x) can't 
intersect\n",
 uncompressed_joiner_pipes, bigjoiner_pipes);
+   drm_WARN(_priv->drm, (ultrajoiner_pipes & bigjoiner_pipes) != 
ultrajoiner_pipes,
+"Ultrajoiner pipes(%x) should be bigjoiner pipes(%x)\n",
+ultrajoiner_pipes, bigjoiner_pipes);
+
drm_WARN(_priv->drm, secondary_bigjoiner_pipes !=
-expected_secondary_pipes(primary_bigjoiner_pipes),
+expected_secondary_pipes(primary_bigjoiner_pipes, 
*ultrajoiner_used),
 "Wrong secondary bigjoiner pipes(expected %x, current %x)\n",
-expected_secondary_pipes(primary_bigjoiner_pipes),
+expected_secondary_pipes(primary_bigjoiner_pipes, 
*ultrajoiner_used),
 secondary_bigjoiner_pipes);
drm_WARN(_priv->drm, secondary_uncompressed_joiner_pipes !=
-expected_secondary_pipes(primary_uncompressed_joiner_pipes),
+expected_secondary_pipes(primary_uncompressed_joiner_pi

[PATCH 03/12] drm/i915/display: Use joined pipes in intel_mode_valid_max_plane_size

2024-07-18 Thread Ankit Nautiyal
In preparation of ultrajoiner, use number of joined pipes in the
intel_mode_valid_max_plane_size helper, instead of joiner flag.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_display.c | 4 ++--
 drivers/gpu/drm/i915/display/intel_display.h | 3 ++-
 drivers/gpu/drm/i915/display/intel_dp.c  | 2 +-
 drivers/gpu/drm/i915/display/intel_dp_mst.c  | 2 +-
 drivers/gpu/drm/i915/display/intel_dsi.c | 2 +-
 drivers/gpu/drm/i915/display/intel_hdmi.c| 2 +-
 6 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index eab07a5fa377..26e4b0c2e9f7 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -8081,7 +8081,7 @@ 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)
+   enum intel_joiner_pipe_count joined_pipes)
 {
int plane_width_max, plane_height_max;
 
@@ -8098,7 +8098,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 << joined_pipes / 2;
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 0aecc3330a53..bf665f947b97 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -31,6 +31,7 @@
 #include "intel_display_limits.h"
 
 enum drm_scaling_filter;
+enum intel_joiner_pipe_count;
 struct dpll;
 struct drm_atomic_state;
 struct drm_connector;
@@ -415,7 +416,7 @@ 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);
+   enum intel_joiner_pipe_count joined_pipes);
 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 7d66a969c461..320d8b6d1bce 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1295,7 +1295,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, joined_pipes);
 }
 
 bool intel_dp_source_supports_tps3(struct drm_i915_private *i915)
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c 
b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index e5797ee13667..3f45ac7ca4d5 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -1491,7 +1491,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, joined_pipes);
return 0;
 }
 
diff --git a/drivers/gpu/drm/i915/display/intel_dsi.c 
b/drivers/gpu/drm/i915/display/intel_dsi.c
index bd5888ce4852..acc17546215f 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, 
INTEL_PIPE_JOINER_NONE);
 }
 
 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..5aa4a9f0c470 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, 
INTEL_PIPE_JOINER_NONE);
 }
 
 bool intel_hdmi_bpc_possible(const struct intel_crtc_state *crtc_state,
-- 
2.45.2



[PATCH 02/12] drm/i915/display: Use joined pipes in intel_dp_joiner_needs_dsc

2024-07-18 Thread Ankit Nautiyal
In preparation of ultrajoiner, use number of joined pipes in the
intel_dp_joiner_needs_dsc helper, instead of joiner flag.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_display.c |  2 +-
 drivers/gpu/drm/i915/display/intel_display.h |  2 ++
 drivers/gpu/drm/i915/display/intel_dp.c  | 18 +-
 drivers/gpu/drm/i915/display/intel_dp.h  |  4 +++-
 drivers/gpu/drm/i915/display/intel_dp_mst.c  | 13 ++---
 5 files changed, 29 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 01a5faa3fea5..eab07a5fa377 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -276,7 +276,7 @@ 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)
+int intel_joiner_num_pipes(const struct intel_crtc_state *crtc_state)
 {
return hweight8(crtc_state->joiner_pipes);
 }
diff --git a/drivers/gpu/drm/i915/display/intel_display.h 
b/drivers/gpu/drm/i915/display/intel_display.h
index b0cf6ca70952..0aecc3330a53 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -584,4 +584,6 @@ bool assert_port_valid(struct drm_i915_private *i915, enum 
port port);
 
 bool intel_scanout_needs_vtd_wa(struct drm_i915_private *i915);
 
+int intel_joiner_num_pipes(const struct intel_crtc_state *crtc_state);
+
 #endif
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 30442c9da06b..7d66a969c461 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1202,6 +1202,7 @@ intel_dp_mode_valid(struct drm_connector *_connector,
u8 dsc_slice_count = 0;
enum drm_mode_status status;
bool dsc = false, joiner = false;
+   enum intel_joiner_pipe_count joined_pipes = INTEL_PIPE_JOINER_NONE;
 
status = intel_cpu_transcoder_mode_valid(dev_priv, mode);
if (status != MODE_OK)
@@ -1225,7 +1226,8 @@ intel_dp_mode_valid(struct drm_connector *_connector,
if (intel_dp_need_joiner(intel_dp, connector,
 mode->hdisplay, target_clock)) {
joiner = true;
-   max_dotclk *= 2;
+   joined_pipes = INTEL_PIPE_JOINER_BIG;
+   max_dotclk *= INTEL_PIPE_JOINER_BIG;
}
if (target_clock > max_dotclk)
return MODE_CLOCK_HIGH;
@@ -1283,7 +1285,7 @@ intel_dp_mode_valid(struct drm_connector *_connector,
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, joined_pipes) && !dsc)
return MODE_CLOCK_HIGH;
 
if (mode_rate > max_rate && !dsc)
@@ -2391,14 +2393,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,
+  enum intel_joiner_pipe_count joined_pipes)
 {
/*
 * Pipe joiner needs compression up to display 12 due to bandwidth
 * limitation. DG2 onwards pipe joiner can be enabled without
 * compression.
 */
-   return DISPLAY_VER(i915) < 13 && use_joiner;
+   return DISPLAY_VER(i915) < 13 && (joined_pipes == 
INTEL_PIPE_JOINER_BIG);
 }
 
 static int
@@ -2416,6 +2419,7 @@ 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;
+   enum intel_joiner_pipe_count joined_pipes;
int ret = 0;
 
if (pipe_config->fec_enable &&
@@ -2427,7 +2431,11 @@ intel_dp_compute_link_config(struct intel_encoder 
*encoder,
 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);
+   joined_pipes = intel_joiner_num_pipes(pipe_config);
+   if (joined_pipes >= INTEL_PIPE_JOINER_INVALID)
+   drm_warn(>drm, "Invalid joined pipes : %d\n", 
joined_pipes);
+
+   joiner_needs_dsc = intel_dp_joiner_needs_dsc(i915, joined_pipes);
 
dsc_needed = joiner_needs_dsc || intel_dp->force_dsc_en ||
 !intel_dp_compute_config_limits(intel_dp, pipe_config,
diff --git a/drive

[PATCH 07/12] drm/i915: Add bigjoiner and uncompressed joiner hw readout sanity checks

2024-07-18 Thread Ankit Nautiyal
From: Stanislav Lisovskiy 

Adding sanity checks for primary and secondary bigjoiner/uncompressed
bitmasks, should make it easier to spot possible issues.

Signed-off-by: Stanislav Lisovskiy 
---
 drivers/gpu/drm/i915/display/intel_display.c | 25 +++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 4aed8117f614..59cb0d2f773b 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -3648,11 +3648,17 @@ static void enabled_bigjoiner_pipes(struct 
drm_i915_private *dev_priv,
}
 }
 
+static u8 expected_secondary_pipes(u8 primary_pipes)
+{
+   return primary_pipes << 1;
+}
+
 static void enabled_joiner_pipes(struct drm_i915_private *dev_priv,
 u8 *primary_pipes, u8 *secondary_pipes)
 {
u8 primary_uncompressed_joiner_pipes, primary_bigjoiner_pipes;
u8 secondary_uncompressed_joiner_pipes, secondary_bigjoiner_pipes;
+   u8 uncompressed_joiner_pipes, bigjoiner_pipes;
 
enabled_uncompressed_joiner_pipes(dev_priv, 
_uncompressed_joiner_pipes,
  _uncompressed_joiner_pipes);
@@ -3660,11 +3666,28 @@ static void enabled_joiner_pipes(struct 
drm_i915_private *dev_priv,
enabled_bigjoiner_pipes(dev_priv, _bigjoiner_pipes,
_bigjoiner_pipes);
 
+   uncompressed_joiner_pipes = primary_uncompressed_joiner_pipes |
+   secondary_uncompressed_joiner_pipes;
+   bigjoiner_pipes = primary_bigjoiner_pipes | secondary_bigjoiner_pipes;
+
+   drm_WARN(_priv->drm, (uncompressed_joiner_pipes & bigjoiner_pipes) 
!= 0,
+"Uncomressed joiner pipes(%x) and bigjoiner pipes(%x) can't 
intersect\n",
+uncompressed_joiner_pipes, bigjoiner_pipes);
+   drm_WARN(_priv->drm, secondary_bigjoiner_pipes !=
+expected_secondary_pipes(primary_bigjoiner_pipes),
+"Wrong secondary bigjoiner pipes(expected %x, current %x)\n",
+expected_secondary_pipes(primary_bigjoiner_pipes),
+secondary_bigjoiner_pipes);
+   drm_WARN(_priv->drm, secondary_uncompressed_joiner_pipes !=
+expected_secondary_pipes(primary_uncompressed_joiner_pipes),
+"Wrong secondary uncompressed joiner pipes(expected %x, 
current %x)\n",
+expected_secondary_pipes(primary_uncompressed_joiner_pipes),
+secondary_uncompressed_joiner_pipes);
+
*primary_pipes = 0;
*secondary_pipes = 0;
 
*primary_pipes = primary_uncompressed_joiner_pipes | 
primary_bigjoiner_pipes;
-
*secondary_pipes = secondary_uncompressed_joiner_pipes | 
secondary_bigjoiner_pipes;
 }
 
-- 
2.45.2



[PATCH 06/12] drm/i915: Split current joiner hw state readout

2024-07-18 Thread Ankit Nautiyal
From: Stanislav Lisovskiy 

We need to add a new sanity checks and also do
some preparations for adding ultrajoiner hw state readout.
Lets first split reading of the uncompressed joiner and bigjoiner
bit masks into separate functions.

v2: Fixed checkpatch warnings (Ankit)

Signed-off-by: Stanislav Lisovskiy 
Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_display.c | 65 +++-
 1 file changed, 48 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 38e7c6811bf3..4aed8117f614 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -3590,51 +3590,82 @@ 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;
 
+   if (DISPLAY_VER(dev_priv) < 13)
+   return;
+
for_each_intel_crtc_in_pipe_mask(_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);
+   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 & BIG_JOINER_ENABLE))
-   continue;
-
-   if (tmp & PRIMARY_BIG_JOINER_ENABLE)
+   if (tmp & UNCOMPRESSED_JOINER_PRIMARY)
*primary_pipes |= BIT(pipe);
-   else
+   if (tmp & UNCOMPRESSED_JOINER_SECONDARY)
*secondary_pipes |= BIT(pipe);
}
+   }
+}
 
-   if (DISPLAY_VER(dev_priv) < 13)
-   continue;
+static void enabled_bigjoiner_pipes(struct drm_i915_private *dev_priv,
+   u8 *primary_pipes, u8 *secondary_pipes)
+{
+   struct intel_crtc *crtc;
 
-   power_domain = POWER_DOMAIN_PIPE(pipe);
+   *primary_pipes = 0;
+   *secondary_pipes = 0;
+
+   for_each_intel_crtc_in_pipe_mask(_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 & BIG_JOINER_ENABLE))
+   continue;
+
+   if (tmp & PRIMARY_BIG_JOINER_ENABLE)
*primary_pipes |= BIT(pipe);
-   if (tmp & UNCOMPRESSED_JOINER_SECONDARY)
+   else
*secondary_pipes |= BIT(pipe);
}
}
+}
+
+static void enabled_joiner_pipes(struct drm_i915_private *dev_priv,
+u8 *primary_pipes, u8 *secondary_pipes)
+{
+   u8 primary_uncompressed_joiner_pipes, primary_bigjoiner_pipes;
+   u8 secondary_uncompressed_joiner_pipes, secondary_bigjoiner_pipes;
+
+   enabled_uncompressed_joiner_pipes(dev_priv, 
_uncompressed_joiner_pipes,
+ _uncompressed_joiner_pipes);
+
+   enabled_bigjoiner_pipes(dev_priv, _bigjoiner_pipes,
+   _bigjoiner_pipes);
+
+   *primary_pipes = 0;
+   *secondary_pipes = 0;
+
+   *primary_pipes = primary_uncompressed_joiner_pipes | 
primary_bigjoiner_pipes;
 
-   /* Joiner pipes should always be consecutive primary and secondary */
-   drm_WARN(_priv->drm, *secondary_pipes != *primary_pipes << 1,
-"Joiner misconfigured (primary pipes 0x%x, secondary pipes 
0x%x)\n",
-*primary_pipes, *secondary_pipes);
+   *secondary_pipes = secondary_uncompressed_joiner_pipes | 
secondary_bigjoiner_pipes;
 }
 
 static enum pipe get_

[PATCH 00/12] Ultrajoiner basic functionality series

2024-07-18 Thread Ankit Nautiyal
This patch series attempts to implement basic support
for Ultrajoiner functionality.

Rev6:
-Upgrade the debugfs functionality to enable the joining of a
specified number of pipes.
-Modify the display helpers reliant on the pipe joiner mechanism
to use number of pipes joined, instead of joiner flag.
-Checkpatch fixes.

Ankit Nautiyal (5):
  drm/i915/display: Modify debugfs for joiner to force n pipes
  drm/i915/display: Use joined pipes in intel_dp_joiner_needs_dsc
  drm/i915/display: Use joined pipes in intel_mode_valid_max_plane_size
  drm/i915/display: Use joined pipes in dsc helpers for slices, bpp
  drm/i915/intel_dp: Add support for forcing ultrajoiner

Stanislav Lisovskiy (7):
  drm/i915: Add some essential functionality for joiners
  drm/i915: Split current joiner hw state readout
  drm/i915: Add bigjoiner and uncompressed joiner hw readout sanity
checks
  drm/i915: Implement hw state readout and checks for ultrajoiner
  drm/i915/display/vdsc: Add ultrajoiner support with DSC
  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  | 357 +++---
 drivers/gpu/drm/i915/display/intel_display.h  |  20 +-
 .../drm/i915/display/intel_display_debugfs.c  |  71 +++-
 .../drm/i915/display/intel_display_types.h|   9 +-
 drivers/gpu/drm/i915/display/intel_dp.c   | 118 --
 drivers/gpu/drm/i915/display/intel_dp.h   |  17 +-
 drivers/gpu/drm/i915/display/intel_dp_mst.c   |  62 +--
 drivers/gpu/drm/i915/display/intel_dsi.c  |   2 +-
 drivers/gpu/drm/i915/display/intel_hdmi.c |   2 +-
 .../drm/i915/display/intel_modeset_verify.c   |   2 +-
 drivers/gpu/drm/i915/display/intel_vdsc.c |  26 +-
 .../gpu/drm/i915/display/intel_vdsc_regs.h|   3 +
 14 files changed, 569 insertions(+), 141 deletions(-)

-- 
2.45.2



[PATCH 05/12] drm/i915: Add some essential functionality for joiners

2024-07-18 Thread Ankit Nautiyal
From: Stanislav Lisovskiy 

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.

v2: Fixed checkpatch warnings (Ankit)

Signed-off-by: Stanislav Lisovskiy 
Signed-off-by: Ankit Nautiyal 
---
 .../gpu/drm/i915/display/intel_atomic_plane.c |  2 +-
 drivers/gpu/drm/i915/display/intel_display.c  | 75 ---
 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, 76 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 e979786aa5cf..9862d0339e6a 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c
+++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c
@@ -724,7 +724,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 26e4b0c2e9f7..38e7c6811bf3 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -252,6 +252,68 @@ static enum pipe joiner_primary_pipe(const struct 
intel_crtc_state *crtc_state)
return ffs(crtc_state->joiner_pipes) - 1;
 }
 
+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)
@@ -276,11 +338,6 @@ bool intel_crtc_is_joiner_primary(const struct 
intel_crtc_state *crtc_state)
crtc->pipe == joiner_primary_pipe(crtc_state);
 }
 
-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);
@@ -288,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_

[PATCH 04/12] drm/i915/display: Use joined pipes in dsc helpers for slices, bpp

2024-07-18 Thread Ankit Nautiyal
In preparation of ultrajoiner, use number of joined pipes in the dsc
helpers to compute dsc slices and max compressed bpp, instead of using
the joiner flag.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 27 +++--
 drivers/gpu/drm/i915/display/intel_dp.h |  4 +--
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 11 +
 3 files changed, 22 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 320d8b6d1bce..ff4c123de0ed 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -752,14 +752,14 @@ 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)
+  enum intel_joiner_pipe_count 
joined_pipes)
 {
u32 max_bpp_small_joiner_ram;
 
/* Small Joiner Check: output bpp <= joiner RAM (bits) / Horiz. width */
max_bpp_small_joiner_ram = small_joiner_ram_size_bits(i915) / 
mode_hdisplay;
 
-   if (bigjoiner) {
+   if (joined_pipes == INTEL_PIPE_JOINER_BIG) {
int bigjoiner_interface_bits = DISPLAY_VER(i915) >= 14 ? 36 : 
24;
/* With bigjoiner multiple dsc engines are used in parallel so 
PPC is 2 */
int ppc = 2;
@@ -778,7 +778,7 @@ u32 get_max_compressed_bpp_with_joiner(struct 
drm_i915_private *i915,
 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,
+   enum intel_joiner_pipe_count 
joined_pipes,
enum intel_output_format output_format,
u32 pipe_bpp,
u32 timeslots)
@@ -824,7 +824,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, 
joined_pipes);
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);
@@ -834,7 +834,7 @@ 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)
+   enum intel_joiner_pipe_count joined_pipes)
 {
struct drm_i915_private *i915 = to_i915(connector->base.dev);
u8 min_slice_count, i;
@@ -868,14 +868,14 @@ 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] << (joined_pipes 
/ 2);
 
if (test_slice_count >
drm_dp_dsc_sink_max_slice_count(connector->dp.dsc_dpcd, 
false))
break;
 
/* big joiner needs small joiner to be enabled */
-   if (bigjoiner && test_slice_count < 4)
+   if (joined_pipes == INTEL_PIPE_JOINER_BIG && test_slice_count < 
4)
continue;
 
if (min_slice_count <= test_slice_count)
@@ -1201,7 +1201,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;
enum intel_joiner_pipe_count joined_pipes = INTEL_PIPE_JOINER_NONE;
 
status = intel_cpu_transcoder_mode_valid(dev_priv, mode);
@@ -1225,7 +1225,6 @@ intel_dp_mode_valid(struct drm_connector *_connector,
 
if (intel_dp_need_joiner(intel_dp, connector,
 mode->hdisplay, target_clock)) {
-   joiner = true;
joined_pipes = INTEL_PIPE_JOINER_BIG;
max_dotclk *= INTEL_PIPE_JOINER_BIG;
}
@@ -1272,14 +1271,14 @@ intel_dp_mode_valid(struct drm_connector *_connector,
   

[PATCH 01/12] drm/i915/display: Modify debugfs for joiner to force n pipes

2024-07-18 Thread Ankit Nautiyal
At the moment, the debugfs for joiner allows only to force enable/disable
pipe joiner for 2 pipes. Modify it to force join 'n' number of pipes.
This will help in case of ultra joiner where 4 pipes are joined.

Signed-off-by: Ankit Nautiyal 
---
 .../drm/i915/display/intel_display_debugfs.c  | 71 ++-
 .../drm/i915/display/intel_display_types.h|  8 ++-
 drivers/gpu/drm/i915/display/intel_dp.c   |  2 +-
 3 files changed, 77 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c 
b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
index 5cf9b4af9adf..18f3d83265ce 100644
--- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
+++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
@@ -1497,6 +1497,73 @@ static int intel_crtc_pipe_show(struct seq_file *m, void 
*unused)
 }
 DEFINE_SHOW_ATTRIBUTE(intel_crtc_pipe);
 
+static int i915_joiner_show(struct seq_file *m, void *data)
+{
+   struct intel_connector *connector = m->private;
+   struct drm_i915_private *i915 = to_i915(connector->base.dev);
+   int ret;
+
+   ret = 
drm_modeset_lock_single_interruptible(>drm.mode_config.connection_mutex);
+   if (ret)
+   return ret;
+
+   seq_printf(m, "Force_joined_pipes: %d\n", 
connector->force_joined_pipes);
+
+   drm_modeset_unlock(>drm.mode_config.connection_mutex);
+
+   return ret;
+}
+
+static ssize_t i915_joiner_write(struct file *file,
+const char __user *ubuf,
+size_t len, loff_t *offp)
+{
+   struct seq_file *m = file->private_data;
+   struct intel_connector *connector = m->private;
+   struct drm_i915_private *i915 = to_i915(connector->base.dev);
+   int force_join_pipes = 0;
+   int ret;
+
+   if (len == 0)
+   return 0;
+
+   drm_dbg(>drm,
+   "Copied %zu bytes from user to force joiner\n", len);
+
+   ret = kstrtoint_from_user(ubuf, len, 0, _join_pipes);
+   if (ret < 0)
+   return ret;
+
+   drm_dbg(>drm, "Got %d for force joining pipes\n", 
force_join_pipes);
+
+   if (force_join_pipes < INTEL_PIPE_JOINER_NONE ||
+   force_join_pipes >= INTEL_PIPE_JOINER_INVALID) {
+   drm_dbg(>drm, "Ignoring Invalid num of pipes %d for force 
joining\n",
+   force_join_pipes);
+   connector->force_joined_pipes = INTEL_PIPE_JOINER_NONE;
+   } else {
+   connector->force_joined_pipes = force_join_pipes;
+   }
+
+   *offp += len;
+
+   return len;
+}
+
+static int i915_joiner_open(struct inode *inode, struct file *file)
+{
+   return single_open(file, i915_joiner_show, inode->i_private);
+}
+
+static const struct file_operations i915_joiner_fops = {
+   .owner = THIS_MODULE,
+   .open = i915_joiner_open,
+   .read = seq_read,
+   .llseek = seq_lseek,
+   .release = single_release,
+   .write = i915_joiner_write
+};
+
 /**
  * intel_connector_debugfs_add - add i915 specific connector debugfs files
  * @connector: pointer to a registered intel_connector
@@ -1546,8 +1613,8 @@ void intel_connector_debugfs_add(struct intel_connector 
*connector)
if (DISPLAY_VER(i915) >= 11 &&
(connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
 connector_type == DRM_MODE_CONNECTOR_eDP)) {
-   debugfs_create_bool("i915_bigjoiner_force_enable", 0644, root,
-   >force_bigjoiner_enable);
+   debugfs_create_file("i915_joiner_force_enable", 0644, root,
+   connector, _joiner_fops);
}
 
if (connector_type == DRM_MODE_CONNECTOR_DSI ||
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index a9d2acdc51a4..14c78b18ffa1 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -613,6 +613,12 @@ struct intel_hdcp {
enum transcoder stream_transcoder;
 };
 
+enum intel_joiner_pipe_count {
+   INTEL_PIPE_JOINER_NONE = 0,
+   INTEL_PIPE_JOINER_BIG = 2,
+   INTEL_PIPE_JOINER_INVALID,
+};
+
 struct intel_connector {
struct drm_connector base;
/*
@@ -651,7 +657,7 @@ struct intel_connector {
 
struct intel_dp *mst_port;
 
-   bool force_bigjoiner_enable;
+   enum intel_joiner_pipe_count force_joined_pipes;
 
struct {
struct drm_dp_aux *dsc_decompression_aux;
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index d4b1b18453dc..30442c9da06b 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1164,7 +1164,7 @@ bool intel_dp_need_joiner(stru

[PATCH 10/10] drm/i915/vrr: Always use VRR timing generator for XELPD+

2024-07-08 Thread Ankit Nautiyal
Currently VRR timing generator is used only when VRR is enabled by
userspace. From XELPD+, gradually move away from older timing
generator and use VRR timing generator for fixed refresh rate also.
In such a case, Flipline VMin and VMax all are set to the Vtotal of the
mode, which effectively makes the VRR timing generator work in
fixed refresh rate mode.

v2: Use VRR Timing Generator from XELPD+ instead of MTL as it needs
Wa_14015406119.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_vrr.c | 59 +++-
 1 file changed, 37 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c 
b/drivers/gpu/drm/i915/display/intel_vrr.c
index 9f6b83f059cb..7af08e7a7896 100644
--- a/drivers/gpu/drm/i915/display/intel_vrr.c
+++ b/drivers/gpu/drm/i915/display/intel_vrr.c
@@ -174,41 +174,56 @@ intel_vrr_compute_config(struct intel_crtc_state 
*crtc_state,
if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
return;
 
-   crtc_state->vrr.in_range =
-   intel_vrr_is_in_range(connector, 
drm_mode_vrefresh(adjusted_mode));
-   if (!crtc_state->vrr.in_range)
-   return;
-
if (HAS_LRR(i915))
crtc_state->update_lrr = true;
 
-   vmin = DIV_ROUND_UP(adjusted_mode->crtc_clock * 1000,
-   adjusted_mode->crtc_htotal * 
info->monitor_range.max_vfreq);
-   vmax = adjusted_mode->crtc_clock * 1000 /
-   (adjusted_mode->crtc_htotal * info->monitor_range.min_vfreq);
+   if (!crtc_state->uapi.vrr_enabled && DISPLAY_VER(i915) >= 20) {
+   /*
+* for XELPD+ always go for VRR timing generator even for
+* fixed refresh rate.
+*/
+   crtc_state->vrr.vmin = adjusted_mode->crtc_vtotal;
+   crtc_state->vrr.vmax = adjusted_mode->crtc_vtotal;
+   crtc_state->vrr.flipline = adjusted_mode->crtc_vtotal;
+   crtc_state->vrr.fixed_rr = true;
+   } else {
 
-   vmin = max_t(int, vmin, adjusted_mode->crtc_vtotal);
-   vmax = max_t(int, vmax, adjusted_mode->crtc_vtotal);
+   crtc_state->vrr.in_range =
+   intel_vrr_is_in_range(connector, 
drm_mode_vrefresh(adjusted_mode));
 
-   if (vmin >= vmax)
-   return;
+   if (!crtc_state->vrr.in_range)
+   return;
 
-   /*
-* flipline determines the min vblank length the hardware will
-* generate, and flipline>=vmin+1, hence we reduce vmin by one
-* to make sure we can get the actual min vblank length.
-*/
-   crtc_state->vrr.vmin = vmin - 1;
-   crtc_state->vrr.vmax = vmax;
 
-   crtc_state->vrr.flipline = crtc_state->vrr.vmin + 1;
+   vmin = DIV_ROUND_UP(adjusted_mode->crtc_clock * 1000,
+   adjusted_mode->crtc_htotal * 
info->monitor_range.max_vfreq);
+   vmax = adjusted_mode->crtc_clock * 1000 /
+   (adjusted_mode->crtc_htotal * 
info->monitor_range.min_vfreq);
+
+   vmin = max_t(int, vmin, adjusted_mode->crtc_vtotal);
+   vmax = max_t(int, vmax, adjusted_mode->crtc_vtotal);
+
+   if (vmin >= vmax)
+   return;
+
+   /*
+* flipline determines the min vblank length the hardware will
+* generate, and flipline>=vmin+1, hence we reduce vmin by one
+* to make sure we can get the actual min vblank length.
+*/
+   crtc_state->vrr.vmin = vmin - 1;
+   crtc_state->vrr.vmax = vmax;
+
+   crtc_state->vrr.flipline = crtc_state->vrr.vmin + 1;
+   crtc_state->vrr.fixed_rr = false;
+   }
 
/*
 * When panel is VRR capable and userspace has
 * not enabled adaptive sync mode then Fixed Average
 * Vtotal mode should be enabled.
 */
-   if (crtc_state->uapi.vrr_enabled) {
+   if (crtc_state->uapi.vrr_enabled || crtc_state->vrr.fixed_rr) {
crtc_state->vrr.enable = true;
crtc_state->mode_flags |= I915_MODE_FLAG_VRR;
} else if (is_cmrr_frac_required(crtc_state) && is_edp) {
-- 
2.40.1



[PATCH 09/10] drm/i915/vrr: Handle joiner with vrr

2024-07-08 Thread Ankit Nautiyal
Do not program transcoder registers for VRR for the secondary pipe of
the joiner. Remove check to skip VRR for joiner case.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_vrr.c | 19 ---
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c 
b/drivers/gpu/drm/i915/display/intel_vrr.c
index 43ade1c24784..9f6b83f059cb 100644
--- a/drivers/gpu/drm/i915/display/intel_vrr.c
+++ b/drivers/gpu/drm/i915/display/intel_vrr.c
@@ -171,13 +171,6 @@ intel_vrr_compute_config(struct intel_crtc_state 
*crtc_state,
const struct drm_display_info *info = >base.display_info;
int vmin, vmax;
 
-   /*
-* FIXME all joined pipes share the same transcoder.
-* Need to account for that during VRR toggle/push/etc.
-*/
-   if (crtc_state->joiner_pipes)
-   return;
-
if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
return;
 
@@ -274,6 +267,9 @@ void intel_vrr_set_transcoder_timings(const struct 
intel_crtc_state *crtc_state)
struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
 
+   if (intel_crtc_is_joiner_secondary(crtc_state))
+   return;
+
/*
 * This bit seems to have two meanings depending on the platform:
 * TGL: generate VRR "safe window" for DSB vblank waits
@@ -316,6 +312,9 @@ void intel_vrr_send_push(const struct intel_crtc_state 
*crtc_state)
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
 
+   if (intel_crtc_is_joiner_secondary(crtc_state))
+   return;
+
if (!crtc_state->vrr.enable || crtc_state->vrr.fixed_rr)
return;
 
@@ -340,6 +339,9 @@ void intel_vrr_enable(const struct intel_crtc_state 
*crtc_state)
struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
 
+   if (intel_crtc_is_joiner_secondary(crtc_state))
+   return;
+
if (!crtc_state->vrr.enable)
return;
 
@@ -369,6 +371,9 @@ void intel_vrr_disable(const struct intel_crtc_state 
*old_crtc_state)
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder;
 
+   if (intel_crtc_is_joiner_secondary(old_crtc_state))
+   return;
+
if (!old_crtc_state->vrr.enable)
return;
 
-- 
2.40.1



[PATCH 08/10] drm/i915/vrr: Avoid sending PUSH when VRR TG is used with Fixed refresh rate

2024-07-08 Thread Ankit Nautiyal
As per Bspec:68925: Push enable must be set if not configuring for a
fixed refresh rate (i.e Vmin == Flipline == Vmax is not true).

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_vrr.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c 
b/drivers/gpu/drm/i915/display/intel_vrr.c
index 43b772f91556..43ade1c24784 100644
--- a/drivers/gpu/drm/i915/display/intel_vrr.c
+++ b/drivers/gpu/drm/i915/display/intel_vrr.c
@@ -316,7 +316,7 @@ void intel_vrr_send_push(const struct intel_crtc_state 
*crtc_state)
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
 
-   if (!crtc_state->vrr.enable)
+   if (!crtc_state->vrr.enable || crtc_state->vrr.fixed_rr)
return;
 
intel_de_write(dev_priv, TRANS_PUSH(dev_priv, cpu_transcoder),
@@ -329,7 +329,7 @@ bool intel_vrr_is_push_sent(const struct intel_crtc_state 
*crtc_state)
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
 
-   if (!crtc_state->vrr.enable)
+   if (!crtc_state->vrr.enable || crtc_state->vrr.fixed_rr)
return false;
 
return intel_de_read(dev_priv, TRANS_PUSH(dev_priv, cpu_transcoder)) & 
TRANS_PUSH_SEND;
@@ -343,8 +343,9 @@ void intel_vrr_enable(const struct intel_crtc_state 
*crtc_state)
if (!crtc_state->vrr.enable)
return;
 
-   intel_de_write(dev_priv, TRANS_PUSH(dev_priv, cpu_transcoder),
-  TRANS_PUSH_EN);
+   if (!crtc_state->vrr.fixed_rr)
+   intel_de_write(dev_priv, TRANS_PUSH(dev_priv, cpu_transcoder),
+  TRANS_PUSH_EN);
 
if (HAS_AS_SDP(dev_priv))
intel_de_write(dev_priv,
-- 
2.40.1



[PATCH 07/10] drm/i915/psr: Allow PSR for fixed refrsh rate with VRR TG

2024-07-08 Thread Ankit Nautiyal
At the moment PSR/PSR2 are not supported with variable refresh rate.
However it can be supported with fixed refresh rate while running with
VRR timing generator.
Enable PSR for fixed refresh rate when using the VRR timing generator.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_psr.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index 9cb1cdaaeefa..5a228d8e93b5 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -1523,7 +1523,7 @@ static bool _psr_compute_config(struct intel_dp *intel_dp,
 * Current PSR panels don't work reliably with VRR enabled
 * So if VRR is enabled, do not enable PSR.
 */
-   if (crtc_state->vrr.enable)
+   if (crtc_state->vrr.enable && !crtc_state->vrr.fixed_rr)
return false;
 
if (!CAN_PSR(intel_dp))
-- 
2.40.1



[PATCH 06/10] drm/i915/display: Disable PSR before disabling VRR

2024-07-08 Thread Ankit Nautiyal
As per bspec 49268: Disable PSR before disabling VRR.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_display.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 85695dc2b2e5..a979931a081b 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -1182,6 +1182,8 @@ static void intel_pre_plane_update(struct 
intel_atomic_state *state,
intel_atomic_get_new_crtc_state(state, crtc);
enum pipe pipe = crtc->pipe;
 
+   intel_psr_pre_plane_update(state, crtc);
+
if (vrr_disabling(old_crtc_state, new_crtc_state)) {
intel_vrr_disable(old_crtc_state);
intel_crtc_update_active_timings(old_crtc_state, false);
@@ -1192,8 +1194,6 @@ static void intel_pre_plane_update(struct 
intel_atomic_state *state,
 
intel_drrs_deactivate(old_crtc_state);
 
-   intel_psr_pre_plane_update(state, crtc);
-
if (hsw_ips_pre_update(state, crtc))
intel_crtc_wait_for_next_vblank(crtc);
 
-- 
2.40.1



[PATCH 05/10] drm/i915/hdmi: Use VRR Timing generator for HDMI

2024-07-08 Thread Ankit Nautiyal
Add support for using VRR Timing generator for HDMI panels.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_hdmi.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c 
b/drivers/gpu/drm/i915/display/intel_hdmi.c
index 19498ee455fa..c8442772bacf 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -59,6 +59,7 @@
 #include "intel_lspcon.h"
 #include "intel_panel.h"
 #include "intel_snps_phy.h"
+#include "intel_vrr.h"
 
 inline struct drm_i915_private *intel_hdmi_to_i915(struct intel_hdmi 
*intel_hdmi)
 {
@@ -2366,6 +2367,8 @@ int intel_hdmi_compute_config(struct intel_encoder 
*encoder,
}
}
 
+   intel_vrr_compute_config(pipe_config, conn_state);
+
intel_hdmi_compute_gcp_infoframe(encoder, pipe_config,
 conn_state);
 
-- 
2.40.1



[PATCH 04/10] drm/i915/vrr: Compute vrr vsync if platforms support it

2024-07-08 Thread Ankit Nautiyal
Previously, TRANS_VRR_VSYNC was exclusively used for panels with
adaptive-sync SDP support in VRR scenarios. However, to drive fixed refresh
rates using the VRR Timing generator, we now need to program
TRANS_VRR_VSYNC regardless of adaptive sync SDP support. Therefore, let's
remove the adaptive sync SDP check and program TRANS_VRR_VSYNC for
platforms where VRR timing generator is used.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_vrr.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c 
b/drivers/gpu/drm/i915/display/intel_vrr.c
index 24568dae717a..43b772f91556 100644
--- a/drivers/gpu/drm/i915/display/intel_vrr.c
+++ b/drivers/gpu/drm/i915/display/intel_vrr.c
@@ -233,8 +233,7 @@ intel_vrr_compute_config(struct intel_crtc_state 
*crtc_state,
crtc_state->mode_flags |= I915_MODE_FLAG_VRR;
}
 
-   if (intel_dp_as_sdp_supported(intel_dp) &&
-   crtc_state->vrr.enable) {
+   if (HAS_AS_SDP(i915) && crtc_state->vrr.enable) {
crtc_state->vrr.vsync_start =
(crtc_state->hw.adjusted_mode.crtc_vtotal -
 crtc_state->hw.adjusted_mode.vsync_start);
-- 
2.40.1



[PATCH 03/10] drm/i915/dp: Set FAVT mode in DP SDP with fixed refresh rate

2024-07-08 Thread Ankit Nautiyal
While running with fixed refresh rate and VRR timing generator set FAVT
mode (Fixed Vtotal) in DP Adaptive Sync SDP to intimate the panel
about Fixed refresh rate.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 3f46e13bb7b8..dcb94526cf00 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2642,6 +2642,10 @@ static void intel_dp_compute_as_sdp(struct intel_dp 
*intel_dp,
as_sdp->target_rr = drm_mode_vrefresh(adjusted_mode);
as_sdp->target_rr_divider = true;
} else {
+   if (crtc_state->vrr.fixed_rr)
+   as_sdp->mode = DP_AS_SDP_AVT_FIXED_VTOTAL;
+   else
+   as_sdp->mode = DP_AS_SDP_AVT_DYNAMIC_VTOTAL;
as_sdp->mode = DP_AS_SDP_AVT_DYNAMIC_VTOTAL;
as_sdp->vtotal = adjusted_mode->vtotal;
as_sdp->target_rr = 0;
-- 
2.40.1



[PATCH 02/10] drm/i915/display: Add member fixed_rr to denote Fixed refresh rate with VRRTG

2024-07-08 Thread Ankit Nautiyal
Add fixed_rr member to struct vrr to represent the case where a
fixed refresh rate with VRR timing generator is required.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_display.c   | 4 +++-
 drivers/gpu/drm/i915/display/intel_display_types.h | 2 +-
 drivers/gpu/drm/i915/display/intel_vrr.c   | 3 +++
 3 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index c2c388212e2e..85695dc2b2e5 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -1004,7 +1004,8 @@ static bool vrr_params_changed(const struct 
intel_crtc_state *old_crtc_state,
old_crtc_state->vrr.vmin != new_crtc_state->vrr.vmin ||
old_crtc_state->vrr.vmax != new_crtc_state->vrr.vmax ||
old_crtc_state->vrr.guardband != new_crtc_state->vrr.guardband 
||
-   old_crtc_state->vrr.pipeline_full != 
new_crtc_state->vrr.pipeline_full;
+   old_crtc_state->vrr.pipeline_full != 
new_crtc_state->vrr.pipeline_full ||
+   old_crtc_state->vrr.fixed_rr != new_crtc_state->vrr.fixed_rr;
 }
 
 static bool cmrr_params_changed(const struct intel_crtc_state *old_crtc_state,
@@ -5469,6 +5470,7 @@ intel_pipe_config_compare(const struct intel_crtc_state 
*current_config,
 
if (!fastset) {
PIPE_CONF_CHECK_BOOL(vrr.enable);
+   PIPE_CONF_CHECK_BOOL(vrr.fixed_rr);
PIPE_CONF_CHECK_I(vrr.vmin);
PIPE_CONF_CHECK_I(vrr.vmax);
PIPE_CONF_CHECK_I(vrr.flipline);
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index 8713835e2307..875370219892 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1407,7 +1407,7 @@ struct intel_crtc_state {
 
/* Variable Refresh Rate state */
struct {
-   bool enable, in_range;
+   bool enable, in_range, fixed_rr;
u8 pipeline_full;
u16 flipline, vmin, vmax, guardband;
u32 vsync_end, vsync_start;
diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c 
b/drivers/gpu/drm/i915/display/intel_vrr.c
index 5a0da64c7db3..24568dae717a 100644
--- a/drivers/gpu/drm/i915/display/intel_vrr.c
+++ b/drivers/gpu/drm/i915/display/intel_vrr.c
@@ -421,6 +421,9 @@ void intel_vrr_get_config(struct intel_crtc_state 
*crtc_state)
 TRANS_VRR_VMAX(dev_priv, 
cpu_transcoder)) + 1;
crtc_state->vrr.vmin = intel_de_read(dev_priv,
 TRANS_VRR_VMIN(dev_priv, 
cpu_transcoder)) + 1;
+   if (crtc_state->vrr.vmax == crtc_state->vrr.flipline &&
+   crtc_state->vrr.vmin == crtc_state->vrr.flipline)
+   crtc_state->vrr.fixed_rr = true;
}
 
if (crtc_state->vrr.enable) {
-- 
2.40.1



[PATCH 01/10] drm/i915/dp: fix the Adaptive sync Operation mode for SDP

2024-07-08 Thread Ankit Nautiyal
Currently we support Adaptive sync operation mode with dynamic frame
rate, but instead the operation mode with fixed rate is set.
This was initially set correctly in the earlier version of changes but
later got changed, while defining a macro for the same.

Fixes: a5bd5991cb8a ("drm/i915/display: Compute AS SDP parameters")
Cc: Mitul Golani 
Cc: Ankit Nautiyal 
Cc: Jani Nikula 
Reviewed-by: Mitul Golani 
Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 3903f6ead6e6..3f46e13bb7b8 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2631,7 +2631,6 @@ static void intel_dp_compute_as_sdp(struct intel_dp 
*intel_dp,
 
crtc_state->infoframes.enable |= 
intel_hdmi_infoframe_enable(DP_SDP_ADAPTIVE_SYNC);
 
-   /* Currently only DP_AS_SDP_AVT_FIXED_VTOTAL mode supported */
as_sdp->sdp_type = DP_SDP_ADAPTIVE_SYNC;
as_sdp->length = 0x9;
as_sdp->duration_incr_ms = 0;
@@ -2643,7 +2642,7 @@ static void intel_dp_compute_as_sdp(struct intel_dp 
*intel_dp,
as_sdp->target_rr = drm_mode_vrefresh(adjusted_mode);
as_sdp->target_rr_divider = true;
} else {
-   as_sdp->mode = DP_AS_SDP_AVT_FIXED_VTOTAL;
+   as_sdp->mode = DP_AS_SDP_AVT_DYNAMIC_VTOTAL;
as_sdp->vtotal = adjusted_mode->vtotal;
as_sdp->target_rr = 0;
}
-- 
2.40.1



[PATCH 00/10] Use VRR timing generator for fixed refresh rate modes

2024-07-08 Thread Ankit Nautiyal
Even though the VRR timing generator (TG) is primarily used for
variable refresh rates, it can be used for fixed refresh rates as
well. For a fixed refresh rate the Flip Line and Vmax must be equal
(TRANS_VRR_FLIPLINE = TRANS_VRR_VMAX). Beyond that, there are some
dependencies between the VRR timings and the legacy timing generator
registgers.

This series is an attempt to use VRR TG for fixed refresh rate.
For platforms XELPD+, always go with VRR timing generator for both fixed and
variable refresh rate cases.

Rev2:
-Added support from MTL+ and for HDMI too.
-Changed VRR VSYNC programming which is required for HDMI.
-Modified vrr compute config for bigjoiner case. (Still to be tested).

Rev3:
-Start support from XELPD+ as MTL needs a WA to have PSR +VRR (fixed
refresh rate)
-Add changes to enable PSR with VRR with fixed refresh rate.

Ankit Nautiyal (10):
  drm/i915/dp: fix the Adaptive sync Operation mode for SDP
  drm/i915/display: Add member fixed_rr to denote Fixed refresh rate
with VRRTG
  drm/i915/dp: Set FAVT mode in DP SDP with fixed refresh rate
  drm/i915/vrr: Compute vrr vsync if platforms support it
  drm/i915/hdmi: Use VRR Timing generator for HDMI
  drm/i915/display: Disable PSR before disabling VRR
  drm/i915/psr: Allow PSR for fixed refrsh rate with VRR TG
  drm/i915/vrr: Avoid sending PUSH when VRR TG is used with Fixed
refresh rate
  drm/i915/vrr: Handle joiner with vrr
  drm/i915/vrr: Always use VRR timing generator for XELPD+

 drivers/gpu/drm/i915/display/intel_display.c  |  8 +-
 .../drm/i915/display/intel_display_types.h|  2 +-
 drivers/gpu/drm/i915/display/intel_dp.c   |  7 +-
 drivers/gpu/drm/i915/display/intel_hdmi.c |  3 +
 drivers/gpu/drm/i915/display/intel_psr.c  |  2 +-
 drivers/gpu/drm/i915/display/intel_vrr.c  | 93 ---
 6 files changed, 73 insertions(+), 42 deletions(-)

-- 
2.40.1



[PATCH] drm/i915/dp: Wait more before rearming FIFO underrun during retrain

2024-06-26 Thread Ankit Nautiyal
During Link re-training reporting underrun is disabled and then
renabled after re-training is completed. For BMG its seen that we get
FIFO underrun just after the retraining is completed and the underrun
reporting is re-enabled.
Add one more intel_crtc_wait_for_next_vblank before re-arming the
underruns.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 3903f6ead6e6..25af51499383 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -5325,7 +5325,12 @@ static int intel_dp_retrain_link(struct intel_encoder 
*encoder,
const struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
 
-   /* Keep underrun reporting disabled until things are stable */
+   /*
+* Keep underrun reporting disabled until things are stable.
+* Wait for some more time, as we see (at least on BMG) that
+* underrun gets reported just after the reporting is enabled.
+*/
+   intel_crtc_wait_for_next_vblank(crtc);
intel_crtc_wait_for_next_vblank(crtc);
 
intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, 
true);
-- 
2.40.1



[PATCH 5/5] drm/xe: Add intel_pll_algorithm in Makefile

2024-06-25 Thread Ankit Nautiyal
Include the intel_pll_algorithm for xe driver.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/xe/Makefile | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
index 478acc94a71c..30b63c2eadd0 100644
--- a/drivers/gpu/drm/xe/Makefile
+++ b/drivers/gpu/drm/xe/Makefile
@@ -261,6 +261,7 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \
i915-display/intel_modeset_setup.o \
i915-display/intel_modeset_verify.o \
i915-display/intel_panel.o \
+   i915-display/intel_pll_algorithm.o \
i915-display/intel_pmdemand.o \
i915-display/intel_pps.o \
i915-display/intel_psr.o \
-- 
2.40.1



[PATCH 3/5] drm/i915/cx0_phy_regs: Add C10 registers bits

2024-06-25 Thread Ankit Nautiyal
Add C10 register bits to be used for computing HDMI PLLs with
algorithm.

Signed-off-by: Ankit Nautiyal 
---
 .../gpu/drm/i915/display/intel_cx0_phy_regs.h | 24 +++
 1 file changed, 24 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h 
b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
index ab3ae110b68f..56443bf3e7cf 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
@@ -202,10 +202,34 @@
 
 /* C10 Vendor Registers */
 #define PHY_C10_VDR_PLL(idx)   (0xC00 + (idx))
+#define   C10_PLL0_SSC_EN  REG_BIT8(0)
+#define   C10_PLL0_DIVCLK_EN   REG_BIT8(1)
+#define   C10_PLL0_DIV5CLK_EN  REG_BIT8(2)
+#define   C10_PLL0_WORDDIV2_EN REG_BIT8(3)
 #define   C10_PLL0_FRACEN  REG_BIT8(4)
+#define   C10_PLL0_PMIX_EN REG_BIT8(5)
+#define   C10_PLL0_ANA_FREQ_VCO_MASK   REG_GENMASK8(7, 6)
+#define   C10_PLL1_DIV_MULTIPLIER_MASK REG_GENMASK8(7, 0)
+#define   C10_PLL2_MULTIPLIERL_MASKREG_GENMASK8(7, 0)
 #define   C10_PLL3_MULTIPLIERH_MASKREG_GENMASK8(3, 0)
+#define   C10_PLL8_SSC_UP_SPREAD   REG_BIT(5)
+#define   C10_PLL9_FRACN_DENL_MASK REG_GENMASK8(7, 0)
+#define   C10_PLL10_FRACN_DENH_MASKREG_GENMASK8(7, 0)
+#define   C10_PLL11_FRACN_QUOT_L_MASK  REG_GENMASK8(7, 0)
+#define   C10_PLL12_FRACN_QUOT_H_MASK  REG_GENMASK8(7, 0)
+#define   C10_PLL13_FRACN_REM_L_MASK   REG_GENMASK8(7, 0)
+#define   C10_PLL14_FRACN_REM_H_MASK   REG_GENMASK8(7, 0)
 #define   C10_PLL15_TXCLKDIV_MASK  REG_GENMASK8(2, 0)
 #define   C10_PLL15_HDMIDIV_MASK   REG_GENMASK8(5, 3)
+#define   C10_PLL15_PIXELCLKDIV_MASK   REG_GENMASK8(7, 6)
+#define   C10_PLL16_ANA_CPINT  REG_GENMASK8(6, 0)
+#define   C10_PLL16_ANA_CPINTGS_L  REG_BIT(7)
+#define   C10_PLL17_ANA_CPINTGS_H_MASK REG_GENMASK8(5, 0)
+#define   C10_PLL17_ANA_CPPROP_L_MASK  REG_GENMASK8(7, 6)
+#define   C10_PLL18_ANA_CPPROP_H_MASK  REG_GENMASK8(4, 0)
+#define   C10_PLL18_ANA_CPPROPGS_L_MASKREG_GENMASK8(7, 5)
+#define   C10_PLL19_ANA_CPPROPGS_H_MASKREG_GENMASK8(3, 0)
+#define   C10_PLL19_ANA_V2I_MASK   REG_GENMASK8(5, 4)
 
 #define PHY_C10_VDR_CMN(idx)   (0xC20 + (idx))
 #define   C10_CMN0_REF_RANGE   REG_FIELD_PREP(REG_GENMASK(4, 0), 1)
-- 
2.40.1



[PATCH 4/5] drm/i915/pll_algorithm: Compute C10 HDMI PLLs with algorithm

2024-06-25 Thread Ankit Nautiyal
Add support for computing C10 HDMI PLLS using the HDMI PLL algorithm.
Try C10 HDMI tables computed with the algorithm, before using the
consolidated tables.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c  | 15 +
 .../drm/i915/display/intel_pll_algorithm.c| 65 +++
 .../drm/i915/display/intel_pll_algorithm.h|  2 +
 3 files changed, 82 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 41f684c970dc..ebd2ec4023d6 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -15,6 +15,7 @@
 #include "intel_dp.h"
 #include "intel_hdmi.h"
 #include "intel_panel.h"
+#include "intel_pll_algorithm.h"
 #include "intel_psr.h"
 #include "intel_tc.h"
 
@@ -1980,6 +1981,9 @@ static int intel_c10_phy_check_hdmi_link_rate(int clock)
return MODE_OK;
}
 
+   if (clock >= 25175 && clock <= 594000)
+   return MODE_OK;
+
return MODE_CLOCK_RANGE;
 }
 
@@ -2030,6 +2034,17 @@ static int intel_c10pll_calc_state(struct 
intel_crtc_state *crtc_state,
const struct intel_c10pll_state * const *tables;
int i;
 
+   /* try computed C10 HDMI tables before using consolidated tables */
+   if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
+   if (intel_c10_phy_compute_hdmi_tmds_pll(crtc_state->port_clock,
+   
_state->dpll_hw_state.cx0pll.c10) == 0) {
+   intel_c10pll_update_pll(crtc_state, encoder);
+   crtc_state->dpll_hw_state.cx0pll.use_c10 = true;
+   }
+
+   return 0;
+   }
+
tables = intel_c10pll_tables_get(crtc_state, encoder);
if (!tables)
return -EINVAL;
diff --git a/drivers/gpu/drm/i915/display/intel_pll_algorithm.c 
b/drivers/gpu/drm/i915/display/intel_pll_algorithm.c
index d935715bd3ab..07b712cc0d6f 100644
--- a/drivers/gpu/drm/i915/display/intel_pll_algorithm.c
+++ b/drivers/gpu/drm/i915/display/intel_pll_algorithm.c
@@ -5,6 +5,7 @@
 
 #include 
 #include "i915_reg.h"
+#include "intel_cx0_phy_regs.h"
 #include "intel_ddi.h"
 #include "intel_ddi_buf_trans.h"
 #include "intel_de.h"
@@ -250,3 +251,67 @@ int intel_snps_phy_compute_hdmi_tmds_pll(u64 pixel_clock, 
struct intel_mpllb_sta
 
return 0;
 }
+
+int intel_c10_phy_compute_hdmi_tmds_pll(u64 pixel_clock, struct 
intel_c10pll_state *pll_state)
+{
+   struct pll_output_params pll_params;
+   u32 refclk = 3840;
+   u32 prescaler_divider = 0;
+   u32 ref_range = 1;
+   u32 ana_cp_int_gs = 30;
+   u32 ana_cp_prop_gs = 28;
+   int ret;
+   /* x axis frequencies. One curve in each array per v2i point */
+   const u64 c10_curve_freq_hz[2][8] = {
+   {25, 30, 30, 35, 35, 
40, 40, 50},
+   {40, 46, 460100, 54, 540100, 
66, 660100, 800100}};
+   /* y axis heights multiplied with 10 */
+
+   const u64 c10_curve_0[2][8] = {
+   {41174500, 48605500, 42973700, 49433100, 42408600, 47681900, 
40297400, 49131400},
+   {82056800, 94420700, 82323400, 96370600, 81273300, 98630100, 
81728700, 99105700}};
+
+   const u64 c10_curve_1[2][8] = {
+   {733000, 66, 831000, 
753000, 997000, 923000, 125, 
110},
+   {537000, 477000, 622000, 
544000, 751000, 634000, 906000, 
763000}};
+
+   /* Multiplied with 1 */
+   const u64 c10_curve_2[2][8] = {
+   {241579, 313646, 258199, 322267, 252933, 
304202, 233697, 319146},
+   {480839, 599425, 483273, 619373, 473770, 
642875, 477920, 647934}};
+
+   ret = _intel_phy_compute_hdmi_tmds_pll(pixel_clock, refclk, ref_range,
+  ana_cp_int_gs, ana_cp_prop_gs,
+  c10_curve_freq_hz, c10_curve_0,
+  c10_curve_1, c10_curve_2, 
prescaler_divider,
+  _params);
+   if (ret)
+   return ret;
+
+   pll_state->tx = 0x10;
+   pll_state->cmn = 0x1;
+   pll_state->pll[0] = REG_FIELD_PREP(C10_PLL0_DIV5CLK_EN, 
pll_params.mpll_div5_en) |
+   REG_FIELD_PREP(C10_PLL0_FRACEN, 
pll_params.fracn_en) |
+   REG_FIELD_PREP(C10_PLL0_PMIX_EN, 
pll_params.pmix_en) 

[PATCH 2/5] drm/i915/snps_phy: Use HDMI PLL algorithm for DG2

2024-06-25 Thread Ankit Nautiyal
Try SNPS_PHY HDMI tables computed using the algorithm, before using
consolidated tables.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_snps_phy.c | 20 ---
 1 file changed, 8 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_snps_phy.c 
b/drivers/gpu/drm/i915/display/intel_snps_phy.c
index e6df1f92def5..10fe28af0d11 100644
--- a/drivers/gpu/drm/i915/display/intel_snps_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_snps_phy.c
@@ -12,6 +12,7 @@
 #include "intel_display_types.h"
 #include "intel_snps_phy.h"
 #include "intel_snps_phy_regs.h"
+#include "intel_pll_algorithm.h"
 
 /**
  * DOC: Synopsis PHY support
@@ -1787,22 +1788,14 @@ intel_mpllb_tables_get(struct intel_crtc_state 
*crtc_state,
 int intel_mpllb_calc_state(struct intel_crtc_state *crtc_state,
   struct intel_encoder *encoder)
 {
-   struct drm_i915_private *i915 = to_i915(encoder->base.dev);
const struct intel_mpllb_state * const *tables;
int i;
 
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
-   if (intel_snps_phy_check_hdmi_link_rate(crtc_state->port_clock)
-   != MODE_OK) {
-   /*
-* FIXME: Can only support fixed HDMI frequencies
-* until we have a proper algorithm under a valid
-* license.
-*/
-   drm_dbg_kms(>drm, "Can't support HDMI link rate 
%d\n",
-   crtc_state->port_clock);
-   return -EINVAL;
-   }
+   /* try computed SNPS_PHY HDMI tables before using consolidated 
tables */
+   if (intel_snps_phy_compute_hdmi_tmds_pll(crtc_state->port_clock,
+
_state->dpll_hw_state.mpllb) == 0)
+   return 0;
}
 
tables = intel_mpllb_tables_get(crtc_state, encoder);
@@ -1991,6 +1984,9 @@ int intel_snps_phy_check_hdmi_link_rate(int clock)
return MODE_OK;
}
 
+   if (clock >= 25175 && clock <= 594000)
+   return MODE_OK;
+
return MODE_CLOCK_RANGE;
 }
 
-- 
2.40.1



[PATCH 1/5] drm/i915/display: Add support for SNPS PHY HDMI PLL algorithm for DG2

2024-06-25 Thread Ankit Nautiyal
Add helper _intel_phy_compute_hdmi_tmds_pll to calculate the necessary
parameters for configuring the HDMI PLL for SNPS MPLLB and C10 PHY.

The pll parameters are computed for desired pixel clock, curve data
and other inputs used for interpolation and finally stored in the
pll_state. Bspec:54032

Currently the helper is used to compute PLLs for DG2 SNPS PHY.
Support for computing Plls for C10 PHY is added in subsequent patches.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/Makefile |   1 +
 .../drm/i915/display/intel_pll_algorithm.c| 252 ++
 .../drm/i915/display/intel_pll_algorithm.h|  39 +++
 3 files changed, 292 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/display/intel_pll_algorithm.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_pll_algorithm.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 4022e4499382..f1a293110bc6 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -334,6 +334,7 @@ i915-y += \
display/intel_lspcon.o \
display/intel_lvds.o \
display/intel_panel.o \
+   display/intel_pll_algorithm.o \
display/intel_pps.o \
display/intel_qp_tables.o \
display/intel_sdvo.o \
diff --git a/drivers/gpu/drm/i915/display/intel_pll_algorithm.c 
b/drivers/gpu/drm/i915/display/intel_pll_algorithm.c
new file mode 100644
index ..d935715bd3ab
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_pll_algorithm.c
@@ -0,0 +1,252 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2024 Synopsys, Inc., Intel Corporation
+ */
+
+#include 
+#include "i915_reg.h"
+#include "intel_ddi.h"
+#include "intel_ddi_buf_trans.h"
+#include "intel_de.h"
+#include "intel_display_types.h"
+#include "intel_snps_phy.h"
+#include "intel_snps_phy_regs.h"
+#include "intel_pll_algorithm.h"
+
+#define INTEL_SNPS_PHY_HDMI_4999MHZ 499900ull
+#define INTEL_SNPS_PHY_HDMI_16GHZ 160ull
+#define INTEL_SNPS_PHY_HDMI_MHZ (2 * INTEL_SNPS_PHY_HDMI_4999MHZ)
+
+#define CURVE0_MULTIPLIER 10
+#define CURVE1_MULTIPLIER 100
+#define CURVE2_MULTIPLIER 1
+
+static int64_t interp(s64 x, s64 x1, s64 x2, s64 y1, s64 y2)
+{
+   s64 dydx;
+
+   dydx = DIV_ROUND_UP((y2 - y1) * 10, (x2 - x1));
+
+   return (y1 + DIV_ROUND_UP(dydx * (x - x1), 10));
+}
+
+static void get_ana_cp_int_prop(u32 vco_clk,
+   u32 refclk_postscalar,
+   int mpll_ana_v2i,
+   int c, int a,
+   const u64 curve_freq_hz[2][8],
+   const u64 curve_0[2][8],
+   const u64 curve_1[2][8],
+   const u64 curve_2[2][8],
+   u32 *ana_cp_int,
+   u32 *ana_cp_prop)
+{
+   u64 vco_div_refclk_float;
+   u64 o_397ced90;
+   u64 o_20c634d6;
+   u64 o_20c634d4;
+   u64 o_72019306;
+   u64 o_6593e82b;
+   u64 o_5cefc329;
+   u64 o_49960328;
+   u64 o_544adb37;
+   u64 o_4ef74e66;
+   u32 ana_cp_int_temp;
+   u64 temp1, temp2, temp3, temp4;
+
+   vco_div_refclk_float = vco_clk * (1 / refclk_postscalar);
+   o_397ced90 = interp(vco_clk, curve_freq_hz[c][a], curve_freq_hz[c][a + 
1],
+   curve_0[c][a], curve_0[c][a + 1]);
+
+   o_20c634d6 = interp(vco_clk, curve_freq_hz[c][a], curve_freq_hz[c][a + 
1],
+   curve_2[c][a], curve_2[c][a + 1]);
+
+   o_20c634d4 = interp(vco_clk, curve_freq_hz[c][a], curve_freq_hz[c][a + 
1],
+   curve_1[c][a], curve_1[c][a + 1]);
+
+   o_20c634d4 /= CURVE1_MULTIPLIER;
+
+   temp1 = o_20c634d6 * (4 - mpll_ana_v2i);
+
+   o_72019306 = temp1 / 16000;
+   o_6593e82b = temp1 / 160;
+
+   temp2 = ((112008301 * (vco_div_refclk_float / 10)));
+   o_5cefc329 = CURVE2_MULTIPLIER * (temp2 / (o_397ced90 * (o_20c634d4 / 
CURVE0_MULTIPLIER)));
+
+   ana_cp_int_temp = min(DIV_ROUND_CLOSEST(o_5cefc329 / o_72019306, 
CURVE2_MULTIPLIER), 127);
+   ana_cp_int_temp = max(1, ana_cp_int_temp);
+
+   *ana_cp_int = ana_cp_int_temp;
+
+   o_49960328 = o_72019306 * ana_cp_int_temp;
+
+   temp3 = o_20c634d4 * (o_49960328 * o_397ced90 / CURVE0_MULTIPLIER);
+   o_544adb37 = int_sqrt(DIV_ROUND_UP(temp3, vco_div_refclk_float) * 
(1 / 55));
+
+   temp4 = DIV_ROUND_UP(vco_div_refclk_float, 100);
+   o_4ef74e66 = (1460281 * DIV_ROUND_UP(o_544adb37 * temp4, o_20c634d4));
+
+   *ana_cp_prop = max(1, min(DIV_ROUND_UP(o_4ef74e66, o_6593e82b), 127));
+}
+
+static int _intel_phy_compute_hdmi_tmds_pll(u64 pixel_clock, u32 refclk,
+   u32 ref_range,
+ 

[PATCH 0/5] Add HDMI PLL Algorithm for SNPS/C10PHY

2024-06-25 Thread Ankit Nautiyal
The HDMI PLL programming involves pre-calculated values for specific
frequencies and an algorithm to compute values for other frequencies.
While the algorithm itself wasn't part of the driver, tables were
added based on it for known modes.

Some HDMI modes were pruned due to lack of support (for example issues
[1],[2], and [3]).
This series adds the algorithm for computing HDMI PLLs for SNPS/C10PHY
to work with all modes supported by the hardware.

The original algorithm uses floating-point math, which has been
converted to integers while preserving precision. As a result,
the values in the existing computable tables are very close but not
exact. Testing with DG2 and MTL on various panels revealed no issues.

[1] https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9722
[2] https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/10654
[3] https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/10956

Ankit Nautiyal (5):
  drm/i915/display: Add support for SNPS PHY HDMI PLL algorithm for DG2
  drm/i915/snps_phy: Use HDMI PLL algorithm for DG2
  drm/i915/cx0_phy_regs: Add C10 registers bits
  drm/i915/pll_algorithm: Compute C10 HDMI PLLs with algorithm
  drm/xe: Add intel_pll_algorithm in Makefile

 drivers/gpu/drm/i915/Makefile |   1 +
 drivers/gpu/drm/i915/display/intel_cx0_phy.c  |  15 +
 .../gpu/drm/i915/display/intel_cx0_phy_regs.h |  24 ++
 .../drm/i915/display/intel_pll_algorithm.c| 317 ++
 .../drm/i915/display/intel_pll_algorithm.h|  41 +++
 drivers/gpu/drm/i915/display/intel_snps_phy.c |  20 +-
 drivers/gpu/drm/xe/Makefile   |   1 +
 7 files changed, 407 insertions(+), 12 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_pll_algorithm.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_pll_algorithm.h

-- 
2.40.1



[PATCH 9/9] drm/i915/vrr: Use VRR timing generator whenever panel supports VRR

2024-06-23 Thread Ankit Nautiyal
Currently VRR timing generator is used only when VRR is enabled by
userspace. From MTL+, gradually move away from older timing
generator and use VRR timing generator for fixed refresh rate also.
In such a case, Flipline VMin and VMax all are set to the Vtotal of the
mode, which effectively makes the VRR timing generator work in
fixed refresh rate mode.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_vrr.c | 59 +++-
 1 file changed, 37 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c 
b/drivers/gpu/drm/i915/display/intel_vrr.c
index 025063098370..913752424adc 100644
--- a/drivers/gpu/drm/i915/display/intel_vrr.c
+++ b/drivers/gpu/drm/i915/display/intel_vrr.c
@@ -174,41 +174,56 @@ intel_vrr_compute_config(struct intel_crtc_state 
*crtc_state,
if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
return;
 
-   crtc_state->vrr.in_range =
-   intel_vrr_is_in_range(connector, 
drm_mode_vrefresh(adjusted_mode));
-   if (!crtc_state->vrr.in_range)
-   return;
-
if (HAS_LRR(i915))
crtc_state->update_lrr = true;
 
-   vmin = DIV_ROUND_UP(adjusted_mode->crtc_clock * 1000,
-   adjusted_mode->crtc_htotal * 
info->monitor_range.max_vfreq);
-   vmax = adjusted_mode->crtc_clock * 1000 /
-   (adjusted_mode->crtc_htotal * info->monitor_range.min_vfreq);
+   if (!crtc_state->uapi.vrr_enabled && DISPLAY_VER(i915) >= 14) {
+   /*
+* for MTL+ if panel supports VRR and user has not set VRR,
+* always go for fixed average Vtotal mode.
+*/
+   crtc_state->vrr.vmin = adjusted_mode->crtc_vtotal;
+   crtc_state->vrr.vmax = adjusted_mode->crtc_vtotal;
+   crtc_state->vrr.flipline = adjusted_mode->crtc_vtotal;
+   crtc_state->vrr.fixed_rr = true;
+   } else {
 
-   vmin = max_t(int, vmin, adjusted_mode->crtc_vtotal);
-   vmax = max_t(int, vmax, adjusted_mode->crtc_vtotal);
+   crtc_state->vrr.in_range =
+   intel_vrr_is_in_range(connector, 
drm_mode_vrefresh(adjusted_mode));
 
-   if (vmin >= vmax)
-   return;
+   if (!crtc_state->vrr.in_range)
+   return;
 
-   /*
-* flipline determines the min vblank length the hardware will
-* generate, and flipline>=vmin+1, hence we reduce vmin by one
-* to make sure we can get the actual min vblank length.
-*/
-   crtc_state->vrr.vmin = vmin - 1;
-   crtc_state->vrr.vmax = vmax;
 
-   crtc_state->vrr.flipline = crtc_state->vrr.vmin + 1;
+   vmin = DIV_ROUND_UP(adjusted_mode->crtc_clock * 1000,
+   adjusted_mode->crtc_htotal * 
info->monitor_range.max_vfreq);
+   vmax = adjusted_mode->crtc_clock * 1000 /
+   (adjusted_mode->crtc_htotal * 
info->monitor_range.min_vfreq);
+
+   vmin = max_t(int, vmin, adjusted_mode->crtc_vtotal);
+   vmax = max_t(int, vmax, adjusted_mode->crtc_vtotal);
+
+   if (vmin >= vmax)
+   return;
+
+   /*
+* flipline determines the min vblank length the hardware will
+* generate, and flipline>=vmin+1, hence we reduce vmin by one
+* to make sure we can get the actual min vblank length.
+*/
+   crtc_state->vrr.vmin = vmin - 1;
+   crtc_state->vrr.vmax = vmax;
+
+   crtc_state->vrr.flipline = crtc_state->vrr.vmin + 1;
+   crtc_state->vrr.fixed_rr = false;
+   }
 
/*
 * When panel is VRR capable and userspace has
 * not enabled adaptive sync mode then Fixed Average
 * Vtotal mode should be enabled.
 */
-   if (crtc_state->uapi.vrr_enabled) {
+   if (crtc_state->uapi.vrr_enabled || crtc_state->vrr.fixed_rr) {
crtc_state->vrr.enable = true;
crtc_state->mode_flags |= I915_MODE_FLAG_VRR;
} else if (is_cmrr_frac_required(crtc_state) && is_edp) {
-- 
2.40.1



[PATCH 5/9] drm/i915/vrr: Avoid sending PUSH when VRR TG is used with Fixed refresh rate

2024-06-23 Thread Ankit Nautiyal
As per Bspec:68925: Push enable must be set if not configuring for a
fixed refresh rate (i.e Vmin == Flipline == Vmax is not true).

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_vrr.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c 
b/drivers/gpu/drm/i915/display/intel_vrr.c
index 6736e8a44faa..a771706d80df 100644
--- a/drivers/gpu/drm/i915/display/intel_vrr.c
+++ b/drivers/gpu/drm/i915/display/intel_vrr.c
@@ -317,7 +317,7 @@ void intel_vrr_send_push(const struct intel_crtc_state 
*crtc_state)
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
 
-   if (!crtc_state->vrr.enable)
+   if (!crtc_state->vrr.enable || crtc_state->vrr.fixed_rr)
return;
 
intel_de_write(dev_priv, TRANS_PUSH(dev_priv, cpu_transcoder),
@@ -330,7 +330,7 @@ bool intel_vrr_is_push_sent(const struct intel_crtc_state 
*crtc_state)
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
 
-   if (!crtc_state->vrr.enable)
+   if (!crtc_state->vrr.enable || crtc_state->vrr.fixed_rr)
return false;
 
return intel_de_read(dev_priv, TRANS_PUSH(dev_priv, cpu_transcoder)) & 
TRANS_PUSH_SEND;
@@ -344,8 +344,9 @@ void intel_vrr_enable(const struct intel_crtc_state 
*crtc_state)
if (!crtc_state->vrr.enable)
return;
 
-   intel_de_write(dev_priv, TRANS_PUSH(dev_priv, cpu_transcoder),
-  TRANS_PUSH_EN);
+   if (!crtc_state->vrr.fixed_rr)
+   intel_de_write(dev_priv, TRANS_PUSH(dev_priv, cpu_transcoder),
+  TRANS_PUSH_EN);
 
if (HAS_AS_SDP(dev_priv))
intel_de_write(dev_priv,
-- 
2.40.1



[PATCH 8/9] drm/i915/hdmi: Use VRR Timing generator for HDMI

2024-06-23 Thread Ankit Nautiyal
Add support for using VRR Timing generator for HDMI panels.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_hdmi.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c 
b/drivers/gpu/drm/i915/display/intel_hdmi.c
index 19498ee455fa..c8442772bacf 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -59,6 +59,7 @@
 #include "intel_lspcon.h"
 #include "intel_panel.h"
 #include "intel_snps_phy.h"
+#include "intel_vrr.h"
 
 inline struct drm_i915_private *intel_hdmi_to_i915(struct intel_hdmi 
*intel_hdmi)
 {
@@ -2366,6 +2367,8 @@ int intel_hdmi_compute_config(struct intel_encoder 
*encoder,
}
}
 
+   intel_vrr_compute_config(pipe_config, conn_state);
+
intel_hdmi_compute_gcp_infoframe(encoder, pipe_config,
 conn_state);
 
-- 
2.40.1



[PATCH 7/9] drm/i915/vrr: Handle joiner with vrr

2024-06-23 Thread Ankit Nautiyal
Do not program transcoder registers for VRR for the secondary pipe of
the joiner. Remove check to skip VRR for joiner case.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_vrr.c | 19 ---
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c 
b/drivers/gpu/drm/i915/display/intel_vrr.c
index ae9bea854282..025063098370 100644
--- a/drivers/gpu/drm/i915/display/intel_vrr.c
+++ b/drivers/gpu/drm/i915/display/intel_vrr.c
@@ -171,13 +171,6 @@ intel_vrr_compute_config(struct intel_crtc_state 
*crtc_state,
const struct drm_display_info *info = >base.display_info;
int vmin, vmax;
 
-   /*
-* FIXME all joined pipes share the same transcoder.
-* Need to account for that during VRR toggle/push/etc.
-*/
-   if (crtc_state->joiner_pipes)
-   return;
-
if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
return;
 
@@ -274,6 +267,9 @@ void intel_vrr_set_transcoder_timings(const struct 
intel_crtc_state *crtc_state)
struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
 
+   if (intel_crtc_is_joiner_secondary(crtc_state))
+   return;
+
/*
 * This bit seems to have two meanings depending on the platform:
 * TGL: generate VRR "safe window" for DSB vblank waits
@@ -316,6 +312,9 @@ void intel_vrr_send_push(const struct intel_crtc_state 
*crtc_state)
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
 
+   if (intel_crtc_is_joiner_secondary(crtc_state))
+   return;
+
if (!crtc_state->vrr.enable || crtc_state->vrr.fixed_rr)
return;
 
@@ -340,6 +339,9 @@ void intel_vrr_enable(const struct intel_crtc_state 
*crtc_state)
struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
 
+   if (intel_crtc_is_joiner_secondary(crtc_state))
+   return;
+
if (!crtc_state->vrr.enable)
return;
 
@@ -369,6 +371,9 @@ void intel_vrr_disable(const struct intel_crtc_state 
*old_crtc_state)
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder;
 
+   if (intel_crtc_is_joiner_secondary(old_crtc_state))
+   return;
+
if (!old_crtc_state->vrr.enable)
return;
 
-- 
2.40.1



[PATCH 3/9] drm/i915/display: Add member fixed_rr to denote Fixed refresh rate with VRRTG

2024-06-23 Thread Ankit Nautiyal
Add fixed_rr member to struct vrr to represent the case where a
fixed refresh rate with VRR timing generator is required.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_display.c   | 4 +++-
 drivers/gpu/drm/i915/display/intel_display_types.h | 2 +-
 drivers/gpu/drm/i915/display/intel_vrr.c   | 3 +++
 3 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 60d383c9002e..17d3ecd72f47 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -1003,7 +1003,8 @@ static bool vrr_params_changed(const struct 
intel_crtc_state *old_crtc_state,
old_crtc_state->vrr.vmin != new_crtc_state->vrr.vmin ||
old_crtc_state->vrr.vmax != new_crtc_state->vrr.vmax ||
old_crtc_state->vrr.guardband != new_crtc_state->vrr.guardband 
||
-   old_crtc_state->vrr.pipeline_full != 
new_crtc_state->vrr.pipeline_full;
+   old_crtc_state->vrr.pipeline_full != 
new_crtc_state->vrr.pipeline_full ||
+   old_crtc_state->vrr.fixed_rr != new_crtc_state->vrr.fixed_rr;
 }
 
 static bool cmrr_params_changed(const struct intel_crtc_state *old_crtc_state,
@@ -5468,6 +5469,7 @@ intel_pipe_config_compare(const struct intel_crtc_state 
*current_config,
 
if (!fastset) {
PIPE_CONF_CHECK_BOOL(vrr.enable);
+   PIPE_CONF_CHECK_BOOL(vrr.fixed_rr);
PIPE_CONF_CHECK_I(vrr.vmin);
PIPE_CONF_CHECK_I(vrr.vmax);
PIPE_CONF_CHECK_I(vrr.flipline);
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index 8fe7942511f8..8515c715440e 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1402,7 +1402,7 @@ struct intel_crtc_state {
 
/* Variable Refresh Rate state */
struct {
-   bool enable, in_range;
+   bool enable, in_range, fixed_rr;
u8 pipeline_full;
u16 flipline, vmin, vmax, guardband;
u32 vsync_end, vsync_start;
diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c 
b/drivers/gpu/drm/i915/display/intel_vrr.c
index 6430da25957d..6736e8a44faa 100644
--- a/drivers/gpu/drm/i915/display/intel_vrr.c
+++ b/drivers/gpu/drm/i915/display/intel_vrr.c
@@ -421,6 +421,9 @@ void intel_vrr_get_config(struct intel_crtc_state 
*crtc_state)
 TRANS_VRR_VMAX(dev_priv, 
cpu_transcoder)) + 1;
crtc_state->vrr.vmin = intel_de_read(dev_priv,
 TRANS_VRR_VMIN(dev_priv, 
cpu_transcoder)) + 1;
+   if (crtc_state->vrr.vmax == crtc_state->vrr.flipline &&
+   crtc_state->vrr.vmin == crtc_state->vrr.flipline)
+   crtc_state->vrr.fixed_rr = true;
}
 
if (crtc_state->vrr.enable) {
-- 
2.40.1



[PATCH 6/9] drm/i915/vrr: Compute vrr vsync if platforms support it

2024-06-23 Thread Ankit Nautiyal
Previously, TRANS_VRR_VSYNC was exclusively used for panels with
adaptive-sync SDP support in VRR scenarios. However, to drive fixed refresh
rates using the VRR Timing generator, we now need to program
TRANS_VRR_VSYNC regardless of adaptive sync SDP support. Therefore, let's
remove the adaptive sync SDP check and program TRANS_VRR_VSYNC for
platforms where VRR timing generator is used.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_vrr.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c 
b/drivers/gpu/drm/i915/display/intel_vrr.c
index a771706d80df..ae9bea854282 100644
--- a/drivers/gpu/drm/i915/display/intel_vrr.c
+++ b/drivers/gpu/drm/i915/display/intel_vrr.c
@@ -233,8 +233,7 @@ intel_vrr_compute_config(struct intel_crtc_state 
*crtc_state,
crtc_state->mode_flags |= I915_MODE_FLAG_VRR;
}
 
-   if (intel_dp_as_sdp_supported(intel_dp) &&
-   crtc_state->vrr.enable) {
+   if (HAS_AS_SDP(i915) && crtc_state->vrr.enable) {
crtc_state->vrr.vsync_start =
(crtc_state->hw.adjusted_mode.crtc_vtotal -
 crtc_state->hw.adjusted_mode.vsync_start);
-- 
2.40.1



[PATCH 4/9] drm/i915/dp: Set FAVT mode in DP SDP with fixed refresh rate

2024-06-23 Thread Ankit Nautiyal
While running with fixed refresh rate and VRR timing generator set FAVT
mode (Fixed Vtotal) in DP Adaptive Sync SDP to intimate the panel
about Fixed refresh rate.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 3f46e13bb7b8..dcb94526cf00 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2642,6 +2642,10 @@ static void intel_dp_compute_as_sdp(struct intel_dp 
*intel_dp,
as_sdp->target_rr = drm_mode_vrefresh(adjusted_mode);
as_sdp->target_rr_divider = true;
} else {
+   if (crtc_state->vrr.fixed_rr)
+   as_sdp->mode = DP_AS_SDP_AVT_FIXED_VTOTAL;
+   else
+   as_sdp->mode = DP_AS_SDP_AVT_DYNAMIC_VTOTAL;
as_sdp->mode = DP_AS_SDP_AVT_DYNAMIC_VTOTAL;
as_sdp->vtotal = adjusted_mode->vtotal;
as_sdp->target_rr = 0;
-- 
2.40.1



[PATCH 2/9] drm/i915/display: Get VRR compute config before get_transcoder_timing

2024-06-23 Thread Ankit Nautiyal
For fixed refresh rate with VRR framework, we need to fill
adjusted_mode->crtc_vtotal from VMAX register in intel_vrr_get_config,
that can be used in intel_get_transcoder_timings.

Call intel_vrr_get_config before intel_get_transcoder_timings.
Subsequent changes will move filling of crtc_vtotal in vrr compute
config step.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_display.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index c782e65a7123..60d383c9002e 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -3843,13 +3843,13 @@ static bool hsw_get_pipe_config(struct intel_crtc *crtc,
intel_joiner_get_config(pipe_config);
intel_dsc_get_config(pipe_config);
 
+   if (HAS_VRR(dev_priv) && 
!transcoder_is_dsi(pipe_config->cpu_transcoder))
+   intel_vrr_get_config(pipe_config);
+
if (!transcoder_is_dsi(pipe_config->cpu_transcoder) ||
DISPLAY_VER(dev_priv) >= 11)
intel_get_transcoder_timings(crtc, pipe_config);
 
-   if (HAS_VRR(dev_priv) && 
!transcoder_is_dsi(pipe_config->cpu_transcoder))
-   intel_vrr_get_config(pipe_config);
-
intel_get_pipe_src_size(crtc, pipe_config);
 
if (IS_HASWELL(dev_priv)) {
-- 
2.40.1



[PATCH 1/9] drm/i915/dp: fix the Adaptive sync Operation mode for SDP

2024-06-23 Thread Ankit Nautiyal
Currently we support Adaptive sync operation mode with dynamic frame
rate, but instead the operation mode with fixed rate is set.
This was initially set correctly in the earlier version of changes but
later got changed, while defining a macro for the same.

Fixes: a5bd5991cb8a ("drm/i915/display: Compute AS SDP parameters")
Cc: Mitul Golani 
Cc: Ankit Nautiyal 
Cc: Jani Nikula 

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 3903f6ead6e6..3f46e13bb7b8 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2631,7 +2631,6 @@ static void intel_dp_compute_as_sdp(struct intel_dp 
*intel_dp,
 
crtc_state->infoframes.enable |= 
intel_hdmi_infoframe_enable(DP_SDP_ADAPTIVE_SYNC);
 
-   /* Currently only DP_AS_SDP_AVT_FIXED_VTOTAL mode supported */
as_sdp->sdp_type = DP_SDP_ADAPTIVE_SYNC;
as_sdp->length = 0x9;
as_sdp->duration_incr_ms = 0;
@@ -2643,7 +2642,7 @@ static void intel_dp_compute_as_sdp(struct intel_dp 
*intel_dp,
as_sdp->target_rr = drm_mode_vrefresh(adjusted_mode);
as_sdp->target_rr_divider = true;
} else {
-   as_sdp->mode = DP_AS_SDP_AVT_FIXED_VTOTAL;
+   as_sdp->mode = DP_AS_SDP_AVT_DYNAMIC_VTOTAL;
as_sdp->vtotal = adjusted_mode->vtotal;
as_sdp->target_rr = 0;
}
-- 
2.40.1



[PATCH 0/9] Use VRR timing generator for fixed refresh rate modes

2024-06-23 Thread Ankit Nautiyal
Even though the VRR timing generator (TG) is primarily used for
variable refresh rates, it can be used for fixed refresh rates as
well. For a fixed refresh rate the Flip Line and Vmax must be equal
(TRANS_VRR_FLIPLINE = TRANS_VRR_VMAX). Beyond that, there are some
dependencies between the VRR timings and the legacy timing generator
registgers.

This series is an attempt to use VRR TG for fixed refresh rate.
For platforms MTL+, always go with VRR timing generator for both fixed and
variable refresh rate cases. There are still few cases that need plumbing
like having PSR/PSR2 with VRR timing generator.

Rev2:
-Added support from MTL+ and for HDMI too.
-Changed VRR VSYNC programming which is required for HDMI.
-Modified vrr compute config for bigjoiner case. (Still to be tested).

Ankit Nautiyal (9):
  drm/i915/dp: fix the Adaptive sync Operation mode for SDP
  drm/i915/display: Get VRR compute config before get_transcoder_timing
  drm/i915/display: Add member fixed_rr to denote Fixed refresh rate
with VRRTG
  drm/i915/dp: Set FAVT mode in DP SDP with fixed refresh rate
  drm/i915/vrr: Avoid sending PUSH when VRR TG is used with Fixed
refresh rate
  drm/i915/vrr: Compute vrr vsync if platforms support it
  drm/i915/vrr: Handle joiner with vrr
  drm/i915/hdmi: Use VRR Timing generator for HDMI
  drm/i915/vrr: Use VRR timing generator whenever panel supports VRR

 drivers/gpu/drm/i915/display/intel_display.c  | 10 +-
 .../drm/i915/display/intel_display_types.h|  2 +-
 drivers/gpu/drm/i915/display/intel_dp.c   |  7 +-
 drivers/gpu/drm/i915/display/intel_hdmi.c |  3 +
 drivers/gpu/drm/i915/display/intel_vrr.c  | 93 ---
 5 files changed, 73 insertions(+), 42 deletions(-)

-- 
2.40.1



[PATCH 4/5] drm/i915/vrr: Avoid sending PUSH when VRR TG is used with Fixed refresh rate

2024-06-03 Thread Ankit Nautiyal
As per Bspec:68925: Push enable must be set if not configuring for a
fixed refresh rate (i.e Vmin == Flipline == Vmax is not true).

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_vrr.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c 
b/drivers/gpu/drm/i915/display/intel_vrr.c
index 1a9e10fb396d..406838df2d7a 100644
--- a/drivers/gpu/drm/i915/display/intel_vrr.c
+++ b/drivers/gpu/drm/i915/display/intel_vrr.c
@@ -234,7 +234,7 @@ void intel_vrr_send_push(const struct intel_crtc_state 
*crtc_state)
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
 
-   if (!crtc_state->vrr.enable)
+   if (!crtc_state->vrr.enable || crtc_state->vrr.fixed_rr)
return;
 
intel_de_write(dev_priv, TRANS_PUSH(dev_priv, cpu_transcoder),
@@ -247,7 +247,7 @@ bool intel_vrr_is_push_sent(const struct intel_crtc_state 
*crtc_state)
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
 
-   if (!crtc_state->vrr.enable)
+   if (!crtc_state->vrr.enable || crtc_state->vrr.fixed_rr)
return false;
 
return intel_de_read(dev_priv, TRANS_PUSH(dev_priv, cpu_transcoder)) & 
TRANS_PUSH_SEND;
@@ -261,8 +261,9 @@ void intel_vrr_enable(const struct intel_crtc_state 
*crtc_state)
if (!crtc_state->vrr.enable)
return;
 
-   intel_de_write(dev_priv, TRANS_PUSH(dev_priv, cpu_transcoder),
-  TRANS_PUSH_EN);
+   if (!crtc_state->vrr.fixed_rr)
+   intel_de_write(dev_priv, TRANS_PUSH(dev_priv, cpu_transcoder),
+  TRANS_PUSH_EN);
 
if (HAS_AS_SDP(dev_priv))
intel_de_write(dev_priv,
-- 
2.40.1



[PATCH 5/5] drm/i915/vrr/xe2lpd: Use VRR timing generator whenever panel supports VRR

2024-06-03 Thread Ankit Nautiyal
Currently VRR timing generator is used only when VRR is enabled by
userspace. From XE2LPD, gradually move away from older timing
generator and use VRR timing generator if panel supports VRR but
VRR is not enabled by the userspace.
In such a case, Flipline VMin and VMax all are set to the Vtotal of the
mode, which effectively makes the VRR timing generator work in
fixed refresh rate mode.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_vrr.c | 47 +++-
 1 file changed, 30 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c 
b/drivers/gpu/drm/i915/display/intel_vrr.c
index 406838df2d7a..5d281f3c9fe4 100644
--- a/drivers/gpu/drm/i915/display/intel_vrr.c
+++ b/drivers/gpu/drm/i915/display/intel_vrr.c
@@ -137,26 +137,39 @@ intel_vrr_compute_config(struct intel_crtc_state 
*crtc_state,
if (HAS_LRR(i915))
crtc_state->update_lrr = true;
 
-   vmin = DIV_ROUND_UP(adjusted_mode->crtc_clock * 1000,
-   adjusted_mode->crtc_htotal * 
info->monitor_range.max_vfreq);
-   vmax = adjusted_mode->crtc_clock * 1000 /
-   (adjusted_mode->crtc_htotal * info->monitor_range.min_vfreq);
+   if (!crtc_state->uapi.vrr_enabled && DISPLAY_VER(i915) >= 20) {
+   /*
+* for LNL+ if panel supports VRR and user has not set VRR,
+* always go for fixed average Vtotal mode.
+*/
+   crtc_state->vrr.vmin = adjusted_mode->crtc_vtotal;
+   crtc_state->vrr.vmax = adjusted_mode->crtc_vtotal;
+   crtc_state->vrr.flipline = adjusted_mode->crtc_vtotal;
+   crtc_state->vrr.fixed_rr = true;
+   } else {
 
-   vmin = max_t(int, vmin, adjusted_mode->crtc_vtotal);
-   vmax = max_t(int, vmax, adjusted_mode->crtc_vtotal);
+   vmin = DIV_ROUND_UP(adjusted_mode->crtc_clock * 1000,
+   adjusted_mode->crtc_htotal * 
info->monitor_range.max_vfreq);
+   vmax = adjusted_mode->crtc_clock * 1000 /
+   (adjusted_mode->crtc_htotal * 
info->monitor_range.min_vfreq);
 
-   if (vmin >= vmax)
-   return;
+   vmin = max_t(int, vmin, adjusted_mode->crtc_vtotal);
+   vmax = max_t(int, vmax, adjusted_mode->crtc_vtotal);
 
-   /*
-* flipline determines the min vblank length the hardware will
-* generate, and flipline>=vmin+1, hence we reduce vmin by one
-* to make sure we can get the actual min vblank length.
-*/
-   crtc_state->vrr.vmin = vmin - 1;
-   crtc_state->vrr.vmax = vmax;
+   if (vmin >= vmax)
+   return;
+
+   /*
+* flipline determines the min vblank length the hardware will
+* generate, and flipline>=vmin+1, hence we reduce vmin by one
+* to make sure we can get the actual min vblank length.
+*/
+   crtc_state->vrr.vmin = vmin - 1;
+   crtc_state->vrr.vmax = vmax;
 
-   crtc_state->vrr.flipline = crtc_state->vrr.vmin + 1;
+   crtc_state->vrr.flipline = crtc_state->vrr.vmin + 1;
+   crtc_state->vrr.fixed_rr = false;
+   }
 
/*
 * For XE_LPD+, we use guardband and pipeline override
@@ -171,7 +184,7 @@ intel_vrr_compute_config(struct intel_crtc_state 
*crtc_state,
crtc_state->framestart_delay - 1);
}
 
-   if (crtc_state->uapi.vrr_enabled) {
+   if (crtc_state->uapi.vrr_enabled || crtc_state->vrr.fixed_rr) {
crtc_state->vrr.enable = true;
crtc_state->mode_flags |= I915_MODE_FLAG_VRR;
if (intel_dp_as_sdp_supported(intel_dp)) {
-- 
2.40.1



[PATCH 3/5] drm/i915/dp: Set FAVT mode in DP SDP with fixed refresh rate

2024-06-03 Thread Ankit Nautiyal
While running with fixed refresh rate and VRR timing generator set FAVT
mode (Fixed Vtotal) in DP Adaptive Sync SDP to intimate the panel
about Fixed refresh rate.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index f33b2da1b084..8b362b20bc8d 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2634,10 +2634,12 @@ static void intel_dp_compute_as_sdp(struct intel_dp 
*intel_dp,
 
crtc_state->infoframes.enable |= 
intel_hdmi_infoframe_enable(DP_SDP_ADAPTIVE_SYNC);
 
-   /* Currently only DP_AS_SDP_AVT_DYNAMIC_VTOTAL mode supported */
as_sdp->sdp_type = DP_SDP_ADAPTIVE_SYNC;
as_sdp->length = 0x9;
-   as_sdp->mode = DP_AS_SDP_AVT_DYNAMIC_VTOTAL;
+   if (crtc_state->vrr.fixed_rr)
+   as_sdp->mode = DP_AS_SDP_AVT_FIXED_VTOTAL;
+   else
+   as_sdp->mode = DP_AS_SDP_AVT_DYNAMIC_VTOTAL;
as_sdp->vtotal = adjusted_mode->vtotal;
as_sdp->target_rr = 0;
as_sdp->duration_incr_ms = 0;
-- 
2.40.1



[PATCH 2/5] drm/i915/display: Add member fixed_rr to denote Fixed refresh rate with VRRTG

2024-06-03 Thread Ankit Nautiyal
Add fixed_rr member to struct vrr to represent the case where a
fixed refresh rate with VRR timing generator is required.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_display.c   | 4 +++-
 drivers/gpu/drm/i915/display/intel_display_types.h | 2 +-
 drivers/gpu/drm/i915/display/intel_vrr.c   | 3 +++
 3 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 7370acdd6b8b..8b3885ef9c85 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -1002,7 +1002,8 @@ static bool vrr_params_changed(const struct 
intel_crtc_state *old_crtc_state,
old_crtc_state->vrr.vmin != new_crtc_state->vrr.vmin ||
old_crtc_state->vrr.vmax != new_crtc_state->vrr.vmax ||
old_crtc_state->vrr.guardband != new_crtc_state->vrr.guardband 
||
-   old_crtc_state->vrr.pipeline_full != 
new_crtc_state->vrr.pipeline_full;
+   old_crtc_state->vrr.pipeline_full != 
new_crtc_state->vrr.pipeline_full ||
+   old_crtc_state->vrr.fixed_rr != new_crtc_state->vrr.fixed_rr;
 }
 
 static bool vrr_enabling(const struct intel_crtc_state *old_crtc_state,
@@ -5425,6 +5426,7 @@ intel_pipe_config_compare(const struct intel_crtc_state 
*current_config,
 
if (!fastset) {
PIPE_CONF_CHECK_BOOL(vrr.enable);
+   PIPE_CONF_CHECK_BOOL(vrr.fixed_rr);
PIPE_CONF_CHECK_I(vrr.vmin);
PIPE_CONF_CHECK_I(vrr.vmax);
PIPE_CONF_CHECK_I(vrr.flipline);
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index 77609656317b..eb9061253a4d 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1395,7 +1395,7 @@ struct intel_crtc_state {
 
/* Variable Refresh Rate state */
struct {
-   bool enable, in_range;
+   bool enable, in_range, fixed_rr;
u8 pipeline_full;
u16 flipline, vmin, vmax, guardband;
u32 vsync_end, vsync_start;
diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c 
b/drivers/gpu/drm/i915/display/intel_vrr.c
index 5f3657aa8313..1a9e10fb396d 100644
--- a/drivers/gpu/drm/i915/display/intel_vrr.c
+++ b/drivers/gpu/drm/i915/display/intel_vrr.c
@@ -321,6 +321,9 @@ void intel_vrr_get_config(struct intel_crtc_state 
*crtc_state)
 TRANS_VRR_VMAX(dev_priv, 
cpu_transcoder)) + 1;
crtc_state->vrr.vmin = intel_de_read(dev_priv,
 TRANS_VRR_VMIN(dev_priv, 
cpu_transcoder)) + 1;
+   if (crtc_state->vrr.vmax == crtc_state->vrr.flipline &&
+   crtc_state->vrr.vmin == crtc_state->vrr.flipline)
+   crtc_state->vrr.fixed_rr = true;
}
 
if (crtc_state->vrr.enable) {
-- 
2.40.1



[PATCH 1/5] drm/i915/dp: fix the Adaptive sync Operation mode for SDP

2024-06-03 Thread Ankit Nautiyal
Currently we support Adaptive sync operation mode with dynamic frame
rate, but instead the operation mode with fixed rate is set.
This was initially set correctly in the earlier version of changes but
later got changed, while defining a macro for the same.

Fixes: a5bd5991cb8a ("drm/i915/display: Compute AS SDP parameters")
Cc: Mitul Golani 
Cc: Ankit Nautiyal 
Cc: Jani Nikula 

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index fd054e16850d..f33b2da1b084 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2634,10 +2634,10 @@ static void intel_dp_compute_as_sdp(struct intel_dp 
*intel_dp,
 
crtc_state->infoframes.enable |= 
intel_hdmi_infoframe_enable(DP_SDP_ADAPTIVE_SYNC);
 
-   /* Currently only DP_AS_SDP_AVT_FIXED_VTOTAL mode supported */
+   /* Currently only DP_AS_SDP_AVT_DYNAMIC_VTOTAL mode supported */
as_sdp->sdp_type = DP_SDP_ADAPTIVE_SYNC;
as_sdp->length = 0x9;
-   as_sdp->mode = DP_AS_SDP_AVT_FIXED_VTOTAL;
+   as_sdp->mode = DP_AS_SDP_AVT_DYNAMIC_VTOTAL;
as_sdp->vtotal = adjusted_mode->vtotal;
as_sdp->target_rr = 0;
as_sdp->duration_incr_ms = 0;
-- 
2.40.1



[PATCH 0/5] Use VRR timing generator for fixed refresh rate modes

2024-06-03 Thread Ankit Nautiyal
Even though the VRR timing generator (TG) is primarily used for
variable refresh rates, it can be used for fixed refresh rates as
well. For a fixed refresh rate the Flip Line and Vmax must be equal
(TRANS_VRR_FLIPLINE = TRANS_VRR_VMAX). Beyond that, there are some
dependencies between the VRR timings and the legacy timing generator
registgers.

This series is an attempt to use VRR TG for fixed refresh rate.
Currently the support to use VRR timing generator for fixed refresh
rate is added from LNL+ and only for panels that support VRR, however
this can be used for older platforms also and used with panels that do
not support VRR, which will be added subsequently.
There are still few cases that need plumbing like having PSR/PSR2 with
VRR timing generator and bigjoiner + VRR.

Ankit Nautiyal (5):
  drm/i915/dp: fix the Adaptive sync Operation mode for SDP
  drm/i915/display: Add member fixed_rr to denote Fixed refresh rate
with VRRTG
  drm/i915/dp: Set FAVT mode in DP SDP with fixed refresh rate
  drm/i915/vrr: Avoid sending PUSH when VRR TG is used with Fixed
refresh rate
  drm/i915/vrr/xe2lpd: Use VRR timing generator whenever panel supports
VRR

 drivers/gpu/drm/i915/display/intel_display.c  |  4 +-
 .../drm/i915/display/intel_display_types.h|  2 +-
 drivers/gpu/drm/i915/display/intel_dp.c   |  6 +-
 drivers/gpu/drm/i915/display/intel_vrr.c  | 59 ---
 4 files changed, 46 insertions(+), 25 deletions(-)

-- 
2.40.1



[PATCH v2 3/3] drm/915/lspcon: Reduce dmesg errors during lspcon_init failure

2024-04-09 Thread Ankit Nautiyal
Currently lspcon_resume calls lspcon_init and in case of failure we get
error messages from lspcon_init and then again from lspcon_resume.

Just have a single error message in lspcon_init.

v2: Add the relavant info with each error, and avoid mix of dbg and
error messages. (Jani)

Signed-off-by: Ankit Nautiyal 
Reviewed-by: Jani Nikula 
---
 drivers/gpu/drm/i915/display/intel_lspcon.c | 19 +--
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c 
b/drivers/gpu/drm/i915/display/intel_lspcon.c
index 16ee0dc179f7..84d953496098 100644
--- a/drivers/gpu/drm/i915/display/intel_lspcon.c
+++ b/drivers/gpu/drm/i915/display/intel_lspcon.c
@@ -680,23 +680,27 @@ bool lspcon_init(struct intel_digital_port *dig_port)
return false;
 
if (!lspcon_set_pcon_mode(lspcon)) {
-   drm_err(>drm, "LSPCON mode change to PCON failed\n");
+   drm_err(>drm, "Failure: LSPCON init on port %c, mode 
change to PCON failed\n",
+   port_name(dig_port->base.port));
return false;
}
 
if (drm_dp_read_dpcd_caps(_dp->aux, intel_dp->dpcd) != 0) {
-   drm_err(>drm, "LSPCON DPCD read failed\n");
+   drm_err(>drm, "Failure: LSPCON init on port %c, DPCD caps 
read failed\n",
+   port_name(dig_port->base.port));
return false;
}
 
if (!lspcon_detect_vendor(lspcon)) {
-   drm_err(>drm, "LSPCON vendor detection failed\n");
+   drm_err(>drm, "Failure: LSPCON init on port %c, vendor 
detection failed\n",
+   port_name(dig_port->base.port));
return false;
}
 
connector->ycbcr_420_allowed = true;
lspcon->active = true;
drm_dbg_kms(>drm, "Success: LSPCON init\n");
+
return true;
 }
 
@@ -718,13 +722,8 @@ void lspcon_resume(struct intel_digital_port *dig_port)
if (!intel_bios_encoder_is_lspcon(dig_port->base.devdata))
return;
 
-   if (!lspcon->active) {
-   if (!lspcon_init(dig_port)) {
-   drm_err(>drm, "LSPCON init failed on port %c\n",
-   port_name(dig_port->base.port));
-   return;
-   }
-   }
+   if (!lspcon->active && !lspcon_init(dig_port))
+   return;
 
expected_mode = lspcon_get_expected_mode(lspcon);
if (expected_mode == DRM_LSPCON_MODE_PCON)
-- 
2.40.1



[PATCH v2 3/3] drm/915/lspcon: Reduce dmesg errors during lspcon_init failure

2024-04-08 Thread Ankit Nautiyal
Currently lspcon_resume calls lspcon_init and in case of failure we get
error messages from lspcon_init and then again from lspcon_resume.

Just have a single error message in lspcon_init.

v2: Add the relavant info with each error, and avoid mix of dbg and
error messages. (Jani)

Signed-off-by: Ankit Nautiyal 
Reviewed-by: Jani Nikula 
---
 drivers/gpu/drm/i915/display/intel_lspcon.c | 19 +--
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c 
b/drivers/gpu/drm/i915/display/intel_lspcon.c
index 16ee0dc179f7..84d953496098 100644
--- a/drivers/gpu/drm/i915/display/intel_lspcon.c
+++ b/drivers/gpu/drm/i915/display/intel_lspcon.c
@@ -680,23 +680,27 @@ bool lspcon_init(struct intel_digital_port *dig_port)
return false;
 
if (!lspcon_set_pcon_mode(lspcon)) {
-   drm_err(>drm, "LSPCON mode change to PCON failed\n");
+   drm_err(>drm, "Failure: LSPCON init on port %c, mode 
change to PCON failed\n",
+   port_name(dig_port->base.port));
return false;
}
 
if (drm_dp_read_dpcd_caps(_dp->aux, intel_dp->dpcd) != 0) {
-   drm_err(>drm, "LSPCON DPCD read failed\n");
+   drm_err(>drm, "Failure: LSPCON init on port %c, DPCD caps 
read failed\n",
+   port_name(dig_port->base.port));
return false;
}
 
if (!lspcon_detect_vendor(lspcon)) {
-   drm_err(>drm, "LSPCON vendor detection failed\n");
+   drm_err(>drm, "Failure: LSPCON init on port %c, vendor 
detection failed\n",
+   port_name(dig_port->base.port));
return false;
}
 
connector->ycbcr_420_allowed = true;
lspcon->active = true;
drm_dbg_kms(>drm, "Success: LSPCON init\n");
+
return true;
 }
 
@@ -718,13 +722,8 @@ void lspcon_resume(struct intel_digital_port *dig_port)
if (!intel_bios_encoder_is_lspcon(dig_port->base.devdata))
return;
 
-   if (!lspcon->active) {
-   if (!lspcon_init(dig_port)) {
-   drm_err(>drm, "LSPCON init failed on port %c\n",
-   port_name(dig_port->base.port));
-   return;
-   }
-   }
+   if (!lspcon->active && !lspcon_init(dig_port))
+   return;
 
expected_mode = lspcon_get_expected_mode(lspcon);
if (expected_mode == DRM_LSPCON_MODE_PCON)
-- 
2.40.1



[PATCH 1/3] drm/i915/lspcon: Separate out function to get expected mode

2024-04-07 Thread Ankit Nautiyal
Reuse code to wake native aux channel and get the expected lspcon
mode.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_lspcon.c | 18 ++
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c 
b/drivers/gpu/drm/i915/display/intel_lspcon.c
index 1d048fa98561..36e8d9fb2bbb 100644
--- a/drivers/gpu/drm/i915/display/intel_lspcon.c
+++ b/drivers/gpu/drm/i915/display/intel_lspcon.c
@@ -240,6 +240,13 @@ static bool lspcon_wake_native_aux_ch(struct intel_lspcon 
*lspcon)
return true;
 }
 
+static
+enum drm_lspcon_mode lspcon_get_expected_mode(struct intel_lspcon *lspcon)
+{
+   return lspcon_wake_native_aux_ch(lspcon) ?
+   DRM_LSPCON_MODE_PCON : DRM_LSPCON_MODE_LS;
+}
+
 static bool lspcon_probe(struct intel_lspcon *lspcon)
 {
int retry;
@@ -249,9 +256,7 @@ static bool lspcon_probe(struct intel_lspcon *lspcon)
struct i2c_adapter *ddc = _dp->aux.ddc;
enum drm_lspcon_mode expected_mode;
 
-   expected_mode = lspcon_wake_native_aux_ch(lspcon) ?
-   DRM_LSPCON_MODE_PCON : DRM_LSPCON_MODE_LS;
-
+   expected_mode = lspcon_get_expected_mode(lspcon);
/* Lets probe the adaptor and check its type */
for (retry = 0; retry < 6; retry++) {
if (retry)
@@ -713,12 +718,9 @@ void lspcon_resume(struct intel_digital_port *dig_port)
}
}
 
-   if (lspcon_wake_native_aux_ch(lspcon)) {
-   expected_mode = DRM_LSPCON_MODE_PCON;
+   expected_mode = lspcon_get_expected_mode(lspcon);
+   if (expected_mode == DRM_LSPCON_MODE_PCON)
lspcon_resume_in_pcon_wa(lspcon);
-   } else {
-   expected_mode = DRM_LSPCON_MODE_LS;
-   }
 
if (lspcon_wait_mode(lspcon, expected_mode) == DRM_LSPCON_MODE_PCON)
return;
-- 
2.40.1



[PATCH 3/3] drm/915/lspcon: Reduce dmesg errors during lspcon_init failure

2024-04-07 Thread Ankit Nautiyal
Currently lspcon_resume calls lspcon_init and in case of failure we get
error messages from lspcon_init and then again from lspcon_resume.

Just have a single error message in lspcon_init and convert all other
errors as dbg messages.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_lspcon.c | 27 +++--
 1 file changed, 14 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c 
b/drivers/gpu/drm/i915/display/intel_lspcon.c
index 16ee0dc179f7..3c3bc80e32f0 100644
--- a/drivers/gpu/drm/i915/display/intel_lspcon.c
+++ b/drivers/gpu/drm/i915/display/intel_lspcon.c
@@ -680,24 +680,30 @@ bool lspcon_init(struct intel_digital_port *dig_port)
return false;
 
if (!lspcon_set_pcon_mode(lspcon)) {
-   drm_err(>drm, "LSPCON mode change to PCON failed\n");
-   return false;
+   drm_dbg_kms(>drm, "LSPCON mode change to PCON failed\n");
+   goto lspcon_init_failed;
}
 
if (drm_dp_read_dpcd_caps(_dp->aux, intel_dp->dpcd) != 0) {
-   drm_err(>drm, "LSPCON DPCD read failed\n");
-   return false;
+   drm_dbg_kms(>drm, "LSPCON DPCD read failed\n");
+   goto lspcon_init_failed;
}
 
if (!lspcon_detect_vendor(lspcon)) {
-   drm_err(>drm, "LSPCON vendor detection failed\n");
-   return false;
+   drm_dbg_kms(>drm, "LSPCON vendor detection failed\n");
+   goto lspcon_init_failed;
}
 
connector->ycbcr_420_allowed = true;
lspcon->active = true;
drm_dbg_kms(>drm, "Success: LSPCON init\n");
return true;
+
+lspcon_init_failed:
+   drm_err(>drm, "LSPCON init failed on port %c\n",
+   port_name(dig_port->base.port));
+
+   return false;
 }
 
 u32 intel_lspcon_infoframes_enabled(struct intel_encoder *encoder,
@@ -718,13 +724,8 @@ void lspcon_resume(struct intel_digital_port *dig_port)
if (!intel_bios_encoder_is_lspcon(dig_port->base.devdata))
return;
 
-   if (!lspcon->active) {
-   if (!lspcon_init(dig_port)) {
-   drm_err(>drm, "LSPCON init failed on port %c\n",
-   port_name(dig_port->base.port));
-   return;
-   }
-   }
+   if (!lspcon->active && !lspcon_init(dig_port))
+   return;
 
expected_mode = lspcon_get_expected_mode(lspcon);
if (expected_mode == DRM_LSPCON_MODE_PCON)
-- 
2.40.1



[PATCH 2/3] drm/i915/lspcon: Separate out function to set pcon mode

2024-04-07 Thread Ankit Nautiyal
Currently lspcon_probe tries to probe for LSPCON and also set the
PCON mode on the LSPCON. If any of these fails, it returns fail
resulting in error message. So even if there is nothing connected to
LSPCON port we get error messages for probe failure.

Separate out the function to set pcon mode from the lspcon_probe
function, and show the error message only when the set pcon mode fails.
Do not show error message if no LSPCON is detected.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_lspcon.c | 24 ++---
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c 
b/drivers/gpu/drm/i915/display/intel_lspcon.c
index 36e8d9fb2bbb..16ee0dc179f7 100644
--- a/drivers/gpu/drm/i915/display/intel_lspcon.c
+++ b/drivers/gpu/drm/i915/display/intel_lspcon.c
@@ -277,17 +277,22 @@ static bool lspcon_probe(struct intel_lspcon *lspcon)
drm_dbg_kms(>drm, "LSPCON detected\n");
lspcon->mode = lspcon_wait_mode(lspcon, expected_mode);
 
+   return true;
+}
+
+static bool lspcon_set_pcon_mode(struct intel_lspcon *lspcon)
+{
/*
 * In the SW state machine, lets Put LSPCON in PCON mode only.
 * In this way, it will work with both HDMI 1.4 sinks as well as HDMI
 * 2.0 sinks.
 */
-   if (lspcon->mode != DRM_LSPCON_MODE_PCON) {
-   if (lspcon_change_mode(lspcon, DRM_LSPCON_MODE_PCON) < 0) {
-   drm_err(>drm, "LSPCON mode change to PCON 
failed\n");
-   return false;
-   }
-   }
+   if (lspcon->mode == DRM_LSPCON_MODE_PCON)
+   return true;
+
+   if (lspcon_change_mode(lspcon, DRM_LSPCON_MODE_PCON) < 0)
+   return false;
+
return true;
 }
 
@@ -671,8 +676,11 @@ bool lspcon_init(struct intel_digital_port *dig_port)
lspcon->active = false;
lspcon->mode = DRM_LSPCON_MODE_INVALID;
 
-   if (!lspcon_probe(lspcon)) {
-   drm_err(>drm, "Failed to probe lspcon\n");
+   if (!lspcon_probe(lspcon))
+   return false;
+
+   if (!lspcon_set_pcon_mode(lspcon)) {
+   drm_err(>drm, "LSPCON mode change to PCON failed\n");
return false;
}
 
-- 
2.40.1



[PATCH 0/3] Avoid unwanted lspcon init and probe warnings

2024-04-07 Thread Ankit Nautiyal
Currently we probe for lspcon, inside lspcon init.

If there is no lspcon connected, the probe expectedly fails and
results in error message. This inturn gets propogated to
lspcon init and we get again error message for lspcon init
failure.

Reduce the error messages from lspcon init.
Separate out some of the functions and avoid displaying error if the
probe fails.

rev2: Changed the approach from previous revision where lspcon_probe was
separated out from lspcon_init, as this was resulting in
lspcon_wake_native_aux_ch not being called before probe.
Instead, just separate out the part of lspcon_probe that can fail, to a
separate function and display the error message for it.

Ankit Nautiyal (3):
  drm/i915/lspcon: Separate out function to get expected mode
  drm/i915/lspcon: Separate out function to set pcon mode
  drm/915/lspcon: Reduce dmesg errors during lspcon_init failure

 drivers/gpu/drm/i915/display/intel_lspcon.c | 65 -
 1 file changed, 38 insertions(+), 27 deletions(-)

-- 
2.40.1



[PATCH] drm/i915/display_debugfs: Remove check for crtc in force bigjoiner

2024-03-28 Thread Ankit Nautiyal
At the moment, we allow force joiner debugs to work only for connector
with status connected and a crtc attached to it.
This creates a problem when we force bigjoiner and then pipe gets reset
before the force bigjoiner is disabled.
Relax the condition to check for crtc while exposing the debugfs.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_display_debugfs.c | 8 ++--
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c 
b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
index b99c024b0934..94bc9e0d30fe 100644
--- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
+++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
@@ -1405,10 +1405,8 @@ out: 
drm_modeset_unlock(>drm.mode_config.connection_mutex);
 static int i915_bigjoiner_enable_show(struct seq_file *m, void *data)
 {
struct intel_connector *connector = m->private;
-   struct drm_crtc *crtc;
 
-   crtc = connector->base.state->crtc;
-   if (connector->base.status != connector_status_connected || !crtc)
+   if (connector->base.status != connector_status_connected)
return -ENODEV;
 
seq_printf(m, "Bigjoiner enable: %d\n", 
connector->force_bigjoiner_enable);
@@ -1443,12 +1441,10 @@ static ssize_t i915_bigjoiner_enable_write(struct file 
*file,
 {
struct seq_file *m = file->private_data;
struct intel_connector *connector = m->private;
-   struct drm_crtc *crtc;
bool bigjoiner_en = 0;
int ret;
 
-   crtc = connector->base.state->crtc;
-   if (connector->base.status != connector_status_connected || !crtc)
+   if (connector->base.status != connector_status_connected)
return -ENODEV;
 
ret = kstrtobool_from_user(ubuf, len, _en);
-- 
2.40.1



[PATCH 2/2] drm/i915/lspcon: Separate lspcon probe and lspcon init

2024-03-22 Thread Ankit Nautiyal
Currently we probe for lspcon, inside lspcon init. Which does 2 things:
probe the lspcon and set the expected LS/PCON mode.

If there is no lspcon connected, the probe expectedly fails and
results in error message. This inturn gets propogated to
lspcon init and we get again error message for lspcon init
failure.

Separate the probe function and avoid displaying error if probe fails.
If probe succeeds, only then start lspcon init and set the expected
LS/PCON mode as first step.

While at it move the drm_err message in lspcon init, instead of the
caller.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_dp.c |  3 +++
 drivers/gpu/drm/i915/display/intel_lspcon.c | 27 +++--
 drivers/gpu/drm/i915/display/intel_lspcon.h |  1 +
 3 files changed, 18 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 94fa34f77cf0..ea8d3e70127e 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -5882,6 +5882,9 @@ intel_dp_connector_register(struct drm_connector 
*connector)
 * ToDo: Clean this up to handle lspcon init and resume more
 * efficiently and streamlined.
 */
+   if (!lspcon_probe(lspcon))
+   return ret;
+
if (lspcon_init(dig_port)) {
lspcon_detect_hdr_capability(lspcon);
if (lspcon->hdr_supported)
diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c 
b/drivers/gpu/drm/i915/display/intel_lspcon.c
index 62159d3ead56..570fde848d00 100644
--- a/drivers/gpu/drm/i915/display/intel_lspcon.c
+++ b/drivers/gpu/drm/i915/display/intel_lspcon.c
@@ -266,7 +266,7 @@ static bool lspcon_set_expected_mode(struct intel_lspcon 
*lspcon)
return true;
 }
 
-static bool lspcon_probe(struct intel_lspcon *lspcon)
+bool lspcon_probe(struct intel_lspcon *lspcon)
 {
int retry;
enum drm_dp_dual_mode_type adaptor_type;
@@ -676,30 +676,31 @@ bool lspcon_init(struct intel_digital_port *dig_port)
lspcon->active = false;
lspcon->mode = DRM_LSPCON_MODE_INVALID;
 
-   if (!lspcon_probe(lspcon)) {
-   drm_err(>drm, "Failed to probe lspcon\n");
-   return false;
-   }
-
if (!lspcon_set_expected_mode(lspcon)) {
drm_err(>drm, "LSPCON Set expected Mode failed\n");
-   return false;
+   goto lspcon_init_failed;
}
 
if (drm_dp_read_dpcd_caps(_dp->aux, intel_dp->dpcd) != 0) {
drm_err(>drm, "LSPCON DPCD read failed\n");
-   return false;
+   goto lspcon_init_failed;
}
 
if (!lspcon_detect_vendor(lspcon)) {
drm_err(>drm, "LSPCON vendor detection failed\n");
-   return false;
+   goto lspcon_init_failed;
}
 
connector->ycbcr_420_allowed = true;
lspcon->active = true;
drm_dbg_kms(>drm, "Success: LSPCON init\n");
return true;
+
+lspcon_init_failed:
+   drm_err(>drm, "LSPCON init failed on port %c\n",
+   port_name(dig_port->base.port));
+
+   return false;
 }
 
 u32 intel_lspcon_infoframes_enabled(struct intel_encoder *encoder,
@@ -721,11 +722,11 @@ void lspcon_resume(struct intel_digital_port *dig_port)
return;
 
if (!lspcon->active) {
-   if (!lspcon_init(dig_port)) {
-   drm_err(>drm, "LSPCON init failed on port %c\n",
-   port_name(dig_port->base.port));
+   if (!lspcon_probe(lspcon))
+   return;
+
+   if (!lspcon_init(dig_port))
return;
-   }
}
 
if (lspcon_wake_native_aux_ch(lspcon)) {
diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.h 
b/drivers/gpu/drm/i915/display/intel_lspcon.h
index e19e10492b05..b156cc6b3a23 100644
--- a/drivers/gpu/drm/i915/display/intel_lspcon.h
+++ b/drivers/gpu/drm/i915/display/intel_lspcon.h
@@ -16,6 +16,7 @@ struct intel_encoder;
 struct intel_lspcon;
 
 bool lspcon_init(struct intel_digital_port *dig_port);
+bool lspcon_probe(struct intel_lspcon *lspcon);
 void lspcon_detect_hdr_capability(struct intel_lspcon *lspcon);
 void lspcon_resume(struct intel_digital_port *dig_port);
 void lspcon_wait_pcon_mode(struct intel_lspcon *lspcon);
-- 
2.40.1



[PATCH 0/2] Avoid unwanted lspcon init and probe warnings

2024-03-22 Thread Ankit Nautiyal
Currently we probe for lspcon, inside lspcon init.

If there is no lspcon connected, the probe expectedly fails and
results in error message. This inturn gets propogated to
lspcon init and we get again error message for lspcon init
failure.

Separate the probe function and avoid displaying error if probe fails.
If probe succeeds, only then start lspcon init and set the expected
LS/PCON mode as first step.

Ankit Nautiyal (2):
  drm/i915/lspcon: Separate function to set expected mode
  drm/i915/lspcon: Separate lspcon probe and lspcon init

 drivers/gpu/drm/i915/display/intel_dp.c |  3 +
 drivers/gpu/drm/i915/display/intel_lspcon.c | 66 +
 drivers/gpu/drm/i915/display/intel_lspcon.h |  1 +
 3 files changed, 45 insertions(+), 25 deletions(-)

-- 
2.40.1



[PATCH 1/2] drm/i915/lspcon: Separate function to set expected mode

2024-03-22 Thread Ankit Nautiyal
LSPCON can be configured to LS or PCON mode.
Separate the function to set the expected mode from the lspcon probe
function during lspcon init.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_lspcon.c | 47 ++---
 1 file changed, 31 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c 
b/drivers/gpu/drm/i915/display/intel_lspcon.c
index 1d048fa98561..62159d3ead56 100644
--- a/drivers/gpu/drm/i915/display/intel_lspcon.c
+++ b/drivers/gpu/drm/i915/display/intel_lspcon.c
@@ -240,18 +240,40 @@ static bool lspcon_wake_native_aux_ch(struct intel_lspcon 
*lspcon)
return true;
 }
 
-static bool lspcon_probe(struct intel_lspcon *lspcon)
+static bool lspcon_set_expected_mode(struct intel_lspcon *lspcon)
 {
-   int retry;
-   enum drm_dp_dual_mode_type adaptor_type;
struct intel_dp *intel_dp = lspcon_to_intel_dp(lspcon);
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
-   struct i2c_adapter *ddc = _dp->aux.ddc;
enum drm_lspcon_mode expected_mode;
 
expected_mode = lspcon_wake_native_aux_ch(lspcon) ?
DRM_LSPCON_MODE_PCON : DRM_LSPCON_MODE_LS;
 
+   lspcon->mode = lspcon_wait_mode(lspcon, expected_mode);
+
+   /*
+* In the SW state machine, lets Put LSPCON in PCON mode only.
+* In this way, it will work with both HDMI 1.4 sinks as well as HDMI
+* 2.0 sinks.
+*/
+   if (lspcon->mode != DRM_LSPCON_MODE_PCON) {
+   if (lspcon_change_mode(lspcon, DRM_LSPCON_MODE_PCON) < 0) {
+   drm_err(>drm, "LSPCON mode change to PCON 
failed\n");
+   return false;
+   }
+   }
+
+   return true;
+}
+
+static bool lspcon_probe(struct intel_lspcon *lspcon)
+{
+   int retry;
+   enum drm_dp_dual_mode_type adaptor_type;
+   struct intel_dp *intel_dp = lspcon_to_intel_dp(lspcon);
+   struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+   struct i2c_adapter *ddc = _dp->aux.ddc;
+
/* Lets probe the adaptor and check its type */
for (retry = 0; retry < 6; retry++) {
if (retry)
@@ -270,19 +292,7 @@ static bool lspcon_probe(struct intel_lspcon *lspcon)
 
/* Yay ... got a LSPCON device */
drm_dbg_kms(>drm, "LSPCON detected\n");
-   lspcon->mode = lspcon_wait_mode(lspcon, expected_mode);
 
-   /*
-* In the SW state machine, lets Put LSPCON in PCON mode only.
-* In this way, it will work with both HDMI 1.4 sinks as well as HDMI
-* 2.0 sinks.
-*/
-   if (lspcon->mode != DRM_LSPCON_MODE_PCON) {
-   if (lspcon_change_mode(lspcon, DRM_LSPCON_MODE_PCON) < 0) {
-   drm_err(>drm, "LSPCON mode change to PCON 
failed\n");
-   return false;
-   }
-   }
return true;
 }
 
@@ -671,6 +681,11 @@ bool lspcon_init(struct intel_digital_port *dig_port)
return false;
}
 
+   if (!lspcon_set_expected_mode(lspcon)) {
+   drm_err(>drm, "LSPCON Set expected Mode failed\n");
+   return false;
+   }
+
if (drm_dp_read_dpcd_caps(_dp->aux, intel_dp->dpcd) != 0) {
drm_err(>drm, "LSPCON DPCD read failed\n");
return false;
-- 
2.40.1



[PATCH] drm/i915/scaler: Update Pipe src size check in skl_update_scaler

2024-03-13 Thread Ankit Nautiyal
For Earlier platforms, the Pipe source size is 12-bits so
max pipe source width and height is 4096. For newer platforms it is
13-bits so theoretically max width/height is 8192. For few of the
earlier platforms the scaler did not use all bits of the PIPESRC,
so max scaler source size was used to make that the pipe source
size is programmed within limits, before using scaler.

This creates a problem, for MTL where scaler source size is 4096, but
max pipe source width can theroretically be 8192.

Switch the check to use the max scaler destination size, which closely
match the limits.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/skl_scaler.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c 
b/drivers/gpu/drm/i915/display/skl_scaler.c
index 8a934bada624..baa601d27815 100644
--- a/drivers/gpu/drm/i915/display/skl_scaler.c
+++ b/drivers/gpu/drm/i915/display/skl_scaler.c
@@ -213,10 +213,11 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, 
bool force_detach,
 * The pipe scaler does not use all the bits of PIPESRC, at least
 * on the earlier platforms. So even when we're scaling a plane
 * the *pipe* source size must not be too large. For simplicity
-* we assume the limits match the scaler source size limits. Might
-* not be 100% accurate on all platforms, but good enough for now.
+* we assume the limits match the scaler destination size limits.
+* Might not be 100% accurate on all platforms, but good enough for
+* now.
 */
-   if (pipe_src_w > max_src_w || pipe_src_h > max_src_h) {
+   if (pipe_src_w > max_dst_w || pipe_src_h > max_dst_h) {
drm_dbg_kms(_priv->drm,
"scaler_user index %u.%u: pipe src size %ux%u "
"is out of scaler range\n",
-- 
2.40.1



[PATCH] drm/i915/dp: Fix the computation for compressed_bpp for DISPLAY < 13

2024-03-04 Thread Ankit Nautiyal
For DISPLAY < 13, compressed bpp is chosen from a list of
supported compressed bpps. Fix the condition to choose the
appropriate compressed bpp from the list.

Fixes: 1c56e9a39833 ("drm/i915/dp: Get optimal link config to have best 
compressed bpp")
Cc: Ankit Nautiyal 
Cc: Stanislav Lisovskiy 
Cc: Jani Nikula 
Cc:  # v6.7+
Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/10162
Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index e13121dc3a03..d579195f84ee 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1918,8 +1918,9 @@ icl_dsc_compute_link_config(struct intel_dp *intel_dp,
dsc_max_bpp = min(dsc_max_bpp, pipe_bpp - 1);
 
for (i = 0; i < ARRAY_SIZE(valid_dsc_bpp); i++) {
-   if (valid_dsc_bpp[i] < dsc_min_bpp ||
-   valid_dsc_bpp[i] > dsc_max_bpp)
+   if (valid_dsc_bpp[i] < dsc_min_bpp)
+   continue;
+   if (valid_dsc_bpp[i] > dsc_max_bpp)
break;
 
ret = dsc_compute_link_config(intel_dp,
-- 
2.40.1



[PATCH] drm/i915/scaler: Update Pipe src size check for DISPLAY_VER >= 12

2024-02-18 Thread Ankit Nautiyal
For Earlier platforms, the Pipe source size is 12-bits so
max pipe source width and height is 4096. For newer platforms it is
13-bits so theoretically max height is 8192, but maximum width
supported on a single pipe is 5120, beyond which we need to use
bigjoiner.

Currently we are using max scaler source size to make sure that the
pipe source size is programmed within limits, before using scaler.
This creates a problem, for MTL where scaler source size is 4096, but
max pipe source width can be 5120.

Update the check to use the aforementioned limits.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/skl_scaler.c | 19 +++
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c 
b/drivers/gpu/drm/i915/display/skl_scaler.c
index 8a934bada624..36342142efaa 100644
--- a/drivers/gpu/drm/i915/display/skl_scaler.c
+++ b/drivers/gpu/drm/i915/display/skl_scaler.c
@@ -115,6 +115,7 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool 
force_detach,
int pipe_src_h = drm_rect_height(_state->pipe_src);
int min_src_w, min_src_h, min_dst_w, min_dst_h;
int max_src_w, max_src_h, max_dst_w, max_dst_h;
+   int max_pipe_src_w, max_pipe_src_h;
 
/*
 * Src coordinates are already rotated by 270 degrees for
@@ -212,11 +213,21 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, 
bool force_detach,
/*
 * The pipe scaler does not use all the bits of PIPESRC, at least
 * on the earlier platforms. So even when we're scaling a plane
-* the *pipe* source size must not be too large. For simplicity
-* we assume the limits match the scaler source size limits. Might
-* not be 100% accurate on all platforms, but good enough for now.
+* the *pipe* source size must not be too large.
+*
+* For Earlier platforms, the Pipe source size is 12-bits so
+* max pipe src width and height is 4096. For newer platforms it is 
13-bits.
+* Theoretically maximum pipe src height supported on a single pipe is 
8192,
+* but maximum pipe src width supported on a single pipe is 5120.
 */
-   if (pipe_src_w > max_src_w || pipe_src_h > max_src_h) {
+   if (DISPLAY_VER(dev_priv) < 12) {
+   max_pipe_src_w = 4096;
+   max_pipe_src_h = 4096;
+   } else {
+   max_pipe_src_w = 5120;
+   max_pipe_src_h = 8192;
+   }
+   if (pipe_src_w > max_pipe_src_w || pipe_src_h > max_pipe_src_h) {
drm_dbg_kms(_priv->drm,
"scaler_user index %u.%u: pipe src size %ux%u "
"is out of scaler range\n",
-- 
2.40.1



[PATCH 3/5] drm/i915/dp: Return int from dsc_max/min_src_input_bpc helpers

2023-12-13 Thread Ankit Nautiyal
Use ints for dsc_max/min_bpc instead of u8 in
dsc_max/min_src_input_bpc helpers and their callers.
This will also help replace min_t/max_t macros with min/max ones.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index b2e767a87476..1f95ba9cf5fd 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1627,7 +1627,7 @@ intel_dp_compute_link_config_wide(struct intel_dp 
*intel_dp,
 }
 
 static
-u8 intel_dp_dsc_max_src_input_bpc(struct drm_i915_private *i915)
+int intel_dp_dsc_max_src_input_bpc(struct drm_i915_private *i915)
 {
if (!HAS_DSC(i915))
return 0;
@@ -1645,14 +1645,14 @@ int intel_dp_dsc_compute_max_bpp(const struct 
intel_connector *connector,
struct drm_i915_private *i915 = to_i915(connector->base.dev);
int i, num_bpc;
u8 dsc_bpc[3] = {};
-   u8 dsc_max_bpc;
+   int dsc_max_bpc;
 
dsc_max_bpc = intel_dp_dsc_max_src_input_bpc(i915);
 
if (!dsc_max_bpc)
return dsc_max_bpc;
 
-   dsc_max_bpc = min_t(u8, dsc_max_bpc, max_req_bpc);
+   dsc_max_bpc = min(dsc_max_bpc, max_req_bpc);
 
num_bpc = drm_dp_dsc_sink_supported_input_bpcs(connector->dp.dsc_dpcd,
   dsc_bpc);
@@ -2027,7 +2027,7 @@ static int dsc_compute_compressed_bpp(struct intel_dp 
*intel_dp,
 }
 
 static
-u8 intel_dp_dsc_min_src_input_bpc(struct drm_i915_private *i915)
+int intel_dp_dsc_min_src_input_bpc(struct drm_i915_private *i915)
 {
/* Min DSC Input BPC for ICL+ is 8 */
return HAS_DSC(i915) ? 8 : 0;
@@ -2039,7 +2039,7 @@ bool is_dsc_pipe_bpp_sufficient(struct drm_i915_private 
*i915,
struct link_config_limits *limits,
int pipe_bpp)
 {
-   u8 dsc_max_bpc, dsc_min_bpc, dsc_max_pipe_bpp, dsc_min_pipe_bpp;
+   int dsc_max_bpc, dsc_min_bpc, dsc_max_pipe_bpp, dsc_min_pipe_bpp;
 
dsc_max_bpc = min(intel_dp_dsc_max_src_input_bpc(i915), 
conn_state->max_requested_bpc);
dsc_min_bpc = intel_dp_dsc_min_src_input_bpc(i915);
@@ -2084,9 +2084,9 @@ static int intel_dp_dsc_compute_pipe_bpp(struct intel_dp 
*intel_dp,
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
const struct intel_connector *connector =
to_intel_connector(conn_state->connector);
-   u8 max_req_bpc = conn_state->max_requested_bpc;
-   u8 dsc_max_bpc, dsc_max_bpp;
-   u8 dsc_min_bpc, dsc_min_bpp;
+   int max_req_bpc = conn_state->max_requested_bpc;
+   int dsc_max_bpc, dsc_max_bpp;
+   int dsc_min_bpc, dsc_min_bpp;
u8 dsc_bpc[3] = {};
int forced_bpp, pipe_bpp;
int num_bpc, i, ret;
@@ -2106,7 +2106,7 @@ static int intel_dp_dsc_compute_pipe_bpp(struct intel_dp 
*intel_dp,
if (!dsc_max_bpc)
return -EINVAL;
 
-   dsc_max_bpc = min_t(u8, dsc_max_bpc, max_req_bpc);
+   dsc_max_bpc = min(dsc_max_bpc, max_req_bpc);
dsc_max_bpp = min(dsc_max_bpc * 3, limits->pipe.max_bpp);
 
dsc_min_bpc = intel_dp_dsc_min_src_input_bpc(i915);
-- 
2.40.1



[PATCH 1/5] drm/i915/dp: Simplify checks for helper intel_dp_dsc_max_src_input_bpc

2023-12-13 Thread Ankit Nautiyal
In helper intel_dp_dsc_max_src_input_bpc it is assumed that platforms
earlier to ICL do not support DSC, and the function returns 0 for
those platforms.

Use HAS_DSC macro instead and return 0 for platforms that do not support
DSC.

v2: Updated commit message with clarification. (Jani)

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 3b2482bf683f..a8015f701626 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1629,13 +1629,14 @@ intel_dp_compute_link_config_wide(struct intel_dp 
*intel_dp,
 static
 u8 intel_dp_dsc_max_src_input_bpc(struct drm_i915_private *i915)
 {
+   if (!HAS_DSC(i915))
+   return 0;
+
/* Max DSC Input BPC for ICL is 10 and for TGL+ is 12 */
-   if (DISPLAY_VER(i915) >= 12)
-   return 12;
if (DISPLAY_VER(i915) == 11)
return 10;
 
-   return 0;
+   return 12;
 }
 
 int intel_dp_dsc_compute_max_bpp(const struct intel_connector *connector,
-- 
2.40.1



[PATCH 5/5] drm/i915/dp: Ignore max_requested_bpc if its too low for DSC

2023-12-13 Thread Ankit Nautiyal
At the moment, while choosing the input bpc for DSC, we take into
account the max_requested_bpc property. This creates a problem, if the
max_requested_bpc is lower than the minimum bpc required by source with
DSC.

So consider max_requested_bpc if its within the limits that we can
support with DSC.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 22 ++
 1 file changed, 18 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index e8aa2f469142..0014aa5ea652 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1638,6 +1638,16 @@ int intel_dp_dsc_max_src_input_bpc(struct 
drm_i915_private *i915)
return 12;
 }
 
+static int
+intel_dp_dsc_limit_max_bpc(int max_requested_bpc, int src_dsc_max_bpc, int 
src_dsc_min_bpc)
+{
+   /* Consider max_requested_bpc only if src can support it with DSC */
+   if (max_requested_bpc >= src_dsc_min_bpc)
+   return min(src_dsc_max_bpc, max_requested_bpc);
+
+   return src_dsc_max_bpc;
+}
+
 int intel_dp_dsc_compute_max_bpp(const struct intel_connector *connector,
 u8 max_req_bpc)
 {
@@ -1651,7 +1661,8 @@ int intel_dp_dsc_compute_max_bpp(const struct 
intel_connector *connector,
if (!dsc_max_bpc)
return dsc_max_bpc;
 
-   dsc_max_bpc = min(dsc_max_bpc, max_req_bpc);
+   dsc_max_bpc = intel_dp_dsc_limit_max_bpc(max_req_bpc, dsc_max_bpc,
+
intel_dp_dsc_min_src_input_bpc(i915));
 
num_bpc = drm_dp_dsc_sink_supported_input_bpcs(connector->dp.dsc_dpcd,
   dsc_bpc);
@@ -2039,8 +2050,11 @@ bool is_dsc_pipe_bpp_sufficient(struct drm_i915_private 
*i915,
 {
int dsc_max_bpc, dsc_min_bpc, dsc_max_pipe_bpp, dsc_min_pipe_bpp;
 
-   dsc_max_bpc = min(intel_dp_dsc_max_src_input_bpc(i915), 
conn_state->max_requested_bpc);
dsc_min_bpc = intel_dp_dsc_min_src_input_bpc(i915);
+   dsc_max_bpc = intel_dp_dsc_max_src_input_bpc(i915);
+
+   dsc_max_bpc = intel_dp_dsc_limit_max_bpc(conn_state->max_requested_bpc,
+dsc_max_bpc, dsc_min_bpc);
 
dsc_max_pipe_bpp = min(dsc_max_bpc * 3, limits->pipe.max_bpp);
dsc_min_pipe_bpp = max(dsc_min_bpc * 3, limits->pipe.min_bpp);
@@ -2100,14 +2114,14 @@ static int intel_dp_dsc_compute_pipe_bpp(struct 
intel_dp *intel_dp,
}
}
 
+   dsc_min_bpc = intel_dp_dsc_min_src_input_bpc(i915);
dsc_max_bpc = intel_dp_dsc_max_src_input_bpc(i915);
if (!dsc_max_bpc)
return -EINVAL;
 
-   dsc_max_bpc = min(dsc_max_bpc, max_req_bpc);
+   dsc_max_bpc = intel_dp_dsc_limit_max_bpc(max_req_bpc, dsc_max_bpc, 
dsc_min_bpc);
dsc_max_bpp = min(dsc_max_bpc * 3, limits->pipe.max_bpp);
 
-   dsc_min_bpc = intel_dp_dsc_min_src_input_bpc(i915);
dsc_min_bpp = max(dsc_min_bpc * 3, limits->pipe.min_bpp);
 
/*
-- 
2.40.1



[PATCH 4/5] drm/i915/dp_mst: Use helpers to get dsc min/max input bpc

2023-12-13 Thread Ankit Nautiyal
Use helpers for source min/max input bpc with DSC.
While at it, make them return int instead of u8.

v2: Make the helpers return int instead of u8. (Jani)

v3: Use min/max macros instead of min_t/max_t. (Jani)

Signed-off-by: Ankit Nautiyal 
Reviewed-by: Suraj Kandpal 
---
 drivers/gpu/drm/i915/display/intel_dp.c |  2 --
 drivers/gpu/drm/i915/display/intel_dp.h |  2 ++
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 13 +
 3 files changed, 7 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 1f95ba9cf5fd..e8aa2f469142 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1626,7 +1626,6 @@ intel_dp_compute_link_config_wide(struct intel_dp 
*intel_dp,
return -EINVAL;
 }
 
-static
 int intel_dp_dsc_max_src_input_bpc(struct drm_i915_private *i915)
 {
if (!HAS_DSC(i915))
@@ -2026,7 +2025,6 @@ static int dsc_compute_compressed_bpp(struct intel_dp 
*intel_dp,
   dsc_max_bpp, dsc_min_bpp, pipe_bpp, 
timeslots);
 }
 
-static
 int intel_dp_dsc_min_src_input_bpc(struct drm_i915_private *i915)
 {
/* Min DSC Input BPC for ICL+ is 8 */
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h 
b/drivers/gpu/drm/i915/display/intel_dp.h
index 05db46b111f2..f613ced9eda6 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -184,5 +184,7 @@ intel_dp_compute_config_link_bpp_limits(struct intel_dp 
*intel_dp,
struct link_config_limits *limits);
 
 void intel_dp_get_dsc_sink_cap(u8 dpcd_rev, struct intel_connector *connector);
+int intel_dp_dsc_max_src_input_bpc(struct drm_i915_private *i915);
+int intel_dp_dsc_min_src_input_bpc(struct drm_i915_private *i915);
 
 #endif /* __INTEL_DP_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c 
b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index e8940acea8ad..a80e59597996 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -293,17 +293,14 @@ static int intel_dp_dsc_mst_compute_link_config(struct 
intel_encoder *encoder,
int i, num_bpc;
u8 dsc_bpc[3] = {};
int min_bpp, max_bpp, sink_min_bpp, sink_max_bpp;
-   u8 dsc_max_bpc;
+   int dsc_max_bpc, dsc_min_bpc;
int min_compressed_bpp, max_compressed_bpp;
 
-   /* Max DSC Input BPC for ICL is 10 and for TGL+ is 12 */
-   if (DISPLAY_VER(i915) >= 12)
-   dsc_max_bpc = min_t(u8, 12, conn_state->max_requested_bpc);
-   else
-   dsc_max_bpc = min_t(u8, 10, conn_state->max_requested_bpc);
+   dsc_max_bpc = intel_dp_dsc_max_src_input_bpc(i915);
+   dsc_min_bpc = intel_dp_dsc_min_src_input_bpc(i915);
 
-   max_bpp = min_t(u8, dsc_max_bpc * 3, limits->pipe.max_bpp);
-   min_bpp = limits->pipe.min_bpp;
+   max_bpp = min(dsc_max_bpc * 3, limits->pipe.max_bpp);
+   min_bpp = max(dsc_min_bpc * 3, limits->pipe.min_bpp);
 
num_bpc = drm_dp_dsc_sink_supported_input_bpcs(connector->dp.dsc_dpcd,
   dsc_bpc);
-- 
2.40.1



[PATCH 2/5] drm/i915/dp: Fix the max DSC bpc supported by source

2023-12-13 Thread Ankit Nautiyal
Use correct helper for getting max DSC bpc supported by the source.

Fixes: 1c56e9a39833 ("drm/i915/dp: Get optimal link config to have best 
compressed bpp")
Cc: Ankit Nautiyal 
Cc: Stanislav Lisovskiy 
Cc: Jani Nikula 

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index a8015f701626..b2e767a87476 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2102,7 +2102,7 @@ static int intel_dp_dsc_compute_pipe_bpp(struct intel_dp 
*intel_dp,
}
}
 
-   dsc_max_bpc = intel_dp_dsc_min_src_input_bpc(i915);
+   dsc_max_bpc = intel_dp_dsc_max_src_input_bpc(i915);
if (!dsc_max_bpc)
return -EINVAL;
 
-- 
2.40.1



[PATCH 0/5] DP DSC min/max src bpc fixes

2023-12-13 Thread Ankit Nautiyal
Use helpers for source min/max src bpc appropriately for dp mst case and
to limit max_requested_bpc property min/max values. 

Rev2: Dropped patch to limit max_requested_bpc based on src DSC bpc
limits. Instead added change to ignore max_requested_bpc if its
too low for DSC.

Rev3: Updated patch#1 commit message.

Rev4: Rebased.

Rev5: Addressed Jani's comment on patch#3

Rev6: Added patch to fix return type for dsc_min/max_src bpc helpers to
int.

Ankit Nautiyal (5):
  drm/i915/dp: Simplify checks for helper intel_dp_dsc_max_src_input_bpc
  drm/i915/dp: Fix the max DSC bpc supported by source
  drm/i915/dp: Return int from dsc_max/min_src_input_bpc helpers
  drm/i915/dp_mst: Use helpers to get dsc min/max input bpc
  drm/i915/dp: Ignore max_requested_bpc if its too low for DSC

 drivers/gpu/drm/i915/display/intel_dp.c | 47 +
 drivers/gpu/drm/i915/display/intel_dp.h |  2 +
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 13 +++---
 3 files changed, 37 insertions(+), 25 deletions(-)

-- 
2.40.1



[PATCH] drm/i915/dp: Update dfp caps only if its a branch device

2023-12-10 Thread Ankit Nautiyal
Avoid checking for Downstream Facing Port capabilities,
if its not a DP branch device.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 3b2482bf683f..bef797b63000 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -5502,6 +5502,9 @@ intel_dp_update_dfp(struct intel_dp *intel_dp,
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
struct intel_connector *connector = intel_dp->attached_connector;
 
+   if (!drm_dp_is_branch(intel_dp->dpcd))
+   return;
+
intel_dp->dfp.max_bpc =
drm_dp_downstream_max_bpc(intel_dp->dpcd,
  intel_dp->downstream_ports, drm_edid);
-- 
2.40.1



[Intel-gfx] [PATCH 3/4] drm/i915/dp_mst: Use helpers to get dsc min/max input bpc

2023-11-26 Thread Ankit Nautiyal
Use helpers for source min/max input bpc with DSC.
While at it, make them return int instead of u8.

v2: Make the helpers return int instead of u8. (Jani)

Signed-off-by: Ankit Nautiyal 
Reviewed-by: Suraj Kandpal 
---
 drivers/gpu/drm/i915/display/intel_dp.c |  6 ++
 drivers/gpu/drm/i915/display/intel_dp.h |  2 ++
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 11 ---
 3 files changed, 8 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 1f68d4819282..74000b65829e 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1622,8 +1622,7 @@ intel_dp_compute_link_config_wide(struct intel_dp 
*intel_dp,
return -EINVAL;
 }
 
-static
-u8 intel_dp_dsc_max_src_input_bpc(struct drm_i915_private *i915)
+int intel_dp_dsc_max_src_input_bpc(struct drm_i915_private *i915)
 {
if (!HAS_DSC(i915))
return 0;
@@ -2022,8 +2021,7 @@ static int dsc_compute_compressed_bpp(struct intel_dp 
*intel_dp,
   dsc_max_bpp, dsc_min_bpp, pipe_bpp, 
timeslots);
 }
 
-static
-u8 intel_dp_dsc_min_src_input_bpc(struct drm_i915_private *i915)
+int intel_dp_dsc_min_src_input_bpc(struct drm_i915_private *i915)
 {
/* Min DSC Input BPC for ICL+ is 8 */
return HAS_DSC(i915) ? 8 : 0;
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h 
b/drivers/gpu/drm/i915/display/intel_dp.h
index 05db46b111f2..f613ced9eda6 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -184,5 +184,7 @@ intel_dp_compute_config_link_bpp_limits(struct intel_dp 
*intel_dp,
struct link_config_limits *limits);
 
 void intel_dp_get_dsc_sink_cap(u8 dpcd_rev, struct intel_connector *connector);
+int intel_dp_dsc_max_src_input_bpc(struct drm_i915_private *i915);
+int intel_dp_dsc_min_src_input_bpc(struct drm_i915_private *i915);
 
 #endif /* __INTEL_DP_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c 
b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 63364c9602ef..01e9d6fb9548 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -293,17 +293,14 @@ static int intel_dp_dsc_mst_compute_link_config(struct 
intel_encoder *encoder,
int i, num_bpc;
u8 dsc_bpc[3] = {};
int min_bpp, max_bpp, sink_min_bpp, sink_max_bpp;
-   u8 dsc_max_bpc;
+   u8 dsc_max_bpc, dsc_min_bpc;
int min_compressed_bpp, max_compressed_bpp;
 
-   /* Max DSC Input BPC for ICL is 10 and for TGL+ is 12 */
-   if (DISPLAY_VER(i915) >= 12)
-   dsc_max_bpc = min_t(u8, 12, conn_state->max_requested_bpc);
-   else
-   dsc_max_bpc = min_t(u8, 10, conn_state->max_requested_bpc);
+   dsc_max_bpc = intel_dp_dsc_max_src_input_bpc(i915);
+   dsc_min_bpc = intel_dp_dsc_min_src_input_bpc(i915);
 
max_bpp = min_t(u8, dsc_max_bpc * 3, limits->pipe.max_bpp);
-   min_bpp = limits->pipe.min_bpp;
+   min_bpp = max_t(u8, dsc_min_bpc * 3, limits->pipe.min_bpp);
 
num_bpc = drm_dp_dsc_sink_supported_input_bpcs(connector->dp.dsc_dpcd,
   dsc_bpc);
-- 
2.40.1



[Intel-gfx] [PATCH 3/4] drm/i915/dp_mst: Use helpers to get dsc min/max input bpc

2023-11-22 Thread Ankit Nautiyal
Use helpers for source min/max input bpc with DSC.

Signed-off-by: Ankit Nautiyal 
Reviewed-by: Suraj Kandpal 
---
 drivers/gpu/drm/i915/display/intel_dp.c |  2 --
 drivers/gpu/drm/i915/display/intel_dp.h |  2 ++
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 11 ---
 3 files changed, 6 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 37320cc4346f..0f5040c114b3 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1622,7 +1622,6 @@ intel_dp_compute_link_config_wide(struct intel_dp 
*intel_dp,
return -EINVAL;
 }
 
-static
 u8 intel_dp_dsc_max_src_input_bpc(struct drm_i915_private *i915)
 {
if (!HAS_DSC(i915))
@@ -2022,7 +2021,6 @@ static int dsc_compute_compressed_bpp(struct intel_dp 
*intel_dp,
   dsc_max_bpp, dsc_min_bpp, pipe_bpp, 
timeslots);
 }
 
-static
 u8 intel_dp_dsc_min_src_input_bpc(struct drm_i915_private *i915)
 {
/* Min DSC Input BPC for ICL+ is 8 */
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h 
b/drivers/gpu/drm/i915/display/intel_dp.h
index 05db46b111f2..931c5eb71cd0 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -184,5 +184,7 @@ intel_dp_compute_config_link_bpp_limits(struct intel_dp 
*intel_dp,
struct link_config_limits *limits);
 
 void intel_dp_get_dsc_sink_cap(u8 dpcd_rev, struct intel_connector *connector);
+u8 intel_dp_dsc_max_src_input_bpc(struct drm_i915_private *i915);
+u8 intel_dp_dsc_min_src_input_bpc(struct drm_i915_private *i915);
 
 #endif /* __INTEL_DP_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c 
b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index d3d53e1b4489..337db31777df 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -293,17 +293,14 @@ static int intel_dp_dsc_mst_compute_link_config(struct 
intel_encoder *encoder,
int i, num_bpc;
u8 dsc_bpc[3] = {};
int min_bpp, max_bpp, sink_min_bpp, sink_max_bpp;
-   u8 dsc_max_bpc;
+   u8 dsc_max_bpc, dsc_min_bpc;
int min_compressed_bpp, max_compressed_bpp;
 
-   /* Max DSC Input BPC for ICL is 10 and for TGL+ is 12 */
-   if (DISPLAY_VER(i915) >= 12)
-   dsc_max_bpc = min_t(u8, 12, conn_state->max_requested_bpc);
-   else
-   dsc_max_bpc = min_t(u8, 10, conn_state->max_requested_bpc);
+   dsc_max_bpc = intel_dp_dsc_max_src_input_bpc(i915);
+   dsc_min_bpc = intel_dp_dsc_min_src_input_bpc(i915);
 
max_bpp = min_t(u8, dsc_max_bpc * 3, limits->pipe.max_bpp);
-   min_bpp = limits->pipe.min_bpp;
+   min_bpp = max_t(u8, dsc_min_bpc * 3, limits->pipe.min_bpp);
 
num_bpc = drm_dp_dsc_sink_supported_input_bpcs(connector->dp.dsc_dpcd,
   dsc_bpc);
-- 
2.40.1



[Intel-gfx] [PATCH 2/4] drm/i915/dp: Fix the max DSC bpc supported by source

2023-11-22 Thread Ankit Nautiyal
Use correct helper for getting max DSC bpc supported by the source.

Fixes: 1c56e9a39833 ("drm/i915/dp: Get optimal link config to have best 
compressed bpp")
Cc: Ankit Nautiyal 
Cc: Stanislav Lisovskiy 
Cc: Jani Nikula 

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 54306271f5c2..37320cc4346f 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2098,7 +2098,7 @@ static int intel_dp_dsc_compute_pipe_bpp(struct intel_dp 
*intel_dp,
}
}
 
-   dsc_max_bpc = intel_dp_dsc_min_src_input_bpc(i915);
+   dsc_max_bpc = intel_dp_dsc_max_src_input_bpc(i915);
if (!dsc_max_bpc)
return -EINVAL;
 
-- 
2.40.1



[Intel-gfx] [PATCH 1/4] drm/i915/dp: Simplify checks for helper intel_dp_dsc_max_src_input_bpc

2023-11-22 Thread Ankit Nautiyal
In helper intel_dp_dsc_max_src_input_bpc it is assumed that platforms
earlier to ICL do not support DSC, and the function returns 0 for
those platforms.

Use HAS_DSC macro instead and return 0 for platforms that do not support
DSC.

v2: Updated commit message with clarification. (Jani)

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 1422c2370269..54306271f5c2 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1625,13 +1625,14 @@ intel_dp_compute_link_config_wide(struct intel_dp 
*intel_dp,
 static
 u8 intel_dp_dsc_max_src_input_bpc(struct drm_i915_private *i915)
 {
+   if (!HAS_DSC(i915))
+   return 0;
+
/* Max DSC Input BPC for ICL is 10 and for TGL+ is 12 */
-   if (DISPLAY_VER(i915) >= 12)
-   return 12;
if (DISPLAY_VER(i915) == 11)
return 10;
 
-   return 0;
+   return 12;
 }
 
 int intel_dp_dsc_compute_max_bpp(const struct intel_connector *connector,
-- 
2.40.1



[Intel-gfx] [PATCH 4/4] drm/i915/dp: Ignore max_requested_bpc if its too low for DSC

2023-11-22 Thread Ankit Nautiyal
At the moment, while choosing the input bpc for DSC, we take into
account the max_requested_bpc property. This creates a problem, if the
max_requested_bpc is lower than the minimum bpc required by source with
DSC.

So consider max_requested_bpc if its within the limits that we can
support with DSC.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 22 ++
 1 file changed, 18 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 0f5040c114b3..d29cbf6436a5 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1634,6 +1634,16 @@ u8 intel_dp_dsc_max_src_input_bpc(struct 
drm_i915_private *i915)
return 12;
 }
 
+static int
+intel_dp_dsc_limit_max_bpc(int max_requested_bpc, int src_dsc_max_bpc, int 
src_dsc_min_bpc)
+{
+   /* Consider max_requested_bpc only if src can support it with DSC */
+   if (max_requested_bpc >= src_dsc_min_bpc)
+   return min(src_dsc_max_bpc, max_requested_bpc);
+
+   return src_dsc_max_bpc;
+}
+
 int intel_dp_dsc_compute_max_bpp(const struct intel_connector *connector,
 u8 max_req_bpc)
 {
@@ -1647,7 +1657,8 @@ int intel_dp_dsc_compute_max_bpp(const struct 
intel_connector *connector,
if (!dsc_max_bpc)
return dsc_max_bpc;
 
-   dsc_max_bpc = min_t(u8, dsc_max_bpc, max_req_bpc);
+   dsc_max_bpc = intel_dp_dsc_limit_max_bpc(max_req_bpc, dsc_max_bpc,
+
intel_dp_dsc_min_src_input_bpc(i915));
 
num_bpc = drm_dp_dsc_sink_supported_input_bpcs(connector->dp.dsc_dpcd,
   dsc_bpc);
@@ -2035,8 +2046,11 @@ bool is_dsc_pipe_bpp_sufficient(struct drm_i915_private 
*i915,
 {
u8 dsc_max_bpc, dsc_min_bpc, dsc_max_pipe_bpp, dsc_min_pipe_bpp;
 
-   dsc_max_bpc = min(intel_dp_dsc_max_src_input_bpc(i915), 
conn_state->max_requested_bpc);
dsc_min_bpc = intel_dp_dsc_min_src_input_bpc(i915);
+   dsc_max_bpc = intel_dp_dsc_max_src_input_bpc(i915);
+
+   dsc_max_bpc = intel_dp_dsc_limit_max_bpc(conn_state->max_requested_bpc,
+dsc_max_bpc, dsc_min_bpc);
 
dsc_max_pipe_bpp = min(dsc_max_bpc * 3, limits->pipe.max_bpp);
dsc_min_pipe_bpp = max(dsc_min_bpc * 3, limits->pipe.min_bpp);
@@ -2096,14 +2110,14 @@ static int intel_dp_dsc_compute_pipe_bpp(struct 
intel_dp *intel_dp,
}
}
 
+   dsc_min_bpc = intel_dp_dsc_min_src_input_bpc(i915);
dsc_max_bpc = intel_dp_dsc_max_src_input_bpc(i915);
if (!dsc_max_bpc)
return -EINVAL;
 
-   dsc_max_bpc = min_t(u8, dsc_max_bpc, max_req_bpc);
+   dsc_max_bpc = intel_dp_dsc_limit_max_bpc(max_req_bpc, dsc_max_bpc, 
dsc_min_bpc);
dsc_max_bpp = min(dsc_max_bpc * 3, limits->pipe.max_bpp);
 
-   dsc_min_bpc = intel_dp_dsc_min_src_input_bpc(i915);
dsc_min_bpp = max(dsc_min_bpc * 3, limits->pipe.min_bpp);
 
/*
-- 
2.40.1



[Intel-gfx] [PATCH 0/4] DP DSC min/max src bpc fixes

2023-11-22 Thread Ankit Nautiyal
Use helpers for source min/max src bpc appropriately for dp mst case and
to limit max_requested_bpc property min/max values. 

Rev2: Dropped patch to limit max_requested_bpc based on src DSC bpc
limits. Instead added change to ignore max_requested_bpc if its
too low for DSC.

Rev3: Updated patch#1 commit message.

Rev4: Rebased.

Ankit Nautiyal (4):
  drm/i915/dp: Simplify checks for helper intel_dp_dsc_max_src_input_bpc
  drm/i915/dp: Fix the max DSC bpc supported by source
  drm/i915/dp_mst: Use helpers to get dsc min/max input bpc
  drm/i915/dp: Ignore max_requested_bpc if its too low for DSC

 drivers/gpu/drm/i915/display/intel_dp.c | 33 ++---
 drivers/gpu/drm/i915/display/intel_dp.h |  2 ++
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 11 +++
 3 files changed, 29 insertions(+), 17 deletions(-)

-- 
2.40.1



[Intel-gfx] [PATCH] drm/i915/display: Get bigjoiner config before dsc config during readout

2023-11-21 Thread Ankit Nautiyal
Currently we get bigjoiner config after the dsc get config, during HW
readout.
Since dsc_get_config now uses bigjoiner flags/pipes to compute DSC PPS
parameter pic_width, this results in a state mismatch when Bigjoiner
and DSC are used together.

So call get bigjoiner config before calling dsc get config function.

Fixes: 8b70b5691704 ("drm/i915/vdsc: Fill the intel_dsc_get_pps_config 
function")
Cc: Suraj Kandpal 
Cc: Ankit Nautiyal 
Cc: Animesh Manna 
Cc: Jani Nikula 

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_display.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 959db3f61e84..e086caf3963d 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -3694,8 +3694,8 @@ static bool hsw_get_pipe_config(struct intel_crtc *crtc,
if (!active)
goto out;
 
-   intel_dsc_get_config(pipe_config);
intel_bigjoiner_get_config(pipe_config);
+   intel_dsc_get_config(pipe_config);
 
if (!transcoder_is_dsi(pipe_config->cpu_transcoder) ||
DISPLAY_VER(dev_priv) >= 11)
-- 
2.40.1



[Intel-gfx] [PATCH 1/4] drm/i915/dp: Simplify checks for helper intel_dp_dsc_max_src_input_bpc

2023-11-16 Thread Ankit Nautiyal
In helper intel_dp_dsc_max_src_input_bpc it is assumed that platforms
earlier to ICL do not support DSC, and the function returns 0 for
those platforms.

Use HAS_DSC macro instead and return 0 for platforms that do not support
DSC.

v2: Updated commit message with clarification. (Jani)

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 5391b2a83405..30ea4820b210 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1569,13 +1569,14 @@ intel_dp_compute_link_config_wide(struct intel_dp 
*intel_dp,
 static
 u8 intel_dp_dsc_max_src_input_bpc(struct drm_i915_private *i915)
 {
+   if (!HAS_DSC(i915))
+   return 0;
+
/* Max DSC Input BPC for ICL is 10 and for TGL+ is 12 */
-   if (DISPLAY_VER(i915) >= 12)
-   return 12;
if (DISPLAY_VER(i915) == 11)
return 10;
 
-   return 0;
+   return 12;
 }
 
 int intel_dp_dsc_compute_max_bpp(const struct intel_connector *connector,
-- 
2.40.1



[Intel-gfx] [PATCH 11/11] drm/i915/dp_mst: Add support for forcing dsc fractional bpp via debugfs

2023-11-10 Thread Ankit Nautiyal
If force_dsc_fractional_bpp_en is set through debugfs allow DSC iff
compressed bpp is fractional. Continue if the computed compressed bpp
turns out to be a integer.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 14 +++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c 
b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 322046bb7d42..26b51ba6871d 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -172,6 +172,10 @@ static int intel_dp_mst_find_vcpi_slots_for_bpp(struct 
intel_encoder *encoder,
struct intel_link_m_n remote_m_n;
int link_bpp_x16;
 
+   if (dsc && intel_dp->force_dsc_fractional_bpp_en &&
+   !to_bpp_frac(bpp_x16))
+   continue;
+
drm_dbg_kms(>drm, "Trying bpp " BPP_X16_FMT "\n", 
BPP_X16_ARGS(bpp_x16));
 
ret = intel_dp_mst_check_constraints(i915, bpp_x16, 
adjusted_mode, crtc_state, dsc);
@@ -225,12 +229,16 @@ static int intel_dp_mst_find_vcpi_slots_for_bpp(struct 
intel_encoder *encoder,
drm_dbg_kms(>drm, "failed finding vcpi slots:%d\n",
slots);
} else {
-   if (!dsc)
-   crtc_state->pipe_bpp = to_bpp_int(bpp_x16);
-   else
+   if (dsc) {
crtc_state->dsc.compressed_bpp_x16 = bpp_x16;
+   if (intel_dp->force_dsc_fractional_bpp_en && 
to_bpp_frac(bpp_x16))
+   drm_dbg_kms(>drm, "Forcing DSC fractional 
bpp\n");
+   } else {
+   crtc_state->pipe_bpp = to_bpp_int(bpp_x16);
+   }
drm_dbg_kms(>drm, "Got %d slots for pipe bpp " 
BPP_X16_FMT " dsc %d\n",
slots, BPP_X16_ARGS(bpp_x16), dsc);
+
}
 
return slots;
-- 
2.40.1



[Intel-gfx] [PATCH 10/11] drm/i916/dp_mst: Iterate over the DSC bpps as per DSC precision support

2023-11-10 Thread Ankit Nautiyal
Currently we iterate over the bpp_x16 in step of 16.
Use DSC fractional bpp precision supported by the sink to compute
the appropriate steps to iterate over the bpps.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c 
b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index e7806fe11b9d..322046bb7d42 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -273,6 +273,8 @@ static int intel_dp_dsc_mst_compute_link_config(struct 
intel_encoder *encoder,
int min_bpp, max_bpp, sink_min_bpp, sink_max_bpp;
u8 dsc_max_bpc;
int min_compressed_bpp, max_compressed_bpp;
+   int bppx16_incr = drm_dp_dsc_sink_bpp_incr(connector->dp.dsc_dpcd);
+   int bppx16_step;
 
/* Max DSC Input BPC for ICL is 10 and for TGL+ is 12 */
if (DISPLAY_VER(i915) >= 12)
@@ -327,11 +329,16 @@ static int intel_dp_dsc_mst_compute_link_config(struct 
intel_encoder *encoder,
min_compressed_bpp = intel_dp_dsc_nearest_valid_bpp(i915, 
min_compressed_bpp,

crtc_state->pipe_bpp);
 
+   if (DISPLAY_VER(i915) < 14 || bppx16_incr <= 1)
+   bppx16_step = 16;
+   else
+   bppx16_step = 16 / bppx16_incr;
+
slots = intel_dp_mst_find_vcpi_slots_for_bpp(encoder, crtc_state,
 
to_bpp_x16(max_compressed_bpp),
 
to_bpp_x16(min_compressed_bpp),
 limits,
-conn_state, 16, true);
+conn_state, bppx16_step, 
true);
 
if (slots < 0)
return slots;
-- 
2.40.1



[Intel-gfx] [PATCH 09/11] drm/i915/dp_mst: Use precision of 1/16 for computing bpp

2023-11-10 Thread Ankit Nautiyal
Modify the functions to deal with bpps with 1/16 precision.
This will make way for cases when DSC with fractional bpp is used.
For bpp without DSC, there is no change, as we still use whole numbers.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 56 +++--
 1 file changed, 30 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c 
b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 5c7e9d296483..e7806fe11b9d 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -47,20 +47,21 @@
 #include "intel_vdsc.h"
 #include "skl_scaler.h"
 
-static int intel_dp_mst_check_constraints(struct drm_i915_private *i915, int 
bpp,
+static int intel_dp_mst_check_constraints(struct drm_i915_private *i915, int 
bpp_x16,
  const struct drm_display_mode 
*adjusted_mode,
  struct intel_crtc_state *crtc_state,
  bool dsc)
 {
if (intel_dp_is_uhbr(crtc_state) && DISPLAY_VER(i915) <= 13 && dsc) {
-   int output_bpp = bpp;
+   int output_bpp_x16 = bpp_x16;
/* DisplayPort 2 128b/132b, bits per lane is always 32 */
int symbol_clock = crtc_state->port_clock / 32;
 
-   if (output_bpp * adjusted_mode->crtc_clock >=
+   if (DIV_ROUND_UP(output_bpp_x16 * adjusted_mode->crtc_clock, 
16) >=
symbol_clock * 72) {
drm_dbg_kms(>drm, "UHBR check failed(required bw 
%d available %d)\n",
-   output_bpp * adjusted_mode->crtc_clock, 
symbol_clock * 72);
+   DIV_ROUND_UP(output_bpp_x16 * 
adjusted_mode->crtc_clock, 16),
+   symbol_clock * 72);
return -EINVAL;
}
}
@@ -127,8 +128,8 @@ static void intel_dp_mst_compute_m_n(const struct 
intel_crtc_state *crtc_state,
 
 static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder,
struct intel_crtc_state 
*crtc_state,
-   int max_bpp,
-   int min_bpp,
+   int max_bpp_x16,
+   int min_bpp_x16,
struct link_config_limits 
*limits,
struct drm_connector_state 
*conn_state,
int step,
@@ -143,7 +144,7 @@ static int intel_dp_mst_find_vcpi_slots_for_bpp(struct 
intel_encoder *encoder,
struct drm_i915_private *i915 = to_i915(connector->base.dev);
const struct drm_display_mode *adjusted_mode =
_state->hw.adjusted_mode;
-   int bpp, slots = -EINVAL;
+   int bpp_x16, slots = -EINVAL;
int ret = 0;
 
mst_state = drm_atomic_get_mst_topology_state(state, 
_dp->mst_mgr);
@@ -164,25 +165,25 @@ static int intel_dp_mst_find_vcpi_slots_for_bpp(struct 
intel_encoder *encoder,
  crtc_state->port_clock,
  crtc_state->lane_count);
 
-   drm_dbg_kms(>drm, "Looking for slots in range min bpp %d max bpp 
%d\n",
-   min_bpp, max_bpp);
+   drm_dbg_kms(>drm, "Looking for slots in range min bpp " 
BPP_X16_FMT " max bpp " BPP_X16_FMT "\n",
+   BPP_X16_ARGS(min_bpp_x16), BPP_X16_ARGS(max_bpp_x16));
 
-   for (bpp = max_bpp; bpp >= min_bpp; bpp -= step) {
+   for (bpp_x16 = max_bpp_x16; bpp_x16 >= min_bpp_x16; bpp_x16 -= step) {
struct intel_link_m_n remote_m_n;
-   int link_bpp;
+   int link_bpp_x16;
 
-   drm_dbg_kms(>drm, "Trying bpp %d\n", bpp);
+   drm_dbg_kms(>drm, "Trying bpp " BPP_X16_FMT "\n", 
BPP_X16_ARGS(bpp_x16));
 
-   ret = intel_dp_mst_check_constraints(i915, bpp, adjusted_mode, 
crtc_state, dsc);
+   ret = intel_dp_mst_check_constraints(i915, bpp_x16, 
adjusted_mode, crtc_state, dsc);
if (ret)
continue;
 
-   link_bpp = dsc ? bpp :
-   intel_dp_output_bpp(crtc_state->output_format, bpp);
+   link_bpp_x16 = dsc ? bpp_x16 :
+   intel_dp_output_bpp(crtc_state->output_format, 
to_bpp_int(bpp_x16));
 
-   intel_dp_mst_compute_m_n(crtc_state, connector, false, dsc, 
to_bpp_x16(link_bpp),
+   intel_dp_mst_compute_m_n(crtc_state, 

[Intel-gfx] [PATCH 08/11] drm/i915/dsc: Allow DSC only with fractional bpp when forced from debugfs

2023-11-10 Thread Ankit Nautiyal
From: Swati Sharma 

If force_dsc_fractional_bpp_en is set through debugfs allow DSC iff
compressed bpp is fractional. Continue if the computed compressed bpp
turns out to be a integer.

v2:
-Use helpers for fractional, integral bits of bits_per_pixel. (Suraj)
-Fix comment (Suraj)

Signed-off-by: Swati Sharma 
Reviewed-by: Suraj Kandpal 
Reviewed-by: Sui Jingfeng 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index e53c87825194..607d03382db8 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1928,6 +1928,9 @@ xelpd_dsc_compute_link_config(struct intel_dp *intel_dp,
for (compressed_bppx16 = dsc_max_bpp;
 compressed_bppx16 >= dsc_min_bpp;
 compressed_bppx16 -= bppx16_step) {
+   if (intel_dp->force_dsc_fractional_bpp_en &&
+   !to_bpp_frac(compressed_bppx16))
+   continue;
ret = dsc_compute_link_config(intel_dp,
  pipe_config,
  limits,
@@ -1935,6 +1938,10 @@ xelpd_dsc_compute_link_config(struct intel_dp *intel_dp,
  timeslots);
if (ret == 0) {
pipe_config->dsc.compressed_bpp_x16 = compressed_bppx16;
+   if (intel_dp->force_dsc_fractional_bpp_en &&
+   to_bpp_frac(compressed_bppx16))
+   drm_dbg_kms(>drm, "Forcing DSC fractional 
bpp\n");
+
return 0;
}
}
-- 
2.40.1



[Intel-gfx] [PATCH 07/11] drm/i915/dsc: Add debugfs entry to validate DSC fractional bpp

2023-11-10 Thread Ankit Nautiyal
From: Swati Sharma 

DSC_Sink_BPP_Precision entry is added to i915_dsc_fec_support_show
to depict sink's precision.
Also, new debugfs entry is created to enforce fractional bpp.
If Force_DSC_Fractional_BPP_en is set then while iterating over
output bpp with fractional step size we will continue if output_bpp is
computed as integer. With this approach, we will be able to validate
DSC with fractional bpp.

v2:
Add drm_modeset_unlock to new line(Suraj)

Signed-off-by: Swati Sharma 
Signed-off-by: Ankit Nautiyal 
Signed-off-by: Mitul Golani 
Reviewed-by: Suraj Kandpal 
Reviewed-by: Sui Jingfeng 
---
 .../drm/i915/display/intel_display_debugfs.c  | 84 +++
 .../drm/i915/display/intel_display_types.h|  1 +
 2 files changed, 85 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c 
b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
index f3700c18d685..915420d0cef8 100644
--- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
+++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
@@ -1256,6 +1256,8 @@ static int i915_dsc_fec_support_show(struct seq_file *m, 
void *data)
  
DP_DSC_YCbCr420_Native)),
   
str_yes_no(drm_dp_dsc_sink_supports_format(connector->dp.dsc_dpcd,
  
DP_DSC_YCbCr444)));
+   seq_printf(m, "DSC_Sink_BPP_Precision: %d\n",
+  drm_dp_dsc_sink_bpp_incr(connector->dp.dsc_dpcd));
seq_printf(m, "Force_DSC_Enable: %s\n",
   str_yes_no(intel_dp->force_dsc_en));
if (!intel_dp_is_edp(intel_dp))
@@ -1448,6 +1450,85 @@ static const struct file_operations 
i915_dsc_output_format_fops = {
.write = i915_dsc_output_format_write
 };
 
+static int i915_dsc_fractional_bpp_show(struct seq_file *m, void *data)
+{
+   struct drm_connector *connector = m->private;
+   struct drm_device *dev = connector->dev;
+   struct drm_crtc *crtc;
+   struct intel_dp *intel_dp;
+   struct intel_connector *intel_connector = to_intel_connector(connector);
+   struct intel_encoder *encoder = intel_attached_encoder(intel_connector);
+   int ret;
+
+   if (!encoder)
+   return -ENODEV;
+
+   ret = 
drm_modeset_lock_single_interruptible(>mode_config.connection_mutex);
+   if (ret)
+   return ret;
+
+   crtc = connector->state->crtc;
+   if (connector->status != connector_status_connected || !crtc) {
+   ret = -ENODEV;
+   goto out;
+   }
+
+   intel_dp = intel_attached_dp(intel_connector);
+   seq_printf(m, "Force_DSC_Fractional_BPP_Enable: %s\n",
+  str_yes_no(intel_dp->force_dsc_fractional_bpp_en));
+
+out:
+   drm_modeset_unlock(>mode_config.connection_mutex);
+
+   return ret;
+}
+
+static ssize_t i915_dsc_fractional_bpp_write(struct file *file,
+const char __user *ubuf,
+size_t len, loff_t *offp)
+{
+   struct drm_connector *connector =
+   ((struct seq_file *)file->private_data)->private;
+   struct intel_encoder *encoder = 
intel_attached_encoder(to_intel_connector(connector));
+   struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+   struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+   bool dsc_fractional_bpp_enable = false;
+   int ret;
+
+   if (len == 0)
+   return 0;
+
+   drm_dbg(>drm,
+   "Copied %zu bytes from user to force fractional bpp for DSC\n", 
len);
+
+   ret = kstrtobool_from_user(ubuf, len, _fractional_bpp_enable);
+   if (ret < 0)
+   return ret;
+
+   drm_dbg(>drm, "Got %s for DSC Fractional BPP Enable\n",
+   (dsc_fractional_bpp_enable) ? "true" : "false");
+   intel_dp->force_dsc_fractional_bpp_en = dsc_fractional_bpp_enable;
+
+   *offp += len;
+
+   return len;
+}
+
+static int i915_dsc_fractional_bpp_open(struct inode *inode,
+   struct file *file)
+{
+   return single_open(file, i915_dsc_fractional_bpp_show, 
inode->i_private);
+}
+
+static const struct file_operations i915_dsc_fractional_bpp_fops = {
+   .owner = THIS_MODULE,
+   .open = i915_dsc_fractional_bpp_open,
+   .read = seq_read,
+   .llseek = seq_lseek,
+   .release = single_release,
+   .write = i915_dsc_fractional_bpp_write
+};
+
 /*
  * Returns the Current CRTC's bpc.
  * Example usage: cat /sys/kernel/debug/dri/0/crtc-0/i915_current_bpc
@@ -1525,6 +1606,9 @@ void intel_connector_debugfs_add(struct intel_connector 
*intel_connector)
 
debugfs_create_file("i915_dsc_output

[Intel-gfx] [PATCH 05/11] drm/i915/dsc/mtl: Add support for fractional bpp

2023-11-10 Thread Ankit Nautiyal
From: Vandita Kulkarni 

Consider the fractional bpp while reading the qp values.

v2: Use helpers for fractional, integral bits of bits_per_pixel. (Suraj)

Signed-off-by: Vandita Kulkarni 
Signed-off-by: Ankit Nautiyal 
Reviewed-by: Suraj Kandpal 
Reviewed-by: Sui Jingfeng 
---
 .../gpu/drm/i915/display/intel_qp_tables.c|  3 ---
 drivers/gpu/drm/i915/display/intel_vdsc.c | 25 +++
 2 files changed, 20 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_qp_tables.c 
b/drivers/gpu/drm/i915/display/intel_qp_tables.c
index 543cdc46aa1d..600c815e37e4 100644
--- a/drivers/gpu/drm/i915/display/intel_qp_tables.c
+++ b/drivers/gpu/drm/i915/display/intel_qp_tables.c
@@ -34,9 +34,6 @@
  * These qp tables are as per the C model
  * and it has the rows pointing to bpps which increment
  * in steps of 0.5
- * We do not support fractional bpps as of today,
- * hence we would skip the fractional bpps during
- * our references for qp calclulations.
  */
 static const u8 
rc_range_minqp444_8bpc[DSC_NUM_BUF_RANGES][RC_RANGE_QP444_8BPC_MAX_NUM_BPP] = {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c 
b/drivers/gpu/drm/i915/display/intel_vdsc.c
index 3a1ed574edbb..5f2fb702e367 100644
--- a/drivers/gpu/drm/i915/display/intel_vdsc.c
+++ b/drivers/gpu/drm/i915/display/intel_vdsc.c
@@ -77,8 +77,8 @@ intel_vdsc_set_min_max_qp(struct drm_dsc_config *vdsc_cfg, 
int buf,
 static void
 calculate_rc_params(struct drm_dsc_config *vdsc_cfg)
 {
+   int bpp = to_bpp_int(vdsc_cfg->bits_per_pixel);
int bpc = vdsc_cfg->bits_per_component;
-   int bpp = vdsc_cfg->bits_per_pixel >> 4;
int qp_bpc_modifier = (bpc - 8) * 2;
int uncompressed_bpg_rate;
int first_line_bpg_offset;
@@ -148,7 +148,13 @@ calculate_rc_params(struct drm_dsc_config *vdsc_cfg)
static const s8 ofs_und8[] = {
10, 8, 6, 4, 2, 0, -2, -4, -6, -8, -10, -10, -12, -12, 
-12
};
-
+   /*
+* For 420 format since bits_per_pixel (bpp) is set to target 
bpp * 2,
+* QP table values for target bpp 4.0 to 4.4375 (rounded to 
4.0) are
+* actually for bpp 8 to 8.875 (rounded to 4.0 * 2 i.e 8).
+* Similarly values for target bpp 4.5 to 4.8375 (rounded to 
4.5)
+* are for bpp 9 to 9.875 (rounded to 4.5 * 2 i.e 9), and so on.
+*/
bpp_i  = bpp - 8;
for (buf_i = 0; buf_i < DSC_NUM_BUF_RANGES; buf_i++) {
u8 range_bpg_offset;
@@ -178,6 +184,9 @@ calculate_rc_params(struct drm_dsc_config *vdsc_cfg)
range_bpg_offset & DSC_RANGE_BPG_OFFSET_MASK;
}
} else {
+   /* fractional bpp part * 1 (for precision up to 4 decimal 
places) */
+   int fractional_bits = to_bpp_frac(vdsc_cfg->bits_per_pixel);
+
static const s8 ofs_und6[] = {
0, -2, -2, -4, -6, -6, -8, -8, -8, -10, -10, -12, -12, 
-12, -12
};
@@ -191,7 +200,14 @@ calculate_rc_params(struct drm_dsc_config *vdsc_cfg)
10, 8, 6, 4, 2, 0, -2, -4, -6, -8, -10, -10, -12, -12, 
-12
};
 
-   bpp_i  = (2 * (bpp - 6));
+   /*
+* QP table rows have values in increment of 0.5.
+* So 6.0 bpp to 6.4375 will have index 0, 6.5 to 6.9375 will 
have index 1,
+* and so on.
+* 0.5 fractional part with 4 decimal precision becomes 5000
+*/
+   bpp_i  = ((bpp - 6) + (fractional_bits < 5000 ? 0 : 1));
+
for (buf_i = 0; buf_i < DSC_NUM_BUF_RANGES; buf_i++) {
u8 range_bpg_offset;
 
@@ -279,8 +295,7 @@ int intel_dsc_compute_params(struct intel_crtc_state 
*pipe_config)
/* Gen 11 does not support VBR */
vdsc_cfg->vbr_enable = false;
 
-   /* Gen 11 only supports integral values of bpp */
-   vdsc_cfg->bits_per_pixel = compressed_bpp << 4;
+   vdsc_cfg->bits_per_pixel = pipe_config->dsc.compressed_bpp_x16;
 
/*
 * According to DSC 1.2 specs in Section 4.1 if native_420 is set
-- 
2.40.1



[Intel-gfx] [PATCH 06/11] drm/i915/dp: Iterate over output bpp with fractional step size

2023-11-10 Thread Ankit Nautiyal
This patch adds support to iterate over compressed output bpp as per the
fractional step, supported by DP sink.

v2:
-Avoid ending up with compressed bpp, same as pipe bpp. (Stan)

Signed-off-by: Ankit Nautiyal 
Reviewed-by: Suraj Kandpal 
Reviewed-by: Sui Jingfeng 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 41 +++--
 1 file changed, 25 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 246f50d1f030..e53c87825194 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1737,15 +1737,15 @@ static bool intel_dp_dsc_supports_format(const struct 
intel_connector *connector
return drm_dp_dsc_sink_supports_format(connector->dp.dsc_dpcd, 
sink_dsc_format);
 }
 
-static bool is_bw_sufficient_for_dsc_config(u16 compressed_bpp, u32 link_clock,
+static bool is_bw_sufficient_for_dsc_config(u16 compressed_bppx16, u32 
link_clock,
u32 lane_count, u32 mode_clock,
enum intel_output_format 
output_format,
int timeslots)
 {
u32 available_bw, required_bw;
 
-   available_bw = (link_clock * lane_count * timeslots)  / 8;
-   required_bw = compressed_bpp * (intel_dp_mode_to_fec_clock(mode_clock));
+   available_bw = (link_clock * lane_count * timeslots * 16)  / 8;
+   required_bw = compressed_bppx16 * 
(intel_dp_mode_to_fec_clock(mode_clock));
 
return available_bw > required_bw;
 }
@@ -1753,7 +1753,7 @@ static bool is_bw_sufficient_for_dsc_config(u16 
compressed_bpp, u32 link_clock,
 static int dsc_compute_link_config(struct intel_dp *intel_dp,
   struct intel_crtc_state *pipe_config,
   struct link_config_limits *limits,
-  u16 compressed_bpp,
+  u16 compressed_bppx16,
   int timeslots)
 {
const struct drm_display_mode *adjusted_mode = 
_config->hw.adjusted_mode;
@@ -1768,8 +1768,8 @@ static int dsc_compute_link_config(struct intel_dp 
*intel_dp,
for (lane_count = limits->min_lane_count;
 lane_count <= limits->max_lane_count;
 lane_count <<= 1) {
-   if (!is_bw_sufficient_for_dsc_config(compressed_bpp, 
link_rate, lane_count,
-
adjusted_mode->clock,
+   if (!is_bw_sufficient_for_dsc_config(compressed_bppx16, 
link_rate,
+lane_count, 
adjusted_mode->clock,
 
pipe_config->output_format,
 timeslots))
continue;
@@ -1882,7 +1882,7 @@ icl_dsc_compute_link_config(struct intel_dp *intel_dp,
ret = dsc_compute_link_config(intel_dp,
  pipe_config,
  limits,
- valid_dsc_bpp[i],
+ valid_dsc_bpp[i] << 4,
  timeslots);
if (ret == 0) {
pipe_config->dsc.compressed_bpp_x16 =
@@ -1902,6 +1902,7 @@ icl_dsc_compute_link_config(struct intel_dp *intel_dp,
  */
 static int
 xelpd_dsc_compute_link_config(struct intel_dp *intel_dp,
+ const struct intel_connector *connector,
  struct intel_crtc_state *pipe_config,
  struct link_config_limits *limits,
  int dsc_max_bpp,
@@ -1909,23 +1910,31 @@ xelpd_dsc_compute_link_config(struct intel_dp *intel_dp,
  int pipe_bpp,
  int timeslots)
 {
-   u16 compressed_bpp;
+   u8 bppx16_incr = drm_dp_dsc_sink_bpp_incr(connector->dp.dsc_dpcd);
+   struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+   u16 compressed_bppx16;
+   u8 bppx16_step;
int ret;
 
+   if (DISPLAY_VER(i915) < 14 || bppx16_incr <= 1)
+   bppx16_step = 16;
+   else
+   bppx16_step = 16 / bppx16_incr;
+
/* Compressed BPP should be less than the Input DSC bpp */
-   dsc_max_bpp = min(dsc_max_bpp, pipe_bpp - 1);
+   dsc_max_bpp = min(dsc_max_bpp << 4, (pipe_bpp << 4) - bppx16_step);
+   dsc_min_bpp = dsc_min_bpp << 4;
 
-   for (compressed_bpp = dsc_max_bpp;
-compressed_bpp >= dsc_min_bpp;
-compressed_bpp--) {
+   for (compressed_bppx16 = dsc_max_bpp;
+compres

[Intel-gfx] [PATCH 04/11] drm/i915/audio: Consider fractional vdsc bpp while computing tu_data

2023-11-10 Thread Ankit Nautiyal
MTL+ supports fractional compressed bits_per_pixel, with precision of
1/16. This compressed bpp is stored in U6.4 format.
Accommodate the precision during calculation of transfer unit data
for hblank_early calculation.

v2:
-Fix tu_data calculation while dealing with U6.4 format. (Stan)

v3:
-Use BPP_X16_FMT to print vdsc bpp.

Signed-off-by: Ankit Nautiyal 
Reviewed-by: Suraj Kandpal 
Reviewed-by: Sui Jingfeng 
---
 drivers/gpu/drm/i915/display/intel_audio.c | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_audio.c 
b/drivers/gpu/drm/i915/display/intel_audio.c
index aa93ccd6c2aa..8796d90c46a6 100644
--- a/drivers/gpu/drm/i915/display/intel_audio.c
+++ b/drivers/gpu/drm/i915/display/intel_audio.c
@@ -521,25 +521,25 @@ static unsigned int calc_hblank_early_prog(struct 
intel_encoder *encoder,
unsigned int link_clks_available, link_clks_required;
unsigned int tu_data, tu_line, link_clks_active;
unsigned int h_active, h_total, hblank_delta, pixel_clk;
-   unsigned int fec_coeff, cdclk, vdsc_bpp;
+   unsigned int fec_coeff, cdclk, vdsc_bppx16;
unsigned int link_clk, lanes;
unsigned int hblank_rise;
 
h_active = crtc_state->hw.adjusted_mode.crtc_hdisplay;
h_total = crtc_state->hw.adjusted_mode.crtc_htotal;
pixel_clk = crtc_state->hw.adjusted_mode.crtc_clock;
-   vdsc_bpp = to_bpp_int(crtc_state->dsc.compressed_bpp_x16);
+   vdsc_bppx16 = crtc_state->dsc.compressed_bpp_x16;
cdclk = i915->display.cdclk.hw.cdclk;
/* fec= 0.972261, using rounding multiplier of 100 */
fec_coeff = 972261;
link_clk = crtc_state->port_clock;
lanes = crtc_state->lane_count;
 
-   drm_dbg_kms(>drm, "h_active = %u link_clk = %u :"
-   "lanes = %u vdsc_bpp = %u cdclk = %u\n",
-   h_active, link_clk, lanes, vdsc_bpp, cdclk);
+   drm_dbg_kms(>drm,
+   "h_active = %u link_clk = %u : lanes = %u vdsc_bpp = " 
BPP_X16_FMT " cdclk = %u\n",
+   h_active, link_clk, lanes, BPP_X16_ARGS(vdsc_bppx16), 
cdclk);
 
-   if (WARN_ON(!link_clk || !pixel_clk || !lanes || !vdsc_bpp || !cdclk))
+   if (WARN_ON(!link_clk || !pixel_clk || !lanes || !vdsc_bppx16 || 
!cdclk))
return 0;
 
link_clks_available = (h_total - h_active) * link_clk / pixel_clk - 28;
@@ -551,8 +551,8 @@ static unsigned int calc_hblank_early_prog(struct 
intel_encoder *encoder,
hblank_delta = DIV64_U64_ROUND_UP(mul_u32_u32(5 * (link_clk + 
cdclk), pixel_clk),
  mul_u32_u32(link_clk, cdclk));
 
-   tu_data = div64_u64(mul_u32_u32(pixel_clk * vdsc_bpp * 8, 100),
-   mul_u32_u32(link_clk * lanes, fec_coeff));
+   tu_data = div64_u64(mul_u32_u32(pixel_clk * vdsc_bppx16 * 8, 100),
+   mul_u32_u32(link_clk * lanes * 16, fec_coeff));
tu_line = div64_u64(h_active * mul_u32_u32(link_clk, fec_coeff),
mul_u32_u32(64 * pixel_clk, 100));
link_clks_active  = (tu_line - 1) * 64 + tu_data;
-- 
2.40.1



[Intel-gfx] [PATCH 03/11] drm/i915/display: Consider fractional vdsc bpp while computing m_n values

2023-11-10 Thread Ankit Nautiyal
MTL+ supports fractional compressed bits_per_pixel, with precision of
1/16. This compressed bpp is stored in U6.4 format.
Accommodate this precision while computing m_n values.

v1:
Replace the computation of 'data_clock' with 'data_clock =
DIV_ROUND_UP(data_clock, 16).' (Sui Jingfeng).

v2:
Rebase and pass bits_per_pixel in U6.4 format.

Signed-off-by: Ankit Nautiyal 
Signed-off-by: Mitul Golani 
Reviewed-by: Suraj Kandpal 
Reviewed-by: Sui Jingfeng 
---
 drivers/gpu/drm/i915/display/intel_display.c |  4 ++--
 drivers/gpu/drm/i915/display/intel_dp.c  | 16 
 drivers/gpu/drm/i915/display/intel_dp_mst.c  | 14 +++---
 drivers/gpu/drm/i915/display/intel_fdi.c |  3 ++-
 4 files changed, 19 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index b4a8e3087e50..125903007a29 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -2415,12 +2415,12 @@ add_bw_alloc_overhead(int link_clock, int bw_overhead,
 }
 
 void
-intel_link_compute_m_n(u16 bits_per_pixel, int nlanes,
+intel_link_compute_m_n(u16 bits_per_pixel_x16, int nlanes,
   int pixel_clock, int link_clock,
   int bw_overhead,
   struct intel_link_m_n *m_n)
 {
-   u32 data_clock = bits_per_pixel * pixel_clock;
+   u32 data_clock = DIV_ROUND_UP(bits_per_pixel_x16 * pixel_clock, 16);
u32 data_m;
u32 data_n;
 
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 4ad3718c3c7d..246f50d1f030 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2663,7 +2663,7 @@ static bool can_enable_drrs(struct intel_connector 
*connector,
 static void
 intel_dp_drrs_compute_config(struct intel_connector *connector,
 struct intel_crtc_state *pipe_config,
-int link_bpp)
+int link_bpp_x16)
 {
struct drm_i915_private *i915 = to_i915(connector->base.dev);
const struct drm_display_mode *downclock_mode =
@@ -2688,7 +2688,7 @@ intel_dp_drrs_compute_config(struct intel_connector 
*connector,
if (pipe_config->splitter.enable)
pixel_clock /= pipe_config->splitter.link_count;
 
-   intel_link_compute_m_n(link_bpp, pipe_config->lane_count, pixel_clock,
+   intel_link_compute_m_n(link_bpp_x16, pipe_config->lane_count, 
pixel_clock,
   pipe_config->port_clock,
   
intel_dp_bw_fec_overhead(pipe_config->fec_enable),
   _config->dp_m2_n2);
@@ -2792,7 +2792,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
const struct drm_display_mode *fixed_mode;
struct intel_connector *connector = intel_dp->attached_connector;
-   int ret = 0, link_bpp;
+   int ret = 0, link_bpp_x16;
 
if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv) && encoder->port != 
PORT_A)
pipe_config->has_pch_encoder = true;
@@ -2841,10 +2841,10 @@ intel_dp_compute_config(struct intel_encoder *encoder,
drm_dp_enhanced_frame_cap(intel_dp->dpcd);
 
if (pipe_config->dsc.compression_enable)
-   link_bpp = to_bpp_int(pipe_config->dsc.compressed_bpp_x16);
+   link_bpp_x16 = pipe_config->dsc.compressed_bpp_x16;
else
-   link_bpp = intel_dp_output_bpp(pipe_config->output_format,
-  pipe_config->pipe_bpp);
+   link_bpp_x16 = 
to_bpp_x16(intel_dp_output_bpp(pipe_config->output_format,
+ 
pipe_config->pipe_bpp));
 
if (intel_dp->mso_link_count) {
int n = intel_dp->mso_link_count;
@@ -2868,7 +2868,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 
intel_dp_audio_compute_config(encoder, pipe_config, conn_state);
 
-   intel_link_compute_m_n(link_bpp,
+   intel_link_compute_m_n(link_bpp_x16,
   pipe_config->lane_count,
   adjusted_mode->crtc_clock,
   pipe_config->port_clock,
@@ -2884,7 +2884,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 
intel_vrr_compute_config(pipe_config, conn_state);
intel_psr_compute_config(intel_dp, pipe_config, conn_state);
-   intel_dp_drrs_compute_config(connector, pipe_config, link_bpp);
+   intel_dp_drrs_compute_config(connector, pipe_config, link_bpp_x16);
intel_dp_compute_vsc_sdp(intel_dp, pipe_config, conn_state);
intel_dp_compute_hdr_metadata_infoframe_sdp(intel_dp, pipe_config, 
co

[Intel-gfx] [PATCH 02/11] drm/i915/display: Store compressed bpp in U6.4 format

2023-11-10 Thread Ankit Nautiyal
DSC parameter bits_per_pixel is stored in U6.4 format.
The 4 bits represent the fractional part of the bpp.
Currently we use compressed_bpp member of dsc structure to store
only the integral part of the bits_per_pixel.
To store the full bits_per_pixel along with the fractional part,
compressed_bpp is changed to store bpp in U6.4 formats. Intergral
part is retrieved by simply right shifting the member compressed_bpp by 4.

v2:
-Use to_bpp_int, to_bpp_frac_dec, to_bpp_x16 helpers while dealing
 with compressed bpp. (Suraj)
-Fix comment styling. (Suraj)

v3:
-Add separate file for 6.4 fixed point helper(Jani, Nikula)
-Add comment for magic values(Suraj)

v4:
-Fix checkpatch warnings caused by renaming(Suraj)

v5:
-Rebase.
-Use existing helpers for conversion of bpp_int to bpp_x16
 and vice versa.

Signed-off-by: Ankit Nautiyal 
Signed-off-by: Mitul Golani 
Reviewed-by: Suraj Kandpal 
Reviewed-by: Sui Jingfeng 
---
 drivers/gpu/drm/i915/display/icl_dsi.c| 10 +++
 drivers/gpu/drm/i915/display/intel_audio.c|  2 +-
 drivers/gpu/drm/i915/display/intel_bios.c |  4 +--
 drivers/gpu/drm/i915/display/intel_cdclk.c|  5 ++--
 drivers/gpu/drm/i915/display/intel_display.c  |  2 +-
 .../drm/i915/display/intel_display_types.h|  3 ++-
 drivers/gpu/drm/i915/display/intel_dp.c   | 27 ++-
 drivers/gpu/drm/i915/display/intel_dp_mst.c   |  2 +-
 drivers/gpu/drm/i915/display/intel_link_bw.c  |  2 +-
 drivers/gpu/drm/i915/display/intel_vdsc.c |  4 +--
 10 files changed, 33 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c 
b/drivers/gpu/drm/i915/display/icl_dsi.c
index c4585e445198..481fcb650850 100644
--- a/drivers/gpu/drm/i915/display/icl_dsi.c
+++ b/drivers/gpu/drm/i915/display/icl_dsi.c
@@ -330,7 +330,7 @@ static int afe_clk(struct intel_encoder *encoder,
int bpp;
 
if (crtc_state->dsc.compression_enable)
-   bpp = crtc_state->dsc.compressed_bpp;
+   bpp = to_bpp_int(crtc_state->dsc.compressed_bpp_x16);
else
bpp = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format);
 
@@ -860,7 +860,7 @@ gen11_dsi_set_transcoder_timings(struct intel_encoder 
*encoder,
 * compressed and non-compressed bpp.
 */
if (crtc_state->dsc.compression_enable) {
-   mul = crtc_state->dsc.compressed_bpp;
+   mul = to_bpp_int(crtc_state->dsc.compressed_bpp_x16);
div = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format);
}
 
@@ -884,7 +884,7 @@ gen11_dsi_set_transcoder_timings(struct intel_encoder 
*encoder,
int bpp, line_time_us, byte_clk_period_ns;
 
if (crtc_state->dsc.compression_enable)
-   bpp = crtc_state->dsc.compressed_bpp;
+   bpp = to_bpp_int(crtc_state->dsc.compressed_bpp_x16);
else
bpp = 
mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format);
 
@@ -1451,8 +1451,8 @@ static void gen11_dsi_get_timings(struct intel_encoder 
*encoder,
struct drm_display_mode *adjusted_mode =
_config->hw.adjusted_mode;
 
-   if (pipe_config->dsc.compressed_bpp) {
-   int div = pipe_config->dsc.compressed_bpp;
+   if (pipe_config->dsc.compressed_bpp_x16) {
+   int div = to_bpp_int(pipe_config->dsc.compressed_bpp_x16);
int mul = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format);
 
adjusted_mode->crtc_htotal =
diff --git a/drivers/gpu/drm/i915/display/intel_audio.c 
b/drivers/gpu/drm/i915/display/intel_audio.c
index 19605264a35c..aa93ccd6c2aa 100644
--- a/drivers/gpu/drm/i915/display/intel_audio.c
+++ b/drivers/gpu/drm/i915/display/intel_audio.c
@@ -528,7 +528,7 @@ static unsigned int calc_hblank_early_prog(struct 
intel_encoder *encoder,
h_active = crtc_state->hw.adjusted_mode.crtc_hdisplay;
h_total = crtc_state->hw.adjusted_mode.crtc_htotal;
pixel_clk = crtc_state->hw.adjusted_mode.crtc_clock;
-   vdsc_bpp = crtc_state->dsc.compressed_bpp;
+   vdsc_bpp = to_bpp_int(crtc_state->dsc.compressed_bpp_x16);
cdclk = i915->display.cdclk.hw.cdclk;
/* fec= 0.972261, using rounding multiplier of 100 */
fec_coeff = 972261;
diff --git a/drivers/gpu/drm/i915/display/intel_bios.c 
b/drivers/gpu/drm/i915/display/intel_bios.c
index 719fb550342b..2fd72b2fd109 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -3414,8 +3414,8 @@ static void fill_dsc(struct intel_crtc_state *crtc_state,
 
crtc_state->pipe_bpp = bpc * 3;
 
-   crtc_state->dsc.compressed_bpp = min(crtc_state->pipe_bpp,
-VBT_DSC_MAX_BPP(dsc->max_bpp));
+   crtc_state->dsc.compressed_bpp_x16 = 
to_bpp_x16(min(crtc_sta

[Intel-gfx] [PATCH 01/11] drm/display/dp: Add helper function to get DSC bpp precision

2023-11-10 Thread Ankit Nautiyal
Add helper to get the DSC bits_per_pixel precision for the DP sink.

Signed-off-by: Ankit Nautiyal 
Reviewed-by: Suraj Kandpal 
Reviewed-by: Sui Jingfeng 
Acked-by: Maxime Ripard 
---
 drivers/gpu/drm/display/drm_dp_helper.c | 27 +
 include/drm/display/drm_dp_helper.h |  1 +
 2 files changed, 28 insertions(+)

diff --git a/drivers/gpu/drm/display/drm_dp_helper.c 
b/drivers/gpu/drm/display/drm_dp_helper.c
index 72ba9ae89f86..d72b6f9a352c 100644
--- a/drivers/gpu/drm/display/drm_dp_helper.c
+++ b/drivers/gpu/drm/display/drm_dp_helper.c
@@ -2328,6 +2328,33 @@ int drm_dp_read_desc(struct drm_dp_aux *aux, struct 
drm_dp_desc *desc,
 }
 EXPORT_SYMBOL(drm_dp_read_desc);
 
+/**
+ * drm_dp_dsc_sink_bpp_incr() - Get bits per pixel increment
+ * @dsc_dpcd: DSC capabilities from DPCD
+ *
+ * Returns the bpp precision supported by the DP sink.
+ */
+u8 drm_dp_dsc_sink_bpp_incr(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE])
+{
+   u8 bpp_increment_dpcd = dsc_dpcd[DP_DSC_BITS_PER_PIXEL_INC - 
DP_DSC_SUPPORT];
+
+   switch (bpp_increment_dpcd) {
+   case DP_DSC_BITS_PER_PIXEL_1_16:
+   return 16;
+   case DP_DSC_BITS_PER_PIXEL_1_8:
+   return 8;
+   case DP_DSC_BITS_PER_PIXEL_1_4:
+   return 4;
+   case DP_DSC_BITS_PER_PIXEL_1_2:
+   return 2;
+   case DP_DSC_BITS_PER_PIXEL_1_1:
+   return 1;
+   }
+
+   return 0;
+}
+EXPORT_SYMBOL(drm_dp_dsc_sink_bpp_incr);
+
 /**
  * drm_dp_dsc_sink_max_slice_count() - Get the max slice count
  * supported by the DSC sink.
diff --git a/include/drm/display/drm_dp_helper.h 
b/include/drm/display/drm_dp_helper.h
index caee29d28463..c5f1079acb3b 100644
--- a/include/drm/display/drm_dp_helper.h
+++ b/include/drm/display/drm_dp_helper.h
@@ -164,6 +164,7 @@ drm_dp_is_branch(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
 }
 
 /* DP/eDP DSC support */
+u8 drm_dp_dsc_sink_bpp_incr(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE]);
 u8 drm_dp_dsc_sink_max_slice_count(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE],
   bool is_edp);
 u8 drm_dp_dsc_sink_line_buf_depth(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE]);
-- 
2.40.1



[Intel-gfx] [PATCH 00/11] Add DSC fractional bpp support

2023-11-10 Thread Ankit Nautiyal
This patch series adds support for DSC fractional compressed bpp
for MTL+. The series starts with some fixes, followed by patches that
lay groundwork to iterate over valid compressed bpps to select the
'best' compressed bpp with optimal link configuration (taken from
upstream series: https://patchwork.freedesktop.org/series/105200/).

The later patches, add changes to accommodate compressed bpp with
fractional part, including changes to QP calculations.
To get the 'best' compressed bpp, we iterate over the valid compressed
bpp values, but with fractional step size 1/16, 1/8, 1/4 or 1/2 as per
sink support.

The last 2 patches add support to depict DSC sink's fractional support,
and debugfs to enforce use of fractional bpp, while choosing an
appropriate compressed bpp.

Rev10: Rebased and added DSC Fractional support for DP MST.

Ankit Nautiyal (8):
  drm/display/dp: Add helper function to get DSC bpp precision
  drm/i915/display: Store compressed bpp in U6.4 format
  drm/i915/display: Consider fractional vdsc bpp while computing m_n
values
  drm/i915/audio: Consider fractional vdsc bpp while computing tu_data
  drm/i915/dp: Iterate over output bpp with fractional step size
  drm/i915/dp_mst: Use precision of 1/16 for computing bpp
  drm/i916/dp_mst: Iterate over the DSC bpps as per DSC precision
support
  drm/i915/dp_mst: Add support for forcing dsc fractional bpp via
debugfs

Swati Sharma (2):
  drm/i915/dsc: Add debugfs entry to validate DSC fractional bpp
  drm/i915/dsc: Allow DSC only with fractional bpp when forced from
debugfs

Vandita Kulkarni (1):
  drm/i915/dsc/mtl: Add support for fractional bpp

 drivers/gpu/drm/display/drm_dp_helper.c   | 27 ++
 drivers/gpu/drm/i915/display/icl_dsi.c| 10 +--
 drivers/gpu/drm/i915/display/intel_audio.c| 16 ++--
 drivers/gpu/drm/i915/display/intel_bios.c |  4 +-
 drivers/gpu/drm/i915/display/intel_cdclk.c|  5 +-
 drivers/gpu/drm/i915/display/intel_display.c  |  6 +-
 .../drm/i915/display/intel_display_debugfs.c  | 84 ++
 .../drm/i915/display/intel_display_types.h|  4 +-
 drivers/gpu/drm/i915/display/intel_dp.c   | 87 +++
 drivers/gpu/drm/i915/display/intel_dp_mst.c   | 85 +++---
 drivers/gpu/drm/i915/display/intel_fdi.c  |  3 +-
 drivers/gpu/drm/i915/display/intel_link_bw.c  |  2 +-
 .../gpu/drm/i915/display/intel_qp_tables.c|  3 -
 drivers/gpu/drm/i915/display/intel_vdsc.c | 29 +--
 include/drm/display/drm_dp_helper.h   |  1 +
 15 files changed, 266 insertions(+), 100 deletions(-)

-- 
2.40.1



[Intel-gfx] [PATCH 1/4] drm/i915/dp: Simplify checks for helper intel_dp_dsc_max_src_input_bpc

2023-11-08 Thread Ankit Nautiyal
In helper intel_dp_dsc_max_src_input_bpc it is assumed that platforms
earlier to ICL do not support DSC, and the function returns 0 for
those platforms.

Use HAS_DSC macro instead and return 0 for platforms that do not support
DSC.

v2: Updated commit message with clarification. (Jani)

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 5391b2a83405..30ea4820b210 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1569,13 +1569,14 @@ intel_dp_compute_link_config_wide(struct intel_dp 
*intel_dp,
 static
 u8 intel_dp_dsc_max_src_input_bpc(struct drm_i915_private *i915)
 {
+   if (!HAS_DSC(i915))
+   return 0;
+
/* Max DSC Input BPC for ICL is 10 and for TGL+ is 12 */
-   if (DISPLAY_VER(i915) >= 12)
-   return 12;
if (DISPLAY_VER(i915) == 11)
return 10;
 
-   return 0;
+   return 12;
 }
 
 int intel_dp_dsc_compute_max_bpp(const struct intel_connector *connector,
-- 
2.40.1



[Intel-gfx] [PATCH 4/4] drm/i915/dp: Ignore max_requested_bpc if its too low for DSC

2023-11-06 Thread Ankit Nautiyal
At the moment, while choosing the input bpc for DSC, we take into
account the max_requested_bpc property. This creates a problem, if the
max_requested_bpc is lower than the minimum bpc required by source with
DSC.

So consider max_requested_bpc if its within the limits that we can
support with DSC.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 22 ++
 1 file changed, 18 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index abc718f1a878..ea4c42a5705e 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1578,6 +1578,16 @@ u8 intel_dp_dsc_max_src_input_bpc(struct 
drm_i915_private *i915)
return 12;
 }
 
+static int
+intel_dp_dsc_limit_max_bpc(int max_requested_bpc, int src_dsc_max_bpc, int 
src_dsc_min_bpc)
+{
+   /* Consider max_requested_bpc only if src can support it with DSC */
+   if (max_requested_bpc >= src_dsc_min_bpc)
+   return min(src_dsc_max_bpc, max_requested_bpc);
+
+   return src_dsc_max_bpc;
+}
+
 int intel_dp_dsc_compute_max_bpp(const struct intel_connector *connector,
 u8 max_req_bpc)
 {
@@ -1591,7 +1601,8 @@ int intel_dp_dsc_compute_max_bpp(const struct 
intel_connector *connector,
if (!dsc_max_bpc)
return dsc_max_bpc;
 
-   dsc_max_bpc = min_t(u8, dsc_max_bpc, max_req_bpc);
+   dsc_max_bpc = intel_dp_dsc_limit_max_bpc(max_req_bpc, dsc_max_bpc,
+
intel_dp_dsc_min_src_input_bpc(i915));
 
num_bpc = drm_dp_dsc_sink_supported_input_bpcs(connector->dp.dsc_dpcd,
   dsc_bpc);
@@ -1959,8 +1970,11 @@ bool is_dsc_pipe_bpp_sufficient(struct drm_i915_private 
*i915,
 {
u8 dsc_max_bpc, dsc_min_bpc, dsc_max_pipe_bpp, dsc_min_pipe_bpp;
 
-   dsc_max_bpc = min(intel_dp_dsc_max_src_input_bpc(i915), 
conn_state->max_requested_bpc);
dsc_min_bpc = intel_dp_dsc_min_src_input_bpc(i915);
+   dsc_max_bpc = intel_dp_dsc_max_src_input_bpc(i915);
+
+   dsc_max_bpc = intel_dp_dsc_limit_max_bpc(conn_state->max_requested_bpc,
+dsc_max_bpc, dsc_min_bpc);
 
dsc_max_pipe_bpp = min(dsc_max_bpc * 3, limits->pipe.max_bpp);
dsc_min_pipe_bpp = max(dsc_min_bpc * 3, limits->pipe.min_bpp);
@@ -2020,14 +2034,14 @@ static int intel_dp_dsc_compute_pipe_bpp(struct 
intel_dp *intel_dp,
}
}
 
+   dsc_min_bpc = intel_dp_dsc_min_src_input_bpc(i915);
dsc_max_bpc = intel_dp_dsc_max_src_input_bpc(i915);
if (!dsc_max_bpc)
return -EINVAL;
 
-   dsc_max_bpc = min_t(u8, dsc_max_bpc, max_req_bpc);
+   dsc_max_bpc = intel_dp_dsc_limit_max_bpc(max_req_bpc, dsc_max_bpc, 
dsc_min_bpc);
dsc_max_bpp = min(dsc_max_bpc * 3, limits->pipe.max_bpp);
 
-   dsc_min_bpc = intel_dp_dsc_min_src_input_bpc(i915);
dsc_min_bpp = max(dsc_min_bpc * 3, limits->pipe.min_bpp);
 
/*
-- 
2.40.1



  1   2   3   4   5   6   7   8   >