Commit 45a1261b authored by Jake Wang's avatar Jake Wang Committed by Alex Deucher

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: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarJake Wang <haonan.wang2@amd.com>
Reviewed-by: default avatarNicholas Kazlauskas <Nicholas.Kazlauskas@amd.com>
Acked-by: default avatarRodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent cca912e0
...@@ -87,12 +87,16 @@ int clk_mgr_helper_get_active_plane_cnt( ...@@ -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) 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) if (dc->hwss.exit_optimized_pwr_state)
dc->hwss.exit_optimized_pwr_state(dc, dc->current_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; clk_mgr->psr_allow_active_cache = edp_link->psr_settings.psr_allow_active;
dc_link_set_psr_allow_active(edp_link, false, false, false); 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 ...@@ -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) 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, dc_link_set_psr_allow_active(edp_link,
clk_mgr->psr_allow_active_cache, false, false); clk_mgr->psr_allow_active_cache, false, false);
}
if (dc->hwss.optimize_pwr_state) if (dc->hwss.optimize_pwr_state)
dc->hwss.optimize_pwr_state(dc, dc->current_state); dc->hwss.optimize_pwr_state(dc, dc->current_state);
......
...@@ -1012,22 +1012,26 @@ struct dc *dc_create(const struct dc_init_data *init_params) ...@@ -1012,22 +1012,26 @@ struct dc *dc_create(const struct dc_init_data *init_params)
static void detect_edp_presence(struct dc *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; bool edp_sink_present = true;
if (!edp_link) get_edp_links(dc, edp_links, &edp_num);
if (!edp_num)
return; return;
if (dc->config.edp_not_connected) { if (dc->config.edp_not_connected) {
edp_sink_present = false; edp_sink_present = false;
} else { } else {
enum dc_connection_type type; enum dc_connection_type type;
for (i = 0; i < edp_num; i++) {
edp_link = edp_links[i];
dc_link_detect_sink(edp_link, &type); dc_link_detect_sink(edp_link, &type);
if (type == dc_connection_none) edp_link->edp_sink_present = (type != dc_connection_none);
edp_sink_present = false; }
} }
edp_link->edp_sink_present = edp_sink_present;
} }
void dc_hardware_init(struct dc *dc) void dc_hardware_init(struct dc *dc)
......
...@@ -52,6 +52,7 @@ struct aux_payload; ...@@ -52,6 +52,7 @@ struct aux_payload;
#define MAX_STREAMS 6 #define MAX_STREAMS 6
#define MAX_SINKS_PER_LINK 4 #define MAX_SINKS_PER_LINK 4
#define MIN_VIEWPORT_SIZE 12 #define MIN_VIEWPORT_SIZE 12
#define MAX_NUM_EDP 2
/******************************************************************************* /*******************************************************************************
* Display Core Interfaces * Display Core Interfaces
......
...@@ -187,16 +187,21 @@ static inline struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_ ...@@ -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]; 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; int i;
// report any eDP links, even unconnected DDI's *edp_num = 0;
for (i = 0; i < dc->link_count; i++) { for (i = 0; i < dc->link_count; i++) {
if (dc->links[i]->connector_signal == SIGNAL_TYPE_EDP) // report any eDP links, even unconnected DDI's
return dc->links[i]; 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). /* Set backlight level of an embedded panel (eDP, LVDS).
......
...@@ -216,6 +216,7 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub, ...@@ -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 == link &&
res_ctx->pipe_ctx[i].stream->link->connector_signal == SIGNAL_TYPE_EDP) { res_ctx->pipe_ctx[i].stream->link->connector_signal == SIGNAL_TYPE_EDP) {
pipe_ctx = &res_ctx->pipe_ctx[i]; pipe_ctx = &res_ctx->pipe_ctx[i];
//TODO: refactor for multi edp support
break; break;
} }
} }
......
...@@ -1629,34 +1629,39 @@ static void disable_vga_and_power_gate_all_controllers( ...@@ -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; int i;
*edp_stream_num = 0;
for (i = 0; i < context->stream_count; i++) { for (i = 0; i < context->stream_count; i++) {
if (context->streams[i]->signal == SIGNAL_TYPE_EDP) if (context->streams[i]->signal == SIGNAL_TYPE_EDP) {
return context->streams[i]; 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 *dc,
struct dc_state *context) struct dc_link **edp_links_with_sink,
int *edp_with_sink_num)
{ {
int i; int i;
struct dc_link *link = NULL;
/* check if there is an eDP panel not in use */ /* check if there is an eDP panel not in use */
*edp_with_sink_num = 0;
for (i = 0; i < dc->link_count; i++) { for (i = 0; i < dc->link_count; i++) {
if (dc->links[i]->local_sink && if (dc->links[i]->local_sink &&
dc->links[i]->local_sink->sink_signal == SIGNAL_TYPE_EDP) { dc->links[i]->local_sink->sink_signal == SIGNAL_TYPE_EDP) {
link = dc->links[i]; edp_links_with_sink[*edp_with_sink_num] = dc->links[i];
break; if (++(*edp_with_sink_num) == MAX_NUM_EDP)
return;
} }
} }
return link;
} }
/* /*
...@@ -1668,36 +1673,48 @@ static struct dc_link *get_edp_link_with_sink( ...@@ -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) void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context)
{ {
int i; struct dc_link *edp_links_with_sink[MAX_NUM_EDP];
struct dc_link *edp_link_with_sink = get_edp_link_with_sink(dc, context); struct dc_link *edp_links[MAX_NUM_EDP];
struct dc_link *edp_link = get_edp_link(dc); 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 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_edp_fast_boot = false;
bool can_apply_seamless_boot = false; bool can_apply_seamless_boot = false;
bool keep_edp_vdd_on = 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) if (hws->funcs.init_pipes)
hws->funcs.init_pipes(dc, context); 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 // 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_1 &&
dc->ctx->dce_version != DCE_VERSION_8_3) { dc->ctx->dce_version != DCE_VERSION_8_3) {
for (i = 0; i < edp_num; i++) {
edp_link = edp_links[i];
// enable fastboot if backend is enabled on eDP // enable fastboot if backend is enabled on eDP
if (edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc)) { if (edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc)) {
/* Set optimization flag on eDP stream*/ /* Set optimization flag on eDP stream*/
if (edp_stream && edp_link->link_status.link_active) { if (edp_stream_num && edp_link->link_status.link_active) {
edp_stream = edp_streams[0];
edp_stream->apply_edp_fast_boot_optimization = true; edp_stream->apply_edp_fast_boot_optimization = true;
can_apply_edp_fast_boot = true; can_apply_edp_fast_boot = true;
break;
}
} }
} }
// We are trying to enable eDP, don't power down VDD // We are trying to enable eDP, don't power down VDD
if (edp_stream) if (edp_stream_num)
keep_edp_vdd_on = true; keep_edp_vdd_on = true;
} }
...@@ -1712,6 +1729,9 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context) ...@@ -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 /* eDP should not have stream in resume from S4 and so even with VBios post
* it should get turned off * 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 (!can_apply_edp_fast_boot && !can_apply_seamless_boot) {
if (edp_link_with_sink && !keep_edp_vdd_on) { if (edp_link_with_sink && !keep_edp_vdd_on) {
/*turn off backlight before DP_blank and encoder powered down*/ /*turn off backlight before DP_blank and encoder powered down*/
......
...@@ -1462,12 +1462,17 @@ void dcn10_init_hw(struct dc *dc) ...@@ -1462,12 +1462,17 @@ void dcn10_init_hw(struct dc *dc)
*/ */
void dcn10_power_down_on_boot(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; struct dc_link *edp_link;
int edp_num;
int i = 0;
get_edp_links(dc, edp_links, &edp_num);
edp_link = get_edp_link(dc); if (edp_num) {
if (edp_link && for (i = 0; i < edp_num; i++) {
edp_link->link_enc->funcs->is_dig_enabled && 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) && edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) &&
dc->hwseq->funcs.edp_backlight_control && dc->hwseq->funcs.edp_backlight_control &&
dc->hwss.power_down && dc->hwss.power_down &&
...@@ -1475,6 +1480,8 @@ void dcn10_power_down_on_boot(struct dc *dc) ...@@ -1475,6 +1480,8 @@ void dcn10_power_down_on_boot(struct dc *dc)
dc->hwseq->funcs.edp_backlight_control(edp_link, false); dc->hwseq->funcs.edp_backlight_control(edp_link, false);
dc->hwss.power_down(dc); dc->hwss.power_down(dc);
dc->hwss.edp_power_control(edp_link, false); dc->hwss.edp_power_control(edp_link, false);
}
}
} else { } else {
for (i = 0; i < dc->link_count; i++) { for (i = 0; i < dc->link_count; i++) {
struct dc_link *link = dc->links[i]; struct dc_link *link = dc->links[i];
......
...@@ -421,11 +421,12 @@ void dcn30_program_all_writeback_pipes_in_tree( ...@@ -421,11 +421,12 @@ void dcn30_program_all_writeback_pipes_in_tree(
void dcn30_init_hw(struct dc *dc) void dcn30_init_hw(struct dc *dc)
{ {
int i, j;
struct abm **abms = dc->res_pool->multiple_abms; struct abm **abms = dc->res_pool->multiple_abms;
struct dce_hwseq *hws = dc->hwseq; struct dce_hwseq *hws = dc->hwseq;
struct dc_bios *dcb = dc->ctx->dc_bios; struct dc_bios *dcb = dc->ctx->dc_bios;
struct resource_pool *res_pool = dc->res_pool; struct resource_pool *res_pool = dc->res_pool;
int i, j;
int edp_num;
uint32_t backlight = MAX_BACKLIGHT_LEVEL; uint32_t backlight = MAX_BACKLIGHT_LEVEL;
if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks) if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks)
...@@ -574,10 +575,14 @@ void dcn30_init_hw(struct dc *dc) ...@@ -574,10 +575,14 @@ void dcn30_init_hw(struct dc *dc)
* if DIG is turned on and seamless boot not enabled * if DIG is turned on and seamless boot not enabled
*/ */
if (dc->config.power_down_display_on_boot) { if (dc->config.power_down_display_on_boot) {
struct dc_link *edp_link = get_edp_link(dc); struct dc_link *edp_links[MAX_NUM_EDP];
struct dc_link *edp_link;
if (edp_link &&
edp_link->link_enc->funcs->is_dig_enabled && 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) && edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) &&
dc->hwss.edp_backlight_control && dc->hwss.edp_backlight_control &&
dc->hwss.power_down && dc->hwss.power_down &&
...@@ -585,6 +590,8 @@ void dcn30_init_hw(struct dc *dc) ...@@ -585,6 +590,8 @@ void dcn30_init_hw(struct dc *dc)
dc->hwss.edp_backlight_control(edp_link, false); dc->hwss.edp_backlight_control(edp_link, false);
dc->hwss.power_down(dc); dc->hwss.power_down(dc);
dc->hwss.edp_power_control(edp_link, false); dc->hwss.edp_power_control(edp_link, false);
}
}
} else { } else {
for (i = 0; i < dc->link_count; i++) { for (i = 0; i < dc->link_count; i++) {
struct dc_link *link = dc->links[i]; struct dc_link *link = dc->links[i];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment