summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/display/dc/link
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/link')
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/Makefile2
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c65
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.h19
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_trace.c21
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_trace.h17
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c22
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_dp.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/link_detection.c132
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/link_detection.h15
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/link_dpms.c100
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/link_dpms.h23
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/link_factory.c275
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/link_factory.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/link_resource.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/link_validation.c81
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/link_validation.h11
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c24
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.h31
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c103
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.h28
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia.h4
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c175
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.h57
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c30
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.h12
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c10
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c60
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_auxless.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_auxless.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c9
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.c378
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.h5
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c56
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h30
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_hpd.c14
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_hpd.h7
41 files changed, 1420 insertions, 428 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/link/Makefile b/drivers/gpu/drm/amd/display/dc/link/Makefile
index 40352d8d7648..a52b56e2859e 100644
--- a/drivers/gpu/drm/amd/display/dc/link/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/link/Makefile
@@ -55,7 +55,7 @@ LINK_PROTOCOLS = link_hpd.o link_ddc.o link_dpcd.o link_dp_dpia.o \
link_dp_training.o link_dp_training_8b_10b.o link_dp_training_128b_132b.o \
link_dp_training_dpia.o link_dp_training_auxless.o \
link_dp_training_fixed_vs_pe_retimer.o link_dp_phy.o link_dp_capability.o \
-link_edp_panel_control.o link_dp_irq_handler.o
+link_edp_panel_control.o link_dp_irq_handler.o link_dp_dpia_bw.o
AMD_DAL_LINK_PROTOCOLS = $(addprefix $(AMDDALPATH)/dc/link/protocols/, \
$(LINK_PROTOCOLS))
diff --git a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c
index 942300e0bd92..db9f1baa27e5 100644
--- a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c
+++ b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c
@@ -28,6 +28,7 @@
#include "link/protocols/link_dp_training.h"
#include "link/protocols/link_dp_phy.h"
#include "link/protocols/link_dp_training_fixed_vs_pe_retimer.h"
+#include "link/protocols/link_dp_capability.h"
#include "link/link_dpms.h"
#include "resource.h"
#include "dm_helpers.h"
@@ -75,7 +76,7 @@ static bool is_dp_phy_pattern(enum dp_test_pattern test_pattern)
return false;
}
-void dp_retrain_link_dp_test(struct dc_link *link,
+static void dp_retrain_link_dp_test(struct dc_link *link,
struct dc_link_settings *link_setting,
bool skip_video_pattern)
{
@@ -250,7 +251,7 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link)
/* prepare link training settings */
link_training_settings.link_settings = link->cur_link_settings;
- link_training_settings.lttpr_mode = dc_link_decide_lttpr_mode(link, &link->cur_link_settings);
+ link_training_settings.lttpr_mode = dp_decide_lttpr_mode(link, &link->cur_link_settings);
if ((link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
link_training_settings.lttpr_mode == LTTPR_MODE_TRANSPARENT)
@@ -408,7 +409,7 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link)
* all the time. Do not touch it.
* forward request to DS
*/
- dc_link_dp_set_test_pattern(
+ dp_set_test_pattern(
link,
test_pattern,
DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED,
@@ -585,7 +586,7 @@ static void set_crtc_test_pattern(struct dc_link *link,
}
}
-void dc_link_dp_handle_automated_test(struct dc_link *link)
+void dp_handle_automated_test(struct dc_link *link)
{
union test_request test_request;
union test_response test_response;
@@ -651,7 +652,7 @@ void dc_link_dp_handle_automated_test(struct dc_link *link)
sizeof(test_response));
}
-bool dc_link_dp_set_test_pattern(
+bool dp_set_test_pattern(
struct dc_link *link,
enum dp_test_pattern test_pattern,
enum dp_test_pattern_color_space test_pattern_color_space,
@@ -941,28 +942,9 @@ bool dc_link_dp_set_test_pattern(
return true;
}
-void dc_link_set_drive_settings(struct dc *dc,
- struct link_training_settings *lt_settings,
- const struct dc_link *link)
-{
-
- int i;
- struct link_resource link_res;
-
- for (i = 0; i < dc->link_count; i++)
- if (dc->links[i] == link)
- break;
-
- if (i >= dc->link_count)
- ASSERT_CRITICAL(false);
-
- link_get_cur_link_res(link, &link_res);
- dp_set_drive_settings(dc->links[i], &link_res, lt_settings);
-}
-
-void dc_link_set_preferred_link_settings(struct dc *dc,
- struct dc_link_settings *link_setting,
- struct dc_link *link)
+void dp_set_preferred_link_settings(struct dc *dc,
+ struct dc_link_settings *link_setting,
+ struct dc_link *link)
{
int i;
struct pipe_ctx *pipe;
@@ -1001,11 +983,11 @@ void dc_link_set_preferred_link_settings(struct dc *dc,
dp_retrain_link_dp_test(link, &store_settings, false);
}
-void dc_link_set_preferred_training_settings(struct dc *dc,
- struct dc_link_settings *link_setting,
- struct dc_link_training_overrides *lt_overrides,
- struct dc_link *link,
- bool skip_immediate_retrain)
+void dp_set_preferred_training_settings(struct dc *dc,
+ struct dc_link_settings *link_setting,
+ struct dc_link_training_overrides *lt_overrides,
+ struct dc_link *link,
+ bool skip_immediate_retrain)
{
if (lt_overrides != NULL)
link->preferred_training_settings = *lt_overrides;
@@ -1025,22 +1007,5 @@ void dc_link_set_preferred_training_settings(struct dc *dc,
/* Retrain now, or wait until next stream update to apply */
if (skip_immediate_retrain == false)
- dc_link_set_preferred_link_settings(dc, &link->preferred_link_setting, link);
-}
-
-void dc_link_set_test_pattern(struct dc_link *link,
- enum dp_test_pattern test_pattern,
- enum dp_test_pattern_color_space test_pattern_color_space,
- const struct link_training_settings *p_link_settings,
- const unsigned char *p_custom_pattern,
- unsigned int cust_pattern_size)
-{
- if (link != NULL)
- dc_link_dp_set_test_pattern(
- link,
- test_pattern,
- test_pattern_color_space,
- p_link_settings,
- p_custom_pattern,
- cust_pattern_size);
+ dp_set_preferred_link_settings(dc, &link->preferred_link_setting, link);
}
diff --git a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.h b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.h
index 7f17838b653b..eae23ea7f6ec 100644
--- a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.h
+++ b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.h
@@ -25,9 +25,20 @@
#ifndef __LINK_DP_CTS_H__
#define __LINK_DP_CTS_H__
#include "link.h"
-
-void dp_retrain_link_dp_test(struct dc_link *link,
+void dp_handle_automated_test(struct dc_link *link);
+bool dp_set_test_pattern(
+ struct dc_link *link,
+ enum dp_test_pattern test_pattern,
+ enum dp_test_pattern_color_space test_pattern_color_space,
+ const struct link_training_settings *p_link_settings,
+ const unsigned char *p_custom_pattern,
+ unsigned int cust_pattern_size);
+void dp_set_preferred_link_settings(struct dc *dc,
struct dc_link_settings *link_setting,
- bool skip_video_pattern);
-
+ struct dc_link *link);
+void dp_set_preferred_training_settings(struct dc *dc,
+ struct dc_link_settings *link_setting,
+ struct dc_link_training_overrides *lt_overrides,
+ struct dc_link *link,
+ bool skip_immediate_retrain);
#endif /* __LINK_DP_CTS_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_trace.c b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_trace.c
index 459b362ed374..fbcd8fb58ea8 100644
--- a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_trace.c
+++ b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_trace.c
@@ -37,7 +37,7 @@ void dp_trace_reset(struct dc_link *link)
memset(&link->dp_trace, 0, sizeof(link->dp_trace));
}
-bool dc_dp_trace_is_initialized(struct dc_link *link)
+bool dp_trace_is_initialized(struct dc_link *link)
{
return link->dp_trace.is_initialized;
}
@@ -76,7 +76,7 @@ void dp_trace_lt_total_count_increment(struct dc_link *link,
link->dp_trace.commit_lt_trace.counts.total++;
}
-void dc_dp_trace_set_is_logged_flag(struct dc_link *link,
+void dp_trace_set_is_logged_flag(struct dc_link *link,
bool in_detection,
bool is_logged)
{
@@ -86,8 +86,7 @@ void dc_dp_trace_set_is_logged_flag(struct dc_link *link,
link->dp_trace.commit_lt_trace.is_logged = is_logged;
}
-bool dc_dp_trace_is_logged(struct dc_link *link,
- bool in_detection)
+bool dp_trace_is_logged(struct dc_link *link, bool in_detection)
{
if (in_detection)
return link->dp_trace.detect_lt_trace.is_logged;
@@ -123,7 +122,7 @@ void dp_trace_set_lt_end_timestamp(struct dc_link *link,
link->dp_trace.commit_lt_trace.timestamps.end = dm_get_timestamp(link->dc->ctx);
}
-unsigned long long dc_dp_trace_get_lt_end_timestamp(struct dc_link *link,
+unsigned long long dp_trace_get_lt_end_timestamp(struct dc_link *link,
bool in_detection)
{
if (in_detection)
@@ -132,7 +131,7 @@ unsigned long long dc_dp_trace_get_lt_end_timestamp(struct dc_link *link,
return link->dp_trace.commit_lt_trace.timestamps.end;
}
-struct dp_trace_lt_counts *dc_dp_trace_get_lt_counts(struct dc_link *link,
+const struct dp_trace_lt_counts *dp_trace_get_lt_counts(struct dc_link *link,
bool in_detection)
{
if (in_detection)
@@ -141,12 +140,12 @@ struct dp_trace_lt_counts *dc_dp_trace_get_lt_counts(struct dc_link *link,
return &link->dp_trace.commit_lt_trace.counts;
}
-unsigned int dc_dp_trace_get_link_loss_count(struct dc_link *link)
+unsigned int dp_trace_get_link_loss_count(struct dc_link *link)
{
return link->dp_trace.link_loss_count;
}
-void link_dp_trace_set_edp_power_timestamp(struct dc_link *link,
+void dp_trace_set_edp_power_timestamp(struct dc_link *link,
bool power_up)
{
if (!power_up)
@@ -156,17 +155,17 @@ void link_dp_trace_set_edp_power_timestamp(struct dc_link *link,
link->dp_trace.edp_trace_power_timestamps.poweron = dm_get_timestamp(link->dc->ctx);
}
-uint64_t link_dp_trace_get_edp_poweron_timestamp(struct dc_link *link)
+uint64_t dp_trace_get_edp_poweron_timestamp(struct dc_link *link)
{
return link->dp_trace.edp_trace_power_timestamps.poweron;
}
-uint64_t link_dp_trace_get_edp_poweroff_timestamp(struct dc_link *link)
+uint64_t dp_trace_get_edp_poweroff_timestamp(struct dc_link *link)
{
return link->dp_trace.edp_trace_power_timestamps.poweroff;
}
-void link_dp_source_sequence_trace(struct dc_link *link, uint8_t dp_test_mode)
+void dp_trace_source_sequence(struct dc_link *link, uint8_t dp_test_mode)
{
if (link != NULL && link->dc->debug.enable_driver_sequence_debug)
core_link_write_dpcd(link, DP_SOURCE_SEQUENCE,
diff --git a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_trace.h b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_trace.h
index 89feea1b2692..ab437a0c9101 100644
--- a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_trace.h
+++ b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_trace.h
@@ -28,7 +28,7 @@
void dp_trace_init(struct dc_link *link);
void dp_trace_reset(struct dc_link *link);
-bool dc_dp_trace_is_initialized(struct dc_link *link);
+bool dp_trace_is_initialized(struct dc_link *link);
void dp_trace_detect_lt_init(struct dc_link *link);
void dp_trace_commit_lt_init(struct dc_link *link);
void dp_trace_link_loss_increment(struct dc_link *link);
@@ -37,10 +37,10 @@ void dp_trace_lt_fail_count_update(struct dc_link *link,
bool in_detection);
void dp_trace_lt_total_count_increment(struct dc_link *link,
bool in_detection);
-void dc_dp_trace_set_is_logged_flag(struct dc_link *link,
+void dp_trace_set_is_logged_flag(struct dc_link *link,
bool in_detection,
bool is_logged);
-bool dc_dp_trace_is_logged(struct dc_link *link,
+bool dp_trace_is_logged(struct dc_link *link,
bool in_detection);
void dp_trace_lt_result_update(struct dc_link *link,
enum link_training_result result,
@@ -49,10 +49,15 @@ void dp_trace_set_lt_start_timestamp(struct dc_link *link,
bool in_detection);
void dp_trace_set_lt_end_timestamp(struct dc_link *link,
bool in_detection);
-unsigned long long dc_dp_trace_get_lt_end_timestamp(struct dc_link *link,
+unsigned long long dp_trace_get_lt_end_timestamp(struct dc_link *link,
bool in_detection);
-struct dp_trace_lt_counts *dc_dp_trace_get_lt_counts(struct dc_link *link,
+const struct dp_trace_lt_counts *dp_trace_get_lt_counts(struct dc_link *link,
bool in_detection);
-unsigned int dc_dp_trace_get_link_loss_count(struct dc_link *link);
+unsigned int dp_trace_get_link_loss_count(struct dc_link *link);
+void dp_trace_set_edp_power_timestamp(struct dc_link *link,
+ bool power_up);
+uint64_t dp_trace_get_edp_poweron_timestamp(struct dc_link *link);
+uint64_t dp_trace_get_edp_poweroff_timestamp(struct dc_link *link);
+void dp_trace_source_sequence(struct dc_link *link, uint8_t dp_test_mode);
#endif /* __LINK_DP_TRACE_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c
index b092b00b3599..bebf9c4c8702 100644
--- a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c
+++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c
@@ -44,7 +44,7 @@ void setup_dio_stream_encoder(struct pipe_ctx *pipe_ctx)
link_enc->funcs->connect_dig_be_to_fe(link_enc,
pipe_ctx->stream_res.stream_enc->id, true);
if (dc_is_dp_signal(pipe_ctx->stream->signal))
- link_dp_source_sequence_trace(pipe_ctx->stream->link,
+ pipe_ctx->stream->ctx->dc->link_srv->dp_trace_source_sequence(pipe_ctx->stream->link,
DPCD_SOURCE_SEQ_AFTER_CONNECT_DIG_FE_BE);
if (stream_enc->funcs->enable_fifo)
stream_enc->funcs->enable_fifo(stream_enc);
@@ -63,7 +63,8 @@ void reset_dio_stream_encoder(struct pipe_ctx *pipe_ctx)
pipe_ctx->stream_res.stream_enc->id,
false);
if (dc_is_dp_signal(pipe_ctx->stream->signal))
- link_dp_source_sequence_trace(pipe_ctx->stream->link,
+ pipe_ctx->stream->ctx->dc->link_srv->dp_trace_source_sequence(
+ pipe_ctx->stream->link,
DPCD_SOURCE_SEQ_AFTER_DISCONNECT_DIG_FE_BE);
}
@@ -105,7 +106,8 @@ void setup_dio_stream_attribute(struct pipe_ctx *pipe_ctx)
&stream->timing);
if (dc_is_dp_signal(stream->signal))
- link_dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DP_STREAM_ATTR);
+ link->dc->link_srv->dp_trace_source_sequence(link,
+ DPCD_SOURCE_SEQ_AFTER_DP_STREAM_ATTR);
}
void enable_dio_dp_link_output(struct dc_link *link,
@@ -126,7 +128,8 @@ void enable_dio_dp_link_output(struct dc_link *link,
link_enc,
link_settings,
clock_source);
- link_dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_ENABLE_LINK_PHY);
+ link->dc->link_srv->dp_trace_source_sequence(link,
+ DPCD_SOURCE_SEQ_AFTER_ENABLE_LINK_PHY);
}
void disable_dio_link_output(struct dc_link *link,
@@ -136,7 +139,8 @@ void disable_dio_link_output(struct dc_link *link,
struct link_encoder *link_enc = link_enc_cfg_get_link_enc(link);
link_enc->funcs->disable_output(link_enc, signal);
- link_dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_LINK_PHY);
+ link->dc->link_srv->dp_trace_source_sequence(link,
+ DPCD_SOURCE_SEQ_AFTER_DISABLE_LINK_PHY);
}
void set_dio_dp_link_test_pattern(struct dc_link *link,
@@ -146,7 +150,7 @@ void set_dio_dp_link_test_pattern(struct dc_link *link,
struct link_encoder *link_enc = link_enc_cfg_get_link_enc(link);
link_enc->funcs->dp_set_phy_pattern(link_enc, tp_params);
- link_dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_SET_SOURCE_PATTERN);
+ link->dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_SET_SOURCE_PATTERN);
}
void set_dio_dp_lane_settings(struct dc_link *link,
@@ -195,7 +199,8 @@ void enable_dio_audio_packet(struct pipe_ctx *pipe_ctx)
pipe_ctx->stream_res.stream_enc, false);
if (dc_is_dp_signal(pipe_ctx->stream->signal))
- link_dp_source_sequence_trace(pipe_ctx->stream->link,
+ pipe_ctx->stream->ctx->dc->link_srv->dp_trace_source_sequence(
+ pipe_ctx->stream->link,
DPCD_SOURCE_SEQ_AFTER_ENABLE_AUDIO_STREAM);
}
@@ -214,7 +219,8 @@ void disable_dio_audio_packet(struct pipe_ctx *pipe_ctx)
}
if (dc_is_dp_signal(pipe_ctx->stream->signal))
- link_dp_source_sequence_trace(pipe_ctx->stream->link,
+ pipe_ctx->stream->ctx->dc->link_srv->dp_trace_source_sequence(
+ pipe_ctx->stream->link,
DPCD_SOURCE_SEQ_AFTER_DISABLE_AUDIO_STREAM);
}
diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_dp.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_dp.c
index aa1c5e253b43..edd7d026a762 100644
--- a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_dp.c
+++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_dp.c
@@ -68,7 +68,8 @@ static void set_hpo_dp_hblank_min_symbol_width(struct pipe_ctx *pipe_ctx,
struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
struct fixed31_32 h_blank_in_ms, time_slot_in_ms, mtp_cnt_per_h_blank;
uint32_t link_bw_in_kbps =
- dc_link_bandwidth_kbps(pipe_ctx->stream->link, link_settings);
+ hpo_dp_stream_encoder->ctx->dc->link_srv->dp_link_bandwidth_kbps(
+ pipe_ctx->stream->link, link_settings);
uint16_t hblank_min_symbol_width = 0;
if (link_bw_in_kbps > 0) {
@@ -115,7 +116,8 @@ static void setup_hpo_dp_stream_attribute(struct pipe_ctx *pipe_ctx)
stream->use_vsc_sdp_for_colorimetry,
stream->timing.flags.DSC,
false);
- link_dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DP_STREAM_ATTR);
+ link->dc->link_srv->dp_trace_source_sequence(link,
+ DPCD_SOURCE_SEQ_AFTER_DP_STREAM_ATTR);
}
static void enable_hpo_dp_fpga_link_output(struct dc_link *link,
@@ -201,7 +203,7 @@ static void set_hpo_dp_link_test_pattern(struct dc_link *link,
{
link_res->hpo_dp_link_enc->funcs->set_link_test_pattern(
link_res->hpo_dp_link_enc, tp_params);
- link_dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_SET_SOURCE_PATTERN);
+ link->dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_SET_SOURCE_PATTERN);
}
static void set_hpo_dp_lane_settings(struct dc_link *link,
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_detection.c b/drivers/gpu/drm/amd/display/dc/link/link_detection.c
index f70025ef7b69..a131e30fd7d6 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_detection.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_detection.c
@@ -60,6 +60,10 @@
*/
#define LINK_TRAINING_MAX_VERIFY_RETRY 2
+static const u8 DP_SINK_BRANCH_DEV_NAME_7580[] = "7580\x80u";
+
+static const uint8_t dp_hdmi_dongle_signature_str[] = "DP-HDMI ADAPTOR";
+
static enum ddc_transaction_type get_ddc_transaction_type(enum signal_type sink_signal)
{
enum ddc_transaction_type transaction_type = DDC_TRANSACTION_TYPE_NONE;
@@ -466,7 +470,6 @@ static void link_disconnect_remap(struct dc_sink *prev_sink, struct dc_link *lin
link->local_sink = prev_sink;
}
-#if defined(CONFIG_DRM_AMD_DC_HDCP)
static void query_hdcp_capability(enum signal_type signal, struct dc_link *link)
{
struct hdcp_protection_message msg22;
@@ -495,8 +498,6 @@ static void query_hdcp_capability(enum signal_type signal, struct dc_link *link)
dc_process_hdcp_msg(signal, link, &msg22);
if (signal == SIGNAL_TYPE_DISPLAY_PORT || signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
- enum hdcp_message_status status = HDCP_MESSAGE_UNSUPPORTED;
-
msg14.data = &link->hdcp_caps.bcaps.raw;
msg14.length = sizeof(link->hdcp_caps.bcaps.raw);
msg14.msg_id = HDCP_MESSAGE_ID_READ_BCAPS;
@@ -504,11 +505,10 @@ static void query_hdcp_capability(enum signal_type signal, struct dc_link *link)
msg14.link = HDCP_LINK_PRIMARY;
msg14.max_retries = 5;
- status = dc_process_hdcp_msg(signal, link, &msg14);
+ dc_process_hdcp_msg(signal, link, &msg14);
}
}
-#endif // CONFIG_DRM_AMD_DC_HDCP
static void read_current_link_settings_on_detect(struct dc_link *link)
{
union lane_count_set lane_count_set = {0};
@@ -832,7 +832,7 @@ static void verify_link_capability(struct dc_link *link, struct dc_sink *sink,
verify_link_capability_non_destructive(link);
}
-/**
+/*
* detect_link_and_local_sink() - Detect if a sink is attached to a given link
*
* link->local_sink is created or destroyed as needed.
@@ -879,7 +879,7 @@ static bool detect_link_and_local_sink(struct dc_link *link,
return true;
}
- if (!dc_link_detect_connection_type(link, &new_connection_type)) {
+ if (!link_detect_connection_type(link, &new_connection_type)) {
BREAK_TO_DEBUGGER();
return false;
}
@@ -1087,9 +1087,7 @@ static bool detect_link_and_local_sink(struct dc_link *link,
* TODO debug why certain monitors don't like
* two link trainings
*/
-#if defined(CONFIG_DRM_AMD_DC_HDCP)
query_hdcp_capability(sink->sink_signal, link);
-#endif
} else {
// If edid is the same, then discard new sink and revert back to original sink
if (same_edid) {
@@ -1097,9 +1095,7 @@ static bool detect_link_and_local_sink(struct dc_link *link,
sink = prev_sink;
prev_sink = NULL;
}
-#if defined(CONFIG_DRM_AMD_DC_HDCP)
query_hdcp_capability(sink->sink_signal, link);
-#endif
}
/* HDMI-DVI Dongle */
@@ -1165,9 +1161,7 @@ static bool detect_link_and_local_sink(struct dc_link *link,
/* From Connected-to-Disconnected. */
link->type = dc_connection_none;
sink_caps.signal = SIGNAL_TYPE_NONE;
-#if defined(CONFIG_DRM_AMD_DC_HDCP)
memset(&link->hdcp_caps, 0, sizeof(struct hdcp_caps));
-#endif
/* When we unplug a passive DP-HDMI dongle connection, dongle_max_pix_clk
* is not cleared. If we emulate a DP signal on this connection, it thinks
* the dongle is still there and limits the number of modes we can emulate.
@@ -1191,8 +1185,8 @@ static bool detect_link_and_local_sink(struct dc_link *link,
return true;
}
-/**
- * dc_link_detect_connection_type() - Determine if there is a sink connected
+/*
+ * link_detect_connection_type() - Determine if there is a sink connected
*
* @type: Returned connection type
* Does not detect downstream devices, such as MST sinks
@@ -1216,7 +1210,7 @@ bool link_detect_connection_type(struct dc_link *link, enum dc_connection_type *
/* Link may not have physical HPD pin. */
if (link->ep_type != DISPLAY_ENDPOINT_PHY) {
- if (link->is_hpd_pending || !dc_link_dpia_query_hpd_status(link))
+ if (link->is_hpd_pending || !dpia_query_hpd_status(link))
*type = dc_connection_none;
else
*type = dc_connection_single;
@@ -1233,6 +1227,11 @@ bool link_detect_connection_type(struct dc_link *link, enum dc_connection_type *
/* TODO: need to do the actual detection */
} else {
*type = dc_connection_none;
+ if (link->connector_signal == SIGNAL_TYPE_EDP) {
+ /* eDP is not connected, power down it */
+ if (!link->dc->config.edp_no_power_sequencing)
+ link->dc->hwss.edp_power_control(link, false);
+ }
}
return true;
@@ -1274,7 +1273,6 @@ void link_clear_dprx_states(struct dc_link *link)
{
memset(&link->dprx_states, 0, sizeof(link->dprx_states));
}
-#if defined(CONFIG_DRM_AMD_DC_HDCP)
bool link_is_hdcp14(struct dc_link *link, enum signal_type signal)
{
@@ -1322,10 +1320,108 @@ bool link_is_hdcp22(struct dc_link *link, enum signal_type signal)
return ret;
}
-#endif // CONFIG_DRM_AMD_DC_HDCP
const struct dc_link_status *link_get_status(const struct dc_link *link)
{
return &link->link_status;
}
+
+static bool link_add_remote_sink_helper(struct dc_link *dc_link, struct dc_sink *sink)
+{
+ if (dc_link->sink_count >= MAX_SINKS_PER_LINK) {
+ BREAK_TO_DEBUGGER();
+ return false;
+ }
+
+ dc_sink_retain(sink);
+
+ dc_link->remote_sinks[dc_link->sink_count] = sink;
+ dc_link->sink_count++;
+
+ return true;
+}
+
+struct dc_sink *link_add_remote_sink(
+ struct dc_link *link,
+ const uint8_t *edid,
+ int len,
+ struct dc_sink_init_data *init_data)
+{
+ struct dc_sink *dc_sink;
+ enum dc_edid_status edid_status;
+
+ if (len > DC_MAX_EDID_BUFFER_SIZE) {
+ dm_error("Max EDID buffer size breached!\n");
+ return NULL;
+ }
+
+ if (!init_data) {
+ BREAK_TO_DEBUGGER();
+ return NULL;
+ }
+
+ if (!init_data->link) {
+ BREAK_TO_DEBUGGER();
+ return NULL;
+ }
+
+ dc_sink = dc_sink_create(init_data);
+
+ if (!dc_sink)
+ return NULL;
+
+ memmove(dc_sink->dc_edid.raw_edid, edid, len);
+ dc_sink->dc_edid.length = len;
+
+ if (!link_add_remote_sink_helper(
+ link,
+ dc_sink))
+ goto fail_add_sink;
+
+ edid_status = dm_helpers_parse_edid_caps(
+ link,
+ &dc_sink->dc_edid,
+ &dc_sink->edid_caps);
+
+ /*
+ * Treat device as no EDID device if EDID
+ * parsing fails
+ */
+ if (edid_status != EDID_OK && edid_status != EDID_PARTIAL_VALID) {
+ dc_sink->dc_edid.length = 0;
+ dm_error("Bad EDID, status%d!\n", edid_status);
+ }
+
+ return dc_sink;
+
+fail_add_sink:
+ dc_sink_release(dc_sink);
+ return NULL;
+}
+
+void link_remove_remote_sink(struct dc_link *link, struct dc_sink *sink)
+{
+ int i;
+
+ if (!link->sink_count) {
+ BREAK_TO_DEBUGGER();
+ return;
+ }
+
+ for (i = 0; i < link->sink_count; i++) {
+ if (link->remote_sinks[i] == sink) {
+ dc_sink_release(sink);
+ link->remote_sinks[i] = NULL;
+
+ /* shrink array to remove empty place */
+ while (i < link->sink_count - 1) {
+ link->remote_sinks[i] = link->remote_sinks[i+1];
+ i++;
+ }
+ link->remote_sinks[i] = NULL;
+ link->sink_count--;
+ return;
+ }
+ }
+}
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_detection.h b/drivers/gpu/drm/amd/display/dc/link/link_detection.h
index 1831636516fb..7da05078721e 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_detection.h
+++ b/drivers/gpu/drm/amd/display/dc/link/link_detection.h
@@ -26,5 +26,18 @@
#ifndef __DC_LINK_DETECTION_H__
#define __DC_LINK_DETECTION_H__
#include "link.h"
-
+bool link_detect(struct dc_link *link, enum dc_detect_reason reason);
+bool link_detect_connection_type(struct dc_link *link,
+ enum dc_connection_type *type);
+struct dc_sink *link_add_remote_sink(
+ struct dc_link *link,
+ const uint8_t *edid,
+ int len,
+ struct dc_sink_init_data *init_data);
+void link_remove_remote_sink(struct dc_link *link, struct dc_sink *sink);
+bool link_reset_cur_dp_mst_topology(struct dc_link *link);
+const struct dc_link_status *link_get_status(const struct dc_link *link);
+bool link_is_hdcp14(struct dc_link *link, enum signal_type signal);
+bool link_is_hdcp22(struct dc_link *link, enum signal_type signal);
+void link_clear_dprx_states(struct dc_link *link);
#endif /* __DC_LINK_DETECTION_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
index 257e1c3ba00a..027ad1f0144d 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
@@ -37,6 +37,7 @@
#include "link_dpms.h"
#include "link_hwss.h"
+#include "link_validation.h"
#include "accessories/link_fpga.h"
#include "accessories/link_dp_trace.h"
#include "protocols/link_dpcd.h"
@@ -46,6 +47,7 @@
#include "protocols/link_dp_capability.h"
#include "protocols/link_dp_training.h"
#include "protocols/link_edp_panel_control.h"
+#include "protocols/link_dp_dpia_bw.h"
#include "dm_helpers.h"
#include "link_enc_cfg.h"
@@ -136,7 +138,7 @@ void link_blank_dp_stream(struct dc_link *link, bool hw_init)
}
if ((!link->wa_flags.dp_keep_receiver_powered) || hw_init)
- dc_link_dp_receiver_power_ctrl(link, false);
+ dpcd_write_rx_power_ctrl(link, false);
}
}
@@ -646,7 +648,6 @@ static void write_i2c_redriver_setting(
if (!i2c_success)
DC_LOG_DEBUG("Set redriver failed");
}
-#if defined(CONFIG_DRM_AMD_DC_HDCP)
static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off)
{
@@ -672,7 +673,7 @@ static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off)
/* stream encoder index */
config.stream_enc_idx = pipe_ctx->stream_res.stream_enc->id - ENGINE_ID_DIGA;
- if (link_is_dp_128b_132b_signal(pipe_ctx))
+ if (dp_is_128b_132b_signal(pipe_ctx))
config.stream_enc_idx =
pipe_ctx->stream_res.hpo_dp_stream_enc->id - ENGINE_ID_HPO_DP_0;
@@ -681,7 +682,7 @@ static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off)
/* link encoder index */
config.link_enc_idx = link_enc->transmitter - TRANSMITTER_UNIPHY_A;
- if (link_is_dp_128b_132b_signal(pipe_ctx))
+ if (dp_is_128b_132b_signal(pipe_ctx))
config.link_enc_idx = pipe_ctx->link_res.hpo_dp_link_enc->inst;
/* dio output index is dpia index for DPIA endpoint & dcio index by default */
@@ -702,7 +703,7 @@ static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off)
config.assr_enabled = (panel_mode == DP_PANEL_MODE_EDP) ? 1 : 0;
config.mst_enabled = (pipe_ctx->stream->signal ==
SIGNAL_TYPE_DISPLAY_PORT_MST) ? 1 : 0;
- config.dp2_enabled = link_is_dp_128b_132b_signal(pipe_ctx) ? 1 : 0;
+ config.dp2_enabled = dp_is_128b_132b_signal(pipe_ctx) ? 1 : 0;
config.usb4_enabled = (pipe_ctx->stream->link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) ?
1 : 0;
config.dpms_off = dpms_off;
@@ -712,7 +713,6 @@ static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off)
cp_psp->funcs.update_stream_config(cp_psp->handle, &config);
}
-#endif
static void set_avmute(struct pipe_ctx *pipe_ctx, bool enable)
{
@@ -817,7 +817,7 @@ void link_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
/* Enable DSC in encoder */
if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)
- && !link_is_dp_128b_132b_signal(pipe_ctx)) {
+ && !dp_is_128b_132b_signal(pipe_ctx)) {
DC_LOG_DSC("Setting stream encoder DSC config for engine %d:", (int)pipe_ctx->stream_res.stream_enc->id);
dsc_optc_config_log(dsc, &dsc_optc_cfg);
pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(pipe_ctx->stream_res.stream_enc,
@@ -843,7 +843,7 @@ void link_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
/* disable DSC in stream encoder */
if (dc_is_dp_signal(stream->signal)) {
- if (link_is_dp_128b_132b_signal(pipe_ctx))
+ if (dp_is_128b_132b_signal(pipe_ctx))
pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet(
pipe_ctx->stream_res.hpo_dp_stream_enc,
false,
@@ -902,7 +902,7 @@ bool link_set_dsc_pps_packet(struct pipe_ctx *pipe_ctx, bool enable, bool immedi
memcpy(&stream->dsc_packed_pps[0], &dsc_packed_pps[0], sizeof(stream->dsc_packed_pps));
if (dc_is_dp_signal(stream->signal)) {
DC_LOG_DSC("Setting stream encoder DSC PPS SDP for engine %d\n", (int)pipe_ctx->stream_res.stream_enc->id);
- if (link_is_dp_128b_132b_signal(pipe_ctx))
+ if (dp_is_128b_132b_signal(pipe_ctx))
pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet(
pipe_ctx->stream_res.hpo_dp_stream_enc,
true,
@@ -919,7 +919,7 @@ bool link_set_dsc_pps_packet(struct pipe_ctx *pipe_ctx, bool enable, bool immedi
/* disable DSC PPS in stream encoder */
memset(&stream->dsc_packed_pps[0], 0, sizeof(stream->dsc_packed_pps));
if (dc_is_dp_signal(stream->signal)) {
- if (link_is_dp_128b_132b_signal(pipe_ctx))
+ if (dp_is_128b_132b_signal(pipe_ctx))
pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet(
pipe_ctx->stream_res.hpo_dp_stream_enc,
false,
@@ -1001,7 +1001,7 @@ static void enable_stream_features(struct pipe_ctx *pipe_ctx)
}
}
-static void dc_log_vcp_x_y(const struct dc_link *link, struct fixed31_32 avg_time_slots_per_mtp)
+static void log_vcp_x_y(const struct dc_link *link, struct fixed31_32 avg_time_slots_per_mtp)
{
const uint32_t VCP_Y_PRECISION = 1000;
uint64_t vcp_x, vcp_y;
@@ -1044,7 +1044,7 @@ static void dc_log_vcp_x_y(const struct dc_link *link, struct fixed31_32 avg_tim
static struct fixed31_32 get_pbn_per_slot(struct dc_stream_state *stream)
{
struct fixed31_32 mbytes_per_sec;
- uint32_t link_rate_in_mbytes_per_sec = dc_link_bandwidth_kbps(stream->link,
+ uint32_t link_rate_in_mbytes_per_sec = dp_link_bandwidth_kbps(stream->link,
&stream->link->cur_link_settings);
link_rate_in_mbytes_per_sec /= 8000; /* Kbits to MBytes */
@@ -1153,7 +1153,7 @@ static bool poll_for_allocation_change_trigger(struct dc_link *link)
break;
}
- msleep(5);
+ fsleep(5000);
}
if (result == ACT_FAILED) {
@@ -1517,7 +1517,7 @@ static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx)
pbn = get_pbn_from_timing(pipe_ctx);
avg_time_slots_per_mtp = dc_fixpt_div(pbn, pbn_per_slot);
- dc_log_vcp_x_y(link, avg_time_slots_per_mtp);
+ log_vcp_x_y(link, avg_time_slots_per_mtp);
if (link_hwss->ext.set_throttled_vcp_size)
link_hwss->ext.set_throttled_vcp_size(pipe_ctx, avg_time_slots_per_mtp);
@@ -1535,7 +1535,7 @@ struct fixed31_32 link_calculate_sst_avg_time_slots_per_mtp(
{
struct fixed31_32 link_bw_effective =
dc_fixpt_from_int(
- dc_link_bandwidth_kbps(link, &link->cur_link_settings));
+ dp_link_bandwidth_kbps(link, &link->cur_link_settings));
struct fixed31_32 timeslot_bw_effective =
dc_fixpt_div_int(link_bw_effective, MAX_MTP_SLOT_COUNT);
struct fixed31_32 timing_bw =
@@ -1640,7 +1640,7 @@ static bool write_128b_132b_sst_payload_allocation_table(
}
}
retries++;
- msleep(5);
+ fsleep(5000);
}
if (!result && retries == max_retries) {
@@ -1670,7 +1670,7 @@ static enum dc_status update_sst_payload(struct pipe_ctx *pipe_ctx,
if (!allocate) {
avg_time_slots_per_mtp = dc_fixpt_from_int(0);
- dc_log_vcp_x_y(link, avg_time_slots_per_mtp);
+ log_vcp_x_y(link, avg_time_slots_per_mtp);
if (link_hwss->ext.set_throttled_vcp_size)
link_hwss->ext.set_throttled_vcp_size(pipe_ctx,
@@ -1721,7 +1721,7 @@ static enum dc_status update_sst_payload(struct pipe_ctx *pipe_ctx,
DP_128b_132b_ENCODING) {
avg_time_slots_per_mtp = link_calculate_sst_avg_time_slots_per_mtp(stream, link);
- dc_log_vcp_x_y(link, avg_time_slots_per_mtp);
+ log_vcp_x_y(link, avg_time_slots_per_mtp);
if (link_hwss->ext.set_throttled_vcp_size)
link_hwss->ext.set_throttled_vcp_size(pipe_ctx,
@@ -2035,6 +2035,12 @@ static enum dc_status enable_link_dp(struct dc_state *state,
uint32_t post_oui_delay = 30; // 30ms
/* Reduce link bandwidth between failed link training attempts. */
bool do_fallback = false;
+ int lt_attempts = LINK_TRAINING_ATTEMPTS;
+
+ // Increase retry count if attempting DP1.x on FIXED_VS link
+ if ((link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
+ link_dp_get_encoding_format(link_settings) == DP_8b_10b_ENCODING)
+ lt_attempts = 10;
// check for seamless boot
for (i = 0; i < state->stream_count; i++) {
@@ -2044,11 +2050,17 @@ static enum dc_status enable_link_dp(struct dc_state *state,
}
}
- /* Train with fallback when enabling DPIA link. Conventional links are
+ /*
+ * If the link is DP-over-USB4 do the following:
+ * - Train with fallback when enabling DPIA link. Conventional links are
* trained with fallback during sink detection.
+ * - Allocate only what the stream needs for bw in Gbps. Inform the CM
+ * in case stream needs more or less bw from what has been allocated
+ * earlier at plug time.
*/
- if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA)
+ if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) {
do_fallback = true;
+ }
/*
* Temporary w/a to get DP2.0 link rates to work with SST.
@@ -2093,7 +2105,7 @@ static enum dc_status enable_link_dp(struct dc_state *state,
if (perform_link_training_with_retries(link_settings,
skip_video_pattern,
- LINK_TRAINING_ATTEMPTS,
+ lt_attempts,
pipe_ctx,
pipe_ctx->stream->signal,
do_fallback)) {
@@ -2117,7 +2129,7 @@ static enum dc_status enable_link_dp(struct dc_state *state,
set_default_brightness_aux(link); // TODO: use cached if known
if (link->dpcd_sink_ext_caps.bits.oled == 1)
msleep(bl_oled_enable_delay);
- link_backlight_enable_aux(link, true);
+ edp_backlight_enable_aux(link, true);
}
return status;
@@ -2154,6 +2166,7 @@ static enum dc_status enable_link_dp_mst(
struct pipe_ctx *pipe_ctx)
{
struct dc_link *link = pipe_ctx->stream->link;
+ unsigned char mstm_cntl;
/* sink signal type after MST branch is MST. Multiple MST sinks
* share one link. Link DP PHY is enable or training only once.
@@ -2162,7 +2175,9 @@ static enum dc_status enable_link_dp_mst(
return DC_OK;
/* clear payload table */
- dm_helpers_dp_mst_clear_payload_allocation_table(link->ctx, link);
+ core_link_read_dpcd(link, DP_MSTM_CTRL, &mstm_cntl, 1);
+ if (mstm_cntl & DP_MST_EN)
+ dm_helpers_dp_mst_clear_payload_allocation_table(link->ctx, link);
/* to make sure the pending down rep can be processed
* before enabling the link
@@ -2237,7 +2252,7 @@ void link_set_dpms_off(struct pipe_ctx *pipe_ctx)
ASSERT(is_master_pipe_for_link(link, pipe_ctx));
- if (link_is_dp_128b_132b_signal(pipe_ctx))
+ if (dp_is_128b_132b_signal(pipe_ctx))
vpg = pipe_ctx->stream_res.hpo_dp_stream_enc->vpg;
DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);
@@ -2262,15 +2277,13 @@ void link_set_dpms_off(struct pipe_ctx *pipe_ctx)
dc->hwss.disable_audio_stream(pipe_ctx);
-#if defined(CONFIG_DRM_AMD_DC_HDCP)
update_psp_stream_config(pipe_ctx, true);
-#endif
dc->hwss.blank_stream(pipe_ctx);
if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
deallocate_mst_payload(pipe_ctx);
else if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT &&
- link_is_dp_128b_132b_signal(pipe_ctx))
+ dp_is_128b_132b_signal(pipe_ctx))
update_sst_payload(pipe_ctx, false);
if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) {
@@ -2299,7 +2312,7 @@ void link_set_dpms_off(struct pipe_ctx *pipe_ctx)
}
if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT &&
- !link_is_dp_128b_132b_signal(pipe_ctx)) {
+ !dp_is_128b_132b_signal(pipe_ctx)) {
/* In DP1.x SST mode, our encoder will go to TPS1
* when link is on but stream is off.
@@ -2319,7 +2332,7 @@ void link_set_dpms_off(struct pipe_ctx *pipe_ctx)
if (dc_is_dp_signal(pipe_ctx->stream->signal))
link_set_dsc_enable(pipe_ctx, false);
}
- if (link_is_dp_128b_132b_signal(pipe_ctx)) {
+ if (dp_is_128b_132b_signal(pipe_ctx)) {
if (pipe_ctx->stream_res.tg->funcs->set_out_mux)
pipe_ctx->stream_res.tg->funcs->set_out_mux(pipe_ctx->stream_res.tg, OUT_MUX_DIO);
}
@@ -2343,7 +2356,7 @@ void link_set_dpms_on(
ASSERT(is_master_pipe_for_link(link, pipe_ctx));
- if (link_is_dp_128b_132b_signal(pipe_ctx))
+ if (dp_is_128b_132b_signal(pipe_ctx))
vpg = pipe_ctx->stream_res.hpo_dp_stream_enc->vpg;
DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);
@@ -2365,7 +2378,7 @@ void link_set_dpms_on(
ASSERT(link_enc);
if (!dc_is_virtual_signal(pipe_ctx->stream->signal)
- && !link_is_dp_128b_132b_signal(pipe_ctx)) {
+ && !dp_is_128b_132b_signal(pipe_ctx)) {
if (link_enc)
link_enc->funcs->setup(
link_enc,
@@ -2375,7 +2388,7 @@ void link_set_dpms_on(
pipe_ctx->stream->link->link_state_valid = true;
if (pipe_ctx->stream_res.tg->funcs->set_out_mux) {
- if (link_is_dp_128b_132b_signal(pipe_ctx))
+ if (dp_is_128b_132b_signal(pipe_ctx))
otg_out_dest = OUT_MUX_HPO_DP;
else
otg_out_dest = OUT_MUX_DIO;
@@ -2398,7 +2411,7 @@ void link_set_dpms_on(
dc->hwss.update_info_frame(pipe_ctx);
if (dc_is_dp_signal(pipe_ctx->stream->signal))
- link_dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_UPDATE_INFO_FRAME);
+ dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_UPDATE_INFO_FRAME);
/* Do not touch link on seamless boot optimization. */
if (pipe_ctx->stream->apply_seamless_boot_optimization) {
@@ -2410,9 +2423,7 @@ void link_set_dpms_on(
dc->hwss.enable_audio_stream(pipe_ctx);
}
-#if defined(CONFIG_DRM_AMD_DC_HDCP)
update_psp_stream_config(pipe_ctx, false);
-#endif
return;
}
@@ -2422,9 +2433,7 @@ void link_set_dpms_on(
!pipe_ctx->stream->timing.flags.DSC &&
!pipe_ctx->next_odm_pipe) {
pipe_ctx->stream->dpms_off = false;
-#if defined(CONFIG_DRM_AMD_DC_HDCP)
update_psp_stream_config(pipe_ctx, false);
-#endif
return;
}
@@ -2477,11 +2486,12 @@ void link_set_dpms_on(
* from transmitter control.
*/
if (!(dc_is_virtual_signal(pipe_ctx->stream->signal) ||
- link_is_dp_128b_132b_signal(pipe_ctx)))
- if (link_enc)
- link_enc->funcs->setup(
- link_enc,
- pipe_ctx->stream->signal);
+ dp_is_128b_132b_signal(pipe_ctx))) {
+ if (link_enc)
+ link_enc->funcs->setup(
+ link_enc,
+ pipe_ctx->stream->signal);
+ }
dc->hwss.enable_stream(pipe_ctx);
@@ -2497,7 +2507,7 @@ void link_set_dpms_on(
if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
allocate_mst_payload(pipe_ctx);
else if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT &&
- link_is_dp_128b_132b_signal(pipe_ctx))
+ dp_is_128b_132b_signal(pipe_ctx))
update_sst_payload(pipe_ctx, true);
dc->hwss.unblank_stream(pipe_ctx,
@@ -2508,14 +2518,12 @@ void link_set_dpms_on(
if (dc_is_dp_signal(pipe_ctx->stream->signal))
enable_stream_features(pipe_ctx);
-#if defined(CONFIG_DRM_AMD_DC_HDCP)
update_psp_stream_config(pipe_ctx, false);
-#endif
dc->hwss.enable_audio_stream(pipe_ctx);
} else { // if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
- if (link_is_dp_128b_132b_signal(pipe_ctx))
+ if (dp_is_128b_132b_signal(pipe_ctx))
dp_fpga_hpo_enable_link_and_stream(state, pipe_ctx);
if (dc_is_dp_signal(pipe_ctx->stream->signal) ||
dc_is_virtual_signal(pipe_ctx->stream->signal))
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dpms.h b/drivers/gpu/drm/amd/display/dc/link/link_dpms.h
index 33d312dabdb8..9398f9c1666a 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_dpms.h
+++ b/drivers/gpu/drm/amd/display/dc/link/link_dpms.h
@@ -27,14 +27,27 @@
#define __DC_LINK_DPMS_H__
#include "link.h"
-bool link_set_dsc_pps_packet(struct pipe_ctx *pipe_ctx,
- bool enable, bool immediate_update);
-struct fixed31_32 link_calculate_sst_avg_time_slots_per_mtp(
- const struct dc_stream_state *stream,
- const struct dc_link *link);
+void link_set_dpms_on(
+ struct dc_state *state,
+ struct pipe_ctx *pipe_ctx);
+void link_set_dpms_off(struct pipe_ctx *pipe_ctx);
+void link_resume(struct dc_link *link);
+void link_blank_all_dp_displays(struct dc *dc);
+void link_blank_all_edp_displays(struct dc *dc);
+void link_blank_dp_stream(struct dc_link *link, bool hw_init);
void link_set_all_streams_dpms_off_for_link(struct dc_link *link);
void link_get_master_pipes_with_dpms_on(const struct dc_link *link,
struct dc_state *state,
uint8_t *count,
struct pipe_ctx *pipes[MAX_PIPES]);
+enum dc_status link_increase_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t req_pbn);
+enum dc_status link_reduce_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t req_pbn);
+bool link_set_dsc_pps_packet(struct pipe_ctx *pipe_ctx,
+ bool enable, bool immediate_update);
+struct fixed31_32 link_calculate_sst_avg_time_slots_per_mtp(
+ const struct dc_stream_state *stream,
+ const struct dc_link *link);
+void link_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable);
+bool link_set_dsc_enable(struct pipe_ctx *pipe_ctx, bool enable);
+bool link_update_dsc_config(struct pipe_ctx *pipe_ctx);
#endif /* __DC_LINK_DPMS_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_factory.c b/drivers/gpu/drm/amd/display/dc/link/link_factory.c
index aeb26a4d539e..1515c817f03b 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_factory.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_factory.c
@@ -27,7 +27,20 @@
* This file owns the creation/destruction of link structure.
*/
#include "link_factory.h"
+#include "link_detection.h"
+#include "link_resource.h"
+#include "link_validation.h"
+#include "link_dpms.h"
+#include "accessories/link_dp_cts.h"
+#include "accessories/link_dp_trace.h"
+#include "accessories/link_fpga.h"
#include "protocols/link_ddc.h"
+#include "protocols/link_dp_capability.h"
+#include "protocols/link_dp_dpia_bw.h"
+#include "protocols/link_dp_dpia.h"
+#include "protocols/link_dp_irq_handler.h"
+#include "protocols/link_dp_phy.h"
+#include "protocols/link_dp_training.h"
#include "protocols/link_edp_panel_control.h"
#include "protocols/link_hpd.h"
#include "gpio_service_interface.h"
@@ -39,7 +52,249 @@
DC_LOG_HW_HOTPLUG( \
__VA_ARGS__)
-static enum transmitter translate_encoder_to_transmitter(struct graphics_object_id encoder)
+/* link factory owns the creation/destruction of link structures. */
+static void construct_link_service_factory(struct link_service *link_srv)
+{
+
+ link_srv->create_link = link_create;
+ link_srv->destroy_link = link_destroy;
+}
+
+/* link_detection manages link detection states and receiver states by using
+ * various link protocols. It also provides helper functions to interpret
+ * certain capabilities or status based on the states it manages or retrieve
+ * them directly from connected receivers.
+ */
+static void construct_link_service_detection(struct link_service *link_srv)
+{
+ link_srv->detect_link = link_detect;
+ link_srv->detect_connection_type = link_detect_connection_type;
+ link_srv->add_remote_sink = link_add_remote_sink;
+ link_srv->remove_remote_sink = link_remove_remote_sink;
+ link_srv->get_hpd_state = link_get_hpd_state;
+ link_srv->get_hpd_gpio = link_get_hpd_gpio;
+ link_srv->enable_hpd = link_enable_hpd;
+ link_srv->disable_hpd = link_disable_hpd;
+ link_srv->enable_hpd_filter = link_enable_hpd_filter;
+ link_srv->reset_cur_dp_mst_topology = link_reset_cur_dp_mst_topology;
+ link_srv->get_status = link_get_status;
+ link_srv->is_hdcp1x_supported = link_is_hdcp14;
+ link_srv->is_hdcp2x_supported = link_is_hdcp22;
+ link_srv->clear_dprx_states = link_clear_dprx_states;
+}
+
+/* link resource implements accessors to link resource. */
+static void construct_link_service_resource(struct link_service *link_srv)
+{
+ link_srv->get_cur_res_map = link_get_cur_res_map;
+ link_srv->restore_res_map = link_restore_res_map;
+ link_srv->get_cur_link_res = link_get_cur_link_res;
+}
+
+/* link validation owns timing validation against various link limitations. (ex.
+ * link bandwidth, receiver capability or our hardware capability) It also
+ * provides helper functions exposing bandwidth formulas used in validation.
+ */
+static void construct_link_service_validation(struct link_service *link_srv)
+{
+ link_srv->validate_mode_timing = link_validate_mode_timing;
+ link_srv->dp_link_bandwidth_kbps = dp_link_bandwidth_kbps;
+ link_srv->validate_dpia_bandwidth = link_validate_dpia_bandwidth;
+}
+
+/* link dpms owns the programming sequence of stream's dpms state associated
+ * with the link and link's enable/disable sequences as result of the stream's
+ * dpms state change.
+ */
+static void construct_link_service_dpms(struct link_service *link_srv)
+{
+ link_srv->set_dpms_on = link_set_dpms_on;
+ link_srv->set_dpms_off = link_set_dpms_off;
+ link_srv->resume = link_resume;
+ link_srv->blank_all_dp_displays = link_blank_all_dp_displays;
+ link_srv->blank_all_edp_displays = link_blank_all_edp_displays;
+ link_srv->blank_dp_stream = link_blank_dp_stream;
+ link_srv->increase_mst_payload = link_increase_mst_payload;
+ link_srv->reduce_mst_payload = link_reduce_mst_payload;
+ link_srv->set_dsc_on_stream = link_set_dsc_on_stream;
+ link_srv->set_dsc_enable = link_set_dsc_enable;
+ link_srv->update_dsc_config = link_update_dsc_config;
+}
+
+/* link ddc implements generic display communication protocols such as i2c, aux
+ * and scdc. It should not contain any specific applications of these
+ * protocols such as display capability query, detection, or handshaking such as
+ * link training.
+ */
+static void construct_link_service_ddc(struct link_service *link_srv)
+{
+ link_srv->create_ddc_service = link_create_ddc_service;
+ link_srv->destroy_ddc_service = link_destroy_ddc_service;
+ link_srv->query_ddc_data = link_query_ddc_data;
+ link_srv->aux_transfer_raw = link_aux_transfer_raw;
+ link_srv->aux_transfer_with_retries_no_mutex =
+ link_aux_transfer_with_retries_no_mutex;
+ link_srv->is_in_aux_transaction_mode = link_is_in_aux_transaction_mode;
+ link_srv->get_aux_defer_delay = link_get_aux_defer_delay;
+}
+
+/* link dp capability implements dp specific link capability retrieval sequence.
+ * It is responsible for retrieving, parsing, overriding, deciding capability
+ * obtained from dp link. Link capability consists of encoders, DPRXs, cables,
+ * retimers, usb and all other possible backend capabilities.
+ */
+static void construct_link_service_dp_capability(struct link_service *link_srv)
+{
+ link_srv->dp_is_sink_present = dp_is_sink_present;
+ link_srv->dp_is_fec_supported = dp_is_fec_supported;
+ link_srv->dp_is_128b_132b_signal = dp_is_128b_132b_signal;
+ link_srv->dp_get_max_link_enc_cap = dp_get_max_link_enc_cap;
+ link_srv->dp_get_verified_link_cap = dp_get_verified_link_cap;
+ link_srv->dp_get_encoding_format = link_dp_get_encoding_format;
+ link_srv->dp_should_enable_fec = dp_should_enable_fec;
+ link_srv->dp_decide_link_settings = link_decide_link_settings;
+ link_srv->mst_decide_link_encoding_format =
+ mst_decide_link_encoding_format;
+ link_srv->edp_decide_link_settings = edp_decide_link_settings;
+ link_srv->bw_kbps_from_raw_frl_link_rate_data =
+ link_bw_kbps_from_raw_frl_link_rate_data;
+ link_srv->dp_overwrite_extended_receiver_cap =
+ dp_overwrite_extended_receiver_cap;
+ link_srv->dp_decide_lttpr_mode = dp_decide_lttpr_mode;
+}
+
+/* link dp phy/dpia implements basic dp phy/dpia functionality such as
+ * enable/disable output and set lane/drive settings. It is responsible for
+ * maintaining and update software state representing current phy/dpia status
+ * such as current link settings.
+ */
+static void construct_link_service_dp_phy_or_dpia(struct link_service *link_srv)
+{
+ link_srv->dpia_handle_usb4_bandwidth_allocation_for_link =
+ dpia_handle_usb4_bandwidth_allocation_for_link;
+ link_srv->dpia_handle_bw_alloc_response = dpia_handle_bw_alloc_response;
+ link_srv->dp_set_drive_settings = dp_set_drive_settings;
+ link_srv->dpcd_write_rx_power_ctrl = dpcd_write_rx_power_ctrl;
+}
+
+/* link dp irq handler implements DP HPD short pulse handling sequence according
+ * to DP specifications
+ */
+static void construct_link_service_dp_irq_handler(struct link_service *link_srv)
+{
+ link_srv->dp_parse_link_loss_status = dp_parse_link_loss_status;
+ link_srv->dp_should_allow_hpd_rx_irq = dp_should_allow_hpd_rx_irq;
+ link_srv->dp_handle_link_loss = dp_handle_link_loss;
+ link_srv->dp_read_hpd_rx_irq_data = dp_read_hpd_rx_irq_data;
+ link_srv->dp_handle_hpd_rx_irq = dp_handle_hpd_rx_irq;
+}
+
+/* link edp panel control implements retrieval and configuration of eDP panel
+ * features such as PSR and ABM and it also manages specs defined eDP panel
+ * power sequences.
+ */
+static void construct_link_service_edp_panel_control(struct link_service *link_srv)
+{
+ link_srv->edp_panel_backlight_power_on = edp_panel_backlight_power_on;
+ link_srv->edp_get_backlight_level = edp_get_backlight_level;
+ link_srv->edp_get_backlight_level_nits = edp_get_backlight_level_nits;
+ link_srv->edp_set_backlight_level = edp_set_backlight_level;
+ link_srv->edp_set_backlight_level_nits = edp_set_backlight_level_nits;
+ link_srv->edp_get_target_backlight_pwm = edp_get_target_backlight_pwm;
+ link_srv->edp_get_psr_state = edp_get_psr_state;
+ link_srv->edp_set_psr_allow_active = edp_set_psr_allow_active;
+ link_srv->edp_setup_psr = edp_setup_psr;
+ link_srv->edp_set_sink_vtotal_in_psr_active =
+ edp_set_sink_vtotal_in_psr_active;
+ link_srv->edp_get_psr_residency = edp_get_psr_residency;
+ link_srv->edp_wait_for_t12 = edp_wait_for_t12;
+ link_srv->edp_is_ilr_optimization_required =
+ edp_is_ilr_optimization_required;
+ link_srv->edp_backlight_enable_aux = edp_backlight_enable_aux;
+ link_srv->edp_add_delay_for_T9 = edp_add_delay_for_T9;
+ link_srv->edp_receiver_ready_T9 = edp_receiver_ready_T9;
+ link_srv->edp_receiver_ready_T7 = edp_receiver_ready_T7;
+ link_srv->edp_power_alpm_dpcd_enable = edp_power_alpm_dpcd_enable;
+}
+
+/* link dp cts implements dp compliance test automation protocols and manual
+ * testing interfaces for debugging and certification purpose.
+ */
+static void construct_link_service_dp_cts(struct link_service *link_srv)
+{
+ link_srv->dp_handle_automated_test = dp_handle_automated_test;
+ link_srv->dp_set_test_pattern = dp_set_test_pattern;
+ link_srv->dp_set_preferred_link_settings =
+ dp_set_preferred_link_settings;
+ link_srv->dp_set_preferred_training_settings =
+ dp_set_preferred_training_settings;
+}
+
+/* link dp trace implements tracing interfaces for tracking major dp sequences
+ * including execution status and timestamps
+ */
+static void construct_link_service_dp_trace(struct link_service *link_srv)
+{
+ link_srv->dp_trace_is_initialized = dp_trace_is_initialized;
+ link_srv->dp_trace_set_is_logged_flag = dp_trace_set_is_logged_flag;
+ link_srv->dp_trace_is_logged = dp_trace_is_logged;
+ link_srv->dp_trace_get_lt_end_timestamp = dp_trace_get_lt_end_timestamp;
+ link_srv->dp_trace_get_lt_counts = dp_trace_get_lt_counts;
+ link_srv->dp_trace_get_link_loss_count = dp_trace_get_link_loss_count;
+ link_srv->dp_trace_set_edp_power_timestamp =
+ dp_trace_set_edp_power_timestamp;
+ link_srv->dp_trace_get_edp_poweron_timestamp =
+ dp_trace_get_edp_poweron_timestamp;
+ link_srv->dp_trace_get_edp_poweroff_timestamp =
+ dp_trace_get_edp_poweroff_timestamp;
+ link_srv->dp_trace_source_sequence = dp_trace_source_sequence;
+}
+
+static void construct_link_service(struct link_service *link_srv)
+{
+ /* All link service functions should fall under some sub categories.
+ * If a new function doesn't perfectly fall under an existing sub
+ * category, it must be that you are either adding a whole new aspect of
+ * responsibility to link service or something doesn't belong to link
+ * service. In that case please contact the arch owner to arrange a
+ * design review meeting.
+ */
+ construct_link_service_factory(link_srv);
+ construct_link_service_detection(link_srv);
+ construct_link_service_resource(link_srv);
+ construct_link_service_validation(link_srv);
+ construct_link_service_dpms(link_srv);
+ construct_link_service_ddc(link_srv);
+ construct_link_service_dp_capability(link_srv);
+ construct_link_service_dp_phy_or_dpia(link_srv);
+ construct_link_service_dp_irq_handler(link_srv);
+ construct_link_service_edp_panel_control(link_srv);
+ construct_link_service_dp_cts(link_srv);
+ construct_link_service_dp_trace(link_srv);
+}
+
+struct link_service *link_create_link_service(void)
+{
+ struct link_service *link_srv = kzalloc(sizeof(*link_srv), GFP_KERNEL);
+
+ if (link_srv == NULL)
+ goto fail;
+
+ construct_link_service(link_srv);
+
+ return link_srv;
+fail:
+ return NULL;
+}
+
+void link_destroy_link_service(struct link_service **link_srv)
+{
+ kfree(*link_srv);
+ *link_srv = NULL;
+}
+
+static enum transmitter translate_encoder_to_transmitter(
+ struct graphics_object_id encoder)
{
switch (encoder.id) {
case ENCODER_ID_INTERNAL_UNIPHY:
@@ -181,7 +436,7 @@ static enum channel_id get_ddc_line(struct dc_link *link)
return channel;
}
-static bool dc_link_construct_phy(struct dc_link *link,
+static bool construct_phy(struct dc_link *link,
const struct link_init_data *init_params)
{
uint8_t i;
@@ -274,14 +529,18 @@ static bool dc_link_construct_phy(struct dc_link *link,
link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
switch (link->dc->config.allow_edp_hotplug_detection) {
- case 1: // only the 1st eDP handles hotplug
+ case HPD_EN_FOR_ALL_EDP:
+ link->irq_source_hpd_rx =
+ dal_irq_get_rx_source(link->hpd_gpio);
+ break;
+ case HPD_EN_FOR_PRIMARY_EDP_ONLY:
if (link->link_index == 0)
link->irq_source_hpd_rx =
dal_irq_get_rx_source(link->hpd_gpio);
else
link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
break;
- case 2: // only the 2nd eDP handles hotplug
+ case HPD_EN_FOR_SECONDARY_EDP_ONLY:
if (link->link_index == 1)
link->irq_source_hpd_rx =
dal_irq_get_rx_source(link->hpd_gpio);
@@ -289,6 +548,7 @@ static bool dc_link_construct_phy(struct dc_link *link,
link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
break;
default:
+ link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
break;
}
}
@@ -473,7 +733,7 @@ create_fail:
return false;
}
-static bool dc_link_construct_dpia(struct dc_link *link,
+static bool construct_dpia(struct dc_link *link,
const struct link_init_data *init_params)
{
struct ddc_service_init_data ddc_service_init_data = { 0 };
@@ -543,9 +803,9 @@ static bool link_construct(struct dc_link *link,
{
/* Handle dpia case */
if (init_params->is_dpia_link == true)
- return dc_link_construct_dpia(link, init_params);
+ return construct_dpia(link, init_params);
else
- return dc_link_construct_phy(link, init_params);
+ return construct_phy(link, init_params);
}
struct dc_link *link_create(const struct link_init_data *init_params)
@@ -574,4 +834,3 @@ void link_destroy(struct dc_link **link)
kfree(*link);
*link = NULL;
}
-
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_factory.h b/drivers/gpu/drm/amd/display/dc/link/link_factory.h
index 5b846147c4a6..e96220d48d03 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_factory.h
+++ b/drivers/gpu/drm/amd/display/dc/link/link_factory.h
@@ -25,5 +25,7 @@
#ifndef __LINK_FACTORY_H__
#define __LINK_FACTORY_H__
#include "link.h"
+struct dc_link *link_create(const struct link_init_data *init_params);
+void link_destroy(struct dc_link **link);
#endif /* __LINK_FACTORY_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_resource.h b/drivers/gpu/drm/amd/display/dc/link/link_resource.h
index 45554d30adf0..1907bda3cb6e 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_resource.h
+++ b/drivers/gpu/drm/amd/display/dc/link/link_resource.h
@@ -25,7 +25,8 @@
#ifndef __LINK_RESOURCE_H__
#define __LINK_RESOURCE_H__
#include "link.h"
+void link_get_cur_res_map(const struct dc *dc, uint32_t *map);
+void link_restore_res_map(const struct dc *dc, uint32_t *map);
void link_get_cur_link_res(const struct dc_link *link,
struct link_resource *link_res);
-
#endif /* __LINK_RESOURCE_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_validation.c b/drivers/gpu/drm/amd/display/dc/link/link_validation.c
index d4f6ee6ca948..d4b7da526f0a 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_validation.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_validation.c
@@ -29,6 +29,8 @@
* provides helper functions exposing bandwidth formulas used in validation.
*/
#include "link_validation.h"
+#include "protocols/link_dp_capability.h"
+#include "protocols/link_dp_dpia_bw.h"
#include "resource.h"
#define DC_LOGGER_INIT(logger)
@@ -123,7 +125,7 @@ static bool dp_active_dongle_validate_timing(
if (dongle_caps->dp_hdmi_frl_max_link_bw_in_kbps > 0) { // DP to HDMI FRL converter
struct dc_crtc_timing outputTiming = *timing;
-#if defined(CONFIG_DRM_AMD_DC_DCN)
+#if defined(CONFIG_DRM_AMD_DC_FP)
if (timing->flags.DSC && !timing->dsc_cfg.is_frl)
/* DP input has DSC, HDMI FRL output doesn't have DSC, remove DSC from output timing */
outputTiming.flags.DSC = 0;
@@ -233,7 +235,7 @@ uint32_t dp_link_bandwidth_kbps(
*/
link_rate_per_lane_kbps = link_settings->link_rate * LINK_RATE_REF_FREQ_IN_KHZ * BITS_PER_DP_BYTE;
total_data_bw_efficiency_x10000 = DATA_EFFICIENCY_8b_10b_x10000;
- if (dc_link_should_enable_fec(link)) {
+ if (dp_should_enable_fec(link)) {
total_data_bw_efficiency_x10000 /= 100;
total_data_bw_efficiency_x10000 *= DATA_EFFICIENCY_8b_10b_FEC_EFFICIENCY_x100;
}
@@ -254,60 +256,6 @@ uint32_t dp_link_bandwidth_kbps(
return link_rate_per_lane_kbps * link_settings->lane_count / 10000 * total_data_bw_efficiency_x10000;
}
-uint32_t link_timing_bandwidth_kbps(
- const struct dc_crtc_timing *timing)
-{
- uint32_t bits_per_channel = 0;
- uint32_t kbps;
-
-#if defined(CONFIG_DRM_AMD_DC_DCN)
- if (timing->flags.DSC)
- return dc_dsc_stream_bandwidth_in_kbps(timing,
- timing->dsc_cfg.bits_per_pixel,
- timing->dsc_cfg.num_slices_h,
- timing->dsc_cfg.is_dp);
-#endif /* CONFIG_DRM_AMD_DC_DCN */
-
- switch (timing->display_color_depth) {
- case COLOR_DEPTH_666:
- bits_per_channel = 6;
- break;
- case COLOR_DEPTH_888:
- bits_per_channel = 8;
- break;
- case COLOR_DEPTH_101010:
- bits_per_channel = 10;
- break;
- case COLOR_DEPTH_121212:
- bits_per_channel = 12;
- break;
- case COLOR_DEPTH_141414:
- bits_per_channel = 14;
- break;
- case COLOR_DEPTH_161616:
- bits_per_channel = 16;
- break;
- default:
- ASSERT(bits_per_channel != 0);
- bits_per_channel = 8;
- break;
- }
-
- kbps = timing->pix_clk_100hz / 10;
- kbps *= bits_per_channel;
-
- if (timing->flags.Y_ONLY != 1) {
- /*Only YOnly make reduce bandwidth by 1/3 compares to RGB*/
- kbps *= 3;
- if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
- kbps /= 2;
- else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422)
- kbps = kbps * 2 / 3;
- }
-
- return kbps;
-}
-
static bool dp_validate_mode_timing(
struct dc_link *link,
const struct dc_crtc_timing *timing)
@@ -329,7 +277,7 @@ static bool dp_validate_mode_timing(
timing->v_addressable == (uint32_t) 480)
return true;
- link_setting = dc_link_get_link_cap(link);
+ link_setting = dp_get_verified_link_cap(link);
/* TODO: DYNAMIC_VALIDATION needs to be implemented */
/*if (flags.DYNAMIC_VALIDATION == 1 &&
@@ -338,7 +286,7 @@ static bool dp_validate_mode_timing(
*/
req_bw = dc_bandwidth_in_kbps_from_timing(timing);
- max_bw = dc_link_bandwidth_kbps(link, link_setting);
+ max_bw = dp_link_bandwidth_kbps(link, link_setting);
if (req_bw <= max_bw) {
/* remember the biggest mode here, during
@@ -396,3 +344,20 @@ enum dc_status link_validate_mode_timing(
return DC_OK;
}
+
+bool link_validate_dpia_bandwidth(const struct dc_stream_state *stream, const unsigned int num_streams)
+{
+ bool ret = true;
+ int bw_needed[MAX_DPIA_NUM];
+ struct dc_link *link[MAX_DPIA_NUM];
+
+ if (!num_streams || num_streams > MAX_DPIA_NUM)
+ return ret;
+
+ for (uint8_t i = 0; i < num_streams; ++i) {
+
+ link[i] = stream[i].link;
+ bw_needed[i] = dc_bandwidth_in_kbps_from_timing(&stream[i].timing);
+ }
+ return ret;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_validation.h b/drivers/gpu/drm/amd/display/dc/link/link_validation.h
index ab6a44f50032..4a954317d0da 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_validation.h
+++ b/drivers/gpu/drm/amd/display/dc/link/link_validation.h
@@ -25,4 +25,15 @@
#ifndef __LINK_VALIDATION_H__
#define __LINK_VALIDATION_H__
#include "link.h"
+enum dc_status link_validate_mode_timing(
+ const struct dc_stream_state *stream,
+ struct dc_link *link,
+ const struct dc_crtc_timing *timing);
+bool link_validate_dpia_bandwidth(
+ const struct dc_stream_state *stream,
+ const unsigned int num_streams);
+uint32_t dp_link_bandwidth_kbps(
+ const struct dc_link *link,
+ const struct dc_link_settings *link_settings);
+
#endif /* __LINK_VALIDATION_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c
index 5269125bc2a4..0fa1228bc178 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c
@@ -53,7 +53,7 @@ struct aux_payloads {
struct vector payloads;
};
-static bool dal_ddc_i2c_payloads_create(
+static bool i2c_payloads_create(
struct dc_context *ctx,
struct i2c_payloads *payloads,
uint32_t count)
@@ -65,16 +65,24 @@ static bool dal_ddc_i2c_payloads_create(
return false;
}
-static struct i2c_payload *dal_ddc_i2c_payloads_get(struct i2c_payloads *p)
+static struct i2c_payload *i2c_payloads_get(struct i2c_payloads *p)
{
return (struct i2c_payload *)p->payloads.container;
}
-static uint32_t dal_ddc_i2c_payloads_get_count(struct i2c_payloads *p)
+static uint32_t i2c_payloads_get_count(struct i2c_payloads *p)
{
return p->payloads.count;
}
+static void i2c_payloads_destroy(struct i2c_payloads *p)
+{
+ if (!p)
+ return;
+
+ dal_vector_destruct(&p->payloads);
+}
+
#define DDC_MIN(a, b) (((a) < (b)) ? (a) : (b))
static void i2c_payloads_add(
@@ -364,10 +372,10 @@ bool link_query_ddc_data(
struct i2c_command command = {0};
struct i2c_payloads payloads;
- if (!dal_ddc_i2c_payloads_create(ddc->ctx, &payloads, payloads_num))
+ if (!i2c_payloads_create(ddc->ctx, &payloads, payloads_num))
return false;
- command.payloads = dal_ddc_i2c_payloads_get(&payloads);
+ command.payloads = i2c_payloads_get(&payloads);
command.number_of_payloads = 0;
command.engine = DDC_I2C_COMMAND_ENGINE;
command.speed = ddc->ctx->dc->caps.i2c_speed_in_khz;
@@ -379,20 +387,20 @@ bool link_query_ddc_data(
&payloads, address, read_size, read_buf, false);
command.number_of_payloads =
- dal_ddc_i2c_payloads_get_count(&payloads);
+ i2c_payloads_get_count(&payloads);
success = dm_helpers_submit_i2c(
ddc->ctx,
ddc->link,
&command);
- dal_vector_destruct(&payloads.payloads);
+ i2c_payloads_destroy(&payloads);
}
return success;
}
-int dc_link_aux_transfer_raw(struct ddc_service *ddc,
+int link_aux_transfer_raw(struct ddc_service *ddc,
struct aux_payload *payload,
enum aux_return_code_type *operation_result)
{
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.h
index aaa5064408ba..860ef15d7f1b 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.h
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.h
@@ -37,13 +37,41 @@
#define EDID_SEGMENT_SIZE 256
+struct ddc_service *link_create_ddc_service(
+ struct ddc_service_init_data *ddc_init_data);
+
+void link_destroy_ddc_service(struct ddc_service **ddc);
+
void set_ddc_transaction_type(
struct ddc_service *ddc,
enum ddc_transaction_type type);
+uint32_t link_get_aux_defer_delay(struct ddc_service *ddc);
+
+bool link_is_in_aux_transaction_mode(struct ddc_service *ddc);
+
bool try_to_configure_aux_timeout(struct ddc_service *ddc,
uint32_t timeout);
+bool link_query_ddc_data(
+ struct ddc_service *ddc,
+ uint32_t address,
+ uint8_t *write_buf,
+ uint32_t write_size,
+ uint8_t *read_buf,
+ uint32_t read_size);
+
+/* Attempt to submit an aux payload, retrying on timeouts, defers, and busy
+ * states as outlined in the DP spec. Returns true if the request was
+ * successful.
+ *
+ * NOTE: The function requires explicit mutex on DM side in order to prevent
+ * potential race condition. DC components should call the dpcd read/write
+ * function in dm_helpers in order to access dpcd safely
+ */
+bool link_aux_transfer_with_retries_no_mutex(struct ddc_service *ddc,
+ struct aux_payload *payload);
+
void write_scdc_data(
struct ddc_service *ddc_service,
uint32_t pix_clk,
@@ -57,5 +85,8 @@ void set_dongle_type(struct ddc_service *ddc,
struct ddc *get_ddc_pin(struct ddc_service *ddc_service);
+int link_aux_transfer_raw(struct ddc_service *ddc,
+ struct aux_payload *payload,
+ enum aux_return_code_type *operation_result);
#endif /* __DAL_DDC_SERVICE_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
index d4370856f164..ba98013fecd0 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
@@ -42,6 +42,8 @@
#include "link_edp_panel_control.h"
#include "link_dp_irq_handler.h"
#include "link/accessories/link_dp_trace.h"
+#include "link/link_detection.h"
+#include "link/link_validation.h"
#include "link_dp_training.h"
#include "atomfirmware.h"
#include "resource.h"
@@ -155,7 +157,7 @@ uint8_t dp_parse_lttpr_repeater_count(uint8_t lttpr_repeater_count)
return 0; // invalid value
}
-uint32_t dc_link_bw_kbps_from_raw_frl_link_rate_data(uint8_t bw)
+uint32_t link_bw_kbps_from_raw_frl_link_rate_data(uint8_t bw)
{
switch (bw) {
case 0b001:
@@ -201,8 +203,11 @@ static enum dc_link_rate linkRateInKHzToLinkRateMultiplier(uint32_t link_rate_in
case 5400000:
link_rate = LINK_RATE_HIGH2; // Rate_7 (HBR2)- 5.40 Gbps/Lane
break;
+ case 6750000:
+ link_rate = LINK_RATE_RATE_8; // Rate_8 - 6.75 Gbps/Lane
+ break;
case 8100000:
- link_rate = LINK_RATE_HIGH3; // Rate_8 (HBR3)- 8.10 Gbps/Lane
+ link_rate = LINK_RATE_HIGH3; // Rate_9 (HBR3)- 8.10 Gbps/Lane
break;
default:
link_rate = LINK_RATE_UNKNOWN;
@@ -278,7 +283,7 @@ static void dp_wa_power_up_0010FA(struct dc_link *link, uint8_t *dpcd_data,
if (!link->dpcd_caps.dpcd_rev.raw) {
do {
- dc_link_dp_receiver_power_ctrl(link, true);
+ dpcd_write_rx_power_ctrl(link, true);
core_link_read_dpcd(link, DP_DPCD_REV,
dpcd_data, length);
link->dpcd_caps.dpcd_rev.raw = dpcd_data[
@@ -309,7 +314,7 @@ static void dp_wa_power_up_0010FA(struct dc_link *link, uint8_t *dpcd_data,
link->wa_flags.dp_keep_receiver_powered = false;
}
-bool dc_link_is_fec_supported(const struct dc_link *link)
+bool dp_is_fec_supported(const struct dc_link *link)
{
/* TODO - use asic cap instead of link_enc->features
* we no longer know which link enc to use for this link before commit
@@ -325,7 +330,7 @@ bool dc_link_is_fec_supported(const struct dc_link *link)
!IS_FPGA_MAXIMUS_DC(link->ctx->dce_environment));
}
-bool dc_link_should_enable_fec(const struct dc_link *link)
+bool dp_should_enable_fec(const struct dc_link *link)
{
bool force_disable = false;
@@ -342,10 +347,10 @@ bool dc_link_should_enable_fec(const struct dc_link *link)
|| !link->dc->caps.edp_dsc_support))
force_disable = true;
- return !force_disable && dc_link_is_fec_supported(link);
+ return !force_disable && dp_is_fec_supported(link);
}
-bool link_is_dp_128b_132b_signal(struct pipe_ctx *pipe_ctx)
+bool dp_is_128b_132b_signal(struct pipe_ctx *pipe_ctx)
{
/* If this assert is hit then we have a link encoder dynamic management issue */
ASSERT(pipe_ctx->stream_res.hpo_dp_stream_enc ? pipe_ctx->link_res.hpo_dp_link_enc != NULL : true);
@@ -442,8 +447,12 @@ static enum dc_lane_count reduce_lane_count(enum dc_lane_count lane_count)
}
}
-static enum dc_link_rate reduce_link_rate(enum dc_link_rate link_rate)
+static enum dc_link_rate reduce_link_rate(const struct dc_link *link, enum dc_link_rate link_rate)
{
+ // NEEDSWORK: provide some details about why this function never returns some of the
+ // obscure link rates such as 4.32 Gbps or 3.24 Gbps and if such behavior is intended.
+ //
+
switch (link_rate) {
case LINK_RATE_UHBR20:
return LINK_RATE_UHBR13_5;
@@ -452,13 +461,22 @@ static enum dc_link_rate reduce_link_rate(enum dc_link_rate link_rate)
case LINK_RATE_UHBR10:
return LINK_RATE_HIGH3;
case LINK_RATE_HIGH3:
+ if (link->connector_signal == SIGNAL_TYPE_EDP && link->dc->debug.support_eDP1_5)
+ return LINK_RATE_RATE_8;
+ return LINK_RATE_HIGH2;
+ case LINK_RATE_RATE_8:
return LINK_RATE_HIGH2;
case LINK_RATE_HIGH2:
return LINK_RATE_HIGH;
+ case LINK_RATE_RATE_6:
+ case LINK_RATE_RBR2:
+ return LINK_RATE_HIGH;
case LINK_RATE_HIGH:
return LINK_RATE_LOW;
+ case LINK_RATE_RATE_3:
+ case LINK_RATE_RATE_2:
+ return LINK_RATE_LOW;
case LINK_RATE_LOW:
- return LINK_RATE_UNKNOWN;
default:
return LINK_RATE_UNKNOWN;
}
@@ -581,7 +599,7 @@ bool decide_fallback_link_setting(
case LINK_TRAINING_LQA_FAIL:
{
if (!reached_minimum_link_rate(cur->link_rate)) {
- cur->link_rate = reduce_link_rate(cur->link_rate);
+ cur->link_rate = reduce_link_rate(link, cur->link_rate);
} else if (!reached_minimum_lane_count(cur->lane_count)) {
cur->link_rate = max->link_rate;
if (training_result == LINK_TRAINING_CR_FAIL_LANE0)
@@ -603,7 +621,7 @@ bool decide_fallback_link_setting(
if (!reached_minimum_lane_count(cur->lane_count)) {
cur->lane_count = reduce_lane_count(cur->lane_count);
} else if (!reached_minimum_link_rate(cur->link_rate)) {
- cur->link_rate = reduce_link_rate(cur->link_rate);
+ cur->link_rate = reduce_link_rate(link, cur->link_rate);
/* Reduce max link rate to avoid potential infinite loop.
* Needed so that any subsequent CR_FAIL fallback can't
* re-set the link rate higher than the link rate from
@@ -619,7 +637,7 @@ bool decide_fallback_link_setting(
case LINK_TRAINING_EQ_FAIL_CR:
{
if (!reached_minimum_link_rate(cur->link_rate)) {
- cur->link_rate = reduce_link_rate(cur->link_rate);
+ cur->link_rate = reduce_link_rate(link, cur->link_rate);
/* Reduce max link rate to avoid potential infinite loop.
* Needed so that any subsequent CR_FAIL fallback can't
* re-set the link rate higher than the link rate from
@@ -645,7 +663,7 @@ static bool decide_dp_link_settings(struct dc_link *link, struct dc_link_setting
initial_link_setting;
uint32_t link_bw;
- if (req_bw > dc_link_bandwidth_kbps(link, &link->verified_link_cap))
+ if (req_bw > dp_link_bandwidth_kbps(link, &link->verified_link_cap))
return false;
/* search for the minimum link setting that:
@@ -654,7 +672,7 @@ static bool decide_dp_link_settings(struct dc_link *link, struct dc_link_setting
*/
while (current_link_setting.link_rate <=
link->verified_link_cap.link_rate) {
- link_bw = dc_link_bandwidth_kbps(
+ link_bw = dp_link_bandwidth_kbps(
link,
&current_link_setting);
if (req_bw <= link_bw) {
@@ -679,7 +697,8 @@ static bool decide_dp_link_settings(struct dc_link *link, struct dc_link_setting
return false;
}
-bool dc_link_decide_edp_link_settings(struct dc_link *link, struct dc_link_settings *link_setting, uint32_t req_bw)
+bool edp_decide_link_settings(struct dc_link *link,
+ struct dc_link_settings *link_setting, uint32_t req_bw)
{
struct dc_link_settings initial_link_setting;
struct dc_link_settings current_link_setting;
@@ -709,7 +728,7 @@ bool dc_link_decide_edp_link_settings(struct dc_link *link, struct dc_link_setti
*/
while (current_link_setting.link_rate <=
link->verified_link_cap.link_rate) {
- link_bw = dc_link_bandwidth_kbps(
+ link_bw = dp_link_bandwidth_kbps(
link,
&current_link_setting);
if (req_bw <= link_bw) {
@@ -764,7 +783,7 @@ bool decide_edp_link_settings_with_dsc(struct dc_link *link,
initial_link_setting.use_link_rate_set = false;
initial_link_setting.link_rate_set = 0;
current_link_setting = initial_link_setting;
- if (req_bw > dc_link_bandwidth_kbps(link, &link->verified_link_cap))
+ if (req_bw > dp_link_bandwidth_kbps(link, &link->verified_link_cap))
return false;
/* search for the minimum link setting that:
@@ -773,7 +792,7 @@ bool decide_edp_link_settings_with_dsc(struct dc_link *link,
*/
while (current_link_setting.link_rate <=
max_link_rate) {
- link_bw = dc_link_bandwidth_kbps(
+ link_bw = dp_link_bandwidth_kbps(
link,
&current_link_setting);
if (req_bw <= link_bw) {
@@ -830,7 +849,7 @@ bool decide_edp_link_settings_with_dsc(struct dc_link *link,
*/
while (current_link_setting.link_rate <=
max_link_rate) {
- link_bw = dc_link_bandwidth_kbps(
+ link_bw = dp_link_bandwidth_kbps(
link,
&current_link_setting);
if (req_bw <= link_bw) {
@@ -922,12 +941,12 @@ bool link_decide_link_settings(struct dc_stream_state *stream,
tmp_link_setting.link_rate = LINK_RATE_UNKNOWN;
tmp_timing.flags.DSC = 0;
orig_req_bw = dc_bandwidth_in_kbps_from_timing(&tmp_timing);
- dc_link_decide_edp_link_settings(link, &tmp_link_setting, orig_req_bw);
+ edp_decide_link_settings(link, &tmp_link_setting, orig_req_bw);
max_link_rate = tmp_link_setting.link_rate;
}
decide_edp_link_settings_with_dsc(link, link_setting, req_bw, max_link_rate);
} else {
- dc_link_decide_edp_link_settings(link, link_setting, req_bw);
+ edp_decide_link_settings(link, link_setting, req_bw);
}
} else {
decide_dp_link_settings(link, link_setting, req_bw);
@@ -948,7 +967,7 @@ enum dp_link_encoding link_dp_get_encoding_format(const struct dc_link_settings
return DP_UNKNOWN_ENCODING;
}
-enum dp_link_encoding dc_link_dp_mst_decide_link_encoding_format(const struct dc_link *link)
+enum dp_link_encoding mst_decide_link_encoding_format(const struct dc_link *link)
{
struct dc_link_settings link_settings = {0};
@@ -1005,7 +1024,7 @@ static enum dc_status wake_up_aux_channel(struct dc_link *link)
* signal and may need up to 1 ms before being able to reply.
*/
if (status != DC_OK || dpcd_power_state == DP_SET_POWER_D3) {
- udelay(1000);
+ fsleep(1000);
aux_channel_retry_cnt++;
}
}
@@ -1024,6 +1043,9 @@ static enum dc_status wake_up_aux_channel(struct dc_link *link)
DP_SET_POWER,
&dpcd_power_state,
sizeof(dpcd_power_state));
+ if (status < 0)
+ DC_LOG_DC("%s: Failed to power up sink: %s\n", __func__,
+ dpcd_power_state == DP_SET_POWER_D0 ? "D0" : "D3");
return DC_ERROR_UNEXPECTED;
}
@@ -1121,7 +1143,7 @@ static void get_active_converter_info(
union hdmi_encoded_link_bw hdmi_encoded_link_bw;
link->dpcd_caps.dongle_caps.dp_hdmi_frl_max_link_bw_in_kbps =
- dc_link_bw_kbps_from_raw_frl_link_rate_data(
+ link_bw_kbps_from_raw_frl_link_rate_data(
hdmi_color_caps.bits.MAX_ENCODED_LINK_BW_SUPPORT);
// Intersect reported max link bw support with the supported link rate post FRL link training
@@ -1216,7 +1238,7 @@ static void apply_usbc_combo_phy_reset_wa(struct dc_link *link,
dp_disable_link_phy(link, &link_res, link->connector_signal);
}
-static bool dp_overwrite_extended_receiver_cap(struct dc_link *link)
+bool dp_overwrite_extended_receiver_cap(struct dc_link *link)
{
uint8_t dpcd_data[16];
uint32_t read_dpcd_retry_cnt = 3;
@@ -1278,16 +1300,10 @@ static bool dp_overwrite_extended_receiver_cap(struct dc_link *link)
return true;
}
-void dc_link_overwrite_extended_receiver_cap(
- struct dc_link *link)
-{
- dp_overwrite_extended_receiver_cap(link);
-}
-
void dpcd_set_source_specific_data(struct dc_link *link)
{
if (!link->dc->vendor_signature.is_valid) {
- enum dc_status result_write_min_hblank = DC_NOT_SUPPORTED;
+ enum dc_status __maybe_unused result_write_min_hblank = DC_NOT_SUPPORTED;
struct dpcd_amd_signature amd_signature = {0};
struct dpcd_amd_device_id amd_device_id = {0};
@@ -1972,7 +1988,7 @@ void detect_edp_sink_caps(struct dc_link *link)
sizeof(link->dpcd_caps.alpm_caps.raw));
}
-bool dc_link_dp_get_max_link_enc_cap(const struct dc_link *link, struct dc_link_settings *max_link_enc_cap)
+bool dp_get_max_link_enc_cap(const struct dc_link *link, struct dc_link_settings *max_link_enc_cap)
{
struct link_encoder *link_enc = NULL;
@@ -1995,7 +2011,7 @@ bool dc_link_dp_get_max_link_enc_cap(const struct dc_link *link, struct dc_link_
return false;
}
-const struct dc_link_settings *dc_link_get_link_cap(
+const struct dc_link_settings *dp_get_verified_link_cap(
const struct dc_link *link)
{
if (link->preferred_link_setting.lane_count != LANE_COUNT_UNKNOWN &&
@@ -2121,9 +2137,9 @@ static bool dp_verify_link_cap(
if (status == LINK_TRAINING_SUCCESS) {
success = true;
- udelay(1000);
- if (dc_link_dp_read_hpd_rx_irq_data(link, &irq_data) == DC_OK &&
- dc_link_check_link_loss_status(
+ fsleep(1000);
+ if (dp_read_hpd_rx_irq_data(link, &irq_data) == DC_OK &&
+ dp_parse_link_loss_status(
link,
&irq_data))
(*fail_count)++;
@@ -2163,7 +2179,7 @@ bool dp_verify_link_cap_with_retries(
memset(&link->verified_link_cap, 0,
sizeof(struct dc_link_settings));
- if (!dc_link_detect_connection_type(link, &type) || type == dc_connection_none) {
+ if (!link_detect_connection_type(link, &type) || type == dc_connection_none) {
link->verified_link_cap = fail_safe_link_settings;
break;
} else if (dp_verify_link_cap(link, known_limit_link_setting,
@@ -2171,7 +2187,7 @@ bool dp_verify_link_cap_with_retries(
success = true;
break;
}
- msleep(10);
+ fsleep(10 * 1000);
}
dp_trace_lt_fail_count_update(link, fail_count, true);
@@ -2180,11 +2196,10 @@ bool dp_verify_link_cap_with_retries(
return success;
}
-/**
- * dc_link_is_dp_sink_present() - Check if there is a native DP
- * or passive DP-HDMI dongle connected
+/*
+ * Check if there is a native DP or passive DP-HDMI dongle connected
*/
-bool dc_link_is_dp_sink_present(struct dc_link *link)
+bool dp_is_sink_present(struct dc_link *link)
{
enum gpio_result gpio_result;
uint32_t clock_pin = 0;
@@ -2231,7 +2246,7 @@ bool dc_link_is_dp_sink_present(struct dc_link *link)
gpio_result = dal_gpio_get_value(ddc->pin_clock, &clock_pin);
ASSERT(gpio_result == GPIO_RESULT_OK);
if (clock_pin)
- udelay(1000);
+ fsleep(1000);
else
break;
} while (retry++ < 3);
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.h
index f79e4a4a9db6..8f0ce97f2362 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.h
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.h
@@ -34,32 +34,56 @@ void detect_edp_sink_caps(struct dc_link *link);
struct dc_link_settings dp_get_max_link_cap(struct dc_link *link);
+bool dp_get_max_link_enc_cap(const struct dc_link *link,
+ struct dc_link_settings *max_link_enc_cap);
+
+const struct dc_link_settings *dp_get_verified_link_cap(
+ const struct dc_link *link);
+
+enum dp_link_encoding link_dp_get_encoding_format(
+ const struct dc_link_settings *link_settings);
enum dc_status dp_retrieve_lttpr_cap(struct dc_link *link);
/* Convert PHY repeater count read from DPCD uint8_t. */
uint8_t dp_parse_lttpr_repeater_count(uint8_t lttpr_repeater_count);
+bool dp_is_sink_present(struct dc_link *link);
+
bool dp_is_lttpr_present(struct dc_link *link);
+bool dp_is_fec_supported(const struct dc_link *link);
+
bool is_dp_active_dongle(const struct dc_link *link);
bool is_dp_branch_device(const struct dc_link *link);
void dpcd_write_cable_id_to_dprx(struct dc_link *link);
+bool dp_should_enable_fec(const struct dc_link *link);
+
+bool dp_is_128b_132b_signal(struct pipe_ctx *pipe_ctx);
+
/* Initialize output parameter lt_settings. */
void dp_decide_training_settings(
struct dc_link *link,
const struct dc_link_settings *link_setting,
struct link_training_settings *lt_settings);
+bool link_decide_link_settings(
+ struct dc_stream_state *stream,
+ struct dc_link_settings *link_setting);
+
+bool edp_decide_link_settings(struct dc_link *link,
+ struct dc_link_settings *link_setting, uint32_t req_bw);
bool decide_edp_link_settings_with_dsc(struct dc_link *link,
struct dc_link_settings *link_setting,
uint32_t req_bw,
enum dc_link_rate max_link_rate);
+enum dp_link_encoding mst_decide_link_encoding_format(const struct dc_link *link);
+
void dpcd_set_source_specific_data(struct dc_link *link);
/*query dpcd for version and mst cap addresses*/
@@ -76,4 +100,8 @@ bool dp_verify_link_cap_with_retries(
struct dc_link_settings *known_limit_link_setting,
int attempts);
+uint32_t link_bw_kbps_from_raw_frl_link_rate_data(uint8_t bw);
+
+bool dp_overwrite_extended_receiver_cap(struct dc_link *link);
+
#endif /* __DC_LINK_DP_CAPABILITY_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia.c
index 32f48a48e9dd..4626fabc0a96 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia.c
@@ -26,7 +26,6 @@
#include "dc.h"
#include "inc/core_status.h"
-#include "dc_link.h"
#include "dpcd_defs.h"
#include "link_dp_dpia.h"
@@ -79,7 +78,7 @@ enum dc_status dpcd_get_tunneling_device_data(struct dc_link *link)
return status;
}
-bool dc_link_dpia_query_hpd_status(struct dc_link *link)
+bool dpia_query_hpd_status(struct dc_link *link)
{
union dmub_rb_cmd cmd = {0};
struct dc_dmub_srv *dmub_srv = link->ctx->dmub_srv;
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia.h
index 98935cc10bb7..363f45a1a964 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia.h
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia.h
@@ -37,7 +37,5 @@ enum dc_status dpcd_get_tunneling_device_data(struct dc_link *link);
/* Query hot plug status of USB4 DP tunnel.
* Returns true if HPD high.
*/
-bool dc_link_dpia_query_hpd_status(struct dc_link *link);
-
-
+bool dpia_query_hpd_status(struct dc_link *link);
#endif /* __DC_LINK_DPIA_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c
index f69e681b3b5b..7581023daa47 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c
@@ -26,11 +26,12 @@
/*********************************************************************/
// USB4 DPIA BANDWIDTH ALLOCATION LOGIC
/*********************************************************************/
-#include "dc.h"
-#include "dc_link.h"
#include "link_dp_dpia_bw.h"
-#include "drm_dp_helper_dc.h"
#include "link_dpcd.h"
+#include "dc_dmub_srv.h"
+
+#define DC_LOGGER \
+ link->ctx->logger
#define Kbps_TO_Gbps (1000 * 1000)
@@ -84,12 +85,11 @@ static int get_estimated_bw(struct dc_link *link)
{
uint8_t bw_estimated_bw = 0;
- if (core_link_read_dpcd(
- link,
- ESTIMATED_BW,
- &bw_estimated_bw,
- sizeof(uint8_t)) != DC_OK)
- dm_output_to_console("%s: AUX W/R ERROR @ 0x%x\n", __func__, ESTIMATED_BW);
+ core_link_read_dpcd(
+ link,
+ ESTIMATED_BW,
+ &bw_estimated_bw,
+ sizeof(uint8_t));
return bw_estimated_bw * (Kbps_TO_Gbps / link->dpia_bw_alloc_config.bw_granularity);
}
@@ -133,8 +133,9 @@ static uint8_t get_lowest_dpia_index(struct dc_link *link)
{
const struct dc *dc_struct = link->dc;
uint8_t idx = 0xFF;
+ int i;
- for (int i = 0; i < MAX_PIPES * 2; ++i) {
+ for (i = 0; i < MAX_PIPES * 2; ++i) {
if (!dc_struct->links[i] ||
dc_struct->links[i]->ep_type != DISPLAY_ENDPOINT_USB4_DPIA)
@@ -161,8 +162,9 @@ static int get_host_router_total_bw(struct dc_link *link, uint8_t type)
uint8_t idx = (link->link_index - lowest_dpia_index) / 2, idx_temp = 0;
struct dc_link *link_temp;
int total_bw = 0;
+ int i;
- for (int i = 0; i < MAX_PIPES * 2; ++i) {
+ for (i = 0; i < MAX_PIPES * 2; ++i) {
if (!dc_struct->links[i] || dc_struct->links[i]->ep_type != DISPLAY_ENDPOINT_USB4_DPIA)
continue;
@@ -194,15 +196,13 @@ static int get_host_router_total_bw(struct dc_link *link, uint8_t type)
*/
static bool dpia_bw_alloc_unplug(struct dc_link *link)
{
- bool ret = false;
-
if (!link)
return true;
return deallocate_usb4_bw(&link->dpia_bw_alloc_config.sink_allocated_bw,
link->dpia_bw_alloc_config.sink_allocated_bw, link);
}
-static void dc_link_set_usb4_req_bw_req(struct dc_link *link, int req_bw)
+static void set_usb4_req_bw_req(struct dc_link *link, int req_bw)
{
uint8_t requested_bw;
uint32_t temp;
@@ -227,9 +227,7 @@ static void dc_link_set_usb4_req_bw_req(struct dc_link *link, int req_bw)
link,
REQUESTED_BW,
&requested_bw,
- sizeof(uint8_t)) != DC_OK)
- dm_output_to_console("%s: AUX W/R ERROR @ 0x%x\n", __func__, REQUESTED_BW);
- else
+ sizeof(uint8_t)) == DC_OK)
link->dpia_bw_alloc_config.response_ready = false; // Reset flag
}
/*
@@ -246,7 +244,7 @@ static bool get_cm_response_ready_flag(struct dc_link *link)
// ------------------------------------------------------------------
// PUBLIC FUNCTIONS
// ------------------------------------------------------------------
-bool set_dptx_usb4_bw_alloc_support(struct dc_link *link)
+bool link_dp_dpia_set_dptx_usb4_bw_alloc_support(struct dc_link *link)
{
bool ret = false;
uint8_t response = 0,
@@ -257,22 +255,18 @@ bool set_dptx_usb4_bw_alloc_support(struct dc_link *link)
goto out;
if (core_link_read_dpcd(
- link,
- DP_TUNNELING_CAPABILITIES,
- &response,
- sizeof(uint8_t)) != DC_OK)
- dm_output_to_console("%s: AUX W/R ERROR @ 0x%x\n", __func__, DP_TUNNELING_CAPABILITIES);
-
- bw_support_dpia = (response >> 7) & 1;
+ link,
+ DP_TUNNELING_CAPABILITIES,
+ &response,
+ sizeof(uint8_t)) == DC_OK)
+ bw_support_dpia = (response >> 7) & 1;
if (core_link_read_dpcd(
link,
USB4_DRIVER_BW_CAPABILITY,
&response,
- sizeof(uint8_t)) != DC_OK)
- dm_output_to_console("%s: AUX W/R ERROR @ 0x%x\n", __func__, DP_TUNNELING_CAPABILITIES);
-
- bw_support_cm = (response >> 7) & 1;
+ sizeof(uint8_t)) == DC_OK)
+ bw_support_cm = (response >> 7) & 1;
/* Send request acknowledgment to Turn ON DPTX support */
if (bw_support_cm && bw_support_dpia) {
@@ -282,15 +276,14 @@ bool set_dptx_usb4_bw_alloc_support(struct dc_link *link)
link,
DPTX_BW_ALLOCATION_MODE_CONTROL,
&response,
- sizeof(uint8_t)) != DC_OK)
- dm_output_to_console("%s: AUX W/R ERROR @ 0x%x\n",
- "**** FAILURE Enabling DPtx BW Allocation Mode Support ***\n",
- __func__, DP_TUNNELING_CAPABILITIES);
- else {
-
+ sizeof(uint8_t)) != DC_OK) {
+ DC_LOG_DEBUG("%s: **** FAILURE Enabling DPtx BW Allocation Mode Support ***\n",
+ __func__);
+ } else {
// SUCCESS Enabled DPtx BW Allocation Mode Support
link->dpia_bw_alloc_config.bw_alloc_enabled = true;
- dm_output_to_console("**** SUCCESS Enabling DPtx BW Allocation Mode Support ***\n");
+ DC_LOG_DEBUG("%s: **** SUCCESS Enabling DPtx BW Allocation Mode Support ***\n",
+ __func__);
ret = true;
init_usb4_bw_struct(link);
@@ -300,8 +293,12 @@ bool set_dptx_usb4_bw_alloc_support(struct dc_link *link)
out:
return ret;
}
-void dc_link_get_usb4_req_bw_resp(struct dc_link *link, uint8_t bw, uint8_t result)
+void dpia_handle_bw_alloc_response(struct dc_link *link, uint8_t bw, uint8_t result)
{
+ int bw_needed = 0;
+ int estimated = 0;
+ int host_router_total_estimated_bw = 0;
+
if (!get_bw_alloc_proceed_flag((link)))
return;
@@ -309,13 +306,13 @@ void dc_link_get_usb4_req_bw_resp(struct dc_link *link, uint8_t bw, uint8_t resu
case DPIA_BW_REQ_FAILED:
- dm_output_to_console("%s: *** *** BW REQ FAILURE for DP-TX Request *** ***\n", __func__);
+ DC_LOG_DEBUG("%s: *** *** BW REQ FAILURE for DP-TX Request *** ***\n", __func__);
// Update the new Estimated BW value updated by CM
link->dpia_bw_alloc_config.estimated_bw =
bw * (Kbps_TO_Gbps / link->dpia_bw_alloc_config.bw_granularity);
- dc_link_set_usb4_req_bw_req(link, link->dpia_bw_alloc_config.estimated_bw);
+ set_usb4_req_bw_req(link, link->dpia_bw_alloc_config.estimated_bw);
link->dpia_bw_alloc_config.response_ready = false;
/*
@@ -329,18 +326,18 @@ void dc_link_get_usb4_req_bw_resp(struct dc_link *link, uint8_t bw, uint8_t resu
case DPIA_BW_REQ_SUCCESS:
- dm_output_to_console("%s: *** BW REQ SUCCESS for DP-TX Request ***\n", __func__);
+ DC_LOG_DEBUG("%s: *** BW REQ SUCCESS for DP-TX Request ***\n", __func__);
// 1. SUCCESS 1st time before any Pruning is done
// 2. SUCCESS after prev. FAIL before any Pruning is done
// 3. SUCCESS after Pruning is done but before enabling link
- int needed = bw * (Kbps_TO_Gbps / link->dpia_bw_alloc_config.bw_granularity);
+ bw_needed = bw * (Kbps_TO_Gbps / link->dpia_bw_alloc_config.bw_granularity);
// 1.
if (!link->dpia_bw_alloc_config.sink_allocated_bw) {
- allocate_usb4_bw(&link->dpia_bw_alloc_config.sink_allocated_bw, needed, link);
+ allocate_usb4_bw(&link->dpia_bw_alloc_config.sink_allocated_bw, bw_needed, link);
link->dpia_bw_alloc_config.sink_verified_bw =
link->dpia_bw_alloc_config.sink_allocated_bw;
@@ -354,12 +351,12 @@ void dc_link_get_usb4_req_bw_resp(struct dc_link *link, uint8_t bw, uint8_t resu
else if (link->dpia_bw_alloc_config.sink_allocated_bw) {
// Find out how much do we need to de-alloc
- if (link->dpia_bw_alloc_config.sink_allocated_bw > needed)
+ if (link->dpia_bw_alloc_config.sink_allocated_bw > bw_needed)
deallocate_usb4_bw(&link->dpia_bw_alloc_config.sink_allocated_bw,
- link->dpia_bw_alloc_config.sink_allocated_bw - needed, link);
+ link->dpia_bw_alloc_config.sink_allocated_bw - bw_needed, link);
else
allocate_usb4_bw(&link->dpia_bw_alloc_config.sink_allocated_bw,
- needed - link->dpia_bw_alloc_config.sink_allocated_bw, link);
+ bw_needed - link->dpia_bw_alloc_config.sink_allocated_bw, link);
}
// 4. If this is the 2nd sink then any unused bw will be reallocated to master DPIA
@@ -370,27 +367,19 @@ void dc_link_get_usb4_req_bw_resp(struct dc_link *link, uint8_t bw, uint8_t resu
case DPIA_EST_BW_CHANGED:
- dm_output_to_console("%s: *** ESTIMATED BW CHANGED for DP-TX Request ***\n", __func__);
+ DC_LOG_DEBUG("%s: *** ESTIMATED BW CHANGED for DP-TX Request ***\n", __func__);
- int available = 0, estimated = bw * (Kbps_TO_Gbps / link->dpia_bw_alloc_config.bw_granularity);
- int host_router_total_estimated_bw = get_host_router_total_bw(link, HOST_ROUTER_BW_ESTIMATED);
+ estimated = bw * (Kbps_TO_Gbps / link->dpia_bw_alloc_config.bw_granularity);
+ host_router_total_estimated_bw = get_host_router_total_bw(link, HOST_ROUTER_BW_ESTIMATED);
// 1. If due to unplug of other sink
if (estimated == host_router_total_estimated_bw) {
-
// First update the estimated & max_bw fields
- if (link->dpia_bw_alloc_config.estimated_bw < estimated) {
- available = estimated - link->dpia_bw_alloc_config.estimated_bw;
+ if (link->dpia_bw_alloc_config.estimated_bw < estimated)
link->dpia_bw_alloc_config.estimated_bw = estimated;
- }
}
// 2. If due to realloc bw btw 2 dpia due to plug OR realloc unused Bw
else {
-
- // We took from another unplugged/problematic sink to give to us
- if (link->dpia_bw_alloc_config.estimated_bw < estimated)
- available = estimated - link->dpia_bw_alloc_config.estimated_bw;
-
// We lost estimated bw usually due to plug event of other dpia
link->dpia_bw_alloc_config.estimated_bw = estimated;
}
@@ -398,12 +387,12 @@ void dc_link_get_usb4_req_bw_resp(struct dc_link *link, uint8_t bw, uint8_t resu
case DPIA_BW_ALLOC_CAPS_CHANGED:
- dm_output_to_console("%s: *** BW ALLOC CAPABILITY CHANGED for DP-TX Request ***\n", __func__);
+ DC_LOG_DEBUG("%s: *** BW ALLOC CAPABILITY CHANGED for DP-TX Request ***\n", __func__);
link->dpia_bw_alloc_config.bw_alloc_enabled = false;
break;
}
}
-int dc_link_dp_dpia_handle_usb4_bandwidth_allocation_for_link(struct dc_link *link, int peak_bw)
+int dpia_handle_usb4_bandwidth_allocation_for_link(struct dc_link *link, int peak_bw)
{
int ret = 0;
uint8_t timeout = 10;
@@ -417,14 +406,14 @@ int dc_link_dp_dpia_handle_usb4_bandwidth_allocation_for_link(struct dc_link *li
// If DP over USB4 then we need to check BW allocation
link->dpia_bw_alloc_config.sink_max_bw = peak_bw;
- dc_link_set_usb4_req_bw_req(link, link->dpia_bw_alloc_config.sink_max_bw);
+ set_usb4_req_bw_req(link, link->dpia_bw_alloc_config.sink_max_bw);
do {
- if (!timeout > 0)
+ if (!(timeout > 0))
timeout--;
else
break;
- udelay(10 * 1000);
+ fsleep(10 * 1000);
} while (!get_cm_response_ready_flag(link));
if (!timeout)
@@ -439,3 +428,65 @@ int dc_link_dp_dpia_handle_usb4_bandwidth_allocation_for_link(struct dc_link *li
out:
return ret;
}
+int link_dp_dpia_allocate_usb4_bandwidth_for_stream(struct dc_link *link, int req_bw)
+{
+ int ret = 0;
+ uint8_t timeout = 10;
+
+ if (!get_bw_alloc_proceed_flag(link))
+ goto out;
+
+ /*
+ * Sometimes stream uses same timing parameters as the already
+ * allocated max sink bw so no need to re-alloc
+ */
+ if (req_bw != link->dpia_bw_alloc_config.sink_allocated_bw) {
+ set_usb4_req_bw_req(link, req_bw);
+ do {
+ if (!(timeout > 0))
+ timeout--;
+ else
+ break;
+ udelay(10 * 1000);
+ } while (!get_cm_response_ready_flag(link));
+
+ if (!timeout)
+ ret = 0;// ERROR TIMEOUT waiting for response for allocating bw
+ else if (link->dpia_bw_alloc_config.sink_allocated_bw > 0)
+ ret = get_host_router_total_bw(link, HOST_ROUTER_BW_ALLOCATED);
+ }
+
+out:
+ return ret;
+}
+bool dpia_validate_usb4_bw(struct dc_link **link, int *bw_needed_per_dpia, const unsigned int num_dpias)
+{
+ bool ret = true;
+ int bw_needed_per_hr[MAX_HR_NUM] = { 0, 0 };
+ uint8_t lowest_dpia_index = 0, dpia_index = 0;
+ uint8_t i;
+
+ if (!num_dpias || num_dpias > MAX_DPIA_NUM)
+ return ret;
+
+ //Get total Host Router BW & Validate against each Host Router max BW
+ for (i = 0; i < num_dpias; ++i) {
+
+ if (!link[i]->dpia_bw_alloc_config.bw_alloc_enabled)
+ continue;
+
+ lowest_dpia_index = get_lowest_dpia_index(link[i]);
+ if (link[i]->link_index < lowest_dpia_index)
+ continue;
+
+ dpia_index = (link[i]->link_index - lowest_dpia_index) / 2;
+ bw_needed_per_hr[dpia_index] += bw_needed_per_dpia[i];
+ if (bw_needed_per_hr[dpia_index] > get_host_router_total_bw(link[i], HOST_ROUTER_BW_ALLOCATED)) {
+
+ ret = false;
+ break;
+ }
+ }
+
+ return ret;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.h
index c2c3049adcd1..7292690383ae 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.h
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.h
@@ -26,6 +26,13 @@
#ifndef DC_INC_LINK_DP_DPIA_BW_H_
#define DC_INC_LINK_DP_DPIA_BW_H_
+#include "link.h"
+
+/* Number of Host Routers per motherboard is 2 */
+#define MAX_HR_NUM 2
+/* Number of DPIA per host router is 2 */
+#define MAX_DPIA_NUM (MAX_HR_NUM * 2)
+
/*
* Host Router BW type
*/
@@ -42,6 +49,54 @@ enum bw_type {
*
* return: SUCCESS or FAILURE
*/
-bool set_dptx_usb4_bw_alloc_support(struct dc_link *link);
+bool link_dp_dpia_set_dptx_usb4_bw_alloc_support(struct dc_link *link);
+
+/*
+ * Allocates only what the stream needs for bw, so if:
+ * If (stream_req_bw < or > already_allocated_bw_at_HPD)
+ * => Deallocate Max Bw & then allocate only what the stream needs
+ *
+ * @link: pointer to the dc_link struct instance
+ * @req_bw: Bw requested by the stream
+ *
+ * return: allocated bw else return 0
+ */
+int link_dp_dpia_allocate_usb4_bandwidth_for_stream(struct dc_link *link, int req_bw);
+
+/*
+ * Handle the USB4 BW Allocation related functionality here:
+ * Plug => Try to allocate max bw from timing parameters supported by the sink
+ * Unplug => de-allocate bw
+ *
+ * @link: pointer to the dc_link struct instance
+ * @peak_bw: Peak bw used by the link/sink
+ *
+ * return: allocated bw else return 0
+ */
+int dpia_handle_usb4_bandwidth_allocation_for_link(struct dc_link *link, int peak_bw);
+
+/*
+ * Handle function for when the status of the Request above is complete.
+ * We will find out the result of allocating on CM and update structs.
+ *
+ * @link: pointer to the dc_link struct instance
+ * @bw: Allocated or Estimated BW depending on the result
+ * @result: Response type
+ *
+ * return: none
+ */
+void dpia_handle_bw_alloc_response(struct dc_link *link, uint8_t bw, uint8_t result);
+
+/*
+ * Handle the validation of total BW here and confirm that the bw used by each
+ * DPIA doesn't exceed available BW for each host router (HR)
+ *
+ * @link[]: array of link pointer to all possible DPIA links
+ * @bw_needed[]: bw needed for each DPIA link based on timing
+ * @num_dpias: Number of DPIAs for the above 2 arrays. Should always be <= MAX_DPIA_NUM
+ *
+ * return: TRUE if bw used by DPIAs doesn't exceed available BW else return FALSE
+ */
+bool dpia_validate_usb4_bw(struct dc_link **link, int *bw_needed, const unsigned int num_dpias);
#endif /* DC_INC_LINK_DP_DPIA_BW_H_ */
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c
index 9d80427520cf..ba95facc4ee8 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c
@@ -33,13 +33,14 @@
#include "link_dpcd.h"
#include "link_dp_training.h"
#include "link_dp_capability.h"
+#include "link_edp_panel_control.h"
#include "link/accessories/link_dp_trace.h"
#include "link/link_dpms.h"
#include "dm_helpers.h"
#define DC_LOGGER_INIT(logger)
-bool dc_link_check_link_loss_status(
+bool dp_parse_link_loss_status(
struct dc_link *link,
union hpd_irq_data *hpd_irq_dpcd_data)
{
@@ -155,9 +156,9 @@ static bool handle_hpd_irq_psr_sink(struct dc_link *link)
/* PSR error, disable and re-enable PSR */
if (link->psr_settings.psr_allow_active) {
allow_active = false;
- dc_link_set_psr_allow_active(link, &allow_active, true, false, NULL);
+ edp_set_psr_allow_active(link, &allow_active, true, false, NULL);
allow_active = true;
- dc_link_set_psr_allow_active(link, &allow_active, true, false, NULL);
+ edp_set_psr_allow_active(link, &allow_active, true, false, NULL);
}
return true;
@@ -174,7 +175,7 @@ static bool handle_hpd_irq_psr_sink(struct dc_link *link)
return false;
}
-void dc_link_dp_handle_link_loss(struct dc_link *link)
+void dp_handle_link_loss(struct dc_link *link)
{
struct pipe_ctx *pipes[MAX_PIPES];
struct dc_state *state = link->dc->current_state;
@@ -200,7 +201,7 @@ void dc_link_dp_handle_link_loss(struct dc_link *link)
}
}
-enum dc_status dc_link_dp_read_hpd_rx_irq_data(
+enum dc_status dp_read_hpd_rx_irq_data(
struct dc_link *link,
union hpd_irq_data *irq_data)
{
@@ -247,7 +248,7 @@ enum dc_status dc_link_dp_read_hpd_rx_irq_data(
}
/*************************Short Pulse IRQ***************************/
-bool dc_link_dp_allow_hpd_rx_irq(const struct dc_link *link)
+bool dp_should_allow_hpd_rx_irq(const struct dc_link *link)
{
/*
* Don't handle RX IRQ unless one of following is met:
@@ -262,8 +263,9 @@ bool dc_link_dp_allow_hpd_rx_irq(const struct dc_link *link)
return false;
}
-bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd_irq_dpcd_data, bool *out_link_loss,
- bool defer_handling, bool *has_left_work)
+bool dp_handle_hpd_rx_irq(struct dc_link *link,
+ union hpd_irq_data *out_hpd_irq_dpcd_data, bool *out_link_loss,
+ bool defer_handling, bool *has_left_work)
{
union hpd_irq_data hpd_irq_dpcd_data = {0};
union device_service_irq device_service_clear = {0};
@@ -288,7 +290,7 @@ bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd
* dal_dpsst_ls_read_hpd_irq_data
* Order of calls is important too
*/
- result = dc_link_dp_read_hpd_rx_irq_data(link, &hpd_irq_dpcd_data);
+ result = dp_read_hpd_rx_irq_data(link, &hpd_irq_dpcd_data);
if (out_hpd_irq_dpcd_data)
*out_hpd_irq_dpcd_data = hpd_irq_dpcd_data;
@@ -315,7 +317,7 @@ bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd
return false;
}
- if (!dc_link_dp_allow_hpd_rx_irq(link)) {
+ if (!dp_should_allow_hpd_rx_irq(link)) {
DC_LOG_HW_HPD_IRQ("%s: skipping HPD handling on %d\n",
__func__, link->link_index);
return false;
@@ -348,9 +350,9 @@ bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd
* then DM should call DC to do the detection.
* NOTE: Do not handle link loss on eDP since it is internal link*/
if ((link->connector_signal != SIGNAL_TYPE_EDP) &&
- dc_link_check_link_loss_status(
- link,
- &hpd_irq_dpcd_data)) {
+ dp_parse_link_loss_status(
+ link,
+ &hpd_irq_dpcd_data)) {
/* Connectivity log: link loss */
CONN_DATA_LINK_LOSS(link,
hpd_irq_dpcd_data.raw,
@@ -360,7 +362,7 @@ bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd
if (defer_handling && has_left_work)
*has_left_work = true;
else
- dc_link_dp_handle_link_loss(link);
+ dp_handle_link_loss(link);
status = false;
if (out_link_loss)
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.h
index 39b2e51ea79d..ac33730fedd4 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.h
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.h
@@ -27,5 +27,15 @@
#define __DC_LINK_DP_IRQ_HANDLER_H__
#include "link.h"
-
+bool dp_parse_link_loss_status(
+ struct dc_link *link,
+ union hpd_irq_data *hpd_irq_dpcd_data);
+bool dp_should_allow_hpd_rx_irq(const struct dc_link *link);
+void dp_handle_link_loss(struct dc_link *link);
+enum dc_status dp_read_hpd_rx_irq_data(
+ struct dc_link *link,
+ union hpd_irq_data *irq_data);
+bool dp_handle_hpd_rx_irq(struct dc_link *link,
+ union hpd_irq_data *out_hpd_irq_dpcd_data, bool *out_link_loss,
+ bool defer_handling, bool *has_left_work);
#endif /* __DC_LINK_DP_IRQ_HANDLER_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c
index cd9fb8126bcf..b7abba55bc2f 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c
@@ -40,7 +40,7 @@
#define DC_LOGGER \
link->ctx->logger
-void dc_link_dp_receiver_power_ctrl(struct dc_link *link, bool on)
+void dpcd_write_rx_power_ctrl(struct dc_link *link, bool on)
{
uint8_t state;
@@ -64,7 +64,7 @@ void dp_enable_link_phy(
link->cur_link_settings = *link_settings;
link->dc->hwss.enable_dp_link_output(link, link_res, signal,
clock_source, link_settings);
- dc_link_dp_receiver_power_ctrl(link, true);
+ dpcd_write_rx_power_ctrl(link, true);
}
void dp_disable_link_phy(struct dc_link *link,
@@ -74,7 +74,7 @@ void dp_disable_link_phy(struct dc_link *link,
struct dc *dc = link->ctx->dc;
if (!link->wa_flags.dp_keep_receiver_powered)
- dc_link_dp_receiver_power_ctrl(link, false);
+ dpcd_write_rx_power_ctrl(link, false);
dc->hwss.disable_link_output(link, link_res, signal);
/* Clear current link setting.*/
@@ -143,7 +143,7 @@ enum dc_status dp_set_fec_ready(struct dc_link *link, const struct link_resource
link_enc = link_enc_cfg_get_link_enc(link);
ASSERT(link_enc);
- if (!dc_link_should_enable_fec(link))
+ if (!dp_should_enable_fec(link))
return status;
if (link_enc->funcs->fec_set_ready &&
@@ -183,7 +183,7 @@ void dp_set_fec_enable(struct dc_link *link, bool enable)
link_enc = link_enc_cfg_get_link_enc(link);
ASSERT(link_enc);
- if (!dc_link_should_enable_fec(link))
+ if (!dp_should_enable_fec(link))
return;
if (link_enc->funcs->fec_set_enable &&
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.h
index dba1f29df319..1eb0619d6710 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.h
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.h
@@ -51,6 +51,9 @@ void dp_set_drive_settings(
enum dc_status dp_set_fec_ready(struct dc_link *link,
const struct link_resource *link_res, bool ready);
+
void dp_set_fec_enable(struct dc_link *link, bool enable);
+void dpcd_write_rx_power_ctrl(struct dc_link *link, bool on);
+
#endif /* __DC_LINK_DP_PHY_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c
index b48d4d822991..170f33835930 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c
@@ -41,6 +41,8 @@
#include "link_dp_phy.h"
#include "link_dp_capability.h"
#include "link_edp_panel_control.h"
+#include "link/link_detection.h"
+#include "link/link_validation.h"
#include "atomfirmware.h"
#include "link_enc_cfg.h"
#include "resource.h"
@@ -84,6 +86,9 @@ void dp_log_training_result(
case LINK_RATE_HIGH2:
link_rate = "HBR2";
break;
+ case LINK_RATE_RATE_8:
+ link_rate = "R8";
+ break;
case LINK_RATE_HIGH3:
link_rate = "HBR3";
break;
@@ -207,27 +212,36 @@ enum dpcd_training_patterns
switch (pattern) {
case DP_TRAINING_PATTERN_SEQUENCE_1:
+ DC_LOG_HW_LINK_TRAINING("%s: Using DP training pattern TPS1\n", __func__);
dpcd_tr_pattern = DPCD_TRAINING_PATTERN_1;
break;
case DP_TRAINING_PATTERN_SEQUENCE_2:
+ DC_LOG_HW_LINK_TRAINING("%s: Using DP training pattern TPS2\n", __func__);
dpcd_tr_pattern = DPCD_TRAINING_PATTERN_2;
break;
case DP_TRAINING_PATTERN_SEQUENCE_3:
+ DC_LOG_HW_LINK_TRAINING("%s: Using DP training pattern TPS3\n", __func__);
dpcd_tr_pattern = DPCD_TRAINING_PATTERN_3;
break;
case DP_TRAINING_PATTERN_SEQUENCE_4:
+ DC_LOG_HW_LINK_TRAINING("%s: Using DP training pattern TPS4\n", __func__);
dpcd_tr_pattern = DPCD_TRAINING_PATTERN_4;
break;
case DP_128b_132b_TPS1:
+ DC_LOG_HW_LINK_TRAINING("%s: Using DP 128b/132b training pattern TPS1\n", __func__);
dpcd_tr_pattern = DPCD_128b_132b_TPS1;
break;
case DP_128b_132b_TPS2:
+ DC_LOG_HW_LINK_TRAINING("%s: Using DP 128b/132b training pattern TPS2\n", __func__);
dpcd_tr_pattern = DPCD_128b_132b_TPS2;
break;
case DP_128b_132b_TPS2_CDS:
+ DC_LOG_HW_LINK_TRAINING("%s: Using DP 128b/132b training pattern TPS2 CDS\n",
+ __func__);
dpcd_tr_pattern = DPCD_128b_132b_TPS2_CDS;
break;
case DP_TRAINING_PATTERN_VIDEOIDLE:
+ DC_LOG_HW_LINK_TRAINING("%s: Using DP training pattern videoidle\n", __func__);
dpcd_tr_pattern = DPCD_TRAINING_PATTERN_VIDEOIDLE;
break;
default:
@@ -258,10 +272,7 @@ void dp_wait_for_training_aux_rd_interval(
struct dc_link *link,
uint32_t wait_in_micro_secs)
{
- if (wait_in_micro_secs > 1000)
- msleep(wait_in_micro_secs/1000);
- else
- udelay(wait_in_micro_secs);
+ fsleep(wait_in_micro_secs);
DC_LOG_HW_LINK_TRAINING("%s:\n wait = %d\n",
__func__,
@@ -725,12 +736,10 @@ void override_training_settings(
if (link->preferred_training_settings.fec_enable != NULL)
lt_settings->should_set_fec_ready = *link->preferred_training_settings.fec_enable;
-#if defined(CONFIG_DRM_AMD_DC_DCN)
/* Check DP tunnel LTTPR mode debug option. */
if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA && link->dc->debug.dpia_debug.bits.force_non_lttpr)
lt_settings->lttpr_mode = LTTPR_MODE_NON_LTTPR;
-#endif
dp_get_lttpr_mode_override(link, &lt_settings->lttpr_mode);
}
@@ -780,7 +789,7 @@ enum dc_dp_training_pattern decide_eq_training_pattern(struct dc_link *link,
return pattern;
}
-enum lttpr_mode dc_link_decide_lttpr_mode(struct dc_link *link,
+enum lttpr_mode dp_decide_lttpr_mode(struct dc_link *link,
struct dc_link_settings *link_setting)
{
enum dp_link_encoding encoding = link_dp_get_encoding_format(link_setting);
@@ -865,8 +874,9 @@ static enum dc_status configure_lttpr_mode_non_transparent(
uint8_t repeater_id;
enum dc_status result = DC_ERROR_UNEXPECTED;
uint8_t repeater_mode = DP_PHY_REPEATER_MODE_TRANSPARENT;
+ const struct dc *dc = link->dc;
- enum dp_link_encoding encoding = link_dp_get_encoding_format(&lt_settings->link_settings);
+ enum dp_link_encoding encoding = dc->link_srv->dp_get_encoding_format(&lt_settings->link_settings);
if (encoding == DP_8b_10b_ENCODING) {
DC_LOG_HW_LINK_TRAINING("%s\n Set LTTPR to Transparent Mode\n", __func__);
@@ -970,7 +980,7 @@ static void dpcd_exit_training_mode(struct dc_link *link, enum dp_link_encoding
if ((core_link_read_dpcd(link, DP_SINK_STATUS, &sink_status, 1) == DC_OK) &&
(sink_status & DP_INTRA_HOP_AUX_REPLY_INDICATION) == 0)
break;
- udelay(1000);
+ fsleep(1000);
}
}
}
@@ -1495,7 +1505,10 @@ enum link_training_result dp_perform_link_training(
* Non-LT AUX transactions inside training mode.
*/
if ((link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) && encoding == DP_8b_10b_ENCODING)
- status = dp_perform_fixed_vs_pe_training_sequence(link, link_res, &lt_settings);
+ if (link->dc->config.use_old_fixed_vs_sequence)
+ status = dp_perform_fixed_vs_pe_training_sequence_legacy(link, link_res, &lt_settings);
+ else
+ status = dp_perform_fixed_vs_pe_training_sequence(link, link_res, &lt_settings);
else if (encoding == DP_8b_10b_ENCODING)
status = dp_perform_8b_10b_link_training(link, link_res, &lt_settings);
else if (encoding == DP_128b_132b_ENCODING)
@@ -1556,9 +1569,10 @@ bool perform_link_training_with_retries(
j = 0;
while (j < attempts && fail_count < (attempts * 10)) {
- DC_LOG_HW_LINK_TRAINING("%s: Beginning link(%d) training attempt %u of %d @ rate(%d) x lane(%d)\n",
- __func__, link->link_index, (unsigned int)j + 1, attempts, cur_link_settings.link_rate,
- cur_link_settings.lane_count);
+ DC_LOG_HW_LINK_TRAINING("%s: Beginning link(%d) training attempt %u of %d @ rate(%d) x lane(%d) @ spread = %x\n",
+ __func__, link->link_index, (unsigned int)j + 1, attempts,
+ cur_link_settings.link_rate, cur_link_settings.lane_count,
+ cur_link_settings.link_spread);
dp_enable_link_phy(
link,
@@ -1573,7 +1587,6 @@ bool perform_link_training_with_retries(
msleep(delay_dp_power_up_in_ms);
}
-#ifdef CONFIG_DRM_AMD_DC_HDCP
if (panel_mode == DP_PANEL_MODE_EDP) {
struct cp_psp *cp_psp = &stream->ctx->cp_psp;
@@ -1583,21 +1596,19 @@ bool perform_link_training_with_retries(
* Report and continue with eDP panel mode to
* perform eDP link training with right settings
*/
- bool result;
- result = cp_psp->funcs.enable_assr(cp_psp->handle, link);
+ cp_psp->funcs.enable_assr(cp_psp->handle, link);
}
}
-#endif
dp_set_panel_mode(link, panel_mode);
if (link->aux_access_disabled) {
- dc_link_dp_perform_link_training_skip_aux(link, &pipe_ctx->link_res, &cur_link_settings);
+ dp_perform_link_training_skip_aux(link, &pipe_ctx->link_res, &cur_link_settings);
return true;
} else {
/** @todo Consolidate USB4 DP and DPx.x training. */
if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) {
- status = dc_link_dpia_perform_link_training(
+ status = dpia_perform_link_training(
link,
&pipe_ctx->link_res,
&cur_link_settings,
@@ -1639,9 +1650,10 @@ bool perform_link_training_with_retries(
break;
}
- DC_LOG_WARNING("%s: Link(%d) training attempt %u of %d failed @ rate(%d) x lane(%d) : fail reason:(%d)\n",
- __func__, link->link_index, (unsigned int)j + 1, attempts, cur_link_settings.link_rate,
- cur_link_settings.lane_count, status);
+ DC_LOG_WARNING("%s: Link(%d) training attempt %u of %d failed @ rate(%d) x lane(%d) @ spread = %x : fail reason:(%d)\n",
+ __func__, link->link_index, (unsigned int)j + 1, attempts,
+ cur_link_settings.link_rate, cur_link_settings.lane_count,
+ cur_link_settings.link_spread, status);
dp_disable_link_phy(link, &pipe_ctx->link_res, signal);
@@ -1649,7 +1661,7 @@ bool perform_link_training_with_retries(
if (status == LINK_TRAINING_ABORT) {
enum dc_connection_type type = dc_connection_none;
- dc_link_detect_connection_type(link, &type);
+ link_detect_connection_type(link, &type);
if (type == dc_connection_none) {
DC_LOG_HW_LINK_TRAINING("%s: Aborting training because sink unplugged\n", __func__);
break;
@@ -1682,7 +1694,7 @@ bool perform_link_training_with_retries(
* minimum link bandwidth.
*/
req_bw = dc_bandwidth_in_kbps_from_timing(&stream->timing);
- link_bw = dc_link_bandwidth_kbps(link, &cur_link_settings);
+ link_bw = dp_link_bandwidth_kbps(link, &cur_link_settings);
is_link_bw_low = (req_bw > link_bw);
is_link_bw_min = ((cur_link_settings.link_rate <= LINK_RATE_LOW) &&
(cur_link_settings.lane_count <= LANE_COUNT_ONE));
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.h
index a04948635369..7d027bac8255 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.h
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.h
@@ -119,6 +119,9 @@ enum dc_dp_training_pattern decide_cr_training_pattern(
enum dc_dp_training_pattern decide_eq_training_pattern(struct dc_link *link,
const struct dc_link_settings *link_settings);
+enum lttpr_mode dp_decide_lttpr_mode(struct dc_link *link,
+ struct dc_link_settings *link_setting);
+
void dp_get_lttpr_mode_override(struct dc_link *link,
enum lttpr_mode *override);
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.c
index 14b98e096d39..3889ebb2256b 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.c
@@ -225,8 +225,10 @@ enum link_training_result perform_8b_10b_clock_recovery_sequence(
offset);
/* 5. check CR done*/
- if (dp_is_cr_done(lane_count, dpcd_lane_status))
+ if (dp_is_cr_done(lane_count, dpcd_lane_status)) {
+ DC_LOG_HW_LINK_TRAINING("%s: Clock recovery OK\n", __func__);
return LINK_TRAINING_SUCCESS;
+ }
/* 6. max VS reached*/
if ((link_dp_get_encoding_format(&lt_settings->link_settings) ==
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_auxless.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_auxless.c
index e50ec5012559..4c6b886a9da8 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_auxless.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_auxless.c
@@ -30,7 +30,7 @@
#include "link_dp_phy.h"
#define DC_LOGGER \
link->ctx->logger
-bool dc_link_dp_perform_link_training_skip_aux(
+bool dp_perform_link_training_skip_aux(
struct dc_link *link,
const struct link_resource *link_res,
const struct dc_link_settings *link_setting)
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_auxless.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_auxless.h
index 413999cd03c4..546387a5f32d 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_auxless.h
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_auxless.h
@@ -28,7 +28,7 @@
#define __DC_LINK_DP_TRAINING_AUXLESS_H__
#include "link_dp_training.h"
-bool dc_link_dp_perform_link_training_skip_aux(
+bool dp_perform_link_training_skip_aux(
struct dc_link *link,
const struct link_resource *link_res,
const struct dc_link_settings *link_setting);
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c
index e60da0532c53..4f4e899e5c46 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c
@@ -29,7 +29,6 @@
#include "link_dp_training_dpia.h"
#include "dc.h"
#include "inc/core_status.h"
-#include "dc_link.h"
#include "dpcd_defs.h"
#include "link_dp_dpia.h"
@@ -402,6 +401,7 @@ static enum link_training_result dpia_training_cr_non_transparent(
/* Check if clock recovery successful. */
if (dp_is_cr_done(lane_count, dpcd_lane_status)) {
+ DC_LOG_HW_LINK_TRAINING("%s: Clock recovery OK\n", __func__);
result = LINK_TRAINING_SUCCESS;
break;
}
@@ -509,6 +509,7 @@ static enum link_training_result dpia_training_cr_transparent(
/* Check if clock recovery successful. */
if (dp_is_cr_done(lane_count, dpcd_lane_status)) {
+ DC_LOG_HW_LINK_TRAINING("%s: Clock recovery OK\n", __func__);
result = LINK_TRAINING_SUCCESS;
break;
}
@@ -986,7 +987,7 @@ static void dpia_training_abort(
core_link_send_set_config(link, DPIA_SET_CFG_SET_LINK, data);
}
-enum link_training_result dc_link_dpia_perform_link_training(
+enum link_training_result dpia_perform_link_training(
struct dc_link *link,
const struct link_resource *link_res,
const struct dc_link_settings *link_setting,
@@ -999,7 +1000,7 @@ enum link_training_result dc_link_dpia_perform_link_training(
struct dc_link_settings link_settings = *link_setting; // non-const copy to pass in
- lt_settings.lttpr_mode = dc_link_decide_lttpr_mode(link, &link_settings);
+ lt_settings.lttpr_mode = dp_decide_lttpr_mode(link, &link_settings);
/* Configure link as prescribed in link_setting and set LTTPR mode. */
result = dpia_configure_link(link, link_res, link_setting, &lt_settings);
@@ -1035,7 +1036,7 @@ enum link_training_result dc_link_dpia_perform_link_training(
* falling back to lower bandwidth settings possible.
*/
if (result == LINK_TRAINING_SUCCESS) {
- msleep(5);
+ fsleep(5000);
if (!link->is_automated)
result = dp_check_link_loss_status(link, &lt_settings);
} else if (result == LINK_TRAINING_ABORT)
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.h
index 0150f2916421..b39fb9faf1c2 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.h
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.h
@@ -32,7 +32,7 @@
* DPIA equivalent of dc_link_dp_perfrorm_link_training.
* Aborts link training upon detection of sink unplug.
*/
-enum link_training_result dc_link_dpia_perform_link_training(
+enum link_training_result dpia_perform_link_training(
struct dc_link *link,
const struct link_resource *link_res,
const struct dc_link_settings *link_setting,
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.c
index a4071d2959a0..5731c4b61f9f 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.c
@@ -223,7 +223,7 @@ static enum link_training_result perform_fixed_vs_pe_nontransparent_training_seq
}
-enum link_training_result dp_perform_fixed_vs_pe_training_sequence(
+enum link_training_result dp_perform_fixed_vs_pe_training_sequence_legacy(
struct dc_link *link,
const struct link_resource *link_res,
struct link_training_settings *lt_settings)
@@ -577,3 +577,379 @@ enum link_training_result dp_perform_fixed_vs_pe_training_sequence(
return status;
}
+
+enum link_training_result dp_perform_fixed_vs_pe_training_sequence(
+ struct dc_link *link,
+ const struct link_resource *link_res,
+ struct link_training_settings *lt_settings)
+{
+ const uint8_t vendor_lttpr_write_data_reset[4] = {0x1, 0x50, 0x63, 0xFF};
+ const uint8_t offset = dp_parse_lttpr_repeater_count(
+ link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
+ const uint8_t vendor_lttpr_write_data_intercept_en[4] = {0x1, 0x55, 0x63, 0x0};
+ const uint8_t vendor_lttpr_write_data_intercept_dis[4] = {0x1, 0x55, 0x63, 0x6E};
+ const uint8_t vendor_lttpr_write_data_adicora_eq1[4] = {0x1, 0x55, 0x63, 0x2E};
+ const uint8_t vendor_lttpr_write_data_adicora_eq2[4] = {0x1, 0x55, 0x63, 0x01};
+ const uint8_t vendor_lttpr_write_data_adicora_eq3[4] = {0x1, 0x55, 0x63, 0x68};
+ uint32_t pre_disable_intercept_delay_ms = link->dc->debug.fixed_vs_aux_delay_config_wa;
+ uint8_t vendor_lttpr_write_data_vs[4] = {0x1, 0x51, 0x63, 0x0};
+ uint8_t vendor_lttpr_write_data_pe[4] = {0x1, 0x52, 0x63, 0x0};
+
+ uint32_t vendor_lttpr_write_address = 0xF004F;
+ enum link_training_result status = LINK_TRAINING_SUCCESS;
+ uint8_t lane = 0;
+ union down_spread_ctrl downspread = {0};
+ union lane_count_set lane_count_set = {0};
+ uint8_t toggle_rate;
+ uint8_t rate;
+
+ /* Only 8b/10b is supported */
+ ASSERT(link_dp_get_encoding_format(&lt_settings->link_settings) ==
+ DP_8b_10b_ENCODING);
+
+ if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) {
+ status = perform_fixed_vs_pe_nontransparent_training_sequence(link, link_res, lt_settings);
+ return status;
+ }
+
+ if (offset != 0xFF) {
+ vendor_lttpr_write_address +=
+ ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
+
+ /* Certain display and cable configuration require extra delay */
+ if (offset > 2)
+ pre_disable_intercept_delay_ms = link->dc->debug.fixed_vs_aux_delay_config_wa * 2;
+ }
+
+ /* Vendor specific: Reset lane settings */
+ core_link_write_dpcd(
+ link,
+ vendor_lttpr_write_address,
+ &vendor_lttpr_write_data_reset[0],
+ sizeof(vendor_lttpr_write_data_reset));
+ core_link_write_dpcd(
+ link,
+ vendor_lttpr_write_address,
+ &vendor_lttpr_write_data_vs[0],
+ sizeof(vendor_lttpr_write_data_vs));
+ core_link_write_dpcd(
+ link,
+ vendor_lttpr_write_address,
+ &vendor_lttpr_write_data_pe[0],
+ sizeof(vendor_lttpr_write_data_pe));
+
+ /* Vendor specific: Enable intercept */
+ core_link_write_dpcd(
+ link,
+ vendor_lttpr_write_address,
+ &vendor_lttpr_write_data_intercept_en[0],
+ sizeof(vendor_lttpr_write_data_intercept_en));
+
+ /* 1. set link rate, lane count and spread. */
+
+ downspread.raw = (uint8_t)(lt_settings->link_settings.link_spread);
+
+ lane_count_set.bits.LANE_COUNT_SET =
+ lt_settings->link_settings.lane_count;
+
+ lane_count_set.bits.ENHANCED_FRAMING = lt_settings->enhanced_framing;
+ lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = 0;
+
+
+ if (lt_settings->pattern_for_eq < DP_TRAINING_PATTERN_SEQUENCE_4) {
+ lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED =
+ link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED;
+ }
+
+ core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL,
+ &downspread.raw, sizeof(downspread));
+
+ core_link_write_dpcd(link, DP_LANE_COUNT_SET,
+ &lane_count_set.raw, 1);
+
+ rate = get_dpcd_link_rate(&lt_settings->link_settings);
+
+ /* Vendor specific: Toggle link rate */
+ toggle_rate = (rate == 0x6) ? 0xA : 0x6;
+
+ if (link->vendor_specific_lttpr_link_rate_wa == rate) {
+ core_link_write_dpcd(
+ link,
+ DP_LINK_BW_SET,
+ &toggle_rate,
+ 1);
+ }
+
+ link->vendor_specific_lttpr_link_rate_wa = rate;
+
+ core_link_write_dpcd(link, DP_LINK_BW_SET, &rate, 1);
+
+ DC_LOG_HW_LINK_TRAINING("%s\n %x rate = %x\n %x lane = %x framing = %x\n %x spread = %x\n",
+ __func__,
+ DP_LINK_BW_SET,
+ lt_settings->link_settings.link_rate,
+ DP_LANE_COUNT_SET,
+ lt_settings->link_settings.lane_count,
+ lt_settings->enhanced_framing,
+ DP_DOWNSPREAD_CTRL,
+ lt_settings->link_settings.link_spread);
+
+ /* 2. Perform link training */
+
+ /* Perform Clock Recovery Sequence */
+ if (status == LINK_TRAINING_SUCCESS) {
+ const uint8_t max_vendor_dpcd_retries = 10;
+ uint32_t retries_cr;
+ uint32_t retry_count;
+ uint32_t wait_time_microsec;
+ enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
+ union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
+ union lane_align_status_updated dpcd_lane_status_updated;
+ union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
+ enum dc_status dpcd_status = DC_OK;
+ uint8_t i = 0;
+
+ retries_cr = 0;
+ retry_count = 0;
+
+ memset(&dpcd_lane_status, '\0', sizeof(dpcd_lane_status));
+ memset(&dpcd_lane_status_updated, '\0',
+ sizeof(dpcd_lane_status_updated));
+
+ while ((retries_cr < LINK_TRAINING_MAX_RETRY_COUNT) &&
+ (retry_count < LINK_TRAINING_MAX_CR_RETRY)) {
+
+
+ /* 1. call HWSS to set lane settings */
+ dp_set_hw_lane_settings(
+ link,
+ link_res,
+ lt_settings,
+ 0);
+
+ /* 2. update DPCD of the receiver */
+ if (!retry_count) {
+ /* EPR #361076 - write as a 5-byte burst,
+ * but only for the 1-st iteration.
+ */
+ dpcd_set_lt_pattern_and_lane_settings(
+ link,
+ lt_settings,
+ lt_settings->pattern_for_cr,
+ 0);
+ /* Vendor specific: Disable intercept */
+ for (i = 0; i < max_vendor_dpcd_retries; i++) {
+ msleep(pre_disable_intercept_delay_ms);
+ dpcd_status = core_link_write_dpcd(
+ link,
+ vendor_lttpr_write_address,
+ &vendor_lttpr_write_data_intercept_dis[0],
+ sizeof(vendor_lttpr_write_data_intercept_dis));
+
+ if (dpcd_status == DC_OK)
+ break;
+
+ core_link_write_dpcd(
+ link,
+ vendor_lttpr_write_address,
+ &vendor_lttpr_write_data_intercept_en[0],
+ sizeof(vendor_lttpr_write_data_intercept_en));
+ }
+ } else {
+ vendor_lttpr_write_data_vs[3] = 0;
+ vendor_lttpr_write_data_pe[3] = 0;
+
+ for (lane = 0; lane < lane_count; lane++) {
+ vendor_lttpr_write_data_vs[3] |=
+ lt_settings->dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET << (2 * lane);
+ vendor_lttpr_write_data_pe[3] |=
+ lt_settings->dpcd_lane_settings[lane].bits.PRE_EMPHASIS_SET << (2 * lane);
+ }
+
+ /* Vendor specific: Update VS and PE to DPRX requested value */
+ core_link_write_dpcd(
+ link,
+ vendor_lttpr_write_address,
+ &vendor_lttpr_write_data_vs[0],
+ sizeof(vendor_lttpr_write_data_vs));
+ core_link_write_dpcd(
+ link,
+ vendor_lttpr_write_address,
+ &vendor_lttpr_write_data_pe[0],
+ sizeof(vendor_lttpr_write_data_pe));
+
+ dpcd_set_lane_settings(
+ link,
+ lt_settings,
+ 0);
+ }
+
+ /* 3. wait receiver to lock-on*/
+ wait_time_microsec = lt_settings->cr_pattern_time;
+
+ dp_wait_for_training_aux_rd_interval(
+ link,
+ wait_time_microsec);
+
+ /* 4. Read lane status and requested drive
+ * settings as set by the sink
+ */
+ dp_get_lane_status_and_lane_adjust(
+ link,
+ lt_settings,
+ dpcd_lane_status,
+ &dpcd_lane_status_updated,
+ dpcd_lane_adjust,
+ 0);
+
+ /* 5. check CR done*/
+ if (dp_is_cr_done(lane_count, dpcd_lane_status)) {
+ status = LINK_TRAINING_SUCCESS;
+ break;
+ }
+
+ /* 6. max VS reached*/
+ if (dp_is_max_vs_reached(lt_settings))
+ break;
+
+ /* 7. same lane settings */
+ /* Note: settings are the same for all lanes,
+ * so comparing first lane is sufficient
+ */
+ if (lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET ==
+ dpcd_lane_adjust[0].bits.VOLTAGE_SWING_LANE)
+ retries_cr++;
+ else
+ retries_cr = 0;
+
+ /* 8. update VS/PE/PC2 in lt_settings*/
+ dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
+ lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
+ retry_count++;
+ }
+
+ if (retry_count >= LINK_TRAINING_MAX_CR_RETRY) {
+ ASSERT(0);
+ DC_LOG_ERROR("%s: Link Training Error, could not get CR after %d tries. Possibly voltage swing issue",
+ __func__,
+ LINK_TRAINING_MAX_CR_RETRY);
+
+ }
+
+ status = dp_get_cr_failure(lane_count, dpcd_lane_status);
+ }
+
+ /* Perform Channel EQ Sequence */
+ if (status == LINK_TRAINING_SUCCESS) {
+ enum dc_dp_training_pattern tr_pattern;
+ uint32_t retries_ch_eq;
+ uint32_t wait_time_microsec;
+ enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
+ union lane_align_status_updated dpcd_lane_status_updated = {0};
+ union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0};
+ union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
+
+ core_link_write_dpcd(
+ link,
+ vendor_lttpr_write_address,
+ &vendor_lttpr_write_data_adicora_eq1[0],
+ sizeof(vendor_lttpr_write_data_adicora_eq1));
+ core_link_write_dpcd(
+ link,
+ vendor_lttpr_write_address,
+ &vendor_lttpr_write_data_adicora_eq2[0],
+ sizeof(vendor_lttpr_write_data_adicora_eq2));
+
+ /* Note: also check that TPS4 is a supported feature*/
+ tr_pattern = lt_settings->pattern_for_eq;
+
+ dp_set_hw_training_pattern(link, link_res, tr_pattern, 0);
+
+ status = LINK_TRAINING_EQ_FAIL_EQ;
+
+ for (retries_ch_eq = 0; retries_ch_eq <= LINK_TRAINING_MAX_RETRY_COUNT;
+ retries_ch_eq++) {
+
+ dp_set_hw_lane_settings(link, link_res, lt_settings, 0);
+
+ vendor_lttpr_write_data_vs[3] = 0;
+ vendor_lttpr_write_data_pe[3] = 0;
+
+ for (lane = 0; lane < lane_count; lane++) {
+ vendor_lttpr_write_data_vs[3] |=
+ lt_settings->dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET << (2 * lane);
+ vendor_lttpr_write_data_pe[3] |=
+ lt_settings->dpcd_lane_settings[lane].bits.PRE_EMPHASIS_SET << (2 * lane);
+ }
+
+ /* Vendor specific: Update VS and PE to DPRX requested value */
+ core_link_write_dpcd(
+ link,
+ vendor_lttpr_write_address,
+ &vendor_lttpr_write_data_vs[0],
+ sizeof(vendor_lttpr_write_data_vs));
+ core_link_write_dpcd(
+ link,
+ vendor_lttpr_write_address,
+ &vendor_lttpr_write_data_pe[0],
+ sizeof(vendor_lttpr_write_data_pe));
+
+ /* 2. update DPCD*/
+ if (!retries_ch_eq) {
+ /* EPR #361076 - write as a 5-byte burst,
+ * but only for the 1-st iteration
+ */
+
+ dpcd_set_lt_pattern_and_lane_settings(
+ link,
+ lt_settings,
+ tr_pattern, 0);
+
+ core_link_write_dpcd(
+ link,
+ vendor_lttpr_write_address,
+ &vendor_lttpr_write_data_adicora_eq3[0],
+ sizeof(vendor_lttpr_write_data_adicora_eq3));
+ } else
+ dpcd_set_lane_settings(link, lt_settings, 0);
+
+ /* 3. wait for receiver to lock-on*/
+ wait_time_microsec = lt_settings->eq_pattern_time;
+
+ dp_wait_for_training_aux_rd_interval(
+ link,
+ wait_time_microsec);
+
+ /* 4. Read lane status and requested
+ * drive settings as set by the sink
+ */
+ dp_get_lane_status_and_lane_adjust(
+ link,
+ lt_settings,
+ dpcd_lane_status,
+ &dpcd_lane_status_updated,
+ dpcd_lane_adjust,
+ 0);
+
+ /* 5. check CR done*/
+ if (!dp_is_cr_done(lane_count, dpcd_lane_status)) {
+ status = LINK_TRAINING_EQ_FAIL_CR;
+ break;
+ }
+
+ /* 6. check CHEQ done*/
+ if (dp_is_ch_eq_done(lane_count, dpcd_lane_status) &&
+ dp_is_symbol_locked(lane_count, dpcd_lane_status) &&
+ dp_is_interlane_aligned(dpcd_lane_status_updated)) {
+ status = LINK_TRAINING_SUCCESS;
+ break;
+ }
+
+ /* 7. update VS/PE/PC2 in lt_settings*/
+ dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
+ lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
+ }
+ }
+
+ return status;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.h
index e61970e27661..c0d6ea329504 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.h
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.h
@@ -28,6 +28,11 @@
#define __DC_LINK_DP_FIXED_VS_PE_RETIMER_H__
#include "link_dp_training.h"
+enum link_training_result dp_perform_fixed_vs_pe_training_sequence_legacy(
+ struct dc_link *link,
+ const struct link_resource *link_res,
+ struct link_training_settings *lt_settings);
+
enum link_training_result dp_perform_fixed_vs_pe_training_sequence(
struct dc_link *link,
const struct link_resource *link_res,
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c
index 97e02b5b21ae..d895046787bc 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c
@@ -37,6 +37,11 @@
#include "abm.h"
#define DC_LOGGER_INIT(logger)
+/* Travis */
+static const uint8_t DP_VGA_LVDS_CONVERTER_ID_2[] = "sivarT";
+/* Nutmeg */
+static const uint8_t DP_VGA_LVDS_CONVERTER_ID_3[] = "dnomlA";
+
void dp_set_panel_mode(struct dc_link *link, enum dp_panel_mode panel_mode)
{
union dpcd_edp_config edp_config_set;
@@ -139,7 +144,7 @@ enum dp_panel_mode dp_get_panel_mode(struct dc_link *link)
return DP_PANEL_MODE_DEFAULT;
}
-bool dc_link_set_backlight_level_nits(struct dc_link *link,
+bool edp_set_backlight_level_nits(struct dc_link *link,
bool isHDR,
uint32_t backlight_millinits,
uint32_t transition_time_in_ms)
@@ -171,7 +176,7 @@ bool dc_link_set_backlight_level_nits(struct dc_link *link,
return true;
}
-bool dc_link_get_backlight_level_nits(struct dc_link *link,
+bool edp_get_backlight_level_nits(struct dc_link *link,
uint32_t *backlight_millinits_avg,
uint32_t *backlight_millinits_peak)
{
@@ -201,7 +206,7 @@ bool dc_link_get_backlight_level_nits(struct dc_link *link,
return true;
}
-bool link_backlight_enable_aux(struct dc_link *link, bool enable)
+bool edp_backlight_enable_aux(struct dc_link *link, bool enable)
{
uint8_t backlight_enable = enable ? 1 : 0;
@@ -243,13 +248,13 @@ bool set_default_brightness_aux(struct dc_link *link)
if (default_backlight < 5000 || default_backlight > 5000000)
default_backlight = 150000; //
- return dc_link_set_backlight_level_nits(link, true,
+ return edp_set_backlight_level_nits(link, true,
default_backlight, 0);
}
return false;
}
-bool link_is_edp_ilr_optimization_required(struct dc_link *link,
+bool edp_is_ilr_optimization_required(struct dc_link *link,
struct dc_crtc_timing *crtc_timing)
{
struct dc_link_settings link_setting;
@@ -285,7 +290,7 @@ bool link_is_edp_ilr_optimization_required(struct dc_link *link,
req_bw = dc_bandwidth_in_kbps_from_timing(crtc_timing);
if (!crtc_timing->flags.DSC)
- dc_link_decide_edp_link_settings(link, &link_setting, req_bw);
+ edp_decide_link_settings(link, &link_setting, req_bw);
else
decide_edp_link_settings_with_dsc(link, &link_setting, req_bw, LINK_RATE_UNKNOWN);
@@ -299,7 +304,7 @@ bool link_is_edp_ilr_optimization_required(struct dc_link *link,
return false;
}
-void dc_link_edp_panel_backlight_power_on(struct dc_link *link, bool wait_for_hpd)
+void edp_panel_backlight_power_on(struct dc_link *link, bool wait_for_hpd)
{
if (link->connector_signal != SIGNAL_TYPE_EDP)
return;
@@ -311,7 +316,7 @@ void dc_link_edp_panel_backlight_power_on(struct dc_link *link, bool wait_for_hp
link->dc->hwss.edp_backlight_control(link, true);
}
-bool dc_link_wait_for_t12(struct dc_link *link)
+bool edp_wait_for_t12(struct dc_link *link)
{
if (link->connector_signal == SIGNAL_TYPE_EDP && link->dc->hwss.edp_wait_for_T12) {
link->dc->hwss.edp_wait_for_T12(link);
@@ -322,13 +327,13 @@ bool dc_link_wait_for_t12(struct dc_link *link)
return false;
}
-void link_edp_add_delay_for_T9(struct dc_link *link)
+void edp_add_delay_for_T9(struct dc_link *link)
{
if (link && link->panel_config.pps.extra_delay_backlight_off > 0)
- udelay(link->panel_config.pps.extra_delay_backlight_off * 1000);
+ fsleep(link->panel_config.pps.extra_delay_backlight_off * 1000);
}
-bool link_edp_receiver_ready_T9(struct dc_link *link)
+bool edp_receiver_ready_T9(struct dc_link *link)
{
unsigned int tries = 0;
unsigned char sinkstatus = 0;
@@ -353,7 +358,7 @@ bool link_edp_receiver_ready_T9(struct dc_link *link)
return result;
}
-bool link_edp_receiver_ready_T7(struct dc_link *link)
+bool edp_receiver_ready_T7(struct dc_link *link)
{
unsigned char sinkstatus = 0;
unsigned char edpRev = 0;
@@ -383,12 +388,12 @@ bool link_edp_receiver_ready_T7(struct dc_link *link)
}
if (link && link->panel_config.pps.extra_t7_ms > 0)
- udelay(link->panel_config.pps.extra_t7_ms * 1000);
+ fsleep(link->panel_config.pps.extra_t7_ms * 1000);
return result;
}
-bool link_power_alpm_dpcd_enable(struct dc_link *link, bool enable)
+bool edp_power_alpm_dpcd_enable(struct dc_link *link, bool enable)
{
bool ret = false;
union dpcd_alpm_configuration alpm_config;
@@ -422,7 +427,7 @@ static struct pipe_ctx *get_pipe_from_link(const struct dc_link *link)
return pipe_ctx;
}
-bool dc_link_set_backlight_level(const struct dc_link *link,
+bool edp_set_backlight_level(const struct dc_link *link,
uint32_t backlight_pwm_u16_16,
uint32_t frame_ramp)
{
@@ -453,7 +458,7 @@ bool dc_link_set_backlight_level(const struct dc_link *link,
return true;
}
-bool dc_link_set_psr_allow_active(struct dc_link *link, const bool *allow_active,
+bool edp_set_psr_allow_active(struct dc_link *link, const bool *allow_active,
bool wait, bool force_static, const unsigned int *power_opts)
{
struct dc *dc = link->ctx->dc;
@@ -502,7 +507,7 @@ bool dc_link_set_psr_allow_active(struct dc_link *link, const bool *allow_active
return true;
}
-bool dc_link_get_psr_state(const struct dc_link *link, enum dc_psr_state *state)
+bool edp_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;
@@ -557,7 +562,7 @@ transmitter_to_phy_id(struct dc_link *link)
}
}
-bool dc_link_setup_psr(struct dc_link *link,
+bool edp_setup_psr(struct dc_link *link,
const struct dc_stream_state *stream, struct psr_config *psr_config,
struct psr_context *psr_context)
{
@@ -623,7 +628,7 @@ bool dc_link_setup_psr(struct dc_link *link,
sizeof(psr_configuration.raw));
if (link->psr_settings.psr_version == DC_PSR_VERSION_SU_1) {
- link_power_alpm_dpcd_enable(link, true);
+ edp_power_alpm_dpcd_enable(link, true);
psr_context->su_granularity_required =
psr_config->su_granularity_required;
psr_context->su_y_granularity =
@@ -695,7 +700,6 @@ bool dc_link_setup_psr(struct dc_link *link,
psr_context->psr_level.u32all = 0;
/*skip power down the single pipe since it blocks the cstate*/
-#if defined(CONFIG_DRM_AMD_DC_DCN)
if (link->ctx->asic_id.chip_family >= FAMILY_RV) {
switch (link->ctx->asic_id.chip_family) {
case FAMILY_YELLOW_CARP:
@@ -709,10 +713,6 @@ bool dc_link_setup_psr(struct dc_link *link,
break;
}
}
-#else
- if (link->ctx->asic_id.chip_family >= FAMILY_RV)
- psr_context->psr_level.bits.SKIP_CRTC_DISABLE = true;
-#endif
/* SMU will perform additional powerdown sequence.
* For unsupported ASICs, set psr_level flag to skip PSR
@@ -757,7 +757,7 @@ bool dc_link_setup_psr(struct dc_link *link,
}
-void link_get_psr_residency(const struct dc_link *link, uint32_t *residency)
+void edp_get_psr_residency(const struct dc_link *link, uint32_t *residency)
{
struct dc *dc = link->ctx->dc;
struct dmub_psr *psr = dc->res_pool->psr;
@@ -772,7 +772,7 @@ void link_get_psr_residency(const struct dc_link *link, uint32_t *residency)
else
*residency = 0;
}
-bool link_set_sink_vtotal_in_psr_active(const struct dc_link *link, uint16_t psr_vtotal_idle, uint16_t psr_vtotal_su)
+bool edp_set_sink_vtotal_in_psr_active(const struct dc_link *link, uint16_t psr_vtotal_idle, uint16_t psr_vtotal_su)
{
struct dc *dc = link->ctx->dc;
struct dmub_psr *psr = dc->res_pool->psr;
@@ -803,7 +803,7 @@ static struct abm *get_abm_from_stream_res(const struct dc_link *link)
return abm;
}
-int dc_link_get_backlight_level(const struct dc_link *link)
+int edp_get_backlight_level(const struct dc_link *link)
{
struct abm *abm = get_abm_from_stream_res(link);
struct panel_cntl *panel_cntl = link->panel_cntl;
@@ -822,7 +822,7 @@ int dc_link_get_backlight_level(const struct dc_link *link)
return DC_ERROR_UNEXPECTED;
}
-int dc_link_get_target_backlight_pwm(const struct dc_link *link)
+int edp_get_target_backlight_pwm(const struct dc_link *link)
{
struct abm *abm = get_abm_from_stream_res(link);
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h
index 7f91a564b089..28f552080558 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h
@@ -30,4 +30,34 @@
enum dp_panel_mode dp_get_panel_mode(struct dc_link *link);
void dp_set_panel_mode(struct dc_link *link, enum dp_panel_mode panel_mode);
bool set_default_brightness_aux(struct dc_link *link);
+void edp_panel_backlight_power_on(struct dc_link *link, bool wait_for_hpd);
+int edp_get_backlight_level(const struct dc_link *link);
+bool edp_get_backlight_level_nits(struct dc_link *link,
+ uint32_t *backlight_millinits_avg,
+ uint32_t *backlight_millinits_peak);
+bool edp_set_backlight_level(const struct dc_link *link,
+ uint32_t backlight_pwm_u16_16,
+ uint32_t frame_ramp);
+bool edp_set_backlight_level_nits(struct dc_link *link,
+ bool isHDR,
+ uint32_t backlight_millinits,
+ uint32_t transition_time_in_ms);
+int edp_get_target_backlight_pwm(const struct dc_link *link);
+bool edp_get_psr_state(const struct dc_link *link, enum dc_psr_state *state);
+bool edp_set_psr_allow_active(struct dc_link *link, const bool *allow_active,
+ bool wait, bool force_static, const unsigned int *power_opts);
+bool edp_setup_psr(struct dc_link *link,
+ const struct dc_stream_state *stream, struct psr_config *psr_config,
+ struct psr_context *psr_context);
+bool edp_set_sink_vtotal_in_psr_active(const struct dc_link *link,
+ uint16_t psr_vtotal_idle, uint16_t psr_vtotal_su);
+void edp_get_psr_residency(const struct dc_link *link, uint32_t *residency);
+bool edp_wait_for_t12(struct dc_link *link);
+bool edp_is_ilr_optimization_required(struct dc_link *link,
+ struct dc_crtc_timing *crtc_timing);
+bool edp_backlight_enable_aux(struct dc_link *link, bool enable);
+void edp_add_delay_for_T9(struct dc_link *link);
+bool edp_receiver_ready_T9(struct dc_link *link);
+bool edp_receiver_ready_T7(struct dc_link *link);
+bool edp_power_alpm_dpcd_enable(struct dc_link *link, bool enable);
#endif /* __DC_LINK_EDP_POWER_CONTROL_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_hpd.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_hpd.c
index 5f39dfe06e9a..e3d729ab5b9f 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_hpd.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_hpd.c
@@ -33,18 +33,18 @@
#include "link_hpd.h"
#include "gpio_service_interface.h"
-bool dc_link_get_hpd_state(struct dc_link *dc_link)
+bool link_get_hpd_state(struct dc_link *link)
{
uint32_t state;
- dal_gpio_lock_pin(dc_link->hpd_gpio);
- dal_gpio_get_value(dc_link->hpd_gpio, &state);
- dal_gpio_unlock_pin(dc_link->hpd_gpio);
+ dal_gpio_lock_pin(link->hpd_gpio);
+ dal_gpio_get_value(link->hpd_gpio, &state);
+ dal_gpio_unlock_pin(link->hpd_gpio);
return state;
}
-void dc_link_enable_hpd(const struct dc_link *link)
+void link_enable_hpd(const struct dc_link *link)
{
struct link_encoder *encoder = link->link_enc;
@@ -52,7 +52,7 @@ void dc_link_enable_hpd(const struct dc_link *link)
encoder->funcs->enable_hpd(encoder);
}
-void dc_link_disable_hpd(const struct dc_link *link)
+void link_disable_hpd(const struct dc_link *link)
{
struct link_encoder *encoder = link->link_enc;
@@ -60,7 +60,7 @@ void dc_link_disable_hpd(const struct dc_link *link)
encoder->funcs->disable_hpd(encoder);
}
-void dc_link_enable_hpd_filter(struct dc_link *link, bool enable)
+void link_enable_hpd_filter(struct dc_link *link, bool enable)
{
struct gpio *hpd;
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_hpd.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_hpd.h
index 3d122def0c88..4fb526b264f9 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_hpd.h
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_hpd.h
@@ -44,4 +44,11 @@ bool program_hpd_filter(const struct dc_link *link);
*/
bool dpia_query_hpd_status(struct dc_link *link);
bool query_hpd_status(struct dc_link *link, uint32_t *is_hpd_high);
+bool link_get_hpd_state(struct dc_link *link);
+struct gpio *link_get_hpd_gpio(struct dc_bios *dcb,
+ struct graphics_object_id link_id,
+ struct gpio_service *gpio_service);
+void link_enable_hpd(const struct dc_link *link);
+void link_disable_hpd(const struct dc_link *link);
+void link_enable_hpd_filter(struct dc_link *link, bool enable);
#endif /* __DC_LINK_HPD_H__ */