]> git.baikalelectronics.ru Git - kernel.git/commitdiff
drm/amd/display: Engage PSR synchronously
authorKrunoslav Kovac <Krunoslav.Kovac@amd.com>
Tue, 20 Oct 2020 20:23:15 +0000 (16:23 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 10 Nov 2020 19:24:55 +0000 (14:24 -0500)
[Why & How]
The intended use is to force PSR into active state and ignore all
events until explicit EXIT.
A new event force_static is added to power module. It is then sent
to FW.

Signed-off-by: Krunoslav Kovac <Krunoslav.Kovac@amd.com>
Acked-by: Bindu Ramamurthy <bindu.r@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
12 files changed:
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/display/dc/core/dc_link.c
drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
drivers/gpu/drm/amd/display/dc/dc_link.h
drivers/gpu/drm/amd/display/dc/dc_types.h
drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c
drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c
drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h
drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h

index 2855bb918535810a038a34524c9f408f60a0e2f4..152b1b1f3c07046765e76c13ac04565e38396eee 100644 (file)
@@ -9611,7 +9611,7 @@ bool amdgpu_dm_psr_enable(struct dc_stream_state *stream)
                                           &stream, 1,
                                           &params);
 
-       return dc_link_set_psr_allow_active(link, true, false);
+       return dc_link_set_psr_allow_active(link, true, false, false);
 }
 
 /*
@@ -9625,7 +9625,7 @@ static bool amdgpu_dm_psr_disable(struct dc_stream_state *stream)
 
        DRM_DEBUG_DRIVER("Disabling psr...\n");
 
-       return dc_link_set_psr_allow_active(stream->link, false, true);
+       return dc_link_set_psr_allow_active(stream->link, false, true, false);
 }
 
 /*
index d31380ea57dc5db907e89dfc1d183e831c86a7c4..11459fb09a372a5b165aa62084344480c1638998 100644 (file)
@@ -2333,11 +2333,11 @@ static int psr_get(void *data, u64 *val)
 {
        struct amdgpu_dm_connector *connector = data;
        struct dc_link *link = connector->dc_link;
-       uint32_t psr_state = 0;
+       enum dc_psr_state state = PSR_STATE0;
 
-       dc_link_get_psr_state(link, &psr_state);
+       dc_link_get_psr_state(link, &state);
 
-       *val = psr_state;
+       *val = state;
 
        return 0;
 }
index 73c91027572b68bcd860ba2630a1789d2fb36c1f..995ffbbf64e7ca104f5205f84b1b6c24796e04a4 100644 (file)
@@ -94,7 +94,7 @@ void clk_mgr_exit_optimized_pwr_state(const struct dc *dc, struct clk_mgr *clk_m
 
        if (edp_link) {
                clk_mgr->psr_allow_active_cache = edp_link->psr_settings.psr_allow_active;
-               dc_link_set_psr_allow_active(edp_link, false, false);
+               dc_link_set_psr_allow_active(edp_link, false, false, false);
        }
 
 }
@@ -104,7 +104,8 @@ void clk_mgr_optimize_pwr_state(const struct dc *dc, struct clk_mgr *clk_mgr)
        struct dc_link *edp_link = get_edp_link(dc);
 
        if (edp_link)
-               dc_link_set_psr_allow_active(edp_link, clk_mgr->psr_allow_active_cache, false);
+               dc_link_set_psr_allow_active(edp_link,
+                               clk_mgr->psr_allow_active_cache, false, false);
 
        if (dc->hwss.optimize_pwr_state)
                dc->hwss.optimize_pwr_state(dc, dc->current_state);
index 5951f7d4022f95918e6aaa5864e2beefa864070a..28b856e2686dca3d9d437f9c838c5c0e383d5826 100644 (file)
@@ -3058,9 +3058,9 @@ bool dc_set_psr_allow_active(struct dc *dc, bool enable)
 
                if (link->psr_settings.psr_feature_enabled) {
                        if (enable && !link->psr_settings.psr_allow_active)
-                               return dc_link_set_psr_allow_active(link, true, false);
+                               return dc_link_set_psr_allow_active(link, true, false, false);
                        else if (!enable && link->psr_settings.psr_allow_active)
-                               return dc_link_set_psr_allow_active(link, false, true);
+                               return dc_link_set_psr_allow_active(link, false, true, false);
                }
        }
 
index ea9c459c91305c0df913513b357bce21a505e51b..ee2a51b7a2eeeccf41723b428649ed097c837035 100644 (file)
@@ -2565,17 +2565,23 @@ bool dc_link_set_backlight_level(const struct dc_link *link,
        return true;
 }
 
-bool dc_link_set_psr_allow_active(struct dc_link *link, bool allow_active, bool wait)
+bool dc_link_set_psr_allow_active(struct dc_link *link, bool allow_active,
+               bool wait, bool force_static)
 {
        struct dc  *dc = link->ctx->dc;
        struct dmcu *dmcu = dc->res_pool->dmcu;
        struct dmub_psr *psr = dc->res_pool->psr;
 
+       if (psr == NULL && force_static)
+               return false;
+
        link->psr_settings.psr_allow_active = allow_active;
 
-       if (psr != NULL && link->psr_settings.psr_feature_enabled)
+       if (psr != NULL && link->psr_settings.psr_feature_enabled) {
+               if (force_static && psr->funcs->psr_force_static)
+                       psr->funcs->psr_force_static(psr);
                psr->funcs->psr_enable(psr, allow_active, wait);
-       else if ((dmcu != NULL && dmcu->funcs->is_dmcu_initialized(dmcu)) && link->psr_settings.psr_feature_enabled)
+       else if ((dmcu != NULL && dmcu->funcs->is_dmcu_initialized(dmcu)) && link->psr_settings.psr_feature_enabled)
                dmcu->funcs->set_psr_enable(dmcu, allow_active, wait);
        else
                return false;
@@ -2583,16 +2589,16 @@ bool dc_link_set_psr_allow_active(struct dc_link *link, bool allow_active, bool
        return true;
 }
 
-bool dc_link_get_psr_state(const struct dc_link *link, uint32_t *psr_state)
+bool dc_link_get_psr_state(const struct dc_link *link, enum dc_psr_state *state)
 {
        struct dc  *dc = link->ctx->dc;
        struct dmcu *dmcu = dc->res_pool->dmcu;
        struct dmub_psr *psr = dc->res_pool->psr;
 
        if (psr != NULL && link->psr_settings.psr_feature_enabled)
-               psr->funcs->psr_get_state(psr, psr_state);
+               psr->funcs->psr_get_state(psr, state);
        else if (dmcu != NULL && link->psr_settings.psr_feature_enabled)
-               dmcu->funcs->get_psr_state(dmcu, psr_state);
+               dmcu->funcs->get_psr_state(dmcu, state);
 
        return true;
 }
index 8a7c4de49a4b418bc55ea77bfe8b858e199456cf..6c60c1fdebdc19fdca47aed22dafe1d537648fa2 100644 (file)
@@ -2575,8 +2575,8 @@ static bool handle_hpd_irq_psr_sink(struct dc_link *link)
                                sizeof(psr_error_status.raw));
 
                        /* PSR error, disable and re-enable PSR */
-                       dc_link_set_psr_allow_active(link, false, true);
-                       dc_link_set_psr_allow_active(link, true, true);
+                       dc_link_set_psr_allow_active(link, false, true, false);
+                       dc_link_set_psr_allow_active(link, true, true, false);
 
                        return true;
                } else if (psr_sink_psr_status.bits.SINK_SELF_REFRESH_STATUS ==
index 266b93a705d5551063727f6bcdb741bf4e72e1a2..39277aaa3e62d343dba698c151d8c0b7d6c6fc91 100644 (file)
@@ -219,9 +219,10 @@ int dc_link_get_backlight_level(const struct dc_link *dc_link);
 
 int dc_link_get_target_backlight_pwm(const struct dc_link *link);
 
-bool dc_link_set_psr_allow_active(struct dc_link *dc_link, bool enable, bool wait);
+bool dc_link_set_psr_allow_active(struct dc_link *dc_link, bool enable,
+               bool wait, bool force_static);
 
-bool dc_link_get_psr_state(const struct dc_link *dc_link, uint32_t *psr_state);
+bool dc_link_get_psr_state(const struct dc_link *dc_link, enum dc_psr_state *state);
 
 bool dc_link_setup_psr(struct dc_link *dc_link,
                const struct dc_stream_state *stream, struct psr_config *psr_config,
index 53c29d811493d94f02861eeafcb3da706e90b073..86406b42572c570d48e0c5327aa6403179bb3dfd 100644 (file)
@@ -671,6 +671,25 @@ struct dc_plane_flip_time {
        unsigned int prev_update_time_in_us;
 };
 
+enum dc_psr_state {
+       PSR_STATE0 = 0x0,
+       PSR_STATE1,
+       PSR_STATE1a,
+       PSR_STATE2,
+       PSR_STATE2a,
+       PSR_STATE3,
+       PSR_STATE3Init,
+       PSR_STATE4,
+       PSR_STATE4a,
+       PSR_STATE4b,
+       PSR_STATE4c,
+       PSR_STATE4d,
+       PSR_STATE5,
+       PSR_STATE5a,
+       PSR_STATE5b,
+       PSR_STATE5c
+};
+
 struct psr_config {
        unsigned char psr_version;
        unsigned int psr_rfb_setup_time;
index f0cebe721bcc1385961bb7da64c309449fa03db8..f3ed8b619cafd5b84b05ecc5c6e4cd64d059097a 100644 (file)
@@ -99,7 +99,7 @@ bool dce_dmcu_load_iram(struct dmcu *dmcu,
        return true;
 }
 
-static void dce_get_dmcu_psr_state(struct dmcu *dmcu, uint32_t *psr_state)
+static void dce_get_dmcu_psr_state(struct dmcu *dmcu, enum dc_psr_state *state)
 {
        struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu);
 
@@ -114,7 +114,7 @@ static void dce_get_dmcu_psr_state(struct dmcu *dmcu, uint32_t *psr_state)
        REG_WRITE(DMCU_IRAM_RD_CTRL, psr_state_offset);
 
        /* Read data from IRAM_RD_DATA in DMCU_IRAM_RD_DATA*/
-       *psr_state = REG_READ(DMCU_IRAM_RD_DATA);
+       *state = (enum dc_psr_state)REG_READ(DMCU_IRAM_RD_DATA);
 
        /* Disable write access to IRAM after finished using IRAM
         * in order to allow dynamic sleep state
@@ -129,7 +129,7 @@ static void dce_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable, bool wait)
        unsigned int dmcu_wait_reg_ready_interval = 100;
 
        unsigned int retryCount;
-       uint32_t psr_state = 0;
+       enum dc_psr_state state = PSR_STATE0;
 
        /* waitDMCUReadyForCmd */
        REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0,
@@ -148,12 +148,12 @@ static void dce_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable, bool wait)
        REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
        if (wait == true) {
                for (retryCount = 0; retryCount <= 100; retryCount++) {
-                       dce_get_dmcu_psr_state(dmcu, &psr_state);
+                       dce_get_dmcu_psr_state(dmcu, &state);
                        if (enable) {
-                               if (psr_state != 0)
+                               if (state != PSR_STATE0)
                                        break;
                        } else {
-                               if (psr_state == 0)
+                               if (state == PSR_STATE0)
                                        break;
                        }
                        udelay(10);
@@ -513,7 +513,7 @@ static bool dcn10_dmcu_load_iram(struct dmcu *dmcu,
        return true;
 }
 
-static void dcn10_get_dmcu_psr_state(struct dmcu *dmcu, uint32_t *psr_state)
+static void dcn10_get_dmcu_psr_state(struct dmcu *dmcu, enum dc_psr_state *state)
 {
        struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu);
 
@@ -532,7 +532,7 @@ static void dcn10_get_dmcu_psr_state(struct dmcu *dmcu, uint32_t *psr_state)
        REG_WRITE(DMCU_IRAM_RD_CTRL, psr_state_offset);
 
        /* Read data from IRAM_RD_DATA in DMCU_IRAM_RD_DATA*/
-       *psr_state = REG_READ(DMCU_IRAM_RD_DATA);
+       *state = (enum dc_psr_state)REG_READ(DMCU_IRAM_RD_DATA);
 
        /* Disable write access to IRAM after finished using IRAM
         * in order to allow dynamic sleep state
@@ -547,7 +547,7 @@ static void dcn10_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable, bool wait)
        unsigned int dmcu_wait_reg_ready_interval = 100;
 
        unsigned int retryCount;
-       uint32_t psr_state = 0;
+       enum dc_psr_state state = PSR_STATE0;
 
        /* If microcontroller is not running, do nothing */
        if (dmcu->dmcu_state != DMCU_RUNNING)
@@ -575,12 +575,12 @@ static void dcn10_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable, bool wait)
         */
        if (wait == true) {
                for (retryCount = 0; retryCount <= 1000; retryCount++) {
-                       dcn10_get_dmcu_psr_state(dmcu, &psr_state);
+                       dcn10_get_dmcu_psr_state(dmcu, &state);
                        if (enable) {
-                               if (psr_state != 0)
+                               if (state != PSR_STATE0)
                                        break;
                        } else {
-                               if (psr_state == 0)
+                               if (state == PSR_STATE0)
                                        break;
                        }
                        udelay(500);
index 67af67ef28659e91468329126d506f423cf84ada..df3879c713c5669cd976a2814a79f760880d1f48 100644 (file)
 /**
  * Convert dmcub psr state to dmcu psr state.
  */
-static void convert_psr_state(uint32_t *psr_state)
+static enum dc_psr_state convert_psr_state(uint32_t raw_state)
 {
-       if (*psr_state == 0)
-               *psr_state = 0;
-       else if (*psr_state == 0x10)
-               *psr_state = 1;
-       else if (*psr_state == 0x11)
-               *psr_state = 2;
-       else if (*psr_state == 0x20)
-               *psr_state = 3;
-       else if (*psr_state == 0x21)
-               *psr_state = 4;
-       else if (*psr_state == 0x30)
-               *psr_state = 5;
-       else if (*psr_state == 0x31)
-               *psr_state = 6;
-       else if (*psr_state == 0x40)
-               *psr_state = 7;
-       else if (*psr_state == 0x41)
-               *psr_state = 8;
-       else if (*psr_state == 0x42)
-               *psr_state = 9;
-       else if (*psr_state == 0x43)
-               *psr_state = 10;
-       else if (*psr_state == 0x44)
-               *psr_state = 11;
-       else if (*psr_state == 0x50)
-               *psr_state = 12;
-       else if (*psr_state == 0x51)
-               *psr_state = 13;
-       else if (*psr_state == 0x52)
-               *psr_state = 14;
-       else if (*psr_state == 0x53)
-               *psr_state = 15;
+       enum dc_psr_state state = PSR_STATE0;
+
+       if (raw_state == 0)
+               state = PSR_STATE0;
+       else if (raw_state == 0x10)
+               state = PSR_STATE1;
+       else if (raw_state == 0x11)
+               state = PSR_STATE1a;
+       else if (raw_state == 0x20)
+               state = PSR_STATE2;
+       else if (raw_state == 0x21)
+               state = PSR_STATE2a;
+       else if (raw_state == 0x30)
+               state = PSR_STATE3;
+       else if (raw_state == 0x31)
+               state = PSR_STATE3Init;
+       else if (raw_state == 0x40)
+               state = PSR_STATE4;
+       else if (raw_state == 0x41)
+               state = PSR_STATE4a;
+       else if (raw_state == 0x42)
+               state = PSR_STATE4b;
+       else if (raw_state == 0x43)
+               state = PSR_STATE4c;
+       else if (raw_state == 0x44)
+               state = PSR_STATE4d;
+       else if (raw_state == 0x50)
+               state = PSR_STATE5;
+       else if (raw_state == 0x51)
+               state = PSR_STATE5a;
+       else if (raw_state == 0x52)
+               state = PSR_STATE5b;
+       else if (raw_state == 0x53)
+               state = PSR_STATE5c;
+
+       return state;
 }
 
 /**
  * Get PSR state from firmware.
  */
-static void dmub_psr_get_state(struct dmub_psr *dmub, uint32_t *psr_state)
+static void dmub_psr_get_state(struct dmub_psr *dmub, enum dc_psr_state *state)
 {
        struct dmub_srv *srv = dmub->ctx->dmub_srv->dmub;
+       uint32_t raw_state;
 
        // Send gpint command and wait for ack
        dmub_srv_send_gpint_command(srv, DMUB_GPINT__GET_PSR_STATE, 0, 30);
 
-       dmub_srv_get_gpint_response(srv, psr_state);
+       dmub_srv_get_gpint_response(srv, &raw_state);
 
-       convert_psr_state(psr_state);
+       *state = convert_psr_state(raw_state);
 }
 
 /**
@@ -123,7 +128,9 @@ static void dmub_psr_enable(struct dmub_psr *dmub, bool enable, bool wait)
 {
        union dmub_rb_cmd cmd;
        struct dc_context *dc = dmub->ctx;
-       uint32_t retry_count, psr_state = 0;
+       uint32_t retry_count;
+       enum dc_psr_state state = PSR_STATE0;
+
 
        cmd.psr_enable.header.type = DMUB_CMD__PSR;
 
@@ -144,13 +151,13 @@ static void dmub_psr_enable(struct dmub_psr *dmub, bool enable, bool wait)
         */
        if (wait) {
                for (retry_count = 0; retry_count <= 1000; retry_count++) {
-                       dmub_psr_get_state(dmub, &psr_state);
+                       dmub_psr_get_state(dmub, &state);
 
                        if (enable) {
-                               if (psr_state != 0)
+                               if (state != PSR_STATE0)
                                        break;
                        } else {
-                               if (psr_state == 0)
+                               if (state == PSR_STATE0)
                                        break;
                        }
 
@@ -169,12 +176,12 @@ static void dmub_psr_enable(struct dmub_psr *dmub, bool enable, bool wait)
 static void dmub_psr_set_level(struct dmub_psr *dmub, uint16_t psr_level)
 {
        union dmub_rb_cmd cmd;
-       uint32_t psr_state = 0;
+       enum dc_psr_state state = PSR_STATE0;
        struct dc_context *dc = dmub->ctx;
 
-       dmub_psr_get_state(dmub, &psr_state);
+       dmub_psr_get_state(dmub, &state);
 
-       if (psr_state == 0)
+       if (state == PSR_STATE0)
                return;
 
        cmd.psr_set_level.header.type = DMUB_CMD__PSR;
@@ -269,11 +276,29 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub,
        return true;
 }
 
+/**
+ * Send command to PSR to force static ENTER and ignore all state changes until exit
+ */
+static void dmub_psr_force_static(struct dmub_psr *dmub)
+{
+       union dmub_rb_cmd cmd;
+       struct dc_context *dc = dmub->ctx;
+
+       cmd.psr_force_static.header.type = DMUB_CMD__PSR;
+       cmd.psr_force_static.header.sub_type = DMUB_CMD__PSR_FORCE_STATIC;
+       cmd.psr_enable.header.payload_bytes = 0;
+
+       dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
+       dc_dmub_srv_cmd_execute(dc->dmub_srv);
+       dc_dmub_srv_wait_idle(dc->dmub_srv);
+}
+
 static const struct dmub_psr_funcs psr_funcs = {
        .psr_copy_settings              = dmub_psr_copy_settings,
        .psr_enable                     = dmub_psr_enable,
        .psr_get_state                  = dmub_psr_get_state,
        .psr_set_level                  = dmub_psr_set_level,
+       .psr_force_static               = dmub_psr_force_static,
 };
 
 /**
index dc121ed92d2e1eef7312526b74c9ce8a8100933e..4e113ac5a56bf9ebb6af6150a90f26b81bc32fd8 100644 (file)
@@ -37,8 +37,9 @@ struct dmub_psr {
 struct dmub_psr_funcs {
        bool (*psr_copy_settings)(struct dmub_psr *dmub, struct dc_link *link, struct psr_context *psr_context);
        void (*psr_enable)(struct dmub_psr *dmub, bool enable, bool wait);
-       void (*psr_get_state)(struct dmub_psr *dmub, uint32_t *psr_state);
+       void (*psr_get_state)(struct dmub_psr *dmub, enum dc_psr_state *dc_psr_state);
        void (*psr_set_level)(struct dmub_psr *dmub, uint16_t psr_level);
+       void (*psr_force_static)(struct dmub_psr *dmub);
 };
 
 struct dmub_psr *dmub_psr_create(struct dc_context *ctx);
index 5315f1f86b219f904dc07d095741147104ed59b3..69d9fbfb4bec18a183fc604b315ad2c4a8e430ac 100644 (file)
@@ -66,7 +66,7 @@ struct dmcu_funcs {
        bool (*setup_psr)(struct dmcu *dmcu,
                        struct dc_link *link,
                        struct psr_context *psr_context);
-       void (*get_psr_state)(struct dmcu *dmcu, uint32_t *psr_state);
+       void (*get_psr_state)(struct dmcu *dmcu, enum dc_psr_state *dc_psr_state);
        void (*set_psr_wait_loop)(struct dmcu *dmcu,
                        unsigned int wait_loop_number);
        void (*get_psr_wait_loop)(struct dmcu *dmcu,