From: Tom Chung <chiahsuan.ch...@amd.com>

[Why]
Enable the Panel Replay if eDP panel and ASIC support.
(prioritize Panel Replay over PSR)

[How]
- Setup the Panel Replay config during the device init
  (prioritize Panel Replay over PSR).
- Separate the Replay init function into two functions
  amdgpu_dm_link_setup_replay() and amdgpu_dm_set_replay_caps()
  to fix the issue in the earlier commit that cause PSR and Replay
  enabled at the same time.

Reviewed-by: Sun peng Li <sunpeng...@amd.com>
Acked-by: Alex Hung <alex.h...@amd.com>
Signed-off-by: Tom Chung <chiahsuan.ch...@amd.com>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  42 ++++++-
 .../amd/display/amdgpu_dm/amdgpu_dm_crtc.c    |  59 +++++++--
 .../amd/display/amdgpu_dm/amdgpu_dm_replay.c  | 119 ++++++++++--------
 .../amd/display/amdgpu_dm/amdgpu_dm_replay.h  |   4 +-
 4 files changed, 156 insertions(+), 68 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 95ff3800fc87..f9e41006ac87 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -67,6 +67,7 @@
 #include "amdgpu_dm_debugfs.h"
 #endif
 #include "amdgpu_dm_psr.h"
+#include "amdgpu_dm_replay.h"
 
 #include "ivsrcid/ivsrcid_vislands30.h"
 
@@ -4393,6 +4394,7 @@ static int amdgpu_dm_initialize_drm_device(struct 
amdgpu_device *adev)
        enum dc_connection_type new_connection_type = dc_connection_none;
        const struct dc_plane_cap *plane;
        bool psr_feature_enabled = false;
+       bool replay_feature_enabled = false;
        int max_overlay = dm->dc->caps.max_slave_planes;
 
        dm->display_indexes_num = dm->dc->caps.max_streams;
@@ -4504,6 +4506,23 @@ static int amdgpu_dm_initialize_drm_device(struct 
amdgpu_device *adev)
                }
        }
 
+       /* Determine whether to enable Replay support by default. */
+       if (!(amdgpu_dc_debug_mask & DC_DISABLE_REPLAY)) {
+               switch (amdgpu_ip_version(adev, DCE_HWIP, 0)) {
+               case IP_VERSION(3, 1, 4):
+               case IP_VERSION(3, 1, 5):
+               case IP_VERSION(3, 1, 6):
+               case IP_VERSION(3, 2, 0):
+               case IP_VERSION(3, 2, 1):
+               case IP_VERSION(3, 5, 0):
+                       replay_feature_enabled = true;
+                       break;
+               default:
+                       replay_feature_enabled = amdgpu_dc_feature_mask & 
DC_REPLAY_MASK;
+                       break;
+               }
+       }
+
        /* loops over all connectors on the board */
        for (i = 0; i < link_cnt; i++) {
                struct dc_link *link = NULL;
@@ -4572,6 +4591,11 @@ static int amdgpu_dm_initialize_drm_device(struct 
amdgpu_device *adev)
                                
amdgpu_dm_update_connector_after_detect(aconnector);
                                setup_backlight_device(dm, aconnector);
 
+                               /* Disable PSR if Replay can be enabled */
+                               if (replay_feature_enabled)
+                                       if (amdgpu_dm_set_replay_caps(link, 
aconnector))
+                                               psr_feature_enabled = false;
+
                                if (psr_feature_enabled)
                                        amdgpu_dm_set_psr_caps(link);
 
@@ -8521,10 +8545,17 @@ static void amdgpu_dm_commit_planes(struct 
drm_atomic_state *state,
                        dm_update_pflip_irq_state(drm_to_adev(dev),
                                                  acrtc_attach);
 
-               if ((acrtc_state->update_type > UPDATE_TYPE_FAST) &&
-                               
acrtc_state->stream->link->psr_settings.psr_version != 
DC_PSR_VERSION_UNSUPPORTED &&
-                               
!acrtc_state->stream->link->psr_settings.psr_feature_enabled)
-                       amdgpu_dm_link_setup_psr(acrtc_state->stream);
+               if (acrtc_state->update_type > UPDATE_TYPE_FAST) {
+                       if 
(acrtc_state->stream->link->replay_settings.config.replay_supported &&
+                                       
!acrtc_state->stream->link->replay_settings.replay_feature_enabled) {
+                               struct amdgpu_dm_connector *aconn =
+                                       (struct amdgpu_dm_connector 
*)acrtc_state->stream->dm_stream_context;
+                               
amdgpu_dm_link_setup_replay(acrtc_state->stream->link, aconn);
+                       } else if 
(acrtc_state->stream->link->psr_settings.psr_version != 
DC_PSR_VERSION_UNSUPPORTED &&
+                                       
!acrtc_state->stream->link->psr_settings.psr_feature_enabled) {
+                               amdgpu_dm_link_setup_psr(acrtc_state->stream);
+                       }
+               }
 
                /* Decrement skip count when PSR is enabled and we're doing 
fast updates. */
                if (acrtc_state->update_type == UPDATE_TYPE_FAST &&
@@ -8813,11 +8844,12 @@ static void amdgpu_dm_commit_streams(struct 
drm_atomic_state *state,
                }
        } /* for_each_crtc_in_state() */
 
-       /* if there mode set or reset, disable eDP PSR */
+       /* if there mode set or reset, disable eDP PSR, Replay */
        if (mode_set_reset_required) {
                if (dm->vblank_control_workqueue)
                        flush_workqueue(dm->vblank_control_workqueue);
 
+               amdgpu_dm_replay_disable_all(dm);
                amdgpu_dm_psr_disable_all(dm);
        }
 
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
index 6e715ef3a556..f64c5ffed234 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
@@ -29,6 +29,7 @@
 #include "dc.h"
 #include "amdgpu.h"
 #include "amdgpu_dm_psr.h"
+#include "amdgpu_dm_replay.h"
 #include "amdgpu_dm_crtc.h"
 #include "amdgpu_dm_plane.h"
 #include "amdgpu_dm_trace.h"
@@ -95,6 +96,48 @@ bool amdgpu_dm_crtc_vrr_active(struct dm_crtc_state 
*dm_state)
               dm_state->freesync_config.state == VRR_STATE_ACTIVE_FIXED;
 }
 
+/**
+ * The DRM vblank counter enable/disable action is used as the trigger to 
enable
+ * or disable various panel self-refresh features:
+ *
+ * Panel Replay and PSR SU
+ * - Enable when:
+ *      - vblank counter is disabled
+ *      - entry is allowed: usermode demonstrates an adequate number of fast
+ *        commits)
+ *     - CRC capture window isn't active
+ * - Keep enabled even when vblank counter gets enabled
+ *
+ * PSR1
+ * - Enable condition same as above
+ * - Disable when vblank counter is enabled
+ */
+static void amdgpu_dm_crtc_set_panel_sr_feature(
+       struct vblank_control_work *vblank_work,
+       bool vblank_enabled, bool allow_sr_entry)
+{
+       struct dc_link *link = vblank_work->stream->link;
+       bool is_sr_active = (link->replay_settings.replay_allow_active ||
+                                link->psr_settings.psr_allow_active);
+       bool is_crc_window_active = false;
+
+#ifdef CONFIG_DRM_AMD_SECURE_DISPLAY
+       is_crc_window_active =
+               amdgpu_dm_crc_window_is_activated(&vblank_work->acrtc->base);
+#endif
+
+       if (link->replay_settings.replay_feature_enabled &&
+               allow_sr_entry && !is_sr_active && !is_crc_window_active) {
+               amdgpu_dm_replay_enable(vblank_work->stream, true);
+       } else if (vblank_enabled) {
+               if (link->psr_settings.psr_version < DC_PSR_VERSION_SU_1 && 
is_sr_active)
+                       amdgpu_dm_psr_disable(vblank_work->stream);
+       } else if (link->psr_settings.psr_feature_enabled &&
+               allow_sr_entry && !is_sr_active && !is_crc_window_active) {
+               amdgpu_dm_psr_enable(vblank_work->stream);
+       }
+}
+
 static void amdgpu_dm_crtc_vblank_control_worker(struct work_struct *work)
 {
        struct vblank_control_work *vblank_work =
@@ -123,18 +166,10 @@ static void amdgpu_dm_crtc_vblank_control_worker(struct 
work_struct *work)
         * fill_dc_dirty_rects().
         */
        if (vblank_work->stream && vblank_work->stream->link) {
-               if (vblank_work->enable) {
-                       if (vblank_work->stream->link->psr_settings.psr_version 
< DC_PSR_VERSION_SU_1 &&
-                           
vblank_work->stream->link->psr_settings.psr_allow_active)
-                               amdgpu_dm_psr_disable(vblank_work->stream);
-               } else if 
(vblank_work->stream->link->psr_settings.psr_feature_enabled &&
-                          
!vblank_work->stream->link->psr_settings.psr_allow_active &&
-#ifdef CONFIG_DRM_AMD_SECURE_DISPLAY
-                          
!amdgpu_dm_crc_window_is_activated(&vblank_work->acrtc->base) &&
-#endif
-                          vblank_work->acrtc->dm_irq_params.allow_psr_entry) {
-                       amdgpu_dm_psr_enable(vblank_work->stream);
-               }
+               amdgpu_dm_crtc_set_panel_sr_feature(
+                       vblank_work, vblank_work->enable,
+                       vblank_work->acrtc->dm_irq_params.allow_psr_entry ||
+                       
vblank_work->stream->link->replay_settings.replay_feature_enabled);
        }
 
        mutex_unlock(&dm->dc_lock);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_replay.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_replay.c
index 5ce542b1f860..738a58eebba7 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_replay.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_replay.c
@@ -60,21 +60,26 @@ static bool link_supports_replay(struct dc_link *link, 
struct amdgpu_dm_connecto
        if (!as_caps->dp_adap_sync_caps.bits.ADAPTIVE_SYNC_SDP_SUPPORT)
                return false;
 
+       // Sink shall populate line deviation information
+       if (dpcd_caps->pr_info.pixel_deviation_per_line == 0 ||
+               dpcd_caps->pr_info.max_deviation_line == 0)
+               return false;
+
        return true;
 }
 
 /*
- * amdgpu_dm_setup_replay() - setup replay configuration
+ * amdgpu_dm_set_replay_caps() - setup Replay capabilities
  * @link: link
  * @aconnector: aconnector
  *
  */
-bool amdgpu_dm_setup_replay(struct dc_link *link, struct amdgpu_dm_connector 
*aconnector)
+bool amdgpu_dm_set_replay_caps(struct dc_link *link, struct 
amdgpu_dm_connector *aconnector)
 {
-       struct replay_config pr_config;
+       struct replay_config pr_config = { 0 };
        union replay_debug_flags *debug_flags = NULL;
 
-       // For eDP, if Replay is supported, return true to skip checks
+       // If Replay is already set to support, return true to skip checks
        if (link->replay_settings.config.replay_supported)
                return true;
 
@@ -87,27 +92,50 @@ bool amdgpu_dm_setup_replay(struct dc_link *link, struct 
amdgpu_dm_connector *ac
        if (!link_supports_replay(link, aconnector))
                return false;
 
-       // Mark Replay is supported in link and update related attributes
+       // Mark Replay is supported in pr_config
        pr_config.replay_supported = true;
-       pr_config.replay_power_opt_supported = 0;
-       pr_config.replay_enable_option |= pr_enable_option_static_screen;
-       pr_config.replay_timing_sync_supported = aconnector->max_vfreq >= 2 * 
aconnector->min_vfreq;
-
-       if (!pr_config.replay_timing_sync_supported)
-               pr_config.replay_enable_option &= ~pr_enable_option_general_ui;
 
        debug_flags = (union replay_debug_flags *)&pr_config.debug_flags;
        debug_flags->u32All = 0;
        debug_flags->bitfields.visual_confirm =
                link->ctx->dc->debug.visual_confirm == VISUAL_CONFIRM_REPLAY;
 
-       link->replay_settings.replay_feature_enabled = true;
-
        init_replay_config(link, &pr_config);
 
        return true;
 }
 
+/*
+ * amdgpu_dm_link_setup_replay() - configure replay link
+ * @link: link
+ * @aconnector: aconnector
+ *
+ */
+bool amdgpu_dm_link_setup_replay(struct dc_link *link, struct 
amdgpu_dm_connector *aconnector)
+{
+       struct replay_config *pr_config;
+
+       if (link == NULL || aconnector == NULL)
+               return false;
+
+       pr_config = &link->replay_settings.config;
+
+       if (!pr_config->replay_supported)
+               return false;
+
+       pr_config->replay_power_opt_supported = 0x11;
+       pr_config->replay_smu_opt_supported = false;
+       pr_config->replay_enable_option |= pr_enable_option_static_screen;
+       pr_config->replay_support_fast_resync_in_ultra_sleep_mode = 
aconnector->max_vfreq >= 2 * aconnector->min_vfreq;
+       pr_config->replay_timing_sync_supported = false;
+
+       if (!pr_config->replay_timing_sync_supported)
+               pr_config->replay_enable_option &= ~pr_enable_option_general_ui;
+
+       link->replay_settings.replay_feature_enabled = true;
+
+       return true;
+}
 
 /*
  * amdgpu_dm_replay_enable() - enable replay f/w
@@ -117,51 +145,23 @@ bool amdgpu_dm_setup_replay(struct dc_link *link, struct 
amdgpu_dm_connector *ac
  */
 bool amdgpu_dm_replay_enable(struct dc_stream_state *stream, bool wait)
 {
-       uint64_t state;
-       unsigned int retry_count;
        bool replay_active = true;
-       const unsigned int max_retry = 1000;
-       bool force_static = true;
        struct dc_link *link = NULL;
 
-
        if (stream == NULL)
                return false;
 
        link = stream->link;
 
-       if (link == NULL)
-               return false;
-
-       link->dc->link_srv->edp_setup_replay(link, stream);
-
-       link->dc->link_srv->edp_set_replay_allow_active(link, NULL, false, 
false, NULL);
-
-       link->dc->link_srv->edp_set_replay_allow_active(link, &replay_active, 
false, true, NULL);
-
-       if (wait == true) {
-
-               for (retry_count = 0; retry_count <= max_retry; retry_count++) {
-                       dc_link_get_replay_state(link, &state);
-                       if (replay_active) {
-                               if (state != REPLAY_STATE_0 &&
-                                       (!force_static || state == 
REPLAY_STATE_3))
-                                       break;
-                       } else {
-                               if (state == REPLAY_STATE_0)
-                                       break;
-                       }
-                       udelay(500);
-               }
-
-               /* assert if max retry hit */
-               if (retry_count >= max_retry)
-                       ASSERT(0);
-       } else {
-               /* To-do: Add trace log */
+       if (link) {
+               link->dc->link_srv->edp_setup_replay(link, stream);
+               link->dc->link_srv->edp_set_coasting_vtotal(link, 
stream->timing.v_total);
+               DRM_DEBUG_DRIVER("Enabling replay...\n");
+               link->dc->link_srv->edp_set_replay_allow_active(link, 
&replay_active, wait, false, NULL);
+               return true;
        }
 
-       return true;
+       return false;
 }
 
 /*
@@ -172,12 +172,31 @@ bool amdgpu_dm_replay_enable(struct dc_stream_state 
*stream, bool wait)
  */
 bool amdgpu_dm_replay_disable(struct dc_stream_state *stream)
 {
+       bool replay_active = false;
+       struct dc_link *link = NULL;
 
-       if (stream->link) {
+       if (stream == NULL)
+               return false;
+
+       link = stream->link;
+
+       if (link) {
                DRM_DEBUG_DRIVER("Disabling replay...\n");
-               
stream->link->dc->link_srv->edp_set_replay_allow_active(stream->link, NULL, 
false, false, NULL);
+               link->dc->link_srv->edp_set_replay_allow_active(stream->link, 
&replay_active, true, false, NULL);
                return true;
        }
 
        return false;
 }
+
+/*
+ * amdgpu_dm_replay_disable_all() - disable replay f/w
+ * if replay is enabled on any stream
+ *
+ * Return: true if success
+ */
+bool amdgpu_dm_replay_disable_all(struct amdgpu_display_manager *dm)
+{
+       DRM_DEBUG_DRIVER("Disabling replay if replay is enabled on any 
stream\n");
+       return dc_set_replay_allow_active(dm->dc, false);
+}
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_replay.h 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_replay.h
index 01cba3cd6246..f0d30eb47312 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_replay.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_replay.h
@@ -40,7 +40,9 @@ enum replay_enable_option {
 
 
 bool amdgpu_dm_replay_enable(struct dc_stream_state *stream, bool enable);
-bool amdgpu_dm_setup_replay(struct dc_link *link, struct amdgpu_dm_connector 
*aconnector);
+bool amdgpu_dm_set_replay_caps(struct dc_link *link, struct 
amdgpu_dm_connector *aconnector);
+bool amdgpu_dm_link_setup_replay(struct dc_link *link, struct 
amdgpu_dm_connector *aconnector);
 bool amdgpu_dm_replay_disable(struct dc_stream_state *stream);
+bool amdgpu_dm_replay_disable_all(struct amdgpu_display_manager *dm);
 
 #endif /* AMDGPU_DM_AMDGPU_DM_REPLAY_H_ */
-- 
2.34.1

Reply via email to