[PATCH v6 4/6] drm/i915/alpm: Add compute config for lobf

2024-05-27 Thread Animesh Manna
Link Off Between Active Frames, is a new feature for eDP
that allows the panel to go to lower power state after
transmission of data. This is a feature on top of ALPM, AS SDP.
Add compute config during atomic-check phase.

v1: RFC version.
v2: Add separate flag for auxless-alpm. [Jani]
v3:
- intel_dp->lobf_supported replaced with crtc_state->has_lobf. [Jouni]
- Add DISPLAY_VER() check. [Jouni]
- Modify function name of get_aux_less_status. [Jani]
v4: Add enum alpm_mode to hold the aux-wake/less capability.
v5: Add alpm_dpcd to intel_dp and use aux_wake_supported()/
aux_less_wake_supported() instead of enum alpm_mode. [Jouni]

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_alpm.c | 61 +++
 drivers/gpu/drm/i915/display/intel_alpm.h |  5 ++
 .../drm/i915/display/intel_display_types.h|  5 ++
 drivers/gpu/drm/i915/display/intel_dp.c   |  4 ++
 4 files changed, 75 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c 
b/drivers/gpu/drm/i915/display/intel_alpm.c
index 7307e02277d6..3ac5986b4ad9 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.c
+++ b/drivers/gpu/drm/i915/display/intel_alpm.c
@@ -11,6 +11,26 @@
 #include "intel_dp_aux.h"
 #include "intel_psr_regs.h"
 
+static bool intel_alpm_aux_wake_supported(struct intel_dp *intel_dp)
+{
+   return intel_dp->alpm_dpcd & DP_ALPM_CAP;
+}
+
+static bool intel_alpm_aux_less_wake_supported(struct intel_dp *intel_dp)
+{
+   return intel_dp->alpm_dpcd & DP_ALPM_AUX_LESS_CAP;
+}
+
+void intel_alpm_init_dpcd(struct intel_dp *intel_dp)
+{
+   u8 dpcd;
+
+   if (drm_dp_dpcd_readb(_dp->aux, DP_RECEIVER_ALPM_CAP, ) < 0)
+   return;
+
+   intel_dp->alpm_dpcd = dpcd;
+}
+
 /*
  * See Bspec: 71632 for the table
  *
@@ -243,6 +263,47 @@ bool intel_alpm_compute_params(struct intel_dp *intel_dp,
return true;
 }
 
+void intel_alpm_lobf_compute_config(struct intel_dp *intel_dp,
+   struct intel_crtc_state *crtc_state,
+   struct drm_connector_state *conn_state)
+{
+   struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+   struct drm_display_mode *adjusted_mode = _state->hw.adjusted_mode;
+   int waketime_in_lines, first_sdp_position;
+   int context_latency, guardband;
+
+   if (!intel_dp_is_edp(intel_dp))
+   return;
+
+   if (DISPLAY_VER(i915) < 20)
+   return;
+
+   if (!intel_dp_as_sdp_supported(intel_dp))
+   return;
+
+   if (crtc_state->has_psr)
+   return;
+
+   if (!(intel_alpm_aux_wake_supported(intel_dp) ||
+ intel_alpm_aux_less_wake_supported(intel_dp)))
+   return;
+
+   if (!intel_alpm_compute_params(intel_dp, crtc_state))
+   return;
+
+   context_latency = adjusted_mode->crtc_vblank_start - 
adjusted_mode->crtc_vdisplay;
+   guardband = adjusted_mode->crtc_vtotal -
+   adjusted_mode->crtc_vdisplay - context_latency;
+   first_sdp_position = adjusted_mode->crtc_vtotal - 
adjusted_mode->crtc_vsync_start;
+   if (intel_alpm_aux_less_wake_supported(intel_dp))
+   waketime_in_lines = intel_dp->alpm_parameters.io_wake_lines;
+   else
+   waketime_in_lines = intel_dp->alpm_parameters.fast_wake_lines;
+
+   crtc_state->has_lobf = (context_latency + guardband) >
+   (first_sdp_position + waketime_in_lines);
+}
+
 static void lnl_alpm_configure(struct intel_dp *intel_dp)
 {
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
diff --git a/drivers/gpu/drm/i915/display/intel_alpm.h 
b/drivers/gpu/drm/i915/display/intel_alpm.h
index c45d078e5a6b..e586e8a01b10 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.h
+++ b/drivers/gpu/drm/i915/display/intel_alpm.h
@@ -10,9 +10,14 @@
 
 struct intel_dp;
 struct intel_crtc_state;
+struct drm_connector_state;
 
+void intel_alpm_init_dpcd(struct intel_dp *intel_dp);
 bool intel_alpm_compute_params(struct intel_dp *intel_dp,
   struct intel_crtc_state *crtc_state);
+void intel_alpm_lobf_compute_config(struct intel_dp *intel_dp,
+   struct intel_crtc_state *crtc_state,
+   struct drm_connector_state *conn_state);
 void intel_alpm_configure(struct intel_dp *intel_dp);
 
 #endif
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index 0ad6134ba94e..d77a9f22b5c6 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1410,6 +1410,9 @@ struct intel_crtc_state {
 
/* for loading single buffered registers during vblank */
struct drm_vblank_work vblank_work;
+
+   /* LOBF flag */
+   bool has_lobf;
 };
 

[PATCH v6 6/6] drm/i915/alpm: Add debugfs for LOBF

2024-05-27 Thread Animesh Manna
For validation purpose add debugfs for LOBF.

v1: Initial version.
v2: Add aux-wake/less info along with lobf status. [Jouni]

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_alpm.c | 49 +++
 drivers/gpu/drm/i915/display/intel_alpm.h |  2 +
 .../drm/i915/display/intel_display_debugfs.c  |  2 +
 3 files changed, 53 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c 
b/drivers/gpu/drm/i915/display/intel_alpm.c
index a8ae5f65a250..a26716c14aa3 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.c
+++ b/drivers/gpu/drm/i915/display/intel_alpm.c
@@ -360,3 +360,52 @@ void intel_alpm_configure(struct intel_dp *intel_dp,
 {
lnl_alpm_configure(intel_dp, crtc_state);
 }
+
+static int i915_edp_lobf_info_show(struct seq_file *m, void *data)
+{
+   struct intel_connector *connector = m->private;
+   struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+   struct drm_crtc *crtc;
+   struct intel_crtc_state *crtc_state;
+   enum transcoder cpu_transcoder;
+   u32 alpm_ctl;
+   int ret;
+
+   ret = 
drm_modeset_lock_single_interruptible(_priv->drm.mode_config.connection_mutex);
+   if (ret)
+   return ret;
+
+   crtc = connector->base.state->crtc;
+   if (connector->base.status != connector_status_connected || !crtc) {
+   ret = -ENODEV;
+   goto out;
+   }
+
+   crtc_state = to_intel_crtc_state(crtc->state);
+   cpu_transcoder = crtc_state->cpu_transcoder;
+   alpm_ctl = intel_de_read(dev_priv, ALPM_CTL(dev_priv, cpu_transcoder));
+   seq_printf(m, "LOBF status: %s\n", str_enabled_disabled(alpm_ctl & 
ALPM_CTL_LOBF_ENABLE));
+   seq_printf(m, "Aux-wake alpm status: %s\n",
+  str_enabled_disabled(!(alpm_ctl & 
ALPM_CTL_ALPM_AUX_LESS_ENABLE)));
+   seq_printf(m, "Aux-less alpm status: %s\n",
+  str_enabled_disabled(alpm_ctl & 
ALPM_CTL_ALPM_AUX_LESS_ENABLE));
+out:
+   drm_modeset_unlock(_priv->drm.mode_config.connection_mutex);
+
+   return ret;
+}
+
+DEFINE_SHOW_ATTRIBUTE(i915_edp_lobf_info);
+
+void intel_alpm_lobf_debugfs_add(struct intel_connector *connector)
+{
+   struct drm_i915_private *i915 = to_i915(connector->base.dev);
+   struct dentry *root = connector->base.debugfs_entry;
+
+   if (DISPLAY_VER(i915) < 20 ||
+   connector->base.connector_type != DRM_MODE_CONNECTOR_eDP)
+   return;
+
+   debugfs_create_file("i915_edp_lobf_info", 0444, root,
+   connector, _edp_lobf_info_fops);
+}
diff --git a/drivers/gpu/drm/i915/display/intel_alpm.h 
b/drivers/gpu/drm/i915/display/intel_alpm.h
index 80b9ca086a49..c82ecc7b4001 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.h
+++ b/drivers/gpu/drm/i915/display/intel_alpm.h
@@ -11,6 +11,7 @@
 struct intel_dp;
 struct intel_crtc_state;
 struct drm_connector_state;
+struct intel_connector;
 
 void intel_alpm_init_dpcd(struct intel_dp *intel_dp);
 bool intel_alpm_compute_params(struct intel_dp *intel_dp,
@@ -20,4 +21,5 @@ void intel_alpm_lobf_compute_config(struct intel_dp *intel_dp,
struct drm_connector_state *conn_state);
 void intel_alpm_configure(struct intel_dp *intel_dp,
  const struct intel_crtc_state *crtc_state);
+void intel_alpm_lobf_debugfs_add(struct intel_connector *connector);
 #endif
diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c 
b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
index 35f9f86ef70f..86d9900c40af 100644
--- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
+++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
@@ -13,6 +13,7 @@
 #include "i915_debugfs.h"
 #include "i915_irq.h"
 #include "i915_reg.h"
+#include "intel_alpm.h"
 #include "intel_crtc.h"
 #include "intel_de.h"
 #include "intel_crtc_state_dump.h"
@@ -1515,6 +1516,7 @@ void intel_connector_debugfs_add(struct intel_connector 
*connector)
intel_drrs_connector_debugfs_add(connector);
intel_pps_connector_debugfs_add(connector);
intel_psr_connector_debugfs_add(connector);
+   intel_alpm_lobf_debugfs_add(connector);
 
if (connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
connector_type == DRM_MODE_CONNECTOR_HDMIA ||
-- 
2.29.0



[PATCH v6 3/6] drm/display: Add missing aux less alpm wake related bits

2024-05-27 Thread Animesh Manna
From: Jouni Högander 

eDP1.5 adds some more bits into DP_RECEIVER_ALPM_CAP and
DP_RECEIVER_ALPM_CONFIG registers. Add definitions for these.

Signed-off-by: Jouni Högander 
---
 include/drm/display/drm_dp.h | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/include/drm/display/drm_dp.h b/include/drm/display/drm_dp.h
index 906949ca3cee..3317ff88ed59 100644
--- a/include/drm/display/drm_dp.h
+++ b/include/drm/display/drm_dp.h
@@ -232,6 +232,8 @@
 
 #define DP_RECEIVER_ALPM_CAP   0x02e   /* eDP 1.4 */
 # define DP_ALPM_CAP   (1 << 0)
+# define DP_ALPM_PM_STATE_2A_SUPPORT   (1 << 1) /* eDP 1.5 */
+# define DP_ALPM_AUX_LESS_CAP  (1 << 2) /* eDP 1.5 */
 
 #define DP_SINK_DEVICE_AUX_FRAME_SYNC_CAP   0x02f   /* eDP 1.4 */
 # define DP_AUX_FRAME_SYNC_CAP (1 << 0)
@@ -683,7 +685,8 @@
 
 #define DP_RECEIVER_ALPM_CONFIG0x116   /* eDP 1.4 */
 # define DP_ALPM_ENABLE(1 << 0)
-# define DP_ALPM_LOCK_ERROR_IRQ_HPD_ENABLE  (1 << 1)
+# define DP_ALPM_LOCK_ERROR_IRQ_HPD_ENABLE  (1 << 1) /* eDP 1.5 */
+# define DP_ALPM_MODE_AUX_LESS (1 << 2) /* eDP 1.5 */
 
 #define DP_SINK_DEVICE_AUX_FRAME_SYNC_CONF  0x117   /* eDP 1.4 */
 # define DP_AUX_FRAME_SYNC_ENABLE  (1 << 0)
-- 
2.29.0



[PATCH v6 5/6] drm/i915/alpm: Enable lobf from source in ALPM_CTL

2024-05-27 Thread Animesh Manna
Set the Link Off Between Frames Enable bit in ALPM_CTL register.

Note: Lobf need to be enabled adaptive sync fixed refresh mode
where vmin = vmax = flipline, which will arise after cmmr feature
enablement. Will add enabling sequence in a separate patch.

v1: Initial version.
v2: Condition check modified in alpm_configure(). [Jouni]

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_alpm.c | 16 +++-
 drivers/gpu/drm/i915/display/intel_alpm.h |  4 ++--
 drivers/gpu/drm/i915/display/intel_psr.c  |  2 +-
 3 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c 
b/drivers/gpu/drm/i915/display/intel_alpm.c
index 3ac5986b4ad9..a8ae5f65a250 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.c
+++ b/drivers/gpu/drm/i915/display/intel_alpm.c
@@ -304,10 +304,11 @@ void intel_alpm_lobf_compute_config(struct intel_dp 
*intel_dp,
(first_sdp_position + waketime_in_lines);
 }
 
-static void lnl_alpm_configure(struct intel_dp *intel_dp)
+static void lnl_alpm_configure(struct intel_dp *intel_dp,
+  const struct intel_crtc_state *crtc_state)
 {
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-   enum transcoder cpu_transcoder = intel_dp->psr.transcoder;
+   enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
u32 alpm_ctl;
 
if (DISPLAY_VER(dev_priv) < 20 || (!intel_dp->psr.sel_update_enabled &&
@@ -318,7 +319,8 @@ static void lnl_alpm_configure(struct intel_dp *intel_dp)
 * Panel Replay on eDP is always using ALPM aux less. I.e. no need to
 * check panel support at this point.
 */
-   if (intel_dp->psr.panel_replay_enabled && intel_dp_is_edp(intel_dp)) {
+   if ((intel_dp->psr.panel_replay_enabled && intel_dp_is_edp(intel_dp)) ||
+   (crtc_state->has_lobf && 
intel_alpm_aux_less_wake_supported(intel_dp))) {
alpm_ctl = ALPM_CTL_ALPM_ENABLE |
ALPM_CTL_ALPM_AUX_LESS_ENABLE |
ALPM_CTL_AUX_LESS_SLEEP_HOLD_TIME_50_SYMBOLS;
@@ -345,12 +347,16 @@ static void lnl_alpm_configure(struct intel_dp *intel_dp)

ALPM_CTL_EXTENDED_FAST_WAKE_TIME(intel_dp->alpm_parameters.fast_wake_lines);
}
 
+   if (crtc_state->has_lobf)
+   alpm_ctl |= ALPM_CTL_LOBF_ENABLE;
+
alpm_ctl |= 
ALPM_CTL_ALPM_ENTRY_CHECK(intel_dp->alpm_parameters.check_entry_lines);
 
intel_de_write(dev_priv, ALPM_CTL(dev_priv, cpu_transcoder), alpm_ctl);
 }
 
-void intel_alpm_configure(struct intel_dp *intel_dp)
+void intel_alpm_configure(struct intel_dp *intel_dp,
+ const struct intel_crtc_state *crtc_state)
 {
-   lnl_alpm_configure(intel_dp);
+   lnl_alpm_configure(intel_dp, crtc_state);
 }
diff --git a/drivers/gpu/drm/i915/display/intel_alpm.h 
b/drivers/gpu/drm/i915/display/intel_alpm.h
index e586e8a01b10..80b9ca086a49 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.h
+++ b/drivers/gpu/drm/i915/display/intel_alpm.h
@@ -18,6 +18,6 @@ bool intel_alpm_compute_params(struct intel_dp *intel_dp,
 void intel_alpm_lobf_compute_config(struct intel_dp *intel_dp,
struct intel_crtc_state *crtc_state,
struct drm_connector_state *conn_state);
-void intel_alpm_configure(struct intel_dp *intel_dp);
-
+void intel_alpm_configure(struct intel_dp *intel_dp,
+ const struct intel_crtc_state *crtc_state);
 #endif
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index b37dfadb994b..ac6b4614fe29 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -1692,7 +1692,7 @@ static void intel_psr_enable_source(struct intel_dp 
*intel_dp,
 IGNORE_PSR2_HW_TRACKING : 0);
 
if (intel_dp_is_edp(intel_dp))
-   intel_alpm_configure(intel_dp);
+   intel_alpm_configure(intel_dp, crtc_state);
 
/*
 * Wa_16013835468
-- 
2.29.0



[PATCH v6 2/6] drm/i915/alpm: Move alpm related code to a new file

2024-05-27 Thread Animesh Manna
Move ALPM feature related code as it will be used for
non-psr panel also thorugh LOBF feature.

v1: Initial version.
v2: Correct ordering in makefile. [Jani]

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/Makefile |   1 +
 drivers/gpu/drm/i915/display/intel_alpm.c | 295 ++
 drivers/gpu/drm/i915/display/intel_alpm.h |  18 ++
 drivers/gpu/drm/i915/display/intel_psr.c  | 283 +
 drivers/gpu/drm/xe/Makefile   |   1 +
 5 files changed, 318 insertions(+), 280 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_alpm.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_alpm.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 7cad944b825c..9a3f910ce4fd 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -243,6 +243,7 @@ i915-y += \
display/hsw_ips.o \
display/i9xx_plane.o \
display/i9xx_wm.o \
+   display/intel_alpm.o \
display/intel_atomic.o \
display/intel_atomic_plane.o \
display/intel_audio.o \
diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c 
b/drivers/gpu/drm/i915/display/intel_alpm.c
new file mode 100644
index ..7307e02277d6
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_alpm.c
@@ -0,0 +1,295 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2024, Intel Corporation.
+ */
+
+#include "intel_alpm.h"
+#include "intel_crtc.h"
+#include "intel_de.h"
+#include "intel_display_types.h"
+#include "intel_dp.h"
+#include "intel_dp_aux.h"
+#include "intel_psr_regs.h"
+
+/*
+ * See Bspec: 71632 for the table
+ *
+ * Silence_period = tSilence,Min + ((tSilence,Max - tSilence,Min) / 2)
+ *
+ * Half cycle duration:
+ *
+ * Link rates 1.62 - 4.32 and tLFPS_Cycle = 70 ns
+ * FLOOR( (Link Rate * tLFPS_Cycle) / (2 * 10) )
+ *
+ * Link rates 5.4 - 8.1
+ * PORT_ALPM_LFPS_CTL[ LFPS Cycle Count ] = 10
+ * LFPS Period chosen is the mid-point of the min:max values from the table
+ * FLOOR( LFPS Period in Symbol clocks /
+ * (2 * PORT_ALPM_LFPS_CTL[ LFPS Cycle Count ]) )
+ */
+static bool _lnl_get_silence_period_and_lfps_half_cycle(int link_rate,
+   int *silence_period,
+   int *lfps_half_cycle)
+{
+   switch (link_rate) {
+   case 162000:
+   *silence_period = 20;
+   *lfps_half_cycle = 5;
+   break;
+   case 216000:
+   *silence_period = 27;
+   *lfps_half_cycle = 7;
+   break;
+   case 243000:
+   *silence_period = 31;
+   *lfps_half_cycle = 8;
+   break;
+   case 27:
+   *silence_period = 34;
+   *lfps_half_cycle = 9;
+   break;
+   case 324000:
+   *silence_period = 41;
+   *lfps_half_cycle = 11;
+   break;
+   case 432000:
+   *silence_period = 56;
+   *lfps_half_cycle = 15;
+   break;
+   case 54:
+   *silence_period = 69;
+   *lfps_half_cycle = 12;
+   break;
+   case 648000:
+   *silence_period = 84;
+   *lfps_half_cycle = 15;
+   break;
+   case 675000:
+   *silence_period = 87;
+   *lfps_half_cycle = 15;
+   break;
+   case 81:
+   *silence_period = 104;
+   *lfps_half_cycle = 19;
+   break;
+   default:
+   *silence_period = *lfps_half_cycle = -1;
+   return false;
+   }
+   return true;
+}
+
+/*
+ * AUX-Less Wake Time = CEILING( ((PHY P2 to P0) + tLFPS_Period, Max+
+ * tSilence, Max+ tPHY Establishment + tCDS) / tline)
+ * For the "PHY P2 to P0" latency see the PHY Power Control page
+ * (PHY P2 to P0) : https://gfxspecs.intel.com/Predator/Home/Index/68965
+ * : 12 us
+ * The tLFPS_Period, Max term is 800ns
+ * The tSilence, Max term is 180ns
+ * The tPHY Establishment (a.k.a. t1) term is 50us
+ * The tCDS term is 1 or 2 times t2
+ * t2 = Number ML_PHY_LOCK * tML_PHY_LOCK
+ * Number ML_PHY_LOCK = ( 7 + CEILING( 6.5us / tML_PHY_LOCK ) + 1)
+ * Rounding up the 6.5us padding to the next ML_PHY_LOCK boundary and
+ * adding the "+ 1" term ensures all ML_PHY_LOCK sequences that start
+ * within the CDS period complete within the CDS period regardless of
+ * entry into the period
+ * tML_PHY_LOCK = TPS4 Length * ( 10 / (Link Rate in MHz) )
+ * TPS4 Length = 252 Symbols
+ */
+static int _lnl_compute_aux_less_wake_time(int port_clock)
+{
+   int tphy2_p2_to_p0 = 12 * 1000;
+   int tlfps_period_max = 800;
+   int tsilence_max = 180;
+   int t1 = 50 * 1000;
+   int tps4 = 252;
+   int tml_phy_lock = 1000 * 1000 * tps4 * 10 / port_clo

[PATCH v6 1/6] drm/i915/alpm: Move alpm parameters from intel_psr

2024-05-27 Thread Animesh Manna
ALPM can be enabled for non psr panel and currenly aplm-params are
encapsulated under intel_psr struct, so moving out to intel_dp struct.

Signed-off-by: Animesh Manna 
---
 .../drm/i915/display/intel_display_types.h| 21 +
 drivers/gpu/drm/i915/display/intel_psr.c  | 44 +--
 2 files changed, 31 insertions(+), 34 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index 9678c2b157f6..0ad6134ba94e 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1705,17 +1705,6 @@ struct intel_psr {
bool psr2_sel_fetch_cff_enabled;
bool req_psr2_sdp_prior_scanline;
u8 sink_sync_latency;
-
-   struct {
-   u8 io_wake_lines;
-   u8 fast_wake_lines;
-
-   /* LNL and beyond */
-   u8 check_entry_lines;
-   u8 silence_period_sym_clocks;
-   u8 lfps_half_cycle_num_of_syms;
-   } alpm_parameters;
-
ktime_t last_entry_attempt;
ktime_t last_exit;
bool sink_not_reliable;
@@ -1846,6 +1835,16 @@ struct intel_dp {
unsigned long last_oui_write;
 
bool colorimetry_support;
+
+   struct {
+   u8 io_wake_lines;
+   u8 fast_wake_lines;
+
+   /* LNL and beyond */
+   u8 check_entry_lines;
+   u8 silence_period_sym_clocks;
+   u8 lfps_half_cycle_num_of_syms;
+   } alpm_parameters;
 };
 
 enum lspcon_vendor {
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index f59238d3d484..845ef9822666 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -871,8 +871,8 @@ static u32 intel_psr2_get_tp_time(struct intel_dp *intel_dp)
 
 static int psr2_block_count_lines(struct intel_dp *intel_dp)
 {
-   return intel_dp->psr.alpm_parameters.io_wake_lines < 9 &&
-   intel_dp->psr.alpm_parameters.fast_wake_lines < 9 ? 8 : 12;
+   return intel_dp->alpm_parameters.io_wake_lines < 9 &&
+   intel_dp->alpm_parameters.fast_wake_lines < 9 ? 8 : 12;
 }
 
 static int psr2_block_count(struct intel_dp *intel_dp)
@@ -910,7 +910,6 @@ static void dg2_activate_panel_replay(struct intel_dp 
*intel_dp)
 static void hsw_activate_psr2(struct intel_dp *intel_dp)
 {
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-   struct intel_psr *psr = _dp->psr;
enum transcoder cpu_transcoder = intel_dp->psr.transcoder;
u32 val = EDP_PSR2_ENABLE;
u32 psr_val = 0;
@@ -952,20 +951,20 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp)
 */
int tmp;
 
-   tmp = map[psr->alpm_parameters.io_wake_lines -
+   tmp = map[intel_dp->alpm_parameters.io_wake_lines -
  TGL_EDP_PSR2_IO_BUFFER_WAKE_MIN_LINES];
val |= TGL_EDP_PSR2_IO_BUFFER_WAKE(tmp + 
TGL_EDP_PSR2_IO_BUFFER_WAKE_MIN_LINES);
 
-   tmp = map[psr->alpm_parameters.fast_wake_lines - 
TGL_EDP_PSR2_FAST_WAKE_MIN_LINES];
+   tmp = map[intel_dp->alpm_parameters.fast_wake_lines - 
TGL_EDP_PSR2_FAST_WAKE_MIN_LINES];
val |= TGL_EDP_PSR2_FAST_WAKE(tmp + 
TGL_EDP_PSR2_FAST_WAKE_MIN_LINES);
} else if (DISPLAY_VER(dev_priv) >= 20) {
-   val |= 
LNL_EDP_PSR2_IO_BUFFER_WAKE(psr->alpm_parameters.io_wake_lines);
+   val |= 
LNL_EDP_PSR2_IO_BUFFER_WAKE(intel_dp->alpm_parameters.io_wake_lines);
} else if (DISPLAY_VER(dev_priv) >= 12) {
-   val |= 
TGL_EDP_PSR2_IO_BUFFER_WAKE(psr->alpm_parameters.io_wake_lines);
-   val |= 
TGL_EDP_PSR2_FAST_WAKE(psr->alpm_parameters.fast_wake_lines);
+   val |= 
TGL_EDP_PSR2_IO_BUFFER_WAKE(intel_dp->alpm_parameters.io_wake_lines);
+   val |= 
TGL_EDP_PSR2_FAST_WAKE(intel_dp->alpm_parameters.fast_wake_lines);
} else if (DISPLAY_VER(dev_priv) >= 9) {
-   val |= 
EDP_PSR2_IO_BUFFER_WAKE(psr->alpm_parameters.io_wake_lines);
-   val |= EDP_PSR2_FAST_WAKE(psr->alpm_parameters.fast_wake_lines);
+   val |= 
EDP_PSR2_IO_BUFFER_WAKE(intel_dp->alpm_parameters.io_wake_lines);
+   val |= 
EDP_PSR2_FAST_WAKE(intel_dp->alpm_parameters.fast_wake_lines);
}
 
if (intel_dp->psr.req_psr2_sdp_prior_scanline)
@@ -1348,9 +1347,9 @@ static int _lnl_compute_aux_less_alpm_params(struct 
intel_dp *intel_dp,
if (i915->display.params.psr_safest_params)
aux_less_wake_lines = ALPM_CTL_AUX_LESS_WAKE_TIME_MASK;
 
-   intel_dp->psr.alpm_parameters.fast_wake_lines = aux_less_wake_lines;
-   intel_dp->psr.alpm_parameters.silence_period_sym_c

[PATCH v6 0/6] Link off between frames for edp

2024-05-27 Thread Animesh Manna
Link Off Between Active Frames (LOBF) allows an eDP link to be turned Off and On
durning long VBLANK durations without enabling any of the PSR/PSR2/PR modes of 
operation.

Bspec: 71477

Note: Lobf need to be enabled adaptive sync fixed refresh mode
where vmin = vmax = flipline, which will arise after cmmr feature
enablement. Currently existing code refactored and make compute-config()
and enabling function ready. Will add enabling sequence in a separate patch.

Signed-off-by: Animesh Manna 

Animesh Manna (5):
  drm/i915/alpm: Move alpm parameters from intel_psr
  drm/i915/alpm: Move alpm related code to a new file
  drm/i915/alpm: Add compute config for lobf
  drm/i915/alpm: Enable lobf from source in ALPM_CTL
  drm/i915/alpm: Add debugfs for LOBF

Jouni Högander (1):
  drm/display: Add missing aux less alpm wake related bits

 drivers/gpu/drm/i915/Makefile |   1 +
 drivers/gpu/drm/i915/display/intel_alpm.c | 411 ++
 drivers/gpu/drm/i915/display/intel_alpm.h |  25 ++
 .../drm/i915/display/intel_display_debugfs.c  |   2 +
 .../drm/i915/display/intel_display_types.h|  26 +-
 drivers/gpu/drm/i915/display/intel_dp.c   |   4 +
 drivers/gpu/drm/i915/display/intel_psr.c  | 303 +
 drivers/gpu/drm/xe/Makefile   |   1 +
 include/drm/display/drm_dp.h  |   5 +-
 9 files changed, 475 insertions(+), 303 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_alpm.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_alpm.h

-- 
2.29.0



[PATCH v5 3/6] drm/display: Add missing aux less alpm wake related bits

2024-05-20 Thread Animesh Manna
From: Jouni Högander 

eDP1.5 adds some more bits into DP_RECEIVER_ALPM_CAP and
DP_RECEIVER_ALPM_CONFIG registers. Add definitions for these.

Signed-off-by: Jouni Högander 
---
 include/drm/display/drm_dp.h | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/include/drm/display/drm_dp.h b/include/drm/display/drm_dp.h
index 906949ca3cee..3317ff88ed59 100644
--- a/include/drm/display/drm_dp.h
+++ b/include/drm/display/drm_dp.h
@@ -232,6 +232,8 @@
 
 #define DP_RECEIVER_ALPM_CAP   0x02e   /* eDP 1.4 */
 # define DP_ALPM_CAP   (1 << 0)
+# define DP_ALPM_PM_STATE_2A_SUPPORT   (1 << 1) /* eDP 1.5 */
+# define DP_ALPM_AUX_LESS_CAP  (1 << 2) /* eDP 1.5 */
 
 #define DP_SINK_DEVICE_AUX_FRAME_SYNC_CAP   0x02f   /* eDP 1.4 */
 # define DP_AUX_FRAME_SYNC_CAP (1 << 0)
@@ -683,7 +685,8 @@
 
 #define DP_RECEIVER_ALPM_CONFIG0x116   /* eDP 1.4 */
 # define DP_ALPM_ENABLE(1 << 0)
-# define DP_ALPM_LOCK_ERROR_IRQ_HPD_ENABLE  (1 << 1)
+# define DP_ALPM_LOCK_ERROR_IRQ_HPD_ENABLE  (1 << 1) /* eDP 1.5 */
+# define DP_ALPM_MODE_AUX_LESS (1 << 2) /* eDP 1.5 */
 
 #define DP_SINK_DEVICE_AUX_FRAME_SYNC_CONF  0x117   /* eDP 1.4 */
 # define DP_AUX_FRAME_SYNC_ENABLE  (1 << 0)
-- 
2.29.0



[PATCH v5 6/6] drm/i915/alpm: Add debugfs for LOBF

2024-05-20 Thread Animesh Manna
For validation purpose add debugfs for LOBF.

v1: Initial version.
v2: Add aux-wake/less info along with lobf status. [Jouni]

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_alpm.c | 49 +++
 drivers/gpu/drm/i915/display/intel_alpm.h |  2 +
 .../drm/i915/display/intel_display_debugfs.c  |  2 +
 3 files changed, 53 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c 
b/drivers/gpu/drm/i915/display/intel_alpm.c
index 8f4da817ef55..843ffb5fcb7a 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.c
+++ b/drivers/gpu/drm/i915/display/intel_alpm.c
@@ -360,3 +360,52 @@ void intel_alpm_configure(struct intel_dp *intel_dp,
 {
lnl_alpm_configure(intel_dp, crtc_state);
 }
+
+static int i915_edp_lobf_info_show(struct seq_file *m, void *data)
+{
+   struct intel_connector *connector = m->private;
+   struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+   struct drm_crtc *crtc;
+   struct intel_crtc_state *crtc_state;
+   enum transcoder cpu_transcoder;
+   u32 alpm_ctl;
+   int ret;
+
+   ret = 
drm_modeset_lock_single_interruptible(_priv->drm.mode_config.connection_mutex);
+   if (ret)
+   return ret;
+
+   crtc = connector->base.state->crtc;
+   if (connector->base.status != connector_status_connected || !crtc) {
+   ret = -ENODEV;
+   goto out;
+   }
+
+   crtc_state = to_intel_crtc_state(crtc->state);
+   cpu_transcoder = crtc_state->cpu_transcoder;
+   alpm_ctl = intel_de_read(dev_priv, ALPM_CTL(dev_priv, cpu_transcoder));
+   seq_printf(m, "LOBF status: %s\n", str_enabled_disabled(alpm_ctl & 
ALPM_CTL_LOBF_ENABLE));
+   seq_printf(m, "Aux-wake alpm status: %s\n",
+  str_enabled_disabled(!(alpm_ctl & 
ALPM_CTL_ALPM_AUX_LESS_ENABLE)));
+   seq_printf(m, "Aux-less alpm status: %s\n",
+  str_enabled_disabled(alpm_ctl & 
ALPM_CTL_ALPM_AUX_LESS_ENABLE));
+out:
+   drm_modeset_unlock(_priv->drm.mode_config.connection_mutex);
+
+   return ret;
+}
+
+DEFINE_SHOW_ATTRIBUTE(i915_edp_lobf_info);
+
+void intel_alpm_lobf_debugfs_add(struct intel_connector *connector)
+{
+   struct drm_i915_private *i915 = to_i915(connector->base.dev);
+   struct dentry *root = connector->base.debugfs_entry;
+
+   if (DISPLAY_VER(i915) < 20 ||
+   connector->base.connector_type != DRM_MODE_CONNECTOR_eDP)
+   return;
+
+   debugfs_create_file("i915_edp_lobf_info", 0444, root,
+   connector, _edp_lobf_info_fops);
+}
diff --git a/drivers/gpu/drm/i915/display/intel_alpm.h 
b/drivers/gpu/drm/i915/display/intel_alpm.h
index fd9be8aa876c..0dab2068164a 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.h
+++ b/drivers/gpu/drm/i915/display/intel_alpm.h
@@ -11,6 +11,7 @@
 struct intel_dp;
 struct intel_crtc_state;
 struct drm_connector_state;
+struct intel_connector;
 
 void intel_alpm_get_capability(struct intel_dp *intel_dp);
 bool intel_alpm_compute_params(struct intel_dp *intel_dp,
@@ -20,4 +21,5 @@ void intel_alpm_compute_lobf_config(struct intel_dp *intel_dp,
struct drm_connector_state *conn_state);
 void intel_alpm_configure(struct intel_dp *intel_dp,
  const struct intel_crtc_state *crtc_state);
+void intel_alpm_lobf_debugfs_add(struct intel_connector *connector);
 #endif
diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c 
b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
index 35f9f86ef70f..86d9900c40af 100644
--- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
+++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
@@ -13,6 +13,7 @@
 #include "i915_debugfs.h"
 #include "i915_irq.h"
 #include "i915_reg.h"
+#include "intel_alpm.h"
 #include "intel_crtc.h"
 #include "intel_de.h"
 #include "intel_crtc_state_dump.h"
@@ -1515,6 +1516,7 @@ void intel_connector_debugfs_add(struct intel_connector 
*connector)
intel_drrs_connector_debugfs_add(connector);
intel_pps_connector_debugfs_add(connector);
intel_psr_connector_debugfs_add(connector);
+   intel_alpm_lobf_debugfs_add(connector);
 
if (connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
connector_type == DRM_MODE_CONNECTOR_HDMIA ||
-- 
2.29.0



[PATCH v5 5/6] drm/i915/alpm: Enable lobf from source in ALPM_CTL

2024-05-20 Thread Animesh Manna
Set the Link Off Between Frames Enable bit in ALPM_CTL register.

Note: Lobf need to be enabled adaptive sync fixed refresh mode
where vmin = vmax = flipline, which will arise after cmmr feature
enablement. Will add enabling sequence in a separate patch.

v1: Initial version.
v2: Condition check modified in alpm_configure(). [Jouni]

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_alpm.c | 16 +++-
 drivers/gpu/drm/i915/display/intel_alpm.h |  4 ++--
 drivers/gpu/drm/i915/display/intel_psr.c  |  2 +-
 3 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c 
b/drivers/gpu/drm/i915/display/intel_alpm.c
index c2334197e723..8f4da817ef55 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.c
+++ b/drivers/gpu/drm/i915/display/intel_alpm.c
@@ -304,10 +304,11 @@ void intel_alpm_compute_lobf_config(struct intel_dp 
*intel_dp,
(first_sdp_position + waketime_in_lines);
 }
 
-static void lnl_alpm_configure(struct intel_dp *intel_dp)
+static void lnl_alpm_configure(struct intel_dp *intel_dp,
+  const struct intel_crtc_state *crtc_state)
 {
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-   enum transcoder cpu_transcoder = intel_dp->psr.transcoder;
+   enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
u32 alpm_ctl;
 
if (DISPLAY_VER(dev_priv) < 20 || (!intel_dp->psr.sel_update_enabled &&
@@ -318,7 +319,8 @@ static void lnl_alpm_configure(struct intel_dp *intel_dp)
 * Panel Replay on eDP is always using ALPM aux less. I.e. no need to
 * check panel support at this point.
 */
-   if (intel_dp->psr.panel_replay_enabled && intel_dp_is_edp(intel_dp)) {
+   if ((intel_dp->psr.panel_replay_enabled && intel_dp_is_edp(intel_dp)) ||
+   (crtc_state->has_lobf && 
intel_alpm_aux_less_wake_supported(intel_dp))) {
alpm_ctl = ALPM_CTL_ALPM_ENABLE |
ALPM_CTL_ALPM_AUX_LESS_ENABLE |
ALPM_CTL_AUX_LESS_SLEEP_HOLD_TIME_50_SYMBOLS;
@@ -345,12 +347,16 @@ static void lnl_alpm_configure(struct intel_dp *intel_dp)

ALPM_CTL_EXTENDED_FAST_WAKE_TIME(intel_dp->alpm_parameters.fast_wake_lines);
}
 
+   if (crtc_state->has_lobf)
+   alpm_ctl |= ALPM_CTL_LOBF_ENABLE;
+
alpm_ctl |= 
ALPM_CTL_ALPM_ENTRY_CHECK(intel_dp->alpm_parameters.check_entry_lines);
 
intel_de_write(dev_priv, ALPM_CTL(dev_priv, cpu_transcoder), alpm_ctl);
 }
 
-void intel_alpm_configure(struct intel_dp *intel_dp)
+void intel_alpm_configure(struct intel_dp *intel_dp,
+ const struct intel_crtc_state *crtc_state)
 {
-   lnl_alpm_configure(intel_dp);
+   lnl_alpm_configure(intel_dp, crtc_state);
 }
diff --git a/drivers/gpu/drm/i915/display/intel_alpm.h 
b/drivers/gpu/drm/i915/display/intel_alpm.h
index 45c07f023a63..fd9be8aa876c 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.h
+++ b/drivers/gpu/drm/i915/display/intel_alpm.h
@@ -18,6 +18,6 @@ bool intel_alpm_compute_params(struct intel_dp *intel_dp,
 void intel_alpm_compute_lobf_config(struct intel_dp *intel_dp,
struct intel_crtc_state *crtc_state,
struct drm_connector_state *conn_state);
-void intel_alpm_configure(struct intel_dp *intel_dp);
-
+void intel_alpm_configure(struct intel_dp *intel_dp,
+ const struct intel_crtc_state *crtc_state);
 #endif
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index e2d3be0bf99c..10c71e79a1c8 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -1692,7 +1692,7 @@ static void intel_psr_enable_source(struct intel_dp 
*intel_dp,
 IGNORE_PSR2_HW_TRACKING : 0);
 
if (intel_dp_is_edp(intel_dp))
-   intel_alpm_configure(intel_dp);
+   intel_alpm_configure(intel_dp, crtc_state);
 
/*
 * Wa_16013835468
-- 
2.29.0



[PATCH v5 4/6] drm/i915/alpm: Add compute config for lobf

2024-05-20 Thread Animesh Manna
Link Off Between Active Frames, is a new feature for eDP
that allows the panel to go to lower power state after
transmission of data. This is a feature on top of ALPM, AS SDP.
Add compute config during atomic-check phase.

v1: RFC version.
v2: Add separate flag for auxless-alpm. [Jani]
v3:
- intel_dp->lobf_supported replaced with crtc_state->has_lobf. [Jouni]
- Add DISPLAY_VER() check. [Jouni]
- Modify function name of get_aux_less_status. [Jani]
v4: Add enum alpm_mode to hold the aux-wake/less capability.
v5: Add alpm_dpcd to intel_dp and use aux_wake_supported()/
aux_less_wake_supported() instead of enum alpm_mode. [Jouni]

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_alpm.c | 61 +++
 drivers/gpu/drm/i915/display/intel_alpm.h |  5 ++
 .../drm/i915/display/intel_display_types.h|  5 ++
 drivers/gpu/drm/i915/display/intel_dp.c   |  4 ++
 4 files changed, 75 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c 
b/drivers/gpu/drm/i915/display/intel_alpm.c
index 7307e02277d6..c2334197e723 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.c
+++ b/drivers/gpu/drm/i915/display/intel_alpm.c
@@ -11,6 +11,26 @@
 #include "intel_dp_aux.h"
 #include "intel_psr_regs.h"
 
+static bool intel_alpm_aux_wake_supported(struct intel_dp *intel_dp)
+{
+   return intel_dp->alpm_dpcd & DP_ALPM_CAP;
+}
+
+static bool intel_alpm_aux_less_wake_supported(struct intel_dp *intel_dp)
+{
+   return intel_dp->alpm_dpcd & DP_ALPM_AUX_LESS_CAP;
+}
+
+void intel_alpm_get_capability(struct intel_dp *intel_dp)
+{
+   u8 dpcd;
+
+   if (drm_dp_dpcd_readb(_dp->aux, DP_RECEIVER_ALPM_CAP, ) < 0)
+   return;
+
+   intel_dp->alpm_dpcd = dpcd;
+}
+
 /*
  * See Bspec: 71632 for the table
  *
@@ -243,6 +263,47 @@ bool intel_alpm_compute_params(struct intel_dp *intel_dp,
return true;
 }
 
+void intel_alpm_compute_lobf_config(struct intel_dp *intel_dp,
+   struct intel_crtc_state *crtc_state,
+   struct drm_connector_state *conn_state)
+{
+   struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+   struct drm_display_mode *adjusted_mode = _state->hw.adjusted_mode;
+   int waketime_in_lines, first_sdp_position;
+   int context_latency, guardband;
+
+   if (!intel_dp_is_edp(intel_dp))
+   return;
+
+   if (DISPLAY_VER(i915) < 20)
+   return;
+
+   if (!intel_dp_as_sdp_supported(intel_dp))
+   return;
+
+   if (crtc_state->has_psr)
+   return;
+
+   if (!(intel_alpm_aux_wake_supported(intel_dp) ||
+ intel_alpm_aux_less_wake_supported(intel_dp)))
+   return;
+
+   if (!intel_alpm_compute_params(intel_dp, crtc_state))
+   return;
+
+   context_latency = adjusted_mode->crtc_vblank_start - 
adjusted_mode->crtc_vdisplay;
+   guardband = adjusted_mode->crtc_vtotal -
+   adjusted_mode->crtc_vdisplay - context_latency;
+   first_sdp_position = adjusted_mode->crtc_vtotal - 
adjusted_mode->crtc_vsync_start;
+   if (intel_alpm_aux_less_wake_supported(intel_dp))
+   waketime_in_lines = intel_dp->alpm_parameters.io_wake_lines;
+   else
+   waketime_in_lines = intel_dp->alpm_parameters.fast_wake_lines;
+
+   crtc_state->has_lobf = (context_latency + guardband) >
+   (first_sdp_position + waketime_in_lines);
+}
+
 static void lnl_alpm_configure(struct intel_dp *intel_dp)
 {
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
diff --git a/drivers/gpu/drm/i915/display/intel_alpm.h 
b/drivers/gpu/drm/i915/display/intel_alpm.h
index c45d078e5a6b..45c07f023a63 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.h
+++ b/drivers/gpu/drm/i915/display/intel_alpm.h
@@ -10,9 +10,14 @@
 
 struct intel_dp;
 struct intel_crtc_state;
+struct drm_connector_state;
 
+void intel_alpm_get_capability(struct intel_dp *intel_dp);
 bool intel_alpm_compute_params(struct intel_dp *intel_dp,
   struct intel_crtc_state *crtc_state);
+void intel_alpm_compute_lobf_config(struct intel_dp *intel_dp,
+   struct intel_crtc_state *crtc_state,
+   struct drm_connector_state *conn_state);
 void intel_alpm_configure(struct intel_dp *intel_dp);
 
 #endif
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index 0ad6134ba94e..d77a9f22b5c6 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1410,6 +1410,9 @@ struct intel_crtc_state {
 
/* for loading single buffered registers during vblank */
struct drm_vblank_work vblank_work;
+
+   /* LOBF flag */
+   bool has_lobf;
 };
 

[PATCH v5 2/6] drm/i915/alpm: Move alpm related code to a new file

2024-05-20 Thread Animesh Manna
Move ALPM feature related code as it will be used for
non-psr panel also thorugh LOBF feature.

v1: Initial version.
v2: Correct ordering in makefile. [Jani]

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/Makefile |   1 +
 drivers/gpu/drm/i915/display/intel_alpm.c | 295 ++
 drivers/gpu/drm/i915/display/intel_alpm.h |  18 ++
 drivers/gpu/drm/i915/display/intel_psr.c  | 283 +
 drivers/gpu/drm/xe/Makefile   |   1 +
 5 files changed, 318 insertions(+), 280 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_alpm.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_alpm.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 7cad944b825c..9a3f910ce4fd 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -243,6 +243,7 @@ i915-y += \
display/hsw_ips.o \
display/i9xx_plane.o \
display/i9xx_wm.o \
+   display/intel_alpm.o \
display/intel_atomic.o \
display/intel_atomic_plane.o \
display/intel_audio.o \
diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c 
b/drivers/gpu/drm/i915/display/intel_alpm.c
new file mode 100644
index ..7307e02277d6
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_alpm.c
@@ -0,0 +1,295 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2024, Intel Corporation.
+ */
+
+#include "intel_alpm.h"
+#include "intel_crtc.h"
+#include "intel_de.h"
+#include "intel_display_types.h"
+#include "intel_dp.h"
+#include "intel_dp_aux.h"
+#include "intel_psr_regs.h"
+
+/*
+ * See Bspec: 71632 for the table
+ *
+ * Silence_period = tSilence,Min + ((tSilence,Max - tSilence,Min) / 2)
+ *
+ * Half cycle duration:
+ *
+ * Link rates 1.62 - 4.32 and tLFPS_Cycle = 70 ns
+ * FLOOR( (Link Rate * tLFPS_Cycle) / (2 * 10) )
+ *
+ * Link rates 5.4 - 8.1
+ * PORT_ALPM_LFPS_CTL[ LFPS Cycle Count ] = 10
+ * LFPS Period chosen is the mid-point of the min:max values from the table
+ * FLOOR( LFPS Period in Symbol clocks /
+ * (2 * PORT_ALPM_LFPS_CTL[ LFPS Cycle Count ]) )
+ */
+static bool _lnl_get_silence_period_and_lfps_half_cycle(int link_rate,
+   int *silence_period,
+   int *lfps_half_cycle)
+{
+   switch (link_rate) {
+   case 162000:
+   *silence_period = 20;
+   *lfps_half_cycle = 5;
+   break;
+   case 216000:
+   *silence_period = 27;
+   *lfps_half_cycle = 7;
+   break;
+   case 243000:
+   *silence_period = 31;
+   *lfps_half_cycle = 8;
+   break;
+   case 27:
+   *silence_period = 34;
+   *lfps_half_cycle = 9;
+   break;
+   case 324000:
+   *silence_period = 41;
+   *lfps_half_cycle = 11;
+   break;
+   case 432000:
+   *silence_period = 56;
+   *lfps_half_cycle = 15;
+   break;
+   case 54:
+   *silence_period = 69;
+   *lfps_half_cycle = 12;
+   break;
+   case 648000:
+   *silence_period = 84;
+   *lfps_half_cycle = 15;
+   break;
+   case 675000:
+   *silence_period = 87;
+   *lfps_half_cycle = 15;
+   break;
+   case 81:
+   *silence_period = 104;
+   *lfps_half_cycle = 19;
+   break;
+   default:
+   *silence_period = *lfps_half_cycle = -1;
+   return false;
+   }
+   return true;
+}
+
+/*
+ * AUX-Less Wake Time = CEILING( ((PHY P2 to P0) + tLFPS_Period, Max+
+ * tSilence, Max+ tPHY Establishment + tCDS) / tline)
+ * For the "PHY P2 to P0" latency see the PHY Power Control page
+ * (PHY P2 to P0) : https://gfxspecs.intel.com/Predator/Home/Index/68965
+ * : 12 us
+ * The tLFPS_Period, Max term is 800ns
+ * The tSilence, Max term is 180ns
+ * The tPHY Establishment (a.k.a. t1) term is 50us
+ * The tCDS term is 1 or 2 times t2
+ * t2 = Number ML_PHY_LOCK * tML_PHY_LOCK
+ * Number ML_PHY_LOCK = ( 7 + CEILING( 6.5us / tML_PHY_LOCK ) + 1)
+ * Rounding up the 6.5us padding to the next ML_PHY_LOCK boundary and
+ * adding the "+ 1" term ensures all ML_PHY_LOCK sequences that start
+ * within the CDS period complete within the CDS period regardless of
+ * entry into the period
+ * tML_PHY_LOCK = TPS4 Length * ( 10 / (Link Rate in MHz) )
+ * TPS4 Length = 252 Symbols
+ */
+static int _lnl_compute_aux_less_wake_time(int port_clock)
+{
+   int tphy2_p2_to_p0 = 12 * 1000;
+   int tlfps_period_max = 800;
+   int tsilence_max = 180;
+   int t1 = 50 * 1000;
+   int tps4 = 252;
+   int tml_phy_lock = 1000 * 1000 * tps4 * 10 / port_clo

[PATCH v5 1/6] drm/i915/alpm: Move alpm parameters from intel_psr

2024-05-20 Thread Animesh Manna
ALPM can be enabled for non psr panel and currenly aplm-params are
encapsulated under intel_psr struct, so moving out to intel_dp struct.

Signed-off-by: Animesh Manna 
---
 .../drm/i915/display/intel_display_types.h| 21 +
 drivers/gpu/drm/i915/display/intel_psr.c  | 44 +--
 2 files changed, 31 insertions(+), 34 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index 9678c2b157f6..0ad6134ba94e 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1705,17 +1705,6 @@ struct intel_psr {
bool psr2_sel_fetch_cff_enabled;
bool req_psr2_sdp_prior_scanline;
u8 sink_sync_latency;
-
-   struct {
-   u8 io_wake_lines;
-   u8 fast_wake_lines;
-
-   /* LNL and beyond */
-   u8 check_entry_lines;
-   u8 silence_period_sym_clocks;
-   u8 lfps_half_cycle_num_of_syms;
-   } alpm_parameters;
-
ktime_t last_entry_attempt;
ktime_t last_exit;
bool sink_not_reliable;
@@ -1846,6 +1835,16 @@ struct intel_dp {
unsigned long last_oui_write;
 
bool colorimetry_support;
+
+   struct {
+   u8 io_wake_lines;
+   u8 fast_wake_lines;
+
+   /* LNL and beyond */
+   u8 check_entry_lines;
+   u8 silence_period_sym_clocks;
+   u8 lfps_half_cycle_num_of_syms;
+   } alpm_parameters;
 };
 
 enum lspcon_vendor {
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index d18baeb971bb..a9019fde907f 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -871,8 +871,8 @@ static u32 intel_psr2_get_tp_time(struct intel_dp *intel_dp)
 
 static int psr2_block_count_lines(struct intel_dp *intel_dp)
 {
-   return intel_dp->psr.alpm_parameters.io_wake_lines < 9 &&
-   intel_dp->psr.alpm_parameters.fast_wake_lines < 9 ? 8 : 12;
+   return intel_dp->alpm_parameters.io_wake_lines < 9 &&
+   intel_dp->alpm_parameters.fast_wake_lines < 9 ? 8 : 12;
 }
 
 static int psr2_block_count(struct intel_dp *intel_dp)
@@ -910,7 +910,6 @@ static void dg2_activate_panel_replay(struct intel_dp 
*intel_dp)
 static void hsw_activate_psr2(struct intel_dp *intel_dp)
 {
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-   struct intel_psr *psr = _dp->psr;
enum transcoder cpu_transcoder = intel_dp->psr.transcoder;
u32 val = EDP_PSR2_ENABLE;
u32 psr_val = 0;
@@ -952,20 +951,20 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp)
 */
int tmp;
 
-   tmp = map[psr->alpm_parameters.io_wake_lines -
+   tmp = map[intel_dp->alpm_parameters.io_wake_lines -
  TGL_EDP_PSR2_IO_BUFFER_WAKE_MIN_LINES];
val |= TGL_EDP_PSR2_IO_BUFFER_WAKE(tmp + 
TGL_EDP_PSR2_IO_BUFFER_WAKE_MIN_LINES);
 
-   tmp = map[psr->alpm_parameters.fast_wake_lines - 
TGL_EDP_PSR2_FAST_WAKE_MIN_LINES];
+   tmp = map[intel_dp->alpm_parameters.fast_wake_lines - 
TGL_EDP_PSR2_FAST_WAKE_MIN_LINES];
val |= TGL_EDP_PSR2_FAST_WAKE(tmp + 
TGL_EDP_PSR2_FAST_WAKE_MIN_LINES);
} else if (DISPLAY_VER(dev_priv) >= 20) {
-   val |= 
LNL_EDP_PSR2_IO_BUFFER_WAKE(psr->alpm_parameters.io_wake_lines);
+   val |= 
LNL_EDP_PSR2_IO_BUFFER_WAKE(intel_dp->alpm_parameters.io_wake_lines);
} else if (DISPLAY_VER(dev_priv) >= 12) {
-   val |= 
TGL_EDP_PSR2_IO_BUFFER_WAKE(psr->alpm_parameters.io_wake_lines);
-   val |= 
TGL_EDP_PSR2_FAST_WAKE(psr->alpm_parameters.fast_wake_lines);
+   val |= 
TGL_EDP_PSR2_IO_BUFFER_WAKE(intel_dp->alpm_parameters.io_wake_lines);
+   val |= 
TGL_EDP_PSR2_FAST_WAKE(intel_dp->alpm_parameters.fast_wake_lines);
} else if (DISPLAY_VER(dev_priv) >= 9) {
-   val |= 
EDP_PSR2_IO_BUFFER_WAKE(psr->alpm_parameters.io_wake_lines);
-   val |= EDP_PSR2_FAST_WAKE(psr->alpm_parameters.fast_wake_lines);
+   val |= 
EDP_PSR2_IO_BUFFER_WAKE(intel_dp->alpm_parameters.io_wake_lines);
+   val |= 
EDP_PSR2_FAST_WAKE(intel_dp->alpm_parameters.fast_wake_lines);
}
 
if (intel_dp->psr.req_psr2_sdp_prior_scanline)
@@ -1348,9 +1347,9 @@ static int _lnl_compute_aux_less_alpm_params(struct 
intel_dp *intel_dp,
if (i915->display.params.psr_safest_params)
aux_less_wake_lines = ALPM_CTL_AUX_LESS_WAKE_TIME_MASK;
 
-   intel_dp->psr.alpm_parameters.fast_wake_lines = aux_less_wake_lines;
-   intel_dp->psr.alpm_parameters.silence_period_sym_c

[PATCH v5 0/6] Link off between frames for edp

2024-05-20 Thread Animesh Manna
Link Off Between Active Frames (LOBF) allows an eDP link to be turned Off and On
durning long VBLANK durations without enabling any of the PSR/PSR2/PR modes of 
operation.

Bspec: 71477

Note: Lobf need to be enabled adaptive sync fixed refresh mode
where vmin = vmax = flipline, which will arise after cmmr feature
enablement. Currently existing code refactored and make compute-config()
and enabling function ready. Will add enabling sequence in a separate patch.

Signed-off-by: Animesh Manna 

Animesh Manna (5):
  drm/i915/alpm: Move alpm parameters from intel_psr
  drm/i915/alpm: Move alpm related code to a new file
  drm/i915/alpm: Add compute config for lobf
  drm/i915/alpm: Enable lobf from source in ALPM_CTL
  drm/i915/alpm: Add debugfs for LOBF

Jouni Högander (1):
  drm/display: Add missing aux less alpm wake related bits

 drivers/gpu/drm/i915/Makefile |   1 +
 drivers/gpu/drm/i915/display/intel_alpm.c | 411 ++
 drivers/gpu/drm/i915/display/intel_alpm.h |  25 ++
 .../drm/i915/display/intel_display_debugfs.c  |   2 +
 .../drm/i915/display/intel_display_types.h|  26 +-
 drivers/gpu/drm/i915/display/intel_dp.c   |   4 +
 drivers/gpu/drm/i915/display/intel_psr.c  | 303 +
 drivers/gpu/drm/xe/Makefile   |   1 +
 include/drm/display/drm_dp.h  |   5 +-
 9 files changed, 475 insertions(+), 303 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_alpm.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_alpm.h

-- 
2.29.0



[PATCH v5] drm/i915/panelreplay: Panel replay workaround with VRR

2024-05-14 Thread Animesh Manna
Panel Replay VSC SDP not getting sent when VRR is enabled
and W1 and W2 are 0. So Program Set Context Latency in
TRANS_SET_CONTEXT_LATENCY register to at least a value of 1.

HSD: 14015406119

v1: Initial version.
v2: Update timings stored in adjusted_mode struct. [Ville]
v3: Add WA in compute_config(). [Ville]
v4:
- Add DISPLAY_VER() check and improve code comment. [Rodrigo]
- Introduce centralized intel_crtc_vblank_delay(). [Ville]
v5: Move to crtc_compute_config(). [Ville]

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_display.c | 22 
 drivers/gpu/drm/i915/display/intel_display.h |  1 +
 2 files changed, 23 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index ef986b508431..0664c9478c68 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -2497,10 +2497,15 @@ static int intel_crtc_compute_pipe_mode(struct 
intel_crtc_state *crtc_state)
 static int intel_crtc_compute_config(struct intel_atomic_state *state,
 struct intel_crtc *crtc)
 {
+   struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
struct intel_crtc_state *crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
int ret;
 
+   /* wa_14015401596: display versions 13, 14 */
+   if (DISPLAY_VER(dev_priv) >= 13)
+   intel_crtc_vblank_delay(crtc_state);
+
ret = intel_dpll_crtc_compute_clock(state, crtc);
if (ret)
return ret;
@@ -3889,6 +3894,23 @@ bool intel_crtc_get_pipe_config(struct intel_crtc_state 
*crtc_state)
return true;
 }
 
+void intel_crtc_vblank_delay(struct intel_crtc_state *crtc_state)
+{
+   struct drm_display_mode *adjusted_mode = _state->hw.adjusted_mode;
+
+   /*
+* wa_14015401596 for display versions >= 13.
+* Program Set Context Latency in TRANS_SET_CONTEXT_LATENCY register
+* to at least a value of 1 when Panel Replay is enabled with VRR.
+* Value for TRANS_SET_CONTEXT_LATENCY is calculated by substracting
+* crtc_vdisplay from crtc_vblank_start, so incrementing 
crtc_vblank_start
+* by 1 if both are equal.
+*/
+   if (crtc_state->vrr.enable && crtc_state->has_panel_replay &&
+   adjusted_mode->crtc_vblank_start == adjusted_mode->crtc_vdisplay)
+   adjusted_mode->crtc_vblank_start += 1;
+}
+
 int intel_dotclock_calculate(int link_freq,
 const struct intel_link_m_n *m_n)
 {
diff --git a/drivers/gpu/drm/i915/display/intel_display.h 
b/drivers/gpu/drm/i915/display/intel_display.h
index 56d1c0e3e62c..d426dd9f7f87 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -428,6 +428,7 @@ bool intel_crtc_is_bigjoiner_master(const struct 
intel_crtc_state *crtc_state);
 u8 intel_crtc_bigjoiner_slave_pipes(const struct intel_crtc_state *crtc_state);
 struct intel_crtc *intel_master_crtc(const struct intel_crtc_state 
*crtc_state);
 bool intel_crtc_get_pipe_config(struct intel_crtc_state *crtc_state);
+void intel_crtc_vblank_delay(struct intel_crtc_state *crtc_state);
 bool intel_pipe_config_compare(const struct intel_crtc_state *current_config,
   const struct intel_crtc_state *pipe_config,
   bool fastset);
-- 
2.29.0



[PATCH v4 6/6] drm/i915/alpm: Add debugfs for LOBF

2024-05-08 Thread Animesh Manna
For validation purpose add debugfs for LOBF.

v1: Initial version.
v2: Add aux-wake/less info along with lobf status. [Jouni]

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_alpm.c | 49 +++
 drivers/gpu/drm/i915/display/intel_alpm.h |  2 +
 .../drm/i915/display/intel_display_debugfs.c  |  2 +
 3 files changed, 53 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c 
b/drivers/gpu/drm/i915/display/intel_alpm.c
index c8eddc910cc5..b5b4c212de88 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.c
+++ b/drivers/gpu/drm/i915/display/intel_alpm.c
@@ -354,3 +354,52 @@ void intel_alpm_configure(struct intel_dp *intel_dp,
 {
lnl_alpm_configure(intel_dp, crtc_state);
 }
+
+static int i915_edp_lobf_info_show(struct seq_file *m, void *data)
+{
+   struct intel_connector *connector = m->private;
+   struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+   struct drm_crtc *crtc;
+   struct intel_crtc_state *crtc_state;
+   enum transcoder cpu_transcoder;
+   u32 alpm_ctl;
+   int ret;
+
+   ret = 
drm_modeset_lock_single_interruptible(_priv->drm.mode_config.connection_mutex);
+   if (ret)
+   return ret;
+
+   crtc = connector->base.state->crtc;
+   if (connector->base.status != connector_status_connected || !crtc) {
+   ret = -ENODEV;
+   goto out;
+   }
+
+   crtc_state = to_intel_crtc_state(crtc->state);
+   cpu_transcoder = crtc_state->cpu_transcoder;
+   alpm_ctl = intel_de_read(dev_priv, ALPM_CTL(dev_priv, cpu_transcoder));
+   seq_printf(m, "LOBF status: %s\n", str_enabled_disabled(alpm_ctl & 
ALPM_CTL_LOBF_ENABLE));
+   seq_printf(m, "Aux-wake alpm status: %s\n",
+  str_enabled_disabled(!(alpm_ctl & 
ALPM_CTL_ALPM_AUX_LESS_ENABLE)));
+   seq_printf(m, "Aux-less alpm status: %s\n",
+  str_enabled_disabled(alpm_ctl & 
ALPM_CTL_ALPM_AUX_LESS_ENABLE));
+out:
+   drm_modeset_unlock(_priv->drm.mode_config.connection_mutex);
+
+   return ret;
+}
+
+DEFINE_SHOW_ATTRIBUTE(i915_edp_lobf_info);
+
+void intel_alpm_lobf_debugfs_add(struct intel_connector *connector)
+{
+   struct drm_i915_private *i915 = to_i915(connector->base.dev);
+   struct dentry *root = connector->base.debugfs_entry;
+
+   if (DISPLAY_VER(i915) < 20 ||
+   connector->base.connector_type != DRM_MODE_CONNECTOR_eDP)
+   return;
+
+   debugfs_create_file("i915_edp_lobf_info", 0444, root,
+   connector, _edp_lobf_info_fops);
+}
diff --git a/drivers/gpu/drm/i915/display/intel_alpm.h 
b/drivers/gpu/drm/i915/display/intel_alpm.h
index c0c085c1e5b0..8e1e0bbd44a3 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.h
+++ b/drivers/gpu/drm/i915/display/intel_alpm.h
@@ -11,6 +11,7 @@
 struct intel_dp;
 struct intel_crtc_state;
 struct drm_connector_state;
+struct intel_connector;
 
 enum alpm_mode intel_alpm_get_capability(struct intel_dp *intel_dp);
 bool intel_alpm_compute_params(struct intel_dp *intel_dp,
@@ -20,4 +21,5 @@ void intel_alpm_compute_lobf_config(struct intel_dp *intel_dp,
struct drm_connector_state *conn_state);
 void intel_alpm_configure(struct intel_dp *intel_dp,
  const struct intel_crtc_state *crtc_state);
+void intel_alpm_lobf_debugfs_add(struct intel_connector *connector);
 #endif
diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c 
b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
index 35f9f86ef70f..86d9900c40af 100644
--- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
+++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
@@ -13,6 +13,7 @@
 #include "i915_debugfs.h"
 #include "i915_irq.h"
 #include "i915_reg.h"
+#include "intel_alpm.h"
 #include "intel_crtc.h"
 #include "intel_de.h"
 #include "intel_crtc_state_dump.h"
@@ -1515,6 +1516,7 @@ void intel_connector_debugfs_add(struct intel_connector 
*connector)
intel_drrs_connector_debugfs_add(connector);
intel_pps_connector_debugfs_add(connector);
intel_psr_connector_debugfs_add(connector);
+   intel_alpm_lobf_debugfs_add(connector);
 
if (connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
connector_type == DRM_MODE_CONNECTOR_HDMIA ||
-- 
2.29.0



[PATCH v4 5/6] drm/i915/alpm: Enable lobf from source in ALPM_CTL

2024-05-08 Thread Animesh Manna
Set the Link Off Between Frames Enable bit in ALPM_CTL register.

Note: Lobf need to be enabled adaptive sync fixed refresh mode
where vmin = vmax = flipline, which will arise after cmmr feature
enablement. Will add enabling sequence in a separate patch.

v1: Initial version.
v2: Condition check modified in alpm_configure(). [Jouni]

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_alpm.c | 16 +++-
 drivers/gpu/drm/i915/display/intel_alpm.h |  4 ++--
 drivers/gpu/drm/i915/display/intel_psr.c  |  2 +-
 3 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c 
b/drivers/gpu/drm/i915/display/intel_alpm.c
index 5979eab1f2e0..c8eddc910cc5 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.c
+++ b/drivers/gpu/drm/i915/display/intel_alpm.c
@@ -300,10 +300,11 @@ void intel_alpm_compute_lobf_config(struct intel_dp 
*intel_dp,
(first_sdp_position + waketime_in_lines);
 }
 
-static void lnl_alpm_configure(struct intel_dp *intel_dp)
+static void lnl_alpm_configure(struct intel_dp *intel_dp,
+  const struct intel_crtc_state *crtc_state)
 {
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-   enum transcoder cpu_transcoder = intel_dp->psr.transcoder;
+   enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
u32 alpm_ctl;
 
if (DISPLAY_VER(dev_priv) < 20 || (!intel_dp->psr.psr2_enabled &&
@@ -314,7 +315,8 @@ static void lnl_alpm_configure(struct intel_dp *intel_dp)
 * Panel Replay on eDP is always using ALPM aux less. I.e. no need to
 * check panel support at this point.
 */
-   if (intel_dp->psr.panel_replay_enabled && intel_dp_is_edp(intel_dp)) {
+   if ((intel_dp->psr.panel_replay_enabled && intel_dp_is_edp(intel_dp)) ||
+   (crtc_state->has_lobf && intel_dp->alpm_parameters.mode == 
ALPM_AUX_LESS)) {
alpm_ctl = ALPM_CTL_ALPM_ENABLE |
ALPM_CTL_ALPM_AUX_LESS_ENABLE |
ALPM_CTL_AUX_LESS_SLEEP_HOLD_TIME_50_SYMBOLS;
@@ -339,12 +341,16 @@ static void lnl_alpm_configure(struct intel_dp *intel_dp)
   
ALPM_CTL_EXTENDED_FAST_WAKE_TIME(intel_dp->alpm_parameters.fast_wake_lines);
}
 
+   if (crtc_state->has_lobf)
+   alpm_ctl |= ALPM_CTL_LOBF_ENABLE;
+
alpm_ctl |= 
ALPM_CTL_ALPM_ENTRY_CHECK(intel_dp->alpm_parameters.check_entry_lines);
 
intel_de_write(dev_priv, ALPM_CTL(dev_priv, cpu_transcoder), alpm_ctl);
 }
 
-void intel_alpm_configure(struct intel_dp *intel_dp)
+void intel_alpm_configure(struct intel_dp *intel_dp,
+ const struct intel_crtc_state *crtc_state)
 {
-   lnl_alpm_configure(intel_dp);
+   lnl_alpm_configure(intel_dp, crtc_state);
 }
diff --git a/drivers/gpu/drm/i915/display/intel_alpm.h 
b/drivers/gpu/drm/i915/display/intel_alpm.h
index 80c8a66b34af..c0c085c1e5b0 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.h
+++ b/drivers/gpu/drm/i915/display/intel_alpm.h
@@ -18,6 +18,6 @@ bool intel_alpm_compute_params(struct intel_dp *intel_dp,
 void intel_alpm_compute_lobf_config(struct intel_dp *intel_dp,
struct intel_crtc_state *crtc_state,
struct drm_connector_state *conn_state);
-void intel_alpm_configure(struct intel_dp *intel_dp);
-
+void intel_alpm_configure(struct intel_dp *intel_dp,
+ const struct intel_crtc_state *crtc_state);
 #endif
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index 9e89844e6418..cd1afc82aefc 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -1620,7 +1620,7 @@ static void intel_psr_enable_source(struct intel_dp 
*intel_dp,
 IGNORE_PSR2_HW_TRACKING : 0);
 
if (intel_dp_is_edp(intel_dp))
-   intel_alpm_configure(intel_dp);
+   intel_alpm_configure(intel_dp, crtc_state);
 
/*
 * Wa_16013835468
-- 
2.29.0



[PATCH v4 4/6] drm/i915/alpm: Add compute config for lobf

2024-05-08 Thread Animesh Manna
Link Off Between Active Frames, is a new feature for eDP
that allows the panel to go to lower power state after
transmission of data. This is a feature on top of ALPM, AS SDP.
Add compute config during atomic-check phase.

v1: RFC version.
v2: Add separate flag for auxless-alpm. [Jani]
v3:
- intel_dp->lobf_supported replaced with crtc_state->has_lobf. [Jouni]
- Add DISPLAY_VER() check. [Jouni]
- Modify function name of get_aux_less_status. [Jani]
v4: Add enum alpm_mode to hold the aux-wake/less capability.

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_alpm.c | 58 +++
 drivers/gpu/drm/i915/display/intel_alpm.h |  5 ++
 .../drm/i915/display/intel_display_types.h| 11 
 drivers/gpu/drm/i915/display/intel_dp.c   |  4 ++
 4 files changed, 78 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c 
b/drivers/gpu/drm/i915/display/intel_alpm.c
index ee6c2a959f09..5979eab1f2e0 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.c
+++ b/drivers/gpu/drm/i915/display/intel_alpm.c
@@ -11,6 +11,23 @@
 #include "intel_dp_aux.h"
 #include "intel_psr_regs.h"
 
+enum alpm_mode intel_alpm_get_capability(struct intel_dp *intel_dp)
+{
+   u8 alpm_caps = 0;
+
+   if (drm_dp_dpcd_readb(_dp->aux, DP_RECEIVER_ALPM_CAP,
+ _caps) != 1)
+   return ALPM_INVALID;
+
+   if (alpm_caps & DP_ALPM_CAP)
+   return ALPM_AUX_WAKE;
+
+   if (alpm_caps & DP_ALPM_AUX_LESS_CAP)
+   return ALPM_AUX_LESS;
+
+   return ALPM_NOT_SUPPORTED;
+}
+
 /*
  * See Bspec: 71632 for the table
  *
@@ -242,6 +259,47 @@ bool intel_alpm_compute_params(struct intel_dp *intel_dp,
return true;
 }
 
+void intel_alpm_compute_lobf_config(struct intel_dp *intel_dp,
+   struct intel_crtc_state *crtc_state,
+   struct drm_connector_state *conn_state)
+{
+   struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+   struct drm_display_mode *adjusted_mode = _state->hw.adjusted_mode;
+   int waketime_in_lines, first_sdp_position;
+   int context_latency, guardband;
+
+   if (!intel_dp_is_edp(intel_dp))
+   return;
+
+   if (DISPLAY_VER(i915) < 20)
+   return;
+
+   if (!intel_dp_as_sdp_supported(intel_dp))
+   return;
+
+   if (crtc_state->has_psr)
+   return;
+
+   if (intel_dp->alpm_parameters.mode == ALPM_INVALID ||
+   intel_dp->alpm_parameters.mode == ALPM_NOT_SUPPORTED)
+   return;
+
+   if (!intel_alpm_compute_params(intel_dp, crtc_state))
+   return;
+
+   context_latency = adjusted_mode->crtc_vblank_start - 
adjusted_mode->crtc_vdisplay;
+   guardband = adjusted_mode->crtc_vtotal -
+   adjusted_mode->crtc_vdisplay - context_latency;
+   first_sdp_position = adjusted_mode->crtc_vtotal - 
adjusted_mode->crtc_vsync_start;
+   if (intel_dp->alpm_parameters.mode == ALPM_AUX_LESS)
+   waketime_in_lines = intel_dp->alpm_parameters.io_wake_lines;
+   else
+   waketime_in_lines = intel_dp->alpm_parameters.fast_wake_lines;
+
+   crtc_state->has_lobf = (context_latency + guardband) >
+   (first_sdp_position + waketime_in_lines);
+}
+
 static void lnl_alpm_configure(struct intel_dp *intel_dp)
 {
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
diff --git a/drivers/gpu/drm/i915/display/intel_alpm.h 
b/drivers/gpu/drm/i915/display/intel_alpm.h
index c45d078e5a6b..80c8a66b34af 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.h
+++ b/drivers/gpu/drm/i915/display/intel_alpm.h
@@ -10,9 +10,14 @@
 
 struct intel_dp;
 struct intel_crtc_state;
+struct drm_connector_state;
 
+enum alpm_mode intel_alpm_get_capability(struct intel_dp *intel_dp);
 bool intel_alpm_compute_params(struct intel_dp *intel_dp,
   struct intel_crtc_state *crtc_state);
+void intel_alpm_compute_lobf_config(struct intel_dp *intel_dp,
+   struct intel_crtc_state *crtc_state,
+   struct drm_connector_state *conn_state);
 void intel_alpm_configure(struct intel_dp *intel_dp);
 
 #endif
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index e81fd71ce57b..79e9e543020b 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1405,6 +1405,9 @@ struct intel_crtc_state {
 
/* for loading single buffered registers during vblank */
struct drm_vblank_work vblank_work;
+
+   /* LOBF flag */
+   bool has_lobf;
 };
 
 enum intel_pipe_crc_source {
@@ -1715,6 +1718,13 @@ struct intel_psr {
u8 entry_setup_frames;
 };
 
+enum alpm_mode {
+   A

[PATCH v4 3/6] drm/display: Add missing aux less alpm wake related bits

2024-05-08 Thread Animesh Manna
From: Jouni Högander 

eDP1.5 adds some more bits into DP_RECEIVER_ALPM_CAP and
DP_RECEIVER_ALPM_CONFIG registers. Add definitions for these.

Signed-off-by: Jouni Högander 
---
 include/drm/display/drm_dp.h | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/include/drm/display/drm_dp.h b/include/drm/display/drm_dp.h
index 0b032faa8cf2..ad0cb0a1de87 100644
--- a/include/drm/display/drm_dp.h
+++ b/include/drm/display/drm_dp.h
@@ -232,6 +232,8 @@
 
 #define DP_RECEIVER_ALPM_CAP   0x02e   /* eDP 1.4 */
 # define DP_ALPM_CAP   (1 << 0)
+# define DP_ALPM_PM_STATE_2A_SUPPORT   (1 << 1) /* eDP 1.5 */
+# define DP_ALPM_AUX_LESS_CAP  (1 << 2) /* eDP 1.5 */
 
 #define DP_SINK_DEVICE_AUX_FRAME_SYNC_CAP   0x02f   /* eDP 1.4 */
 # define DP_AUX_FRAME_SYNC_CAP (1 << 0)
@@ -677,7 +679,8 @@
 
 #define DP_RECEIVER_ALPM_CONFIG0x116   /* eDP 1.4 */
 # define DP_ALPM_ENABLE(1 << 0)
-# define DP_ALPM_LOCK_ERROR_IRQ_HPD_ENABLE  (1 << 1)
+# define DP_ALPM_LOCK_ERROR_IRQ_HPD_ENABLE  (1 << 1) /* eDP 1.5 */
+# define DP_ALPM_MODE_AUX_LESS (1 << 2) /* eDP 1.5 */
 
 #define DP_SINK_DEVICE_AUX_FRAME_SYNC_CONF  0x117   /* eDP 1.4 */
 # define DP_AUX_FRAME_SYNC_ENABLE  (1 << 0)
-- 
2.29.0



[PATCH v4 2/6] drm/i915/alpm: Move alpm related code to a new file

2024-05-08 Thread Animesh Manna
Move ALPM feature related code as it will be used for
non-psr panel also thorugh LOBF feature.

v1: Initial version.
v2: Correct ordering in makefile. [Jani]

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/Makefile |   1 +
 drivers/gpu/drm/i915/display/intel_alpm.c | 292 ++
 drivers/gpu/drm/i915/display/intel_alpm.h |  18 ++
 drivers/gpu/drm/i915/display/intel_psr.c  | 282 +
 drivers/gpu/drm/xe/Makefile   |   1 +
 5 files changed, 315 insertions(+), 279 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_alpm.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_alpm.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 7cad944b825c..9a3f910ce4fd 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -243,6 +243,7 @@ i915-y += \
display/hsw_ips.o \
display/i9xx_plane.o \
display/i9xx_wm.o \
+   display/intel_alpm.o \
display/intel_atomic.o \
display/intel_atomic_plane.o \
display/intel_audio.o \
diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c 
b/drivers/gpu/drm/i915/display/intel_alpm.c
new file mode 100644
index ..ee6c2a959f09
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_alpm.c
@@ -0,0 +1,292 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2024, Intel Corporation.
+ */
+
+#include "intel_alpm.h"
+#include "intel_crtc.h"
+#include "intel_de.h"
+#include "intel_display_types.h"
+#include "intel_dp.h"
+#include "intel_dp_aux.h"
+#include "intel_psr_regs.h"
+
+/*
+ * See Bspec: 71632 for the table
+ *
+ * Silence_period = tSilence,Min + ((tSilence,Max - tSilence,Min) / 2)
+ *
+ * Half cycle duration:
+ *
+ * Link rates 1.62 - 4.32 and tLFPS_Cycle = 70 ns
+ * FLOOR( (Link Rate * tLFPS_Cycle) / (2 * 10) )
+ *
+ * Link rates 5.4 - 8.1
+ * PORT_ALPM_LFPS_CTL[ LFPS Cycle Count ] = 10
+ * LFPS Period chosen is the mid-point of the min:max values from the table
+ * FLOOR( LFPS Period in Symbol clocks /
+ * (2 * PORT_ALPM_LFPS_CTL[ LFPS Cycle Count ]) )
+ */
+static bool _lnl_get_silence_period_and_lfps_half_cycle(int link_rate,
+   int *silence_period,
+   int *lfps_half_cycle)
+{
+   switch (link_rate) {
+   case 162000:
+   *silence_period = 20;
+   *lfps_half_cycle = 5;
+   break;
+   case 216000:
+   *silence_period = 27;
+   *lfps_half_cycle = 7;
+   break;
+   case 243000:
+   *silence_period = 31;
+   *lfps_half_cycle = 8;
+   break;
+   case 27:
+   *silence_period = 34;
+   *lfps_half_cycle = 9;
+   break;
+   case 324000:
+   *silence_period = 41;
+   *lfps_half_cycle = 11;
+   break;
+   case 432000:
+   *silence_period = 56;
+   *lfps_half_cycle = 15;
+   break;
+   case 54:
+   *silence_period = 69;
+   *lfps_half_cycle = 12;
+   break;
+   case 648000:
+   *silence_period = 84;
+   *lfps_half_cycle = 15;
+   break;
+   case 675000:
+   *silence_period = 87;
+   *lfps_half_cycle = 15;
+   break;
+   case 81:
+   *silence_period = 104;
+   *lfps_half_cycle = 19;
+   break;
+   default:
+   *silence_period = *lfps_half_cycle = -1;
+   return false;
+   }
+   return true;
+}
+
+/*
+ * AUX-Less Wake Time = CEILING( ((PHY P2 to P0) + tLFPS_Period, Max+
+ * tSilence, Max+ tPHY Establishment + tCDS) / tline)
+ * For the "PHY P2 to P0" latency see the PHY Power Control page
+ * (PHY P2 to P0) : https://gfxspecs.intel.com/Predator/Home/Index/68965
+ * : 12 us
+ * The tLFPS_Period, Max term is 800ns
+ * The tSilence, Max term is 180ns
+ * The tPHY Establishment (a.k.a. t1) term is 50us
+ * The tCDS term is 1 or 2 times t2
+ * t2 = Number ML_PHY_LOCK * tML_PHY_LOCK
+ * Number ML_PHY_LOCK = ( 7 + CEILING( 6.5us / tML_PHY_LOCK ) + 1)
+ * Rounding up the 6.5us padding to the next ML_PHY_LOCK boundary and
+ * adding the "+ 1" term ensures all ML_PHY_LOCK sequences that start
+ * within the CDS period complete within the CDS period regardless of
+ * entry into the period
+ * tML_PHY_LOCK = TPS4 Length * ( 10 / (Link Rate in MHz) )
+ * TPS4 Length = 252 Symbols
+ */
+static int _lnl_compute_aux_less_wake_time(int port_clock)
+{
+   int tphy2_p2_to_p0 = 12 * 1000;
+   int tlfps_period_max = 800;
+   int tsilence_max = 180;
+   int t1 = 50 * 1000;
+   int tps4 = 252;
+   int tml_phy_lock = 1000 * 1000 * tps4 * 10 / port_clo

[PATCH v4 1/6] drm/i915/alpm: Move alpm parameters from intel_psr

2024-05-08 Thread Animesh Manna
ALPM can be enabled for non psr panel and currenly aplm-params are
encapsulated under intel_psr struct, so moving out to intel_dp struct.

Signed-off-by: Animesh Manna 
---
 .../drm/i915/display/intel_display_types.h| 21 +
 drivers/gpu/drm/i915/display/intel_psr.c  | 43 +--
 2 files changed, 31 insertions(+), 33 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index 00eba3fbcdc6..e81fd71ce57b 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1700,17 +1700,6 @@ struct intel_psr {
bool psr2_sel_fetch_cff_enabled;
bool req_psr2_sdp_prior_scanline;
u8 sink_sync_latency;
-
-   struct {
-   u8 io_wake_lines;
-   u8 fast_wake_lines;
-
-   /* LNL and beyond */
-   u8 check_entry_lines;
-   u8 silence_period_sym_clocks;
-   u8 lfps_half_cycle_num_of_syms;
-   } alpm_parameters;
-
ktime_t last_entry_attempt;
ktime_t last_exit;
bool sink_not_reliable;
@@ -1840,6 +1829,16 @@ struct intel_dp {
unsigned long last_oui_write;
 
bool colorimetry_support;
+
+   struct {
+   u8 io_wake_lines;
+   u8 fast_wake_lines;
+
+   /* LNL and beyond */
+   u8 check_entry_lines;
+   u8 silence_period_sym_clocks;
+   u8 lfps_half_cycle_num_of_syms;
+   } alpm_parameters;
 };
 
 enum lspcon_vendor {
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index 595eb1b3b6c6..13c0f44f48b9 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -816,8 +816,8 @@ static u32 intel_psr2_get_tp_time(struct intel_dp *intel_dp)
 
 static int psr2_block_count_lines(struct intel_dp *intel_dp)
 {
-   return intel_dp->psr.alpm_parameters.io_wake_lines < 9 &&
-   intel_dp->psr.alpm_parameters.fast_wake_lines < 9 ? 8 : 12;
+   return intel_dp->alpm_parameters.io_wake_lines < 9 &&
+   intel_dp->alpm_parameters.fast_wake_lines < 9 ? 8 : 12;
 }
 
 static int psr2_block_count(struct intel_dp *intel_dp)
@@ -855,7 +855,6 @@ static void dg2_activate_panel_replay(struct intel_dp 
*intel_dp)
 static void hsw_activate_psr2(struct intel_dp *intel_dp)
 {
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-   struct intel_psr *psr = _dp->psr;
enum transcoder cpu_transcoder = intel_dp->psr.transcoder;
u32 val = EDP_PSR2_ENABLE;
u32 psr_val = 0;
@@ -897,18 +896,19 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp)
 */
int tmp;
 
-   tmp = map[psr->alpm_parameters.io_wake_lines -
+   tmp = map[intel_dp->alpm_parameters.io_wake_lines -
  TGL_EDP_PSR2_IO_BUFFER_WAKE_MIN_LINES];
val |= TGL_EDP_PSR2_IO_BUFFER_WAKE(tmp + 
TGL_EDP_PSR2_IO_BUFFER_WAKE_MIN_LINES);
 
-   tmp = map[psr->alpm_parameters.fast_wake_lines - 
TGL_EDP_PSR2_FAST_WAKE_MIN_LINES];
+   tmp = map[intel_dp->alpm_parameters.fast_wake_lines -
+ TGL_EDP_PSR2_FAST_WAKE_MIN_LINES];
val |= TGL_EDP_PSR2_FAST_WAKE(tmp + 
TGL_EDP_PSR2_FAST_WAKE_MIN_LINES);
} else if (DISPLAY_VER(dev_priv) >= 12) {
-   val |= 
TGL_EDP_PSR2_IO_BUFFER_WAKE(psr->alpm_parameters.io_wake_lines);
-   val |= 
TGL_EDP_PSR2_FAST_WAKE(psr->alpm_parameters.fast_wake_lines);
+   val |= 
TGL_EDP_PSR2_IO_BUFFER_WAKE(intel_dp->alpm_parameters.io_wake_lines);
+   val |= 
TGL_EDP_PSR2_FAST_WAKE(intel_dp->alpm_parameters.fast_wake_lines);
} else if (DISPLAY_VER(dev_priv) >= 9) {
-   val |= 
EDP_PSR2_IO_BUFFER_WAKE(psr->alpm_parameters.io_wake_lines);
-   val |= EDP_PSR2_FAST_WAKE(psr->alpm_parameters.fast_wake_lines);
+   val |= 
EDP_PSR2_IO_BUFFER_WAKE(intel_dp->alpm_parameters.io_wake_lines);
+   val |= 
EDP_PSR2_FAST_WAKE(intel_dp->alpm_parameters.fast_wake_lines);
}
 
if (intel_dp->psr.req_psr2_sdp_prior_scanline)
@@ -1294,9 +1294,9 @@ static int _lnl_compute_aux_less_alpm_params(struct 
intel_dp *intel_dp,
if (i915->display.params.psr_safest_params)
aux_less_wake_lines = ALPM_CTL_AUX_LESS_WAKE_TIME_MASK;
 
-   intel_dp->psr.alpm_parameters.fast_wake_lines = aux_less_wake_lines;
-   intel_dp->psr.alpm_parameters.silence_period_sym_clocks = 
silence_period;
-   intel_dp->psr.alpm_parameters.lfps_half_cycle_num_of_syms = 
lfps_half_cycle;
+   intel_dp->alpm_parameters.fast_wake_lines = aux_less_wake_lines;
+   intel_dp->alpm_paramet

[PATCH v4 0/6] Link off between frames for edp

2024-05-08 Thread Animesh Manna
Link Off Between Active Frames (LOBF) allows an eDP link to be turned Off and On
durning long VBLANK durations without enabling any of the PSR/PSR2/PR modes of 
operation.

Bspec: 71477

Note: Lobf need to be enabled adaptive sync fixed refresh mode
where vmin = vmax = flipline, which will arise after cmmr feature
enablement. Currently existing code refactored and make compute-config()
and enabling function ready. Will add enabling sequence in a separate patch.

Signed-off-by: Animesh Manna 

Animesh Manna (5):
  drm/i915/alpm: Move alpm parameters from intel_psr
  drm/i915/alpm: Move alpm related code to a new file
  drm/i915/alpm: Add compute config for lobf
  drm/i915/alpm: Enable lobf from source in ALPM_CTL
  drm/i915/alpm: Add debugfs for LOBF

Jouni Högander (1):
  drm/display: Add missing aux less alpm wake related bits

 drivers/gpu/drm/i915/Makefile |   1 +
 drivers/gpu/drm/i915/display/intel_alpm.c | 405 ++
 drivers/gpu/drm/i915/display/intel_alpm.h |  25 ++
 .../drm/i915/display/intel_display_debugfs.c  |   2 +
 .../drm/i915/display/intel_display_types.h|  32 +-
 drivers/gpu/drm/i915/display/intel_dp.c   |   4 +
 drivers/gpu/drm/i915/display/intel_psr.c  | 301 +
 drivers/gpu/drm/xe/Makefile   |   1 +
 include/drm/display/drm_dp.h  |   5 +-
 9 files changed, 475 insertions(+), 301 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_alpm.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_alpm.h

-- 
2.29.0



[PATCH v3 6/6] drm/i915/alpm: Add debugfs for LOBF

2024-04-24 Thread Animesh Manna
For validation purpose add debugfs for LOBF.

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_alpm.c | 48 +++
 drivers/gpu/drm/i915/display/intel_alpm.h |  2 +
 .../drm/i915/display/intel_display_debugfs.c  |  2 +
 3 files changed, 52 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c 
b/drivers/gpu/drm/i915/display/intel_alpm.c
index b08799586b58..2d3027c2fb0a 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.c
+++ b/drivers/gpu/drm/i915/display/intel_alpm.c
@@ -343,3 +343,51 @@ void intel_alpm_configure(struct intel_dp *intel_dp,
 {
lnl_alpm_configure(intel_dp, crtc_state);
 }
+
+static int i915_edp_lobf_info_show(struct seq_file *m, void *data)
+{
+   struct intel_connector *connector = m->private;
+   struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+   struct drm_crtc *crtc;
+   struct intel_crtc_state *crtc_state;
+   enum transcoder cpu_transcoder;
+   bool lobf_enabled;
+   int ret;
+
+   ret = 
drm_modeset_lock_single_interruptible(_priv->drm.mode_config.connection_mutex);
+   if (ret)
+   return ret;
+
+   crtc = connector->base.state->crtc;
+   if (connector->base.status != connector_status_connected || !crtc) {
+   ret = -ENODEV;
+   goto out;
+   }
+
+   crtc_state = to_intel_crtc_state(crtc->state);
+   seq_printf(m, "LOBF Criteria met: %s\n", 
str_yes_no(crtc_state->has_lobf));
+
+   cpu_transcoder = crtc_state->cpu_transcoder;
+   lobf_enabled = intel_de_read(dev_priv, ALPM_CTL(cpu_transcoder)) & 
ALPM_CTL_LOBF_ENABLE;
+   seq_printf(m, "LOBF status: %s\n", str_enabled_disabled(lobf_enabled));
+
+out:
+   drm_modeset_unlock(_priv->drm.mode_config.connection_mutex);
+
+   return ret;
+}
+
+DEFINE_SHOW_ATTRIBUTE(i915_edp_lobf_info);
+
+void intel_alpm_lobf_debugfs_add(struct intel_connector *connector)
+{
+   struct drm_i915_private *i915 = to_i915(connector->base.dev);
+   struct dentry *root = connector->base.debugfs_entry;
+
+   if (DISPLAY_VER(i915) < 20 ||
+   connector->base.connector_type != DRM_MODE_CONNECTOR_eDP)
+   return;
+
+   debugfs_create_file("i915_edp_lobf_info", 0444, root,
+   connector, _edp_lobf_info_fops);
+}
diff --git a/drivers/gpu/drm/i915/display/intel_alpm.h 
b/drivers/gpu/drm/i915/display/intel_alpm.h
index a9ca190da3e4..01fd08eb96f5 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.h
+++ b/drivers/gpu/drm/i915/display/intel_alpm.h
@@ -11,6 +11,7 @@
 struct intel_dp;
 struct intel_crtc_state;
 struct drm_connector_state;
+struct intel_connector;
 
 bool intel_alpm_get_aux_less_status(struct intel_dp *intel_dp);
 bool intel_alpm_compute_params(struct intel_dp *intel_dp,
@@ -20,4 +21,5 @@ void intel_alpm_compute_lobf_config(struct intel_dp *intel_dp,
struct drm_connector_state *conn_state);
 void intel_alpm_configure(struct intel_dp *intel_dp,
  const struct intel_crtc_state *crtc_state);
+void intel_alpm_lobf_debugfs_add(struct intel_connector *connector);
 #endif
diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c 
b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
index 35f9f86ef70f..86d9900c40af 100644
--- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
+++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
@@ -13,6 +13,7 @@
 #include "i915_debugfs.h"
 #include "i915_irq.h"
 #include "i915_reg.h"
+#include "intel_alpm.h"
 #include "intel_crtc.h"
 #include "intel_de.h"
 #include "intel_crtc_state_dump.h"
@@ -1515,6 +1516,7 @@ void intel_connector_debugfs_add(struct intel_connector 
*connector)
intel_drrs_connector_debugfs_add(connector);
intel_pps_connector_debugfs_add(connector);
intel_psr_connector_debugfs_add(connector);
+   intel_alpm_lobf_debugfs_add(connector);
 
if (connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
connector_type == DRM_MODE_CONNECTOR_HDMIA ||
-- 
2.29.0



[PATCH v3 5/6] drm/i915/alpm: Enable lobf from source in ALPM_CTL

2024-04-24 Thread Animesh Manna
Set the Link Off Between Frames Enable bit in ALPM_CTL register.

Note: Lobf need to be enabled adaptive sync fixed refresh mode
where vmin = vmax = flipline, which will arise after cmmr feature
enablement. Will add enabling sequence in a separate patch.

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_alpm.c | 13 +
 drivers/gpu/drm/i915/display/intel_alpm.h |  4 ++--
 drivers/gpu/drm/i915/display/intel_psr.c  |  2 +-
 3 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c 
b/drivers/gpu/drm/i915/display/intel_alpm.c
index 3bb69ed16aab..b08799586b58 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.c
+++ b/drivers/gpu/drm/i915/display/intel_alpm.c
@@ -290,10 +290,11 @@ void intel_alpm_compute_lobf_config(struct intel_dp 
*intel_dp,
}
 }
 
-static void lnl_alpm_configure(struct intel_dp *intel_dp)
+static void lnl_alpm_configure(struct intel_dp *intel_dp,
+  const struct intel_crtc_state *crtc_state)
 {
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-   enum transcoder cpu_transcoder = intel_dp->psr.transcoder;
+   enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
u32 alpm_ctl;
 
if (DISPLAY_VER(dev_priv) < 20 || (!intel_dp->psr.psr2_enabled &&
@@ -329,12 +330,16 @@ static void lnl_alpm_configure(struct intel_dp *intel_dp)
   
ALPM_CTL_EXTENDED_FAST_WAKE_TIME(intel_dp->alpm_parameters.fast_wake_lines);
}
 
+   if (crtc_state->has_lobf)
+   alpm_ctl |= ALPM_CTL_LOBF_ENABLE;
+
alpm_ctl |= 
ALPM_CTL_ALPM_ENTRY_CHECK(intel_dp->alpm_parameters.check_entry_lines);
 
intel_de_write(dev_priv, ALPM_CTL(cpu_transcoder), alpm_ctl);
 }
 
-void intel_alpm_configure(struct intel_dp *intel_dp)
+void intel_alpm_configure(struct intel_dp *intel_dp,
+ const struct intel_crtc_state *crtc_state)
 {
-   lnl_alpm_configure(intel_dp);
+   lnl_alpm_configure(intel_dp, crtc_state);
 }
diff --git a/drivers/gpu/drm/i915/display/intel_alpm.h 
b/drivers/gpu/drm/i915/display/intel_alpm.h
index b9602b71d28f..a9ca190da3e4 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.h
+++ b/drivers/gpu/drm/i915/display/intel_alpm.h
@@ -18,6 +18,6 @@ bool intel_alpm_compute_params(struct intel_dp *intel_dp,
 void intel_alpm_compute_lobf_config(struct intel_dp *intel_dp,
struct intel_crtc_state *crtc_state,
struct drm_connector_state *conn_state);
-void intel_alpm_configure(struct intel_dp *intel_dp);
-
+void intel_alpm_configure(struct intel_dp *intel_dp,
+ const struct intel_crtc_state *crtc_state);
 #endif
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index c4ab289dbc15..4eb45df20ad2 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -1611,7 +1611,7 @@ static void intel_psr_enable_source(struct intel_dp 
*intel_dp,
 IGNORE_PSR2_HW_TRACKING : 0);
 
if (intel_dp_is_edp(intel_dp))
-   intel_alpm_configure(intel_dp);
+   intel_alpm_configure(intel_dp, crtc_state);
 
/*
 * Wa_16013835468
-- 
2.29.0



[PATCH v3 4/6] drm/i915/alpm: Add compute config for lobf

2024-04-24 Thread Animesh Manna
Link Off Between Active Frames, is a new feature for eDP
that allows the panel to go to lower power state after
transmission of data. This is a feature on top of ALPM, AS SDP.
Add compute config during atomic-check phase.

v1: RFC version.
v2: Add separate flag for auxless-alpm. [Jani]
v3:
- intel_dp->lobf_supported replaced with crtc_state->has_lobf. [Jouni]
- Add DISPLAY_VER() check. [Jouni]
- Modify function name of get_aux_less_status. [Jani]

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_alpm.c | 48 +++
 drivers/gpu/drm/i915/display/intel_alpm.h |  5 ++
 .../drm/i915/display/intel_display_types.h|  4 ++
 drivers/gpu/drm/i915/display/intel_dp.c   |  4 ++
 4 files changed, 61 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c 
b/drivers/gpu/drm/i915/display/intel_alpm.c
index 13bac3e8c8fa..3bb69ed16aab 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.c
+++ b/drivers/gpu/drm/i915/display/intel_alpm.c
@@ -11,6 +11,16 @@
 #include "intel_dp_aux.h"
 #include "intel_psr_regs.h"
 
+bool intel_alpm_get_aux_less_status(struct intel_dp *intel_dp)
+{
+   u8 alpm_caps = 0;
+
+   if (drm_dp_dpcd_readb(_dp->aux, DP_RECEIVER_ALPM_CAP,
+ _caps) != 1)
+   return false;
+   return alpm_caps & DP_ALPM_AUX_LESS_CAP;
+}
+
 /*
  * See Bspec: 71632 for the table
  *
@@ -242,6 +252,44 @@ bool intel_alpm_compute_params(struct intel_dp *intel_dp,
return true;
 }
 
+void intel_alpm_compute_lobf_config(struct intel_dp *intel_dp,
+   struct intel_crtc_state *crtc_state,
+   struct drm_connector_state *conn_state)
+{
+   struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+   struct drm_display_mode *adjusted_mode = _state->hw.adjusted_mode;
+   int waketime_in_lines, first_sdp_position;
+   int context_latency, guardband;
+
+   crtc_state->has_lobf = false;
+
+   if (!intel_dp_is_edp(intel_dp))
+   return;
+
+   if (DISPLAY_VER(i915) < 20)
+   return;
+
+   if (!intel_dp_as_sdp_supported(intel_dp))
+   return;
+
+   if (crtc_state->has_psr)
+   return;
+
+   if (intel_alpm_compute_params(intel_dp, crtc_state)) {
+   context_latency = adjusted_mode->crtc_vblank_start - 
adjusted_mode->crtc_vdisplay;
+   guardband = adjusted_mode->crtc_vtotal -
+   adjusted_mode->crtc_vdisplay - context_latency;
+   first_sdp_position = adjusted_mode->crtc_vtotal - 
adjusted_mode->crtc_vsync_start;
+   if (intel_dp->alpm_parameters.auxless_alpm_supported)
+   waketime_in_lines = 
intel_dp->alpm_parameters.io_wake_lines;
+   else
+   waketime_in_lines = 
intel_dp->alpm_parameters.fast_wake_lines;
+
+   if ((context_latency + guardband) > (first_sdp_position + 
waketime_in_lines))
+   crtc_state->has_lobf = true;
+   }
+}
+
 static void lnl_alpm_configure(struct intel_dp *intel_dp)
 {
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
diff --git a/drivers/gpu/drm/i915/display/intel_alpm.h 
b/drivers/gpu/drm/i915/display/intel_alpm.h
index c45d078e5a6b..b9602b71d28f 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.h
+++ b/drivers/gpu/drm/i915/display/intel_alpm.h
@@ -10,9 +10,14 @@
 
 struct intel_dp;
 struct intel_crtc_state;
+struct drm_connector_state;
 
+bool intel_alpm_get_aux_less_status(struct intel_dp *intel_dp);
 bool intel_alpm_compute_params(struct intel_dp *intel_dp,
   struct intel_crtc_state *crtc_state);
+void intel_alpm_compute_lobf_config(struct intel_dp *intel_dp,
+   struct intel_crtc_state *crtc_state,
+   struct drm_connector_state *conn_state);
 void intel_alpm_configure(struct intel_dp *intel_dp);
 
 #endif
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index d94f50c6dc6c..5a0ffd5aa48b 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1405,6 +1405,9 @@ struct intel_crtc_state {
 
/* for loading single buffered registers during vblank */
struct drm_vblank_work vblank_work;
+
+   /* LOBF flag */
+   bool has_lobf;
 };
 
 enum intel_pipe_crc_source {
@@ -1835,6 +1838,7 @@ struct intel_dp {
u8 fast_wake_lines;
 
/* LNL and beyond */
+   bool auxless_alpm_supported;
u8 check_entry_lines;
u8 silence_period_sym_clocks;
u8 lfps_half_cycle_num_of_syms;
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_d

[PATCH v3 2/6] drm/i915/alpm: Move alpm related code to a new file

2024-04-24 Thread Animesh Manna
Move ALPM feature related code as it will be used for
non-psr panel also thorugh LOBF feature.

v1: Initial version.
v2: Correct ordering in makefile. [Jani]

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/Makefile |   1 +
 drivers/gpu/drm/i915/display/intel_alpm.c | 292 ++
 drivers/gpu/drm/i915/display/intel_alpm.h |  18 ++
 drivers/gpu/drm/i915/display/intel_psr.c  | 280 +
 4 files changed, 314 insertions(+), 277 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_alpm.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_alpm.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 7cad944b825c..9a3f910ce4fd 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -243,6 +243,7 @@ i915-y += \
display/hsw_ips.o \
display/i9xx_plane.o \
display/i9xx_wm.o \
+   display/intel_alpm.o \
display/intel_atomic.o \
display/intel_atomic_plane.o \
display/intel_audio.o \
diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c 
b/drivers/gpu/drm/i915/display/intel_alpm.c
new file mode 100644
index ..13bac3e8c8fa
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_alpm.c
@@ -0,0 +1,292 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2024, Intel Corporation.
+ */
+
+#include "intel_alpm.h"
+#include "intel_crtc.h"
+#include "intel_de.h"
+#include "intel_display_types.h"
+#include "intel_dp.h"
+#include "intel_dp_aux.h"
+#include "intel_psr_regs.h"
+
+/*
+ * See Bspec: 71632 for the table
+ *
+ * Silence_period = tSilence,Min + ((tSilence,Max - tSilence,Min) / 2)
+ *
+ * Half cycle duration:
+ *
+ * Link rates 1.62 - 4.32 and tLFPS_Cycle = 70 ns
+ * FLOOR( (Link Rate * tLFPS_Cycle) / (2 * 10) )
+ *
+ * Link rates 5.4 - 8.1
+ * PORT_ALPM_LFPS_CTL[ LFPS Cycle Count ] = 10
+ * LFPS Period chosen is the mid-point of the min:max values from the table
+ * FLOOR( LFPS Period in Symbol clocks /
+ * (2 * PORT_ALPM_LFPS_CTL[ LFPS Cycle Count ]) )
+ */
+static bool _lnl_get_silence_period_and_lfps_half_cycle(int link_rate,
+   int *silence_period,
+   int *lfps_half_cycle)
+{
+   switch (link_rate) {
+   case 162000:
+   *silence_period = 20;
+   *lfps_half_cycle = 5;
+   break;
+   case 216000:
+   *silence_period = 27;
+   *lfps_half_cycle = 7;
+   break;
+   case 243000:
+   *silence_period = 31;
+   *lfps_half_cycle = 8;
+   break;
+   case 27:
+   *silence_period = 34;
+   *lfps_half_cycle = 9;
+   break;
+   case 324000:
+   *silence_period = 41;
+   *lfps_half_cycle = 11;
+   break;
+   case 432000:
+   *silence_period = 56;
+   *lfps_half_cycle = 15;
+   break;
+   case 54:
+   *silence_period = 69;
+   *lfps_half_cycle = 12;
+   break;
+   case 648000:
+   *silence_period = 84;
+   *lfps_half_cycle = 15;
+   break;
+   case 675000:
+   *silence_period = 87;
+   *lfps_half_cycle = 15;
+   break;
+   case 81:
+   *silence_period = 104;
+   *lfps_half_cycle = 19;
+   break;
+   default:
+   *silence_period = *lfps_half_cycle = -1;
+   return false;
+   }
+   return true;
+}
+
+/*
+ * AUX-Less Wake Time = CEILING( ((PHY P2 to P0) + tLFPS_Period, Max+
+ * tSilence, Max+ tPHY Establishment + tCDS) / tline)
+ * For the "PHY P2 to P0" latency see the PHY Power Control page
+ * (PHY P2 to P0) : https://gfxspecs.intel.com/Predator/Home/Index/68965
+ * : 12 us
+ * The tLFPS_Period, Max term is 800ns
+ * The tSilence, Max term is 180ns
+ * The tPHY Establishment (a.k.a. t1) term is 50us
+ * The tCDS term is 1 or 2 times t2
+ * t2 = Number ML_PHY_LOCK * tML_PHY_LOCK
+ * Number ML_PHY_LOCK = ( 7 + CEILING( 6.5us / tML_PHY_LOCK ) + 1)
+ * Rounding up the 6.5us padding to the next ML_PHY_LOCK boundary and
+ * adding the "+ 1" term ensures all ML_PHY_LOCK sequences that start
+ * within the CDS period complete within the CDS period regardless of
+ * entry into the period
+ * tML_PHY_LOCK = TPS4 Length * ( 10 / (Link Rate in MHz) )
+ * TPS4 Length = 252 Symbols
+ */
+static int _lnl_compute_aux_less_wake_time(int port_clock)
+{
+   int tphy2_p2_to_p0 = 12 * 1000;
+   int tlfps_period_max = 800;
+   int tsilence_max = 180;
+   int t1 = 50 * 1000;
+   int tps4 = 252;
+   int tml_phy_lock = 1000 * 1000 * tps4 * 10 / port_clock;
+   int num_ml_phy_lock = 7 + DIV_ROUND_UP(6500, tml

[PATCH v3 3/6] drm/display: Add missing aux less alpm wake related bits

2024-04-24 Thread Animesh Manna
From: Jouni Högander 

eDP1.5 adds some more bits into DP_RECEIVER_ALPM_CAP and
DP_RECEIVER_ALPM_CONFIG registers. Add definitions for these.

Signed-off-by: Jouni Högander 
---
 include/drm/display/drm_dp.h | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/include/drm/display/drm_dp.h b/include/drm/display/drm_dp.h
index 0b032faa8cf2..ad0cb0a1de87 100644
--- a/include/drm/display/drm_dp.h
+++ b/include/drm/display/drm_dp.h
@@ -232,6 +232,8 @@
 
 #define DP_RECEIVER_ALPM_CAP   0x02e   /* eDP 1.4 */
 # define DP_ALPM_CAP   (1 << 0)
+# define DP_ALPM_PM_STATE_2A_SUPPORT   (1 << 1) /* eDP 1.5 */
+# define DP_ALPM_AUX_LESS_CAP  (1 << 2) /* eDP 1.5 */
 
 #define DP_SINK_DEVICE_AUX_FRAME_SYNC_CAP   0x02f   /* eDP 1.4 */
 # define DP_AUX_FRAME_SYNC_CAP (1 << 0)
@@ -677,7 +679,8 @@
 
 #define DP_RECEIVER_ALPM_CONFIG0x116   /* eDP 1.4 */
 # define DP_ALPM_ENABLE(1 << 0)
-# define DP_ALPM_LOCK_ERROR_IRQ_HPD_ENABLE  (1 << 1)
+# define DP_ALPM_LOCK_ERROR_IRQ_HPD_ENABLE  (1 << 1) /* eDP 1.5 */
+# define DP_ALPM_MODE_AUX_LESS (1 << 2) /* eDP 1.5 */
 
 #define DP_SINK_DEVICE_AUX_FRAME_SYNC_CONF  0x117   /* eDP 1.4 */
 # define DP_AUX_FRAME_SYNC_ENABLE  (1 << 0)
-- 
2.29.0



[PATCH v3 1/6] drm/i915/alpm: Move alpm parameters from intel_psr

2024-04-24 Thread Animesh Manna
ALPM can be enabled for non psr panel and currenly aplm-params are
encapsulated under intel_psr struct, so moving out to intel_dp struct.

Signed-off-by: Animesh Manna 
---
 .../drm/i915/display/intel_display_types.h| 21 +
 drivers/gpu/drm/i915/display/intel_psr.c  | 43 +--
 2 files changed, 31 insertions(+), 33 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index 62f7a30c37dc..d94f50c6dc6c 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1700,17 +1700,6 @@ struct intel_psr {
bool psr2_sel_fetch_cff_enabled;
bool req_psr2_sdp_prior_scanline;
u8 sink_sync_latency;
-
-   struct {
-   u8 io_wake_lines;
-   u8 fast_wake_lines;
-
-   /* LNL and beyond */
-   u8 check_entry_lines;
-   u8 silence_period_sym_clocks;
-   u8 lfps_half_cycle_num_of_syms;
-   } alpm_parameters;
-
ktime_t last_entry_attempt;
ktime_t last_exit;
bool sink_not_reliable;
@@ -1840,6 +1829,16 @@ struct intel_dp {
unsigned long last_oui_write;
 
bool colorimetry_support;
+
+   struct {
+   u8 io_wake_lines;
+   u8 fast_wake_lines;
+
+   /* LNL and beyond */
+   u8 check_entry_lines;
+   u8 silence_period_sym_clocks;
+   u8 lfps_half_cycle_num_of_syms;
+   } alpm_parameters;
 };
 
 enum lspcon_vendor {
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index f5b5a9ae..acc45c0f4694 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -814,8 +814,8 @@ static u32 intel_psr2_get_tp_time(struct intel_dp *intel_dp)
 
 static int psr2_block_count_lines(struct intel_dp *intel_dp)
 {
-   return intel_dp->psr.alpm_parameters.io_wake_lines < 9 &&
-   intel_dp->psr.alpm_parameters.fast_wake_lines < 9 ? 8 : 12;
+   return intel_dp->alpm_parameters.io_wake_lines < 9 &&
+   intel_dp->alpm_parameters.fast_wake_lines < 9 ? 8 : 12;
 }
 
 static int psr2_block_count(struct intel_dp *intel_dp)
@@ -852,7 +852,6 @@ static void dg2_activate_panel_replay(struct intel_dp 
*intel_dp)
 static void hsw_activate_psr2(struct intel_dp *intel_dp)
 {
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-   struct intel_psr *psr = _dp->psr;
enum transcoder cpu_transcoder = intel_dp->psr.transcoder;
u32 val = EDP_PSR2_ENABLE;
u32 psr_val = 0;
@@ -894,18 +893,19 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp)
 */
int tmp;
 
-   tmp = map[psr->alpm_parameters.io_wake_lines -
+   tmp = map[intel_dp->alpm_parameters.io_wake_lines -
  TGL_EDP_PSR2_IO_BUFFER_WAKE_MIN_LINES];
val |= TGL_EDP_PSR2_IO_BUFFER_WAKE(tmp + 
TGL_EDP_PSR2_IO_BUFFER_WAKE_MIN_LINES);
 
-   tmp = map[psr->alpm_parameters.fast_wake_lines - 
TGL_EDP_PSR2_FAST_WAKE_MIN_LINES];
+   tmp = map[intel_dp->alpm_parameters.fast_wake_lines -
+ TGL_EDP_PSR2_FAST_WAKE_MIN_LINES];
val |= TGL_EDP_PSR2_FAST_WAKE(tmp + 
TGL_EDP_PSR2_FAST_WAKE_MIN_LINES);
} else if (DISPLAY_VER(dev_priv) >= 12) {
-   val |= 
TGL_EDP_PSR2_IO_BUFFER_WAKE(psr->alpm_parameters.io_wake_lines);
-   val |= 
TGL_EDP_PSR2_FAST_WAKE(psr->alpm_parameters.fast_wake_lines);
+   val |= 
TGL_EDP_PSR2_IO_BUFFER_WAKE(intel_dp->alpm_parameters.io_wake_lines);
+   val |= 
TGL_EDP_PSR2_FAST_WAKE(intel_dp->alpm_parameters.fast_wake_lines);
} else if (DISPLAY_VER(dev_priv) >= 9) {
-   val |= 
EDP_PSR2_IO_BUFFER_WAKE(psr->alpm_parameters.io_wake_lines);
-   val |= EDP_PSR2_FAST_WAKE(psr->alpm_parameters.fast_wake_lines);
+   val |= 
EDP_PSR2_IO_BUFFER_WAKE(intel_dp->alpm_parameters.io_wake_lines);
+   val |= 
EDP_PSR2_FAST_WAKE(intel_dp->alpm_parameters.fast_wake_lines);
}
 
if (intel_dp->psr.req_psr2_sdp_prior_scanline)
@@ -1289,9 +1289,9 @@ static int _lnl_compute_aux_less_alpm_params(struct 
intel_dp *intel_dp,
if (i915->display.params.psr_safest_params)
aux_less_wake_lines = ALPM_CTL_AUX_LESS_WAKE_TIME_MASK;
 
-   intel_dp->psr.alpm_parameters.fast_wake_lines = aux_less_wake_lines;
-   intel_dp->psr.alpm_parameters.silence_period_sym_clocks = 
silence_period;
-   intel_dp->psr.alpm_parameters.lfps_half_cycle_num_of_syms = 
lfps_half_cycle;
+   intel_dp->alpm_parameters.fast_wake_lines = aux_less_wake_lines;
+   intel_dp->alpm_paramet

[PATCH v3 0/6] Link off between frames for edp

2024-04-24 Thread Animesh Manna
Link Off Between Active Frames (LOBF) allows an eDP link to be turned Off and On
durning long VBLANK durations without enabling any of the PSR/PSR2/PR modes of 
operation.

Bspec: 71477

Note: These patches are not tested, sending early for review feedback.

Signed-off-by: Animesh Manna 

Animesh Manna (5):
  drm/i915/alpm: Move alpm parameters from intel_psr
  drm/i915/alpm: Move alpm related code to a new file
  drm/i915/alpm: Add compute config for lobf
  drm/i915/alpm: Enable lobf from source in ALPM_CTL
  drm/i915/alpm: Add debugfs for LOBF

Jouni Högander (1):
  drm/display: Add missing aux less alpm wake related bits

 drivers/gpu/drm/i915/Makefile |   1 +
 drivers/gpu/drm/i915/display/intel_alpm.c | 393 ++
 drivers/gpu/drm/i915/display/intel_alpm.h |  25 ++
 .../drm/i915/display/intel_display_debugfs.c  |   2 +
 .../drm/i915/display/intel_display_types.h|  25 +-
 drivers/gpu/drm/i915/display/intel_dp.c   |   4 +
 drivers/gpu/drm/i915/display/intel_psr.c  | 299 +
 include/drm/display/drm_dp.h  |   5 +-
 8 files changed, 455 insertions(+), 299 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_alpm.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_alpm.h

-- 
2.29.0



[PATCH v2 5/6] drm/i915/alpm: Enable lobf from source in ALPM_CTL

2024-04-12 Thread Animesh Manna
Set the Link Off Between Frames Enable bit in ALPM_CTL register.

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_alpm.c  | 5 +
 drivers/gpu/drm/i915/display/intel_display_types.h | 1 +
 2 files changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c 
b/drivers/gpu/drm/i915/display/intel_alpm.c
index 699f2f051766..ae894c85233c 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.c
+++ b/drivers/gpu/drm/i915/display/intel_alpm.c
@@ -325,6 +325,11 @@ static void lnl_alpm_configure(struct intel_dp *intel_dp)
   
ALPM_CTL_EXTENDED_FAST_WAKE_TIME(intel_dp->alpm_parameters.fast_wake_lines);
}
 
+   if (intel_dp->lobf_supported) {
+   alpm_ctl |= ALPM_CTL_LOBF_ENABLE;
+   intel_dp->lobf_enabled = true;
+   }
+
alpm_ctl |= 
ALPM_CTL_ALPM_ENTRY_CHECK(intel_dp->alpm_parameters.check_entry_lines);
 
intel_de_write(dev_priv, ALPM_CTL(cpu_transcoder), alpm_ctl);
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index 6116c383b543..f61ba582429b 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1884,6 +1884,7 @@ struct intel_dp {
 
/* LOBF flags*/
bool lobf_supported;
+   bool lobf_enabled;
 };
 
 enum lspcon_vendor {
-- 
2.29.0



[PATCH v2 4/6] drm/i915/alpm: Add compute config for lobf

2024-04-12 Thread Animesh Manna
Link Off Between Active Frames, is a new feature for eDP
that allows the panel to go to lower power state after
transmission of data. This is a feature on top of ALPM, AS SDP.
Add compute config during atomic-check phase.

v1: RFC version.
v2: Add separate flag for auxless-alpm. [Jani]

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_alpm.c | 44 +++
 drivers/gpu/drm/i915/display/intel_alpm.h |  5 +++
 .../drm/i915/display/intel_display_types.h|  4 ++
 drivers/gpu/drm/i915/display/intel_dp.c   |  5 +++
 4 files changed, 58 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c 
b/drivers/gpu/drm/i915/display/intel_alpm.c
index 13bac3e8c8fa..699f2f051766 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.c
+++ b/drivers/gpu/drm/i915/display/intel_alpm.c
@@ -11,6 +11,16 @@
 #include "intel_dp_aux.h"
 #include "intel_psr_regs.h"
 
+bool intel_dp_get_aux_less_alpm_status(struct intel_dp *intel_dp)
+{
+   u8 alpm_caps = 0;
+
+   if (drm_dp_dpcd_readb(_dp->aux, DP_RECEIVER_ALPM_CAP,
+ _caps) != 1)
+   return false;
+   return alpm_caps & DP_ALPM_AUX_LESS_CAP;
+}
+
 /*
  * See Bspec: 71632 for the table
  *
@@ -242,6 +252,40 @@ bool intel_alpm_compute_params(struct intel_dp *intel_dp,
return true;
 }
 
+void intel_alpm_compute_lobf_config(struct intel_dp *intel_dp,
+   struct intel_crtc_state *crtc_state,
+   struct drm_connector_state *conn_state)
+{
+   struct drm_display_mode *adjusted_mode = _state->hw.adjusted_mode;
+   int waketime_in_lines, first_sdp_position;
+   int context_latency, guardband;
+
+   intel_dp->lobf_supported = false;
+
+   if (!intel_dp_is_edp(intel_dp))
+   return;
+
+   if (!intel_dp_as_sdp_supported(intel_dp))
+   return;
+
+   if (crtc_state->has_psr2 || crtc_state->has_panel_replay)
+   return;
+
+   if (intel_alpm_compute_params(intel_dp, crtc_state)) {
+   context_latency = adjusted_mode->crtc_vblank_start - 
adjusted_mode->crtc_vdisplay;
+   guardband = adjusted_mode->crtc_vtotal -
+   adjusted_mode->crtc_vdisplay - context_latency;
+   first_sdp_position = adjusted_mode->crtc_vtotal - 
adjusted_mode->crtc_vsync_start;
+   if (intel_dp->alpm_parameters.auxless_alpm_supported)
+   waketime_in_lines = 
intel_dp->alpm_parameters.io_wake_lines;
+   else
+   waketime_in_lines = 
intel_dp->alpm_parameters.fast_wake_lines;
+
+   if ((context_latency + guardband) > (first_sdp_position + 
waketime_in_lines))
+   intel_dp->lobf_supported = true;
+   }
+}
+
 static void lnl_alpm_configure(struct intel_dp *intel_dp)
 {
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
diff --git a/drivers/gpu/drm/i915/display/intel_alpm.h 
b/drivers/gpu/drm/i915/display/intel_alpm.h
index c45d078e5a6b..c341d2c2b7f7 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.h
+++ b/drivers/gpu/drm/i915/display/intel_alpm.h
@@ -10,9 +10,14 @@
 
 struct intel_dp;
 struct intel_crtc_state;
+struct drm_connector_state;
 
+bool intel_dp_get_aux_less_alpm_status(struct intel_dp *intel_dp);
 bool intel_alpm_compute_params(struct intel_dp *intel_dp,
   struct intel_crtc_state *crtc_state);
+void intel_alpm_compute_lobf_config(struct intel_dp *intel_dp,
+   struct intel_crtc_state *crtc_state,
+   struct drm_connector_state *conn_state);
 void intel_alpm_configure(struct intel_dp *intel_dp);
 
 #endif
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index 73197f014510..6116c383b543 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1876,10 +1876,14 @@ struct intel_dp {
u8 fast_wake_lines;
 
/* LNL and beyond */
+   bool auxless_alpm_supported;
u8 check_entry_lines;
u8 silence_period_sym_clocks;
u8 lfps_half_cycle_num_of_syms;
} alpm_parameters;
+
+   /* LOBF flags*/
+   bool lobf_supported;
 };
 
 enum lspcon_vendor {
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 163da48bc406..12ec796568d9 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -48,6 +48,7 @@
 #include "i915_drv.h"
 #include "i915_irq.h"
 #include "i915_reg.h"
+#include "intel_alpm.h"
 #include "intel_atomic.h"
 #include "intel_audio.h"
 #include "int

[PATCH v2 3/6] drm/display: Add missing aux less alpm wake related bits

2024-04-12 Thread Animesh Manna
From: Jouni Högander 

eDP1.5 adds some more bits into DP_RECEIVER_ALPM_CAP and
DP_RECEIVER_ALPM_CONFIG registers. Add definitions for these.

Signed-off-by: Jouni Högander 
---
 include/drm/display/drm_dp.h | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/include/drm/display/drm_dp.h b/include/drm/display/drm_dp.h
index 0b032faa8cf2..ad0cb0a1de87 100644
--- a/include/drm/display/drm_dp.h
+++ b/include/drm/display/drm_dp.h
@@ -232,6 +232,8 @@
 
 #define DP_RECEIVER_ALPM_CAP   0x02e   /* eDP 1.4 */
 # define DP_ALPM_CAP   (1 << 0)
+# define DP_ALPM_PM_STATE_2A_SUPPORT   (1 << 1) /* eDP 1.5 */
+# define DP_ALPM_AUX_LESS_CAP  (1 << 2) /* eDP 1.5 */
 
 #define DP_SINK_DEVICE_AUX_FRAME_SYNC_CAP   0x02f   /* eDP 1.4 */
 # define DP_AUX_FRAME_SYNC_CAP (1 << 0)
@@ -677,7 +679,8 @@
 
 #define DP_RECEIVER_ALPM_CONFIG0x116   /* eDP 1.4 */
 # define DP_ALPM_ENABLE(1 << 0)
-# define DP_ALPM_LOCK_ERROR_IRQ_HPD_ENABLE  (1 << 1)
+# define DP_ALPM_LOCK_ERROR_IRQ_HPD_ENABLE  (1 << 1) /* eDP 1.5 */
+# define DP_ALPM_MODE_AUX_LESS (1 << 2) /* eDP 1.5 */
 
 #define DP_SINK_DEVICE_AUX_FRAME_SYNC_CONF  0x117   /* eDP 1.4 */
 # define DP_AUX_FRAME_SYNC_ENABLE  (1 << 0)
-- 
2.29.0



[PATCH v2 6/6] drm/i915/alpm: Add debugfs for LOBF

2024-04-12 Thread Animesh Manna
For validation purpose add debugfs for LOBF.

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_alpm.c | 47 +++
 drivers/gpu/drm/i915/display/intel_alpm.h |  2 +
 .../drm/i915/display/intel_display_debugfs.c  |  2 +
 3 files changed, 51 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c 
b/drivers/gpu/drm/i915/display/intel_alpm.c
index ae894c85233c..21dfc06952d7 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.c
+++ b/drivers/gpu/drm/i915/display/intel_alpm.c
@@ -339,3 +339,50 @@ void intel_alpm_configure(struct intel_dp *intel_dp)
 {
lnl_alpm_configure(intel_dp);
 }
+
+static int i915_edp_lobf_support_show(struct seq_file *m, void *data)
+{
+   struct intel_connector *connector = m->private;
+   struct intel_dp *intel_dp = intel_attached_dp(connector);
+
+   seq_printf(m, "LOBF support: = %s",
+  str_yes_no(intel_dp->lobf_supported));
+
+   return 0;
+}
+
+DEFINE_SHOW_ATTRIBUTE(i915_edp_lobf_support);
+
+static int i915_edp_lobf_status_show(struct seq_file *m, void *data)
+{
+   struct intel_connector *connector = m->private;
+   struct intel_dp *intel_dp = intel_attached_dp(connector);
+   const char *status;
+
+   if (intel_dp->lobf_enabled)
+   status = "enabled";
+   else
+   status = "disabled";
+
+   seq_printf(m, "LOBF: %s\n", status);
+
+   return 0;
+}
+
+DEFINE_SHOW_ATTRIBUTE(i915_edp_lobf_status);
+
+void intel_alpm_lobf_debugfs_add(struct intel_connector *connector)
+{
+   struct drm_i915_private *i915 = to_i915(connector->base.dev);
+   struct dentry *root = connector->base.debugfs_entry;
+
+   if (DISPLAY_VER(i915) >= 20 &&
+   connector->base.connector_type != DRM_MODE_CONNECTOR_eDP)
+   return;
+
+   debugfs_create_file("i915_edp_lobf_supported", 0444, root,
+   connector, _edp_lobf_support_fops);
+
+   debugfs_create_file("i915_edp_lobf_status", 0444, root,
+   connector, _edp_lobf_status_fops);
+}
diff --git a/drivers/gpu/drm/i915/display/intel_alpm.h 
b/drivers/gpu/drm/i915/display/intel_alpm.h
index c341d2c2b7f7..66e81ed8b2fb 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.h
+++ b/drivers/gpu/drm/i915/display/intel_alpm.h
@@ -11,6 +11,7 @@
 struct intel_dp;
 struct intel_crtc_state;
 struct drm_connector_state;
+struct intel_connector;
 
 bool intel_dp_get_aux_less_alpm_status(struct intel_dp *intel_dp);
 bool intel_alpm_compute_params(struct intel_dp *intel_dp,
@@ -19,5 +20,6 @@ void intel_alpm_compute_lobf_config(struct intel_dp *intel_dp,
struct intel_crtc_state *crtc_state,
struct drm_connector_state *conn_state);
 void intel_alpm_configure(struct intel_dp *intel_dp);
+void intel_alpm_lobf_debugfs_add(struct intel_connector *connector);
 
 #endif
diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c 
b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
index 0feffe8d4e45..ba1530149836 100644
--- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
+++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
@@ -13,6 +13,7 @@
 #include "i915_debugfs.h"
 #include "i915_irq.h"
 #include "i915_reg.h"
+#include "intel_alpm.h"
 #include "intel_crtc.h"
 #include "intel_de.h"
 #include "intel_crtc_state_dump.h"
@@ -1542,6 +1543,7 @@ void intel_connector_debugfs_add(struct intel_connector 
*connector)
intel_drrs_connector_debugfs_add(connector);
intel_pps_connector_debugfs_add(connector);
intel_psr_connector_debugfs_add(connector);
+   intel_alpm_lobf_debugfs_add(connector);
 
if (connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
connector_type == DRM_MODE_CONNECTOR_HDMIA ||
-- 
2.29.0



[PATCH v2 2/6] drm/i915/alpm: Move alpm related code to a new file

2024-04-12 Thread Animesh Manna
Move ALPM feature related code as it will be used for
non-psr panel also thorugh LOBF feature.

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/Makefile |   1 +
 drivers/gpu/drm/i915/display/intel_alpm.c | 292 ++
 drivers/gpu/drm/i915/display/intel_alpm.h |  18 ++
 drivers/gpu/drm/i915/display/intel_psr.c  | 280 +
 4 files changed, 314 insertions(+), 277 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_alpm.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_alpm.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index af9e871daf1d..c12b7bd98320 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -246,6 +246,7 @@ i915-y += \
display/intel_atomic.o \
display/intel_atomic_plane.o \
display/intel_audio.o \
+   display/intel_alpm.o \
display/intel_bios.o \
display/intel_bw.o \
display/intel_cdclk.o \
diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c 
b/drivers/gpu/drm/i915/display/intel_alpm.c
new file mode 100644
index ..13bac3e8c8fa
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_alpm.c
@@ -0,0 +1,292 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2024, Intel Corporation.
+ */
+
+#include "intel_alpm.h"
+#include "intel_crtc.h"
+#include "intel_de.h"
+#include "intel_display_types.h"
+#include "intel_dp.h"
+#include "intel_dp_aux.h"
+#include "intel_psr_regs.h"
+
+/*
+ * See Bspec: 71632 for the table
+ *
+ * Silence_period = tSilence,Min + ((tSilence,Max - tSilence,Min) / 2)
+ *
+ * Half cycle duration:
+ *
+ * Link rates 1.62 - 4.32 and tLFPS_Cycle = 70 ns
+ * FLOOR( (Link Rate * tLFPS_Cycle) / (2 * 10) )
+ *
+ * Link rates 5.4 - 8.1
+ * PORT_ALPM_LFPS_CTL[ LFPS Cycle Count ] = 10
+ * LFPS Period chosen is the mid-point of the min:max values from the table
+ * FLOOR( LFPS Period in Symbol clocks /
+ * (2 * PORT_ALPM_LFPS_CTL[ LFPS Cycle Count ]) )
+ */
+static bool _lnl_get_silence_period_and_lfps_half_cycle(int link_rate,
+   int *silence_period,
+   int *lfps_half_cycle)
+{
+   switch (link_rate) {
+   case 162000:
+   *silence_period = 20;
+   *lfps_half_cycle = 5;
+   break;
+   case 216000:
+   *silence_period = 27;
+   *lfps_half_cycle = 7;
+   break;
+   case 243000:
+   *silence_period = 31;
+   *lfps_half_cycle = 8;
+   break;
+   case 27:
+   *silence_period = 34;
+   *lfps_half_cycle = 9;
+   break;
+   case 324000:
+   *silence_period = 41;
+   *lfps_half_cycle = 11;
+   break;
+   case 432000:
+   *silence_period = 56;
+   *lfps_half_cycle = 15;
+   break;
+   case 54:
+   *silence_period = 69;
+   *lfps_half_cycle = 12;
+   break;
+   case 648000:
+   *silence_period = 84;
+   *lfps_half_cycle = 15;
+   break;
+   case 675000:
+   *silence_period = 87;
+   *lfps_half_cycle = 15;
+   break;
+   case 81:
+   *silence_period = 104;
+   *lfps_half_cycle = 19;
+   break;
+   default:
+   *silence_period = *lfps_half_cycle = -1;
+   return false;
+   }
+   return true;
+}
+
+/*
+ * AUX-Less Wake Time = CEILING( ((PHY P2 to P0) + tLFPS_Period, Max+
+ * tSilence, Max+ tPHY Establishment + tCDS) / tline)
+ * For the "PHY P2 to P0" latency see the PHY Power Control page
+ * (PHY P2 to P0) : https://gfxspecs.intel.com/Predator/Home/Index/68965
+ * : 12 us
+ * The tLFPS_Period, Max term is 800ns
+ * The tSilence, Max term is 180ns
+ * The tPHY Establishment (a.k.a. t1) term is 50us
+ * The tCDS term is 1 or 2 times t2
+ * t2 = Number ML_PHY_LOCK * tML_PHY_LOCK
+ * Number ML_PHY_LOCK = ( 7 + CEILING( 6.5us / tML_PHY_LOCK ) + 1)
+ * Rounding up the 6.5us padding to the next ML_PHY_LOCK boundary and
+ * adding the "+ 1" term ensures all ML_PHY_LOCK sequences that start
+ * within the CDS period complete within the CDS period regardless of
+ * entry into the period
+ * tML_PHY_LOCK = TPS4 Length * ( 10 / (Link Rate in MHz) )
+ * TPS4 Length = 252 Symbols
+ */
+static int _lnl_compute_aux_less_wake_time(int port_clock)
+{
+   int tphy2_p2_to_p0 = 12 * 1000;
+   int tlfps_period_max = 800;
+   int tsilence_max = 180;
+   int t1 = 50 * 1000;
+   int tps4 = 252;
+   int tml_phy_lock = 1000 * 1000 * tps4 * 10 / port_clock;
+   int num_ml_phy_lock = 7 + DIV_ROUND_UP(6500, tml_phy_lock) + 1;
+   int t2 = num_ml_phy_lo

[PATCH v2 1/6] drm/i915/alpm: Move alpm parameters from intel_psr

2024-04-12 Thread Animesh Manna
ALPM can be enabled for non psr panel and currenly aplm-params are
encapsulated under intel_psr struct, so moving out to intel_dp struct.

Signed-off-by: Animesh Manna 
---
 .../drm/i915/display/intel_display_types.h| 21 +
 drivers/gpu/drm/i915/display/intel_psr.c  | 43 +--
 2 files changed, 31 insertions(+), 33 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index 0f4bd5710796..73197f014510 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1741,17 +1741,6 @@ struct intel_psr {
bool psr2_sel_fetch_cff_enabled;
bool req_psr2_sdp_prior_scanline;
u8 sink_sync_latency;
-
-   struct {
-   u8 io_wake_lines;
-   u8 fast_wake_lines;
-
-   /* LNL and beyond */
-   u8 check_entry_lines;
-   u8 silence_period_sym_clocks;
-   u8 lfps_half_cycle_num_of_syms;
-   } alpm_parameters;
-
ktime_t last_entry_attempt;
ktime_t last_exit;
bool sink_not_reliable;
@@ -1881,6 +1870,16 @@ struct intel_dp {
unsigned long last_oui_write;
 
bool colorimetry_support;
+
+   struct {
+   u8 io_wake_lines;
+   u8 fast_wake_lines;
+
+   /* LNL and beyond */
+   u8 check_entry_lines;
+   u8 silence_period_sym_clocks;
+   u8 lfps_half_cycle_num_of_syms;
+   } alpm_parameters;
 };
 
 enum lspcon_vendor {
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index f5b5a9ae..acc45c0f4694 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -814,8 +814,8 @@ static u32 intel_psr2_get_tp_time(struct intel_dp *intel_dp)
 
 static int psr2_block_count_lines(struct intel_dp *intel_dp)
 {
-   return intel_dp->psr.alpm_parameters.io_wake_lines < 9 &&
-   intel_dp->psr.alpm_parameters.fast_wake_lines < 9 ? 8 : 12;
+   return intel_dp->alpm_parameters.io_wake_lines < 9 &&
+   intel_dp->alpm_parameters.fast_wake_lines < 9 ? 8 : 12;
 }
 
 static int psr2_block_count(struct intel_dp *intel_dp)
@@ -852,7 +852,6 @@ static void dg2_activate_panel_replay(struct intel_dp 
*intel_dp)
 static void hsw_activate_psr2(struct intel_dp *intel_dp)
 {
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-   struct intel_psr *psr = _dp->psr;
enum transcoder cpu_transcoder = intel_dp->psr.transcoder;
u32 val = EDP_PSR2_ENABLE;
u32 psr_val = 0;
@@ -894,18 +893,19 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp)
 */
int tmp;
 
-   tmp = map[psr->alpm_parameters.io_wake_lines -
+   tmp = map[intel_dp->alpm_parameters.io_wake_lines -
  TGL_EDP_PSR2_IO_BUFFER_WAKE_MIN_LINES];
val |= TGL_EDP_PSR2_IO_BUFFER_WAKE(tmp + 
TGL_EDP_PSR2_IO_BUFFER_WAKE_MIN_LINES);
 
-   tmp = map[psr->alpm_parameters.fast_wake_lines - 
TGL_EDP_PSR2_FAST_WAKE_MIN_LINES];
+   tmp = map[intel_dp->alpm_parameters.fast_wake_lines -
+ TGL_EDP_PSR2_FAST_WAKE_MIN_LINES];
val |= TGL_EDP_PSR2_FAST_WAKE(tmp + 
TGL_EDP_PSR2_FAST_WAKE_MIN_LINES);
} else if (DISPLAY_VER(dev_priv) >= 12) {
-   val |= 
TGL_EDP_PSR2_IO_BUFFER_WAKE(psr->alpm_parameters.io_wake_lines);
-   val |= 
TGL_EDP_PSR2_FAST_WAKE(psr->alpm_parameters.fast_wake_lines);
+   val |= 
TGL_EDP_PSR2_IO_BUFFER_WAKE(intel_dp->alpm_parameters.io_wake_lines);
+   val |= 
TGL_EDP_PSR2_FAST_WAKE(intel_dp->alpm_parameters.fast_wake_lines);
} else if (DISPLAY_VER(dev_priv) >= 9) {
-   val |= 
EDP_PSR2_IO_BUFFER_WAKE(psr->alpm_parameters.io_wake_lines);
-   val |= EDP_PSR2_FAST_WAKE(psr->alpm_parameters.fast_wake_lines);
+   val |= 
EDP_PSR2_IO_BUFFER_WAKE(intel_dp->alpm_parameters.io_wake_lines);
+   val |= 
EDP_PSR2_FAST_WAKE(intel_dp->alpm_parameters.fast_wake_lines);
}
 
if (intel_dp->psr.req_psr2_sdp_prior_scanline)
@@ -1289,9 +1289,9 @@ static int _lnl_compute_aux_less_alpm_params(struct 
intel_dp *intel_dp,
if (i915->display.params.psr_safest_params)
aux_less_wake_lines = ALPM_CTL_AUX_LESS_WAKE_TIME_MASK;
 
-   intel_dp->psr.alpm_parameters.fast_wake_lines = aux_less_wake_lines;
-   intel_dp->psr.alpm_parameters.silence_period_sym_clocks = 
silence_period;
-   intel_dp->psr.alpm_parameters.lfps_half_cycle_num_of_syms = 
lfps_half_cycle;
+   intel_dp->alpm_parameters.fast_wake_lines = aux_less_wake_lines;
+   intel_dp->alpm_paramet

[PATCH v2 0/6] Link off between frames for edp

2024-04-12 Thread Animesh Manna
Link Off Between Active Frames (LOBF) allows an eDP link to be turned Off and On
durning long VBLANK durations without enabling any of the PSR/PSR2/PR modes of 
operation.

Bspec: 71477

Note: These patches are not tested, sending early for review feedback.

Signed-off-by: Animesh Manna 

Animesh Manna (5):
  drm/i915/alpm: Move alpm parameters from intel_psr
  drm/i915/alpm: Move alpm related code to a new file
  drm/i915/alpm: Add compute config for lobf
  drm/i915/alpm: Enable lobf from source in ALPM_CTL
  drm/i915/alpm: Add debugfs for LOBF

Jouni Högander (1):
  drm/display: Add missing aux less alpm wake related bits

 drivers/gpu/drm/i915/Makefile |   1 +
 drivers/gpu/drm/i915/display/intel_alpm.c | 388 ++
 drivers/gpu/drm/i915/display/intel_alpm.h |  25 ++
 .../drm/i915/display/intel_display_debugfs.c  |   2 +
 .../drm/i915/display/intel_display_types.h|  26 +-
 drivers/gpu/drm/i915/display/intel_dp.c   |   5 +
 drivers/gpu/drm/i915/display/intel_psr.c  | 299 +-
 include/drm/display/drm_dp.h  |   5 +-
 8 files changed, 452 insertions(+), 299 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_alpm.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_alpm.h

-- 
2.29.0



[PATCH v4] drm/i915/panelreplay: Panel replay workaround with VRR

2024-03-27 Thread Animesh Manna
Panel Replay VSC SDP not getting sent when VRR is enabled
and W1 and W2 are 0. So Program Set Context Latency in
TRANS_SET_CONTEXT_LATENCY register to at least a value of 1.

HSD: 14015406119

v1: Initial version.
v2: Update timings stored in adjusted_mode struct. [Ville]
v3: Add WA in compute_config(). [Ville]
v4:
- Add DISPLAY_VER() check and improve code comment. [Rodrigo]
- Introduce centralized intel_crtc_vblank_delay(). [Ville]

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_display.c | 17 +
 drivers/gpu/drm/i915/display/intel_display.h |  1 +
 drivers/gpu/drm/i915/display/intel_psr.c |  4 
 3 files changed, 22 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 00ac65a14029..7f5c42a14196 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -3840,6 +3840,23 @@ bool intel_crtc_get_pipe_config(struct intel_crtc_state 
*crtc_state)
return true;
 }
 
+void intel_crtc_vblank_delay(struct intel_crtc_state *crtc_state)
+{
+   struct drm_display_mode *adjusted_mode = _state->hw.adjusted_mode;
+
+   /*
+* wa_14015401596 for display versions >= 13.
+* Program Set Context Latency in TRANS_SET_CONTEXT_LATENCY register
+* to at least a value of 1 when Panel Replay is enabled with VRR.
+* Value for TRANS_SET_CONTEXT_LATENCY is calculated by substracting
+* crtc_vdisplay from crtc_vblank_start, so incrementing 
crtc_vblank_start
+* by 1 if both are equal.
+*/
+   if (crtc_state->vrr.enable && crtc_state->has_panel_replay &&
+   adjusted_mode->crtc_vblank_start == adjusted_mode->crtc_vdisplay)
+   adjusted_mode->crtc_vblank_start += 1;
+}
+
 int intel_dotclock_calculate(int link_freq,
 const struct intel_link_m_n *m_n)
 {
diff --git a/drivers/gpu/drm/i915/display/intel_display.h 
b/drivers/gpu/drm/i915/display/intel_display.h
index f4a0773f0fca..23315eced41e 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -413,6 +413,7 @@ bool intel_crtc_is_bigjoiner_master(const struct 
intel_crtc_state *crtc_state);
 u8 intel_crtc_bigjoiner_slave_pipes(const struct intel_crtc_state *crtc_state);
 struct intel_crtc *intel_master_crtc(const struct intel_crtc_state 
*crtc_state);
 bool intel_crtc_get_pipe_config(struct intel_crtc_state *crtc_state);
+void intel_crtc_vblank_delay(struct intel_crtc_state *crtc_state);
 bool intel_pipe_config_compare(const struct intel_crtc_state *current_config,
   const struct intel_crtc_state *pipe_config,
   bool fastset);
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index 72cadad09db5..fccef5434e9c 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -1430,6 +1430,10 @@ void intel_psr_compute_config(struct intel_dp *intel_dp,
if (!(crtc_state->has_panel_replay || crtc_state->has_psr))
return;
 
+   /* wa_14015401596: display versions 13, 14 */
+   if (DISPLAY_VER(dev_priv) >= 13)
+   intel_crtc_vblank_delay(crtc_state);
+
crtc_state->has_psr2 = intel_psr2_config_valid(intel_dp, crtc_state);
 }
 
-- 
2.29.0



[RFC 3/3] drm/i915/alpm: Enable lobf from source in ALPM_CTL

2024-03-03 Thread Animesh Manna
Set the Link Off Between Frames Enable bit in ALPM_CTL register.

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_display_types.h | 1 +
 drivers/gpu/drm/i915/display/intel_psr.c   | 5 +
 2 files changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index 4d2161eeb686..c8e7a65df45d 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1854,6 +1854,7 @@ struct intel_dp {
 
/* LOBF flags*/
bool lobf_supported;
+   bool lobf_enabled;
 };
 
 enum lspcon_vendor {
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index c08bffc2921a..a9f8f2982b50 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -1770,6 +1770,11 @@ static void lnl_alpm_configure(struct intel_dp *intel_dp)

ALPM_CTL_EXTENDED_FAST_WAKE_TIME(intel_dp->alpm_parameters.fast_wake_lines);
}
 
+   if (intel_dp->lobf_supported) {
+   alpm_ctl |= ALPM_CTL_LOBF_ENABLE;
+   intel_dp->lobf_enabled = true;
+   }
+
alpm_ctl |= 
ALPM_CTL_ALPM_ENTRY_CHECK(intel_dp->alpm_parameters.check_entry_lines);
 
intel_de_write(dev_priv, ALPM_CTL(cpu_transcoder), alpm_ctl);
-- 
2.29.0



[RFC 0/3] Link off between frames for edp

2024-03-03 Thread Animesh Manna
Link Off Between Active Frames (LOBF) allows an eDP link to be turned Off and On
durning long VBLANK durations without enabling any of the PSR/PSR2/PR modes of 
operation.

Bspec: 71477

Note: This is a feature has dependency on ALPM, AS SDP. So the below changes
are done on top of the following patch series where review is ongoing. So
compilation issue expected from CI.
https://patchwork.freedesktop.org/series/129938/
https://patchwork.freedesktop.org/series/126829/

These patches are not tested, sending early for review feedback

Signed-off-by: Animesh Manna 

Animesh Manna (3):
  drm/i915/alpm: Move alpm parameters from intel_psr
  drm/i915/alpm: Add compute config for lobf
  drm/i915/alpm: Enable lobf from source in ALPM_CTL

 .../drm/i915/display/intel_display_types.h| 27 +++---
 drivers/gpu/drm/i915/display/intel_dp.c   |  1 +
 drivers/gpu/drm/i915/display/intel_psr.c  | 92 ++-
 drivers/gpu/drm/i915/display/intel_psr.h  |  3 +
 4 files changed, 89 insertions(+), 34 deletions(-)

-- 
2.29.0



[RFC 1/3] drm/i915/alpm: Move alpm parameters from intel_psr

2024-03-03 Thread Animesh Manna
ALPM can be enabled for non psr panel and currenly aplm-params are
encapsulated under intel_psr struct, so moving out to intel_dp struct.

Signed-off-by: Animesh Manna 
---
 .../drm/i915/display/intel_display_types.h| 23 +-
 drivers/gpu/drm/i915/display/intel_psr.c  | 42 +--
 2 files changed, 31 insertions(+), 34 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index cc52693a0e58..d473d8dca90a 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1715,18 +1715,6 @@ struct intel_psr {
bool psr2_sel_fetch_cff_enabled;
bool req_psr2_sdp_prior_scanline;
u8 sink_sync_latency;
-
-   struct {
-   u8 io_wake_lines;
-   u8 fast_wake_lines;
-
-   /* LNL and beyond */
-   u8 check_entry_lines;
-   u8 aux_less_wake_lines;
-   u8 silence_period_sym_clocks;
-   u8 lfps_half_cycle_num_of_syms;
-   } alpm_parameters;
-
ktime_t last_entry_attempt;
ktime_t last_exit;
bool sink_not_reliable;
@@ -1852,6 +1840,17 @@ struct intel_dp {
unsigned long last_oui_write;
 
bool colorimetry_support;
+
+   struct {
+   u8 io_wake_lines;
+   u8 fast_wake_lines;
+
+   /* LNL and beyond */
+   u8 check_entry_lines;
+   u8 aux_less_wake_lines;
+   u8 silence_period_sym_clocks;
+   u8 lfps_half_cycle_num_of_syms;
+   } alpm_parameters;
 };
 
 enum lspcon_vendor {
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index ed5f62f89027..4adcddba69c1 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -779,8 +779,8 @@ static u32 intel_psr2_get_tp_time(struct intel_dp *intel_dp)
 
 static int psr2_block_count_lines(struct intel_dp *intel_dp)
 {
-   return intel_dp->psr.alpm_parameters.io_wake_lines < 9 &&
-   intel_dp->psr.alpm_parameters.fast_wake_lines < 9 ? 8 : 12;
+   return intel_dp->alpm_parameters.io_wake_lines < 9 &&
+   intel_dp->alpm_parameters.fast_wake_lines < 9 ? 8 : 12;
 }
 
 static int psr2_block_count(struct intel_dp *intel_dp)
@@ -817,7 +817,6 @@ static void dg2_activate_panel_replay(struct intel_dp 
*intel_dp)
 static void hsw_activate_psr2(struct intel_dp *intel_dp)
 {
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-   struct intel_psr *psr = _dp->psr;
enum transcoder cpu_transcoder = intel_dp->psr.transcoder;
u32 val = EDP_PSR2_ENABLE;
u32 psr_val = 0;
@@ -859,18 +858,18 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp)
 */
int tmp;
 
-   tmp = map[psr->alpm_parameters.io_wake_lines -
+   tmp = map[intel_dp->alpm_parameters.io_wake_lines -
  TGL_EDP_PSR2_IO_BUFFER_WAKE_MIN_LINES];
val |= TGL_EDP_PSR2_IO_BUFFER_WAKE(tmp + 
TGL_EDP_PSR2_IO_BUFFER_WAKE_MIN_LINES);
 
-   tmp = map[psr->alpm_parameters.fast_wake_lines - 
TGL_EDP_PSR2_FAST_WAKE_MIN_LINES];
+   tmp = map[intel_dp->alpm_parameters.fast_wake_lines - 
TGL_EDP_PSR2_FAST_WAKE_MIN_LINES];
val |= TGL_EDP_PSR2_FAST_WAKE(tmp + 
TGL_EDP_PSR2_FAST_WAKE_MIN_LINES);
} else if (DISPLAY_VER(dev_priv) >= 12) {
-   val |= 
TGL_EDP_PSR2_IO_BUFFER_WAKE(psr->alpm_parameters.io_wake_lines);
-   val |= 
TGL_EDP_PSR2_FAST_WAKE(psr->alpm_parameters.fast_wake_lines);
+   val |= 
TGL_EDP_PSR2_IO_BUFFER_WAKE(intel_dp->alpm_parameters.io_wake_lines);
+   val |= 
TGL_EDP_PSR2_FAST_WAKE(intel_dp->alpm_parameters.fast_wake_lines);
} else if (DISPLAY_VER(dev_priv) >= 9) {
-   val |= 
EDP_PSR2_IO_BUFFER_WAKE(psr->alpm_parameters.io_wake_lines);
-   val |= EDP_PSR2_FAST_WAKE(psr->alpm_parameters.fast_wake_lines);
+   val |= 
EDP_PSR2_IO_BUFFER_WAKE(intel_dp->alpm_parameters.io_wake_lines);
+   val |= 
EDP_PSR2_FAST_WAKE(intel_dp->alpm_parameters.fast_wake_lines);
}
 
if (intel_dp->psr.req_psr2_sdp_prior_scanline)
@@ -1253,9 +1252,9 @@ static int _lnl_compute_aux_less_alpm_params(struct 
intel_dp *intel_dp,
if (i915->display.params.psr_safest_params)
aux_less_wake_lines = 63;
 
-   intel_dp->psr.alpm_parameters.aux_less_wake_lines = aux_less_wake_lines;
-   intel_dp->psr.alpm_parameters.silence_period_sym_clocks = 
silence_period;
-   intel_dp->psr.alpm_parameters.lfps_half_cycle_num_of_syms = 
lfps_half_cycle;
+   intel_dp->alpm_parameters.aux_less_wake_lines = aux_less_

[RFC 2/3] drm/i915/alpm: Add compute config for lobf

2024-03-03 Thread Animesh Manna
Link Off Between Active Frames, is a new feature for eDP
that allows the panel to go to lower power state after
transmission of data. This is a feature on top of ALPM, AS SDP.
Add compute config during atomic-check phase.

Signed-off-by: Animesh Manna 
---
 .../drm/i915/display/intel_display_types.h|  3 ++
 drivers/gpu/drm/i915/display/intel_dp.c   |  1 +
 drivers/gpu/drm/i915/display/intel_psr.c  | 45 +++
 drivers/gpu/drm/i915/display/intel_psr.h  |  3 ++
 4 files changed, 52 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index d473d8dca90a..4d2161eeb686 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1851,6 +1851,9 @@ struct intel_dp {
u8 silence_period_sym_clocks;
u8 lfps_half_cycle_num_of_syms;
} alpm_parameters;
+
+   /* LOBF flags*/
+   bool lobf_supported;
 };
 
 enum lspcon_vendor {
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 8304ef912767..e34b70d88b9a 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2979,6 +2979,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
intel_vrr_compute_config(pipe_config, conn_state);
intel_dp_compute_as_sdp(intel_dp, pipe_config, conn_state);
intel_psr_compute_config(intel_dp, pipe_config, conn_state);
+   intel_psr_lobf_compute_config(intel_dp, pipe_config, conn_state);
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, 
conn_state);
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index 4adcddba69c1..c08bffc2921a 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -436,6 +436,16 @@ static bool intel_dp_get_alpm_status(struct intel_dp 
*intel_dp)
return alpm_caps & DP_ALPM_CAP;
 }
 
+static bool intel_dp_get_aux_less_alpm_status(struct intel_dp *intel_dp)
+{
+   u8 alpm_caps = 0;
+
+   if (drm_dp_dpcd_readb(_dp->aux, DP_RECEIVER_ALPM_CAP,
+ _caps) != 1)
+   return false;
+   return alpm_caps & DP_ALPM_AUX_LESS_CAP;
+}
+
 static u8 intel_dp_get_sink_sync_latency(struct intel_dp *intel_dp)
 {
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
@@ -1569,6 +1579,41 @@ void intel_psr_compute_config(struct intel_dp *intel_dp,
crtc_state->has_psr2 = intel_psr2_config_valid(intel_dp, crtc_state);
 }
 
+void intel_psr_lobf_compute_config(struct intel_dp *intel_dp,
+  struct intel_crtc_state *crtc_state,
+  struct drm_connector_state *conn_state)
+{
+   struct drm_display_mode *adjusted_mode = _state->hw.adjusted_mode;
+   int waketime_in_lines, first_sdp_position;
+   int context_latency, guardband;
+   bool auxless_alpm;
+
+   intel_dp->lobf_supported = false;
+
+   if (!intel_dp_is_edp(intel_dp))
+   return;
+
+   if (!intel_dp_as_sdp_supported(intel_dp))
+   return;
+
+   if (CAN_PSR(intel_dp) || CAN_PANEL_REPLAY(intel_dp))
+   return;
+
+   if (_compute_alpm_params(intel_dp, crtc_state)) {
+   context_latency = adjusted_mode->crtc_vblank_start - 
adjusted_mode->crtc_vdisplay;
+   guardband = adjusted_mode->crtc_vtotal - 
adjusted_mode->crtc_vdisplay - context_latency;
+   first_sdp_position = adjusted_mode->crtc_vtotal - 
adjusted_mode->crtc_vsync_start;
+   auxless_alpm = intel_dp_get_aux_less_alpm_status(intel_dp);
+   if (auxless_alpm)
+   waketime_in_lines = 
intel_dp->alpm_parameters.io_wake_lines;
+   else
+   waketime_in_lines = 
intel_dp->alpm_parameters.aux_less_wake_lines;
+
+   if ((context_latency + guardband) > (first_sdp_position + 
waketime_in_lines))
+   intel_dp->lobf_supported = true;
+   }
+}
+
 void intel_psr_get_config(struct intel_encoder *encoder,
  struct intel_crtc_state *pipe_config)
 {
diff --git a/drivers/gpu/drm/i915/display/intel_psr.h 
b/drivers/gpu/drm/i915/display/intel_psr.h
index cde781df84d5..4bb77295288f 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.h
+++ b/drivers/gpu/drm/i915/display/intel_psr.h
@@ -40,6 +40,9 @@ void intel_psr_init(struct intel_dp *intel_dp);
 void intel_psr_compute_config(struct intel_dp *intel_dp,
  struct intel_crtc_state *crtc_state,
  struct drm_connector_state *conn_state);
+

[PATCH v2] drm/i915/panelreplay: Move out psr_init_dpcd() from init_connector()

2024-02-28 Thread Animesh Manna
Move psr_init_dpcd() from init-connector to connector-detect
function. The dpcd probe for checking panel replay capability
for external dp connector is causing delay during boot which can
be optimized by moving dpcd probe to connector specific detect().

v1: Initial version.
v2: Add details in commit description. [Jani]

Suggested-by: Ville Syrjälä 
Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/10284
Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_dp.c  | 3 +++
 drivers/gpu/drm/i915/display/intel_psr.c | 3 ---
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 6ece2c563c7a..b485ec320085 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -5709,6 +5709,9 @@ intel_dp_detect(struct drm_connector *connector,
if (ret == 1)
intel_connector->base.epoch_counter++;
 
+   if (!intel_dp_is_edp(intel_dp))
+   intel_psr_init_dpcd(intel_dp);
+
intel_dp_detect_dsc_caps(intel_dp, intel_connector);
 
intel_dp_configure_mst(intel_dp);
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index 72cadad09db5..6927785fd6ff 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -2883,9 +2883,6 @@ void intel_psr_init(struct intel_dp *intel_dp)
if (!(HAS_PSR(dev_priv) || HAS_DP20(dev_priv)))
return;
 
-   if (!intel_dp_is_edp(intel_dp))
-   intel_psr_init_dpcd(intel_dp);
-
/*
 * HSW spec explicitly says PSR is tied to port A.
 * BDW+ platforms have a instance of PSR registers per transcoder but
-- 
2.29.0



[PATCH] drm/i915/panelreplay: Move out psr_init_dpcd() from init_connector()

2024-02-22 Thread Animesh Manna
Move psr_init_dpcd() from init-connector to connector-detect
function.

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_dp.c  | 3 +++
 drivers/gpu/drm/i915/display/intel_psr.c | 3 ---
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 217196196e50..4553e1f5f1fc 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -5709,6 +5709,9 @@ intel_dp_detect(struct drm_connector *connector,
goto out;
}
 
+   if (!intel_dp_is_edp(intel_dp))
+   intel_psr_init_dpcd(intel_dp);
+
intel_dp_detect_dsc_caps(intel_dp, intel_connector);
 
intel_dp_configure_mst(intel_dp);
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index 72cadad09db5..6927785fd6ff 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -2883,9 +2883,6 @@ void intel_psr_init(struct intel_dp *intel_dp)
if (!(HAS_PSR(dev_priv) || HAS_DP20(dev_priv)))
return;
 
-   if (!intel_dp_is_edp(intel_dp))
-   intel_psr_init_dpcd(intel_dp);
-
/*
 * HSW spec explicitly says PSR is tied to port A.
 * BDW+ platforms have a instance of PSR registers per transcoder but
-- 
2.29.0



[PATCH v3] drm/i915/panelreplay: Panel replay workaround with VRR

2024-02-20 Thread Animesh Manna
Panel Replay VSC SDP not getting sent when VRR is enabled
and W1 and W2 are 0. So Program Set Context Latency in
TRANS_SET_CONTEXT_LATENCY register to at least a value of 1.

HSD: 14015406119

v1: Initial version.
v2: Update timings stored in adjusted_mode struct. [Ville]
v3: Add WA in compute_config(). [Ville]

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 217196196e50..eb0fa513cd0f 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2948,6 +2948,18 @@ intel_dp_compute_config(struct intel_encoder *encoder,
intel_dp_compute_vsc_sdp(intel_dp, pipe_config, conn_state);
intel_dp_compute_hdr_metadata_infoframe_sdp(intel_dp, pipe_config, 
conn_state);
 
+   /*
+* WA: HSD-14015406119
+* Program Set Context Latency in TRANS_SET_CONTEXT_LATENCY register
+* to at least a value of 1 when Panel Replay is enabled with VRR.
+* Value for TRANS_SET_CONTEXT_LATENCY is calculated by substracting
+* crtc_vdisplay from crtc_vblank_start, so incrementing 
crtc_vblank_start
+* by 1 if both are equal.
+*/
+   if (pipe_config->vrr.enable && pipe_config->has_panel_replay &&
+   adjusted_mode->crtc_vblank_start == adjusted_mode->crtc_vdisplay)
+   adjusted_mode->crtc_vblank_start += 1;
+
return 0;
 }
 
-- 
2.29.0



[PATCH v2] drm/i915/panelreplay: Panel replay workaround with VRR

2024-02-09 Thread Animesh Manna
Panel Replay VSC SDP not getting sent when VRR is enabled
and W1 and W2 are 0. So Program Set Context Latency in
TRANS_SET_CONTEXT_LATENCY register to at least a value of 1.

HSD: 14015406119

v1: Initial version.
v2: Update timings stored in adjusted_mode struct. [Ville]

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_vblank.c | 13 +
 1 file changed, 13 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_vblank.c 
b/drivers/gpu/drm/i915/display/intel_vblank.c
index baf7354cb6e2..2e11629e4e9f 100644
--- a/drivers/gpu/drm/i915/display/intel_vblank.c
+++ b/drivers/gpu/drm/i915/display/intel_vblank.c
@@ -552,6 +552,19 @@ void intel_crtc_update_active_timings(const struct 
intel_crtc_state *crtc_state,
adjusted_mode.crtc_vtotal = crtc_state->vrr.vmax;
adjusted_mode.crtc_vblank_end = crtc_state->vrr.vmax;
adjusted_mode.crtc_vblank_start = 
intel_vrr_vmin_vblank_start(crtc_state);
+
+   /*
+* WA: HSD-14015406119
+* Program Set Context Latency in TRANS_SET_CONTEXT_LATENCY 
register
+* to at least a value of 1 when Panel Replay is enabled with 
VRR.
+* Value for TRANS_SET_CONTEXT_LATENCY is calculated by 
substracting
+* crtc_vdisplay from crtc_vblank_start, so incrementing 
crtc_vblank_start
+* by 1 if both are equal.
+*/
+   if (DISPLAY_VER(i915) >= 13 && crtc_state->has_panel_replay &&
+   adjusted_mode.crtc_vblank_start == 
adjusted_mode.crtc_vdisplay)
+   adjusted_mode.crtc_vblank_start += 1;
+
vmax_vblank_start = intel_vrr_vmax_vblank_start(crtc_state);
} else {
mode_flags &= ~I915_MODE_FLAG_VRR;
-- 
2.29.0



[PATCH] drm/i915/panelreplay: Panel replay workaround with VRR

2024-02-07 Thread Animesh Manna
Panel Replay VSC SDP not getting sent when VRR is enabled
and W1 and W2 are 0. So Program Set Context Latency in
TRANS_SET_CONTEXT_LATENCY register to at least a value of 1.

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_display.c | 12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 1b844cac4c58..c1ec78b5b6c5 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -2618,8 +2618,16 @@ static void intel_set_transcoder_timings(const struct 
intel_crtc_state *crtc_sta
 * TRANS_SET_CONTEXT_LATENCY to configure the pipe vblank start.
 */
if (DISPLAY_VER(dev_priv) >= 13) {
-   intel_de_write(dev_priv, 
TRANS_SET_CONTEXT_LATENCY(cpu_transcoder),
-  crtc_vblank_start - crtc_vdisplay);
+   /*
+* WA: Program Set Context Latency in TRANS_SET_CONTEXT_LATENCY 
register
+* to at least a value of 1 when Panel Replay is enabled with 
VRR.
+*/
+   if (crtc_state->vrr.enable &&  crtc_state->has_panel_replay &&
+   (crtc_vblank_start == crtc_vdisplay))
+   intel_de_write(dev_priv, 
TRANS_SET_CONTEXT_LATENCY(cpu_transcoder), 1);
+   else
+   intel_de_write(dev_priv, 
TRANS_SET_CONTEXT_LATENCY(cpu_transcoder),
+  crtc_vblank_start - crtc_vdisplay);
 
/*
 * VBLANK_START not used by hw, just clear it
-- 
2.29.0



[PATCH] drm/i915/lnl: Block pkgC entry for performance improvemnt

2024-01-16 Thread Animesh Manna
For High refresh rates usages, Vblank is required to be really small.
It cannot accommodate PKGC exit delay after framestart. Block PKGC till
next framestart which will be set by software and later will be
cleared by HW at framestart.

Cc: Mitul Golani 
Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_display.c  |  3 +++
 drivers/gpu/drm/i915/display/intel_dmc.c  | 15 +++
 drivers/gpu/drm/i915/display/intel_dmc.h  |  1 +
 drivers/gpu/drm/i915/display/intel_dmc_regs.h |  5 +
 4 files changed, 24 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index c6680ee2127c..928db551c685 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -7421,6 +7421,9 @@ static void intel_atomic_commit_tail(struct 
intel_atomic_state *state)
 
drm_atomic_helper_commit_hw_done(>base);
 
+   if (DISPLAY_VER(dev_priv) >= 20)
+   intel_dmc_block_pkgc(dev_priv);
+
if (state->modeset) {
/* As one of the primary mmio accessors, KMS has a high
 * likelihood of triggering bugs in unclaimed access. After we
diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c 
b/drivers/gpu/drm/i915/display/intel_dmc.c
index 51e0463518fb..2f86fc5f5f32 100644
--- a/drivers/gpu/drm/i915/display/intel_dmc.c
+++ b/drivers/gpu/drm/i915/display/intel_dmc.c
@@ -1247,3 +1247,18 @@ void intel_dmc_debugfs_register(struct drm_i915_private 
*i915)
debugfs_create_file("i915_dmc_info", 0444, minor->debugfs_root,
i915, _dmc_debugfs_status_fops);
 }
+
+void intel_dmc_block_pkgc(struct drm_i915_private *i915)
+{
+   u32 pkgc_ctrl;
+
+   if (HAS_DMC(i915)) {
+   pkgc_ctrl = intel_de_read(i915, DMC_BLOCK_PKGC);
+   pkgc_ctrl |= DMC_BLOCK_PKGC_ENABLE;
+   intel_de_write(i915, DMC_BLOCK_PKGC, pkgc_ctrl);
+   } else {
+   pkgc_ctrl = intel_de_read(i915, DMC_BLOCK_PKGC_SW);
+   pkgc_ctrl |= DMC_BLOCK_PKGC_ENABLE;
+   intel_de_write(i915, DMC_BLOCK_PKGC_SW, pkgc_ctrl);
+   }
+}
diff --git a/drivers/gpu/drm/i915/display/intel_dmc.h 
b/drivers/gpu/drm/i915/display/intel_dmc.h
index fd607afff2ef..6c2fcaea4c0d 100644
--- a/drivers/gpu/drm/i915/display/intel_dmc.h
+++ b/drivers/gpu/drm/i915/display/intel_dmc.h
@@ -24,6 +24,7 @@ bool intel_dmc_has_payload(struct drm_i915_private *i915);
 void intel_dmc_debugfs_register(struct drm_i915_private *i915);
 void intel_dmc_print_error_state(struct drm_i915_error_state_buf *m,
 struct drm_i915_private *i915);
+void intel_dmc_block_pkgc(struct drm_i915_private *i915);
 
 void assert_dmc_loaded(struct drm_i915_private *i915);
 
diff --git a/drivers/gpu/drm/i915/display/intel_dmc_regs.h 
b/drivers/gpu/drm/i915/display/intel_dmc_regs.h
index cf10094acae3..2d52fe7f3450 100644
--- a/drivers/gpu/drm/i915/display/intel_dmc_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_dmc_regs.h
@@ -80,6 +80,11 @@
 #define ADLP_PIPE_MMIO_START   0x5F000
 #define ADLP_PIPE_MMIO_END 0x5
 
+#define DMC_BLOCK_PKGC _MMIO(0x8F1C0)
+#define DMC_BLOCK_PKGC_SW  _MMIO(0x8F1C4)
+
+#define DMC_BLOCK_PKGC_ENABLE  REG_BIT(31)
+
 #define TGL_PIPE_MMIO_START(dmc_id)_PICK_EVEN(((dmc_id) - 1), 
_TGL_PIPEA_MMIO_START,\
  _TGL_PIPEB_MMIO_START)
 
-- 
2.29.0



[Intel-gfx] [PATCH v6] drm/i915/dsb: DSB code refactoring

2023-11-09 Thread Animesh Manna
Refactor DSB implementation to be compatible with Xe driver.

v1: RFC version.
v2: Make intel_dsb structure opaque from external usage. [Jani]
v3: Rebased on latest.
v4:
- Add boundary check in dsb_buffer_memset(). [Luca]
- Use size_t instead of u32. [Luca]
v5: WARN_ON() added for out of boudary case with some optimization. [Luca]

Cc: Jani Nikula 
Reviewed-by: Luca Coelho 
Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/Makefile |  1 +
 drivers/gpu/drm/i915/display/intel_dsb.c  | 98 +++
 .../gpu/drm/i915/display/intel_dsb_buffer.c   | 82 
 .../gpu/drm/i915/display/intel_dsb_buffer.h   | 29 ++
 4 files changed, 148 insertions(+), 62 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_dsb_buffer.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_dsb_buffer.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 239da40a401f..7e5d6a39d450 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -277,6 +277,7 @@ i915-y += \
display/intel_dpt.o \
display/intel_drrs.o \
display/intel_dsb.o \
+   display/intel_dsb_buffer.o \
display/intel_fb.o \
display/intel_fb_pin.o \
display/intel_fbc.o \
diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c 
b/drivers/gpu/drm/i915/display/intel_dsb.c
index 78b6fe24dcd8..9598d50f68f2 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.c
+++ b/drivers/gpu/drm/i915/display/intel_dsb.c
@@ -4,9 +4,6 @@
  *
  */
 
-#include "gem/i915_gem_internal.h"
-#include "gem/i915_gem_lmem.h"
-
 #include "i915_drv.h"
 #include "i915_irq.h"
 #include "i915_reg.h"
@@ -14,12 +11,13 @@
 #include "intel_de.h"
 #include "intel_display_types.h"
 #include "intel_dsb.h"
+#include "intel_dsb_buffer.h"
 #include "intel_dsb_regs.h"
 #include "intel_vblank.h"
 #include "intel_vrr.h"
 #include "skl_watermark.h"
 
-struct i915_vma;
+#define CACHELINE_BYTES 64
 
 enum dsb_id {
INVALID_DSB = -1,
@@ -32,8 +30,7 @@ enum dsb_id {
 struct intel_dsb {
enum dsb_id id;
 
-   u32 *cmd_buf;
-   struct i915_vma *vma;
+   struct intel_dsb_buffer dsb_buf;
struct intel_crtc *crtc;
 
/*
@@ -109,15 +106,17 @@ static void intel_dsb_dump(struct intel_dsb *dsb)
 {
struct intel_crtc *crtc = dsb->crtc;
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
-   const u32 *buf = dsb->cmd_buf;
int i;
 
drm_dbg_kms(>drm, "[CRTC:%d:%s] DSB %d commands {\n",
crtc->base.base.id, crtc->base.name, dsb->id);
for (i = 0; i < ALIGN(dsb->free_pos, 64 / 4); i += 4)
drm_dbg_kms(>drm,
-   " 0x%08x: 0x%08x 0x%08x 0x%08x 0x%08x\n",
-   i * 4, buf[i], buf[i+1], buf[i+2], buf[i+3]);
+   " 0x%08x: 0x%08x 0x%08x 0x%08x 0x%08x\n", i * 4,
+   intel_dsb_buffer_read(>dsb_buf, i),
+   intel_dsb_buffer_read(>dsb_buf, i + 1),
+   intel_dsb_buffer_read(>dsb_buf, i + 2),
+   intel_dsb_buffer_read(>dsb_buf, i + 3));
drm_dbg_kms(>drm, "}\n");
 }
 
@@ -129,8 +128,6 @@ static bool is_dsb_busy(struct drm_i915_private *i915, enum 
pipe pipe,
 
 static void intel_dsb_emit(struct intel_dsb *dsb, u32 ldw, u32 udw)
 {
-   u32 *buf = dsb->cmd_buf;
-
if (!assert_dsb_has_room(dsb))
return;
 
@@ -139,14 +136,13 @@ static void intel_dsb_emit(struct intel_dsb *dsb, u32 
ldw, u32 udw)
 
dsb->ins_start_offset = dsb->free_pos;
 
-   buf[dsb->free_pos++] = ldw;
-   buf[dsb->free_pos++] = udw;
+   intel_dsb_buffer_write(>dsb_buf, dsb->free_pos++, ldw);
+   intel_dsb_buffer_write(>dsb_buf, dsb->free_pos++, udw);
 }
 
 static bool intel_dsb_prev_ins_is_write(struct intel_dsb *dsb,
u32 opcode, i915_reg_t reg)
 {
-   const u32 *buf = dsb->cmd_buf;
u32 prev_opcode, prev_reg;
 
/*
@@ -157,8 +153,10 @@ static bool intel_dsb_prev_ins_is_write(struct intel_dsb 
*dsb,
if (dsb->free_pos == 0)
return false;
 
-   prev_opcode = buf[dsb->ins_start_offset + 1] & ~DSB_REG_VALUE_MASK;
-   prev_reg = buf[dsb->ins_start_offset + 1] & DSB_REG_VALUE_MASK;
+   prev_opcode = intel_dsb_buffer_read(>dsb_buf,
+   dsb->ins_start_offset + 1) & 
~DSB_REG_VALUE_MASK;
+   prev_reg =  intel_dsb_buffer_read(>dsb_buf,
+ dsb->ins_start_offset + 1) & 
DSB_REG_VALUE_MASK;
 
return prev_opc

[Intel-gfx] [PATCH v9 6/6] drm/i915/panelreplay: Debugfs support for panel replay

2023-11-07 Thread Animesh Manna
Add debugfs support which will print source and sink status
per connector basis. Existing i915_psr_status and
i915_psr_sink_status will be used to get the source and
sink status of panel replay.

v1: Initial version. [rb-ed by Arun]
v2: Added check for DP 2.0 and connector type in connector_debugfs_add().
v3: Optimization and cosmetic changes. [Jouni]

Cc: Jouni Högander 
Cc: Arun R Murthy 
Cc: Jani Nikula 
Reviewed-by: Arun R Murthy 
Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_psr.c | 87 +---
 1 file changed, 63 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index ea292832ca47..b0e46fe4bfac 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -2865,12 +2865,19 @@ static int psr_get_status_and_error_status(struct 
intel_dp *intel_dp,
 {
struct drm_dp_aux *aux = _dp->aux;
int ret;
+   unsigned int offset;
 
-   ret = drm_dp_dpcd_readb(aux, DP_PSR_STATUS, status);
+   offset = intel_dp->psr.panel_replay_enabled ?
+DP_SINK_DEVICE_PR_AND_FRAME_LOCK_STATUS : DP_PSR_STATUS;
+
+   ret = drm_dp_dpcd_readb(aux, offset, status);
if (ret != 1)
return ret;
 
-   ret = drm_dp_dpcd_readb(aux, DP_PSR_ERROR_STATUS, error_status);
+   offset = intel_dp->psr.panel_replay_enabled ?
+DP_PANEL_REPLAY_ERROR_STATUS : DP_PSR_ERROR_STATUS;
+
+   ret = drm_dp_dpcd_readb(aux, offset, error_status);
if (ret != 1)
return ret;
 
@@ -3091,7 +3098,7 @@ psr_source_status(struct intel_dp *intel_dp, struct 
seq_file *m)
status = live_status[status_val];
}
 
-   seq_printf(m, "Source PSR status: %s [0x%08x]\n", status, val);
+   seq_printf(m, "Source PSR/PanelReplay status: %s [0x%08x]\n", status, 
val);
 }
 
 static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp)
@@ -3104,18 +3111,22 @@ static int intel_psr_status(struct seq_file *m, struct 
intel_dp *intel_dp)
bool enabled;
u32 val;
 
-   seq_printf(m, "Sink support: %s", str_yes_no(psr->sink_support));
+   seq_printf(m, "Sink support: PSR = %s",
+  str_yes_no(psr->sink_support));
+
if (psr->sink_support)
seq_printf(m, " [0x%02x]", intel_dp->psr_dpcd[0]);
-   seq_puts(m, "\n");
+   seq_printf(m, ", Panel Replay = %s\n", 
str_yes_no(psr->sink_panel_replay_support));
 
-   if (!psr->sink_support)
+   if (!(psr->sink_support || psr->sink_panel_replay_support))
return 0;
 
wakeref = intel_runtime_pm_get(_priv->runtime_pm);
mutex_lock(>lock);
 
-   if (psr->enabled)
+   if (psr->panel_replay_enabled)
+   status = "Panel Replay Enabled";
+   else if (psr->enabled)
status = psr->psr2_enabled ? "PSR2 enabled" : "PSR1 enabled";
else
status = "disabled";
@@ -3128,14 +3139,17 @@ static int intel_psr_status(struct seq_file *m, struct 
intel_dp *intel_dp)
goto unlock;
}
 
-   if (psr->psr2_enabled) {
+   if (psr->panel_replay_enabled) {
+   val = intel_de_read(dev_priv, TRANS_DP2_CTL(cpu_transcoder));
+   enabled = val & TRANS_DP2_PANEL_REPLAY_ENABLE;
+   } else if (psr->psr2_enabled) {
val = intel_de_read(dev_priv, EDP_PSR2_CTL(cpu_transcoder));
enabled = val & EDP_PSR2_ENABLE;
} else {
val = intel_de_read(dev_priv, psr_ctl_reg(dev_priv, 
cpu_transcoder));
enabled = val & EDP_PSR_ENABLE;
}
-   seq_printf(m, "Source PSR ctl: %s [0x%08x]\n",
+   seq_printf(m, "Source PSR/PanelReplay ctl: %s [0x%08x]\n",
   str_enabled_disabled(enabled), val);
psr_source_status(intel_dp, m);
seq_printf(m, "Busy frontbuffer bits: 0x%08x\n",
@@ -3273,6 +3287,16 @@ void intel_psr_debugfs_register(struct drm_i915_private 
*i915)
i915, _edp_psr_status_fops);
 }
 
+static const char *psr_mode_str(struct intel_dp *intel_dp)
+{
+   if (intel_dp->psr.panel_replay_enabled)
+   return "PANEL-REPLAY";
+   else if (intel_dp->psr.enabled)
+   return "PSR";
+
+   return "unknown";
+}
+
 static int i915_psr_sink_status_show(struct seq_file *m, void *data)
 {
struct intel_connector *connector = m->private;
@@ -3287,12 +3311,19 @@ static int i915_psr_sink_status_show(struct seq_file 
*m, void *data)
"reserved",
"sink internal error",
};
+   stat

[Intel-gfx] [PATCH v9 5/6] drm/i915/panelreplay: enable/disable panel replay

2023-11-07 Thread Animesh Manna
TRANS_DP2_CTL register is programmed to enable panel replay from source
and sink is enabled through panel replay dpcd configuration address.

Bspec: 1407940617

v1: Initial version.
v2:
- Use pr_* flags instead psr_* flags. [Jouni]
- Remove intel_dp_is_edp check as edp1.5 also has panel replay. [Jouni]

v3: Cover letter updated and selective fetch condition check is added
before updating its bit in PSR2_MAN_TRK_CTL register. [Jouni]

v4: Selective fetch related PSR2_MAN_TRK_CTL programmming dropped. [Jouni]

v5: Added PSR2_MAN_TRK_CTL programming as needed for Continuous Full
Frame (CFF) update.

v6: Rebased on latest.

Note: Initial plan is to enable panel replay in  full-screen live active
frame update mode. In a incremental approach panel replay will be enabled
in selctive update mode if there is any gap in curent implementation.

Cc: Jouni Högander 
Cc: Arun R Murthy 
Cc: Jani Nikula 
Reviewed-by: Arun R Murthy 
Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_ddi.c  |  7 ++-
 .../drm/i915/display/intel_display_types.h|  1 +
 drivers/gpu/drm/i915/display/intel_psr.c  | 63 ++-
 3 files changed, 55 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
b/drivers/gpu/drm/i915/display/intel_ddi.c
index c75fd00e360a..5a698b7992ee 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -2717,10 +2717,15 @@ static void intel_ddi_pre_enable_dp(struct 
intel_atomic_state *state,
const struct drm_connector_state 
*conn_state)
 {
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+   struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 
-   if (HAS_DP20(dev_priv))
+   if (HAS_DP20(dev_priv)) {
intel_dp_128b132b_sdp_crc16(enc_to_intel_dp(encoder),
crtc_state);
+   if (crtc_state->has_panel_replay)
+   drm_dp_dpcd_writeb(_dp->aux, PANEL_REPLAY_CONFIG,
+  DP_PANEL_REPLAY_ENABLE);
+   }
 
if (DISPLAY_VER(dev_priv) >= 14)
mtl_ddi_pre_enable_dp(state, encoder, crtc_state, conn_state);
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index 6806605bd534..bb6714deb06b 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1708,6 +1708,7 @@ struct intel_psr {
u16 su_y_granularity;
bool source_panel_replay_support;
bool sink_panel_replay_support;
+   bool panel_replay_enabled;
u32 dc3co_exitline;
u32 dc3co_exit_delay;
struct delayed_work dc3co_work;
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index 3c25c8d85803..ea292832ca47 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -609,8 +609,11 @@ static void intel_psr_enable_sink(struct intel_dp 
*intel_dp)
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
u8 dpcd_val = DP_PSR_ENABLE;
 
-   /* Enable ALPM at sink for psr2 */
+   if (intel_dp->psr.panel_replay_enabled)
+   return;
+
if (intel_dp->psr.psr2_enabled) {
+   /* Enable ALPM at sink for psr2 */
drm_dp_dpcd_writeb(_dp->aux, DP_RECEIVER_ALPM_CONFIG,
   DP_ALPM_ENABLE |
   DP_ALPM_LOCK_ERROR_IRQ_HPD_ENABLE);
@@ -783,6 +786,17 @@ static u8 frames_before_su_entry(struct intel_dp *intel_dp)
return frames_before_su_entry;
 }
 
+static void dg2_activate_panel_replay(struct intel_dp *intel_dp)
+{
+   struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+
+   intel_de_rmw(dev_priv, PSR2_MAN_TRK_CTL(intel_dp->psr.transcoder),
+0, ADLP_PSR2_MAN_TRK_CTL_SF_CONTINUOS_FULL_FRAME);
+
+   intel_de_rmw(dev_priv, TRANS_DP2_CTL(intel_dp->psr.transcoder), 0,
+TRANS_DP2_PANEL_REPLAY_ENABLE);
+}
+
 static void hsw_activate_psr2(struct intel_dp *intel_dp)
 {
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
@@ -1379,18 +1393,23 @@ void intel_psr_get_config(struct intel_encoder *encoder,
return;
 
intel_dp = _port->dp;
-   if (!CAN_PSR(intel_dp))
+   if (!(CAN_PSR(intel_dp) || CAN_PANEL_REPLAY(intel_dp)))
return;
 
mutex_lock(_dp->psr.lock);
if (!intel_dp->psr.enabled)
goto unlock;
 
-   /*
-* Not possible to read EDP_PSR/PSR2_CTL registers as it is
-* enabled/disabled because of frontbuffer tracking and others.
-*/
-   pipe_config->has_psr = true;
+   if (intel_dp->psr.panel_replay_enabled) {
+   pipe_confi

[Intel-gfx] [PATCH v9 3/6] drm/i915/panelreplay: Initializaton and compute config for panel replay

2023-11-07 Thread Animesh Manna
Modify existing PSR implementation to enable panel replay feature of DP 2.0
which is similar to PSR feature of EDP panel. There is different DPCD
address to check panel capability compare to PSR and vsc sdp header
is different.

v1: Initial version.
v2:
- Set source_panel_replay_support flag under HAS_PANEL_REPLAY()
condition check. [Jouni]
- Code restructured around intel_panel_replay_init
and renamed to intel_panel_replay_init_dpcd. [Jouni]
- Remove the initial code modification around has_psr2 flag. [Jouni]
- Add CAN_PANEL_REPLAY() in intel_encoder_can_psr which is used to
enable in intel_psr_post_plane_update. [Jouni]
v3:
- Initialize both psr and panel-replay. [Jouni]
- Initialize both panel replay and psr if detected. [Jouni]
- Refactoring psr function by introducing _psr_compute_config(). [Jouni]
- Add check for !is_edp while deriving source_panel_replay_support. [Jouni]
- Enable panel replay dpcd initialization in a separate patch. [Jouni]

v4:
- HAS_PANEL_REPLAY() check not needed during sink capability check. [Jouni]
- Set either panel replay source support or psr. [Jouni]

v5:
- HAS_PANEL_REPLAY() removed and use HAS_DP20() instead. [Jouni]
- Move psr related code to intel_psr.c. [Jani]
- Reset sink_panel_replay_support flag during disconnection. [Jani]

v6: return statement restored which is removed by misatke. [Jouni]
v7: cosmetic changes. [Arun]

Cc: Jouni Högander 
Cc: Arun R Murthy 
Cc: Jani Nikula 
Reviewed-by: Arun R Murthy 
Signed-off-by: Animesh Manna 
---
 .../drm/i915/display/intel_display_types.h| 14 +---
 drivers/gpu/drm/i915/display/intel_dp.c   | 49 +--
 drivers/gpu/drm/i915/display/intel_dp_mst.c   |  3 +
 drivers/gpu/drm/i915/display/intel_psr.c  | 84 ++-
 drivers/gpu/drm/i915/display/intel_psr.h  |  7 ++
 5 files changed, 117 insertions(+), 40 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index 92f06d67fd1e..6806605bd534 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1208,6 +1208,7 @@ struct intel_crtc_state {
bool has_psr2;
bool enable_psr2_sel_fetch;
bool req_psr2_sdp_prior_scanline;
+   bool has_panel_replay;
bool wm_level_disabled;
u32 dc3co_exitline;
u16 su_y_granularity;
@@ -1705,6 +1706,8 @@ struct intel_psr {
bool irq_aux_error;
u16 su_w_granularity;
u16 su_y_granularity;
+   bool source_panel_replay_support;
+   bool sink_panel_replay_support;
u32 dc3co_exitline;
u32 dc3co_exit_delay;
struct delayed_work dc3co_work;
@@ -1991,17 +1994,6 @@ dp_to_lspcon(struct intel_dp *intel_dp)
 
 #define dp_to_i915(__intel_dp) 
to_i915(dp_to_dig_port(__intel_dp)->base.base.dev)
 
-#define CAN_PSR(intel_dp) ((intel_dp)->psr.sink_support && \
-  (intel_dp)->psr.source_support)
-
-static inline bool intel_encoder_can_psr(struct intel_encoder *encoder)
-{
-   if (!intel_encoder_is_dp(encoder))
-   return false;
-
-   return CAN_PSR(enc_to_intel_dp(encoder));
-}
-
 static inline struct intel_digital_port *
 hdmi_to_dig_port(struct intel_hdmi *intel_hdmi)
 {
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 5391b2a83405..8260fa638aa6 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2439,12 +2439,22 @@ static void intel_dp_compute_vsc_colorimetry(const 
struct intel_crtc_state *crtc
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 
-   /*
-* Prepare VSC Header for SU as per DP 1.4 spec, Table 2-118
-* VSC SDP supporting 3D stereo, PSR2, and Pixel Encoding/
-* Colorimetry Format indication.
-*/
-   vsc->revision = 0x5;
+   if (crtc_state->has_panel_replay) {
+   /*
+* Prepare VSC Header for SU as per DP 2.0 spec, Table 2-223
+* VSC SDP supporting 3D stereo, Panel Replay, and Pixel
+* Encoding/Colorimetry Format indication.
+*/
+   vsc->revision = 0x7;
+   } else {
+   /*
+* Prepare VSC Header for SU as per DP 1.4 spec, Table 2-118
+* VSC SDP supporting 3D stereo, PSR2, and Pixel Encoding/
+* Colorimetry Format indication.
+*/
+   vsc->revision = 0x5;
+   }
+
vsc->length = 0x13;
 
/* DP 1.4a spec, Table 2-120 */
@@ -2553,6 +2563,21 @@ void intel_dp_compute_psr_vsc_sdp(struct intel_dp 
*intel_dp,
vsc->revision = 0x4;
vsc->length = 0xe;
}
+   } else if (crtc_state->has_panel_replay) {
+ 

[Intel-gfx] [PATCH v9 4/6] drm/i915/panelreplay: Enable panel replay dpcd initialization for DP

2023-11-07 Thread Animesh Manna
Due to similarity panel replay dpcd initialization got added in psr
function which is specific for edp panel. This patch enables panel
replay initialization for dp connector.

Cc: Jouni Högander 
Cc: Arun R Murthy 
Cc: Jani Nikula 
Reviewed-by: Arun R Murthy 
Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_psr.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index 3ffdeb451a83..3c25c8d85803 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -2794,6 +2794,9 @@ void intel_psr_init(struct intel_dp *intel_dp)
if (!(HAS_PSR(dev_priv) || HAS_DP20(dev_priv)))
return;
 
+   if (!intel_dp_is_edp(intel_dp))
+   intel_psr_init_dpcd(intel_dp);
+
/*
 * HSW spec explicitly says PSR is tied to port A.
 * BDW+ platforms have a instance of PSR registers per transcoder but
-- 
2.29.0



[Intel-gfx] [PATCH v9 2/6] drm/i915/psr: Move psr specific dpcd init into own function

2023-11-07 Thread Animesh Manna
From: Jouni Högander 

This patch is preparing adding panel replay specific dpcd init.

Cc: Arun R Murthy 
Cc: Jani Nikula 
Reviewed-by: Arun R Murthy 
Signed-off-by: Jouni Högander 
---
 drivers/gpu/drm/i915/display/intel_psr.c | 41 +---
 1 file changed, 23 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index 3691f882e1c0..627d82164933 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -475,27 +475,22 @@ static void intel_dp_get_su_granularity(struct intel_dp 
*intel_dp)
intel_dp->psr.su_y_granularity = y;
 }
 
-void intel_psr_init_dpcd(struct intel_dp *intel_dp)
+static void _psr_init_dpcd(struct intel_dp *intel_dp)
 {
-   struct drm_i915_private *dev_priv =
+   struct drm_i915_private *i915 =
to_i915(dp_to_dig_port(intel_dp)->base.base.dev);
 
-   drm_dp_dpcd_read(_dp->aux, DP_PSR_SUPPORT, intel_dp->psr_dpcd,
-sizeof(intel_dp->psr_dpcd));
-
-   if (!intel_dp->psr_dpcd[0])
-   return;
-   drm_dbg_kms(_priv->drm, "eDP panel supports PSR version %x\n",
+   drm_dbg_kms(>drm, "eDP panel supports PSR version %x\n",
intel_dp->psr_dpcd[0]);
 
if (drm_dp_has_quirk(_dp->desc, DP_DPCD_QUIRK_NO_PSR)) {
-   drm_dbg_kms(_priv->drm,
+   drm_dbg_kms(>drm,
"PSR support not currently available for this 
panel\n");
return;
}
 
if (!(intel_dp->edp_dpcd[1] & DP_EDP_SET_POWER_CAP)) {
-   drm_dbg_kms(_priv->drm,
+   drm_dbg_kms(>drm,
"Panel lacks power state control, PSR cannot be 
enabled\n");
return;
}
@@ -504,8 +499,8 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp)
intel_dp->psr.sink_sync_latency =
intel_dp_get_sink_sync_latency(intel_dp);
 
-   if (DISPLAY_VER(dev_priv) >= 9 &&
-   (intel_dp->psr_dpcd[0] == DP_PSR2_WITH_Y_COORD_IS_SUPPORTED)) {
+   if (DISPLAY_VER(i915) >= 9 &&
+   intel_dp->psr_dpcd[0] == DP_PSR2_WITH_Y_COORD_IS_SUPPORTED) {
bool y_req = intel_dp->psr_dpcd[1] &
 DP_PSR2_SU_Y_COORDINATE_REQUIRED;
bool alpm = intel_dp_get_alpm_status(intel_dp);
@@ -522,14 +517,24 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp)
 * GTC first.
 */
intel_dp->psr.sink_psr2_support = y_req && alpm;
-   drm_dbg_kms(_priv->drm, "PSR2 %ssupported\n",
+   drm_dbg_kms(>drm, "PSR2 %ssupported\n",
intel_dp->psr.sink_psr2_support ? "" : "not ");
+   }
+}
 
-   if (intel_dp->psr.sink_psr2_support) {
-   intel_dp->psr.colorimetry_support =
-   intel_dp_get_colorimetry_status(intel_dp);
-   intel_dp_get_su_granularity(intel_dp);
-   }
+void intel_psr_init_dpcd(struct intel_dp *intel_dp)
+{
+   drm_dp_dpcd_read(_dp->aux, DP_PSR_SUPPORT, intel_dp->psr_dpcd,
+sizeof(intel_dp->psr_dpcd));
+
+   if (intel_dp->psr_dpcd[0])
+   _psr_init_dpcd(intel_dp);
+   /* TODO: Add PR case here */
+
+   if (intel_dp->psr.sink_psr2_support) {
+   intel_dp->psr.colorimetry_support =
+   intel_dp_get_colorimetry_status(intel_dp);
+   intel_dp_get_su_granularity(intel_dp);
}
 }
 
-- 
2.29.0



[Intel-gfx] [PATCH v9 1/6] drm/panelreplay: dpcd register definition for panelreplay

2023-11-07 Thread Animesh Manna
Add DPCD register definition for discovering, enabling and
checking status of panel replay of the sink.

Cc: Jouni Högander 
Cc: Arun R Murthy 
Cc: Jani Nikula 
Reviewed-by: Arun R Murthy 
Signed-off-by: Animesh Manna 
---
 include/drm/display/drm_dp.h | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/include/drm/display/drm_dp.h b/include/drm/display/drm_dp.h
index e69cece404b3..fc42b622ef32 100644
--- a/include/drm/display/drm_dp.h
+++ b/include/drm/display/drm_dp.h
@@ -543,6 +543,10 @@
 /* DFP Capability Extension */
 #define DP_DFP_CAPABILITY_EXTENSION_SUPPORT0x0a3   /* 2.0 */
 
+#define DP_PANEL_REPLAY_CAP 0x0b0  /* DP 2.0 */
+# define DP_PANEL_REPLAY_SUPPORT(1 << 0)
+# define DP_PANEL_REPLAY_SU_SUPPORT (1 << 1)
+
 /* Link Configuration */
 #defineDP_LINK_BW_SET  0x100
 # define DP_LINK_RATE_TABLE0x00/* eDP 1.4 */
@@ -716,6 +720,13 @@
 #define DP_BRANCH_DEVICE_CTRL  0x1a1
 # define DP_BRANCH_DEVICE_IRQ_HPD  (1 << 0)
 
+#define PANEL_REPLAY_CONFIG 0x1b0  /* DP 2.0 */
+# define DP_PANEL_REPLAY_ENABLE (1 << 0)
+# define DP_PANEL_REPLAY_UNRECOVERABLE_ERROR_EN (1 << 3)
+# define DP_PANEL_REPLAY_RFB_STORAGE_ERROR_EN   (1 << 4)
+# define DP_PANEL_REPLAY_ACTIVE_FRAME_CRC_ERROR_EN  (1 << 5)
+# define DP_PANEL_REPLAY_SU_ENABLE  (1 << 6)
+
 #define DP_PAYLOAD_ALLOCATE_SET0x1c0
 #define DP_PAYLOAD_ALLOCATE_START_TIME_SLOT 0x1c1
 #define DP_PAYLOAD_ALLOCATE_TIME_SLOT_COUNT 0x1c2
@@ -1105,6 +1116,18 @@
 #define DP_LANE_ALIGN_STATUS_UPDATED_ESI   0x200e /* status same as 0x204 
*/
 #define DP_SINK_STATUS_ESI 0x200f /* status same as 0x205 
*/
 
+#define DP_PANEL_REPLAY_ERROR_STATUS   0x2020  /* DP 2.1*/
+# define DP_PANEL_REPLAY_LINK_CRC_ERROR(1 << 0)
+# define DP_PANEL_REPLAY_RFB_STORAGE_ERROR (1 << 1)
+# define DP_PANEL_REPLAY_VSC_SDP_UNCORRECTABLE_ERROR   (1 << 2)
+
+#define DP_SINK_DEVICE_PR_AND_FRAME_LOCK_STATUS0x2022  /* DP 2.1 */
+# define DP_SINK_DEVICE_PANEL_REPLAY_STATUS_MASK   (7 << 0)
+# define DP_SINK_FRAME_LOCKED_SHIFT3
+# define DP_SINK_FRAME_LOCKED_MASK (3 << 3)
+# define DP_SINK_FRAME_LOCKED_STATUS_VALID_SHIFT   5
+# define DP_SINK_FRAME_LOCKED_STATUS_VALID_MASK(1 << 5)
+
 /* Extended Receiver Capability: See DP_DPCD_REV for definitions */
 #define DP_DP13_DPCD_REV0x2200
 
-- 
2.29.0



[Intel-gfx] [PATCH v9 0/6] Panel replay phase1 implementation

2023-11-07 Thread Animesh Manna
Panel Replay is a power saving feature for DP 2.0 monitor and similar
to PSR on EDP.

These patches are basic enablement patches added on top of
existing psr framework to enable full-screen live active frame
update mode of panel replay. Panel replay also can be enabled
in selective update mode which will be enabled in a incremental
approach.

As per current design panel replay priority is higher than psr.
intel_dp->psr.panel_replay_enabled flag indicate panel replay is enabled.
intel_dp->psr.panel_replay_enabled + intel_dp->psr.psr2_enabled indicates
panel replay is enabled in selective update mode.
intel_dp->psr.panel_replay_enabled + intel_dp->psr.psr2_enabled +
intel_psr.selective_fetch enabled indicates panel replay is
enabled in selective update mode with selective fetch.
PSR replated flags remain same like before.

Note: The patches are under testing by using panel replay emulator and
panel is not avalible.

Cc: Jouni Högander 
Cc: Arun R Murthy 
Cc: Jani Nikula 
Signed-off-by: Animesh Manna 

Animesh Manna (5):
  drm/panelreplay: dpcd register definition for panelreplay
  drm/i915/panelreplay: Initializaton and compute config for panel
replay
  drm/i915/panelreplay: Enable panel replay dpcd initialization for DP
  drm/i915/panelreplay: enable/disable panel replay
  drm/i915/panelreplay: Debugfs support for panel replay

Jouni Högander (1):
  drm/i915/psr: Move psr specific dpcd init into own function

 drivers/gpu/drm/i915/display/intel_ddi.c  |   7 +-
 .../drm/i915/display/intel_display_types.h|  15 +-
 drivers/gpu/drm/i915/display/intel_dp.c   |  49 +++-
 drivers/gpu/drm/i915/display/intel_dp_mst.c   |   3 +
 drivers/gpu/drm/i915/display/intel_psr.c  | 274 +-
 drivers/gpu/drm/i915/display/intel_psr.h  |   7 +
 include/drm/display/drm_dp.h  |  23 ++
 7 files changed, 282 insertions(+), 96 deletions(-)

-- 
2.29.0



[Intel-gfx] [PATCH v8 5/6] drm/i915/panelreplay: enable/disable panel replay

2023-11-03 Thread Animesh Manna
TRANS_DP2_CTL register is programmed to enable panel replay from source
and sink is enabled through panel replay dpcd configuration address.

Bspec: 1407940617

v1: Initial version.
v2:
- Use pr_* flags instead psr_* flags. [Jouni]
- Remove intel_dp_is_edp check as edp1.5 also has panel replay. [Jouni]

v3: Cover letter updated and selective fetch condition check is added
before updating its bit in PSR2_MAN_TRK_CTL register. [Jouni]

v4: Selective fetch related PSR2_MAN_TRK_CTL programmming dropped. [Jouni]

v5: Added PSR2_MAN_TRK_CTL programming as needed for Continuous Full
Frame (CFF) update.

v6: Rebased on latest.

Note: Initial plan is to enable panel replay in  full-screen live active
frame update mode. In a incremental approach panel replay will be enabled
in selctive update mode if there is any gap in curent implementation.

Cc: Jouni Högander 
Cc: Arun R Murthy 
Cc: Jani Nikula 
Reviewed-by: Arun R Murthy 
Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_ddi.c  |  7 ++-
 .../drm/i915/display/intel_display_types.h|  1 +
 drivers/gpu/drm/i915/display/intel_psr.c  | 63 ++-
 3 files changed, 55 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
b/drivers/gpu/drm/i915/display/intel_ddi.c
index 2e37708fecdd..c446d8ef210f 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -2717,10 +2717,15 @@ static void intel_ddi_pre_enable_dp(struct 
intel_atomic_state *state,
const struct drm_connector_state 
*conn_state)
 {
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+   struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 
-   if (HAS_DP20(dev_priv))
+   if (HAS_DP20(dev_priv)) {
intel_dp_128b132b_sdp_crc16(enc_to_intel_dp(encoder),
crtc_state);
+   if (crtc_state->has_panel_replay)
+   drm_dp_dpcd_writeb(_dp->aux, PANEL_REPLAY_CONFIG,
+  DP_PANEL_REPLAY_ENABLE);
+   }
 
if (DISPLAY_VER(dev_priv) >= 14)
mtl_ddi_pre_enable_dp(state, encoder, crtc_state, conn_state);
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index 7d46bece7e06..81a7c6efa4a8 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1708,6 +1708,7 @@ struct intel_psr {
u16 su_y_granularity;
bool source_panel_replay_support;
bool sink_panel_replay_support;
+   bool panel_replay_enabled;
u32 dc3co_exitline;
u32 dc3co_exit_delay;
struct delayed_work dc3co_work;
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index e53a2217627a..8ed4684b4528 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -608,8 +608,11 @@ static void intel_psr_enable_sink(struct intel_dp 
*intel_dp)
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
u8 dpcd_val = DP_PSR_ENABLE;
 
-   /* Enable ALPM at sink for psr2 */
+   if (intel_dp->psr.panel_replay_enabled)
+   return;
+
if (intel_dp->psr.psr2_enabled) {
+   /* Enable ALPM at sink for psr2 */
drm_dp_dpcd_writeb(_dp->aux, DP_RECEIVER_ALPM_CONFIG,
   DP_ALPM_ENABLE |
   DP_ALPM_LOCK_ERROR_IRQ_HPD_ENABLE);
@@ -761,6 +764,17 @@ static int psr2_block_count(struct intel_dp *intel_dp)
return psr2_block_count_lines(intel_dp) / 4;
 }
 
+static void dg2_activate_panel_replay(struct intel_dp *intel_dp)
+{
+   struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+
+   intel_de_rmw(dev_priv, PSR2_MAN_TRK_CTL(intel_dp->psr.transcoder),
+0, ADLP_PSR2_MAN_TRK_CTL_SF_CONTINUOS_FULL_FRAME);
+
+   intel_de_rmw(dev_priv, TRANS_DP2_CTL(intel_dp->psr.transcoder), 0,
+TRANS_DP2_PANEL_REPLAY_ENABLE);
+}
+
 static void hsw_activate_psr2(struct intel_dp *intel_dp)
 {
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
@@ -1325,18 +1339,23 @@ void intel_psr_get_config(struct intel_encoder *encoder,
return;
 
intel_dp = _port->dp;
-   if (!CAN_PSR(intel_dp))
+   if (!(CAN_PSR(intel_dp) || CAN_PANEL_REPLAY(intel_dp)))
return;
 
mutex_lock(_dp->psr.lock);
if (!intel_dp->psr.enabled)
goto unlock;
 
-   /*
-* Not possible to read EDP_PSR/PSR2_CTL registers as it is
-* enabled/disabled because of frontbuffer tracking and others.
-*/
-   pipe_config->has_psr = true;
+   if (intel_dp->psr.panel_replay_enabled) {
+ 

[Intel-gfx] [PATCH v8 6/6] drm/i915/panelreplay: Debugfs support for panel replay

2023-11-03 Thread Animesh Manna
Add debugfs support which will print source and sink status
per connector basis. Existing i915_psr_status and
i915_psr_sink_status will be used to get the source and
sink status of panel replay.

v1: Initial version. [rb-ed by Arun]
v2: Added check for DP 2.0 and connector type in connector_debugfs_add().
v3: Optimization and cosmetic changes. [Jouni]

Cc: Jouni Högander 
Cc: Arun R Murthy 
Cc: Jani Nikula 
Reviewed-by: Arun R Murthy 
Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_psr.c | 93 +---
 1 file changed, 66 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index 8ed4684b4528..8b7c03cd4989 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -2813,12 +2813,19 @@ static int psr_get_status_and_error_status(struct 
intel_dp *intel_dp,
 {
struct drm_dp_aux *aux = _dp->aux;
int ret;
+   unsigned int offset;
 
-   ret = drm_dp_dpcd_readb(aux, DP_PSR_STATUS, status);
+   offset = intel_dp->psr.panel_replay_enabled ?
+DP_SINK_DEVICE_PR_AND_FRAME_LOCK_STATUS : DP_PSR_STATUS;
+
+   ret = drm_dp_dpcd_readb(aux, offset, status);
if (ret != 1)
return ret;
 
-   ret = drm_dp_dpcd_readb(aux, DP_PSR_ERROR_STATUS, error_status);
+   offset = intel_dp->psr.panel_replay_enabled ?
+DP_PANEL_REPLAY_ERROR_STATUS : DP_PSR_ERROR_STATUS;
+
+   ret = drm_dp_dpcd_readb(aux, offset, error_status);
if (ret != 1)
return ret;
 
@@ -3039,7 +3046,7 @@ psr_source_status(struct intel_dp *intel_dp, struct 
seq_file *m)
status = live_status[status_val];
}
 
-   seq_printf(m, "Source PSR status: %s [0x%08x]\n", status, val);
+   seq_printf(m, "Source PSR/PanelReplay status: %s [0x%08x]\n", status, 
val);
 }
 
 static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp)
@@ -3052,18 +3059,23 @@ static int intel_psr_status(struct seq_file *m, struct 
intel_dp *intel_dp)
bool enabled;
u32 val;
 
-   seq_printf(m, "Sink support: %s", str_yes_no(psr->sink_support));
-   if (psr->sink_support)
+   seq_printf(m, "Sink support: PSR = %s, Panel Replay = %s",
+  str_yes_no(psr->sink_support),
+  str_yes_no(psr->sink_panel_replay_support));
+
+   if (psr->sink_support || psr->sink_panel_replay_support)
seq_printf(m, " [0x%02x]", intel_dp->psr_dpcd[0]);
seq_puts(m, "\n");
 
-   if (!psr->sink_support)
+   if (!(psr->sink_support || psr->sink_panel_replay_support))
return 0;
 
wakeref = intel_runtime_pm_get(_priv->runtime_pm);
mutex_lock(>lock);
 
-   if (psr->enabled)
+   if (psr->panel_replay_enabled)
+   status = "Panel Replay Enabled";
+   else if (psr->enabled)
status = psr->psr2_enabled ? "PSR2 enabled" : "PSR1 enabled";
else
status = "disabled";
@@ -3076,14 +3088,17 @@ static int intel_psr_status(struct seq_file *m, struct 
intel_dp *intel_dp)
goto unlock;
}
 
-   if (psr->psr2_enabled) {
+   if (psr->panel_replay_enabled) {
+   val = intel_de_read(dev_priv, TRANS_DP2_CTL(cpu_transcoder));
+   enabled = val & TRANS_DP2_PANEL_REPLAY_ENABLE;
+   } else if (psr->psr2_enabled) {
val = intel_de_read(dev_priv, EDP_PSR2_CTL(cpu_transcoder));
enabled = val & EDP_PSR2_ENABLE;
} else {
val = intel_de_read(dev_priv, psr_ctl_reg(dev_priv, 
cpu_transcoder));
enabled = val & EDP_PSR_ENABLE;
}
-   seq_printf(m, "Source PSR ctl: %s [0x%08x]\n",
+   seq_printf(m, "Source PSR/PanelReplay ctl: %s [0x%08x]\n",
   str_enabled_disabled(enabled), val);
psr_source_status(intel_dp, m);
seq_printf(m, "Busy frontbuffer bits: 0x%08x\n",
@@ -3221,6 +3236,15 @@ void intel_psr_debugfs_register(struct drm_i915_private 
*i915)
i915, _edp_psr_status_fops);
 }
 
+static const char *psr_mode_str(struct intel_dp *intel_dp) {
+   if (intel_dp->psr.panel_replay_enabled)
+   return "PANEL-REPLAY";
+   else if(intel_dp->psr.enabled)
+   return "PSR";
+
+   return "unknown";
+}
+
 static int i915_psr_sink_status_show(struct seq_file *m, void *data)
 {
struct intel_connector *connector = m->private;
@@ -3235,12 +3259,19 @@ static int i915_psr_sink_status_show(struct seq_file 
*m, void *data)
"reserved",
"sink int

[Intel-gfx] [PATCH v8 4/6] drm/i915/panelreplay: Enable panel replay dpcd initialization for DP

2023-11-03 Thread Animesh Manna
Due to similarity panel replay dpcd initialization got added in psr
function which is specific for edp panel. This patch enables panel
replay initialization for dp connector.

Cc: Jouni Högander 
Cc: Arun R Murthy 
Cc: Jani Nikula 
Reviewed-by: Arun R Murthy 
Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_psr.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index 3c66257b6bb2..e53a2217627a 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -2742,6 +2742,9 @@ void intel_psr_init(struct intel_dp *intel_dp)
if (!(HAS_PSR(dev_priv) || HAS_DP20(dev_priv)))
return;
 
+   if (!intel_dp_is_edp(intel_dp))
+   intel_psr_init_dpcd(intel_dp);
+
/*
 * HSW spec explicitly says PSR is tied to port A.
 * BDW+ platforms have a instance of PSR registers per transcoder but
-- 
2.29.0



[Intel-gfx] [PATCH v8 3/6] drm/i915/panelreplay: Initializaton and compute config for panel replay

2023-11-03 Thread Animesh Manna
Modify existing PSR implementation to enable panel replay feature of DP 2.0
which is similar to PSR feature of EDP panel. There is different DPCD
address to check panel capability compare to PSR and vsc sdp header
is different.

v1: Initial version.
v2:
- Set source_panel_replay_support flag under HAS_PANEL_REPLAY()
condition check. [Jouni]
- Code restructured around intel_panel_replay_init
and renamed to intel_panel_replay_init_dpcd. [Jouni]
- Remove the initial code modification around has_psr2 flag. [Jouni]
- Add CAN_PANEL_REPLAY() in intel_encoder_can_psr which is used to
enable in intel_psr_post_plane_update. [Jouni]
v3:
- Initialize both psr and panel-replay. [Jouni]
- Initialize both panel replay and psr if detected. [Jouni]
- Refactoring psr function by introducing _psr_compute_config(). [Jouni]
- Add check for !is_edp while deriving source_panel_replay_support. [Jouni]
- Enable panel replay dpcd initialization in a separate patch. [Jouni]

v4:
- HAS_PANEL_REPLAY() check not needed during sink capability check. [Jouni]
- Set either panel replay source support or psr. [Jouni]

v5:
- HAS_PANEL_REPLAY() removed and use HAS_DP20() instead. [Jouni]
- Move psr related code to intel_psr.c. [Jani]
- Reset sink_panel_replay_support flag during disconnection. [Jani]

v6: return statement restored which is removed by misatke. [Jouni]
v7: cosmetic changes. [Arun]

Cc: Jouni Högander 
Cc: Arun R Murthy 
Cc: Jani Nikula 
Reviewed-by: Arun R Murthy 
Signed-off-by: Animesh Manna 
---
 .../drm/i915/display/intel_display_types.h| 14 +--
 drivers/gpu/drm/i915/display/intel_dp.c   | 49 --
 drivers/gpu/drm/i915/display/intel_dp_mst.c   |  3 +
 drivers/gpu/drm/i915/display/intel_psr.c  | 96 ++-
 drivers/gpu/drm/i915/display/intel_psr.h  |  7 ++
 5 files changed, 123 insertions(+), 46 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index 047fe3f8905a..7d46bece7e06 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1208,6 +1208,7 @@ struct intel_crtc_state {
bool has_psr2;
bool enable_psr2_sel_fetch;
bool req_psr2_sdp_prior_scanline;
+   bool has_panel_replay;
bool wm_level_disabled;
u32 dc3co_exitline;
u16 su_y_granularity;
@@ -1705,6 +1706,8 @@ struct intel_psr {
bool irq_aux_error;
u16 su_w_granularity;
u16 su_y_granularity;
+   bool source_panel_replay_support;
+   bool sink_panel_replay_support;
u32 dc3co_exitline;
u32 dc3co_exit_delay;
struct delayed_work dc3co_work;
@@ -1990,17 +1993,6 @@ dp_to_lspcon(struct intel_dp *intel_dp)
 
 #define dp_to_i915(__intel_dp) 
to_i915(dp_to_dig_port(__intel_dp)->base.base.dev)
 
-#define CAN_PSR(intel_dp) ((intel_dp)->psr.sink_support && \
-  (intel_dp)->psr.source_support)
-
-static inline bool intel_encoder_can_psr(struct intel_encoder *encoder)
-{
-   if (!intel_encoder_is_dp(encoder))
-   return false;
-
-   return CAN_PSR(enc_to_intel_dp(encoder));
-}
-
 static inline struct intel_digital_port *
 hdmi_to_dig_port(struct intel_hdmi *intel_hdmi)
 {
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 5391b2a83405..8260fa638aa6 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2439,12 +2439,22 @@ static void intel_dp_compute_vsc_colorimetry(const 
struct intel_crtc_state *crtc
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 
-   /*
-* Prepare VSC Header for SU as per DP 1.4 spec, Table 2-118
-* VSC SDP supporting 3D stereo, PSR2, and Pixel Encoding/
-* Colorimetry Format indication.
-*/
-   vsc->revision = 0x5;
+   if (crtc_state->has_panel_replay) {
+   /*
+* Prepare VSC Header for SU as per DP 2.0 spec, Table 2-223
+* VSC SDP supporting 3D stereo, Panel Replay, and Pixel
+* Encoding/Colorimetry Format indication.
+*/
+   vsc->revision = 0x7;
+   } else {
+   /*
+* Prepare VSC Header for SU as per DP 1.4 spec, Table 2-118
+* VSC SDP supporting 3D stereo, PSR2, and Pixel Encoding/
+* Colorimetry Format indication.
+*/
+   vsc->revision = 0x5;
+   }
+
vsc->length = 0x13;
 
/* DP 1.4a spec, Table 2-120 */
@@ -2553,6 +2563,21 @@ void intel_dp_compute_psr_vsc_sdp(struct intel_dp 
*intel_dp,
vsc->revision = 0x4;
vsc->length = 0xe;
}
+   } else if (crtc_state->has_panel_replay) {
+ 

[Intel-gfx] [PATCH v8 1/6] drm/panelreplay: dpcd register definition for panelreplay

2023-11-03 Thread Animesh Manna
Add DPCD register definition for discovering, enabling and
checking status of panel replay of the sink.

Cc: Jouni Högander 
Cc: Arun R Murthy 
Cc: Jani Nikula 
Reviewed-by: Arun R Murthy 
Signed-off-by: Animesh Manna 
---
 include/drm/display/drm_dp.h | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/include/drm/display/drm_dp.h b/include/drm/display/drm_dp.h
index e69cece404b3..fc42b622ef32 100644
--- a/include/drm/display/drm_dp.h
+++ b/include/drm/display/drm_dp.h
@@ -543,6 +543,10 @@
 /* DFP Capability Extension */
 #define DP_DFP_CAPABILITY_EXTENSION_SUPPORT0x0a3   /* 2.0 */
 
+#define DP_PANEL_REPLAY_CAP 0x0b0  /* DP 2.0 */
+# define DP_PANEL_REPLAY_SUPPORT(1 << 0)
+# define DP_PANEL_REPLAY_SU_SUPPORT (1 << 1)
+
 /* Link Configuration */
 #defineDP_LINK_BW_SET  0x100
 # define DP_LINK_RATE_TABLE0x00/* eDP 1.4 */
@@ -716,6 +720,13 @@
 #define DP_BRANCH_DEVICE_CTRL  0x1a1
 # define DP_BRANCH_DEVICE_IRQ_HPD  (1 << 0)
 
+#define PANEL_REPLAY_CONFIG 0x1b0  /* DP 2.0 */
+# define DP_PANEL_REPLAY_ENABLE (1 << 0)
+# define DP_PANEL_REPLAY_UNRECOVERABLE_ERROR_EN (1 << 3)
+# define DP_PANEL_REPLAY_RFB_STORAGE_ERROR_EN   (1 << 4)
+# define DP_PANEL_REPLAY_ACTIVE_FRAME_CRC_ERROR_EN  (1 << 5)
+# define DP_PANEL_REPLAY_SU_ENABLE  (1 << 6)
+
 #define DP_PAYLOAD_ALLOCATE_SET0x1c0
 #define DP_PAYLOAD_ALLOCATE_START_TIME_SLOT 0x1c1
 #define DP_PAYLOAD_ALLOCATE_TIME_SLOT_COUNT 0x1c2
@@ -1105,6 +1116,18 @@
 #define DP_LANE_ALIGN_STATUS_UPDATED_ESI   0x200e /* status same as 0x204 
*/
 #define DP_SINK_STATUS_ESI 0x200f /* status same as 0x205 
*/
 
+#define DP_PANEL_REPLAY_ERROR_STATUS   0x2020  /* DP 2.1*/
+# define DP_PANEL_REPLAY_LINK_CRC_ERROR(1 << 0)
+# define DP_PANEL_REPLAY_RFB_STORAGE_ERROR (1 << 1)
+# define DP_PANEL_REPLAY_VSC_SDP_UNCORRECTABLE_ERROR   (1 << 2)
+
+#define DP_SINK_DEVICE_PR_AND_FRAME_LOCK_STATUS0x2022  /* DP 2.1 */
+# define DP_SINK_DEVICE_PANEL_REPLAY_STATUS_MASK   (7 << 0)
+# define DP_SINK_FRAME_LOCKED_SHIFT3
+# define DP_SINK_FRAME_LOCKED_MASK (3 << 3)
+# define DP_SINK_FRAME_LOCKED_STATUS_VALID_SHIFT   5
+# define DP_SINK_FRAME_LOCKED_STATUS_VALID_MASK(1 << 5)
+
 /* Extended Receiver Capability: See DP_DPCD_REV for definitions */
 #define DP_DP13_DPCD_REV0x2200
 
-- 
2.29.0



[Intel-gfx] [PATCH v8 2/6] drm/i915/psr: Move psr specific dpcd init into own function

2023-11-03 Thread Animesh Manna
From: Jouni Högander 

This patch is preparing adding panel replay specific dpcd init.

Cc: Arun R Murthy 
Cc: Jani Nikula 
Reviewed-by: Arun R Murthy 
Signed-off-by: Jouni Högander 
---
 drivers/gpu/drm/i915/display/intel_psr.c | 41 +---
 1 file changed, 23 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index ecd24a0b86cb..48da60005ceb 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -474,27 +474,22 @@ static void intel_dp_get_su_granularity(struct intel_dp 
*intel_dp)
intel_dp->psr.su_y_granularity = y;
 }
 
-void intel_psr_init_dpcd(struct intel_dp *intel_dp)
+static void _psr_init_dpcd(struct intel_dp *intel_dp)
 {
-   struct drm_i915_private *dev_priv =
+   struct drm_i915_private *i915 =
to_i915(dp_to_dig_port(intel_dp)->base.base.dev);
 
-   drm_dp_dpcd_read(_dp->aux, DP_PSR_SUPPORT, intel_dp->psr_dpcd,
-sizeof(intel_dp->psr_dpcd));
-
-   if (!intel_dp->psr_dpcd[0])
-   return;
-   drm_dbg_kms(_priv->drm, "eDP panel supports PSR version %x\n",
+   drm_dbg_kms(>drm, "eDP panel supports PSR version %x\n",
intel_dp->psr_dpcd[0]);
 
if (drm_dp_has_quirk(_dp->desc, DP_DPCD_QUIRK_NO_PSR)) {
-   drm_dbg_kms(_priv->drm,
+   drm_dbg_kms(>drm,
"PSR support not currently available for this 
panel\n");
return;
}
 
if (!(intel_dp->edp_dpcd[1] & DP_EDP_SET_POWER_CAP)) {
-   drm_dbg_kms(_priv->drm,
+   drm_dbg_kms(>drm,
"Panel lacks power state control, PSR cannot be 
enabled\n");
return;
}
@@ -503,8 +498,8 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp)
intel_dp->psr.sink_sync_latency =
intel_dp_get_sink_sync_latency(intel_dp);
 
-   if (DISPLAY_VER(dev_priv) >= 9 &&
-   (intel_dp->psr_dpcd[0] == DP_PSR2_WITH_Y_COORD_IS_SUPPORTED)) {
+   if (DISPLAY_VER(i915) >= 9 &&
+   intel_dp->psr_dpcd[0] == DP_PSR2_WITH_Y_COORD_IS_SUPPORTED) {
bool y_req = intel_dp->psr_dpcd[1] &
 DP_PSR2_SU_Y_COORDINATE_REQUIRED;
bool alpm = intel_dp_get_alpm_status(intel_dp);
@@ -521,14 +516,24 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp)
 * GTC first.
 */
intel_dp->psr.sink_psr2_support = y_req && alpm;
-   drm_dbg_kms(_priv->drm, "PSR2 %ssupported\n",
+   drm_dbg_kms(>drm, "PSR2 %ssupported\n",
intel_dp->psr.sink_psr2_support ? "" : "not ");
+   }
+}
 
-   if (intel_dp->psr.sink_psr2_support) {
-   intel_dp->psr.colorimetry_support =
-   intel_dp_get_colorimetry_status(intel_dp);
-   intel_dp_get_su_granularity(intel_dp);
-   }
+void intel_psr_init_dpcd(struct intel_dp *intel_dp)
+{
+   drm_dp_dpcd_read(_dp->aux, DP_PSR_SUPPORT, intel_dp->psr_dpcd,
+sizeof(intel_dp->psr_dpcd));
+
+   if (intel_dp->psr_dpcd[0])
+   _psr_init_dpcd(intel_dp);
+   /* TODO: Add PR case here */
+
+   if (intel_dp->psr.sink_psr2_support) {
+   intel_dp->psr.colorimetry_support =
+   intel_dp_get_colorimetry_status(intel_dp);
+   intel_dp_get_su_granularity(intel_dp);
}
 }
 
-- 
2.29.0



[Intel-gfx] [PATCH v8 0/6] Panel replay phase1 implementation

2023-11-03 Thread Animesh Manna
Panel Replay is a power saving feature for DP 2.0 monitor and similar
to PSR on EDP.

These patches are basic enablement patches added on top of
existing psr framework to enable full-screen live active frame
update mode of panel replay. Panel replay also can be enabled
in selective update mode which will be enabled in a incremental
approach.

As per current design panel replay priority is higher than psr.
intel_dp->psr.panel_replay_enabled flag indicate panel replay is enabled.
intel_dp->psr.panel_replay_enabled + intel_dp->psr.psr2_enabled indicates
panel replay is enabled in selective update mode.
intel_dp->psr.panel_replay_enabled + intel_dp->psr.psr2_enabled +
intel_psr.selective_fetch enabled indicates panel replay is
enabled in selective update mode with selective fetch.
PSR replated flags remain same like before.

Note: The patches are under testing by using panel replay emulator and
panel is not avalible.

Cc: Jouni Högander 
Cc: Arun R Murthy 
Cc: Jani Nikula 
Signed-off-by: Animesh Manna 

Animesh Manna (5):
  drm/panelreplay: dpcd register definition for panelreplay
  drm/i915/panelreplay: Initializaton and compute config for panel
replay
  drm/i915/panelreplay: Enable panel replay dpcd initialization for DP
  drm/i915/panelreplay: enable/disable panel replay
  drm/i915/panelreplay: Debugfs support for panel replay

Jouni Högander (1):
  drm/i915/psr: Move psr specific dpcd init into own function

 drivers/gpu/drm/i915/display/intel_ddi.c  |   7 +-
 .../drm/i915/display/intel_display_types.h|  15 +-
 drivers/gpu/drm/i915/display/intel_dp.c   |  49 ++-
 drivers/gpu/drm/i915/display/intel_dp_mst.c   |   3 +
 drivers/gpu/drm/i915/display/intel_psr.c  | 292 +-
 drivers/gpu/drm/i915/display/intel_psr.h  |   7 +
 include/drm/display/drm_dp.h  |  23 ++
 7 files changed, 291 insertions(+), 105 deletions(-)

-- 
2.29.0



[Intel-gfx] [PATCH v5] drm/i915/dsb: DSB code refactoring

2023-11-02 Thread Animesh Manna
Refactor DSB implementation to be compatible with Xe driver.

v1: RFC version.
v2: Make intel_dsb structure opaque from external usage. [Jani]
v3: Rebased on latest.
v4:
- Add boundary check in dsb_buffer_memset(). [Luca]
- Use size_t instead of u32. [Luca]
v5: WARN_ON() added for out of boudary case with some optimization. [Luca]

Cc: Jani Nikula 
Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/Makefile |  1 +
 drivers/gpu/drm/i915/display/intel_dsb.c  | 98 +++
 .../gpu/drm/i915/display/intel_dsb_buffer.c   | 82 
 .../gpu/drm/i915/display/intel_dsb_buffer.h   | 29 ++
 4 files changed, 148 insertions(+), 62 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_dsb_buffer.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_dsb_buffer.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 239da40a401f..7e5d6a39d450 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -277,6 +277,7 @@ i915-y += \
display/intel_dpt.o \
display/intel_drrs.o \
display/intel_dsb.o \
+   display/intel_dsb_buffer.o \
display/intel_fb.o \
display/intel_fb_pin.o \
display/intel_fbc.o \
diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c 
b/drivers/gpu/drm/i915/display/intel_dsb.c
index 78b6fe24dcd8..3c7733a416a4 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.c
+++ b/drivers/gpu/drm/i915/display/intel_dsb.c
@@ -4,9 +4,6 @@
  *
  */
 
-#include "gem/i915_gem_internal.h"
-#include "gem/i915_gem_lmem.h"
-
 #include "i915_drv.h"
 #include "i915_irq.h"
 #include "i915_reg.h"
@@ -14,12 +11,13 @@
 #include "intel_de.h"
 #include "intel_display_types.h"
 #include "intel_dsb.h"
+#include "intel_dsb_buffer.h"
 #include "intel_dsb_regs.h"
 #include "intel_vblank.h"
 #include "intel_vrr.h"
 #include "skl_watermark.h"
 
-struct i915_vma;
+#define CACHELINE_BYTES 64
 
 enum dsb_id {
INVALID_DSB = -1,
@@ -32,8 +30,7 @@ enum dsb_id {
 struct intel_dsb {
enum dsb_id id;
 
-   u32 *cmd_buf;
-   struct i915_vma *vma;
+   struct intel_dsb_buffer dsb_buf;
struct intel_crtc *crtc;
 
/*
@@ -109,15 +106,17 @@ static void intel_dsb_dump(struct intel_dsb *dsb)
 {
struct intel_crtc *crtc = dsb->crtc;
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
-   const u32 *buf = dsb->cmd_buf;
int i;
 
drm_dbg_kms(>drm, "[CRTC:%d:%s] DSB %d commands {\n",
crtc->base.base.id, crtc->base.name, dsb->id);
for (i = 0; i < ALIGN(dsb->free_pos, 64 / 4); i += 4)
drm_dbg_kms(>drm,
-   " 0x%08x: 0x%08x 0x%08x 0x%08x 0x%08x\n",
-   i * 4, buf[i], buf[i+1], buf[i+2], buf[i+3]);
+   " 0x%08x: 0x%08x 0x%08x 0x%08x 0x%08x\n", i * 4,
+   intel_dsb_buffer_read(>dsb_buf, i),
+   intel_dsb_buffer_read(>dsb_buf, i + 1),
+   intel_dsb_buffer_read(>dsb_buf, i + 2),
+   intel_dsb_buffer_read(>dsb_buf, i + 3));
drm_dbg_kms(>drm, "}\n");
 }
 
@@ -129,8 +128,6 @@ static bool is_dsb_busy(struct drm_i915_private *i915, enum 
pipe pipe,
 
 static void intel_dsb_emit(struct intel_dsb *dsb, u32 ldw, u32 udw)
 {
-   u32 *buf = dsb->cmd_buf;
-
if (!assert_dsb_has_room(dsb))
return;
 
@@ -139,14 +136,13 @@ static void intel_dsb_emit(struct intel_dsb *dsb, u32 
ldw, u32 udw)
 
dsb->ins_start_offset = dsb->free_pos;
 
-   buf[dsb->free_pos++] = ldw;
-   buf[dsb->free_pos++] = udw;
+   intel_dsb_buffer_write(>dsb_buf, dsb->free_pos++, ldw);
+   intel_dsb_buffer_write(>dsb_buf, dsb->free_pos++, udw);
 }
 
 static bool intel_dsb_prev_ins_is_write(struct intel_dsb *dsb,
u32 opcode, i915_reg_t reg)
 {
-   const u32 *buf = dsb->cmd_buf;
u32 prev_opcode, prev_reg;
 
/*
@@ -157,8 +153,10 @@ static bool intel_dsb_prev_ins_is_write(struct intel_dsb 
*dsb,
if (dsb->free_pos == 0)
return false;
 
-   prev_opcode = buf[dsb->ins_start_offset + 1] & ~DSB_REG_VALUE_MASK;
-   prev_reg = buf[dsb->ins_start_offset + 1] & DSB_REG_VALUE_MASK;
+   prev_opcode = intel_dsb_buffer_read(>dsb_buf,
+   dsb->ins_start_offset + 1) >> 
DSB_OPCODE_SHIFT;
+   prev_reg =  intel_dsb_buffer_read(>dsb_buf,
+ dsb->ins_start_offset + 1) & 
DSB_REG_VALUE_MASK;
 
return prev_opcode == opcode && prev_reg == i915_mmio_reg_offse

[Intel-gfx] [PATCH v4] drm/i915/dsb: DSB code refactoring

2023-10-27 Thread Animesh Manna
Refactor DSB implementation to be compatible with Xe driver.

v1: RFC version.
v2: Make intel_dsb structure opaque from external usage. [Jani]
v3: Rebased on latest.
v4:
- Add boundary check in dsb_buffer_memset(). [Luca]
- Use size_t instead of u32. [Luca]

Cc: Jani Nikula 
Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/Makefile |  1 +
 drivers/gpu/drm/i915/display/intel_dsb.c  | 98 +++
 .../gpu/drm/i915/display/intel_dsb_buffer.c   | 83 
 .../gpu/drm/i915/display/intel_dsb_buffer.h   | 29 ++
 4 files changed, 149 insertions(+), 62 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_dsb_buffer.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_dsb_buffer.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 3b9dcb606fc1..0687b00e1740 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -272,6 +272,7 @@ i915-y += \
display/intel_dpt.o \
display/intel_drrs.o \
display/intel_dsb.o \
+   display/intel_dsb_buffer.o \
display/intel_fb.o \
display/intel_fb_pin.o \
display/intel_fbc.o \
diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c 
b/drivers/gpu/drm/i915/display/intel_dsb.c
index 78b6fe24dcd8..3c7733a416a4 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.c
+++ b/drivers/gpu/drm/i915/display/intel_dsb.c
@@ -4,9 +4,6 @@
  *
  */
 
-#include "gem/i915_gem_internal.h"
-#include "gem/i915_gem_lmem.h"
-
 #include "i915_drv.h"
 #include "i915_irq.h"
 #include "i915_reg.h"
@@ -14,12 +11,13 @@
 #include "intel_de.h"
 #include "intel_display_types.h"
 #include "intel_dsb.h"
+#include "intel_dsb_buffer.h"
 #include "intel_dsb_regs.h"
 #include "intel_vblank.h"
 #include "intel_vrr.h"
 #include "skl_watermark.h"
 
-struct i915_vma;
+#define CACHELINE_BYTES 64
 
 enum dsb_id {
INVALID_DSB = -1,
@@ -32,8 +30,7 @@ enum dsb_id {
 struct intel_dsb {
enum dsb_id id;
 
-   u32 *cmd_buf;
-   struct i915_vma *vma;
+   struct intel_dsb_buffer dsb_buf;
struct intel_crtc *crtc;
 
/*
@@ -109,15 +106,17 @@ static void intel_dsb_dump(struct intel_dsb *dsb)
 {
struct intel_crtc *crtc = dsb->crtc;
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
-   const u32 *buf = dsb->cmd_buf;
int i;
 
drm_dbg_kms(>drm, "[CRTC:%d:%s] DSB %d commands {\n",
crtc->base.base.id, crtc->base.name, dsb->id);
for (i = 0; i < ALIGN(dsb->free_pos, 64 / 4); i += 4)
drm_dbg_kms(>drm,
-   " 0x%08x: 0x%08x 0x%08x 0x%08x 0x%08x\n",
-   i * 4, buf[i], buf[i+1], buf[i+2], buf[i+3]);
+   " 0x%08x: 0x%08x 0x%08x 0x%08x 0x%08x\n", i * 4,
+   intel_dsb_buffer_read(>dsb_buf, i),
+   intel_dsb_buffer_read(>dsb_buf, i + 1),
+   intel_dsb_buffer_read(>dsb_buf, i + 2),
+   intel_dsb_buffer_read(>dsb_buf, i + 3));
drm_dbg_kms(>drm, "}\n");
 }
 
@@ -129,8 +128,6 @@ static bool is_dsb_busy(struct drm_i915_private *i915, enum 
pipe pipe,
 
 static void intel_dsb_emit(struct intel_dsb *dsb, u32 ldw, u32 udw)
 {
-   u32 *buf = dsb->cmd_buf;
-
if (!assert_dsb_has_room(dsb))
return;
 
@@ -139,14 +136,13 @@ static void intel_dsb_emit(struct intel_dsb *dsb, u32 
ldw, u32 udw)
 
dsb->ins_start_offset = dsb->free_pos;
 
-   buf[dsb->free_pos++] = ldw;
-   buf[dsb->free_pos++] = udw;
+   intel_dsb_buffer_write(>dsb_buf, dsb->free_pos++, ldw);
+   intel_dsb_buffer_write(>dsb_buf, dsb->free_pos++, udw);
 }
 
 static bool intel_dsb_prev_ins_is_write(struct intel_dsb *dsb,
u32 opcode, i915_reg_t reg)
 {
-   const u32 *buf = dsb->cmd_buf;
u32 prev_opcode, prev_reg;
 
/*
@@ -157,8 +153,10 @@ static bool intel_dsb_prev_ins_is_write(struct intel_dsb 
*dsb,
if (dsb->free_pos == 0)
return false;
 
-   prev_opcode = buf[dsb->ins_start_offset + 1] & ~DSB_REG_VALUE_MASK;
-   prev_reg = buf[dsb->ins_start_offset + 1] & DSB_REG_VALUE_MASK;
+   prev_opcode = intel_dsb_buffer_read(>dsb_buf,
+   dsb->ins_start_offset + 1) >> 
DSB_OPCODE_SHIFT;
+   prev_reg =  intel_dsb_buffer_read(>dsb_buf,
+ dsb->ins_start_offset + 1) & 
DSB_REG_VALUE_MASK;
 
return prev_opcode == opcode && prev_reg == i915_mmio_reg_offset(reg);
 }
@@ -191,6 +189,8 @@ static bool intel_dsb_prev_ins_is_indexed_wr

[Intel-gfx] [PATCH v7 6/6] drm/i915/panelreplay: Debugfs support for panel replay

2023-10-11 Thread Animesh Manna
Add debugfs support which will print source and sink status
per connector basis.

v1: Initial version. [rb-ed by Arun]
v2: Added check for DP 2.0 and connector type in connector_debugfs_add().

Cc: Jouni Högander 
Cc: Arun R Murthy 
Cc: Jani Nikula 
Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_psr.c | 136 +--
 1 file changed, 102 insertions(+), 34 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index 80de831c2f60..399fc0a8e636 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -2823,6 +2823,25 @@ static int psr_get_status_and_error_status(struct 
intel_dp *intel_dp,
return 0;
 }
 
+static int panel_replay_get_status_and_error_status(struct intel_dp *intel_dp,
+   u8 *status, u8 
*error_status)
+{
+   struct drm_dp_aux *aux = _dp->aux;
+   int ret;
+
+   ret = drm_dp_dpcd_readb(aux, DP_SINK_DEVICE_PR_AND_FRAME_LOCK_STATUS, 
status);
+   if (ret != 1)
+   return ret;
+
+   ret = drm_dp_dpcd_readb(aux, DP_PANEL_REPLAY_ERROR_STATUS, 
error_status);
+   if (ret != 1)
+   return ret;
+
+   *status = *status & DP_PSR_SINK_STATE_MASK;
+
+   return 0;
+}
+
 static void psr_alpm_check(struct intel_dp *intel_dp)
 {
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
@@ -3035,7 +3054,7 @@ psr_source_status(struct intel_dp *intel_dp, struct 
seq_file *m)
status = live_status[status_val];
}
 
-   seq_printf(m, "Source PSR status: %s [0x%08x]\n", status, val);
+   seq_printf(m, "Source PSR/PanelReplay status: %s [0x%08x]\n", status, 
val);
 }
 
 static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp)
@@ -3048,18 +3067,23 @@ static int intel_psr_status(struct seq_file *m, struct 
intel_dp *intel_dp)
bool enabled;
u32 val;
 
-   seq_printf(m, "Sink support: %s", str_yes_no(psr->sink_support));
-   if (psr->sink_support)
+   seq_printf(m, "Sink support: PSR = %s, Panel Replay = %s",
+  str_yes_no(psr->sink_support),
+  str_yes_no(psr->sink_panel_replay_support));
+
+   if (psr->sink_support || psr->sink_panel_replay_support)
seq_printf(m, " [0x%02x]", intel_dp->psr_dpcd[0]);
seq_puts(m, "\n");
 
-   if (!psr->sink_support)
+   if (!(psr->sink_support || psr->sink_panel_replay_support))
return 0;
 
wakeref = intel_runtime_pm_get(_priv->runtime_pm);
mutex_lock(>lock);
 
-   if (psr->enabled)
+   if (psr->panel_replay_enabled)
+   status = "Panel Replay Enabled";
+   else if (psr->enabled)
status = psr->psr2_enabled ? "PSR2 enabled" : "PSR1 enabled";
else
status = "disabled";
@@ -3072,14 +3096,17 @@ static int intel_psr_status(struct seq_file *m, struct 
intel_dp *intel_dp)
goto unlock;
}
 
-   if (psr->psr2_enabled) {
+   if (psr->panel_replay_enabled) {
+   val = intel_de_read(dev_priv, TRANS_DP2_CTL(cpu_transcoder));
+   enabled = val & TRANS_DP2_PANEL_REPLAY_ENABLE;
+   } else if (psr->psr2_enabled) {
val = intel_de_read(dev_priv, EDP_PSR2_CTL(cpu_transcoder));
enabled = val & EDP_PSR2_ENABLE;
} else {
val = intel_de_read(dev_priv, psr_ctl_reg(dev_priv, 
cpu_transcoder));
enabled = val & EDP_PSR_ENABLE;
}
-   seq_printf(m, "Source PSR ctl: %s [0x%08x]\n",
+   seq_printf(m, "Source PSR/PanelReplay ctl: %s [0x%08x]\n",
   str_enabled_disabled(enabled), val);
psr_source_status(intel_dp, m);
seq_printf(m, "Busy frontbuffer bits: 0x%08x\n",
@@ -3221,6 +3248,7 @@ static int i915_psr_sink_status_show(struct seq_file *m, 
void *data)
 {
struct intel_connector *connector = m->private;
struct intel_dp *intel_dp = intel_attached_dp(connector);
+   struct intel_psr *psr = _dp->psr;
static const char * const sink_status[] = {
"inactive",
"transition to active, capture and display",
@@ -3231,45 +3259,82 @@ static int i915_psr_sink_status_show(struct seq_file 
*m, void *data)
"reserved",
"sink internal error",
};
+   static const char * const panel_replay_status[] = {
+   "Sink device frame is locked to the Source device",
+   "Sink device is coasting, using the VTotal target",
+   "Sink device is governing the frame 

[Intel-gfx] [PATCH v7 5/6] drm/i915/panelreplay: enable/disable panel replay

2023-10-11 Thread Animesh Manna
TRANS_DP2_CTL register is programmed to enable panel replay from source
and sink is enabled through panel replay dpcd configuration address.

Bspec: 1407940617

v1: Initial version.
v2:
- Use pr_* flags instead psr_* flags. [Jouni]
- Remove intel_dp_is_edp check as edp1.5 also has panel replay. [Jouni]

v3: Cover letter updated and selective fetch condition check is added
before updating its bit in PSR2_MAN_TRK_CTL register. [Jouni]

v4: Selective fetch related PSR2_MAN_TRK_CTL programmming dropped. [Jouni]

v5: Added PSR2_MAN_TRK_CTL programming as needed for Continuous Full
Frame (CFF) update.

v6: Rebased on latest.

Note: Initial plan is to enable panel replay in  full-screen live active
frame update mode. In a incremental approach panel replay will be enabled
in selctive update mode if there is any gap in curent implementation.

Cc: Jouni Högander 
Cc: Arun R Murthy 
Cc: Jani Nikula 
Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_ddi.c  |  7 ++-
 .../drm/i915/display/intel_display_types.h|  1 +
 drivers/gpu/drm/i915/display/intel_psr.c  | 63 ++-
 3 files changed, 55 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
b/drivers/gpu/drm/i915/display/intel_ddi.c
index 9151d5add960..16f98a7a5f20 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -2717,10 +2717,15 @@ static void intel_ddi_pre_enable_dp(struct 
intel_atomic_state *state,
const struct drm_connector_state 
*conn_state)
 {
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+   struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 
-   if (HAS_DP20(dev_priv))
+   if (HAS_DP20(dev_priv)) {
intel_dp_128b132b_sdp_crc16(enc_to_intel_dp(encoder),
crtc_state);
+   if (crtc_state->has_panel_replay)
+   drm_dp_dpcd_writeb(_dp->aux, PANEL_REPLAY_CONFIG,
+  DP_PANEL_REPLAY_ENABLE);
+   }
 
if (DISPLAY_VER(dev_priv) >= 14)
mtl_ddi_pre_enable_dp(state, encoder, crtc_state, conn_state);
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index 95b318f7b2b8..d8f35054bc11 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1704,6 +1704,7 @@ struct intel_psr {
u16 su_y_granularity;
bool source_panel_replay_support;
bool sink_panel_replay_support;
+   bool panel_replay_enabled;
u32 dc3co_exitline;
u32 dc3co_exit_delay;
struct delayed_work dc3co_work;
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index a2e0637c53fb..80de831c2f60 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -608,8 +608,11 @@ static void intel_psr_enable_sink(struct intel_dp 
*intel_dp)
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
u8 dpcd_val = DP_PSR_ENABLE;
 
-   /* Enable ALPM at sink for psr2 */
+   if (intel_dp->psr.panel_replay_enabled)
+   return;
+
if (intel_dp->psr.psr2_enabled) {
+   /* Enable ALPM at sink for psr2 */
drm_dp_dpcd_writeb(_dp->aux, DP_RECEIVER_ALPM_CONFIG,
   DP_ALPM_ENABLE |
   DP_ALPM_LOCK_ERROR_IRQ_HPD_ENABLE);
@@ -759,6 +762,17 @@ static int psr2_block_count(struct intel_dp *intel_dp)
return psr2_block_count_lines(intel_dp) / 4;
 }
 
+static void dg2_activate_panel_replay(struct intel_dp *intel_dp)
+{
+   struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+
+   intel_de_rmw(dev_priv, PSR2_MAN_TRK_CTL(intel_dp->psr.transcoder),
+0, ADLP_PSR2_MAN_TRK_CTL_SF_CONTINUOS_FULL_FRAME);
+
+   intel_de_rmw(dev_priv, TRANS_DP2_CTL(intel_dp->psr.transcoder), 0,
+TRANS_DP2_PANEL_REPLAY_ENABLE);
+}
+
 static void hsw_activate_psr2(struct intel_dp *intel_dp)
 {
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
@@ -1323,18 +1337,23 @@ void intel_psr_get_config(struct intel_encoder *encoder,
return;
 
intel_dp = _port->dp;
-   if (!CAN_PSR(intel_dp))
+   if (!(CAN_PSR(intel_dp) || CAN_PANEL_REPLAY(intel_dp)))
return;
 
mutex_lock(_dp->psr.lock);
if (!intel_dp->psr.enabled)
goto unlock;
 
-   /*
-* Not possible to read EDP_PSR/PSR2_CTL registers as it is
-* enabled/disabled because of frontbuffer tracking and others.
-*/
-   pipe_config->has_psr = true;
+   if (intel_dp->psr.panel_replay_enabled) {
+   pipe_confi

[Intel-gfx] [PATCH v7 3/6] drm/i915/panelreplay: Initializaton and compute config for panel replay

2023-10-11 Thread Animesh Manna
Modify existing PSR implementation to enable panel replay feature of DP 2.0
which is similar to PSR feature of EDP panel. There is different DPCD
address to check panel capability compare to PSR and vsc sdp header
is different.

v1: Initial version.
v2:
- Set source_panel_replay_support flag under HAS_PANEL_REPLAY()
condition check. [Jouni]
- Code restructured around intel_panel_replay_init
and renamed to intel_panel_replay_init_dpcd. [Jouni]
- Remove the initial code modification around has_psr2 flag. [Jouni]
- Add CAN_PANEL_REPLAY() in intel_encoder_can_psr which is used to
enable in intel_psr_post_plane_update. [Jouni]
v3:
- Initialize both psr and panel-replay. [Jouni]
- Initialize both panel replay and psr if detected. [Jouni]
- Refactoring psr function by introducing _psr_compute_config(). [Jouni]
- Add check for !is_edp while deriving source_panel_replay_support. [Jouni]
- Enable panel replay dpcd initialization in a separate patch. [Jouni]

v4:
- HAS_PANEL_REPLAY() check not needed during sink capability check. [Jouni]
- Set either panel replay source support or psr. [Jouni]

v5:
- HAS_PANEL_REPLAY() removed and use HAS_DP20() instead. [Jouni]
- Move psr related code to intel_psr.c. [Jani]
- Reset sink_panel_replay_support flag during disconnection. [Jani]

v6: return statement restored which is removed by misatke. [Jouni]
v7: cosmetic changes. [Arun]

Cc: Jouni Högander 
Cc: Arun R Murthy 
Cc: Jani Nikula 
Signed-off-by: Animesh Manna 
---
 .../drm/i915/display/intel_display_types.h| 14 +--
 drivers/gpu/drm/i915/display/intel_dp.c   | 49 --
 drivers/gpu/drm/i915/display/intel_dp_mst.c   |  3 +
 drivers/gpu/drm/i915/display/intel_psr.c  | 96 ++-
 drivers/gpu/drm/i915/display/intel_psr.h  |  7 ++
 5 files changed, 123 insertions(+), 46 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index 8d8b2f8d37a9..95b318f7b2b8 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1204,6 +1204,7 @@ struct intel_crtc_state {
bool has_psr2;
bool enable_psr2_sel_fetch;
bool req_psr2_sdp_prior_scanline;
+   bool has_panel_replay;
bool wm_level_disabled;
u32 dc3co_exitline;
u16 su_y_granularity;
@@ -1701,6 +1702,8 @@ struct intel_psr {
bool irq_aux_error;
u16 su_w_granularity;
u16 su_y_granularity;
+   bool source_panel_replay_support;
+   bool sink_panel_replay_support;
u32 dc3co_exitline;
u32 dc3co_exit_delay;
struct delayed_work dc3co_work;
@@ -1988,17 +1991,6 @@ dp_to_lspcon(struct intel_dp *intel_dp)
 
 #define dp_to_i915(__intel_dp) 
to_i915(dp_to_dig_port(__intel_dp)->base.base.dev)
 
-#define CAN_PSR(intel_dp) ((intel_dp)->psr.sink_support && \
-  (intel_dp)->psr.source_support)
-
-static inline bool intel_encoder_can_psr(struct intel_encoder *encoder)
-{
-   if (!intel_encoder_is_dp(encoder))
-   return false;
-
-   return CAN_PSR(enc_to_intel_dp(encoder));
-}
-
 static inline struct intel_digital_port *
 hdmi_to_dig_port(struct intel_hdmi *intel_hdmi)
 {
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 0ef7cb8134b6..b038f1d2a7ad 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2432,12 +2432,22 @@ static void intel_dp_compute_vsc_colorimetry(const 
struct intel_crtc_state *crtc
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 
-   /*
-* Prepare VSC Header for SU as per DP 1.4 spec, Table 2-118
-* VSC SDP supporting 3D stereo, PSR2, and Pixel Encoding/
-* Colorimetry Format indication.
-*/
-   vsc->revision = 0x5;
+   if (crtc_state->has_panel_replay) {
+   /*
+* Prepare VSC Header for SU as per DP 2.0 spec, Table 2-223
+* VSC SDP supporting 3D stereo, Panel Replay, and Pixel
+* Encoding/Colorimetry Format indication.
+*/
+   vsc->revision = 0x7;
+   } else {
+   /*
+* Prepare VSC Header for SU as per DP 1.4 spec, Table 2-118
+* VSC SDP supporting 3D stereo, PSR2, and Pixel Encoding/
+* Colorimetry Format indication.
+*/
+   vsc->revision = 0x5;
+   }
+
vsc->length = 0x13;
 
/* DP 1.4a spec, Table 2-120 */
@@ -2546,6 +2556,21 @@ void intel_dp_compute_psr_vsc_sdp(struct intel_dp 
*intel_dp,
vsc->revision = 0x4;
vsc->length = 0xe;
}
+   } else if (crtc_state->has_panel_replay) {
+ 

[Intel-gfx] [PATCH v7 4/6] drm/i915/panelreplay: Enable panel replay dpcd initialization for DP

2023-10-11 Thread Animesh Manna
Due to similarity panel replay dpcd initialization got added in psr
function which is specific for edp panel. This patch enables panel
replay initialization for dp connector.

Cc: Jouni Högander 
Cc: Arun R Murthy 
Cc: Jani Nikula 
Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_psr.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index f9837001aa5f..a2e0637c53fb 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -2738,6 +2738,9 @@ void intel_psr_init(struct intel_dp *intel_dp)
if (!(HAS_PSR(dev_priv) || HAS_DP20(dev_priv)))
return;
 
+   if (!intel_dp_is_edp(intel_dp))
+   intel_psr_init_dpcd(intel_dp);
+
/*
 * HSW spec explicitly says PSR is tied to port A.
 * BDW+ platforms have a instance of PSR registers per transcoder but
-- 
2.29.0



[Intel-gfx] [PATCH v7 2/6] drm/i915/psr: Move psr specific dpcd init into own function

2023-10-11 Thread Animesh Manna
From: Jouni Högander 

This patch is preparing adding panel replay specific dpcd init.

Cc: Arun R Murthy 
Cc: Jani Nikula 
Reviewed-by: Arun R Murthy 
Signed-off-by: Jouni Högander 
---
 drivers/gpu/drm/i915/display/intel_psr.c | 41 +---
 1 file changed, 23 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index bb65881e87cc..0669ab7a9191 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -474,27 +474,22 @@ static void intel_dp_get_su_granularity(struct intel_dp 
*intel_dp)
intel_dp->psr.su_y_granularity = y;
 }
 
-void intel_psr_init_dpcd(struct intel_dp *intel_dp)
+static void _psr_init_dpcd(struct intel_dp *intel_dp)
 {
-   struct drm_i915_private *dev_priv =
+   struct drm_i915_private *i915 =
to_i915(dp_to_dig_port(intel_dp)->base.base.dev);
 
-   drm_dp_dpcd_read(_dp->aux, DP_PSR_SUPPORT, intel_dp->psr_dpcd,
-sizeof(intel_dp->psr_dpcd));
-
-   if (!intel_dp->psr_dpcd[0])
-   return;
-   drm_dbg_kms(_priv->drm, "eDP panel supports PSR version %x\n",
+   drm_dbg_kms(>drm, "eDP panel supports PSR version %x\n",
intel_dp->psr_dpcd[0]);
 
if (drm_dp_has_quirk(_dp->desc, DP_DPCD_QUIRK_NO_PSR)) {
-   drm_dbg_kms(_priv->drm,
+   drm_dbg_kms(>drm,
"PSR support not currently available for this 
panel\n");
return;
}
 
if (!(intel_dp->edp_dpcd[1] & DP_EDP_SET_POWER_CAP)) {
-   drm_dbg_kms(_priv->drm,
+   drm_dbg_kms(>drm,
"Panel lacks power state control, PSR cannot be 
enabled\n");
return;
}
@@ -503,8 +498,8 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp)
intel_dp->psr.sink_sync_latency =
intel_dp_get_sink_sync_latency(intel_dp);
 
-   if (DISPLAY_VER(dev_priv) >= 9 &&
-   (intel_dp->psr_dpcd[0] == DP_PSR2_WITH_Y_COORD_IS_SUPPORTED)) {
+   if (DISPLAY_VER(i915) >= 9 &&
+   intel_dp->psr_dpcd[0] == DP_PSR2_WITH_Y_COORD_IS_SUPPORTED) {
bool y_req = intel_dp->psr_dpcd[1] &
 DP_PSR2_SU_Y_COORDINATE_REQUIRED;
bool alpm = intel_dp_get_alpm_status(intel_dp);
@@ -521,14 +516,24 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp)
 * GTC first.
 */
intel_dp->psr.sink_psr2_support = y_req && alpm;
-   drm_dbg_kms(_priv->drm, "PSR2 %ssupported\n",
+   drm_dbg_kms(>drm, "PSR2 %ssupported\n",
intel_dp->psr.sink_psr2_support ? "" : "not ");
+   }
+}
 
-   if (intel_dp->psr.sink_psr2_support) {
-   intel_dp->psr.colorimetry_support =
-   intel_dp_get_colorimetry_status(intel_dp);
-   intel_dp_get_su_granularity(intel_dp);
-   }
+void intel_psr_init_dpcd(struct intel_dp *intel_dp)
+{
+   drm_dp_dpcd_read(_dp->aux, DP_PSR_SUPPORT, intel_dp->psr_dpcd,
+sizeof(intel_dp->psr_dpcd));
+
+   if (intel_dp->psr_dpcd[0])
+   _psr_init_dpcd(intel_dp);
+   /* TODO: Add PR case here */
+
+   if (intel_dp->psr.sink_psr2_support) {
+   intel_dp->psr.colorimetry_support =
+   intel_dp_get_colorimetry_status(intel_dp);
+   intel_dp_get_su_granularity(intel_dp);
}
 }
 
-- 
2.29.0



[Intel-gfx] [PATCH v7 0/6] Panel replay phase1 implementation

2023-10-11 Thread Animesh Manna
Panel Replay is a power saving feature for DP 2.0 monitor and similar
to PSR on EDP.

These patches are basic enablement patches added on top of
existing psr framework to enable full-screen live active frame
update mode of panel replay. Panel replay also can be enabled
in selective update mode which will be enabled in a incremental
approach.

As per current design panel replay priority is higher than psr.
intel_dp->psr.panel_replay_enabled flag indicate panel replay is enabled.
intel_dp->psr.panel_replay_enabled + intel_dp->psr.psr2_enabled indicates
panel replay is enabled in selective update mode.
intel_dp->psr.panel_replay_enabled + intel_dp->psr.psr2_enabled +
intel_psr.selective_fetch enabled indicates panel replay is
enabled in selective update mode with selective fetch.
PSR replated flags remain same like before.

Note: The patches are under testing by using panel replay emulator and
panel is not avalible.

Cc: Jouni Högander 
Cc: Arun R Murthy 
Cc: Jani Nikula 
Signed-off-by: Animesh Manna 

Animesh Manna (5):
  drm/panelreplay: dpcd register definition for panelreplay
  drm/i915/panelreplay: Initializaton and compute config for panel
replay
  drm/i915/panelreplay: Enable panel replay dpcd initialization for DP
  drm/i915/panelreplay: enable/disable panel replay
  drm/i915/panelreplay: Debugfs support for panel replay

Jouni Högander (1):
  drm/i915/psr: Move psr specific dpcd init into own function

 drivers/gpu/drm/i915/display/intel_ddi.c  |   7 +-
 .../drm/i915/display/intel_display_types.h|  15 +-
 drivers/gpu/drm/i915/display/intel_dp.c   |  49 ++-
 drivers/gpu/drm/i915/display/intel_dp_mst.c   |   3 +
 drivers/gpu/drm/i915/display/intel_psr.c  | 335 +-
 drivers/gpu/drm/i915/display/intel_psr.h  |   7 +
 include/drm/display/drm_dp.h  |  23 ++
 7 files changed, 327 insertions(+), 112 deletions(-)

-- 
2.29.0



[Intel-gfx] [PATCH v7 1/6] drm/panelreplay: dpcd register definition for panelreplay

2023-10-11 Thread Animesh Manna
Add DPCD register definition for discovering, enabling and
checking status of panel replay of the sink.

Cc: Jouni Högander 
Cc: Arun R Murthy 
Cc: Jani Nikula 
Reviewed-by: Arun R Murthy 
Signed-off-by: Animesh Manna 
---
 include/drm/display/drm_dp.h | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/include/drm/display/drm_dp.h b/include/drm/display/drm_dp.h
index e69cece404b3..fc42b622ef32 100644
--- a/include/drm/display/drm_dp.h
+++ b/include/drm/display/drm_dp.h
@@ -543,6 +543,10 @@
 /* DFP Capability Extension */
 #define DP_DFP_CAPABILITY_EXTENSION_SUPPORT0x0a3   /* 2.0 */
 
+#define DP_PANEL_REPLAY_CAP 0x0b0  /* DP 2.0 */
+# define DP_PANEL_REPLAY_SUPPORT(1 << 0)
+# define DP_PANEL_REPLAY_SU_SUPPORT (1 << 1)
+
 /* Link Configuration */
 #defineDP_LINK_BW_SET  0x100
 # define DP_LINK_RATE_TABLE0x00/* eDP 1.4 */
@@ -716,6 +720,13 @@
 #define DP_BRANCH_DEVICE_CTRL  0x1a1
 # define DP_BRANCH_DEVICE_IRQ_HPD  (1 << 0)
 
+#define PANEL_REPLAY_CONFIG 0x1b0  /* DP 2.0 */
+# define DP_PANEL_REPLAY_ENABLE (1 << 0)
+# define DP_PANEL_REPLAY_UNRECOVERABLE_ERROR_EN (1 << 3)
+# define DP_PANEL_REPLAY_RFB_STORAGE_ERROR_EN   (1 << 4)
+# define DP_PANEL_REPLAY_ACTIVE_FRAME_CRC_ERROR_EN  (1 << 5)
+# define DP_PANEL_REPLAY_SU_ENABLE  (1 << 6)
+
 #define DP_PAYLOAD_ALLOCATE_SET0x1c0
 #define DP_PAYLOAD_ALLOCATE_START_TIME_SLOT 0x1c1
 #define DP_PAYLOAD_ALLOCATE_TIME_SLOT_COUNT 0x1c2
@@ -1105,6 +1116,18 @@
 #define DP_LANE_ALIGN_STATUS_UPDATED_ESI   0x200e /* status same as 0x204 
*/
 #define DP_SINK_STATUS_ESI 0x200f /* status same as 0x205 
*/
 
+#define DP_PANEL_REPLAY_ERROR_STATUS   0x2020  /* DP 2.1*/
+# define DP_PANEL_REPLAY_LINK_CRC_ERROR(1 << 0)
+# define DP_PANEL_REPLAY_RFB_STORAGE_ERROR (1 << 1)
+# define DP_PANEL_REPLAY_VSC_SDP_UNCORRECTABLE_ERROR   (1 << 2)
+
+#define DP_SINK_DEVICE_PR_AND_FRAME_LOCK_STATUS0x2022  /* DP 2.1 */
+# define DP_SINK_DEVICE_PANEL_REPLAY_STATUS_MASK   (7 << 0)
+# define DP_SINK_FRAME_LOCKED_SHIFT3
+# define DP_SINK_FRAME_LOCKED_MASK (3 << 3)
+# define DP_SINK_FRAME_LOCKED_STATUS_VALID_SHIFT   5
+# define DP_SINK_FRAME_LOCKED_STATUS_VALID_MASK(1 << 5)
+
 /* Extended Receiver Capability: See DP_DPCD_REV for definitions */
 #define DP_DP13_DPCD_REV0x2200
 
-- 
2.29.0



[Intel-gfx] [PATCH v3] drm/i915/dsb: DSB code refactoring

2023-10-08 Thread Animesh Manna
Refactor DSB implementation to be compatible with Xe driver.

v1: RFC version.
v2: Make intel_dsb structure opaque from external usage. [Jani]
v3: Rebased on latest.

Cc: Jani Nikula 
Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/Makefile |  1 +
 drivers/gpu/drm/i915/display/intel_dsb.c  | 84 ---
 .../gpu/drm/i915/display/intel_dsb_buffer.c   | 64 ++
 .../gpu/drm/i915/display/intel_dsb_buffer.h   | 26 ++
 4 files changed, 126 insertions(+), 49 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_dsb_buffer.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_dsb_buffer.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index dec78efa452a..7c3f91c2375a 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -260,6 +260,7 @@ i915-y += \
display/intel_dpt.o \
display/intel_drrs.o \
display/intel_dsb.o \
+   display/intel_dsb_buffer.o \
display/intel_fb.o \
display/intel_fb_pin.o \
display/intel_fbc.o \
diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c 
b/drivers/gpu/drm/i915/display/intel_dsb.c
index 3e32aa49b8eb..ec89d968a873 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.c
+++ b/drivers/gpu/drm/i915/display/intel_dsb.c
@@ -13,12 +13,13 @@
 #include "intel_de.h"
 #include "intel_display_types.h"
 #include "intel_dsb.h"
+#include "intel_dsb_buffer.h"
 #include "intel_dsb_regs.h"
 #include "intel_vblank.h"
 #include "intel_vrr.h"
 #include "skl_watermark.h"
 
-struct i915_vma;
+#define CACHELINE_BYTES 64
 
 enum dsb_id {
INVALID_DSB = -1,
@@ -31,8 +32,7 @@ enum dsb_id {
 struct intel_dsb {
enum dsb_id id;
 
-   u32 *cmd_buf;
-   struct i915_vma *vma;
+   struct intel_dsb_buffer dsb_buf;
struct intel_crtc *crtc;
 
/*
@@ -108,15 +108,17 @@ static void intel_dsb_dump(struct intel_dsb *dsb)
 {
struct intel_crtc *crtc = dsb->crtc;
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
-   const u32 *buf = dsb->cmd_buf;
int i;
 
drm_dbg_kms(>drm, "[CRTC:%d:%s] DSB %d commands {\n",
crtc->base.base.id, crtc->base.name, dsb->id);
for (i = 0; i < ALIGN(dsb->free_pos, 64 / 4); i += 4)
drm_dbg_kms(>drm,
-   " 0x%08x: 0x%08x 0x%08x 0x%08x 0x%08x\n",
-   i * 4, buf[i], buf[i+1], buf[i+2], buf[i+3]);
+   " 0x%08x: 0x%08x 0x%08x 0x%08x 0x%08x\n", i * 4,
+   intel_dsb_buffer_read(>dsb_buf, i),
+   intel_dsb_buffer_read(>dsb_buf, i + 1),
+   intel_dsb_buffer_read(>dsb_buf, i + 2),
+   intel_dsb_buffer_read(>dsb_buf, i + 3));
drm_dbg_kms(>drm, "}\n");
 }
 
@@ -128,8 +130,6 @@ static bool is_dsb_busy(struct drm_i915_private *i915, enum 
pipe pipe,
 
 static void intel_dsb_emit(struct intel_dsb *dsb, u32 ldw, u32 udw)
 {
-   u32 *buf = dsb->cmd_buf;
-
if (!assert_dsb_has_room(dsb))
return;
 
@@ -138,14 +138,13 @@ static void intel_dsb_emit(struct intel_dsb *dsb, u32 
ldw, u32 udw)
 
dsb->ins_start_offset = dsb->free_pos;
 
-   buf[dsb->free_pos++] = ldw;
-   buf[dsb->free_pos++] = udw;
+   intel_dsb_buffer_write(>dsb_buf, dsb->free_pos++, ldw);
+   intel_dsb_buffer_write(>dsb_buf, dsb->free_pos++, udw);
 }
 
 static bool intel_dsb_prev_ins_is_write(struct intel_dsb *dsb,
u32 opcode, i915_reg_t reg)
 {
-   const u32 *buf = dsb->cmd_buf;
u32 prev_opcode, prev_reg;
 
/*
@@ -156,8 +155,10 @@ static bool intel_dsb_prev_ins_is_write(struct intel_dsb 
*dsb,
if (dsb->free_pos == 0)
return false;
 
-   prev_opcode = buf[dsb->ins_start_offset + 1] & ~DSB_REG_VALUE_MASK;
-   prev_reg = buf[dsb->ins_start_offset + 1] & DSB_REG_VALUE_MASK;
+   prev_opcode = intel_dsb_buffer_read(>dsb_buf,
+   dsb->ins_start_offset + 1) >> 
DSB_OPCODE_SHIFT;
+   prev_reg =  intel_dsb_buffer_read(>dsb_buf,
+ dsb->ins_start_offset + 1) & 
DSB_REG_VALUE_MASK;
 
return prev_opcode == opcode && prev_reg == i915_mmio_reg_offset(reg);
 }
@@ -190,6 +191,8 @@ static bool intel_dsb_prev_ins_is_indexed_write(struct 
intel_dsb *dsb, i915_reg_
 void intel_dsb_reg_write(struct intel_dsb *dsb,
 i915_reg_t reg, u32 val)
 {
+   u32 old_val;
+
/*
 * For example the buffer will look like below for 3 dwords for auto
 * increment register:
@@ -213,31 

[Intel-gfx] [PATCH] drm/i915: Add wrapper for getiing display step

2023-09-27 Thread Animesh Manna
From: Chaitanya Kumar Borah 

Add a wrapper around intel_step_name to maintain compatibility with xe
driver. The wrapper will share the same name as the one to be used by
xe while both drivers include different files as needed during
compilation.

Signed-off-by: Chaitanya Kumar Borah 
Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_dmc.c | 2 +-
 drivers/gpu/drm/i915/intel_step.c| 5 +
 drivers/gpu/drm/i915/intel_step.h| 1 +
 3 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c 
b/drivers/gpu/drm/i915/display/intel_dmc.c
index 1623c0c5e8a1..0b2c38957c32 100644
--- a/drivers/gpu/drm/i915/display/intel_dmc.c
+++ b/drivers/gpu/drm/i915/display/intel_dmc.c
@@ -309,7 +309,7 @@ static const struct stepping_info *
 intel_get_stepping_info(struct drm_i915_private *i915,
struct stepping_info *si)
 {
-   const char *step_name = 
intel_step_name(RUNTIME_INFO(i915)->step.display_step);
+   const char *step_name = intel_step_display_name(i915);
 
si->stepping = step_name[0];
si->substepping = step_name[1];
diff --git a/drivers/gpu/drm/i915/intel_step.c 
b/drivers/gpu/drm/i915/intel_step.c
index ee4e5a2c0220..3914cf9970b3 100644
--- a/drivers/gpu/drm/i915/intel_step.c
+++ b/drivers/gpu/drm/i915/intel_step.c
@@ -353,3 +353,8 @@ const char *intel_step_name(enum intel_step step)
return "**";
}
 }
+
+const char *intel_step_display_name(struct drm_i915_private *i915)
+{
+   return intel_step_name(RUNTIME_INFO(i915)->step.display_step);
+}
diff --git a/drivers/gpu/drm/i915/intel_step.h 
b/drivers/gpu/drm/i915/intel_step.h
index 96dfca4cba73..26795302cdd8 100644
--- a/drivers/gpu/drm/i915/intel_step.h
+++ b/drivers/gpu/drm/i915/intel_step.h
@@ -78,5 +78,6 @@ enum intel_step {
 
 void intel_step_init(struct drm_i915_private *i915);
 const char *intel_step_name(enum intel_step step);
+const char *intel_step_display_name(struct drm_i915_private *i915);
 
 #endif /* __INTEL_STEP_H__ */
-- 
2.29.0



[Intel-gfx] [PATCH] drm/i915/dsb: DSB code refactoring

2023-09-27 Thread Animesh Manna
Refactor DSB implementation to be compatible with Xe driver.

v1: RFC version.
v2: Make intel_dsb structure opaque from external usage. [Jani]

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/Makefile |  1 +
 drivers/gpu/drm/i915/display/intel_dsb.c  | 82 +++
 .../gpu/drm/i915/display/intel_dsb_buffer.c   | 64 +++
 .../gpu/drm/i915/display/intel_dsb_buffer.h   | 21 +
 4 files changed, 117 insertions(+), 51 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_dsb_buffer.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_dsb_buffer.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 1b2e02e9d92c..c86b49d7f1aa 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -256,6 +256,7 @@ i915-y += \
display/intel_dpt.o \
display/intel_drrs.o \
display/intel_dsb.o \
+   display/intel_dsb_buffer.o \
display/intel_fb.o \
display/intel_fb_pin.o \
display/intel_fbc.o \
diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c 
b/drivers/gpu/drm/i915/display/intel_dsb.c
index 9a507b9ad82c..55d9499bf3de 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.c
+++ b/drivers/gpu/drm/i915/display/intel_dsb.c
@@ -4,16 +4,15 @@
  *
  */
 
-#include "gem/i915_gem_internal.h"
-
 #include "i915_drv.h"
 #include "i915_reg.h"
 #include "intel_de.h"
 #include "intel_display_types.h"
 #include "intel_dsb.h"
 #include "intel_dsb_regs.h"
+#include "intel_dsb_buffer.h"
 
-struct i915_vma;
+#define CACHELINE_BYTES 64
 
 enum dsb_id {
INVALID_DSB = -1,
@@ -26,8 +25,7 @@ enum dsb_id {
 struct intel_dsb {
enum dsb_id id;
 
-   u32 *cmd_buf;
-   struct i915_vma *vma;
+   struct intel_dsb_buffer dsb_buf;
struct intel_crtc *crtc;
 
/*
@@ -97,15 +95,17 @@ static void intel_dsb_dump(struct intel_dsb *dsb)
 {
struct intel_crtc *crtc = dsb->crtc;
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
-   const u32 *buf = dsb->cmd_buf;
int i;
 
drm_dbg_kms(>drm, "[CRTC:%d:%s] DSB %d commands {\n",
crtc->base.base.id, crtc->base.name, dsb->id);
for (i = 0; i < ALIGN(dsb->free_pos, 64 / 4); i += 4)
drm_dbg_kms(>drm,
-   " 0x%08x: 0x%08x 0x%08x 0x%08x 0x%08x\n",
-   i * 4, buf[i], buf[i+1], buf[i+2], buf[i+3]);
+   " 0x%08x: 0x%08x 0x%08x 0x%08x 0x%08x\n", i * 4,
+   intel_dsb_buffer_read(>dsb_buf, i),
+   intel_dsb_buffer_read(>dsb_buf, i + 1),
+   intel_dsb_buffer_read(>dsb_buf, i + 2),
+   intel_dsb_buffer_read(>dsb_buf, i + 3));
drm_dbg_kms(>drm, "}\n");
 }
 
@@ -117,8 +117,6 @@ static bool is_dsb_busy(struct drm_i915_private *i915, enum 
pipe pipe,
 
 static void intel_dsb_emit(struct intel_dsb *dsb, u32 ldw, u32 udw)
 {
-   u32 *buf = dsb->cmd_buf;
-
if (!assert_dsb_has_room(dsb))
return;
 
@@ -127,14 +125,13 @@ static void intel_dsb_emit(struct intel_dsb *dsb, u32 
ldw, u32 udw)
 
dsb->ins_start_offset = dsb->free_pos;
 
-   buf[dsb->free_pos++] = ldw;
-   buf[dsb->free_pos++] = udw;
+   intel_dsb_buffer_write(>dsb_buf, dsb->free_pos++, ldw);
+   intel_dsb_buffer_write(>dsb_buf, dsb->free_pos++, udw);
 }
 
 static bool intel_dsb_prev_ins_is_write(struct intel_dsb *dsb,
u32 opcode, i915_reg_t reg)
 {
-   const u32 *buf = dsb->cmd_buf;
u32 prev_opcode, prev_reg;
 
/*
@@ -145,8 +142,8 @@ static bool intel_dsb_prev_ins_is_write(struct intel_dsb 
*dsb,
if (dsb->free_pos == 0)
return false;
 
-   prev_opcode = buf[dsb->ins_start_offset + 1] & ~DSB_REG_VALUE_MASK;
-   prev_reg = buf[dsb->ins_start_offset + 1] & DSB_REG_VALUE_MASK;
+   prev_opcode = intel_dsb_buffer_read(>dsb_buf, 
dsb->ins_start_offset + 1) >> DSB_OPCODE_SHIFT;
+   prev_reg =  intel_dsb_buffer_read(>dsb_buf, dsb->ins_start_offset 
+ 1) & DSB_REG_VALUE_MASK;
 
return prev_opcode == opcode && prev_reg == i915_mmio_reg_offset(reg);
 }
@@ -179,6 +176,8 @@ static bool intel_dsb_prev_ins_is_indexed_write(struct 
intel_dsb *dsb, i915_reg_
 void intel_dsb_reg_write(struct intel_dsb *dsb,
 i915_reg_t reg, u32 val)
 {
+   u32 old_val;
+
/*
 * For example the buffer will look like below for 3 dwords for auto
 * increment register:
@@ -202,31 +201,30 @@ void intel_dsb_reg_write(struct intel_dsb *dsb,
   (DSB_BYTE_EN << DSB_BYTE_EN_SHIF

[Intel-gfx] [PATCH] drm/i915/dsb: DSB code refactoring

2023-09-22 Thread Animesh Manna
Refactor DSB implementation to be compatible with Xe driver.

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/Makefile|   1 +
 drivers/gpu/drm/i915/display/intel_dsb.c | 115 ---
 drivers/gpu/drm/i915/display/intel_dsb.h |  41 ++-
 drivers/gpu/drm/i915/display/intel_dsb_ops.c |  67 +++
 4 files changed, 130 insertions(+), 94 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_dsb_ops.c

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 1b2e02e9d92c..7fbb5055b85b 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -256,6 +256,7 @@ i915-y += \
display/intel_dpt.o \
display/intel_drrs.o \
display/intel_dsb.o \
+   display/intel_dsb_ops.o \
display/intel_fb.o \
display/intel_fb_pin.o \
display/intel_fbc.o \
diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c 
b/drivers/gpu/drm/i915/display/intel_dsb.c
index 9a507b9ad82c..f7c6b9aa130f 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.c
+++ b/drivers/gpu/drm/i915/display/intel_dsb.c
@@ -4,8 +4,6 @@
  *
  */
 
-#include "gem/i915_gem_internal.h"
-
 #include "i915_drv.h"
 #include "i915_reg.h"
 #include "intel_de.h"
@@ -13,41 +11,7 @@
 #include "intel_dsb.h"
 #include "intel_dsb_regs.h"
 
-struct i915_vma;
-
-enum dsb_id {
-   INVALID_DSB = -1,
-   DSB1,
-   DSB2,
-   DSB3,
-   MAX_DSB_PER_PIPE
-};
-
-struct intel_dsb {
-   enum dsb_id id;
-
-   u32 *cmd_buf;
-   struct i915_vma *vma;
-   struct intel_crtc *crtc;
-
-   /*
-* maximum number of dwords the buffer will hold.
-*/
-   unsigned int size;
-
-   /*
-* free_pos will point the first free dword and
-* help in calculating tail of command buffer.
-*/
-   unsigned int free_pos;
-
-   /*
-* ins_start_offset will help to store start dword of the dsb
-* instuction and help in identifying the batch of auto-increment
-* register.
-*/
-   unsigned int ins_start_offset;
-};
+#define CACHELINE_BYTES 64
 
 /**
  * DOC: DSB
@@ -117,8 +81,6 @@ static bool is_dsb_busy(struct drm_i915_private *i915, enum 
pipe pipe,
 
 static void intel_dsb_emit(struct intel_dsb *dsb, u32 ldw, u32 udw)
 {
-   u32 *buf = dsb->cmd_buf;
-
if (!assert_dsb_has_room(dsb))
return;
 
@@ -127,14 +89,13 @@ static void intel_dsb_emit(struct intel_dsb *dsb, u32 ldw, 
u32 udw)
 
dsb->ins_start_offset = dsb->free_pos;
 
-   buf[dsb->free_pos++] = ldw;
-   buf[dsb->free_pos++] = udw;
+   intel_dsb_write(dsb, dsb->free_pos++, ldw);
+   intel_dsb_write(dsb, dsb->free_pos++, udw);
 }
 
 static bool intel_dsb_prev_ins_is_write(struct intel_dsb *dsb,
u32 opcode, i915_reg_t reg)
 {
-   const u32 *buf = dsb->cmd_buf;
u32 prev_opcode, prev_reg;
 
/*
@@ -145,8 +106,8 @@ static bool intel_dsb_prev_ins_is_write(struct intel_dsb 
*dsb,
if (dsb->free_pos == 0)
return false;
 
-   prev_opcode = buf[dsb->ins_start_offset + 1] & ~DSB_REG_VALUE_MASK;
-   prev_reg = buf[dsb->ins_start_offset + 1] & DSB_REG_VALUE_MASK;
+   prev_opcode = intel_dsb_read(dsb, dsb->ins_start_offset + 1) >> 
DSB_OPCODE_SHIFT;
+   prev_reg =  intel_dsb_read(dsb, dsb->ins_start_offset + 1) & 
DSB_REG_VALUE_MASK;
 
return prev_opcode == opcode && prev_reg == i915_mmio_reg_offset(reg);
 }
@@ -179,6 +140,8 @@ static bool intel_dsb_prev_ins_is_indexed_write(struct 
intel_dsb *dsb, i915_reg_
 void intel_dsb_reg_write(struct intel_dsb *dsb,
 i915_reg_t reg, u32 val)
 {
+   u32 old_val;
+
/*
 * For example the buffer will look like below for 3 dwords for auto
 * increment register:
@@ -202,31 +165,30 @@ void intel_dsb_reg_write(struct intel_dsb *dsb,
   (DSB_BYTE_EN << DSB_BYTE_EN_SHIFT) |
   i915_mmio_reg_offset(reg));
} else {
-   u32 *buf = dsb->cmd_buf;
-
if (!assert_dsb_has_room(dsb))
return;
 
/* convert to indexed write? */
if (intel_dsb_prev_ins_is_mmio_write(dsb, reg)) {
-   u32 prev_val = buf[dsb->ins_start_offset + 0];
+   u32 prev_val = intel_dsb_read(dsb, 
dsb->ins_start_offset + 0);
 
-   buf[dsb->ins_start_offset + 0] = 1; /* count */
-   buf[dsb->ins_start_offset + 1] =
-   (DSB_OPCODE_INDEXED_WRITE << DSB_OPCODE_SHIFT) |
-   i915_mmio_reg_offset(reg);
-   buf[dsb->ins_start_offset + 2] = prev_val;
+   

[Intel-gfx] [PATCH v6 6/6] drm/i915/panelreplay: Debugfs support for panel replay

2023-09-21 Thread Animesh Manna
Add debugfs support which will print source and sink status
per connector basis.

Cc: Jouni Högander 
Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_psr.c | 132 +--
 1 file changed, 97 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index 67337b4a421b..65f22e4ff3b2 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -2834,6 +2834,25 @@ static int psr_get_status_and_error_status(struct 
intel_dp *intel_dp,
return 0;
 }
 
+static int panel_replay_get_status_and_error_status(struct intel_dp *intel_dp,
+   u8 *status, u8 
*error_status)
+{
+   struct drm_dp_aux *aux = _dp->aux;
+   int ret;
+
+   ret = drm_dp_dpcd_readb(aux, DP_SINK_DEVICE_PR_AND_FRAME_LOCK_STATUS, 
status);
+   if (ret != 1)
+   return ret;
+
+   ret = drm_dp_dpcd_readb(aux, DP_PANEL_REPLAY_ERROR_STATUS, 
error_status);
+   if (ret != 1)
+   return ret;
+
+   *status = *status & DP_PSR_SINK_STATE_MASK;
+
+   return 0;
+}
+
 static void psr_alpm_check(struct intel_dp *intel_dp)
 {
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
@@ -3046,7 +3065,7 @@ psr_source_status(struct intel_dp *intel_dp, struct 
seq_file *m)
status = live_status[status_val];
}
 
-   seq_printf(m, "Source PSR status: %s [0x%08x]\n", status, val);
+   seq_printf(m, "Source PSR/PanelReplay status: %s [0x%08x]\n", status, 
val);
 }
 
 static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp)
@@ -3059,18 +3078,23 @@ static int intel_psr_status(struct seq_file *m, struct 
intel_dp *intel_dp)
bool enabled;
u32 val;
 
-   seq_printf(m, "Sink support: %s", str_yes_no(psr->sink_support));
-   if (psr->sink_support)
+   seq_printf(m, "Sink support: PSR = %s, Panel Replay = %s",
+  str_yes_no(psr->sink_support),
+  str_yes_no(psr->sink_panel_replay_support));
+
+   if (psr->sink_support || psr->sink_panel_replay_support)
seq_printf(m, " [0x%02x]", intel_dp->psr_dpcd[0]);
seq_puts(m, "\n");
 
-   if (!psr->sink_support)
+   if (!(psr->sink_support || psr->sink_panel_replay_support))
return 0;
 
wakeref = intel_runtime_pm_get(_priv->runtime_pm);
mutex_lock(>lock);
 
-   if (psr->enabled)
+   if (psr->panel_replay_enabled)
+   status = "Panel Replay Enabled";
+   else if (psr->enabled)
status = psr->psr2_enabled ? "PSR2 enabled" : "PSR1 enabled";
else
status = "disabled";
@@ -3083,14 +3107,17 @@ static int intel_psr_status(struct seq_file *m, struct 
intel_dp *intel_dp)
goto unlock;
}
 
-   if (psr->psr2_enabled) {
+   if (psr->panel_replay_enabled) {
+   val = intel_de_read(dev_priv, TRANS_DP2_CTL(cpu_transcoder));
+   enabled = val & TRANS_DP2_PANEL_REPLAY_ENABLE;
+   } else if (psr->psr2_enabled) {
val = intel_de_read(dev_priv, EDP_PSR2_CTL(cpu_transcoder));
enabled = val & EDP_PSR2_ENABLE;
} else {
val = intel_de_read(dev_priv, psr_ctl_reg(dev_priv, 
cpu_transcoder));
enabled = val & EDP_PSR_ENABLE;
}
-   seq_printf(m, "Source PSR ctl: %s [0x%08x]\n",
+   seq_printf(m, "Source PSR/PanelReplay ctl: %s [0x%08x]\n",
   str_enabled_disabled(enabled), val);
psr_source_status(intel_dp, m);
seq_printf(m, "Busy frontbuffer bits: 0x%08x\n",
@@ -3232,6 +3259,7 @@ static int i915_psr_sink_status_show(struct seq_file *m, 
void *data)
 {
struct intel_connector *connector = m->private;
struct intel_dp *intel_dp = intel_attached_dp(connector);
+   struct intel_psr *psr = _dp->psr;
static const char * const sink_status[] = {
"inactive",
"transition to active, capture and display",
@@ -3242,45 +3270,82 @@ static int i915_psr_sink_status_show(struct seq_file 
*m, void *data)
"reserved",
"sink internal error",
};
+   static const char * const panel_replay_status[] = {
+   "Sink device frame is locked to the Source device",
+   "Sink device is coasting, using the VTotal target",
+   "Sink device is governing the frame rate (frame rate unlock is 
granted)",
+   "Sink device in the process of re-locking with the Source 
device",
+

[Intel-gfx] [PATCH v6 5/6] drm/i915/panelreplay: enable/disable panel replay

2023-09-21 Thread Animesh Manna
TRANS_DP2_CTL register is programmed to enable panel replay from source
and sink is enabled through panel replay dpcd configuration address.

Bspec: 1407940617

v1: Initial version.
v2:
- Use pr_* flags instead psr_* flags. [Jouni]
- Remove intel_dp_is_edp check as edp1.5 also has panel replay. [Jouni]

v3: Cover letter updated and selective fetch condition check is added
before updating its bit in PSR2_MAN_TRK_CTL register. [Jouni]

v4: Selective fetch related PSR2_MAN_TRK_CTL programmming dropped. [Jouni]

v5: Added PSR2_MAN_TRK_CTL programming as needed for Continuous Full
Frame (CFF) update.

Note: Initial plan is to enable panel replay in  full-screen live active
frame update mode. In a incremental approach panel replay will be enabled
in selctive update mode if there is any gap in curent implementation.

Cc: Jouni Högander 
Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_ddi.c  |  7 +-
 .../drm/i915/display/intel_display_types.h|  1 +
 drivers/gpu/drm/i915/display/intel_psr.c  | 65 ++-
 3 files changed, 56 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
b/drivers/gpu/drm/i915/display/intel_ddi.c
index 4668de45d6fe..203c56c5e208 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -2717,10 +2717,15 @@ static void intel_ddi_pre_enable_dp(struct 
intel_atomic_state *state,
const struct drm_connector_state 
*conn_state)
 {
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+   struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 
-   if (HAS_DP20(dev_priv))
+   if (HAS_DP20(dev_priv)) {
intel_dp_128b132b_sdp_crc16(enc_to_intel_dp(encoder),
crtc_state);
+   if (crtc_state->has_panel_replay)
+   drm_dp_dpcd_writeb(_dp->aux, PANEL_REPLAY_CONFIG,
+  DP_PANEL_REPLAY_ENABLE);
+   }
 
if (DISPLAY_VER(dev_priv) >= 14)
mtl_ddi_pre_enable_dp(state, encoder, crtc_state, conn_state);
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index 3eadd8e12f63..1cf302e9deed 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1698,6 +1698,7 @@ struct intel_psr {
u16 su_y_granularity;
bool source_panel_replay_support;
bool sink_panel_replay_support;
+   bool panel_replay_enabled;
u32 dc3co_exitline;
u32 dc3co_exit_delay;
struct delayed_work dc3co_work;
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index a59f13c29c3d..67337b4a421b 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -607,8 +607,11 @@ static void intel_psr_enable_sink(struct intel_dp 
*intel_dp)
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
u8 dpcd_val = DP_PSR_ENABLE;
 
-   /* Enable ALPM at sink for psr2 */
+   if (intel_dp->psr.panel_replay_enabled)
+   return;
+
if (intel_dp->psr.psr2_enabled) {
+   /* Enable ALPM at sink for psr2 */
drm_dp_dpcd_writeb(_dp->aux, DP_RECEIVER_ALPM_CONFIG,
   DP_ALPM_ENABLE |
   DP_ALPM_LOCK_ERROR_IRQ_HPD_ENABLE);
@@ -758,6 +761,17 @@ static int psr2_block_count(struct intel_dp *intel_dp)
return psr2_block_count_lines(intel_dp) / 4;
 }
 
+static void dg2_activate_panel_replay(struct intel_dp *intel_dp)
+{
+   struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+
+   intel_de_rmw(dev_priv, PSR2_MAN_TRK_CTL(intel_dp->psr.transcoder),
+0, ADLP_PSR2_MAN_TRK_CTL_SF_CONTINUOS_FULL_FRAME);
+
+   intel_de_rmw(dev_priv, TRANS_DP2_CTL(intel_dp->psr.transcoder), 0,
+TRANS_DP2_PANEL_REPLAY_ENABLE);
+}
+
 static void hsw_activate_psr2(struct intel_dp *intel_dp)
 {
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
@@ -1322,18 +1336,23 @@ void intel_psr_get_config(struct intel_encoder *encoder,
return;
 
intel_dp = _port->dp;
-   if (!CAN_PSR(intel_dp))
+   if (!(CAN_PSR(intel_dp) || CAN_PANEL_REPLAY(intel_dp)))
return;
 
mutex_lock(_dp->psr.lock);
if (!intel_dp->psr.enabled)
goto unlock;
 
-   /*
-* Not possible to read EDP_PSR/PSR2_CTL registers as it is
-* enabled/disabled because of frontbuffer tracking and others.
-*/
-   pipe_config->has_psr = true;
+   if (intel_dp->psr.panel_replay_enabled) {
+   pipe_config->has_panel_replay = true;
+   } else {
+   /*
+  

[Intel-gfx] [PATCH v6 4/6] drm/i915/panelreplay: Enable panel replay dpcd initialization for DP

2023-09-21 Thread Animesh Manna
Due to similarity panel replay dpcd initialization got added in psr
function which is specific for edp panel. This patch enables panel
replay initialization for dp connector.

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_psr.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index 2427bd5cb7ca..a59f13c29c3d 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -2749,6 +2749,9 @@ void intel_psr_init(struct intel_dp *intel_dp)
if (!(HAS_PSR(dev_priv) || HAS_DP20(dev_priv)))
return;
 
+   if (!intel_dp_is_edp(intel_dp))
+   intel_psr_init_dpcd(intel_dp);
+
/*
 * HSW spec explicitly says PSR is tied to port A.
 * BDW+ platforms have a instance of PSR registers per transcoder but
-- 
2.29.0



[Intel-gfx] [PATCH v6 3/6] drm/i915/panelreplay: Initializaton and compute config for panel replay

2023-09-21 Thread Animesh Manna
Modify existing PSR implementation to enable panel replay feature of DP 2.0
which is similar to PSR feature of EDP panel. There is different DPCD
address to check panel capability compare to PSR and vsc sdp header
is different.

v1: Initial version.
v2:
- Set source_panel_replay_support flag under HAS_PANEL_REPLAY()
condition check. [Jouni]
- Code restructured around intel_panel_replay_init
and renamed to intel_panel_replay_init_dpcd. [Jouni]
- Remove the initial code modification around has_psr2 flag. [Jouni]
- Add CAN_PANEL_REPLAY() in intel_encoder_can_psr which is used to
enable in intel_psr_post_plane_update. [Jouni]
v3:
- Initialize both psr and panel-replay. [Jouni]
- Initialize both panel replay and psr if detected. [Jouni]
- Refactoring psr function by introducing _psr_compute_config(). [Jouni]
- Add check for !is_edp while deriving source_panel_replay_support. [Jouni]
- Enable panel replay dpcd initialization in a separate patch. [Jouni]

v4:
- HAS_PANEL_REPLAY() check not needed during sink capability check. [Jouni]
- Set either panel replay source support or psr. [Jouni]

v5:
- HAS_PANEL_REPLAY() removed and use HAS_DP20() instead. [Jouni]
- Move psr related code to intel_psr.c. [Jani]
- Reset sink_panel_replay_support flag during disconnection. [Jani]

v6: return statement restored which is removed by misatke. [Jouni]

Cc: Jouni Högander 
Signed-off-by: Animesh Manna 
---
 .../drm/i915/display/intel_display_types.h| 14 +--
 drivers/gpu/drm/i915/display/intel_dp.c   | 50 --
 drivers/gpu/drm/i915/display/intel_dp_mst.c   |  3 +
 drivers/gpu/drm/i915/display/intel_psr.c  | 95 ++-
 drivers/gpu/drm/i915/display/intel_psr.h  |  7 ++
 5 files changed, 123 insertions(+), 46 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index 2213ad6c00da..3eadd8e12f63 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1203,6 +1203,7 @@ struct intel_crtc_state {
bool has_psr2;
bool enable_psr2_sel_fetch;
bool req_psr2_sdp_prior_scanline;
+   bool has_panel_replay;
bool wm_level_disabled;
u32 dc3co_exitline;
u16 su_y_granularity;
@@ -1695,6 +1696,8 @@ struct intel_psr {
bool irq_aux_error;
u16 su_w_granularity;
u16 su_y_granularity;
+   bool source_panel_replay_support;
+   bool sink_panel_replay_support;
u32 dc3co_exitline;
u32 dc3co_exit_delay;
struct delayed_work dc3co_work;
@@ -1982,17 +1985,6 @@ dp_to_lspcon(struct intel_dp *intel_dp)
 
 #define dp_to_i915(__intel_dp) 
to_i915(dp_to_dig_port(__intel_dp)->base.base.dev)
 
-#define CAN_PSR(intel_dp) ((intel_dp)->psr.sink_support && \
-  (intel_dp)->psr.source_support)
-
-static inline bool intel_encoder_can_psr(struct intel_encoder *encoder)
-{
-   if (!intel_encoder_is_dp(encoder))
-   return false;
-
-   return CAN_PSR(enc_to_intel_dp(encoder));
-}
-
 static inline struct intel_digital_port *
 hdmi_to_dig_port(struct intel_hdmi *intel_hdmi)
 {
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index f16d9fa88fe1..1c7d9b14fd1c 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2338,12 +2338,22 @@ static void intel_dp_compute_vsc_colorimetry(const 
struct intel_crtc_state *crtc
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 
-   /*
-* Prepare VSC Header for SU as per DP 1.4 spec, Table 2-118
-* VSC SDP supporting 3D stereo, PSR2, and Pixel Encoding/
-* Colorimetry Format indication.
-*/
-   vsc->revision = 0x5;
+   if (crtc_state->has_panel_replay) {
+   /*
+* Prepare VSC Header for SU as per DP 2.0 spec, Table 2-223
+* VSC SDP supporting 3D stereo, Panel Replay, and Pixel
+* Encoding/Colorimetry Format indication.
+*/
+   vsc->revision = 0x7;
+   } else {
+   /*
+* Prepare VSC Header for SU as per DP 1.4 spec, Table 2-118
+* VSC SDP supporting 3D stereo, PSR2, and Pixel Encoding/
+* Colorimetry Format indication.
+*/
+   vsc->revision = 0x5;
+   }
+
vsc->length = 0x13;
 
/* DP 1.4a spec, Table 2-120 */
@@ -2452,6 +2462,21 @@ void intel_dp_compute_psr_vsc_sdp(struct intel_dp 
*intel_dp,
vsc->revision = 0x4;
vsc->length = 0xe;
}
+   } else if (crtc_state->has_panel_replay) {
+   if (intel_dp->psr.colorimetry_support &&
+  

[Intel-gfx] [PATCH v6 2/6] drm/i915/psr: Move psr specific dpcd init into own function

2023-09-21 Thread Animesh Manna
From: Jouni Högander 

This patch is preparing adding panel replay specific dpcd init.

Signed-off-by: Jouni Högander 
---
 drivers/gpu/drm/i915/display/intel_psr.c | 41 +---
 1 file changed, 23 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index 850b11f20285..71fe2e4aca85 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -474,27 +474,22 @@ static void intel_dp_get_su_granularity(struct intel_dp 
*intel_dp)
intel_dp->psr.su_y_granularity = y;
 }
 
-void intel_psr_init_dpcd(struct intel_dp *intel_dp)
+static void _psr_init_dpcd(struct intel_dp *intel_dp)
 {
-   struct drm_i915_private *dev_priv =
+   struct drm_i915_private *i915 =
to_i915(dp_to_dig_port(intel_dp)->base.base.dev);
 
-   drm_dp_dpcd_read(_dp->aux, DP_PSR_SUPPORT, intel_dp->psr_dpcd,
-sizeof(intel_dp->psr_dpcd));
-
-   if (!intel_dp->psr_dpcd[0])
-   return;
-   drm_dbg_kms(_priv->drm, "eDP panel supports PSR version %x\n",
+   drm_dbg_kms(>drm, "eDP panel supports PSR version %x\n",
intel_dp->psr_dpcd[0]);
 
if (drm_dp_has_quirk(_dp->desc, DP_DPCD_QUIRK_NO_PSR)) {
-   drm_dbg_kms(_priv->drm,
+   drm_dbg_kms(>drm,
"PSR support not currently available for this 
panel\n");
return;
}
 
if (!(intel_dp->edp_dpcd[1] & DP_EDP_SET_POWER_CAP)) {
-   drm_dbg_kms(_priv->drm,
+   drm_dbg_kms(>drm,
"Panel lacks power state control, PSR cannot be 
enabled\n");
return;
}
@@ -503,8 +498,8 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp)
intel_dp->psr.sink_sync_latency =
intel_dp_get_sink_sync_latency(intel_dp);
 
-   if (DISPLAY_VER(dev_priv) >= 9 &&
-   (intel_dp->psr_dpcd[0] == DP_PSR2_WITH_Y_COORD_IS_SUPPORTED)) {
+   if (DISPLAY_VER(i915) >= 9 &&
+   intel_dp->psr_dpcd[0] == DP_PSR2_WITH_Y_COORD_IS_SUPPORTED) {
bool y_req = intel_dp->psr_dpcd[1] &
 DP_PSR2_SU_Y_COORDINATE_REQUIRED;
bool alpm = intel_dp_get_alpm_status(intel_dp);
@@ -521,14 +516,24 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp)
 * GTC first.
 */
intel_dp->psr.sink_psr2_support = y_req && alpm;
-   drm_dbg_kms(_priv->drm, "PSR2 %ssupported\n",
+   drm_dbg_kms(>drm, "PSR2 %ssupported\n",
intel_dp->psr.sink_psr2_support ? "" : "not ");
+   }
+}
 
-   if (intel_dp->psr.sink_psr2_support) {
-   intel_dp->psr.colorimetry_support =
-   intel_dp_get_colorimetry_status(intel_dp);
-   intel_dp_get_su_granularity(intel_dp);
-   }
+void intel_psr_init_dpcd(struct intel_dp *intel_dp)
+{
+   drm_dp_dpcd_read(_dp->aux, DP_PSR_SUPPORT, intel_dp->psr_dpcd,
+sizeof(intel_dp->psr_dpcd));
+
+   if (intel_dp->psr_dpcd[0])
+   _psr_init_dpcd(intel_dp);
+   /* TODO: Add PR case here */
+
+   if (intel_dp->psr.sink_psr2_support) {
+   intel_dp->psr.colorimetry_support =
+   intel_dp_get_colorimetry_status(intel_dp);
+   intel_dp_get_su_granularity(intel_dp);
}
 }
 
-- 
2.29.0



[Intel-gfx] [PATCH v6 1/6] drm/panelreplay: dpcd register definition for panelreplay

2023-09-21 Thread Animesh Manna
Add DPCD register definition for discovering, enabling and
checking status of panel replay of the sink.

Cc: Jouni Högander 
Signed-off-by: Animesh Manna 
---
 include/drm/display/drm_dp.h | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/include/drm/display/drm_dp.h b/include/drm/display/drm_dp.h
index e69cece404b3..fc42b622ef32 100644
--- a/include/drm/display/drm_dp.h
+++ b/include/drm/display/drm_dp.h
@@ -543,6 +543,10 @@
 /* DFP Capability Extension */
 #define DP_DFP_CAPABILITY_EXTENSION_SUPPORT0x0a3   /* 2.0 */
 
+#define DP_PANEL_REPLAY_CAP 0x0b0  /* DP 2.0 */
+# define DP_PANEL_REPLAY_SUPPORT(1 << 0)
+# define DP_PANEL_REPLAY_SU_SUPPORT (1 << 1)
+
 /* Link Configuration */
 #defineDP_LINK_BW_SET  0x100
 # define DP_LINK_RATE_TABLE0x00/* eDP 1.4 */
@@ -716,6 +720,13 @@
 #define DP_BRANCH_DEVICE_CTRL  0x1a1
 # define DP_BRANCH_DEVICE_IRQ_HPD  (1 << 0)
 
+#define PANEL_REPLAY_CONFIG 0x1b0  /* DP 2.0 */
+# define DP_PANEL_REPLAY_ENABLE (1 << 0)
+# define DP_PANEL_REPLAY_UNRECOVERABLE_ERROR_EN (1 << 3)
+# define DP_PANEL_REPLAY_RFB_STORAGE_ERROR_EN   (1 << 4)
+# define DP_PANEL_REPLAY_ACTIVE_FRAME_CRC_ERROR_EN  (1 << 5)
+# define DP_PANEL_REPLAY_SU_ENABLE  (1 << 6)
+
 #define DP_PAYLOAD_ALLOCATE_SET0x1c0
 #define DP_PAYLOAD_ALLOCATE_START_TIME_SLOT 0x1c1
 #define DP_PAYLOAD_ALLOCATE_TIME_SLOT_COUNT 0x1c2
@@ -1105,6 +1116,18 @@
 #define DP_LANE_ALIGN_STATUS_UPDATED_ESI   0x200e /* status same as 0x204 
*/
 #define DP_SINK_STATUS_ESI 0x200f /* status same as 0x205 
*/
 
+#define DP_PANEL_REPLAY_ERROR_STATUS   0x2020  /* DP 2.1*/
+# define DP_PANEL_REPLAY_LINK_CRC_ERROR(1 << 0)
+# define DP_PANEL_REPLAY_RFB_STORAGE_ERROR (1 << 1)
+# define DP_PANEL_REPLAY_VSC_SDP_UNCORRECTABLE_ERROR   (1 << 2)
+
+#define DP_SINK_DEVICE_PR_AND_FRAME_LOCK_STATUS0x2022  /* DP 2.1 */
+# define DP_SINK_DEVICE_PANEL_REPLAY_STATUS_MASK   (7 << 0)
+# define DP_SINK_FRAME_LOCKED_SHIFT3
+# define DP_SINK_FRAME_LOCKED_MASK (3 << 3)
+# define DP_SINK_FRAME_LOCKED_STATUS_VALID_SHIFT   5
+# define DP_SINK_FRAME_LOCKED_STATUS_VALID_MASK(1 << 5)
+
 /* Extended Receiver Capability: See DP_DPCD_REV for definitions */
 #define DP_DP13_DPCD_REV0x2200
 
-- 
2.29.0



[Intel-gfx] [PATCH v6 0/6] Panel replay phase1 implementation

2023-09-21 Thread Animesh Manna
Panel Replay is a power saving feature for DP 2.0 monitor and similar
to PSR on EDP.

These patches are basic enablement patches added on top of
existing psr framework to enable full-screen live active frame
update mode of panel replay. Panel replay also can be enabled
in selective update mode which will be enabled in a incremental
approach.

As per current design panel replay priority is higher than psr.
intel_dp->psr.panel_replay_enabled flag indicate panel replay is enabled.
intel_dp->psr.panel_replay_enabled + intel_dp->psr.psr2_enabled indicates
panel replay is enabled in selective update mode.
intel_dp->psr.panel_replay_enabled + intel_dp->psr.psr2_enabled +
intel_psr.selective_fetch enabled indicates panel replay is
enabled in selective update mode with selective fetch.
PSR replated flags remain same like before.

Note: The patches are under testing by using panel replay emulator and
panel is not avalible.

Cc: Jouni Högander 
Signed-off-by: Animesh Manna 

Animesh Manna (5):
  drm/panelreplay: dpcd register definition for panelreplay
  drm/i915/panelreplay: Initializaton and compute config for panel
replay
  drm/i915/panelreplay: Enable panel replay dpcd initialization for DP
  drm/i915/panelreplay: enable/disable panel replay
  drm/i915/panelreplay: Debugfs support for panel replay

Jouni Högander (1):
  drm/i915/psr: Move psr specific dpcd init into own function

 drivers/gpu/drm/i915/display/intel_ddi.c  |   7 +-
 .../drm/i915/display/intel_display_types.h|  15 +-
 drivers/gpu/drm/i915/display/intel_dp.c   |  50 ++-
 drivers/gpu/drm/i915/display/intel_dp_mst.c   |   3 +
 drivers/gpu/drm/i915/display/intel_psr.c  | 332 +-
 drivers/gpu/drm/i915/display/intel_psr.h  |   7 +
 include/drm/display/drm_dp.h  |  23 ++
 7 files changed, 323 insertions(+), 114 deletions(-)

-- 
2.29.0



[Intel-gfx] [PATCH v5 6/6] drm/i915/panelreplay: Debugfs support for panel replay

2023-09-05 Thread Animesh Manna
Add debugfs support which will print source and sink status
per connector basis.

Cc: Jouni Högander 
Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_psr.c | 70 
 1 file changed, 48 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index 5cbf08a4c94c..f50f110feb09 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -3044,7 +3044,7 @@ psr_source_status(struct intel_dp *intel_dp, struct 
seq_file *m)
status = live_status[status_val];
}
 
-   seq_printf(m, "Source PSR status: %s [0x%08x]\n", status, val);
+   seq_printf(m, "Source PSR/PanelReplay status: %s [0x%08x]\n", status, 
val);
 }
 
 static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp)
@@ -3057,18 +3057,23 @@ static int intel_psr_status(struct seq_file *m, struct 
intel_dp *intel_dp)
bool enabled;
u32 val;
 
-   seq_printf(m, "Sink support: %s", str_yes_no(psr->sink_support));
-   if (psr->sink_support)
+   seq_printf(m, "Sink support: PSR = %s, Panel Replay = %s",
+  str_yes_no(psr->sink_support),
+  str_yes_no(psr->sink_panel_replay_support));
+
+   if (psr->sink_support || psr->sink_panel_replay_support)
seq_printf(m, " [0x%02x]", intel_dp->psr_dpcd[0]);
seq_puts(m, "\n");
 
-   if (!psr->sink_support)
+   if (!(psr->sink_support || psr->sink_panel_replay_support))
return 0;
 
wakeref = intel_runtime_pm_get(_priv->runtime_pm);
mutex_lock(>lock);
 
-   if (psr->enabled)
+   if (psr->panel_replay_enabled)
+   status = "Panel Replay Enabled";
+   else if (psr->enabled)
status = psr->psr2_enabled ? "PSR2 enabled" : "PSR1 enabled";
else
status = "disabled";
@@ -3081,14 +3086,17 @@ static int intel_psr_status(struct seq_file *m, struct 
intel_dp *intel_dp)
goto unlock;
}
 
-   if (psr->psr2_enabled) {
+   if (psr->panel_replay_enabled) {
+   val = intel_de_read(dev_priv, TRANS_DP2_CTL(cpu_transcoder));
+   enabled = val & TRANS_DP2_PANEL_REPLAY_ENABLE;
+   } else if (psr->psr2_enabled) {
val = intel_de_read(dev_priv, EDP_PSR2_CTL(cpu_transcoder));
enabled = val & EDP_PSR2_ENABLE;
} else {
val = intel_de_read(dev_priv, psr_ctl_reg(dev_priv, 
cpu_transcoder));
enabled = val & EDP_PSR_ENABLE;
}
-   seq_printf(m, "Source PSR ctl: %s [0x%08x]\n",
+   seq_printf(m, "Source PSR/PanelReplay ctl: %s [0x%08x]\n",
   str_enabled_disabled(enabled), val);
psr_source_status(intel_dp, m);
seq_printf(m, "Busy frontbuffer bits: 0x%08x\n",
@@ -3230,6 +3238,7 @@ static int i915_psr_sink_status_show(struct seq_file *m, 
void *data)
 {
struct intel_connector *connector = m->private;
struct intel_dp *intel_dp = intel_attached_dp(connector);
+   struct intel_psr *psr = _dp->psr;
static const char * const sink_status[] = {
"inactive",
"transition to active, capture and display",
@@ -3240,27 +3249,47 @@ static int i915_psr_sink_status_show(struct seq_file 
*m, void *data)
"reserved",
"sink internal error",
};
+   static const char * const panel_replay_status[] = {
+   "Sink device frame is locked to the Source device",
+   "Sink device is coasting, using the VTotal target",
+   "Sink device is governing the frame rate (frame rate unlock is 
granted)",
+   "Sink device in the process of re-locking with the Source 
device",
+   };
const char *str;
int ret;
-   u8 val;
+   u8 val, temp;
 
-   if (!CAN_PSR(intel_dp)) {
-   seq_puts(m, "PSR Unsupported\n");
+   if (!(CAN_PSR(intel_dp) || CAN_PANEL_REPLAY(intel_dp))) {
+   seq_puts(m, "PSR/Panel-Replay Unsupported\n");
return -ENODEV;
}
 
if (connector->base.status != connector_status_connected)
return -ENODEV;
 
-   ret = drm_dp_dpcd_readb(_dp->aux, DP_PSR_STATUS, );
-   if (ret != 1)
-   return ret < 0 ? ret : -EIO;
+   if (psr->panel_replay_enabled) {
+   ret = drm_dp_dpcd_readb(_dp->aux,
+   
DP_SINK_DEVICE_PR_AND_FRAME_LOCK_STATUS, );
+   if (ret != 1)
+ 

[Intel-gfx] [PATCH v5 5/6] drm/i915/panelreplay: enable/disable panel replay

2023-09-05 Thread Animesh Manna
TRANS_DP2_CTL register is programmed to enable panel replay from source
and sink is enabled through panel replay dpcd configuration address.

Bspec: 1407940617

v1: Initial version.
v2:
- Use pr_* flags instead psr_* flags. [Jouni]
- Remove intel_dp_is_edp check as edp1.5 also has panel replay. [Jouni]

v3: Cover letter updated and selective fetch condition check is added
before updating its bit in PSR2_MAN_TRK_CTL register. [Jouni]

v4: Selective fetch related PSR2_MAN_TRK_CTL programmming dropped. [Jouni]

Note: Initial plan is to enable panel replay in  full-screen live active
frame update mode. In a incremental approach panel replay will be enabled
in selctive update mode if there is any gap in curent implementation.

Cc: Jouni Högander 
Signed-off-by: Animesh Manna 
---
 .../drm/i915/display/intel_display_types.h|  1 +
 drivers/gpu/drm/i915/display/intel_psr.c  | 65 ++-
 2 files changed, 50 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index 4022d6d8281a..b1383988b656 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1696,6 +1696,7 @@ struct intel_psr {
u16 su_y_granularity;
bool source_panel_replay_support;
bool sink_panel_replay_support;
+   bool panel_replay_enabled;
u32 dc3co_exitline;
u32 dc3co_exit_delay;
struct delayed_work dc3co_work;
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index 4e9c126a47ff..5cbf08a4c94c 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -606,8 +606,14 @@ static void intel_psr_enable_sink(struct intel_dp 
*intel_dp)
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
u8 dpcd_val = DP_PSR_ENABLE;
 
-   /* Enable ALPM at sink for psr2 */
+   if (intel_dp->psr.panel_replay_enabled) {
+   drm_dp_dpcd_writeb(_dp->aux, PANEL_REPLAY_CONFIG,
+  DP_PANEL_REPLAY_ENABLE);
+   return;
+   }
+
if (intel_dp->psr.psr2_enabled) {
+   /* Enable ALPM at sink for psr2 */
drm_dp_dpcd_writeb(_dp->aux, DP_RECEIVER_ALPM_CONFIG,
   DP_ALPM_ENABLE |
   DP_ALPM_LOCK_ERROR_IRQ_HPD_ENABLE);
@@ -757,6 +763,14 @@ static int psr2_block_count(struct intel_dp *intel_dp)
return psr2_block_count_lines(intel_dp) / 4;
 }
 
+static void dg2_activate_panel_replay(struct intel_dp *intel_dp)
+{
+   struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+
+   intel_de_rmw(dev_priv, TRANS_DP2_CTL(intel_dp->psr.transcoder), 0,
+TRANS_DP2_PANEL_REPLAY_ENABLE);
+}
+
 static void hsw_activate_psr2(struct intel_dp *intel_dp)
 {
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
@@ -1320,18 +1334,23 @@ void intel_psr_get_config(struct intel_encoder *encoder,
return;
 
intel_dp = _port->dp;
-   if (!CAN_PSR(intel_dp))
+   if (!(CAN_PSR(intel_dp) || CAN_PANEL_REPLAY(intel_dp)))
return;
 
mutex_lock(_dp->psr.lock);
if (!intel_dp->psr.enabled)
goto unlock;
 
-   /*
-* Not possible to read EDP_PSR/PSR2_CTL registers as it is
-* enabled/disabled because of frontbuffer tracking and others.
-*/
-   pipe_config->has_psr = true;
+   if (intel_dp->psr.panel_replay_enabled) {
+   pipe_config->has_panel_replay = true;
+   } else {
+   /*
+* Not possible to read EDP_PSR/PSR2_CTL registers as it is
+* enabled/disabled because of frontbuffer tracking and others.
+*/
+   pipe_config->has_psr = true;
+   }
+
pipe_config->has_psr2 = intel_dp->psr.psr2_enabled;
pipe_config->infoframes.enable |= 
intel_hdmi_infoframe_enable(DP_SDP_VSC);
 
@@ -1368,8 +1387,10 @@ static void intel_psr_activate(struct intel_dp *intel_dp)
 
lockdep_assert_held(_dp->psr.lock);
 
-   /* psr1 and psr2 are mutually exclusive.*/
-   if (intel_dp->psr.psr2_enabled)
+   /* psr1, psr2 and panel-replay are mutually exclusive.*/
+   if (intel_dp->psr.panel_replay_enabled)
+   dg2_activate_panel_replay(intel_dp);
+   else if (intel_dp->psr.psr2_enabled)
hsw_activate_psr2(intel_dp);
else
hsw_activate_psr1(intel_dp);
@@ -1547,6 +1568,7 @@ static void intel_psr_enable_locked(struct intel_dp 
*intel_dp,
drm_WARN_ON(_priv->drm, intel_dp->psr.enabled);
 
intel_dp->psr.psr2_enabled = crtc_state->has_psr2;
+   intel_dp->psr.panel_replay_enabled = crtc_state->has_panel_replay;
intel_dp

[Intel-gfx] [PATCH v5 4/6] drm/i915/panelreplay: Enable panel replay dpcd initialization for DP

2023-09-05 Thread Animesh Manna
Due to similarity panel replay dpcd initialization got added in psr
function which is specific for edp panel. This patch enables panel
replay initialization for dp connector.

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_psr.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index f2209fc94125..4e9c126a47ff 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -2747,6 +2747,9 @@ void intel_psr_init(struct intel_dp *intel_dp)
if (!(HAS_PSR(dev_priv) || HAS_DP20(dev_priv)))
return;
 
+   if (!intel_dp_is_edp(intel_dp))
+   intel_psr_init_dpcd(intel_dp);
+
/*
 * HSW spec explicitly says PSR is tied to port A.
 * BDW+ platforms have a instance of PSR registers per transcoder but
-- 
2.29.0



[Intel-gfx] [PATCH v5 3/6] drm/i915/panelreplay: Initializaton and compute config for panel replay

2023-09-05 Thread Animesh Manna
Modify existing PSR implementation to enable panel replay feature of DP 2.0
which is similar to PSR feature of EDP panel. There is different DPCD
address to check panel capability compare to PSR and vsc sdp header
is different.

v1: Initial version.
v2:
- Set source_panel_replay_support flag under HAS_PANEL_REPLAY()
condition check. [Jouni]
- Code restructured around intel_panel_replay_init
and renamed to intel_panel_replay_init_dpcd. [Jouni]
- Remove the initial code modification around has_psr2 flag. [Jouni]
- Add CAN_PANEL_REPLAY() in intel_encoder_can_psr which is used to
enable in intel_psr_post_plane_update. [Jouni]
v3:
- Initialize both psr and panel-replay. [Jouni]
- Initialize both panel replay and psr if detected. [Jouni]
- Refactoring psr function by introducing _psr_compute_config(). [Jouni]
- Add check for !is_edp while deriving source_panel_replay_support. [Jouni]
- Enable panel replay dpcd initialization in a separate patch. [Jouni]

v4:
- HAS_PANEL_REPLAY() check not needed during sink capability check. [Jouni]
- Set either panel replay source support or psr. [Jouni]

v5:
- HAS_PANEL_REPLAY() removed and use HAS_DP20() instead. [Jouni]
- Move psr related code to intel_psr.c. [Jani]
- Reset sink_panel_replay_support flag during disconnection. [Jani]

Cc: Jouni Högander 
Signed-off-by: Animesh Manna 
---
 .../drm/i915/display/intel_display_types.h| 14 +--
 drivers/gpu/drm/i915/display/intel_dp.c   | 45 +++--
 drivers/gpu/drm/i915/display/intel_dp_mst.c   |  3 +
 drivers/gpu/drm/i915/display/intel_psr.c  | 96 +--
 drivers/gpu/drm/i915/display/intel_psr.h  |  7 ++
 5 files changed, 118 insertions(+), 47 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index c21064794f32..4022d6d8281a 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1202,6 +1202,7 @@ struct intel_crtc_state {
bool has_psr2;
bool enable_psr2_sel_fetch;
bool req_psr2_sdp_prior_scanline;
+   bool has_panel_replay;
bool wm_level_disabled;
u32 dc3co_exitline;
u16 su_y_granularity;
@@ -1693,6 +1694,8 @@ struct intel_psr {
bool irq_aux_error;
u16 su_w_granularity;
u16 su_y_granularity;
+   bool source_panel_replay_support;
+   bool sink_panel_replay_support;
u32 dc3co_exitline;
u32 dc3co_exit_delay;
struct delayed_work dc3co_work;
@@ -1980,17 +1983,6 @@ dp_to_lspcon(struct intel_dp *intel_dp)
 
 #define dp_to_i915(__intel_dp) 
to_i915(dp_to_dig_port(__intel_dp)->base.base.dev)
 
-#define CAN_PSR(intel_dp) ((intel_dp)->psr.sink_support && \
-  (intel_dp)->psr.source_support)
-
-static inline bool intel_encoder_can_psr(struct intel_encoder *encoder)
-{
-   if (!intel_encoder_is_dp(encoder))
-   return false;
-
-   return CAN_PSR(enc_to_intel_dp(encoder));
-}
-
 static inline struct intel_digital_port *
 hdmi_to_dig_port(struct intel_hdmi *intel_hdmi)
 {
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 3faa68989d85..d8c151196a81 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2338,12 +2338,22 @@ static void intel_dp_compute_vsc_colorimetry(const 
struct intel_crtc_state *crtc
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 
-   /*
-* Prepare VSC Header for SU as per DP 1.4 spec, Table 2-118
-* VSC SDP supporting 3D stereo, PSR2, and Pixel Encoding/
-* Colorimetry Format indication.
-*/
-   vsc->revision = 0x5;
+   if (crtc_state->has_panel_replay) {
+   /*
+* Prepare VSC Header for SU as per DP 2.0 spec, Table 2-223
+* VSC SDP supporting 3D stereo, Panel Replay, and Pixel
+* Encoding/Colorimetry Format indication.
+*/
+   vsc->revision = 0x7;
+   } else {
+   /*
+* Prepare VSC Header for SU as per DP 1.4 spec, Table 2-118
+* VSC SDP supporting 3D stereo, PSR2, and Pixel Encoding/
+* Colorimetry Format indication.
+*/
+   vsc->revision = 0x5;
+   }
+
vsc->length = 0x13;
 
/* DP 1.4a spec, Table 2-120 */
@@ -2452,6 +2462,21 @@ void intel_dp_compute_psr_vsc_sdp(struct intel_dp 
*intel_dp,
vsc->revision = 0x4;
vsc->length = 0xe;
}
+   } else if (crtc_state->has_panel_replay) {
+   if (intel_dp->psr.colorimetry_support &&
+   intel_dp_needs_vsc_sdp(crtc_state, conn_state)) {
+   

[Intel-gfx] [PATCH v5 2/6] drm/i915/psr: Move psr specific dpcd init into own function

2023-09-05 Thread Animesh Manna
From: Jouni Högander 

This patch is preparing adding panel replay specific dpcd init.

Signed-off-by: Jouni Högander 
---
 drivers/gpu/drm/i915/display/intel_psr.c | 39 +---
 1 file changed, 22 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index b9e38acc5132..24eed99e8811 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -473,27 +473,22 @@ static void intel_dp_get_su_granularity(struct intel_dp 
*intel_dp)
intel_dp->psr.su_y_granularity = y;
 }
 
-void intel_psr_init_dpcd(struct intel_dp *intel_dp)
+static void _psr_init_dpcd(struct intel_dp *intel_dp)
 {
-   struct drm_i915_private *dev_priv =
+   struct drm_i915_private *i915 =
to_i915(dp_to_dig_port(intel_dp)->base.base.dev);
 
-   drm_dp_dpcd_read(_dp->aux, DP_PSR_SUPPORT, intel_dp->psr_dpcd,
-sizeof(intel_dp->psr_dpcd));
-
-   if (!intel_dp->psr_dpcd[0])
-   return;
-   drm_dbg_kms(_priv->drm, "eDP panel supports PSR version %x\n",
+   drm_dbg_kms(>drm, "eDP panel supports PSR version %x\n",
intel_dp->psr_dpcd[0]);
 
if (drm_dp_has_quirk(_dp->desc, DP_DPCD_QUIRK_NO_PSR)) {
-   drm_dbg_kms(_priv->drm,
+   drm_dbg_kms(>drm,
"PSR support not currently available for this 
panel\n");
return;
}
 
if (!(intel_dp->edp_dpcd[1] & DP_EDP_SET_POWER_CAP)) {
-   drm_dbg_kms(_priv->drm,
+   drm_dbg_kms(>drm,
"Panel lacks power state control, PSR cannot be 
enabled\n");
return;
}
@@ -502,7 +497,7 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp)
intel_dp->psr.sink_sync_latency =
intel_dp_get_sink_sync_latency(intel_dp);
 
-   if (DISPLAY_VER(dev_priv) >= 9 &&
+   if (DISPLAY_VER(i915) >= 9 &&
(intel_dp->psr_dpcd[0] == DP_PSR2_WITH_Y_COORD_IS_SUPPORTED)) {
bool y_req = intel_dp->psr_dpcd[1] &
 DP_PSR2_SU_Y_COORDINATE_REQUIRED;
@@ -520,14 +515,24 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp)
 * GTC first.
 */
intel_dp->psr.sink_psr2_support = y_req && alpm;
-   drm_dbg_kms(_priv->drm, "PSR2 %ssupported\n",
+   drm_dbg_kms(>drm, "PSR2 %ssupported\n",
intel_dp->psr.sink_psr2_support ? "" : "not ");
+   }
+}
 
-   if (intel_dp->psr.sink_psr2_support) {
-   intel_dp->psr.colorimetry_support =
-   intel_dp_get_colorimetry_status(intel_dp);
-   intel_dp_get_su_granularity(intel_dp);
-   }
+void intel_psr_init_dpcd(struct intel_dp *intel_dp)
+{
+   drm_dp_dpcd_read(_dp->aux, DP_PSR_SUPPORT, intel_dp->psr_dpcd,
+sizeof(intel_dp->psr_dpcd));
+
+   if (intel_dp->psr_dpcd[0])
+   _psr_init_dpcd(intel_dp);
+   /* TODO: Add PR case here */
+
+   if (intel_dp->psr.sink_psr2_support) {
+   intel_dp->psr.colorimetry_support =
+   intel_dp_get_colorimetry_status(intel_dp);
+   intel_dp_get_su_granularity(intel_dp);
}
 }
 
-- 
2.29.0



[Intel-gfx] [PATCH v5 1/6] drm/panelreplay: dpcd register definition for panelreplay

2023-09-05 Thread Animesh Manna
Add DPCD register definition for discovering, enabling and
checking status of panel replay of the sink.

Cc: Jouni Högander 
Signed-off-by: Animesh Manna 
---
 include/drm/display/drm_dp.h | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/include/drm/display/drm_dp.h b/include/drm/display/drm_dp.h
index e69cece404b3..23c2a68c32a4 100644
--- a/include/drm/display/drm_dp.h
+++ b/include/drm/display/drm_dp.h
@@ -543,6 +543,10 @@
 /* DFP Capability Extension */
 #define DP_DFP_CAPABILITY_EXTENSION_SUPPORT0x0a3   /* 2.0 */
 
+#define DP_PANEL_REPLAY_CAP 0x0b0  /* DP 2.0 */
+# define DP_PANEL_REPLAY_SUPPORT(1 << 0)
+# define DP_PANEL_REPLAY_SU_SUPPORT (1 << 1)
+
 /* Link Configuration */
 #defineDP_LINK_BW_SET  0x100
 # define DP_LINK_RATE_TABLE0x00/* eDP 1.4 */
@@ -716,6 +720,13 @@
 #define DP_BRANCH_DEVICE_CTRL  0x1a1
 # define DP_BRANCH_DEVICE_IRQ_HPD  (1 << 0)
 
+#define PANEL_REPLAY_CONFIG 0x1b0  /* DP 2.0 */
+# define DP_PANEL_REPLAY_ENABLE (1 << 0)
+# define DP_PANEL_REPLAY_UNRECOVERABLE_ERROR(1 << 3)
+# define DP_PANEL_REPLAY_RFB_STORAGE_ERROR  (1 << 4)
+# define DP_PANEL_REPLAY_ACTIVE_FRAME_CRC_ERROR (1 << 5)
+# define DP_PANEL_REPLAY_SU_ENABLE  (1 << 6)
+
 #define DP_PAYLOAD_ALLOCATE_SET0x1c0
 #define DP_PAYLOAD_ALLOCATE_START_TIME_SLOT 0x1c1
 #define DP_PAYLOAD_ALLOCATE_TIME_SLOT_COUNT 0x1c2
@@ -1105,6 +1116,13 @@
 #define DP_LANE_ALIGN_STATUS_UPDATED_ESI   0x200e /* status same as 0x204 
*/
 #define DP_SINK_STATUS_ESI 0x200f /* status same as 0x205 
*/
 
+#define DP_SINK_DEVICE_PR_AND_FRAME_LOCK_STATUS0x2022  /* DP 2.1 */
+# define DP_SINK_DEVICE_PANEL_REPLAY_STATUS_MASK   (7 << 0)
+# define DP_SINK_FRAME_LOCKED_SHIFT3
+# define DP_SINK_FRAME_LOCKED_MASK (3 << 3)
+# define DP_SINK_FRAME_LOCKED_STATUS_VALID_SHIFT   5
+# define DP_SINK_FRAME_LOCKED_STATUS_VALID_MASK(1 << 5)
+
 /* Extended Receiver Capability: See DP_DPCD_REV for definitions */
 #define DP_DP13_DPCD_REV0x2200
 
-- 
2.29.0



[Intel-gfx] [PATCH v5 0/6] Panel replay phase1 implementation

2023-09-05 Thread Animesh Manna
Panel Replay is a power saving feature for DP 2.0 monitor and similar
to PSR on EDP.

These patches are basic enablement patches added on top of
existing psr framework to enable full-screen live active frame
update mode of panel replay. Panel replay also can be enabled
in selective update mode which will be enabled in a incremental
approach.

As per current design panel replay priority is higher than psr.
intel_dp->psr.panel_replay_enabled flag indicate panel replay is enabled.
intel_dp->psr.panel_replay_enabled + intel_dp->psr.psr2_enabled indicates
panel replay is enabled in selective update mode.
intel_dp->psr.panel_replay_enabled + intel_dp->psr.psr2_enabled +
intel_psr.selective_fetch enabled indicates panel replay is
enabled in selective update mode with selective fetch.
PSR replated flags remain same like before.

Note: The patches are under testing by using panel replay emulator and
panel is not avalible.

Cc: Jouni Högander 
Signed-off-by: Animesh Manna 

Animesh Manna (5):
  drm/panelreplay: dpcd register definition for panelreplay
  drm/i915/panelreplay: Initializaton and compute config for panel
replay
  drm/i915/panelreplay: Enable panel replay dpcd initialization for DP
  drm/i915/panelreplay: enable/disable panel replay
  drm/i915/panelreplay: Debugfs support for panel replay

Jouni Högander (1):
  drm/i915/psr: Move psr specific dpcd init into own function

 .../drm/i915/display/intel_display_types.h|  15 +-
 drivers/gpu/drm/i915/display/intel_dp.c   |  45 ++-
 drivers/gpu/drm/i915/display/intel_dp_mst.c   |   3 +
 drivers/gpu/drm/i915/display/intel_psr.c  | 269 --
 drivers/gpu/drm/i915/display/intel_psr.h  |   7 +
 include/drm/display/drm_dp.h  |  18 ++
 6 files changed, 257 insertions(+), 100 deletions(-)

-- 
2.29.0



[Intel-gfx] [PATCH v4 6/6] drm/i915/panelreplay: enable/disable panel replay

2023-08-23 Thread Animesh Manna
TRANS_DP2_CTL register is programmed to enable panel replay from source
and sink is enabled through panel replay dpcd configuration address.

Bspec: 1407940617

v1: Initial version.
v2:
- Use pr_* flags instead psr_* flags. [Jouni]
- Remove intel_dp_is_edp check as edp1.5 also has panel replay. [Jouni]

v3: cover letter updated and selective fetch condition check is added
before updating its bit in PSR2_MAN_TRK_CTL register. [Jouni]

Note: Initial plan is to enable panel replay in  full-screen live active
frame update mode. In a incremental approach panel replay will be enabled
in selctive update mode if there is any gap in curent implementation.

Cc: Jouni Högander 
Signed-off-by: Animesh Manna 
---
 .../drm/i915/display/intel_display_types.h|  1 +
 drivers/gpu/drm/i915/display/intel_psr.c  | 72 ++-
 2 files changed, 57 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index 97cef458f42b..46f2e8a42d1d 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1696,6 +1696,7 @@ struct intel_psr {
u16 su_y_granularity;
bool source_panel_replay_support;
bool sink_panel_replay_support;
+   bool panel_replay_enabled;
u32 dc3co_exitline;
u32 dc3co_exit_delay;
struct delayed_work dc3co_work;
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index c92acc7be4f1..ccb714f2c9e6 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -596,8 +596,14 @@ static void intel_psr_enable_sink(struct intel_dp 
*intel_dp)
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
u8 dpcd_val = DP_PSR_ENABLE;
 
-   /* Enable ALPM at sink for psr2 */
+   if (intel_dp->psr.panel_replay_enabled) {
+   drm_dp_dpcd_writeb(_dp->aux, PANEL_REPLAY_CONFIG,
+  DP_PANEL_REPLAY_ENABLE);
+   return;
+   }
+
if (intel_dp->psr.psr2_enabled) {
+   /* Enable ALPM at sink for psr2 */
drm_dp_dpcd_writeb(_dp->aux, DP_RECEIVER_ALPM_CONFIG,
   DP_ALPM_ENABLE |
   DP_ALPM_LOCK_ERROR_IRQ_HPD_ENABLE);
@@ -747,6 +753,18 @@ static int psr2_block_count(struct intel_dp *intel_dp)
return psr2_block_count_lines(intel_dp) / 4;
 }
 
+static void dg2_activate_panel_replay(struct intel_dp *intel_dp)
+{
+   struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+
+   if (intel_dp->psr.psr2_sel_fetch_enabled)
+   intel_de_rmw(dev_priv, 
PSR2_MAN_TRK_CTL(intel_dp->psr.transcoder),
+0, ADLP_PSR2_MAN_TRK_CTL_SF_PARTIAL_FRAME_UPDATE);
+
+   intel_de_rmw(dev_priv, TRANS_DP2_CTL(intel_dp->psr.transcoder), 0,
+TRANS_DP2_PANEL_REPLAY_ENABLE);
+}
+
 static void hsw_activate_psr2(struct intel_dp *intel_dp)
 {
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
@@ -1295,6 +1313,9 @@ void intel_psr_compute_config(struct intel_dp *intel_dp,
crtc_state->infoframes.enable |= 
intel_hdmi_infoframe_enable(DP_SDP_VSC);
intel_dp_compute_psr_vsc_sdp(intel_dp, crtc_state, conn_state,
 _state->psr_vsc);
+
+   drm_dbg_kms(_priv->drm, "has_pr = %d, has_psr = %d, has_psr2 = %d, 
infoframes_enable = %d\n",
+   crtc_state->has_panel_replay, crtc_state->has_psr, 
crtc_state->has_psr2, crtc_state->infoframes.enable);
 }
 
 void intel_psr_get_config(struct intel_encoder *encoder,
@@ -1310,18 +1331,23 @@ void intel_psr_get_config(struct intel_encoder *encoder,
return;
 
intel_dp = _port->dp;
-   if (!CAN_PSR(intel_dp))
+   if (!(CAN_PSR(intel_dp) || CAN_PANEL_REPLAY(intel_dp)))
return;
 
mutex_lock(_dp->psr.lock);
if (!intel_dp->psr.enabled)
goto unlock;
 
-   /*
-* Not possible to read EDP_PSR/PSR2_CTL registers as it is
-* enabled/disabled because of frontbuffer tracking and others.
-*/
-   pipe_config->has_psr = true;
+   if (intel_dp->psr.panel_replay_enabled) {
+   pipe_config->has_panel_replay = true;
+   } else {
+   /*
+* Not possible to read EDP_PSR/PSR2_CTL registers as it is
+* enabled/disabled because of frontbuffer tracking and others.
+*/
+   pipe_config->has_psr = true;
+   }
+
pipe_config->has_psr2 = intel_dp->psr.psr2_enabled;
pipe_config->infoframes.enable |= 
intel_hdmi_infoframe_enable(DP_SDP_VSC);
 
@@ -1358,8 +1384,10 @@ static void intel_psr_activate(struct intel_dp *intel_dp)
 
loc

[Intel-gfx] [PATCH v4 5/6] drm/i915/panelreplay: Enable panel replay dpcd initialization for DP

2023-08-23 Thread Animesh Manna
Due to similarity panel replay dpcd initialization got added in psr
function which is specific for edp panel. This patch enables panel
replay initialization for dp connector.

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_psr.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index 8dd61c62492d..c92acc7be4f1 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -2732,6 +2732,9 @@ void intel_psr_init(struct intel_dp *intel_dp)
if (!(HAS_PSR(dev_priv) || HAS_PANEL_REPLAY(dev_priv)))
return;
 
+   if (!intel_dp_is_edp(intel_dp))
+   intel_psr_init_dpcd(intel_dp);
+
/*
 * HSW spec explicitly says PSR is tied to port A.
 * BDW+ platforms have a instance of PSR registers per transcoder but
-- 
2.29.0



[Intel-gfx] [PATCH v4 2/6] drm/i915/panelreplay: Added HAS_PANEL_REPLAY() macro

2023-08-23 Thread Animesh Manna
Platforms having Display 13 and above will support panel
replay feature of DP 2.0 monitor. Added a HAS_PANEL_REPLAY()
macro to check for panel replay capability.

v1: Initial version.
v2: DISPLAY_VER() removed as HAS_DP20() is having platform check. [Jouni]

Cc: Jouni Högander 
Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_display_device.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/i915/display/intel_display_device.h 
b/drivers/gpu/drm/i915/display/intel_display_device.h
index 8198401aa5be..ab615a3199da 100644
--- a/drivers/gpu/drm/i915/display/intel_display_device.h
+++ b/drivers/gpu/drm/i915/display/intel_display_device.h
@@ -61,6 +61,7 @@ struct drm_printer;
 #define HAS_MSO(i915)  (DISPLAY_VER(i915) >= 12)
 #define HAS_OVERLAY(i915)  (DISPLAY_INFO(i915)->has_overlay)
 #define HAS_PSR(i915)  (DISPLAY_INFO(i915)->has_psr)
+#define HAS_PANEL_REPLAY(dev_priv) (HAS_DP20(dev_priv))
 #define HAS_PSR_HW_TRACKING(i915)  
(DISPLAY_INFO(i915)->has_psr_hw_tracking)
 #define HAS_PSR2_SEL_FETCH(i915)   (DISPLAY_VER(i915) >= 12)
 #define HAS_SAGV(i915) (DISPLAY_VER(i915) >= 9 && !IS_LP(i915))
-- 
2.29.0



[Intel-gfx] [PATCH v4 4/6] drm/i915/panelreplay: Initializaton and compute config for panel replay

2023-08-23 Thread Animesh Manna
Modify existing PSR implementation to enable panel replay feature of DP 2.0
which is similar to PSR feature of EDP panel. There is different DPCD
address to check panel capability compare to PSR and vsc sdp header
is different.

v1: Initial version.
v2:
- Set source_panel_replay_support flag under HAS_PNEL_REPLAY() check. [Jouni]
- Code restructured around intel_panel_replay_init
and renamed to intel_panel_replay_init_dpcd. [Jouni]
- Remove the initial code modification around has_psr2 flag. [Jouni]
- Add CAN_PANEL_REPLAY() in intel_encoder_can_psr which is used to
enable in intel_psr_post_plane_update. [Jouni]
v3:
- Initialize both psr and panel-replay. [Jouni]
- Initialize both panel replay and psr if detected. [Jouni]
- Refactoring psr function by introducing _psr_compute_config(). [Jouni]
- Add check for !is_edp while deriving source_panel_replay_support. [Jouni]
- Enable panel replay dpcd initialization in a separate patch. [Jouni]

v4:
- HAS_PANEL_REPLAY() check not needed during sink capability check.[Jouni]
- Set either panel replay source support or psr.[Jouni]

Cc: Jouni Högander 
Signed-off-by: Animesh Manna 
---
 .../drm/i915/display/intel_display_types.h| 12 ++-
 drivers/gpu/drm/i915/display/intel_dp.c   | 44 --
 drivers/gpu/drm/i915/display/intel_dp_mst.c   |  3 +
 drivers/gpu/drm/i915/display/intel_psr.c  | 87 +--
 4 files changed, 107 insertions(+), 39 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index 731f2ec04d5c..97cef458f42b 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1202,6 +1202,7 @@ struct intel_crtc_state {
bool has_psr2;
bool enable_psr2_sel_fetch;
bool req_psr2_sdp_prior_scanline;
+   bool has_panel_replay;
bool wm_level_disabled;
u32 dc3co_exitline;
u16 su_y_granularity;
@@ -1693,6 +1694,8 @@ struct intel_psr {
bool irq_aux_error;
u16 su_w_granularity;
u16 su_y_granularity;
+   bool source_panel_replay_support;
+   bool sink_panel_replay_support;
u32 dc3co_exitline;
u32 dc3co_exit_delay;
struct delayed_work dc3co_work;
@@ -1983,12 +1986,15 @@ dp_to_lspcon(struct intel_dp *intel_dp)
 #define CAN_PSR(intel_dp) ((intel_dp)->psr.sink_support && \
   (intel_dp)->psr.source_support)
 
+#define CAN_PANEL_REPLAY(intel_dp) ((intel_dp)->psr.sink_panel_replay_support 
&& \
+ (intel_dp)->psr.source_panel_replay_support)
+
 static inline bool intel_encoder_can_psr(struct intel_encoder *encoder)
 {
-   if (!intel_encoder_is_dp(encoder))
+   if (intel_encoder_is_dp(encoder) || (encoder->type == 
INTEL_OUTPUT_DP_MST))
+   return CAN_PSR(enc_to_intel_dp(encoder)) || 
CAN_PANEL_REPLAY(enc_to_intel_dp(encoder));
+   else
return false;
-
-   return CAN_PSR(enc_to_intel_dp(encoder));
 }
 
 static inline struct intel_digital_port *
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 7067ee3a4bd3..b3301cf0da0a 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2337,12 +2337,22 @@ static void intel_dp_compute_vsc_colorimetry(const 
struct intel_crtc_state *crtc
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 
-   /*
-* Prepare VSC Header for SU as per DP 1.4 spec, Table 2-118
-* VSC SDP supporting 3D stereo, PSR2, and Pixel Encoding/
-* Colorimetry Format indication.
-*/
-   vsc->revision = 0x5;
+   if (crtc_state->has_panel_replay) {
+   /*
+* Prepare VSC Header for SU as per DP 2.0 spec, Table 2-223
+* VSC SDP supporting 3D stereo, Panel Replay, and Pixel
+* Encoding/Colorimetry Format indication.
+*/
+   vsc->revision = 0x7;
+   } else {
+   /*
+* Prepare VSC Header for SU as per DP 1.4 spec, Table 2-118
+* VSC SDP supporting 3D stereo, PSR2, and Pixel Encoding/
+* Colorimetry Format indication.
+*/
+   vsc->revision = 0x5;
+   }
+
vsc->length = 0x13;
 
/* DP 1.4a spec, Table 2-120 */
@@ -2451,6 +2461,21 @@ void intel_dp_compute_psr_vsc_sdp(struct intel_dp 
*intel_dp,
vsc->revision = 0x4;
vsc->length = 0xe;
}
+   } else if (crtc_state->has_panel_replay) {
+   if (intel_dp->psr.colorimetry_support &&
+   intel_dp_needs_vsc_sdp(crtc_state, conn_state)) {
+   /* [Panel Replay with color

[Intel-gfx] [PATCH v4 3/6] drm/i915/psr: Move psr specific dpcd init into own function

2023-08-23 Thread Animesh Manna
From: Jouni Högander 

This patch is preparing adding panel replay specific dpcd init.

Signed-off-by: Jouni Högander 
---
 drivers/gpu/drm/i915/display/intel_psr.c | 39 +---
 1 file changed, 22 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index 72887c29fb51..b1c0494826f9 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -472,27 +472,22 @@ static void intel_dp_get_su_granularity(struct intel_dp 
*intel_dp)
intel_dp->psr.su_y_granularity = y;
 }
 
-void intel_psr_init_dpcd(struct intel_dp *intel_dp)
+static void _psr_init_dpcd(struct intel_dp *intel_dp)
 {
-   struct drm_i915_private *dev_priv =
+   struct drm_i915_private *i915 =
to_i915(dp_to_dig_port(intel_dp)->base.base.dev);
 
-   drm_dp_dpcd_read(_dp->aux, DP_PSR_SUPPORT, intel_dp->psr_dpcd,
-sizeof(intel_dp->psr_dpcd));
-
-   if (!intel_dp->psr_dpcd[0])
-   return;
-   drm_dbg_kms(_priv->drm, "eDP panel supports PSR version %x\n",
+   drm_dbg_kms(>drm, "eDP panel supports PSR version %x\n",
intel_dp->psr_dpcd[0]);
 
if (drm_dp_has_quirk(_dp->desc, DP_DPCD_QUIRK_NO_PSR)) {
-   drm_dbg_kms(_priv->drm,
+   drm_dbg_kms(>drm,
"PSR support not currently available for this 
panel\n");
return;
}
 
if (!(intel_dp->edp_dpcd[1] & DP_EDP_SET_POWER_CAP)) {
-   drm_dbg_kms(_priv->drm,
+   drm_dbg_kms(>drm,
"Panel lacks power state control, PSR cannot be 
enabled\n");
return;
}
@@ -501,7 +496,7 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp)
intel_dp->psr.sink_sync_latency =
intel_dp_get_sink_sync_latency(intel_dp);
 
-   if (DISPLAY_VER(dev_priv) >= 9 &&
+   if (DISPLAY_VER(i915) >= 9 &&
(intel_dp->psr_dpcd[0] == DP_PSR2_WITH_Y_COORD_IS_SUPPORTED)) {
bool y_req = intel_dp->psr_dpcd[1] &
 DP_PSR2_SU_Y_COORDINATE_REQUIRED;
@@ -519,14 +514,24 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp)
 * GTC first.
 */
intel_dp->psr.sink_psr2_support = y_req && alpm;
-   drm_dbg_kms(_priv->drm, "PSR2 %ssupported\n",
+   drm_dbg_kms(>drm, "PSR2 %ssupported\n",
intel_dp->psr.sink_psr2_support ? "" : "not ");
+   }
+}
 
-   if (intel_dp->psr.sink_psr2_support) {
-   intel_dp->psr.colorimetry_support =
-   intel_dp_get_colorimetry_status(intel_dp);
-   intel_dp_get_su_granularity(intel_dp);
-   }
+void intel_psr_init_dpcd(struct intel_dp *intel_dp)
+{
+   drm_dp_dpcd_read(_dp->aux, DP_PSR_SUPPORT, intel_dp->psr_dpcd,
+sizeof(intel_dp->psr_dpcd));
+
+   if (intel_dp->psr_dpcd[0])
+   _psr_init_dpcd(intel_dp);
+   /* TODO: Add PR case here */
+
+   if (intel_dp->psr.sink_psr2_support) {
+   intel_dp->psr.colorimetry_support =
+   intel_dp_get_colorimetry_status(intel_dp);
+   intel_dp_get_su_granularity(intel_dp);
}
 }
 
-- 
2.29.0



[Intel-gfx] [PATCH v4 1/6] drm/panelreplay: dpcd register definition for panelreplay

2023-08-23 Thread Animesh Manna
DPCD register definition added to check and enable panel replay
capability of the sink.

Cc: Jouni Högander 
Signed-off-by: Animesh Manna 
---
 include/drm/display/drm_dp.h | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/include/drm/display/drm_dp.h b/include/drm/display/drm_dp.h
index e69cece404b3..a38dc5f1731e 100644
--- a/include/drm/display/drm_dp.h
+++ b/include/drm/display/drm_dp.h
@@ -543,6 +543,10 @@
 /* DFP Capability Extension */
 #define DP_DFP_CAPABILITY_EXTENSION_SUPPORT0x0a3   /* 2.0 */
 
+#define DP_PANEL_REPLAY_CAP 0x0b0
+# define DP_PANEL_REPLAY_SUPPORT(1 << 0)
+# define DP_PANEL_REPLAY_SU_SUPPORT (1 << 1)
+
 /* Link Configuration */
 #defineDP_LINK_BW_SET  0x100
 # define DP_LINK_RATE_TABLE0x00/* eDP 1.4 */
@@ -716,6 +720,13 @@
 #define DP_BRANCH_DEVICE_CTRL  0x1a1
 # define DP_BRANCH_DEVICE_IRQ_HPD  (1 << 0)
 
+#define PANEL_REPLAY_CONFIG 0x1b0
+# define DP_PANEL_REPLAY_ENABLE (1 << 0)
+# define DP_PANEL_REPLAY_UNRECOVERABLE_ERROR(1 << 3)
+# define DP_PANEL_REPLAY_RFB_STORAGE_ERROR  (1 << 4)
+# define DP_PANEL_REPLAY_ACTIVE_FRAME_CRC_ERROR (1 << 5)
+# define DP_PANEL_REPLAY_SU_ENABLE  (1 << 6)
+
 #define DP_PAYLOAD_ALLOCATE_SET0x1c0
 #define DP_PAYLOAD_ALLOCATE_START_TIME_SLOT 0x1c1
 #define DP_PAYLOAD_ALLOCATE_TIME_SLOT_COUNT 0x1c2
-- 
2.29.0



[Intel-gfx] [PATCH v4 0/6] Panel replay phase1 implementation

2023-08-23 Thread Animesh Manna
Panel Replay is a power saving feature for DP 2.0 monitor and similar
to PSR on EDP.

These patches are basic enablement patches added on top of
existing psr framework to enable full-screen live active frame
update mode of panel replay. Panel replay also can be enabled
in selective update mode which will be enabled in a incremental
approach.

As per current design panel replay priority is higher than psr.
intel_dp->psr.panel_replay_enabled flag indicate panel replay is enabled.
intel_dp->psr.panel_replay_enabled + intel_dp->psr.psr2_enabled indicates
panel replay is enabled in selective update mode.
intel_dp->psr.panel_replay_enabled + intel_dp->psr.psr2_enabled +
intel_psr.selective_fetch enabled indicates panel replay is
enabled in selective update mode with selective fetch.
PSR replated flags remain same like before.

Note: The patches are under testing by using panel replay emulator and
panel is not avalible.

Cc: Jouni Högander 
Signed-off-by: Animesh Manna 

Animesh Manna (5):
  drm/panelreplay: dpcd register definition for panelreplay
  drm/i915/panelreplay: Added HAS_PANEL_REPLAY() macro
  drm/i915/panelreplay: Initializaton and compute config for panel
replay
  drm/i915/panelreplay: Enable panel replay dpcd initialization for DP
  drm/i915/panelreplay: enable/disable panel replay

Jouni Högander (1):
  drm/i915/psr: Move psr specific dpcd init into own function

 .../drm/i915/display/intel_display_device.h   |   1 +
 .../drm/i915/display/intel_display_types.h|  13 +-
 drivers/gpu/drm/i915/display/intel_dp.c   |  44 +++-
 drivers/gpu/drm/i915/display/intel_dp_mst.c   |   3 +
 drivers/gpu/drm/i915/display/intel_psr.c  | 197 --
 include/drm/display/drm_dp.h  |  11 +
 6 files changed, 199 insertions(+), 70 deletions(-)

-- 
2.29.0



[Intel-gfx] [PATCH v3 3/6] drm/i915/psr: Move psr specific dpcd init into own function

2023-07-28 Thread Animesh Manna
From: Jouni Högander 

This patch is preparing adding panel replay specific dpcd init.

Signed-off-by: Jouni Högander 
---
 drivers/gpu/drm/i915/display/intel_psr.c | 39 +---
 1 file changed, 22 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index 04ab034a8d57..9fbcb4b93f11 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -472,27 +472,22 @@ static void intel_dp_get_su_granularity(struct intel_dp 
*intel_dp)
intel_dp->psr.su_y_granularity = y;
 }
 
-void intel_psr_init_dpcd(struct intel_dp *intel_dp)
+static void _psr_init_dpcd(struct intel_dp *intel_dp)
 {
-   struct drm_i915_private *dev_priv =
+   struct drm_i915_private *i915 =
to_i915(dp_to_dig_port(intel_dp)->base.base.dev);
 
-   drm_dp_dpcd_read(_dp->aux, DP_PSR_SUPPORT, intel_dp->psr_dpcd,
-sizeof(intel_dp->psr_dpcd));
-
-   if (!intel_dp->psr_dpcd[0])
-   return;
-   drm_dbg_kms(_priv->drm, "eDP panel supports PSR version %x\n",
+   drm_dbg_kms(>drm, "eDP panel supports PSR version %x\n",
intel_dp->psr_dpcd[0]);
 
if (drm_dp_has_quirk(_dp->desc, DP_DPCD_QUIRK_NO_PSR)) {
-   drm_dbg_kms(_priv->drm,
+   drm_dbg_kms(>drm,
"PSR support not currently available for this 
panel\n");
return;
}
 
if (!(intel_dp->edp_dpcd[1] & DP_EDP_SET_POWER_CAP)) {
-   drm_dbg_kms(_priv->drm,
+   drm_dbg_kms(>drm,
"Panel lacks power state control, PSR cannot be 
enabled\n");
return;
}
@@ -501,7 +496,7 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp)
intel_dp->psr.sink_sync_latency =
intel_dp_get_sink_sync_latency(intel_dp);
 
-   if (DISPLAY_VER(dev_priv) >= 9 &&
+   if (DISPLAY_VER(i915) >= 9 &&
(intel_dp->psr_dpcd[0] == DP_PSR2_WITH_Y_COORD_IS_SUPPORTED)) {
bool y_req = intel_dp->psr_dpcd[1] &
 DP_PSR2_SU_Y_COORDINATE_REQUIRED;
@@ -519,14 +514,24 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp)
 * GTC first.
 */
intel_dp->psr.sink_psr2_support = y_req && alpm;
-   drm_dbg_kms(_priv->drm, "PSR2 %ssupported\n",
+   drm_dbg_kms(>drm, "PSR2 %ssupported\n",
intel_dp->psr.sink_psr2_support ? "" : "not ");
+   }
+}
 
-   if (intel_dp->psr.sink_psr2_support) {
-   intel_dp->psr.colorimetry_support =
-   intel_dp_get_colorimetry_status(intel_dp);
-   intel_dp_get_su_granularity(intel_dp);
-   }
+void intel_psr_init_dpcd(struct intel_dp *intel_dp)
+{
+   drm_dp_dpcd_read(_dp->aux, DP_PSR_SUPPORT, intel_dp->psr_dpcd,
+sizeof(intel_dp->psr_dpcd));
+
+   if (intel_dp->psr_dpcd[0])
+   _psr_init_dpcd(intel_dp);
+   /* TODO: Add PR case here */
+
+   if (intel_dp->psr.sink_psr2_support) {
+   intel_dp->psr.colorimetry_support =
+   intel_dp_get_colorimetry_status(intel_dp);
+   intel_dp_get_su_granularity(intel_dp);
}
 }
 
-- 
2.29.0



[Intel-gfx] [PATCH v3 6/6] drm/i915/panelreplay: enable/disable panel replay

2023-07-28 Thread Animesh Manna
TRANS_DP2_CTL register is programmed to enable panel replay from source
and sink is enabled through panel replay dpcd configuration address.

Bspec: 1407940617

v1: Initial version.
v2:
- Use pr_* flags instead psr_* flags. [Jouni]
- Remove intel_dp_is_edp check as edp1.5 also has panel replay. [Jouni]

v3: cover letter updated and selective fetch condition check is added
before updating its bit in PSR2_MAN_TRK_CTL register. [Jouni]

Note: Initial plan is to enable panel replay in  full-screen live active
frame update mode. In a incremental approach panel replay will be enabled
in selctive update mode if there is any gap in curent implementation.

Cc: Jouni Högander 
Signed-off-by: Animesh Manna 
---
 .../drm/i915/display/intel_display_types.h|  1 +
 drivers/gpu/drm/i915/display/intel_psr.c  | 32 ---
 2 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index 1ff7e6c03b44..41fbd49393f3 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1696,6 +1696,7 @@ struct intel_psr {
u16 su_y_granularity;
bool source_panel_replay_support;
bool sink_panel_replay_support;
+   bool pr_enabled;
u32 dc3co_exitline;
u32 dc3co_exit_delay;
struct delayed_work dc3co_work;
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index f6b00abe92d4..244fb336f6bc 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -599,8 +599,14 @@ static void intel_psr_enable_sink(struct intel_dp 
*intel_dp)
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
u8 dpcd_val = DP_PSR_ENABLE;
 
-   /* Enable ALPM at sink for psr2 */
+   if (intel_dp->psr.pr_enabled) {
+   drm_dp_dpcd_writeb(_dp->aux, PANEL_REPLAY_CONFIG,
+  DP_PANEL_REPLAY_ENABLE);
+   return;
+   }
+
if (intel_dp->psr.psr2_enabled) {
+   /* Enable ALPM at sink for psr2 */
drm_dp_dpcd_writeb(_dp->aux, DP_RECEIVER_ALPM_CONFIG,
   DP_ALPM_ENABLE |
   DP_ALPM_LOCK_ERROR_IRQ_HPD_ENABLE);
@@ -750,6 +756,18 @@ static int psr2_block_count(struct intel_dp *intel_dp)
return psr2_block_count_lines(intel_dp) / 4;
 }
 
+static void dg2_activate_panel_replay(struct intel_dp *intel_dp)
+{
+   struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+
+   if (intel_dp->psr.psr2_sel_fetch_enabled)
+   intel_de_rmw(dev_priv, 
PSR2_MAN_TRK_CTL(intel_dp->psr.transcoder),
+0, ADLP_PSR2_MAN_TRK_CTL_SF_PARTIAL_FRAME_UPDATE);
+
+   intel_de_rmw(dev_priv, TRANS_DP2_CTL(intel_dp->psr.transcoder), 0,
+TRANS_DP2_PANEL_REPLAY_ENABLE);
+}
+
 static void hsw_activate_psr2(struct intel_dp *intel_dp)
 {
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
@@ -1361,8 +1379,10 @@ static void intel_psr_activate(struct intel_dp *intel_dp)
 
lockdep_assert_held(_dp->psr.lock);
 
-   /* psr1 and psr2 are mutually exclusive.*/
-   if (intel_dp->psr.psr2_enabled)
+   /* psr1, psr2 and panel-replay are mutually exclusive.*/
+   if (intel_dp->psr.pr_enabled)
+   dg2_activate_panel_replay(intel_dp);
+   else if (intel_dp->psr.psr2_enabled)
hsw_activate_psr2(intel_dp);
else
hsw_activate_psr1(intel_dp);
@@ -1541,6 +1561,7 @@ static void intel_psr_enable_locked(struct intel_dp 
*intel_dp,
drm_WARN_ON(_priv->drm, intel_dp->psr.enabled);
 
intel_dp->psr.psr2_enabled = crtc_state->has_psr2;
+   intel_dp->psr.pr_enabled = crtc_state->has_pr;
intel_dp->psr.busy_frontbuffer_bits = 0;
intel_dp->psr.pipe = to_intel_crtc(crtc_state->uapi.crtc)->pipe;
intel_dp->psr.transcoder = crtc_state->cpu_transcoder;
@@ -1586,7 +1607,10 @@ static void intel_psr_exit(struct intel_dp *intel_dp)
return;
}
 
-   if (intel_dp->psr.psr2_enabled) {
+   if (intel_dp->psr.pr_enabled) {
+   intel_de_rmw(dev_priv, TRANS_DP2_CTL(intel_dp->psr.transcoder),
+TRANS_DP2_PANEL_REPLAY_ENABLE, 0);
+   } else if (intel_dp->psr.psr2_enabled) {
tgl_disallow_dc3co_on_psr2_exit(intel_dp);
 
val = intel_de_rmw(dev_priv, EDP_PSR2_CTL(cpu_transcoder),
-- 
2.29.0



[Intel-gfx] [PATCH v3 5/6] drm/i915/panelreplay: Enable panel replay dpcd initialization for DP

2023-07-28 Thread Animesh Manna
Due to similarity panel replay dpcd initialization got added in psr
function which is specific for edp panel. This patch enables panel
replay initialization for dp connector.

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_psr.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index 7508e6c967e2..f6b00abe92d4 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -2735,6 +2735,9 @@ void intel_psr_init(struct intel_dp *intel_dp)
if (!(HAS_PSR(dev_priv) || HAS_PANEL_REPLAY(dev_priv)))
return;
 
+   if (!intel_dp_is_edp(intel_dp))
+   intel_psr_init_dpcd(intel_dp);
+
/*
 * HSW spec explicitly says PSR is tied to port A.
 * BDW+ platforms have a instance of PSR registers per transcoder but
-- 
2.29.0



[Intel-gfx] [PATCH v3 4/6] drm/i915/panelreplay: Initializaton and compute config for panel replay

2023-07-28 Thread Animesh Manna
Modify existing PSR implementation to enable panel replay feature of DP 2.0
which is similar to PSR feature of EDP panel. There is different DPCD
address to check panel capability compare to PSR and vsc sdp header
is different.

v1: Initial version.
v2:
- Set source_panel_replay_support flag under HAS_PNEL_REPLAY() check. [Jouni]
- Code restructured around intel_panel_replay_init
and renamed to intel_panel_replay_init_dpcd. [Jouni]
- Remove the initial code modification around has_psr2 flag. [Jouni]
- Add CAN_PANEL_REPLAY() in intel_encoder_can_psr which is used to
enable in intel_psr_post_plane_update. [Jouni]
v3:
- Initialize both psr and panel-replay. [Jouni]
- Initialize both panel replay and psr if detected. [Jouni]
- Refactoring psr function by introducing _psr_compute_config(). [Jouni]
- Add check for !is_edp while deriving source_panel_replay_support. [Jouni]
- Enable panel replay dpcd initialization in a separate patch. [Jouni]

Cc: Jouni Högander 
Signed-off-by: Animesh Manna 
---
 .../drm/i915/display/intel_display_types.h|  8 +-
 drivers/gpu/drm/i915/display/intel_dp.c   | 44 --
 drivers/gpu/drm/i915/display/intel_psr.c  | 88 +--
 3 files changed, 104 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index 731f2ec04d5c..1ff7e6c03b44 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1202,6 +1202,7 @@ struct intel_crtc_state {
bool has_psr2;
bool enable_psr2_sel_fetch;
bool req_psr2_sdp_prior_scanline;
+   bool has_pr;
bool wm_level_disabled;
u32 dc3co_exitline;
u16 su_y_granularity;
@@ -1693,6 +1694,8 @@ struct intel_psr {
bool irq_aux_error;
u16 su_w_granularity;
u16 su_y_granularity;
+   bool source_panel_replay_support;
+   bool sink_panel_replay_support;
u32 dc3co_exitline;
u32 dc3co_exit_delay;
struct delayed_work dc3co_work;
@@ -1983,12 +1986,15 @@ dp_to_lspcon(struct intel_dp *intel_dp)
 #define CAN_PSR(intel_dp) ((intel_dp)->psr.sink_support && \
   (intel_dp)->psr.source_support)
 
+#define CAN_PANEL_REPLAY(intel_dp) ((intel_dp)->psr.sink_panel_replay_support 
&& \
+ (intel_dp)->psr.source_panel_replay_support)
+
 static inline bool intel_encoder_can_psr(struct intel_encoder *encoder)
 {
if (!intel_encoder_is_dp(encoder))
return false;
 
-   return CAN_PSR(enc_to_intel_dp(encoder));
+   return CAN_PSR(enc_to_intel_dp(encoder)) || 
CAN_PANEL_REPLAY(enc_to_intel_dp(encoder));
 }
 
 static inline struct intel_digital_port *
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 03675620e3ea..0ba231ee6e34 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1946,12 +1946,22 @@ static void intel_dp_compute_vsc_colorimetry(const 
struct intel_crtc_state *crtc
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 
-   /*
-* Prepare VSC Header for SU as per DP 1.4 spec, Table 2-118
-* VSC SDP supporting 3D stereo, PSR2, and Pixel Encoding/
-* Colorimetry Format indication.
-*/
-   vsc->revision = 0x5;
+   if (crtc_state->has_pr) {
+   /*
+* Prepare VSC Header for SU as per DP 2.0 spec, Table 2-223
+* VSC SDP supporting 3D stereo, Panel Replay, and Pixel
+* Encoding/Colorimetry Format indication.
+*/
+   vsc->revision = 0x7;
+   } else {
+   /*
+* Prepare VSC Header for SU as per DP 1.4 spec, Table 2-118
+* VSC SDP supporting 3D stereo, PSR2, and Pixel Encoding/
+* Colorimetry Format indication.
+*/
+   vsc->revision = 0x5;
+   }
+
vsc->length = 0x13;
 
/* DP 1.4a spec, Table 2-120 */
@@ -2060,6 +2070,21 @@ void intel_dp_compute_psr_vsc_sdp(struct intel_dp 
*intel_dp,
vsc->revision = 0x4;
vsc->length = 0xe;
}
+   } else if (crtc_state->has_pr) {
+   if (intel_dp->psr.colorimetry_support &&
+   intel_dp_needs_vsc_sdp(crtc_state, conn_state)) {
+   /* [Panel Replay with colorimetry info] */
+   intel_dp_compute_vsc_colorimetry(crtc_state, conn_state,
+vsc);
+   } else {
+   /*
+* [Panel Replay without colorimetry info]
+* Prepare VSC Header for S

  1   2   3   4   5   6   >