1 /* Copyright 2015 Advanced Micro Devices, Inc. */
4 #include "dm_services.h"
6 #include "inc/core_dc.h"
7 #include "include/ddc_service_types.h"
8 #include "include/i2caux_interface.h"
10 #include "hw_sequencer.h"
11 #include "dc_link_dp.h"
12 #include "dc_link_ddc.h"
13 #include "dm_helpers.h"
14 #include "dce/dce_link_encoder.h"
15 #include "dce/dce_stream_encoder.h"
17 enum dc_status
core_link_read_dpcd(
18 struct core_link
* link
,
23 if (!dm_helpers_dp_read_dpcd(link
->ctx
,
26 return DC_ERROR_UNEXPECTED
;
31 enum dc_status
core_link_write_dpcd(
32 struct core_link
* link
,
37 if (!dm_helpers_dp_write_dpcd(link
->ctx
,
40 return DC_ERROR_UNEXPECTED
;
45 void dp_receiver_power_ctrl(struct core_link
*link
, bool on
)
49 state
= on
? DP_POWER_STATE_D0
: DP_POWER_STATE_D3
;
51 core_link_write_dpcd(link
, DPCD_ADDRESS_POWER_STATE
, &state
,
55 void dp_enable_link_phy(
56 struct core_link
*link
,
57 enum signal_type signal
,
58 enum clock_source_id clock_source
,
59 const struct dc_link_settings
*link_settings
)
61 struct link_encoder
*link_enc
= link
->link_enc
;
63 if (dc_is_dp_sst_signal(signal
)) {
64 if (signal
== SIGNAL_TYPE_EDP
) {
65 link_enc
->funcs
->power_control(link_enc
, true);
66 link_enc
->funcs
->backlight_control(link_enc
, true);
69 link_enc
->funcs
->enable_dp_output(
74 link_enc
->funcs
->enable_dp_mst_output(
80 dp_receiver_power_ctrl(link
, true);
83 void dp_disable_link_phy(struct core_link
*link
, enum signal_type signal
)
85 if (!link
->wa_flags
.dp_keep_receiver_powered
)
86 dp_receiver_power_ctrl(link
, false);
88 if (signal
== SIGNAL_TYPE_EDP
)
89 link
->link_enc
->funcs
->backlight_control(link
->link_enc
, false);
91 link
->link_enc
->funcs
->disable_output(link
->link_enc
, signal
);
93 /* Clear current link setting.*/
94 memset(&link
->public.cur_link_settings
, 0,
95 sizeof(link
->public.cur_link_settings
));
98 void dp_disable_link_phy_mst(struct core_link
*link
, enum signal_type signal
)
100 /* MST disable link only when no stream use the link */
101 if (link
->mst_stream_alloc_table
.stream_count
> 0)
104 dp_disable_link_phy(link
, signal
);
107 bool dp_set_hw_training_pattern(
108 struct core_link
*link
,
109 enum hw_dp_training_pattern pattern
)
111 enum dp_test_pattern test_pattern
= DP_TEST_PATTERN_UNSUPPORTED
;
114 case HW_DP_TRAINING_PATTERN_1
:
115 test_pattern
= DP_TEST_PATTERN_TRAINING_PATTERN1
;
117 case HW_DP_TRAINING_PATTERN_2
:
118 test_pattern
= DP_TEST_PATTERN_TRAINING_PATTERN2
;
120 case HW_DP_TRAINING_PATTERN_3
:
121 test_pattern
= DP_TEST_PATTERN_TRAINING_PATTERN3
;
123 case HW_DP_TRAINING_PATTERN_4
:
124 test_pattern
= DP_TEST_PATTERN_TRAINING_PATTERN4
;
130 dp_set_hw_test_pattern(link
, test_pattern
, NULL
, 0);
135 void dp_set_hw_lane_settings(
136 struct core_link
*link
,
137 const struct link_training_settings
*link_settings
)
139 struct link_encoder
*encoder
= link
->link_enc
;
141 /* call Encoder to set lane settings */
142 encoder
->funcs
->dp_set_lane_settings(encoder
, link_settings
);
145 enum dp_panel_mode
dp_get_panel_mode(struct core_link
*link
)
147 /* We need to explicitly check that connector
148 * is not DP. Some Travis_VGA get reported
149 * by video bios as DP.
151 if (link
->public.connector_signal
!= SIGNAL_TYPE_DISPLAY_PORT
) {
153 switch (link
->dpcd_caps
.branch_dev_id
) {
154 case DP_BRANCH_DEVICE_ID_2
:
156 link
->dpcd_caps
.branch_dev_name
,
157 DP_VGA_LVDS_CONVERTER_ID_2
,
160 branch_dev_name
)) == 0) {
161 return DP_PANEL_MODE_SPECIAL
;
164 case DP_BRANCH_DEVICE_ID_3
:
165 if (strncmp(link
->dpcd_caps
.branch_dev_name
,
166 DP_VGA_LVDS_CONVERTER_ID_3
,
169 branch_dev_name
)) == 0) {
170 return DP_PANEL_MODE_SPECIAL
;
177 if (link
->dpcd_caps
.panel_mode_edp
) {
178 return DP_PANEL_MODE_EDP
;
182 return DP_PANEL_MODE_DEFAULT
;
185 void dp_set_hw_test_pattern(
186 struct core_link
*link
,
187 enum dp_test_pattern test_pattern
,
188 uint8_t *custom_pattern
,
189 uint32_t custom_pattern_size
)
191 struct encoder_set_dp_phy_pattern_param pattern_param
= {0};
192 struct link_encoder
*encoder
= link
->link_enc
;
194 pattern_param
.dp_phy_pattern
= test_pattern
;
195 pattern_param
.custom_pattern
= custom_pattern
;
196 pattern_param
.custom_pattern_size
= custom_pattern_size
;
197 pattern_param
.dp_panel_mode
= dp_get_panel_mode(link
);
199 encoder
->funcs
->dp_set_phy_pattern(encoder
, &pattern_param
);
203 void dp_retrain_link(struct core_link
*link
)
205 struct pipe_ctx
*pipes
= link
->dc
->current_context
->res_ctx
.pipe_ctx
;
208 for (i
= 0; i
< MAX_PIPES
; i
++) {
209 if (pipes
[i
].stream_enc
!= NULL
) {
210 dm_delay_in_microseconds(link
->ctx
, 100);
211 pipes
->stream_enc
->funcs
->dp_blank(pipes
[i
].stream_enc
);
212 link
->dc
->hwss
.disable_stream(&pipes
[i
]);
213 dc_link_dp_perform_link_training(
215 &link
->public.verified_link_cap
,
217 link
->dc
->hwss
.enable_stream(&pipes
[i
]);
218 link
->dc
->hwss
.unblank_stream(&pipes
[i
],
219 &link
->public.verified_link_cap
);