drm/amd/display: Refactored DC interfaces to support multiple eDP
authorJake Wang <haonan.wang2@amd.com>
Fri, 5 Feb 2021 19:46:20 +0000 (14:46 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 2 Mar 2021 19:06:45 +0000 (14:06 -0500)
[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 <daniel.wheeler@amd.com>
Signed-off-by: Jake Wang <haonan.wang2@amd.com>
Reviewed-by: Nicholas Kazlauskas <Nicholas.Kazlauskas@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
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/dc.h
drivers/gpu/drm/amd/display/dc/dc_link.h
drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c
drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c

index 995ffbb..f7c728d 100644 (file)
@@ -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);
index 1cdef90..87b8315 100644 (file)
@@ -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)
index 49e055a..4ada3fe 100644 (file)
@@ -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
index df6ab33..c50ef5a 100644 (file)
@@ -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).
index c13f967..62c019f 100644 (file)
@@ -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;
                }
        }
index caee1c9..ddabc20 100644 (file)
@@ -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*/
index 74c2eda..bdf40ef 100644 (file)
@@ -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];
index 04de9d9..c626334 100644 (file)
@@ -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];