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

2024-05-29 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]

Reviewed-by: Jouni Högander 
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 7b22b66bda6a..4b337bcd9c90 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -1685,7 +1685,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 v7 6/6] drm/i915/alpm: Add debugfs for LOBF

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

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

Reviewed-by: Jouni Högander 
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 v7 4/6] drm/i915/alpm: Add compute config for lobf

2024-05-29 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]

Reviewed-by: Jouni Högander 
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 f03b598638d7..012ff9e18b54 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 */
+   

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

2024-05-29 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]

Reviewed-by: Jouni Högander 
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 c8c8b31da4fb..211b51b21279 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 *

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

2024-05-29 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.

Acked-by: Maxime Ripard 
Reviewed-by: Ankit Nautiyal 
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 79bde372b152..f246fa03a3cb 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)
@@ -684,7 +686,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 v7 1/6] drm/i915/alpm: Move alpm parameters from intel_psr

2024-05-29 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.

Reviewed-by: Jouni Högander 
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 6fbfe8a18f45..f03b598638d7 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;
@@ -1847,6 +1836,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 19f8ac12f995..977a7eaa0cde 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -864,8 +864,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)
@@ -903,7 +903,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;
@@ -945,20 +944,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)
@@ -1341,9 +1340,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.s

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

2024-05-29 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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



[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

[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

[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) {
+ 

[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



[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



[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



[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



[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

[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) {
+ 

[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) {
+ 

[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



[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



[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



[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 

[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

[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) {
+ 

[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



[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



[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



[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



[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",
+

[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 {
+   /*
+  

[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 &&
+  

[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



[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



[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



[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



[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)
+ 

[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

[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



[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)) {
+   

[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



[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



[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



[PATCH] drm/i915/dp: Cable type identification for DP2.1

2023-06-09 Thread Animesh Manna
For DP alt mode display driver get the information
about cable speed and cable type through TCSS_DDI_STATUS
register which will be updated by type-c platform driver.
Accodingly Update dpcd 0x110 with cable information before
link training start. This change came part of DP2.1 SCR.

Note: This patch is not tested due to unavailability of
cable. Sending as RFC for design review.

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_ddi.c | 57 
 drivers/gpu/drm/i915/display/intel_tc.c  | 10 +
 drivers/gpu/drm/i915/display/intel_tc.h  |  1 +
 drivers/gpu/drm/i915/i915_reg.h  |  5 +++
 include/drm/display/drm_dp.h |  9 
 5 files changed, 82 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
b/drivers/gpu/drm/i915/display/intel_ddi.c
index 70d44edd8c6e..3a0f6a3c9f98 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -2208,6 +2208,55 @@ static void 
intel_dp_sink_set_msa_timing_par_ignore_state(struct intel_dp *intel
str_enable_disable(enable));
 }
 
+#define CABLE_SPEED_SHIFT 4
+
+enum dp_cable_speed {
+   DP_CABLE_HBR3 = 1,
+   DP_CABLE_UHBR10,
+   DP_CABLE_GEN3_UHBR20,
+   DP_CABLE_GEN4_UHBR20
+};
+
+static void intel_dp_set_cable_attributes(struct intel_dp *intel_dp,
+ u8 cable_attributes)
+{
+   u8 cable_speed;
+   bool active_cable, retimer;
+   u8 cable_attr_dpcd;
+
+   cable_speed = cable_attributes >> CABLE_SPEED_SHIFT;
+
+   switch (cable_speed) {
+   case DP_CABLE_HBR3:
+   cable_attr_dpcd = 0;
+   break;
+   case DP_CABLE_UHBR10:
+   cable_attr_dpcd = 1;
+   break;
+   case DP_CABLE_GEN3_UHBR20:
+   case DP_CABLE_GEN4_UHBR20:
+   cable_attr_dpcd = 2;
+   break;
+   default:
+   cable_attr_dpcd = 0;
+   break;
+   }
+
+   active_cable = (cable_attributes << TCSS_DDI_STATUS_CABLE_ATTR_SHIFT) &
+  TCSS_DDI_STATUS_ACTIVE_CABLE;
+   retimer = (cable_attributes << TCSS_DDI_STATUS_CABLE_ATTR_SHIFT) &
+ TCSS_DDI_STATUS_RETIMER_REDRIVER;
+   if (retimer && active_cable)
+   cable_attr_dpcd |= DP_CABLE_TYPE_RETIMER_ACTIVE;
+   else if (active_cable)
+   cable_attr_dpcd |= DP_CABLE_TYPE_LRD_ACTIVE;
+   else
+   cable_attr_dpcd |= DP_CABLE_TYPE_PASSIVE;
+
+   drm_dp_dpcd_writeb(_dp->aux, DP_CABLE_ATTRIBUTES_UPDATED_BY_TX,
+  cable_attr_dpcd);
+}
+
 static void intel_dp_sink_set_fec_ready(struct intel_dp *intel_dp,
const struct intel_crtc_state 
*crtc_state)
 {
@@ -2414,6 +2463,7 @@ static void mtl_ddi_pre_enable_dp(struct 
intel_atomic_state *state,
 {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
bool is_mst = intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST);
+   struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
 
intel_dp_set_link_params(intel_dp,
 crtc_state->port_clock,
@@ -2480,6 +2530,13 @@ static void mtl_ddi_pre_enable_dp(struct 
intel_atomic_state *state,
intel_dp_check_frl_training(intel_dp);
intel_dp_pcon_dsc_configure(intel_dp, crtc_state);
 
+   if (intel_tc_port_in_dp_alt_mode(dig_port)) {
+   u8 cable_attributes;
+
+   cable_attributes = intel_tc_get_cable_attributes(dig_port);
+   intel_dp_set_cable_attributes(intel_dp, cable_attributes);
+   }
+
/*
 * 6. The rest of the below are substeps under the bspec's "Enable and
 * Train Display Port" step.  Note that steps that are specific to
diff --git a/drivers/gpu/drm/i915/display/intel_tc.c 
b/drivers/gpu/drm/i915/display/intel_tc.c
index 3ebf41859043..6b10a8839563 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -260,6 +260,16 @@ assert_tc_port_power_enabled(struct intel_tc_port *tc)
!intel_display_power_is_enabled(i915, 
tc_port_power_domain(tc)));
 }
 
+u8 intel_tc_get_cable_attributes(struct intel_digital_port *dig_port)
+{
+   struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+   enum tc_port tc_port = intel_port_to_tc(i915, dig_port->base.port);
+
+   return (intel_de_read(i915, TCSS_DDI_STATUS(tc_port)) &
+   TCSS_DDI_STATUS_CABLE_ATTR_MASK) >>
+   TCSS_DDI_STATUS_CABLE_ATTR_SHIFT;
+}
+
 u32 intel_tc_port_get_lane_mask(struct intel_digital_port *dig_port)
 {
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
diff --git a/drivers/gpu/drm/i915/display/intel_tc.h 
b/drivers/gpu/drm/i915/display/intel_tc.h
index 3b16491925fa..edafe92844b4 100644
---

[PATCH v3 5/5] drm/i915/panelreplay: Added state checker for panel replay state

2021-10-10 Thread Animesh Manna
has_panel_replay flag is used to check panel replay state
which is part of crtc_state structure.

v1: RFC version.
v2: has_panel_replay flag updated as per hw readout. [Jani]

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

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 4f0badb11bbb..a30b6fe87dfc 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -8136,6 +8136,7 @@ intel_pipe_config_compare(const struct intel_crtc_state 
*current_config,
PIPE_CONF_CHECK_BOOL(has_psr);
PIPE_CONF_CHECK_BOOL(has_psr2);
PIPE_CONF_CHECK_BOOL(enable_psr2_sel_fetch);
+   PIPE_CONF_CHECK_BOOL(has_panel_replay);
PIPE_CONF_CHECK_I(dc3co_exitline);
}
}
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index 49f6242c2fde..d1a30b82ce6f 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -1054,6 +1054,12 @@ void intel_psr_get_config(struct intel_encoder *encoder,
pipe_config->has_psr2 = intel_dp->psr.psr2_enabled;
pipe_config->infoframes.enable |= 
intel_hdmi_infoframe_enable(DP_SDP_VSC);
 
+   if (HAS_PANEL_REPLAY(dev_priv) && HAS_DP20(dev_priv)) {
+   val = intel_de_read(dev_priv, 
TRANS_DP2_CTL(intel_dp->psr.transcoder));
+   if (val & TRANS_DP2_PANEL_REPLAY_ENABLE)
+   pipe_config->has_panel_replay = true;
+   }
+
if (!intel_dp->psr.psr2_enabled)
goto unlock;
 
-- 
2.29.0



[PATCH v3 4/5] drm/i915/panelreplay: enable/disable panel replay

2021-10-10 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.

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_psr.c | 30 
 drivers/gpu/drm/i915/i915_reg.h  |  1 +
 2 files changed, 27 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index 91c2efe2f3ad..49f6242c2fde 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -370,8 +370,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.enabled && !intel_dp_is_edp(intel_dp)) {
+   drm_dp_dpcd_writeb(_dp->aux, PANEL_REPLAY_CONFIG,
+  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);
@@ -498,6 +504,17 @@ static u32 intel_psr2_get_tp_time(struct intel_dp 
*intel_dp)
return val;
 }
 
+static void dg2_activate_panel_replay(struct intel_dp *intel_dp)
+{
+   struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+
+   intel_de_write(dev_priv, PSR2_MAN_TRK_CTL(intel_dp->psr.transcoder),
+  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);
@@ -1069,8 +1086,10 @@ static void intel_psr_activate(struct intel_dp *intel_dp)
drm_WARN_ON(_priv->drm, intel_dp->psr.active);
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.enabled && !intel_dp_is_edp(intel_dp))
+   dg2_activate_panel_replay(intel_dp);
+   else if (intel_dp->psr.psr2_enabled)
hsw_activate_psr2(intel_dp);
else
hsw_activate_psr1(intel_dp);
@@ -1243,7 +1262,10 @@ static void intel_psr_exit(struct intel_dp *intel_dp)
return;
}
 
-   if (intel_dp->psr.psr2_enabled) {
+   if (intel_dp->psr.enabled && !intel_dp_is_edp(intel_dp)) {
+   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_read(dev_priv,
EDP_PSR2_CTL(intel_dp->psr.transcoder));
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index a897f4abea0c..6cc6ebcd3bdb 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -4725,6 +4725,7 @@ enum {
 #define  PSR2_MAN_TRK_CTL_SF_SINGLE_FULL_FRAME REG_BIT(3)
 #define  PSR2_MAN_TRK_CTL_SF_CONTINUOS_FULL_FRAME  REG_BIT(2)
 #define  PSR2_MAN_TRK_CTL_SF_PARTIAL_FRAME_UPDATE  REG_BIT(1)
+#define  ADLP_PSR2_MAN_TRK_CTL_SF_PARTIAL_FRAME_UPDATE REG_BIT(31)
 #define  ADLP_PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR_MASK   REG_GENMASK(28, 
16)
 #define  ADLP_PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR(val)   
REG_FIELD_PREP(ADLP_PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR_MASK, val)
 #define  ADLP_PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR_MASK REG_GENMASK(12, 
0)
-- 
2.29.0



[PATCH v3 3/5] drm/i915/panelreplay: Initializaton and compute config for panel replay

2021-10-10 Thread Animesh Manna
As panel replay feature similar to PSR feature of EDP panel, so currently
utilized existing psr framework for panel replay.

v1: RFC version.
v2: optimized code, pr_enabled and pr_dpcd variable removed. [Jose]
v3:
- code comments improved. [Jani]
- dpcd_readb used instead of dpcd_read. [Jani]
- panel-repaplay init/compute functions moved inside respective psr
function. [Jani]

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

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index 39e11eaec1a3..48f7d676ed2c 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1070,6 +1070,7 @@ struct intel_crtc_state {
bool req_psr2_sdp_prior_scanline;
u32 dc3co_exitline;
u16 su_y_granularity;
+   bool has_panel_replay;
struct drm_dp_vsc_sdp psr_vsc;
 
/*
@@ -1531,6 +1532,7 @@ struct intel_psr {
bool irq_aux_error;
u16 su_w_granularity;
u16 su_y_granularity;
+   bool sink_panel_replay_support;
u32 dc3co_exitline;
u32 dc3co_exit_delay;
struct delayed_work dc3co_work;
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 10fda20a5bd8..f58a7b72be14 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1587,12 +1587,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 */
@@ -1701,6 +1711,21 @@ void intel_dp_compute_psr_vsc_sdp(struct intel_dp 
*intel_dp,
vsc->revision = 0x4;
vsc->length = 0xe;
}
+   } else if (intel_dp->psr.enabled && !intel_dp_is_edp(intel_dp)) {
+   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 SU as per DP 2.0 spec, Table 
2-223
+* VSC SDP supporting 3D stereo + Panel Replay.
+*/
+   vsc->revision = 0x6;
+   vsc->length = 0x10;
+   }
} else {
/*
 * [PSR1]
@@ -2749,10 +2774,10 @@ static ssize_t intel_dp_vsc_sdp_pack(const struct 
drm_dp_vsc_sdp *vsc,
sdp->sdp_header.HB3 = vsc->length; /* Number of Valid Data Bytes */
 
/*
-* Only revision 0x5 supports Pixel Encoding/Colorimetry Format as
-* per DP 1.4a spec.
+* Revision 0x5 and 0x7 supports Pixel Encoding/Colorimetry Format as
+* per DP 1.4a spec and DP 2.0 spec respectively.
 */
-   if (vsc->revision != 0x5)
+   if (vsc->revision != 0x5 || vsc->revision != 0x7)
goto out;
 
/* VSC SDP Payload for DB16 through DB18 */
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index 7a205fd5023b..91c2efe2f3ad 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -933,6 +933,21 @@ static bool intel_psr2_config_valid(struct intel_dp 
*intel_dp,
return true;

[PATCH v3 2/5] drm/i915/panelreplay: HAS_PR() macro added for panel replay

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

v1: Initial version.
v2: DISPLAY_VER macro used instead of has_pr flag. [Jose]
v3: HAS_PR renamed to HAS_PANEL_REPLAY. [Jani]

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/i915_drv.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 12256218634f..37313bf51a90 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1693,6 +1693,7 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
 #define HAS_DDI(dev_priv)   (INTEL_INFO(dev_priv)->display.has_ddi)
 #define HAS_FPGA_DBG_UNCLAIMED(dev_priv) 
(INTEL_INFO(dev_priv)->display.has_fpga_dbg)
 #define HAS_PSR(dev_priv)   (INTEL_INFO(dev_priv)->display.has_psr)
+#define HAS_PANEL_REPLAY(dev_priv)  (DISPLAY_VER(dev_priv) >= 13)
 #define HAS_PSR_HW_TRACKING(dev_priv) \
(INTEL_INFO(dev_priv)->display.has_psr_hw_tracking)
 #define HAS_PSR2_SEL_FETCH(dev_priv)(GRAPHICS_VER(dev_priv) >= 12)
-- 
2.29.0



[PATCH v3 1/5] drm/i915/panelreplay: dpcd register definition for panelreplay

2021-10-10 Thread Animesh Manna
DPCD register definition added to check and enable panel replay
capability of the sink.

Signed-off-by: Animesh Manna 
---
 include/drm/drm_dp_helper.h | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index b52df4db3e8f..8a2b929c3f88 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -541,6 +541,9 @@ struct drm_panel;
 /* DFP Capability Extension */
 #define DP_DFP_CAPABILITY_EXTENSION_SUPPORT0x0a3   /* 2.0 */
 
+#define DP_PANEL_REPLAY_CAP 0x0b0
+# define PANEL_REPLAY_SUPPORT   (1 << 0)
+
 /* Link Configuration */
 #defineDP_LINK_BW_SET  0x100
 # define DP_LINK_RATE_TABLE0x00/* eDP 1.4 */
@@ -709,6 +712,9 @@ struct drm_panel;
 #define DP_BRANCH_DEVICE_CTRL  0x1a1
 # define DP_BRANCH_DEVICE_IRQ_HPD  (1 << 0)
 
+#define PANEL_REPLAY_CONFIG 0x1b0
+# define PANEL_REPLAY_ENABLE(1 << 0)
+
 #define DP_PAYLOAD_ALLOCATE_SET0x1c0
 #define DP_PAYLOAD_ALLOCATE_START_TIME_SLOT 0x1c1
 #define DP_PAYLOAD_ALLOCATE_TIME_SLOT_COUNT 0x1c2
-- 
2.29.0



[PATCH v3 0/5] Panel replay phase1 implementation

2021-10-10 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 and reused psr
framework to add panel replay related new changes which
may need further fine tuning to fill the gap if there is any.

Note: The patches are not tested due to unavailability of monitor

Animesh Manna (5):
  drm/i915/panelreplay: dpcd register definition for panelreplay
  drm/i915/panelreplay: HAS_PR() macro added for panel replay
  drm/i915/panelreplay: Initializaton and compute config for panel
replay
  drm/i915/panelreplay: enable/disable panel replay
  drm/i915/panelreplay: Added state checker for panel replay state

 drivers/gpu/drm/i915/display/intel_display.c  |  1 +
 .../drm/i915/display/intel_display_types.h|  2 +
 drivers/gpu/drm/i915/display/intel_dp.c   | 43 --
 drivers/gpu/drm/i915/display/intel_psr.c  | 84 ++-
 drivers/gpu/drm/i915/display/intel_psr.h  |  3 +
 drivers/gpu/drm/i915/i915_drv.h   |  1 +
 drivers/gpu/drm/i915/i915_reg.h   |  1 +
 include/drm/drm_dp_helper.h   |  6 ++
 8 files changed, 128 insertions(+), 13 deletions(-)

-- 
2.29.0



[PATCH v3 7/9] drm/i915/dp: Register definition for DP compliance register

2019-12-30 Thread Animesh Manna
DP_COMP_CTL and DP_COMP_PAT register used to program DP
compliance pattern.

Reviewed-by: Manasi Navare 
Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/i915_reg.h | 20 
 1 file changed, 20 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 030a3f3e69af..a536d920324c 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -9794,6 +9794,26 @@ enum skl_power_gate {
 #define  DDI_BUF_BALANCE_LEG_ENABLE(1 << 31)
 #define DDI_BUF_TRANS_HI(port, i)  _MMIO(_PORT(port, _DDI_BUF_TRANS_A, 
_DDI_BUF_TRANS_B) + (i) * 8 + 4)
 
+/* DDI DP Compliance Control */
+#define DDI_DP_COMP_CTL_A  0x605F0
+#define DDI_DP_COMP_CTL_B  0x615F0
+#define DDI_DP_COMP_CTL(port) _MMIO_PORT(port, DDI_DP_COMP_CTL_A, \
+DDI_DP_COMP_CTL_B)
+#define  DDI_DP_COMP_CTL_ENABLE(1 << 31)
+#define  DDI_DP_COMP_CTL_D10_2 (0 << 28)
+#define  DDI_DP_COMP_CTL_SCRAMBLED_0   (1 << 28)
+#define  DDI_DP_COMP_CTL_PRBS7 (2 << 28)
+#define  DDI_DP_COMP_CTL_CUSTOM80  (3 << 28)
+#define  DDI_DP_COMP_CTL_HBR2  (4 << 28)
+#define  DDI_DP_COMP_CTL_SCRAMBLED_1   (5 << 28)
+#define  DDI_DP_COMP_CTL_HBR2_RESET(0xFC << 0)
+
+/* DDI DP Compliance Pattern */
+#define DDI_DP_COMP_PAT_A  0x605F4
+#define DDI_DP_COMP_PAT_B  0x615F4
+#define DDI_DP_COMP_PAT(port, i) _MMIO(_PORT(port, DDI_DP_COMP_PAT_A, \
+DDI_DP_COMP_PAT_B) + (i) * 4)
+
 /* Sideband Interface (SBI) is programmed indirectly, via
  * SBI_ADDR, which contains the register offset; and SBI_DATA,
  * which contains the payload */
-- 
2.24.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v3 5/9] drm/i915/dsb: Send uevent to testapp.

2019-12-30 Thread Animesh Manna
Send uevent to testapp and set test_active flag. To align with link
compliance design existing intel_dp_compliance tool will be used to
get the phy request in userspace through uevent.

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

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index fa67b8f88e65..cbefda9b6204 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -5013,6 +5013,9 @@ static u8 intel_dp_autotest_phy_pattern(struct intel_dp 
*intel_dp)
if (test_result != DP_TEST_ACK)
DRM_ERROR("Phy test preparation failed\n");
 
+   /* Set test active flag here so userspace doesn't interrupt things */
+   intel_dp->compliance.test_active = 1;
+
return test_result;
 }
 
@@ -5338,8 +5341,11 @@ intel_dp_short_pulse(struct intel_dp *intel_dp)
 
intel_psr_short_pulse(intel_dp);
 
-   if (intel_dp->compliance.test_type == DP_TEST_LINK_TRAINING) {
-   DRM_DEBUG_KMS("Link Training Compliance Test requested\n");
+   if (intel_dp->compliance.test_type == DP_TEST_LINK_TRAINING ||
+   intel_dp->compliance.test_type ==
+   DP_TEST_LINK_PHY_TEST_PATTERN) {
+   DRM_DEBUG_KMS("Compliance Test requested, test-type = 0x%lx\n",
+ intel_dp->compliance.test_type);
/* Send a Hotplug Uevent to userspace to start modeset */
drm_kms_helper_hotplug_event(_priv->drm);
}
-- 
2.24.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v3 1/9] drm/amd/display: Align macro name as per DP spec

2019-12-30 Thread Animesh Manna
[Why]:
Aligh with DP spec wanted to follow same naming convention.

[How]:
Changed the macro name of the dpcd address used for getting requested
test-pattern.

Cc: Harry Wentland 
Cc: Alex Deucher 
Reviewed-by: Harry Wentland 
Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 +-
 include/drm/drm_dp_helper.h  | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c 
b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
index 42aa889fd0f5..1a6109be2fce 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
@@ -2491,7 +2491,7 @@ static void dp_test_send_phy_test_pattern(struct dc_link 
*link)
/* get phy test pattern and pattern parameters from DP receiver */
core_link_read_dpcd(
link,
-   DP_TEST_PHY_PATTERN,
+   DP_PHY_TEST_PATTERN,
_test_pattern.raw,
sizeof(dpcd_test_pattern));
core_link_read_dpcd(
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index 8f8f3632e697..d6e560870fb1 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -699,7 +699,7 @@
 # define DP_TEST_CRC_SUPPORTED (1 << 5)
 # define DP_TEST_COUNT_MASK0xf
 
-#define DP_TEST_PHY_PATTERN 0x248
+#define DP_PHY_TEST_PATTERN 0x248
 #define DP_TEST_80BIT_CUSTOM_PATTERN_7_00x250
 #defineDP_TEST_80BIT_CUSTOM_PATTERN_15_8   0x251
 #defineDP_TEST_80BIT_CUSTOM_PATTERN_23_16  0x252
-- 
2.24.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v3 8/9] drm/i915/dp: Update the pattern as per request

2019-12-30 Thread Animesh Manna
As per request from DP phy compliance test few special
test pattern need to set by source. Added function
to set pattern in DP_COMP_CTL register. It will be
called along with other test parameters like vswing,
pre-emphasis programming in atomic_commit_tail path.

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

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index cbefda9b6204..7c3f65e5d88b 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -5005,6 +5005,61 @@ static u8 intel_dp_prepare_phytest(struct intel_dp 
*intel_dp)
return DP_TEST_ACK;
 }
 
+static inline void intel_dp_phy_pattern_update(struct intel_dp *intel_dp)
+{
+   struct drm_i915_private *dev_priv =
+   to_i915(dp_to_dig_port(intel_dp)->base.base.dev);
+   struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+   struct drm_dp_phy_test_params *data =
+   _dp->compliance.test_data.phytest;
+   u32 temp;
+
+   switch (data->phy_pattern) {
+   case DP_PHY_TEST_PATTERN_NONE:
+   DRM_DEBUG_KMS("Disable Phy Test Pattern\n");
+   I915_WRITE(DDI_DP_COMP_CTL(intel_dig_port->base.port), 0x0);
+   break;
+   case DP_PHY_TEST_PATTERN_D10_2:
+   DRM_DEBUG_KMS("Set D10.2 Phy Test Pattern\n");
+   I915_WRITE(DDI_DP_COMP_CTL(intel_dig_port->base.port),
+  DDI_DP_COMP_CTL_ENABLE | DDI_DP_COMP_CTL_D10_2);
+   break;
+   case DP_PHY_TEST_PATTERN_ERROR_COUNT:
+   DRM_DEBUG_KMS("Set Error Count Phy Test Pattern\n");
+   I915_WRITE(DDI_DP_COMP_CTL(intel_dig_port->base.port),
+  DDI_DP_COMP_CTL_ENABLE |
+  DDI_DP_COMP_CTL_SCRAMBLED_0);
+   break;
+   case DP_PHY_TEST_PATTERN_PRBS7:
+   DRM_DEBUG_KMS("Set PRBS7 Phy Test Pattern\n");
+   I915_WRITE(DDI_DP_COMP_CTL(intel_dig_port->base.port),
+  DDI_DP_COMP_CTL_ENABLE | DDI_DP_COMP_CTL_PRBS7);
+   break;
+   case DP_PHY_TEST_PATTERN_80BIT_CUSTOM:
+   DRM_DEBUG_KMS("Set 80Bit Custom Phy Test Pattern\n");
+   temp = ((data->custom80[0] << 24) | (data->custom80[1] << 16) |
+   (data->custom80[2] << 8) | (data->custom80[3]));
+   I915_WRITE(DDI_DP_COMP_PAT(intel_dig_port->base.port, 0), temp);
+   temp = ((data->custom80[4] << 24) | (data->custom80[5] << 16) |
+   (data->custom80[6] << 8) | (data->custom80[7]));
+   I915_WRITE(DDI_DP_COMP_PAT(intel_dig_port->base.port, 1), temp);
+   temp = ((data->custom80[8] << 8) | data->custom80[9]);
+   I915_WRITE(DDI_DP_COMP_PAT(intel_dig_port->base.port, 2), temp);
+   I915_WRITE(DDI_DP_COMP_CTL(intel_dig_port->base.port),
+  DDI_DP_COMP_CTL_ENABLE | DDI_DP_COMP_CTL_CUSTOM80);
+   break;
+   case DP_PHY_TEST_PATTERN_CP2520:
+   DRM_DEBUG_KMS("Set HBR2 compliance Phy Test Pattern\n");
+   temp = ((data->hbr2_reset[1] << 8) | data->hbr2_reset[0]);
+   I915_WRITE(DDI_DP_COMP_CTL(intel_dig_port->base.port),
+  DDI_DP_COMP_CTL_ENABLE | DDI_DP_COMP_CTL_HBR2 |
+  temp);
+   break;
+   default:
+   WARN(1, "Invalid Phy Test PAttern\n");
+   }
+}
+
 static u8 intel_dp_autotest_phy_pattern(struct intel_dp *intel_dp)
 {
u8 test_result = DP_TEST_NAK;
-- 
2.24.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v3 3/9] drm/i915/dp: Move vswing/pre-emphasis adjustment calculation

2019-12-30 Thread Animesh Manna
vswing/pre-emphasis adjustment calculation is needed in processing
of auto phy compliance request other than link training, so moved
the same function in intel_dp.c.

No functional change.

v1: initial patch.
v2:
- used "intel_dp" prefix in function name. (Jani)
- used array notation instead pointer for link_status. (Ville)

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_dp.c   | 34 ++
 drivers/gpu/drm/i915/display/intel_dp.h   |  4 +++
 .../drm/i915/display/intel_dp_link_training.c | 36 ++-
 3 files changed, 40 insertions(+), 34 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 991f343579ef..2a27ee106089 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -4110,6 +4110,40 @@ ivb_cpu_edp_signal_levels(u8 train_set)
}
 }
 
+void
+intel_dp_get_adjust_train(struct intel_dp *intel_dp,
+ const u8 link_status[DP_LINK_STATUS_SIZE])
+{
+   u8 v = 0;
+   u8 p = 0;
+   int lane;
+   u8 voltage_max;
+   u8 preemph_max;
+
+   for (lane = 0; lane < intel_dp->lane_count; lane++) {
+   u8 this_v = drm_dp_get_adjust_request_voltage(link_status,
+ lane);
+   u8 this_p = drm_dp_get_adjust_request_pre_emphasis(link_status,
+  lane);
+
+   if (this_v > v)
+   v = this_v;
+   if (this_p > p)
+   p = this_p;
+   }
+
+   voltage_max = intel_dp_voltage_max(intel_dp);
+   if (v >= voltage_max)
+   v = voltage_max | DP_TRAIN_MAX_SWING_REACHED;
+
+   preemph_max = intel_dp_pre_emphasis_max(intel_dp, v);
+   if (p >= preemph_max)
+   p = preemph_max | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
+
+   for (lane = 0; lane < 4; lane++)
+   intel_dp->train_set[lane] = v | p;
+}
+
 void
 intel_dp_set_signal_levels(struct intel_dp *intel_dp)
 {
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h 
b/drivers/gpu/drm/i915/display/intel_dp.h
index 3da166054788..83eadc87af26 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -9,6 +9,7 @@
 #include 
 
 #include 
+#include 
 
 #include "i915_reg.h"
 
@@ -91,6 +92,9 @@ void
 intel_dp_program_link_training_pattern(struct intel_dp *intel_dp,
   u8 dp_train_pat);
 void
+intel_dp_get_adjust_train(struct intel_dp *intel_dp,
+ const u8 link_status[DP_LINK_STATUS_SIZE]);
+void
 intel_dp_set_signal_levels(struct intel_dp *intel_dp);
 void intel_dp_set_idle_link_train(struct intel_dp *intel_dp);
 u8
diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c 
b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
index 2a1130dd1ad0..e8ff9e279800 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
@@ -34,38 +34,6 @@ intel_dp_dump_link_status(const u8 
link_status[DP_LINK_STATUS_SIZE])
  link_status[3], link_status[4], link_status[5]);
 }
 
-static void
-intel_get_adjust_train(struct intel_dp *intel_dp,
-  const u8 link_status[DP_LINK_STATUS_SIZE])
-{
-   u8 v = 0;
-   u8 p = 0;
-   int lane;
-   u8 voltage_max;
-   u8 preemph_max;
-
-   for (lane = 0; lane < intel_dp->lane_count; lane++) {
-   u8 this_v = drm_dp_get_adjust_request_voltage(link_status, 
lane);
-   u8 this_p = drm_dp_get_adjust_request_pre_emphasis(link_status, 
lane);
-
-   if (this_v > v)
-   v = this_v;
-   if (this_p > p)
-   p = this_p;
-   }
-
-   voltage_max = intel_dp_voltage_max(intel_dp);
-   if (v >= voltage_max)
-   v = voltage_max | DP_TRAIN_MAX_SWING_REACHED;
-
-   preemph_max = intel_dp_pre_emphasis_max(intel_dp, v);
-   if (p >= preemph_max)
-   p = preemph_max | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
-
-   for (lane = 0; lane < 4; lane++)
-   intel_dp->train_set[lane] = v | p;
-}
-
 static bool
 intel_dp_set_link_train(struct intel_dp *intel_dp,
u8 dp_train_pat)
@@ -215,7 +183,7 @@ intel_dp_link_training_clock_recovery(struct intel_dp 
*intel_dp)
voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
 
/* Update training set as requested by target */
-   intel_get_adjust_train(intel_dp, link_status);
+   intel_dp_get_adjust_train(intel_dp, link_status);
if (!intel_dp_update_link_train(intel_dp)) {
DRM_ERROR("failed to 

[PATCH v3 4/9] drm/i915/dp: Preparation for DP phy compliance auto test

2019-12-30 Thread Animesh Manna
During DP phy compliance auto test mode, sink will request
combination of different test pattern with differnt level of
vswing, pre-emphasis. Function added to prepare for it.

Reviewed-by: Manasi Navare 
Signed-off-by: Animesh Manna 
---
 .../drm/i915/display/intel_display_types.h|  1 +
 drivers/gpu/drm/i915/display/intel_dp.c   | 24 +++
 2 files changed, 25 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index 630a94892b7b..32f0740e4569 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_dp_compliance_data {
u8 video_pattern;
u16 hdisplay, vdisplay;
u8 bpc;
+   struct drm_dp_phy_test_params phytest;
 };
 
 struct intel_dp_compliance {
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 2a27ee106089..fa67b8f88e65 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -4986,9 +4986,33 @@ static u8 intel_dp_autotest_edid(struct intel_dp 
*intel_dp)
return test_result;
 }
 
+static u8 intel_dp_prepare_phytest(struct intel_dp *intel_dp)
+{
+   struct drm_dp_phy_test_params *data =
+   _dp->compliance.test_data.phytest;
+
+   if (drm_dp_get_phy_test_pattern(_dp->aux, data)) {
+   DRM_DEBUG_KMS("DP Phy Test pattern AUX read failure\n");
+   return DP_TEST_NAK;
+   }
+
+   /*
+* link_mst is set to false to avoid executing mst related code
+* during compliance testing.
+*/
+   intel_dp->link_mst = false;
+
+   return DP_TEST_ACK;
+}
+
 static u8 intel_dp_autotest_phy_pattern(struct intel_dp *intel_dp)
 {
u8 test_result = DP_TEST_NAK;
+
+   test_result = intel_dp_prepare_phytest(intel_dp);
+   if (test_result != DP_TEST_ACK)
+   DRM_ERROR("Phy test preparation failed\n");
+
return test_result;
 }
 
-- 
2.24.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v3 6/9] drm/i915/dp: Add debugfs entry for DP phy compliance.

2019-12-30 Thread Animesh Manna
These debugfs entry will help testapp to understand the test request
during dp phy compliance mode.

Acked-by: Manasi Navare 
Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/i915_debugfs.c | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c 
b/drivers/gpu/drm/i915/i915_debugfs.c
index 0ac98e39eb75..a903ed0632cb 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -3177,6 +3177,16 @@ static int i915_displayport_test_data_show(struct 
seq_file *m, void *data)
   
intel_dp->compliance.test_data.vdisplay);
seq_printf(m, "bpc: %u\n",
   intel_dp->compliance.test_data.bpc);
+   } else if (intel_dp->compliance.test_type ==
+  DP_TEST_LINK_PHY_TEST_PATTERN) {
+   seq_printf(m, "pattern: %d\n",
+  
intel_dp->compliance.test_data.phytest.phy_pattern);
+   seq_printf(m, "Number of lanes: %d\n",
+  
intel_dp->compliance.test_data.phytest.num_lanes);
+   seq_printf(m, "Link Rate: %d\n",
+  
intel_dp->compliance.test_data.phytest.link_rate);
+   seq_printf(m, "level: %02x\n",
+  intel_dp->train_set[0]);
}
} else
seq_puts(m, "0");
@@ -3209,7 +3219,7 @@ static int i915_displayport_test_type_show(struct 
seq_file *m, void *data)
 
if (encoder && connector->status == connector_status_connected) 
{
intel_dp = enc_to_intel_dp(>base);
-   seq_printf(m, "%02lx", intel_dp->compliance.test_type);
+   seq_printf(m, "%02lx\n", 
intel_dp->compliance.test_type);
} else
seq_puts(m, "0");
}
-- 
2.24.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v3 9/9] drm/i915/dp: [FIXME] Program vswing, pre-emphasis, test-pattern

2019-12-30 Thread Animesh Manna
This patch process phy compliance request by programming requested
vswing, pre-emphasis and test pattern.

Note: FIXME tag added as design discusion is ongoing in previous patch
series. Some temporary fix added and the patch is under-development, not for
review.

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_display.c | 24 ++-
 drivers/gpu/drm/i915/display/intel_dp.c  | 74 
 drivers/gpu/drm/i915/display/intel_dp.h  |  2 +
 drivers/gpu/drm/i915/i915_drv.h  |  2 +
 4 files changed, 101 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index da5266e76738..c00be1eb67d6 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -14480,6 +14480,9 @@ static int intel_atomic_check(struct drm_device *dev,
int ret, i;
bool any_ms = false;
 
+   if (dev_priv->dp_phy_comp)
+   return 0;
+
/* Catch I915_MODE_FLAG_INHERITED */
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i) {
@@ -15207,10 +15210,23 @@ static void intel_atomic_commit_tail(struct 
intel_atomic_state *state)
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_crtc_state *new_crtc_state, *old_crtc_state;
struct intel_crtc *crtc;
+   const struct drm_connector_state *conn_state;
+   struct drm_connector *conn;
u64 put_domains[I915_MAX_PIPES] = {};
intel_wakeref_t wakeref = 0;
int i;
 
+   if(dev_priv->dp_phy_comp) {
+   for_each_new_connector_in_state(>base, conn, conn_state, 
i) {
+   struct intel_encoder *encoder =
+   to_intel_encoder(conn_state->best_encoder);
+   struct intel_dp *intel_dp = 
enc_to_intel_dp(>base);
+
+   intel_dp_process_phy_request(intel_dp);
+   }
+   goto dp_phy_comp1;
+   }
+
intel_atomic_commit_fence_wait(state);
 
drm_atomic_helper_wait_for_dependencies(>base);
@@ -15345,6 +15361,7 @@ static void intel_atomic_commit_tail(struct 
intel_atomic_state *state)
if (state->modeset && intel_can_enable_sagv(state))
intel_enable_sagv(dev_priv);
 
+dp_phy_comp1:
drm_atomic_helper_commit_hw_done(>base);
 
if (state->modeset) {
@@ -15436,6 +15453,7 @@ static int intel_atomic_commit(struct drm_device *dev,
state->wakeref = intel_runtime_pm_get(_priv->runtime_pm);
 
drm_atomic_state_get(>base);
+   if (!dev_priv->dp_phy_comp) {
i915_sw_fence_init(>commit_ready,
   intel_atomic_commit_ready);
 
@@ -15474,11 +15492,13 @@ static int intel_atomic_commit(struct drm_device *dev,
intel_runtime_pm_put(_priv->runtime_pm, state->wakeref);
return ret;
}
+   }
 
ret = drm_atomic_helper_setup_commit(>base, nonblock);
if (!ret)
ret = drm_atomic_helper_swap_state(>base, true);
 
+   if (!dev_priv->dp_phy_comp) {
if (ret) {
i915_sw_fence_commit(>commit_ready);
 
@@ -15489,6 +15509,7 @@ static int intel_atomic_commit(struct drm_device *dev,
dev_priv->wm.distrust_bios_wm = false;
intel_shared_dpll_swap_state(state);
intel_atomic_track_fbs(state);
+   }
 
if (state->global_state_changed) {
assert_global_state_locked(dev_priv);
@@ -15505,8 +15526,9 @@ static int intel_atomic_commit(struct drm_device *dev,
 
drm_atomic_state_get(>base);
INIT_WORK(>base.commit_work, intel_atomic_commit_work);
-
+   if (!dev_priv->dp_phy_comp) {
i915_sw_fence_commit(>commit_ready);
+   }
if (nonblock && state->modeset) {
queue_work(dev_priv->modeset_wq, >base.commit_work);
} else if (nonblock) {
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 7c3f65e5d88b..c3454053a212 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -5060,9 +5060,82 @@ static inline void intel_dp_phy_pattern_update(struct 
intel_dp *intel_dp)
}
 }
 
+static void
+intel_dp_autotest_phy_ddi_disable(struct intel_dp *intel_dp)
+{
+   struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+   struct drm_device *dev = intel_dig_port->base.base.dev;
+   struct drm_i915_private *dev_priv = to_i915(dev);
+   enum port port = intel_dig_port->base.port;
+   u32 ddi_buf_ctl_value, dp_tp_ctl_value, trans_ddi_func_ctl_value;
+
+   ddi_buf_ctl_value = I915_READ(DDI_BUF_CTL(port));
+   dp_tp_ctl

[PATCH v3 0/9] DP Phy compliance auto test

2019-12-30 Thread Animesh Manna
Driver changes mainly to process the request coming from Test equipment
as short pulse hpd interrupt to change link-pattern/v-swing/pre-emphasis
Complete auto test suite takes much lesser time than manual run.

Overall design:
--
Automate test request will come to source device as HDP short pulse
interrupt from test scope.
Read DPCD 0x201, Check for bit 1 for automated test request.
If set continue and read DPCD 0x218.
Check for bit 3 for phy test pattern, If set continue.
Get the requested test pattern through DPCD 0x248.
Compute requested voltage swing level and pre-emphasis level
from DPCD 0x206 and 0x207
Set signal level through vswing programming sequence.
Write DDI_COMP_CTL and DDI_COMP_PATx as per requested pattern.
Configure the link and write the new test pattern through DPCD.

High level patch description.
-
patch 1: drm level api added to get/set test pattern as per vesa
DP spec. This maybe useful for other driver so added in drm layer.
patch 2: Fix for a compilation issue.
patch 3: vswing/preemphasis adjustment calculation is needed during
phy compliance request processing along with existing link training
process, so moved the same function in intel_dp.c.
patch 4: Parse the test scope request regarding  rquested test pattern,
vswing level, preemphasis level.
patch 5: Notify testapp through uevent.
patch 6: Added debugfs entry for phy compliance.
patch 7: Register difnition of DP compliance register added.
patch 8: Function added to update the pattern in source side.
patch 9: This patch os mainly processing the request.

Currently through prototyping patch able to run DP compliance where
vswing, preemphasis and test pattern is changing fine but complete
test is under process. As per feedback redesigned the code. Could not test
due to unavailability of test scope, so sending as RFC again to get design
feedback.

v1: Redesigned the code as per review feedback from Manasi on RFC.
v2: Addressed review comments from Manasi.
v3: Addressed review commnets from Harry, Ville, Jani.

Animesh Manna (9):
  drm/amd/display: Align macro name as per DP spec
  drm/dp: get/set phy compliance pattern
  drm/i915/dp: Move vswing/pre-emphasis adjustment calculation
  drm/i915/dp: Preparation for DP phy compliance auto test
  drm/i915/dsb: Send uevent to testapp.
  drm/i915/dp: Add debugfs entry for DP phy compliance.
  drm/i915/dp: Register definition for DP compliance register
  drm/i915/dp: Update the pattern as per request
  drm/i915/dp: [FIXME] Program vswing, pre-emphasis, test-pattern

 .../gpu/drm/amd/display/dc/core/dc_link_dp.c  |   2 +-
 drivers/gpu/drm/drm_dp_helper.c   |  94 +
 drivers/gpu/drm/i915/display/intel_display.c  |  24 ++-
 .../drm/i915/display/intel_display_types.h|   1 +
 drivers/gpu/drm/i915/display/intel_dp.c   | 197 +-
 drivers/gpu/drm/i915/display/intel_dp.h   |   6 +
 .../drm/i915/display/intel_dp_link_training.c |  36 +---
 drivers/gpu/drm/i915/i915_debugfs.c   |  12 +-
 drivers/gpu/drm/i915/i915_drv.h   |   2 +
 drivers/gpu/drm/i915/i915_reg.h   |  20 ++
 include/drm/drm_dp_helper.h   |  33 ++-
 11 files changed, 387 insertions(+), 40 deletions(-)

-- 
2.24.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v3 2/9] drm/dp: get/set phy compliance pattern

2019-12-30 Thread Animesh Manna
During phy compliance auto test mode source need to read
requested test pattern from sink through DPCD. After processing
the request source need to set the pattern. So set/get method
added in drm layer as it is DP protocol.

v2: As per review feedback from Manasi on RFC version,
- added dp revision as function argument in set_phy_pattern api.
- used int for link_rate and u8 for lane_count to align with existing code.

v3: As per review feedback from Harry,
- used sizeof() instead of magic number.
- corrected kernel-doc for drm_dp_phy_test_params structure.

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/drm_dp_helper.c | 94 +
 include/drm/drm_dp_helper.h | 31 +++
 2 files changed, 125 insertions(+)

diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index 2c7870aef469..8a0786dd262d 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -1371,3 +1371,97 @@ int drm_dp_dsc_sink_supported_input_bpcs(const u8 
dsc_dpcd[DP_DSC_RECEIVER_CAP_S
return num_bpc;
 }
 EXPORT_SYMBOL(drm_dp_dsc_sink_supported_input_bpcs);
+
+/**
+ * drm_dp_get_phy_test_pattern() - get the requested pattern from the sink.
+ * @aux: DisplayPort AUX channel
+ * @data: DP phy compliance test parameters.
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+int drm_dp_get_phy_test_pattern(struct drm_dp_aux *aux,
+   struct drm_dp_phy_test_params *data)
+{
+   int err;
+   u8 rate, lanes;
+
+   err = drm_dp_dpcd_readb(aux, DP_TEST_LINK_RATE, );
+   if (err < 0)
+   return err;
+   data->link_rate = drm_dp_bw_code_to_link_rate(rate);
+
+   err = drm_dp_dpcd_readb(aux, DP_TEST_LANE_COUNT, );
+   if (err < 0)
+   return err;
+   data->num_lanes = lanes & DP_MAX_LANE_COUNT_MASK;
+
+   if (lanes & DP_ENHANCED_FRAME_CAP)
+   data->enhanced_frame_cap = true;
+
+   err = drm_dp_dpcd_readb(aux, DP_PHY_TEST_PATTERN, >phy_pattern);
+   if (err < 0)
+   return err;
+
+   switch (data->phy_pattern) {
+   case DP_PHY_TEST_PATTERN_80BIT_CUSTOM:
+   err = drm_dp_dpcd_read(aux, DP_TEST_80BIT_CUSTOM_PATTERN_7_0,
+  >custom80, sizeof(data->custom80));
+   if (err < 0)
+   return err;
+
+   break;
+   case DP_PHY_TEST_PATTERN_CP2520:
+   err = drm_dp_dpcd_read(aux, DP_TEST_HBR2_SCRAMBLER_RESET,
+  >hbr2_reset,
+  sizeof(data->hbr2_reset));
+   if (err < 0)
+   return err;
+   }
+
+   return 0;
+}
+EXPORT_SYMBOL(drm_dp_get_phy_test_pattern);
+
+/**
+ * drm_dp_set_phy_test_pattern() - set the pattern to the sink.
+ * @aux: DisplayPort AUX channel
+ * @data: DP phy compliance test parameters.
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+int drm_dp_set_phy_test_pattern(struct drm_dp_aux *aux,
+   struct drm_dp_phy_test_params *data, u8 dp_rev)
+{
+   int err, i;
+   u8 link_config[2];
+   u8 test_pattern;
+
+   link_config[0] = drm_dp_link_rate_to_bw_code(data->link_rate);
+   link_config[1] = data->num_lanes;
+   if (data->enhanced_frame_cap)
+   link_config[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
+   err = drm_dp_dpcd_write(aux, DP_LINK_BW_SET, link_config, 2);
+   if (err < 0)
+   return err;
+
+   test_pattern = data->phy_pattern;
+   if (dp_rev < 0x12) {
+   test_pattern = (test_pattern << 2) &
+  DP_LINK_QUAL_PATTERN_11_MASK;
+   err = drm_dp_dpcd_writeb(aux, DP_TRAINING_PATTERN_SET,
+test_pattern);
+   if (err < 0)
+   return err;
+   } else {
+   for (i = 0; i < data->num_lanes; i++) {
+   err = drm_dp_dpcd_writeb(aux,
+DP_LINK_QUAL_LANE0_SET + i,
+test_pattern);
+   if (err < 0)
+   return err;
+   }
+   }
+
+   return 0;
+}
+EXPORT_SYMBOL(drm_dp_set_phy_test_pattern);
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index d6e560870fb1..3d0e9e0d55cf 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -700,6 +700,15 @@
 # define DP_TEST_COUNT_MASK0xf
 
 #define DP_PHY_TEST_PATTERN 0x248
+# define DP_PHY_TEST_PATTERN_SEL_MASK   0x7
+# define DP_PHY_TEST_PATTERN_NONE   0x0
+# define DP_PHY_TEST_PATTERN_D10_2  0x1
+# define DP_PHY_TEST_PATTERN_ERROR_COUNT0x2
+# defi

[PATCH v3 2/9] drm/dp: get/set phy compliance pattern

2019-12-23 Thread Animesh Manna
During phy compliance auto test mode source need to read
requested test pattern from sink through DPCD. After processing
the request source need to set the pattern. So set/get method
added in drm layer as it is DP protocol.

v2: As per review feedback from Manasi on RFC version,
- added dp revision as function argument in set_phy_pattern api.
- used int for link_rate and u8 for lane_count to align with existing code.

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/drm_dp_helper.c | 93 +
 include/drm/drm_dp_helper.h | 31 +++
 2 files changed, 124 insertions(+)

diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index 2c7870aef469..91c80973aa83 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -1371,3 +1371,96 @@ int drm_dp_dsc_sink_supported_input_bpcs(const u8 
dsc_dpcd[DP_DSC_RECEIVER_CAP_S
return num_bpc;
 }
 EXPORT_SYMBOL(drm_dp_dsc_sink_supported_input_bpcs);
+
+/**
+ * drm_dp_get_phy_test_pattern() - get the requested pattern from the sink.
+ * @aux: DisplayPort AUX channel
+ * @data: DP phy compliance test parameters.
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+int drm_dp_get_phy_test_pattern(struct drm_dp_aux *aux,
+   struct drm_dp_phy_test_params *data)
+{
+   int err;
+   u8 rate, lanes;
+
+   err = drm_dp_dpcd_readb(aux, DP_TEST_LINK_RATE, );
+   if (err < 0)
+   return err;
+   data->link_rate = drm_dp_bw_code_to_link_rate(rate);
+
+   err = drm_dp_dpcd_readb(aux, DP_TEST_LANE_COUNT, );
+   if (err < 0)
+   return err;
+   data->num_lanes = lanes & DP_MAX_LANE_COUNT_MASK;
+
+   if (lanes & DP_ENHANCED_FRAME_CAP)
+   data->enahanced_frame_cap = true;
+
+   err = drm_dp_dpcd_readb(aux, DP_PHY_TEST_PATTERN, >phy_pattern);
+   if (err < 0)
+   return err;
+
+   switch (data->phy_pattern) {
+   case DP_PHY_TEST_PATTERN_80BIT_CUSTOM:
+   err = drm_dp_dpcd_read(aux, DP_TEST_80BIT_CUSTOM_PATTERN_7_0,
+  >custom80, 10);
+   if (err < 0)
+   return err;
+
+   break;
+   case DP_PHY_TEST_PATTERN_CP2520:
+   err = drm_dp_dpcd_read(aux, DP_TEST_HBR2_SCRAMBLER_RESET,
+  >hbr2_reset, 2);
+   if (err < 0)
+   return err;
+   }
+
+   return 0;
+}
+EXPORT_SYMBOL(drm_dp_get_phy_test_pattern);
+
+/**
+ * drm_dp_set_phy_test_pattern() - set the pattern to the sink.
+ * @aux: DisplayPort AUX channel
+ * @data: DP phy compliance test parameters.
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+int drm_dp_set_phy_test_pattern(struct drm_dp_aux *aux,
+   struct drm_dp_phy_test_params *data, u8 dp_rev)
+{
+   int err, i;
+   u8 link_config[2];
+   u8 test_pattern;
+
+   link_config[0] = drm_dp_link_rate_to_bw_code(data->link_rate);
+   link_config[1] = data->num_lanes;
+   if (data->enahanced_frame_cap)
+   link_config[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
+   err = drm_dp_dpcd_write(aux, DP_LINK_BW_SET, link_config, 2);
+   if (err < 0)
+   return err;
+
+   test_pattern = data->phy_pattern;
+   if (dp_rev < 0x12) {
+   test_pattern = (test_pattern << 2) &
+  DP_LINK_QUAL_PATTERN_11_MASK;
+   err = drm_dp_dpcd_writeb(aux, DP_TRAINING_PATTERN_SET,
+test_pattern);
+   if (err < 0)
+   return err;
+   } else {
+   for (i = 0; i < data->num_lanes; i++) {
+   err = drm_dp_dpcd_writeb(aux,
+DP_LINK_QUAL_LANE0_SET + i,
+test_pattern);
+   if (err < 0)
+   return err;
+   }
+   }
+
+   return 0;
+}
+EXPORT_SYMBOL(drm_dp_set_phy_test_pattern);
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index d6e560870fb1..42a364748308 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -700,6 +700,15 @@
 # define DP_TEST_COUNT_MASK0xf
 
 #define DP_PHY_TEST_PATTERN 0x248
+# define DP_PHY_TEST_PATTERN_SEL_MASK   0x7
+# define DP_PHY_TEST_PATTERN_NONE   0x0
+# define DP_PHY_TEST_PATTERN_D10_2  0x1
+# define DP_PHY_TEST_PATTERN_ERROR_COUNT0x2
+# define DP_PHY_TEST_PATTERN_PRBS7  0x3
+# define DP_PHY_TEST_PATTERN_80BIT_CUSTOM   0x4
+# define DP_PHY_TEST_PATTERN_CP2520 0x5
+
+#define DP_TEST_HBR2_SCRAMBLER_RESET0x24A
 #define DP_TEST_80BIT_CUSTOM_PAT

[PATCH v3 1/9] drm/amd/display: Align macro name as per DP spec

2019-12-23 Thread Animesh Manna
[Why]:
Aligh with DP spec wanted to follow same naming convention.

[How]:
Changed the macro name of the dpcd address used for getting requested
test-pattern.

Cc: Harry Wentland 
Cc: Alex Deucher 
Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 +-
 include/drm/drm_dp_helper.h  | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c 
b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
index 42aa889fd0f5..1a6109be2fce 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
@@ -2491,7 +2491,7 @@ static void dp_test_send_phy_test_pattern(struct dc_link 
*link)
/* get phy test pattern and pattern parameters from DP receiver */
core_link_read_dpcd(
link,
-   DP_TEST_PHY_PATTERN,
+   DP_PHY_TEST_PATTERN,
_test_pattern.raw,
sizeof(dpcd_test_pattern));
core_link_read_dpcd(
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index 8f8f3632e697..d6e560870fb1 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -699,7 +699,7 @@
 # define DP_TEST_CRC_SUPPORTED (1 << 5)
 # define DP_TEST_COUNT_MASK0xf
 
-#define DP_TEST_PHY_PATTERN 0x248
+#define DP_PHY_TEST_PATTERN 0x248
 #define DP_TEST_80BIT_CUSTOM_PATTERN_7_00x250
 #defineDP_TEST_80BIT_CUSTOM_PATTERN_15_8   0x251
 #defineDP_TEST_80BIT_CUSTOM_PATTERN_23_16  0x252
-- 
2.24.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v3 3/9] drm/i915/dp: Move vswing/pre-emphasis adjustment calculation

2019-12-23 Thread Animesh Manna
vswing/pre-emphasis adjustment calculation is needed in processing
of auto phy compliance request other than link training, so moved
the same function in intel_dp.c.

No functional change.

v1: initial patch.
v2:
- used "intel_dp" prefix in function name. (Jani)
- used array notation instead pointer for link_status. (Ville)

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_dp.c   | 34 +++
 drivers/gpu/drm/i915/display/intel_dp.h   |  4 +++
 .../drm/i915/display/intel_dp_link_training.c | 32 -
 3 files changed, 38 insertions(+), 32 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 2f31d226c6eb..4703e533feb3 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -4110,6 +4110,40 @@ ivb_cpu_edp_signal_levels(u8 train_set)
}
 }
 
+void
+intel_dp_get_adjust_train(struct intel_dp *intel_dp,
+ const u8 link_status[DP_LINK_STATUS_SIZE])
+{
+   u8 v = 0;
+   u8 p = 0;
+   int lane;
+   u8 voltage_max;
+   u8 preemph_max;
+
+   for (lane = 0; lane < intel_dp->lane_count; lane++) {
+   u8 this_v = drm_dp_get_adjust_request_voltage(link_status,
+ lane);
+   u8 this_p = drm_dp_get_adjust_request_pre_emphasis(link_status,
+  lane);
+
+   if (this_v > v)
+   v = this_v;
+   if (this_p > p)
+   p = this_p;
+   }
+
+   voltage_max = intel_dp_voltage_max(intel_dp);
+   if (v >= voltage_max)
+   v = voltage_max | DP_TRAIN_MAX_SWING_REACHED;
+
+   preemph_max = intel_dp_pre_emphasis_max(intel_dp, v);
+   if (p >= preemph_max)
+   p = preemph_max | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
+
+   for (lane = 0; lane < 4; lane++)
+   intel_dp->train_set[lane] = v | p;
+}
+
 void
 intel_dp_set_signal_levels(struct intel_dp *intel_dp)
 {
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h 
b/drivers/gpu/drm/i915/display/intel_dp.h
index 3da166054788..83eadc87af26 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -9,6 +9,7 @@
 #include 
 
 #include 
+#include 
 
 #include "i915_reg.h"
 
@@ -91,6 +92,9 @@ void
 intel_dp_program_link_training_pattern(struct intel_dp *intel_dp,
   u8 dp_train_pat);
 void
+intel_dp_get_adjust_train(struct intel_dp *intel_dp,
+ const u8 link_status[DP_LINK_STATUS_SIZE]);
+void
 intel_dp_set_signal_levels(struct intel_dp *intel_dp);
 void intel_dp_set_idle_link_train(struct intel_dp *intel_dp);
 u8
diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c 
b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
index 2a1130dd1ad0..1e38584e7d56 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
@@ -34,38 +34,6 @@ intel_dp_dump_link_status(const u8 
link_status[DP_LINK_STATUS_SIZE])
  link_status[3], link_status[4], link_status[5]);
 }
 
-static void
-intel_get_adjust_train(struct intel_dp *intel_dp,
-  const u8 link_status[DP_LINK_STATUS_SIZE])
-{
-   u8 v = 0;
-   u8 p = 0;
-   int lane;
-   u8 voltage_max;
-   u8 preemph_max;
-
-   for (lane = 0; lane < intel_dp->lane_count; lane++) {
-   u8 this_v = drm_dp_get_adjust_request_voltage(link_status, 
lane);
-   u8 this_p = drm_dp_get_adjust_request_pre_emphasis(link_status, 
lane);
-
-   if (this_v > v)
-   v = this_v;
-   if (this_p > p)
-   p = this_p;
-   }
-
-   voltage_max = intel_dp_voltage_max(intel_dp);
-   if (v >= voltage_max)
-   v = voltage_max | DP_TRAIN_MAX_SWING_REACHED;
-
-   preemph_max = intel_dp_pre_emphasis_max(intel_dp, v);
-   if (p >= preemph_max)
-   p = preemph_max | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
-
-   for (lane = 0; lane < 4; lane++)
-   intel_dp->train_set[lane] = v | p;
-}
-
 static bool
 intel_dp_set_link_train(struct intel_dp *intel_dp,
u8 dp_train_pat)
-- 
2.24.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v3 3/9] drm/i915/dp: Move vswing/pre-emphasis adjustment calculation

2019-12-23 Thread Animesh Manna
vswing/pre-emphasis adjustment calculation is needed in processing
of auto phy compliance request other than link training, so moved
the same function in intel_dp.c.

No functional change.

v1: initial patch.
v2:
- used "intel_dp" prefix in function name. (Jani)
- used array notation instead pointer for link_status. (Ville)

Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_dp.c   | 34 +++
 drivers/gpu/drm/i915/display/intel_dp.h   |  4 +++
 .../drm/i915/display/intel_dp_link_training.c | 32 -
 3 files changed, 38 insertions(+), 32 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 2f31d226c6eb..4703e533feb3 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -4110,6 +4110,40 @@ ivb_cpu_edp_signal_levels(u8 train_set)
}
 }
 
+void
+intel_dp_get_adjust_train(struct intel_dp *intel_dp,
+ const u8 link_status[DP_LINK_STATUS_SIZE])
+{
+   u8 v = 0;
+   u8 p = 0;
+   int lane;
+   u8 voltage_max;
+   u8 preemph_max;
+
+   for (lane = 0; lane < intel_dp->lane_count; lane++) {
+   u8 this_v = drm_dp_get_adjust_request_voltage(link_status,
+ lane);
+   u8 this_p = drm_dp_get_adjust_request_pre_emphasis(link_status,
+  lane);
+
+   if (this_v > v)
+   v = this_v;
+   if (this_p > p)
+   p = this_p;
+   }
+
+   voltage_max = intel_dp_voltage_max(intel_dp);
+   if (v >= voltage_max)
+   v = voltage_max | DP_TRAIN_MAX_SWING_REACHED;
+
+   preemph_max = intel_dp_pre_emphasis_max(intel_dp, v);
+   if (p >= preemph_max)
+   p = preemph_max | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
+
+   for (lane = 0; lane < 4; lane++)
+   intel_dp->train_set[lane] = v | p;
+}
+
 void
 intel_dp_set_signal_levels(struct intel_dp *intel_dp)
 {
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h 
b/drivers/gpu/drm/i915/display/intel_dp.h
index 3da166054788..83eadc87af26 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -9,6 +9,7 @@
 #include 
 
 #include 
+#include 
 
 #include "i915_reg.h"
 
@@ -91,6 +92,9 @@ void
 intel_dp_program_link_training_pattern(struct intel_dp *intel_dp,
   u8 dp_train_pat);
 void
+intel_dp_get_adjust_train(struct intel_dp *intel_dp,
+ const u8 link_status[DP_LINK_STATUS_SIZE]);
+void
 intel_dp_set_signal_levels(struct intel_dp *intel_dp);
 void intel_dp_set_idle_link_train(struct intel_dp *intel_dp);
 u8
diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c 
b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
index 2a1130dd1ad0..1e38584e7d56 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
@@ -34,38 +34,6 @@ intel_dp_dump_link_status(const u8 
link_status[DP_LINK_STATUS_SIZE])
  link_status[3], link_status[4], link_status[5]);
 }
 
-static void
-intel_get_adjust_train(struct intel_dp *intel_dp,
-  const u8 link_status[DP_LINK_STATUS_SIZE])
-{
-   u8 v = 0;
-   u8 p = 0;
-   int lane;
-   u8 voltage_max;
-   u8 preemph_max;
-
-   for (lane = 0; lane < intel_dp->lane_count; lane++) {
-   u8 this_v = drm_dp_get_adjust_request_voltage(link_status, 
lane);
-   u8 this_p = drm_dp_get_adjust_request_pre_emphasis(link_status, 
lane);
-
-   if (this_v > v)
-   v = this_v;
-   if (this_p > p)
-   p = this_p;
-   }
-
-   voltage_max = intel_dp_voltage_max(intel_dp);
-   if (v >= voltage_max)
-   v = voltage_max | DP_TRAIN_MAX_SWING_REACHED;
-
-   preemph_max = intel_dp_pre_emphasis_max(intel_dp, v);
-   if (p >= preemph_max)
-   p = preemph_max | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
-
-   for (lane = 0; lane < 4; lane++)
-   intel_dp->train_set[lane] = v | p;
-}
-
 static bool
 intel_dp_set_link_train(struct intel_dp *intel_dp,
u8 dp_train_pat)
-- 
2.24.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 3/9] drm/i915/dp: Move vswing/pre-emphasis adjustment calculation

2019-12-18 Thread Animesh Manna
vswing/pre-emphasis adjustment calculation is needed in processing
of auto phy compliance request other than link training, so moved
the same function in intel_dp.c.

No functional change.

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

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 2f31d226c6eb..ca82835b6dcf 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -4110,6 +4110,38 @@ ivb_cpu_edp_signal_levels(u8 train_set)
}
 }
 
+void
+intel_get_adjust_train(struct intel_dp *intel_dp,
+  const u8 *link_status)
+{
+   u8 v = 0;
+   u8 p = 0;
+   int lane;
+   u8 voltage_max;
+   u8 preemph_max;
+
+   for (lane = 0; lane < intel_dp->lane_count; lane++) {
+   u8 this_v = drm_dp_get_adjust_request_voltage(link_status, 
lane);
+   u8 this_p = drm_dp_get_adjust_request_pre_emphasis(link_status, 
lane);
+
+   if (this_v > v)
+   v = this_v;
+   if (this_p > p)
+   p = this_p;
+   }
+
+   voltage_max = intel_dp_voltage_max(intel_dp);
+   if (v >= voltage_max)
+   v = voltage_max | DP_TRAIN_MAX_SWING_REACHED;
+
+   preemph_max = intel_dp_pre_emphasis_max(intel_dp, v);
+   if (p >= preemph_max)
+   p = preemph_max | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
+
+   for (lane = 0; lane < 4; lane++)
+   intel_dp->train_set[lane] = v | p;
+}
+
 void
 intel_dp_set_signal_levels(struct intel_dp *intel_dp)
 {
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h 
b/drivers/gpu/drm/i915/display/intel_dp.h
index 3da166054788..0d0cb692f701 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -91,6 +91,9 @@ void
 intel_dp_program_link_training_pattern(struct intel_dp *intel_dp,
   u8 dp_train_pat);
 void
+intel_get_adjust_train(struct intel_dp *intel_dp,
+  const u8 *link_status);
+void
 intel_dp_set_signal_levels(struct intel_dp *intel_dp);
 void intel_dp_set_idle_link_train(struct intel_dp *intel_dp);
 u8
diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c 
b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
index 2a1130dd1ad0..1e38584e7d56 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
@@ -34,38 +34,6 @@ intel_dp_dump_link_status(const u8 
link_status[DP_LINK_STATUS_SIZE])
  link_status[3], link_status[4], link_status[5]);
 }
 
-static void
-intel_get_adjust_train(struct intel_dp *intel_dp,
-  const u8 link_status[DP_LINK_STATUS_SIZE])
-{
-   u8 v = 0;
-   u8 p = 0;
-   int lane;
-   u8 voltage_max;
-   u8 preemph_max;
-
-   for (lane = 0; lane < intel_dp->lane_count; lane++) {
-   u8 this_v = drm_dp_get_adjust_request_voltage(link_status, 
lane);
-   u8 this_p = drm_dp_get_adjust_request_pre_emphasis(link_status, 
lane);
-
-   if (this_v > v)
-   v = this_v;
-   if (this_p > p)
-   p = this_p;
-   }
-
-   voltage_max = intel_dp_voltage_max(intel_dp);
-   if (v >= voltage_max)
-   v = voltage_max | DP_TRAIN_MAX_SWING_REACHED;
-
-   preemph_max = intel_dp_pre_emphasis_max(intel_dp, v);
-   if (p >= preemph_max)
-   p = preemph_max | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
-
-   for (lane = 0; lane < 4; lane++)
-   intel_dp->train_set[lane] = v | p;
-}
-
 static bool
 intel_dp_set_link_train(struct intel_dp *intel_dp,
u8 dp_train_pat)
-- 
2.24.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 6/9] drm/i915/dp: Add debugfs entry for DP phy compliance.

2019-12-18 Thread Animesh Manna
These debugfs entry will help testapp to understand the test request
during dp phy compliance mode.

Acked-by: Manasi Navare 
Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/i915_debugfs.c | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c 
b/drivers/gpu/drm/i915/i915_debugfs.c
index d28468eaed57..715a6c26d0c9 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -3173,6 +3173,16 @@ static int i915_displayport_test_data_show(struct 
seq_file *m, void *data)
   
intel_dp->compliance.test_data.vdisplay);
seq_printf(m, "bpc: %u\n",
   intel_dp->compliance.test_data.bpc);
+   } else if (intel_dp->compliance.test_type ==
+  DP_TEST_LINK_PHY_TEST_PATTERN) {
+   seq_printf(m, "pattern: %d\n",
+  
intel_dp->compliance.test_data.phytest.phy_pattern);
+   seq_printf(m, "Number of lanes: %d\n",
+  
intel_dp->compliance.test_data.phytest.num_lanes);
+   seq_printf(m, "Link Rate: %d\n",
+  
intel_dp->compliance.test_data.phytest.link_rate);
+   seq_printf(m, "level: %02x\n",
+  intel_dp->train_set[0]);
}
} else
seq_puts(m, "0");
@@ -3205,7 +3215,7 @@ static int i915_displayport_test_type_show(struct 
seq_file *m, void *data)
 
if (encoder && connector->status == connector_status_connected) 
{
intel_dp = enc_to_intel_dp(>base);
-   seq_printf(m, "%02lx", intel_dp->compliance.test_type);
+   seq_printf(m, "%02lx\n", 
intel_dp->compliance.test_type);
} else
seq_puts(m, "0");
}
-- 
2.24.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


  1   2   >