1 /*
2 * Copyright 2023 Advanced Micro Devices, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: AMD
23 *
24 */
25
26 /* FILE POLICY AND INTENDED USAGE:
27 * This file owns the creation/destruction of link structure.
28 */
29 #include "link_factory.h"
30 #include "link_detection.h"
31 #include "link_resource.h"
32 #include "link_validation.h"
33 #include "link_dpms.h"
34 #include "accessories/link_dp_cts.h"
35 #include "accessories/link_dp_trace.h"
36 #include "protocols/link_ddc.h"
37 #include "protocols/link_dp_capability.h"
38 #include "protocols/link_dp_dpia_bw.h"
39 #include "protocols/link_dp_dpia.h"
40 #include "protocols/link_dp_irq_handler.h"
41 #include "protocols/link_dp_phy.h"
42 #include "protocols/link_dp_training.h"
43 #include "protocols/link_edp_panel_control.h"
44 #include "protocols/link_dp_panel_replay.h"
45 #include "protocols/link_hdmi_frl.h"
46 #include "protocols/link_hpd.h"
47 #include "gpio_service_interface.h"
48 #include "atomfirmware.h"
49
50 #define DC_LOGGER \
51 dc_ctx->logger
52 #define DC_LOGGER_INIT(logger)
53
54 #define LINK_INFO(...) \
55 DC_LOG_HW_HOTPLUG( \
56 __VA_ARGS__)
57
58 /* link factory owns the creation/destruction of link structures. */
construct_link_service_factory(struct link_service * link_srv)59 static void construct_link_service_factory(struct link_service *link_srv)
60 {
61
62 link_srv->create_link = link_create;
63 link_srv->destroy_link = link_destroy;
64 }
65
66 /* link_detection manages link detection states and receiver states by using
67 * various link protocols. It also provides helper functions to interpret
68 * certain capabilities or status based on the states it manages or retrieve
69 * them directly from connected receivers.
70 */
construct_link_service_detection(struct link_service * link_srv)71 static void construct_link_service_detection(struct link_service *link_srv)
72 {
73 link_srv->detect_link = link_detect;
74 link_srv->detect_connection_type = link_detect_connection_type;
75 link_srv->add_remote_sink = link_add_remote_sink;
76 link_srv->remove_remote_sink = link_remove_remote_sink;
77 link_srv->get_hpd_state = link_get_hpd_state;
78 link_srv->enable_hpd = link_enable_hpd;
79 link_srv->disable_hpd = link_disable_hpd;
80 link_srv->enable_hpd_filter = link_enable_hpd_filter;
81 link_srv->reset_cur_dp_mst_topology = link_reset_cur_dp_mst_topology;
82 link_srv->get_status = link_get_status;
83 link_srv->is_hdcp1x_supported = link_is_hdcp14;
84 link_srv->is_hdcp2x_supported = link_is_hdcp22;
85 link_srv->clear_dprx_states = link_clear_dprx_states;
86 }
87
88 /* link resource implements accessors to link resource. */
construct_link_service_resource(struct link_service * link_srv)89 static void construct_link_service_resource(struct link_service *link_srv)
90 {
91 link_srv->get_cur_res_map = link_get_cur_res_map;
92 link_srv->restore_res_map = link_restore_res_map;
93 link_srv->get_cur_link_res = link_get_cur_link_res;
94 }
95
96 /* link validation owns timing validation against various link limitations. (ex.
97 * link bandwidth, receiver capability or our hardware capability) It also
98 * provides helper functions exposing bandwidth formulas used in validation.
99 */
construct_link_service_validation(struct link_service * link_srv)100 static void construct_link_service_validation(struct link_service *link_srv)
101 {
102 link_srv->validate_mode_timing = link_validate_mode_timing;
103 link_srv->dp_link_bandwidth_kbps = dp_link_bandwidth_kbps;
104 link_srv->validate_dp_tunnel_bandwidth = link_validate_dp_tunnel_bandwidth;
105 link_srv->frl_link_bandwidth_kbps = frl_link_bandwidth_kbps;
106 link_srv->frl_margin_check_uncompressed_video = frl_capacity_computations_uncompressed_video;
107 link_srv->dp_required_hblank_size_bytes = dp_required_hblank_size_bytes;
108 }
109
110 /* link dpms owns the programming sequence of stream's dpms state associated
111 * with the link and link's enable/disable sequences as result of the stream's
112 * dpms state change.
113 */
construct_link_service_dpms(struct link_service * link_srv)114 static void construct_link_service_dpms(struct link_service *link_srv)
115 {
116 link_srv->set_dpms_on = link_set_dpms_on;
117 link_srv->set_dpms_off = link_set_dpms_off;
118 link_srv->resume = link_resume;
119 link_srv->blank_all_dp_displays = link_blank_all_dp_displays;
120 link_srv->blank_all_edp_displays = link_blank_all_edp_displays;
121 link_srv->blank_dp_stream = link_blank_dp_stream;
122 link_srv->increase_mst_payload = link_increase_mst_payload;
123 link_srv->reduce_mst_payload = link_reduce_mst_payload;
124 link_srv->set_dsc_on_stream = link_set_dsc_on_stream;
125 link_srv->set_dsc_enable = link_set_dsc_enable;
126 link_srv->update_dsc_config = link_update_dsc_config;
127 link_srv->wait_for_unlocked = link_wait_for_unlocked;
128 }
129
130 /* link ddc implements generic display communication protocols such as i2c, aux
131 * and scdc. It should not contain any specific applications of these
132 * protocols such as display capability query, detection, or handshaking such as
133 * link training.
134 */
construct_link_service_ddc(struct link_service * link_srv)135 static void construct_link_service_ddc(struct link_service *link_srv)
136 {
137 link_srv->create_ddc_service = link_create_ddc_service;
138 link_srv->destroy_ddc_service = link_destroy_ddc_service;
139 link_srv->query_ddc_data = link_query_ddc_data;
140 link_srv->aux_transfer_raw = link_aux_transfer_raw;
141 link_srv->configure_fixed_vs_pe_retimer = link_configure_fixed_vs_pe_retimer;
142 link_srv->aux_transfer_with_retries_no_mutex =
143 link_aux_transfer_with_retries_no_mutex;
144 link_srv->is_in_aux_transaction_mode = link_is_in_aux_transaction_mode;
145 link_srv->get_aux_defer_delay = link_get_aux_defer_delay;
146 link_srv->get_ddc_aux_inst = link_get_ddc_aux_inst;
147 }
148
149 /* link dp capability implements dp specific link capability retrieval sequence.
150 * It is responsible for retrieving, parsing, overriding, deciding capability
151 * obtained from dp link. Link capability consists of encoders, DPRXs, cables,
152 * retimers, usb and all other possible backend capabilities.
153 */
construct_link_service_dp_capability(struct link_service * link_srv)154 static void construct_link_service_dp_capability(struct link_service *link_srv)
155 {
156 link_srv->dp_is_sink_present = dp_is_sink_present;
157 link_srv->dp_is_fec_supported = dp_is_fec_supported;
158 link_srv->dp_is_128b_132b_signal = dp_is_128b_132b_signal;
159 link_srv->dp_get_max_link_enc_cap = dp_get_max_link_enc_cap;
160 link_srv->dp_get_verified_link_cap = dp_get_verified_link_cap;
161 link_srv->dp_get_encoding_format = link_dp_get_encoding_format;
162 link_srv->dp_should_enable_fec = dp_should_enable_fec;
163 link_srv->dp_decide_link_settings = link_decide_link_settings;
164 link_srv->dp_decide_tunnel_settings = link_decide_dp_tunnel_settings;
165 link_srv->mst_decide_link_encoding_format =
166 mst_decide_link_encoding_format;
167 link_srv->edp_decide_link_settings = edp_decide_link_settings;
168 link_srv->bw_kbps_from_raw_frl_link_rate_data =
169 link_bw_kbps_from_raw_frl_link_rate_data;
170 link_srv->dp_overwrite_extended_receiver_cap =
171 dp_overwrite_extended_receiver_cap;
172 link_srv->dp_decide_lttpr_mode = dp_decide_lttpr_mode;
173 link_srv->dp_get_lttpr_count = dp_get_lttpr_count;
174 link_srv->edp_get_alpm_support = edp_get_alpm_support;
175 }
176
177 /* link dp phy/dpia implements basic dp phy/dpia functionality such as
178 * enable/disable output and set lane/drive settings. It is responsible for
179 * maintaining and update software state representing current phy/dpia status
180 * such as current link settings.
181 */
construct_link_service_dp_phy_or_dpia(struct link_service * link_srv)182 static void construct_link_service_dp_phy_or_dpia(struct link_service *link_srv)
183 {
184 link_srv->dpia_handle_usb4_bandwidth_allocation_for_link =
185 dpia_handle_usb4_bandwidth_allocation_for_link;
186 link_srv->dp_set_drive_settings = dp_set_drive_settings;
187 link_srv->dpcd_write_rx_power_ctrl = dpcd_write_rx_power_ctrl;
188 }
189
190 /* link dp irq handler implements DP HPD short pulse handling sequence according
191 * to DP specifications
192 */
construct_link_service_dp_irq_handler(struct link_service * link_srv)193 static void construct_link_service_dp_irq_handler(struct link_service *link_srv)
194 {
195 link_srv->dp_parse_link_loss_status = dp_parse_link_loss_status;
196 link_srv->dp_should_allow_hpd_rx_irq = dp_should_allow_hpd_rx_irq;
197 link_srv->dp_handle_link_loss = dp_handle_link_loss;
198 link_srv->dp_read_hpd_rx_irq_data = dp_read_hpd_rx_irq_data;
199 link_srv->dp_handle_hpd_rx_irq = dp_handle_hpd_rx_irq;
200 }
201
202 /* link edp panel control implements retrieval and configuration of eDP panel
203 * features such as PSR and ABM and it also manages specs defined eDP panel
204 * power sequences.
205 */
construct_link_service_edp_panel_control(struct link_service * link_srv)206 static void construct_link_service_edp_panel_control(struct link_service *link_srv)
207 {
208 link_srv->edp_panel_backlight_power_on = edp_panel_backlight_power_on;
209 link_srv->edp_get_backlight_level = edp_get_backlight_level;
210 link_srv->edp_get_backlight_level_nits = edp_get_backlight_level_nits;
211 link_srv->edp_set_backlight_level = edp_set_backlight_level;
212 link_srv->edp_set_backlight_level_nits = edp_set_backlight_level_nits;
213 link_srv->edp_get_target_backlight_pwm = edp_get_target_backlight_pwm;
214 link_srv->edp_get_psr_state = edp_get_psr_state;
215 link_srv->edp_set_psr_allow_active = edp_set_psr_allow_active;
216 link_srv->edp_setup_psr = edp_setup_psr;
217 link_srv->edp_set_sink_vtotal_in_psr_active =
218 edp_set_sink_vtotal_in_psr_active;
219 link_srv->edp_get_psr_residency = edp_get_psr_residency;
220
221 link_srv->edp_get_replay_state = edp_get_replay_state;
222 link_srv->edp_set_replay_allow_active = edp_set_replay_allow_active;
223 link_srv->edp_send_replay_cmd = edp_send_replay_cmd;
224 link_srv->edp_set_coasting_vtotal = edp_set_coasting_vtotal;
225 link_srv->edp_replay_residency = edp_replay_residency;
226 link_srv->edp_set_replay_power_opt_and_coasting_vtotal = edp_set_replay_power_opt_and_coasting_vtotal;
227
228 link_srv->edp_wait_for_t12 = edp_wait_for_t12;
229 link_srv->edp_is_ilr_optimization_required =
230 edp_is_ilr_optimization_required;
231 link_srv->edp_backlight_enable_aux = edp_backlight_enable_aux;
232 link_srv->edp_add_delay_for_T9 = edp_add_delay_for_T9;
233 link_srv->edp_receiver_ready_T9 = edp_receiver_ready_T9;
234 link_srv->edp_receiver_ready_T7 = edp_receiver_ready_T7;
235 link_srv->edp_power_alpm_dpcd_enable = edp_power_alpm_dpcd_enable;
236 link_srv->edp_set_panel_power = edp_set_panel_power;
237 }
238
239 /* link dp panel replay implements DP panel replay functionality.
240 */
construct_link_service_dp_panel_replay(struct link_service * link_srv)241 static void construct_link_service_dp_panel_replay(struct link_service *link_srv)
242 {
243 link_srv->dp_setup_replay = dp_setup_replay;
244 link_srv->dp_pr_get_panel_inst = dp_pr_get_panel_inst;
245 link_srv->dp_pr_enable = dp_pr_enable;
246 link_srv->dp_pr_update_state = dp_pr_update_state;
247 link_srv->dp_pr_set_general_cmd = dp_pr_set_general_cmd;
248 link_srv->dp_pr_get_state = dp_pr_get_state;
249 }
250
251 /* link hdmi frl implements FRL link capability and link training related
252 * functions. FRL link is established by order of retrieve_link, verify_link,
253 * and poll_status. Other helper functions exist to obtain information required
254 * to maintain the correct sequence according to HDMI specification. Each
255 * sequence and state inside link training functions are timing sensitive and order sensitive.
256 * It is mandatory that these functions are debugged with FRL_LTP output message
257 * configurable in DSAT. Any changes in the LT sequence should follow the HDMI
258 * specification as much as possible and tested through HDMI electrical and
259 * link layer compliance.
260 */
construct_link_service_hdmi_frl(struct link_service * link_srv)261 static void construct_link_service_hdmi_frl(struct link_service *link_srv)
262 {
263 link_srv->hdmi_frl_poll_status_flag = hdmi_frl_poll_status_flag;
264 link_srv->hdmi_frl_get_verified_link_cap =
265 hdmi_frl_get_verified_link_cap;
266 link_srv->hdmi_frl_set_preferred_link_settings =
267 hdmi_frl_set_preferred_link_settings;
268 }
269
270 /* link dp cts implements dp compliance test automation protocols and manual
271 * testing interfaces for debugging and certification purpose.
272 */
construct_link_service_dp_cts(struct link_service * link_srv)273 static void construct_link_service_dp_cts(struct link_service *link_srv)
274 {
275 link_srv->dp_handle_automated_test = dp_handle_automated_test;
276 link_srv->dp_set_test_pattern = dp_set_test_pattern;
277 link_srv->dp_set_preferred_link_settings =
278 dp_set_preferred_link_settings;
279 link_srv->dp_set_preferred_training_settings =
280 dp_set_preferred_training_settings;
281 }
282
283 /* link dp trace implements tracing interfaces for tracking major dp sequences
284 * including execution status and timestamps
285 */
construct_link_service_dp_trace(struct link_service * link_srv)286 static void construct_link_service_dp_trace(struct link_service *link_srv)
287 {
288 link_srv->dp_trace_is_initialized = dp_trace_is_initialized;
289 link_srv->dp_trace_set_is_logged_flag = dp_trace_set_is_logged_flag;
290 link_srv->dp_trace_is_logged = dp_trace_is_logged;
291 link_srv->dp_trace_get_lt_end_timestamp = dp_trace_get_lt_end_timestamp;
292 link_srv->dp_trace_get_lt_counts = dp_trace_get_lt_counts;
293 link_srv->dp_trace_get_link_loss_count = dp_trace_get_link_loss_count;
294 link_srv->dp_trace_set_edp_power_timestamp =
295 dp_trace_set_edp_power_timestamp;
296 link_srv->dp_trace_get_edp_poweron_timestamp =
297 dp_trace_get_edp_poweron_timestamp;
298 link_srv->dp_trace_get_edp_poweroff_timestamp =
299 dp_trace_get_edp_poweroff_timestamp;
300 link_srv->dp_trace_source_sequence = dp_trace_source_sequence;
301 }
302
construct_link_service(struct link_service * link_srv)303 static void construct_link_service(struct link_service *link_srv)
304 {
305 /* All link service functions should fall under some sub categories.
306 * If a new function doesn't perfectly fall under an existing sub
307 * category, it must be that you are either adding a whole new aspect of
308 * responsibility to link service or something doesn't belong to link
309 * service. In that case please contact the arch owner to arrange a
310 * design review meeting.
311 */
312 construct_link_service_factory(link_srv);
313 construct_link_service_detection(link_srv);
314 construct_link_service_resource(link_srv);
315 construct_link_service_validation(link_srv);
316 construct_link_service_dpms(link_srv);
317 construct_link_service_ddc(link_srv);
318 construct_link_service_dp_capability(link_srv);
319 construct_link_service_dp_phy_or_dpia(link_srv);
320 construct_link_service_dp_irq_handler(link_srv);
321 construct_link_service_edp_panel_control(link_srv);
322 construct_link_service_dp_panel_replay(link_srv);
323 construct_link_service_hdmi_frl(link_srv);
324 construct_link_service_dp_cts(link_srv);
325 construct_link_service_dp_trace(link_srv);
326 }
327
link_create_link_service(void)328 struct link_service *link_create_link_service(void)
329 {
330 struct link_service *link_srv = kzalloc_obj(*link_srv);
331
332 if (link_srv == NULL)
333 goto fail;
334
335 construct_link_service(link_srv);
336
337 return link_srv;
338 fail:
339 return NULL;
340 }
341
link_destroy_link_service(struct link_service ** link_srv)342 void link_destroy_link_service(struct link_service **link_srv)
343 {
344 kfree(*link_srv);
345 *link_srv = NULL;
346 }
347
translate_encoder_to_transmitter(struct graphics_object_id encoder)348 static enum transmitter translate_encoder_to_transmitter(
349 struct graphics_object_id encoder)
350 {
351 switch (encoder.id) {
352 case ENCODER_ID_INTERNAL_UNIPHY:
353 switch (encoder.enum_id) {
354 case ENUM_ID_1:
355 return TRANSMITTER_UNIPHY_A;
356 case ENUM_ID_2:
357 return TRANSMITTER_UNIPHY_B;
358 default:
359 return TRANSMITTER_UNKNOWN;
360 }
361 break;
362 case ENCODER_ID_INTERNAL_UNIPHY1:
363 switch (encoder.enum_id) {
364 case ENUM_ID_1:
365 return TRANSMITTER_UNIPHY_C;
366 case ENUM_ID_2:
367 return TRANSMITTER_UNIPHY_D;
368 default:
369 return TRANSMITTER_UNKNOWN;
370 }
371 break;
372 case ENCODER_ID_INTERNAL_UNIPHY2:
373 switch (encoder.enum_id) {
374 case ENUM_ID_1:
375 return TRANSMITTER_UNIPHY_E;
376 case ENUM_ID_2:
377 return TRANSMITTER_UNIPHY_F;
378 default:
379 return TRANSMITTER_UNKNOWN;
380 }
381 break;
382 case ENCODER_ID_INTERNAL_UNIPHY3:
383 switch (encoder.enum_id) {
384 case ENUM_ID_1:
385 return TRANSMITTER_UNIPHY_G;
386 default:
387 return TRANSMITTER_UNKNOWN;
388 }
389 break;
390 default:
391 return TRANSMITTER_UNKNOWN;
392 }
393 }
394
encoder_is_external_dp(struct graphics_object_id encoder)395 static bool encoder_is_external_dp(
396 struct graphics_object_id encoder)
397 {
398 switch (encoder.id) {
399 case ENCODER_ID_EXTERNAL_NUTMEG:
400 case ENCODER_ID_EXTERNAL_TRAVIS:
401 return true;
402 default:
403 return false;
404 }
405 }
406
link_destruct(struct dc_link * link)407 static void link_destruct(struct dc_link *link)
408 {
409 unsigned int i;
410
411 if (link->ddc)
412 link_destroy_ddc_service(&link->ddc);
413
414 if (link->panel_cntl)
415 link->panel_cntl->funcs->destroy(&link->panel_cntl);
416
417 if (link->link_enc && !link->is_dig_mapping_flexible) {
418 /* Update link encoder resource tracking variables. These are used for
419 * the dynamic assignment of link encoders to streams. Virtual links
420 * are not assigned encoder resources on creation.
421 */
422 if (link->link_id.id != CONNECTOR_ID_VIRTUAL && link->eng_id != ENGINE_ID_UNKNOWN) {
423 link->dc->res_pool->link_encoders[link->eng_id - ENGINE_ID_DIGA] = NULL;
424 link->dc->res_pool->dig_link_enc_count--;
425 }
426 link->link_enc->funcs->destroy(&link->link_enc);
427 }
428
429 if (link->hpo_frl_link_enc)
430 link->hpo_frl_link_enc->funcs->destroy(&link->hpo_frl_link_enc);
431 if (link->local_sink)
432 dc_sink_release(link->local_sink);
433
434 for (i = 0; i < link->sink_count; ++i)
435 dc_sink_release(link->remote_sinks[i]);
436 }
437
get_ddc_line(struct dc_link * link)438 static enum channel_id get_ddc_line(struct dc_link *link)
439 {
440 struct ddc *ddc;
441 enum channel_id channel;
442
443 channel = CHANNEL_ID_UNKNOWN;
444
445 if (link->force_to_use_aux) {
446 channel = link->aux_hw_inst + 1;
447 } else {
448 ddc = get_ddc_pin(link->ddc);
449
450 if (ddc) {
451 switch (dal_ddc_get_line(ddc)) {
452 case GPIO_DDC_LINE_DDC1:
453 channel = CHANNEL_ID_DDC1;
454 break;
455 case GPIO_DDC_LINE_DDC2:
456 channel = CHANNEL_ID_DDC2;
457 break;
458 case GPIO_DDC_LINE_DDC3:
459 channel = CHANNEL_ID_DDC3;
460 break;
461 case GPIO_DDC_LINE_DDC4:
462 channel = CHANNEL_ID_DDC4;
463 break;
464 case GPIO_DDC_LINE_DDC5:
465 channel = CHANNEL_ID_DDC5;
466 break;
467 case GPIO_DDC_LINE_DDC6:
468 channel = CHANNEL_ID_DDC6;
469 break;
470 case GPIO_DDC_LINE_DDC_VGA:
471 channel = CHANNEL_ID_DDC_VGA;
472 break;
473 case GPIO_DDC_LINE_I2C_PAD:
474 channel = CHANNEL_ID_I2C_PAD;
475 break;
476 default:
477 BREAK_TO_DEBUGGER();
478 break;
479 }
480 }
481 }
482 return channel;
483 }
484
find_analog_engine(struct dc_link * link,struct graphics_object_id * enc)485 static enum engine_id find_analog_engine(struct dc_link *link, struct graphics_object_id *enc)
486 {
487 struct dc_bios *bp = link->ctx->dc_bios;
488 enum bp_result bp_result = BP_RESULT_OK;
489 int i;
490
491 for (i = 0; i < 3; i++) {
492 bp_result = bp->funcs->get_src_obj(bp, link->link_id, i, enc);
493
494 if (bp_result != BP_RESULT_OK)
495 return ENGINE_ID_UNKNOWN;
496
497 switch (enc->id) {
498 case ENCODER_ID_INTERNAL_DAC1:
499 case ENCODER_ID_INTERNAL_KLDSCP_DAC1:
500 return ENGINE_ID_DACA;
501 case ENCODER_ID_INTERNAL_DAC2:
502 case ENCODER_ID_INTERNAL_KLDSCP_DAC2:
503 return ENGINE_ID_DACB;
504 }
505 }
506
507 memset(enc, 0, sizeof(*enc));
508 return ENGINE_ID_UNKNOWN;
509 }
510
analog_engine_supported(const enum engine_id engine_id)511 static bool analog_engine_supported(const enum engine_id engine_id)
512 {
513 return engine_id == ENGINE_ID_DACA ||
514 engine_id == ENGINE_ID_DACB;
515 }
516
construct_phy(struct dc_link * link,const struct link_init_data * init_params)517 static bool construct_phy(struct dc_link *link,
518 const struct link_init_data *init_params)
519 {
520 uint8_t i;
521 struct ddc_service_init_data ddc_service_init_data = { 0 };
522 struct dc_context *dc_ctx = init_params->ctx;
523 struct encoder_init_data enc_init_data = { 0 };
524 struct panel_cntl_init_data panel_cntl_init_data = { 0 };
525 struct dc_bios *bios = init_params->dc->ctx->dc_bios;
526 const struct dc_vbios_funcs *bp_funcs = bios->funcs;
527 struct bp_disp_connector_caps_info disp_connect_caps_info = { 0 };
528 struct graphics_object_id link_encoder = { 0 };
529 enum transmitter transmitter_from_encoder;
530 enum engine_id link_analog_engine;
531
532 DC_LOGGER_INIT(dc_ctx->logger);
533
534 link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
535 link->irq_source_hpd_rx = DC_IRQ_SOURCE_INVALID;
536 link->irq_source_read_request = DC_IRQ_SOURCE_INVALID;
537 link->link_status.dpcd_caps = &link->dpcd_caps;
538
539 link->dc = init_params->dc;
540 link->ctx = dc_ctx;
541 link->link_index = init_params->link_index;
542
543 memset(&link->preferred_training_settings, 0,
544 sizeof(struct dc_link_training_overrides));
545 memset(&link->preferred_link_setting, 0,
546 sizeof(struct dc_link_settings));
547
548 link->link_id =
549 bios->funcs->get_connector_id(bios, (uint8_t)init_params->connector_index);
550
551 link->ep_type = DISPLAY_ENDPOINT_PHY;
552
553 DC_LOG_DC("BIOS object table - link_id: %d", link->link_id.id);
554
555 /* Determine early if the link has any supported encoders,
556 * so that we avoid initializing DDC and HPD, etc.
557 */
558 bp_funcs->get_src_obj(bios, link->link_id, 0, &link_encoder);
559
560 if (encoder_is_external_dp(link_encoder)) {
561 /* External DP bridge encoders: find the actual link encoder and use that. */
562 link->ext_enc_id = link_encoder;
563 bp_funcs->get_src_obj(bios, link->ext_enc_id, 0, &link_encoder);
564 }
565
566 transmitter_from_encoder = translate_encoder_to_transmitter(link_encoder);
567 link_analog_engine = find_analog_engine(link, &enc_init_data.analog_encoder);
568
569 if (transmitter_from_encoder == TRANSMITTER_UNKNOWN &&
570 !analog_engine_supported(link_analog_engine)) {
571 DC_LOG_WARNING("link_id %d has unsupported encoder\n", link->link_id.id);
572 goto create_fail;
573 }
574
575 if (bios->funcs->get_disp_connector_caps_info) {
576 bios->funcs->get_disp_connector_caps_info(bios, link->link_id, &disp_connect_caps_info);
577 link->is_internal_display = (disp_connect_caps_info.INTERNAL_DISPLAY != 0);
578 DC_LOG_DC("BIOS object table - is_internal_display: %d", link->is_internal_display);
579 link->no_ddc_pin = disp_connect_caps_info.NO_DDC_PIN != 0;
580 //reworked DP port on N-1 board, for testing on N-1, to be removed when IFWI ready
581 if (link->dc->config.dp_connector_no_native_i2c &&
582 (link->link_id.enum_id == link->dc->config.link_index_with_no_ddc))
583 link->no_ddc_pin = true;
584 link->force_to_use_aux = link->dc->config.dp_connector_no_native_i2c
585 && link->no_ddc_pin;
586 }
587
588 if (link->link_id.type != OBJECT_TYPE_CONNECTOR) {
589 dm_output_to_console("%s: Invalid Connector ObjectID from Adapter Service for connector index:%d! type %d expected %d\n",
590 __func__, init_params->connector_index,
591 link->link_id.type, OBJECT_TYPE_CONNECTOR);
592 goto create_fail;
593 }
594
595 if (link->dc->res_pool->funcs->link_init)
596 link->dc->res_pool->funcs->link_init(link);
597
598 ddc_service_init_data.ctx = link->ctx;
599 ddc_service_init_data.id = link->link_id;
600 ddc_service_init_data.link = link;
601 link->ddc = link_create_ddc_service(&ddc_service_init_data);
602
603 if (!link->ddc) {
604 DC_ERROR("Failed to create ddc_service!\n");
605 goto ddc_create_fail;
606 }
607
608 if (link->force_to_use_aux) {
609 link->ddc_hw_inst = link->aux_hw_inst;
610 } else {
611 /* Embedded display connectors such as LVDS may not have DDC. */
612 if (!link->ddc->ddc_pin &&
613 !dc_is_embedded_signal(link->connector_signal)) {
614 DC_ERROR("Failed to get I2C info for connector!\n");
615 goto ddc_create_fail;
616 }
617
618 link->ddc_hw_inst =
619 dal_ddc_get_line(get_ddc_pin(link->ddc));
620 }
621
622 enc_init_data.ctx = dc_ctx;
623 enc_init_data.connector = link->link_id;
624 enc_init_data.channel = get_ddc_line(link);
625 enc_init_data.transmitter = transmitter_from_encoder;
626 enc_init_data.encoder = link_encoder;
627 enc_init_data.analog_engine = link_analog_engine;
628 if (link->ctx->dce_version <= DCN_VERSION_4_01)
629 enc_init_data.hpd_gpio = link_get_hpd_gpio(link->ctx->dc_bios, link->link_id,
630 link->ctx->gpio_service);
631 else
632 enc_init_data.hpd_gpio = NULL;
633 if (enc_init_data.hpd_gpio) {
634 dal_gpio_open(enc_init_data.hpd_gpio, GPIO_MODE_INTERRUPT);
635 dal_gpio_unlock_pin(enc_init_data.hpd_gpio);
636 link->irq_source_hpd = dal_irq_get_source(enc_init_data.hpd_gpio);
637 enc_init_data.hpd_source = get_hpd_line(link);
638 link->hpd_src = enc_init_data.hpd_source;
639
640 DC_LOG_DC("BIOS object table - hpd_gpio id: %d", enc_init_data.hpd_gpio->id);
641 DC_LOG_DC("BIOS object table - hpd_gpio en: %d", enc_init_data.hpd_gpio->en);
642 } else if (link->ctx->dce_version > DCN_VERSION_4_01) {
643 struct graphics_object_hpd_info hpd_info;
644
645 if (link->ctx->dc_bios->funcs->get_hpd_info(link->ctx->dc_bios, link->link_id, &hpd_info) == BP_RESULT_OK) {
646 link->hpd_src = hpd_info.hpd_int_gpio_uid - 1;
647 link->irq_source_hpd = DC_IRQ_SOURCE_HPD1 + link->hpd_src;
648 enc_init_data.hpd_source = link->hpd_src;
649 enc_init_data.hpd_active_high = (hpd_info.hpd_active == 0) ? true : false;
650 DC_LOG_DC("BIOS object table - hpd_int_gpio_uid id: %d", hpd_info.hpd_int_gpio_uid);
651 } else {
652 ASSERT(0);
653 enc_init_data.hpd_source = HPD_SOURCEID_UNKNOWN;
654 }
655 }
656
657 link->link_enc =
658 link->dc->res_pool->funcs->link_enc_create(dc_ctx, &enc_init_data);
659
660 if (!link->link_enc) {
661 DC_ERROR("Failed to create link encoder!\n");
662 goto link_enc_create_fail;
663 }
664
665 DC_LOG_DC("BIOS object table - DP_IS_USB_C: %d", link->link_enc->features.flags.bits.DP_IS_USB_C);
666 DC_LOG_DC("BIOS object table - IS_DP2_CAPABLE: %d", link->link_enc->features.flags.bits.IS_DP2_CAPABLE);
667 DC_LOG_DC("BIOS object table - IS_HDMI_FRL_CAPABLE: %d", link->link_enc->features.flags.bits.IS_HDMI_FRL_CAPABLE);
668
669 switch (link->link_id.id) {
670 case CONNECTOR_ID_HDMI_TYPE_A:
671 link->connector_signal = SIGNAL_TYPE_HDMI_TYPE_A;
672
673 if (link->link_enc->hpd_gpio)
674 link->irq_source_read_request =
675 dal_irq_get_read_request(link->link_enc->hpd_gpio);
676 else if (link->hpd_src != HPD_SOURCEID_UNKNOWN)
677 link->irq_source_read_request = DC_IRQ_SOURCE_DCI2C_RR_DDC1 + link->hpd_src;
678 break;
679 case CONNECTOR_ID_SINGLE_LINK_DVID:
680 case CONNECTOR_ID_SINGLE_LINK_DVII:
681 link->connector_signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
682 break;
683 case CONNECTOR_ID_DUAL_LINK_DVID:
684 case CONNECTOR_ID_DUAL_LINK_DVII:
685 link->connector_signal = SIGNAL_TYPE_DVI_DUAL_LINK;
686 break;
687 case CONNECTOR_ID_VGA:
688 link->connector_signal = SIGNAL_TYPE_RGB;
689 break;
690 case CONNECTOR_ID_DISPLAY_PORT:
691 case CONNECTOR_ID_MXM:
692 case CONNECTOR_ID_USBC:
693 link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT;
694
695 if (link->link_enc->hpd_gpio)
696 link->irq_source_hpd_rx =
697 dal_irq_get_rx_source(link->link_enc->hpd_gpio);
698 else if (link->hpd_src != HPD_SOURCEID_UNKNOWN)
699 link->irq_source_hpd_rx = DC_IRQ_SOURCE_HPD1RX + link->hpd_src;
700
701 break;
702 case CONNECTOR_ID_EDP:
703 // If smartmux is supported, only create the link on the primary eDP.
704 // Dual eDP is not supported with smartmux.
705 if (!(!link->dc->config.smart_mux_version || dc_ctx->dc_edp_id_count == 0))
706 goto create_fail;
707
708 link->connector_signal = SIGNAL_TYPE_EDP;
709 if (!link->dc->config.allow_edp_hotplug_detection
710 && !is_smartmux_suported(link))
711 link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
712
713 switch (link->dc->config.allow_edp_hotplug_detection) {
714 case HPD_EN_FOR_ALL_EDP:
715 if (link->link_enc->hpd_gpio) {
716 link->irq_source_hpd_rx =
717 dal_irq_get_rx_source(link->link_enc->hpd_gpio);
718 } else if (link->hpd_src != HPD_SOURCEID_UNKNOWN) {
719 link->irq_source_hpd_rx = DC_IRQ_SOURCE_HPD1RX + link->hpd_src;
720 }
721 break;
722 case HPD_EN_FOR_PRIMARY_EDP_ONLY:
723 if (link->link_index == 0) {
724 if (link->link_enc->hpd_gpio) {
725 link->irq_source_hpd_rx =
726 dal_irq_get_rx_source(link->link_enc->hpd_gpio);
727 } else if (link->hpd_src != HPD_SOURCEID_UNKNOWN) {
728 link->irq_source_hpd_rx = DC_IRQ_SOURCE_HPD1RX + link->hpd_src;
729 }
730 } else
731 link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
732 break;
733 case HPD_EN_FOR_SECONDARY_EDP_ONLY:
734 if (link->link_index == 1) {
735 if (link->link_enc->hpd_gpio) {
736 link->irq_source_hpd_rx =
737 dal_irq_get_rx_source(link->link_enc->hpd_gpio);
738 } else if (link->hpd_src != HPD_SOURCEID_UNKNOWN) {
739 link->irq_source_hpd_rx = DC_IRQ_SOURCE_HPD1RX + link->hpd_src;
740 }
741 } else
742 link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
743 break;
744 default:
745 link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
746 break;
747 }
748 break;
749 case CONNECTOR_ID_LVDS:
750 link->connector_signal = SIGNAL_TYPE_LVDS;
751 break;
752 default:
753 DC_LOG_WARNING("Unsupported Connector type:%d!\n",
754 link->link_id.id);
755 goto create_fail;
756 }
757
758 /* For external DP bridge encoders:
759 * Set the connector signal to DisplayPort so that they can work with
760 * the pre-existing code paths for DP without a lot of code churn.
761 */
762 if (link->ext_enc_id.id != ENCODER_ID_UNKNOWN)
763 link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT;
764
765 LINK_INFO("Connector[%d] description: signal: %s\n",
766 init_params->connector_index,
767 signal_type_to_string(link->connector_signal));
768
769 /* Update link encoder tracking variables. These are used for the dynamic
770 * assignment of link encoders to streams.
771 */
772 link->eng_id = link->link_enc->preferred_engine;
773 link->dc->res_pool->link_encoders[link->eng_id - ENGINE_ID_DIGA] = link->link_enc;
774 link->dc->res_pool->dig_link_enc_count++;
775
776 link->link_enc_hw_inst = link->link_enc->transmitter;
777
778 if (link->dc->res_pool->funcs->panel_cntl_create &&
779 (link->link_id.id == CONNECTOR_ID_EDP ||
780 link->link_id.id == CONNECTOR_ID_LVDS)) {
781 panel_cntl_init_data.ctx = dc_ctx;
782 panel_cntl_init_data.inst = panel_cntl_init_data.ctx->dc_edp_id_count;
783 panel_cntl_init_data.eng_id = link->eng_id;
784 link->panel_cntl =
785 link->dc->res_pool->funcs->panel_cntl_create(
786 &panel_cntl_init_data);
787 panel_cntl_init_data.ctx->dc_edp_id_count++;
788
789 if (link->panel_cntl == NULL) {
790 DC_ERROR("Failed to create link panel_cntl!\n");
791 goto panel_cntl_create_fail;
792 }
793 }
794 for (i = 0; i < 4; i++) {
795 if (bp_funcs->get_device_tag(dc_ctx->dc_bios,
796 link->link_id, i,
797 &link->device_tag) != BP_RESULT_OK) {
798 DC_ERROR("Failed to find device tag!\n");
799 goto device_tag_fail;
800 }
801
802 /* Look for device tag that matches connector signal,
803 * CRT for rgb, LCD for other supported signal types
804 */
805 if (!bp_funcs->is_device_id_supported(dc_ctx->dc_bios,
806 link->device_tag.dev_id))
807 continue;
808 if (link->device_tag.dev_id.device_type == DEVICE_TYPE_CRT &&
809 link->connector_signal != SIGNAL_TYPE_RGB &&
810 link->ext_enc_id.id == ENCODER_ID_UNKNOWN)
811 continue;
812 if (link->device_tag.dev_id.device_type == DEVICE_TYPE_LCD &&
813 link->connector_signal == SIGNAL_TYPE_RGB)
814 continue;
815
816 DC_LOG_DC("BIOS object table - device_tag.acpi_device: %d", link->device_tag.acpi_device);
817 DC_LOG_DC("BIOS object table - device_tag.dev_id.device_type: %d", link->device_tag.dev_id.device_type);
818 DC_LOG_DC("BIOS object table - device_tag.dev_id.enum_id: %d", link->device_tag.dev_id.enum_id);
819 break;
820 }
821
822 if (bios->integrated_info) {
823 /* Look for channel mapping corresponding to connector and device tag */
824 for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; i++) {
825 struct external_display_path *path =
826 &bios->integrated_info->ext_disp_conn_info.path[i];
827
828 if (path->device_connector_id.enum_id == link->link_id.enum_id &&
829 path->device_connector_id.id == link->link_id.id &&
830 path->device_connector_id.type == link->link_id.type) {
831 if (link->device_tag.acpi_device != 0 &&
832 path->device_acpi_enum == link->device_tag.acpi_device) {
833 link->ddi_channel_mapping = path->channel_mapping;
834 link->chip_caps = path->caps;
835 DC_LOG_DC("BIOS object table - ddi_channel_mapping: 0x%04X",
836 link->ddi_channel_mapping.raw);
837 DC_LOG_DC("BIOS object table - chip_caps: %d",
838 link->chip_caps);
839 } else if (path->device_tag ==
840 link->device_tag.dev_id.raw_device_tag) {
841 link->ddi_channel_mapping = path->channel_mapping;
842 link->chip_caps = path->caps;
843 DC_LOG_DC("BIOS object table - ddi_channel_mapping: 0x%04X",
844 link->ddi_channel_mapping.raw);
845 DC_LOG_DC("BIOS object table - chip_caps: %d",
846 link->chip_caps);
847 }
848
849 if ((link->chip_caps & AMD_EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK) == AMD_EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) {
850 link->bios_forced_drive_settings.VOLTAGE_SWING =
851 (bios->integrated_info->ext_disp_conn_info.fixdpvoltageswing & 0x3);
852 link->bios_forced_drive_settings.PRE_EMPHASIS =
853 ((bios->integrated_info->ext_disp_conn_info.fixdpvoltageswing >> 2) & 0x3);
854 }
855
856 break;
857 }
858 }
859 }
860 if (bios->funcs->get_atom_dc_golden_table)
861 bios->funcs->get_atom_dc_golden_table(bios);
862
863 /*
864 * TODO check if GPIO programmed correctly
865 *
866 * If GPIO isn't programmed correctly HPD might not rise or drain
867 * fast enough, leading to bounces.
868 */
869 program_hpd_filter(link);
870
871 /* If the connector is HDMI FRL capable, also create an HPO link encoder */
872 if ((link->link_enc->features.flags.bits.IS_HDMI_FRL_CAPABLE) &&
873 (!link->link_enc->features.flags.bits.DP_IS_USB_C) &&
874 (link->dc->res_pool->funcs->hpo_frl_link_enc_create)) {
875 enum engine_id hpo_eng_id;
876 hpo_eng_id = ENGINE_ID_HPO_0;
877
878 link->hpo_frl_link_enc = link->dc->res_pool->funcs->hpo_frl_link_enc_create(
879 hpo_eng_id,
880 dc_ctx);
881 if (link->hpo_frl_link_enc == NULL) {
882 DC_ERROR("Failed to create HPO link encoder!\n");
883 goto hpo_enc_create_fail;
884 }
885 }
886
887 link->psr_settings.psr_vtotal_control_support = false;
888 link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED;
889 link->replay_settings.config.replay_version = DC_REPLAY_VERSION_UNSUPPORTED;
890
891 DC_LOG_DC("BIOS object table - %s finished successfully.\n", __func__);
892 return true;
893 hpo_enc_create_fail:
894 device_tag_fail:
895 link_enc_create_fail:
896 panel_cntl_create_fail:
897 ddc_create_fail:
898 create_fail:
899 if (link->ddc)
900 link_destroy_ddc_service(&link->ddc);
901 if (link->panel_cntl)
902 link->panel_cntl->funcs->destroy(&link->panel_cntl);
903 if (link->link_enc)
904 link->link_enc->funcs->destroy(&link->link_enc);
905
906 DC_LOG_DC("BIOS object table - %s failed.\n", __func__);
907 return false;
908 }
909
construct_dpia(struct dc_link * link,const struct link_init_data * init_params)910 static bool construct_dpia(struct dc_link *link,
911 const struct link_init_data *init_params)
912 {
913 struct ddc_service_init_data ddc_service_init_data = { 0 };
914 struct dc_context *dc_ctx = init_params->ctx;
915
916 DC_LOGGER_INIT(dc_ctx->logger);
917
918 /* Initialized irq source for hpd and hpd rx */
919 link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
920 link->irq_source_hpd_rx = DC_IRQ_SOURCE_INVALID;
921 link->link_status.dpcd_caps = &link->dpcd_caps;
922
923 link->dc = init_params->dc;
924 link->ctx = dc_ctx;
925 link->link_index = init_params->link_index;
926
927 memset(&link->preferred_training_settings, 0,
928 sizeof(struct dc_link_training_overrides));
929 memset(&link->preferred_link_setting, 0,
930 sizeof(struct dc_link_settings));
931
932 /* Dummy Init for linkid */
933 link->link_id.type = OBJECT_TYPE_CONNECTOR;
934 link->link_id.id = CONNECTOR_ID_DISPLAY_PORT;
935 link->link_id.enum_id = ENUM_ID_1 + init_params->connector_index;
936 link->is_internal_display = false;
937 link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT;
938 LINK_INFO("Connector[%d] description:signal %d\n",
939 init_params->connector_index,
940 link->connector_signal);
941
942 link->ep_type = DISPLAY_ENDPOINT_USB4_DPIA;
943 link->is_dig_mapping_flexible = true;
944
945 /* TODO: Initialize link : funcs->link_init */
946
947 ddc_service_init_data.ctx = link->ctx;
948 ddc_service_init_data.id = link->link_id;
949 ddc_service_init_data.link = link;
950 /* Set indicator for dpia link so that ddc wont be created */
951 ddc_service_init_data.is_dpia_link = true;
952
953 link->ddc = link_create_ddc_service(&ddc_service_init_data);
954 if (!link->ddc) {
955 DC_ERROR("Failed to create ddc_service!\n");
956 goto ddc_create_fail;
957 }
958
959 /* Set dpia port index : 0 to number of dpia ports */
960 link->ddc_hw_inst = (uint8_t)init_params->connector_index;
961
962 // Assign Dpia preferred eng_id
963 if (link->dc->res_pool->funcs->get_preferred_eng_id_dpia)
964 link->dpia_preferred_eng_id = link->dc->res_pool->funcs->get_preferred_eng_id_dpia(link->ddc_hw_inst);
965
966 /* TODO: Create link encoder */
967
968 link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED;
969 link->replay_settings.config.replay_version = DC_REPLAY_VERSION_UNSUPPORTED;
970
971 return true;
972
973 ddc_create_fail:
974 return false;
975 }
976
link_construct(struct dc_link * link,const struct link_init_data * init_params)977 static bool link_construct(struct dc_link *link,
978 const struct link_init_data *init_params)
979 {
980 /* Handle dpia case */
981 if (init_params->is_dpia_link == true)
982 return construct_dpia(link, init_params);
983 else
984 return construct_phy(link, init_params);
985 }
986
link_create(const struct link_init_data * init_params)987 struct dc_link *link_create(const struct link_init_data *init_params)
988 {
989 struct dc_link *link = kzalloc_obj(*link);
990
991 if (NULL == link)
992 goto alloc_fail;
993
994 if (false == link_construct(link, init_params))
995 goto construct_fail;
996
997 return link;
998
999 construct_fail:
1000 kfree(link);
1001
1002 alloc_fail:
1003 return NULL;
1004 }
1005
link_destroy(struct dc_link ** link)1006 void link_destroy(struct dc_link **link)
1007 {
1008 link_destruct(*link);
1009 kfree(*link);
1010 *link = NULL;
1011 }
1012