From a9edc81564c92b4d86670b722bbe8906e0dfd934 Mon Sep 17 00:00:00 2001 From: Wyatt Wood Date: Thu, 10 Sep 2020 21:50:52 -0400 Subject: [PATCH] drm/amd/display: Implement PSR wait for enable/disable [Why] For DMUB implementation of PSR, the 'wait' parameter, used to determine if driver should wait for PSR enable/disable, is not implemented correctly. [How] Implement wait for PSR enable/disable. Signed-off-by: Wyatt Wood Reviewed-by: Anthony Koo Acked-by: Qingqing Zhuo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 2 +- drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c | 27 ++++++++++++++++++- drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h | 2 +- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 1871ff6119ae..f13396254b5d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -2566,7 +2566,7 @@ bool dc_link_set_psr_allow_active(struct dc_link *link, bool allow_active, bool link->psr_settings.psr_allow_active = allow_active; if (psr != NULL && link->psr_settings.psr_feature_enabled) - psr->funcs->psr_enable(psr, allow_active); + psr->funcs->psr_enable(psr, allow_active, wait); 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 diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c index 5167d6b8a48d..bf24f1029547 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c @@ -119,10 +119,11 @@ static bool dmub_psr_set_version(struct dmub_psr *dmub, struct dc_stream_state * /** * Enable/Disable PSR. */ -static void dmub_psr_enable(struct dmub_psr *dmub, bool enable) +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; cmd.psr_enable.header.type = DMUB_CMD__PSR; @@ -136,6 +137,30 @@ static void dmub_psr_enable(struct dmub_psr *dmub, bool enable) 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); + + /* Below loops 1000 x 500us = 500 ms. + * Exit PSR may need to wait 1-2 frames to power up. Timeout after at + * least a few frames. Should never hit the max retry assert below. + */ + if (wait) { + for (retry_count = 0; retry_count <= 1000; retry_count++) { + dmub_psr_get_state(dmub, &psr_state); + + if (enable) { + if (psr_state != 0) + break; + } else { + if (psr_state == 0) + break; + } + + udelay(500); + } + + /* assert if max retry hit */ + if (retry_count >= 1000) + ASSERT(0); + } } /** diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h index f404fecd6410..dc121ed92d2e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h @@ -36,7 +36,7 @@ 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); + 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_set_level)(struct dmub_psr *dmub, uint16_t psr_level); };