From: Leo Chen <[email protected]>

[Why & How]
Aligned IPS FW state with DMCUB IPS FW state
Added debug option disable_ips_rcg to modify RCG behaviour in IPS modes.
Updated existing debug option disable_ips to align with new changes introduced 
by IPSv2.0

Reviewed-by: Duncan Ma <[email protected]>
Signed-off-by: Leo Chen <[email protected]>
Signed-off-by: Ivan Lipski <[email protected]>
---
 drivers/gpu/drm/amd/display/dc/dc.h           |  1 +
 drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c  | 51 ++++++++++++++-----
 .../gpu/drm/amd/display/dmub/inc/dmub_cmd.h   |  4 +-
 3 files changed, 41 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dc.h 
b/drivers/gpu/drm/amd/display/dc/dc.h
index aa1b976cf40d..8a09c5f487d3 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -515,6 +515,7 @@ struct dc_config {
        bool EnableMinDispClkODM;
        bool enable_auto_dpm_test_logs;
        unsigned int disable_ips;
+       unsigned int disable_ips_rcg;
        unsigned int disable_ips_in_vpb;
        bool disable_ips_in_dpms_off;
        bool usb4_bw_alloc_support;
diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c 
b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
index 0a47d1a3515b..c10e603b54af 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
+++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
@@ -1269,12 +1269,16 @@ static void dc_dmub_srv_notify_idle(const struct dc 
*dc, bool allow_idle)
                        new_signals.bits.allow_ips1 = 1;
                        new_signals.bits.allow_ips2 = 1;
                        new_signals.bits.allow_z10 = 1;
+                       // New in IPSv2.0
+                       new_signals.bits.allow_ips1z8 = 1;
                } else if (dc->config.disable_ips == DMUB_IPS_DISABLE_IPS1) {
                        new_signals.bits.allow_ips1 = 1;
                } else if (dc->config.disable_ips == DMUB_IPS_DISABLE_IPS2) {
+                       // IPSv1.0 only
                        new_signals.bits.allow_pg = 1;
                        new_signals.bits.allow_ips1 = 1;
                } else if (dc->config.disable_ips == DMUB_IPS_DISABLE_IPS2_Z10) 
{
+                       // IPSv1.0 only
                        new_signals.bits.allow_pg = 1;
                        new_signals.bits.allow_ips1 = 1;
                        new_signals.bits.allow_ips2 = 1;
@@ -1286,6 +1290,8 @@ static void dc_dmub_srv_notify_idle(const struct dc *dc, 
bool allow_idle)
                                new_signals.bits.allow_ips1 = 1;
                                new_signals.bits.allow_ips2 = 1;
                                new_signals.bits.allow_z10 = 1;
+                               // New in IPSv2.0
+                               new_signals.bits.allow_ips1z8 = 1;
                        } else {
                                /* RCG only */
                                new_signals.bits.allow_pg = 0;
@@ -1293,8 +1299,21 @@ static void dc_dmub_srv_notify_idle(const struct dc *dc, 
bool allow_idle)
                                new_signals.bits.allow_ips2 = 0;
                                new_signals.bits.allow_z10 = 0;
                        }
+               } else if (dc->config.disable_ips == 
DMUB_IPS_DISABLE_Z8_RETENTION) {
+                       new_signals.bits.allow_pg = 1;
+                       new_signals.bits.allow_ips1 = 1;
+                       new_signals.bits.allow_ips2 = 1;
+                       new_signals.bits.allow_z10 = 1;
+               }
+               // Setting RCG allow bits (IPSv2.0)
+               if (dc->config.disable_ips_rcg == DMUB_IPS_RCG_ENABLE) {
+                       new_signals.bits.allow_ips0_rcg = 1;
+                       new_signals.bits.allow_ips1_rcg = 1;
+               } else if (dc->config.disable_ips_rcg == DMUB_IPS0_RCG_DISABLE) 
{
+                       new_signals.bits.allow_ips1_rcg = 1;
+               } else if (dc->config.disable_ips_rcg == DMUB_IPS1_RCG_DISABLE) 
{
+                       new_signals.bits.allow_ips0_rcg = 1;
                }
-
                ips_driver->signals = new_signals;
                dc_dmub_srv->driver_signals = ips_driver->signals;
        }
@@ -1318,7 +1337,7 @@ static void dc_dmub_srv_notify_idle(const struct dc *dc, 
bool allow_idle)
 static void dc_dmub_srv_exit_low_power_state(const struct dc *dc)
 {
        struct dc_dmub_srv *dc_dmub_srv;
-       uint32_t rcg_exit_count = 0, ips1_exit_count = 0, ips2_exit_count = 0;
+       uint32_t rcg_exit_count = 0, ips1_exit_count = 0, ips2_exit_count = 0, 
ips1z8_exit_count = 0;
 
        if (dc->debug.dmcub_emulation)
                return;
@@ -1338,31 +1357,34 @@ static void dc_dmub_srv_exit_low_power_state(const 
struct dc *dc)
                rcg_exit_count = ips_fw->rcg_exit_count;
                ips1_exit_count = ips_fw->ips1_exit_count;
                ips2_exit_count = ips_fw->ips2_exit_count;
+               ips1z8_exit_count = ips_fw->ips1_z8ret_exit_count;
 
                ips_driver->signals.all = 0;
                dc_dmub_srv->driver_signals = ips_driver->signals;
 
                DC_LOG_IPS(
-                       "%s (allow ips1=%u ips2=%u) (commit ips1=%u ips2=%u) 
(count rcg=%u ips1=%u ips2=%u)",
+                       "%s (allow ips1=%u ips2=%u) (commit ips1=%u ips2=%u 
ips1z8=%u) (count rcg=%u ips1=%u ips2=%u ips1_z8=%u)",
                        __func__,
                        ips_driver->signals.bits.allow_ips1,
                        ips_driver->signals.bits.allow_ips2,
                        ips_fw->signals.bits.ips1_commit,
                        ips_fw->signals.bits.ips2_commit,
+                       ips_fw->signals.bits.ips1z8_commit,
                        ips_fw->rcg_entry_count,
                        ips_fw->ips1_entry_count,
-                       ips_fw->ips2_entry_count);
+                       ips_fw->ips2_entry_count,
+                       ips_fw->ips1_z8ret_entry_count);
 
                /* Note: register access has technically not resumed for DCN 
here, but we
                 * need to be message PMFW through our standard register 
interface.
                 */
                dc_dmub_srv->needs_idle_wake = false;
 
-               if ((prev_driver_signals.bits.allow_ips2 || 
prev_driver_signals.all == 0) &&
+               if (!dc->caps.ips_v2_support && 
((prev_driver_signals.bits.allow_ips2 || prev_driver_signals.all == 0) &&
                    (!dc->debug.optimize_ips_handshake ||
-                    ips_fw->signals.bits.ips2_commit || 
!ips_fw->signals.bits.in_idle)) {
+                    ips_fw->signals.bits.ips2_commit || 
!ips_fw->signals.bits.in_idle))) {
                        DC_LOG_IPS(
-                               "wait IPS2 eval (ips1_commit=%u 
ips2_commit=%u)",
+                               "wait IPS2 eval (ips1_commit=%u ips2_commit=%u 
)",
                                ips_fw->signals.bits.ips1_commit,
                                ips_fw->signals.bits.ips2_commit);
 
@@ -1422,28 +1444,31 @@ static void dc_dmub_srv_exit_low_power_state(const 
struct dc *dc)
                dc_dmub_srv_notify_idle(dc, false);
                if (prev_driver_signals.bits.allow_ips1 || 
prev_driver_signals.all == 0) {
                        DC_LOG_IPS(
-                               "wait for IPS1 commit clear (ips1_commit=%u 
ips2_commit=%u)",
+                               "wait for IPS1 commit clear (ips1_commit=%u 
ips2_commit=%u ips1z8=%u)",
                                ips_fw->signals.bits.ips1_commit,
-                               ips_fw->signals.bits.ips2_commit);
+                               ips_fw->signals.bits.ips2_commit,
+                               ips_fw->signals.bits.ips1z8_commit);
 
                        while (ips_fw->signals.bits.ips1_commit)
                                udelay(1);
 
                        DC_LOG_IPS(
-                               "wait for IPS1 commit clear done 
(ips1_commit=%u ips2_commit=%u)",
+                               "wait for IPS1 commit clear done 
(ips1_commit=%u ips2_commit=%u ips1z8=%u)",
                                ips_fw->signals.bits.ips1_commit,
-                               ips_fw->signals.bits.ips2_commit);
+                               ips_fw->signals.bits.ips2_commit,
+                               ips_fw->signals.bits.ips1z8_commit);
                }
        }
 
        if (!dc_dmub_srv_is_hw_pwr_up(dc->ctx->dmub_srv, true))
                ASSERT(0);
 
-       DC_LOG_IPS("%s exit (count rcg=%u ips1=%u ips2=%u)",
+       DC_LOG_IPS("%s exit (count rcg=%u ips1=%u ips2=%u ips1z8=%u)",
                __func__,
                rcg_exit_count,
                ips1_exit_count,
-               ips2_exit_count);
+               ips2_exit_count,
+               ips1z8_exit_count);
 }
 
 void dc_dmub_srv_set_power_state(struct dc_dmub_srv *dc_dmub_srv, enum 
dc_acpi_cm_power_state power_state)
diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h 
b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
index 5cf5dd5831fc..938a07cdcfec 100644
--- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
+++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
@@ -875,7 +875,7 @@ enum dmub_shared_state_feature_id {
 /**
  * struct dmub_shared_state_ips_fw - Firmware signals for IPS.
  */
-union dmub_shared_state_ips_fw_signals {
+ union dmub_shared_state_ips_fw_signals {
        struct {
                uint32_t ips1_commit : 1;  /**< 1 if in IPS1 or IPS0 RCG */
                uint32_t ips2_commit : 1; /**< 1 if in IPS2 */
@@ -890,7 +890,7 @@ union dmub_shared_state_ips_fw_signals {
 /**
  * struct dmub_shared_state_ips_signals - Firmware signals for IPS.
  */
-union dmub_shared_state_ips_driver_signals {
+ union dmub_shared_state_ips_driver_signals {
        struct {
                uint32_t allow_pg : 1; /**< 1 if PG is allowed */
                uint32_t allow_ips1 : 1; /**< 1 is IPS1 is allowed */
-- 
2.43.0

Reply via email to