From: Wei-Guang Li <[email protected]>

[Why&How]
Add driver-side support for querying boot-time cumulative PHY-off
residency via the REPLAY_SNAPSHOT_CUMULATIVE_RESIDENCY GPINT command
implemented in DMUB FW.

Reviewed-by: Jack Chang <[email protected]>
Signed-off-by: Wei-Guang Li <[email protected]>
Signed-off-by: Jack Chang <[email protected]>
Signed-off-by: Chenyu Chen <[email protected]>
---
 .../gpu/drm/amd/display/dc/dce/dmub_replay.c  | 25 +++++++++++++++++++
 .../gpu/drm/amd/display/dc/dce/dmub_replay.h  |  2 ++
 .../gpu/drm/amd/display/dc/inc/link_service.h |  2 ++
 .../drm/amd/display/dc/link/link_factory.c    |  1 +
 .../link/protocols/link_edp_panel_control.c   | 22 ++++++++++++++++
 .../link/protocols/link_edp_panel_control.h   |  2 ++
 .../drm/amd/display/modules/inc/mod_power.h   |  3 +++
 .../amd/display/modules/power/power_replay.c  | 13 ++++++++++
 8 files changed, 70 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c 
b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c
index eda3a2f1402c..0785a30eb643 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c
@@ -415,6 +415,30 @@ static void dmub_replay_send_cmd(struct dmub_replay *dmub,
        dc_wake_and_execute_dmub_cmd(ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
 }
 
+static bool dmub_replay_get_cumulative_residency(struct dmub_replay *dmub,
+       uint8_t panel_inst, uint32_t *residency_milli_pct)
+{
+       uint32_t milli_pct = 0;
+       uint16_t param = (uint16_t)panel_inst;
+
+       if (!residency_milli_pct)
+               return false;
+
+       /* Zero on failure so the caller never reads a stale value, and report
+        * false so a failed query is still distinguishable from a genuine 0%.
+        */
+       *residency_milli_pct = 0;
+
+       if (!dc_wake_and_execute_gpint(dmub->ctx,
+                       DMUB_GPINT__REPLAY_SNAPSHOT_CUMULATIVE_RESIDENCY,
+                       param, &milli_pct, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY))
+               return false;
+
+       *residency_milli_pct = milli_pct;
+
+       return true;
+}
+
 static const struct dmub_replay_funcs replay_funcs = {
        .replay_copy_settings                           = 
dmub_replay_copy_settings,
        .replay_enable                                  = dmub_replay_enable,
@@ -424,6 +448,7 @@ static const struct dmub_replay_funcs replay_funcs = {
        .replay_residency                               = dmub_replay_residency,
        .replay_set_power_opt_and_coasting_vtotal       = 
dmub_replay_set_power_opt_and_coasting_vtotal,
        .replay_send_cmd                                = dmub_replay_send_cmd,
+       .replay_get_cumulative_residency                = 
dmub_replay_get_cumulative_residency,
 };
 
 /*
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.h 
b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.h
index 07c79739a980..271a42a226e9 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.h
+++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.h
@@ -33,6 +33,8 @@ struct dmub_replay_funcs {
        void (*replay_set_power_opt_and_coasting_vtotal)(struct dmub_replay 
*dmub,
                unsigned int power_opt, uint8_t panel_inst, uint32_t 
coasting_vtotal,
                uint16_t frame_skip_number);
+       bool (*replay_get_cumulative_residency)(struct dmub_replay *dmub,
+               uint8_t panel_inst, uint32_t *residency_milli_pct);
 };
 
 struct dmub_replay *dmub_replay_create(struct dc_context *ctx);
diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_service.h 
b/drivers/gpu/drm/amd/display/dc/inc/link_service.h
index eaf20ca14bcc..b2f86c51d470 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/link_service.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/link_service.h
@@ -297,6 +297,8 @@ struct link_service {
        bool (*edp_replay_residency)(const struct dc_link *link,
                        unsigned int *residency, const bool is_start,
                        const enum pr_residency_mode mode);
+       bool (*edp_replay_get_cumulative_residency)(const struct dc_link *link,
+                       uint32_t *residency_milli_pct);
        bool (*edp_set_replay_power_opt_and_coasting_vtotal)(struct dc_link 
*link,
                        const unsigned int *power_opts, uint32_t 
coasting_vtotal, uint16_t frame_skip_number);
 
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_factory.c 
b/drivers/gpu/drm/amd/display/dc/link/link_factory.c
index fa281de1d566..3b192c539f8b 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_factory.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_factory.c
@@ -223,6 +223,7 @@ static void construct_link_service_edp_panel_control(struct 
link_service *link_s
        link_srv->edp_send_replay_cmd = edp_send_replay_cmd;
        link_srv->edp_set_coasting_vtotal = edp_set_coasting_vtotal;
        link_srv->edp_replay_residency = edp_replay_residency;
+       link_srv->edp_replay_get_cumulative_residency = 
edp_replay_get_cumulative_residency;
        link_srv->edp_set_replay_power_opt_and_coasting_vtotal = 
edp_set_replay_power_opt_and_coasting_vtotal;
 
        link_srv->edp_wait_for_t12 = edp_wait_for_t12;
diff --git 
a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c 
b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c
index 9883216dcc9d..e904c7dd320e 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c
@@ -1154,6 +1154,28 @@ bool edp_replay_residency(const struct dc_link *link,
        return true;
 }
 
+bool edp_replay_get_cumulative_residency(const struct dc_link *link,
+       uint32_t *residency_milli_pct)
+{
+       struct dc *dc = link->ctx->dc;
+       struct dmub_replay *replay = dc->res_pool->replay;
+       unsigned int panel_inst;
+
+       if (!dp_pr_get_pr_panel_inst(dc, link, &panel_inst))
+               return false;
+
+       if (replay && link->replay_settings.replay_feature_enabled &&
+           replay->funcs->replay_get_cumulative_residency)
+               return replay->funcs->replay_get_cumulative_residency(replay,
+                       (uint8_t)panel_inst, residency_milli_pct);
+
+       if (residency_milli_pct)
+               *residency_milli_pct = 0;
+
+       return true;
+}
+
+
 bool edp_set_replay_power_opt_and_coasting_vtotal(struct dc_link *link,
        const unsigned int *power_opts, uint32_t coasting_vtotal, uint16_t 
frame_skip_number)
 {
diff --git 
a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h 
b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h
index 51de13e2387e..0082f5e91878 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h
@@ -60,6 +60,8 @@ bool edp_send_replay_cmd(struct dc_link *link,
 bool edp_set_coasting_vtotal(struct dc_link *link, uint32_t coasting_vtotal, 
uint16_t frame_skip_number);
 bool edp_replay_residency(const struct dc_link *link,
        unsigned int *residency, const bool is_start, const enum 
pr_residency_mode mode);
+bool edp_replay_get_cumulative_residency(const struct dc_link *link,
+       uint32_t *residency_milli_pct);
 bool edp_get_replay_state(const struct dc_link *link, uint64_t *state);
 bool edp_set_replay_power_opt_and_coasting_vtotal(struct dc_link *link,
        const unsigned int *power_opts, uint32_t coasting_vtotal, uint16_t 
frame_skip_number);
diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_power.h 
b/drivers/gpu/drm/amd/display/modules/inc/mod_power.h
index 5d1275b7cd46..25a0c96ac754 100644
--- a/drivers/gpu/drm/amd/display/modules/inc/mod_power.h
+++ b/drivers/gpu/drm/amd/display/modules/inc/mod_power.h
@@ -375,6 +375,9 @@ bool mod_power_replay_set_coasting_vtotal(struct mod_power 
*mod_power,
 void mod_power_replay_residency(const struct dc_stream_state *stream,
        unsigned int *residency, const bool is_start, const bool is_alpm);
 
+bool mod_power_replay_get_cumulative_residency(const struct dc_stream_state 
*stream,
+       uint32_t *residency_milli_pct);
+
 bool mod_power_replay_set_power_opt_and_coasting_vtotal(struct mod_power 
*mod_power,
        const struct dc_stream_state *stream, unsigned int 
active_replay_events, uint32_t coasting_vtotal,
        bool is_ultra_sleep_mode, uint16_t frame_skip_number);
diff --git a/drivers/gpu/drm/amd/display/modules/power/power_replay.c 
b/drivers/gpu/drm/amd/display/modules/power/power_replay.c
index 31d9cb3a12ba..7861e46c612d 100644
--- a/drivers/gpu/drm/amd/display/modules/power/power_replay.c
+++ b/drivers/gpu/drm/amd/display/modules/power/power_replay.c
@@ -761,6 +761,19 @@ void mod_power_replay_residency(const struct 
dc_stream_state *stream,
                link->dc->link_srv->edp_replay_residency(link, residency, 
is_start, mode);
 }
 
+bool mod_power_replay_get_cumulative_residency(const struct dc_stream_state 
*stream,
+       uint32_t *residency_milli_pct)
+{
+       const struct dc_link *link = dc_stream_get_link(stream);
+
+       if (!link || !link->dc || !link->dc->link_srv)
+               return false;
+
+       return link->dc->link_srv->edp_replay_get_cumulative_residency(
+               link, residency_milli_pct);
+}
+
+
 bool mod_power_replay_set_power_opt_and_coasting_vtotal(struct mod_power 
*mod_power,
        const struct dc_stream_state *stream, unsigned int 
active_replay_events, uint32_t coasting_vtotal,
        bool is_ultra_sleep_mode, uint16_t frame_skip_number)
-- 
2.43.0

Reply via email to