summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJake Wang <haonan.wang2@amd.com>2021-02-05 22:46:20 +0300
committerAlex Deucher <alexander.deucher@amd.com>2021-03-02 22:06:45 +0300
commit45a1261b393bd3dc24d1ae8a55249c0897df0c88 (patch)
treebd4f73b8269e06ade4bd2e33ad1422b98503cee0
parentcca912e0a6b49f45c588e7cc50d3ad13bb859ca5 (diff)
downloadlinux-45a1261b393bd3dc24d1ae8a55249c0897df0c88.tar.xz
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 <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>
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c17
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc.c18
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_link.h15
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c72
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c29
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c31
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];