From: Mikita Lipski Date: Mon, 17 May 2021 22:18:25 +0000 (-0400) Subject: drm/amd/display: Enabling PSR support for multiple panels X-Git-Tag: v5.15~765^2~15^2~30 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f56c837afce45ec904b23bfd4d7df3e304624972;p=platform%2Fkernel%2Flinux-starfive.git drm/amd/display: Enabling PSR support for multiple panels [why] Updating PSR interfaces to allow PSR enablement per eDP panel. [how] - Copying PSR command structures to DC - Changing function interfaces to pass panel instance - Communicating with DMUB per link instead of assuming to use a single one -Iterating through all PSR capable panels when enabling/disabling all Signed-off-by: Mikita Lipski Reviewed-by: Nicholas Kazlauskas Acked-by: Stylon Wang Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c index 2f41380..f652f491 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c @@ -93,15 +93,20 @@ void clk_mgr_exit_optimized_pwr_state(const struct dc *dc, struct clk_mgr *clk_m struct dc_link *edp_links[MAX_NUM_EDP]; struct dc_link *edp_link = NULL; int edp_num; + unsigned int panel_inst; get_edp_links(dc, edp_links, &edp_num); if (dc->hwss.exit_optimized_pwr_state) dc->hwss.exit_optimized_pwr_state(dc, dc->current_state); if (edp_num) { - edp_link = edp_links[0]; - clk_mgr->psr_allow_active_cache = edp_link->psr_settings.psr_allow_active; - dc_link_set_psr_allow_active(edp_link, false, false, false); + for (panel_inst = 0; panel_inst < edp_num; panel_inst++) { + edp_link = edp_links[panel_inst]; + if (!edp_link->psr_settings.psr_feature_enabled) + continue; + clk_mgr->psr_allow_active_cache = edp_link->psr_settings.psr_allow_active; + dc_link_set_psr_allow_active(edp_link, false, false, false); + } } } @@ -111,12 +116,17 @@ void clk_mgr_optimize_pwr_state(const struct dc *dc, struct clk_mgr *clk_mgr) struct dc_link *edp_links[MAX_NUM_EDP]; struct dc_link *edp_link = NULL; int edp_num; + unsigned int panel_inst; get_edp_links(dc, edp_links, &edp_num); if (edp_num) { - edp_link = edp_links[0]; - dc_link_set_psr_allow_active(edp_link, - clk_mgr->psr_allow_active_cache, false, false); + for (panel_inst = 0; panel_inst < edp_num; panel_inst++) { + edp_link = edp_links[panel_inst]; + if (!edp_link->psr_settings.psr_feature_enabled) + continue; + dc_link_set_psr_allow_active(edp_link, + clk_mgr->psr_allow_active_cache, false, false); + } } if (dc->hwss.optimize_pwr_state) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 0a8ecb8..2b7639a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -3278,10 +3278,13 @@ bool dc_set_psr_allow_active(struct dc *dc, bool enable) continue; 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, false); - else if (!enable && link->psr_settings.psr_allow_active) - return dc_link_set_psr_allow_active(link, false, true, false); + if (enable && !link->psr_settings.psr_allow_active) { + if (!dc_link_set_psr_allow_active(link, true, false, false)) + return false; + } else if (!enable && link->psr_settings.psr_allow_active) { + if (!dc_link_set_psr_allow_active(link, false, true, false)) + return false; + } } } 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 6e93e6a..89dab6a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -2701,10 +2701,14 @@ bool dc_link_set_psr_allow_active(struct dc_link *link, bool allow_active, struct dc *dc = link->ctx->dc; struct dmcu *dmcu = dc->res_pool->dmcu; struct dmub_psr *psr = dc->res_pool->psr; + unsigned int panel_inst; if (psr == NULL && force_static) return false; + if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst)) + return false; + link->psr_settings.psr_allow_active = allow_active; #if defined(CONFIG_DRM_AMD_DC_DCN3_1) if (!allow_active) @@ -2713,8 +2717,8 @@ bool dc_link_set_psr_allow_active(struct dc_link *link, bool allow_active, 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); + psr->funcs->psr_force_static(psr, panel_inst); + psr->funcs->psr_enable(psr, allow_active, wait, panel_inst); } 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 @@ -2728,9 +2732,13 @@ 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; + unsigned int panel_inst; + + if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst)) + return false; if (psr != NULL && link->psr_settings.psr_feature_enabled) - psr->funcs->psr_get_state(psr, state); + psr->funcs->psr_get_state(psr, state, panel_inst); else if (dmcu != NULL && link->psr_settings.psr_feature_enabled) dmcu->funcs->get_psr_state(dmcu, state); @@ -2780,6 +2788,7 @@ bool dc_link_setup_psr(struct dc_link *link, struct dmcu *dmcu; struct dmub_psr *psr; int i; + unsigned int panel_inst; /* updateSinkPsrDpcdConfig*/ union dpcd_psr_configuration psr_configuration; @@ -2795,6 +2804,9 @@ bool dc_link_setup_psr(struct dc_link *link, if (!dmcu && !psr) return false; + if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst)) + return false; + memset(&psr_configuration, 0, sizeof(psr_configuration)); @@ -2909,7 +2921,8 @@ bool dc_link_setup_psr(struct dc_link *link, psr_context->frame_delay = 0; if (psr) - link->psr_settings.psr_feature_enabled = psr->funcs->psr_copy_settings(psr, link, psr_context); + link->psr_settings.psr_feature_enabled = psr->funcs->psr_copy_settings(psr, + link, psr_context, panel_inst); else link->psr_settings.psr_feature_enabled = dmcu->funcs->setup_psr(dmcu, link, psr_context); 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 5e99553..c41db6d4e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c @@ -77,7 +77,7 @@ static enum dc_psr_state convert_psr_state(uint32_t raw_state) /* * Get PSR state from firmware. */ -static void dmub_psr_get_state(struct dmub_psr *dmub, enum dc_psr_state *state) +static void dmub_psr_get_state(struct dmub_psr *dmub, enum dc_psr_state *state, uint8_t panel_inst) { struct dmub_srv *srv = dmub->ctx->dmub_srv->dmub; uint32_t raw_state = 0; @@ -86,7 +86,7 @@ static void dmub_psr_get_state(struct dmub_psr *dmub, enum dc_psr_state *state) do { // Send gpint command and wait for ack - status = dmub_srv_send_gpint_command(srv, DMUB_GPINT__GET_PSR_STATE, 0, 30); + status = dmub_srv_send_gpint_command(srv, DMUB_GPINT__GET_PSR_STATE, panel_inst, 30); if (status == DMUB_STATUS_OK) { // GPINT was executed, get response @@ -105,7 +105,7 @@ static void dmub_psr_get_state(struct dmub_psr *dmub, enum dc_psr_state *state) /* * Set PSR version. */ -static bool dmub_psr_set_version(struct dmub_psr *dmub, struct dc_stream_state *stream) +static bool dmub_psr_set_version(struct dmub_psr *dmub, struct dc_stream_state *stream, uint8_t panel_inst) { union dmub_rb_cmd cmd; struct dc_context *dc = dmub->ctx; @@ -125,6 +125,8 @@ static bool dmub_psr_set_version(struct dmub_psr *dmub, struct dc_stream_state * cmd.psr_set_version.psr_set_version_data.version = PSR_VERSION_UNSUPPORTED; break; } + cmd.psr_set_version.psr_set_version_data.cmd_version = DMUB_CMD_PSR_CONTROL_VERSION_1; + cmd.psr_set_version.psr_set_version_data.panel_inst = panel_inst; cmd.psr_set_version.header.payload_bytes = sizeof(struct dmub_cmd_psr_set_version_data); dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd); @@ -137,7 +139,7 @@ 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, bool wait) +static void dmub_psr_enable(struct dmub_psr *dmub, bool enable, bool wait, uint8_t panel_inst) { union dmub_rb_cmd cmd; struct dc_context *dc = dmub->ctx; @@ -147,6 +149,9 @@ static void dmub_psr_enable(struct dmub_psr *dmub, bool enable, bool wait) memset(&cmd, 0, sizeof(cmd)); cmd.psr_enable.header.type = DMUB_CMD__PSR; + cmd.psr_enable.data.cmd_version = DMUB_CMD_PSR_CONTROL_VERSION_1; + cmd.psr_enable.data.panel_inst = panel_inst; + if (enable) cmd.psr_enable.header.sub_type = DMUB_CMD__PSR_ENABLE; else @@ -164,7 +169,7 @@ 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, &state); + dmub_psr_get_state(dmub, &state, panel_inst); if (enable) { if (state != PSR_STATE0) @@ -186,13 +191,13 @@ static void dmub_psr_enable(struct dmub_psr *dmub, bool enable, bool wait) /* * Set PSR level. */ -static void dmub_psr_set_level(struct dmub_psr *dmub, uint16_t psr_level) +static void dmub_psr_set_level(struct dmub_psr *dmub, uint16_t psr_level, uint8_t panel_inst) { union dmub_rb_cmd cmd; enum dc_psr_state state = PSR_STATE0; struct dc_context *dc = dmub->ctx; - dmub_psr_get_state(dmub, &state); + dmub_psr_get_state(dmub, &state, panel_inst); if (state == PSR_STATE0) return; @@ -202,7 +207,8 @@ static void dmub_psr_set_level(struct dmub_psr *dmub, uint16_t psr_level) cmd.psr_set_level.header.sub_type = DMUB_CMD__PSR_SET_LEVEL; cmd.psr_set_level.header.payload_bytes = sizeof(struct dmub_cmd_psr_set_level_data); cmd.psr_set_level.psr_set_level_data.psr_level = psr_level; - + cmd.psr_set_level.psr_set_level_data.cmd_version = PSR_VERSION_1; + cmd.psr_set_level.psr_set_level_data.panel_inst = panel_inst; 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); @@ -213,7 +219,8 @@ static void dmub_psr_set_level(struct dmub_psr *dmub, uint16_t psr_level) */ static bool dmub_psr_copy_settings(struct dmub_psr *dmub, struct dc_link *link, - struct psr_context *psr_context) + struct psr_context *psr_context, + uint8_t panel_inst) { union dmub_rb_cmd cmd; struct dc_context *dc = dmub->ctx; @@ -237,7 +244,7 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub, return false; // First, set the psr version - if (!dmub_psr_set_version(dmub, pipe_ctx->stream)) + if (!dmub_psr_set_version(dmub, pipe_ctx->stream, panel_inst)) return false; // Program DP DPHY fast training registers @@ -286,6 +293,8 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub, copy_settings_data->debug.bitfields.use_hw_lock_mgr = 1; copy_settings_data->fec_enable_status = (link->fec_state == dc_link_fec_enabled); copy_settings_data->fec_enable_delay_in100us = link->dc->debug.fec_enable_delay_in100us; + copy_settings_data->cmd_version = PSR_VERSION_1; + copy_settings_data->panel_inst = panel_inst; dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd); dc_dmub_srv_cmd_execute(dc->dmub_srv); @@ -297,12 +306,15 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub, /* * 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) +static void dmub_psr_force_static(struct dmub_psr *dmub, uint8_t panel_inst) { union dmub_rb_cmd cmd; struct dc_context *dc = dmub->ctx; memset(&cmd, 0, sizeof(cmd)); + + cmd.psr_force_static.psr_force_static_data.panel_inst = panel_inst; + cmd.psr_force_static.psr_force_static_data.cmd_version = DMUB_CMD_PSR_CONTROL_VERSION_1; 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; 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 fe747c2..bf73c7e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h @@ -35,11 +35,15 @@ 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, 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); + bool (*psr_copy_settings)(struct dmub_psr *dmub, struct dc_link *link, + struct psr_context *psr_context, uint8_t panel_inst); + void (*psr_enable)(struct dmub_psr *dmub, bool enable, bool wait, + uint8_t panel_inst); + void (*psr_get_state)(struct dmub_psr *dmub, enum dc_psr_state *dc_psr_state, + uint8_t panel_inst); + void (*psr_set_level)(struct dmub_psr *dmub, uint16_t psr_level, + uint8_t panel_inst); + void (*psr_force_static)(struct dmub_psr *dmub, uint8_t panel_inst); void (*psr_get_residency)(struct dmub_psr *dmub, uint32_t *residency); }; 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 026de4e..11edefd0 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -123,6 +123,17 @@ #define TRACE_BUFFER_ENTRY_OFFSET 16 /** + * + * PSR control version legacy + */ +#define DMUB_CMD_PSR_CONTROL_VERSION_UNKNOWN 0x0 +/** + * PSR control version with multi edp support + */ +#define DMUB_CMD_PSR_CONTROL_VERSION_1 0x1 + + +/** * ABM control version legacy */ #define DMUB_CMD_ABM_CONTROL_VERSION_UNKNOWN 0x0 @@ -1380,9 +1391,15 @@ struct dmub_cmd_psr_copy_settings_data { */ uint8_t fec_enable_delay_in100us; /** - * Explicit padding to 4 byte boundary. + * PSR control version. + */ + uint8_t cmd_version; + /** + * Panel Instance. + * Panel isntance to identify which psr_state to use + * Currently the support is only for 0 or 1 */ - uint8_t pad3[2]; + uint8_t panel_inst; }; /** @@ -1408,9 +1425,15 @@ struct dmub_cmd_psr_set_level_data { */ uint16_t psr_level; /** - * Explicit padding to 4 byte boundary. + * PSR control version. */ - uint8_t pad[2]; + uint8_t cmd_version; + /** + * Panel Instance. + * Panel isntance to identify which psr_state to use + * Currently the support is only for 0 or 1 + */ + uint8_t panel_inst; }; /** @@ -1427,6 +1450,23 @@ struct dmub_rb_cmd_psr_set_level { struct dmub_cmd_psr_set_level_data psr_set_level_data; }; +struct dmub_rb_cmd_psr_enable_data { + /** + * PSR control version. + */ + uint8_t cmd_version; + /** + * Panel Instance. + * Panel isntance to identify which psr_state to use + * Currently the support is only for 0 or 1 + */ + uint8_t panel_inst; + /** + * Explicit padding to 4 byte boundary. + */ + uint8_t pad[2]; +}; + /** * Definition of a DMUB_CMD__PSR_ENABLE command. * PSR enable/disable is controlled using the sub_type. @@ -1436,6 +1476,8 @@ struct dmub_rb_cmd_psr_enable { * Command header. */ struct dmub_cmd_header header; + + struct dmub_rb_cmd_psr_enable_data data; }; /** @@ -1446,6 +1488,20 @@ struct dmub_cmd_psr_set_version_data { * PSR version that FW should implement. */ enum psr_version version; + /** + * PSR control version. + */ + uint8_t cmd_version; + /** + * Panel Instance. + * Panel isntance to identify which psr_state to use + * Currently the support is only for 0 or 1 + */ + uint8_t panel_inst; + /** + * Explicit padding to 4 byte boundary. + */ + uint8_t pad[2]; }; /** @@ -1462,6 +1518,23 @@ struct dmub_rb_cmd_psr_set_version { struct dmub_cmd_psr_set_version_data psr_set_version_data; }; +struct dmub_cmd_psr_force_static_data { + /** + * PSR control version. + */ + uint8_t cmd_version; + /** + * Panel Instance. + * Panel isntance to identify which psr_state to use + * Currently the support is only for 0 or 1 + */ + uint8_t panel_inst; + /** + * Explicit padding to 4 byte boundary. + */ + uint8_t pad[2]; +}; + /** * Definition of a DMUB_CMD__PSR_FORCE_STATIC command. */ @@ -1470,6 +1543,10 @@ struct dmub_rb_cmd_psr_force_static { * Command header. */ struct dmub_cmd_header header; + /** + * Data passed from driver to FW in a DMUB_CMD__PSR_FORCE_STATIC command. + */ + struct dmub_cmd_psr_force_static_data psr_force_static_data; }; /**