From 45a1261b393bd3dc24d1ae8a55249c0897df0c88 Mon Sep 17 00:00:00 2001 From: Jake Wang Date: Fri, 5 Feb 2021 14:46:20 -0500 Subject: [PATCH] drm/amd/display: Refactored DC interfaces to support multiple eDP [Why & How] Some existing DC interfaces are optimized to return a single eDP link/stream. Refactored those DC interfaces to support multiple eDP. Tested-by: Daniel Wheeler Signed-off-by: Jake Wang Reviewed-by: Nicholas Kazlauskas Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c | 17 +++-- drivers/gpu/drm/amd/display/dc/core/dc.c | 18 +++-- drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/dc/dc_link.h | 15 ++-- drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c | 1 + .../display/dc/dce110/dce110_hw_sequencer.c | 72 ++++++++++++------- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 29 +++++--- .../drm/amd/display/dc/dcn30/dcn30_hwseq.c | 31 ++++---- 8 files changed, 119 insertions(+), 65 deletions(-) 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 995ffbbf64e7..f7c728d4f50a 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 @@ -87,12 +87,16 @@ int clk_mgr_helper_get_active_plane_cnt( void clk_mgr_exit_optimized_pwr_state(const struct dc *dc, struct clk_mgr *clk_mgr) { - struct dc_link *edp_link = get_edp_link(dc); + struct dc_link *edp_links[MAX_NUM_EDP]; + struct dc_link *edp_link = NULL; + int edp_num; + 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_link) { + 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); } @@ -101,11 +105,16 @@ void clk_mgr_exit_optimized_pwr_state(const struct dc *dc, struct clk_mgr *clk_m void clk_mgr_optimize_pwr_state(const struct dc *dc, struct clk_mgr *clk_mgr) { - struct dc_link *edp_link = get_edp_link(dc); + struct dc_link *edp_links[MAX_NUM_EDP]; + struct dc_link *edp_link = NULL; + int edp_num; - if (edp_link) + 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); + } if (dc->hwss.optimize_pwr_state) dc->hwss.optimize_pwr_state(dc, dc->current_state); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 1cdef90c03aa..87b8315cfbb8 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1012,22 +1012,26 @@ destruct_dc: static void detect_edp_presence(struct dc *dc) { - struct dc_link *edp_link = get_edp_link(dc); + struct dc_link *edp_links[MAX_NUM_EDP]; + struct dc_link *edp_link = NULL; + int i; + int edp_num; bool edp_sink_present = true; - if (!edp_link) + get_edp_links(dc, edp_links, &edp_num); + if (!edp_num) return; if (dc->config.edp_not_connected) { edp_sink_present = false; } else { enum dc_connection_type type; - dc_link_detect_sink(edp_link, &type); - if (type == dc_connection_none) - edp_sink_present = false; + for (i = 0; i < edp_num; i++) { + edp_link = edp_links[i]; + dc_link_detect_sink(edp_link, &type); + edp_link->edp_sink_present = (type != dc_connection_none); + } } - - edp_link->edp_sink_present = edp_sink_present; } void dc_hardware_init(struct dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 49e055a8309c..4ada3fe36b2b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -52,6 +52,7 @@ struct aux_payload; #define MAX_STREAMS 6 #define MAX_SINKS_PER_LINK 4 #define MIN_VIEWPORT_SIZE 12 +#define MAX_NUM_EDP 2 /******************************************************************************* * Display Core Interfaces diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h index df6ab333336c..c50ef5a909a6 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_link.h +++ b/drivers/gpu/drm/amd/display/dc/dc_link.h @@ -187,16 +187,21 @@ static inline struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_ return dc->links[link_index]; } -static inline struct dc_link *get_edp_link(const struct dc *dc) +static inline void get_edp_links(const struct dc *dc, + struct dc_link **edp_links, + int *edp_num) { int i; - // report any eDP links, even unconnected DDI's + *edp_num = 0; for (i = 0; i < dc->link_count; i++) { - if (dc->links[i]->connector_signal == SIGNAL_TYPE_EDP) - return dc->links[i]; + // report any eDP links, even unconnected DDI's + if (dc->links[i]->connector_signal == SIGNAL_TYPE_EDP) { + edp_links[*edp_num] = dc->links[i]; + if (++(*edp_num) == MAX_NUM_EDP) + return; + } } - return NULL; } /* Set backlight level of an embedded panel (eDP, LVDS). 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 c13f9674048e..62c019fd326e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c @@ -216,6 +216,7 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub, res_ctx->pipe_ctx[i].stream->link == link && res_ctx->pipe_ctx[i].stream->link->connector_signal == SIGNAL_TYPE_EDP) { pipe_ctx = &res_ctx->pipe_ctx[i]; + //TODO: refactor for multi edp support break; } } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index caee1c9f54bd..ddabc205bcfc 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1629,34 +1629,39 @@ static void disable_vga_and_power_gate_all_controllers( } -static struct dc_stream_state *get_edp_stream(struct dc_state *context) +static void get_edp_streams(struct dc_state *context, + struct dc_stream_state **edp_streams, + int *edp_stream_num) { int i; + *edp_stream_num = 0; for (i = 0; i < context->stream_count; i++) { - if (context->streams[i]->signal == SIGNAL_TYPE_EDP) - return context->streams[i]; + if (context->streams[i]->signal == SIGNAL_TYPE_EDP) { + edp_streams[*edp_stream_num] = context->streams[i]; + if (++(*edp_stream_num) == MAX_NUM_EDP) + return; + } } - return NULL; } -static struct dc_link *get_edp_link_with_sink( +static void get_edp_links_with_sink( struct dc *dc, - struct dc_state *context) + struct dc_link **edp_links_with_sink, + int *edp_with_sink_num) { int i; - struct dc_link *link = NULL; /* check if there is an eDP panel not in use */ + *edp_with_sink_num = 0; for (i = 0; i < dc->link_count; i++) { if (dc->links[i]->local_sink && dc->links[i]->local_sink->sink_signal == SIGNAL_TYPE_EDP) { - link = dc->links[i]; - break; + edp_links_with_sink[*edp_with_sink_num] = dc->links[i]; + if (++(*edp_with_sink_num) == MAX_NUM_EDP) + return; } } - - return link; } /* @@ -1668,36 +1673,48 @@ static struct dc_link *get_edp_link_with_sink( */ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context) { - int i; - struct dc_link *edp_link_with_sink = get_edp_link_with_sink(dc, context); - struct dc_link *edp_link = get_edp_link(dc); + struct dc_link *edp_links_with_sink[MAX_NUM_EDP]; + struct dc_link *edp_links[MAX_NUM_EDP]; + struct dc_stream_state *edp_streams[MAX_NUM_EDP]; + struct dc_link *edp_link_with_sink = NULL; + struct dc_link *edp_link = NULL; struct dc_stream_state *edp_stream = NULL; + struct dce_hwseq *hws = dc->hwseq; + int edp_with_sink_num; + int edp_num; + int edp_stream_num; + int i; bool can_apply_edp_fast_boot = false; bool can_apply_seamless_boot = false; bool keep_edp_vdd_on = false; - struct dce_hwseq *hws = dc->hwseq; + + get_edp_links_with_sink(dc, edp_links_with_sink, &edp_with_sink_num); + get_edp_links(dc, edp_links, &edp_num); if (hws->funcs.init_pipes) hws->funcs.init_pipes(dc, context); - edp_stream = get_edp_stream(context); + get_edp_streams(context, edp_streams, &edp_stream_num); // Check fastboot support, disable on DCE8 because of blank screens - if (edp_link && dc->ctx->dce_version != DCE_VERSION_8_0 && + if (edp_num && dc->ctx->dce_version != DCE_VERSION_8_0 && dc->ctx->dce_version != DCE_VERSION_8_1 && dc->ctx->dce_version != DCE_VERSION_8_3) { - - // enable fastboot if backend is enabled on eDP - if (edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc)) { - /* Set optimization flag on eDP stream*/ - if (edp_stream && edp_link->link_status.link_active) { - edp_stream->apply_edp_fast_boot_optimization = true; - can_apply_edp_fast_boot = true; + for (i = 0; i < edp_num; i++) { + edp_link = edp_links[i]; + // enable fastboot if backend is enabled on eDP + if (edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc)) { + /* Set optimization flag on eDP stream*/ + if (edp_stream_num && edp_link->link_status.link_active) { + edp_stream = edp_streams[0]; + edp_stream->apply_edp_fast_boot_optimization = true; + can_apply_edp_fast_boot = true; + break; + } } } - // We are trying to enable eDP, don't power down VDD - if (edp_stream) + if (edp_stream_num) keep_edp_vdd_on = true; } @@ -1712,6 +1729,9 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context) /* eDP should not have stream in resume from S4 and so even with VBios post * it should get turned off */ + if (edp_with_sink_num) + edp_link_with_sink = edp_links_with_sink[0]; + if (!can_apply_edp_fast_boot && !can_apply_seamless_boot) { if (edp_link_with_sink && !keep_edp_vdd_on) { /*turn off backlight before DP_blank and encoder powered down*/ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 74c2edae08f2..bdf40ef01607 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1462,19 +1462,26 @@ void dcn10_init_hw(struct dc *dc) */ void dcn10_power_down_on_boot(struct dc *dc) { - int i = 0; + struct dc_link *edp_links[MAX_NUM_EDP]; struct dc_link *edp_link; + int edp_num; + int i = 0; - edp_link = get_edp_link(dc); - if (edp_link && - edp_link->link_enc->funcs->is_dig_enabled && - edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) && - dc->hwseq->funcs.edp_backlight_control && - dc->hwss.power_down && - dc->hwss.edp_power_control) { - dc->hwseq->funcs.edp_backlight_control(edp_link, false); - dc->hwss.power_down(dc); - dc->hwss.edp_power_control(edp_link, false); + get_edp_links(dc, edp_links, &edp_num); + + if (edp_num) { + for (i = 0; i < edp_num; i++) { + edp_link = edp_links[i]; + if (edp_link->link_enc->funcs->is_dig_enabled && + edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) && + dc->hwseq->funcs.edp_backlight_control && + dc->hwss.power_down && + dc->hwss.edp_power_control) { + dc->hwseq->funcs.edp_backlight_control(edp_link, false); + dc->hwss.power_down(dc); + dc->hwss.edp_power_control(edp_link, false); + } + } } else { for (i = 0; i < dc->link_count; i++) { struct dc_link *link = dc->links[i]; diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c index 04de9d9b8e28..c626334e9346 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c @@ -421,11 +421,12 @@ void dcn30_program_all_writeback_pipes_in_tree( void dcn30_init_hw(struct dc *dc) { - int i, j; struct abm **abms = dc->res_pool->multiple_abms; struct dce_hwseq *hws = dc->hwseq; struct dc_bios *dcb = dc->ctx->dc_bios; struct resource_pool *res_pool = dc->res_pool; + int i, j; + int edp_num; uint32_t backlight = MAX_BACKLIGHT_LEVEL; if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks) @@ -574,17 +575,23 @@ void dcn30_init_hw(struct dc *dc) * if DIG is turned on and seamless boot not enabled */ if (dc->config.power_down_display_on_boot) { - struct dc_link *edp_link = get_edp_link(dc); - - if (edp_link && - edp_link->link_enc->funcs->is_dig_enabled && - edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) && - dc->hwss.edp_backlight_control && - dc->hwss.power_down && - dc->hwss.edp_power_control) { - dc->hwss.edp_backlight_control(edp_link, false); - dc->hwss.power_down(dc); - dc->hwss.edp_power_control(edp_link, false); + struct dc_link *edp_links[MAX_NUM_EDP]; + struct dc_link *edp_link; + + get_edp_links(dc, edp_links, &edp_num); + if (edp_num) { + for (i = 0; i < edp_num; i++) { + edp_link = edp_links[i]; + if (edp_link->link_enc->funcs->is_dig_enabled && + edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) && + dc->hwss.edp_backlight_control && + dc->hwss.power_down && + dc->hwss.edp_power_control) { + dc->hwss.edp_backlight_control(edp_link, false); + dc->hwss.power_down(dc); + dc->hwss.edp_power_control(edp_link, false); + } + } } else { for (i = 0; i < dc->link_count; i++) { struct dc_link *link = dc->links[i]; -- 2.20.1