xref: /linux/drivers/gpu/drm/amd/display/dc/link/link_factory.c (revision cbb8e2044b9e936dfa66f1d4a2f835316c741a67)
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. */
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  */
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. */
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  */
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  */
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  */
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 }
147 
148 /* link dp capability implements dp specific link capability retrieval sequence.
149  * It is responsible for retrieving, parsing, overriding, deciding capability
150  * obtained from dp link. Link capability consists of encoders, DPRXs, cables,
151  * retimers, usb and all other possible backend capabilities.
152  */
153 static void construct_link_service_dp_capability(struct link_service *link_srv)
154 {
155 	link_srv->dp_is_sink_present = dp_is_sink_present;
156 	link_srv->dp_is_fec_supported = dp_is_fec_supported;
157 	link_srv->dp_is_128b_132b_signal = dp_is_128b_132b_signal;
158 	link_srv->dp_get_max_link_enc_cap = dp_get_max_link_enc_cap;
159 	link_srv->dp_get_verified_link_cap = dp_get_verified_link_cap;
160 	link_srv->dp_get_encoding_format = link_dp_get_encoding_format;
161 	link_srv->dp_should_enable_fec = dp_should_enable_fec;
162 	link_srv->dp_decide_link_settings = link_decide_link_settings;
163 	link_srv->dp_decide_tunnel_settings = link_decide_dp_tunnel_settings;
164 	link_srv->mst_decide_link_encoding_format =
165 			mst_decide_link_encoding_format;
166 	link_srv->edp_decide_link_settings = edp_decide_link_settings;
167 	link_srv->bw_kbps_from_raw_frl_link_rate_data =
168 			link_bw_kbps_from_raw_frl_link_rate_data;
169 	link_srv->dp_overwrite_extended_receiver_cap =
170 			dp_overwrite_extended_receiver_cap;
171 	link_srv->dp_decide_lttpr_mode = dp_decide_lttpr_mode;
172 	link_srv->dp_get_lttpr_count = dp_get_lttpr_count;
173 	link_srv->edp_get_alpm_support = edp_get_alpm_support;
174 }
175 
176 /* link dp phy/dpia implements basic dp phy/dpia functionality such as
177  * enable/disable output and set lane/drive settings. It is responsible for
178  * maintaining and update software state representing current phy/dpia status
179  * such as current link settings.
180  */
181 static void construct_link_service_dp_phy_or_dpia(struct link_service *link_srv)
182 {
183 	link_srv->dpia_handle_usb4_bandwidth_allocation_for_link =
184 			dpia_handle_usb4_bandwidth_allocation_for_link;
185 	link_srv->dp_set_drive_settings = dp_set_drive_settings;
186 	link_srv->dpcd_write_rx_power_ctrl = dpcd_write_rx_power_ctrl;
187 }
188 
189 /* link dp irq handler implements DP HPD short pulse handling sequence according
190  * to DP specifications
191  */
192 static void construct_link_service_dp_irq_handler(struct link_service *link_srv)
193 {
194 	link_srv->dp_parse_link_loss_status = dp_parse_link_loss_status;
195 	link_srv->dp_should_allow_hpd_rx_irq = dp_should_allow_hpd_rx_irq;
196 	link_srv->dp_handle_link_loss = dp_handle_link_loss;
197 	link_srv->dp_read_hpd_rx_irq_data = dp_read_hpd_rx_irq_data;
198 	link_srv->dp_handle_hpd_rx_irq = dp_handle_hpd_rx_irq;
199 }
200 
201 /* link edp panel control implements retrieval and configuration of eDP panel
202  * features such as PSR and ABM and it also manages specs defined eDP panel
203  * power sequences.
204  */
205 static void construct_link_service_edp_panel_control(struct link_service *link_srv)
206 {
207 	link_srv->edp_panel_backlight_power_on = edp_panel_backlight_power_on;
208 	link_srv->edp_get_backlight_level = edp_get_backlight_level;
209 	link_srv->edp_get_backlight_level_nits = edp_get_backlight_level_nits;
210 	link_srv->edp_set_backlight_level = edp_set_backlight_level;
211 	link_srv->edp_set_backlight_level_nits = edp_set_backlight_level_nits;
212 	link_srv->edp_get_target_backlight_pwm = edp_get_target_backlight_pwm;
213 	link_srv->edp_get_psr_state = edp_get_psr_state;
214 	link_srv->edp_set_psr_allow_active = edp_set_psr_allow_active;
215 	link_srv->edp_setup_psr = edp_setup_psr;
216 	link_srv->edp_set_sink_vtotal_in_psr_active =
217 			edp_set_sink_vtotal_in_psr_active;
218 	link_srv->edp_get_psr_residency = edp_get_psr_residency;
219 
220 	link_srv->edp_get_replay_state = edp_get_replay_state;
221 	link_srv->edp_set_replay_allow_active = edp_set_replay_allow_active;
222 	link_srv->edp_send_replay_cmd = edp_send_replay_cmd;
223 	link_srv->edp_set_coasting_vtotal = edp_set_coasting_vtotal;
224 	link_srv->edp_replay_residency = edp_replay_residency;
225 	link_srv->edp_set_replay_power_opt_and_coasting_vtotal = edp_set_replay_power_opt_and_coasting_vtotal;
226 
227 	link_srv->edp_wait_for_t12 = edp_wait_for_t12;
228 	link_srv->edp_is_ilr_optimization_required =
229 			edp_is_ilr_optimization_required;
230 	link_srv->edp_backlight_enable_aux = edp_backlight_enable_aux;
231 	link_srv->edp_add_delay_for_T9 = edp_add_delay_for_T9;
232 	link_srv->edp_receiver_ready_T9 = edp_receiver_ready_T9;
233 	link_srv->edp_receiver_ready_T7 = edp_receiver_ready_T7;
234 	link_srv->edp_power_alpm_dpcd_enable = edp_power_alpm_dpcd_enable;
235 	link_srv->edp_set_panel_power = edp_set_panel_power;
236 }
237 
238 /* link dp panel replay implements DP panel replay functionality.
239  */
240 static void construct_link_service_dp_panel_replay(struct link_service *link_srv)
241 {
242 	link_srv->dp_setup_replay = dp_setup_replay;
243 	link_srv->dp_pr_get_panel_inst = dp_pr_get_panel_inst;
244 	link_srv->dp_pr_enable = dp_pr_enable;
245 	link_srv->dp_pr_update_state = dp_pr_update_state;
246 	link_srv->dp_pr_set_general_cmd = dp_pr_set_general_cmd;
247 	link_srv->dp_pr_get_state = dp_pr_get_state;
248 }
249 
250 /* link hdmi frl implements FRL link capability and link training related
251  * functions. FRL link is established by order of retrieve_link, verify_link,
252  * and poll_status. Other helper functions exist to obtain information required
253  * to maintain the correct sequence according to HDMI specification. Each
254  * sequence and state inside link training functions are timing sensitive and order sensitive.
255  * It is mandatory that these functions are debugged with FRL_LTP output message
256  * configurable in DSAT.  Any changes in the LT sequence should follow the HDMI
257  * specification as much as possible and tested through HDMI electrical and
258  * link layer compliance.
259  */
260 static void construct_link_service_hdmi_frl(struct link_service *link_srv)
261 {
262 	link_srv->hdmi_frl_poll_status_flag = hdmi_frl_poll_status_flag;
263 	link_srv->hdmi_frl_get_verified_link_cap =
264 			hdmi_frl_get_verified_link_cap;
265 	link_srv->hdmi_frl_set_preferred_link_settings =
266 			hdmi_frl_set_preferred_link_settings;
267 }
268 
269 /* link dp cts implements dp compliance test automation protocols and manual
270  * testing interfaces for debugging and certification purpose.
271  */
272 static void construct_link_service_dp_cts(struct link_service *link_srv)
273 {
274 	link_srv->dp_handle_automated_test = dp_handle_automated_test;
275 	link_srv->dp_set_test_pattern = dp_set_test_pattern;
276 	link_srv->dp_set_preferred_link_settings =
277 			dp_set_preferred_link_settings;
278 	link_srv->dp_set_preferred_training_settings =
279 			dp_set_preferred_training_settings;
280 }
281 
282 /* link dp trace implements tracing interfaces for tracking major dp sequences
283  * including execution status and timestamps
284  */
285 static void construct_link_service_dp_trace(struct link_service *link_srv)
286 {
287 	link_srv->dp_trace_is_initialized = dp_trace_is_initialized;
288 	link_srv->dp_trace_set_is_logged_flag = dp_trace_set_is_logged_flag;
289 	link_srv->dp_trace_is_logged = dp_trace_is_logged;
290 	link_srv->dp_trace_get_lt_end_timestamp = dp_trace_get_lt_end_timestamp;
291 	link_srv->dp_trace_get_lt_counts = dp_trace_get_lt_counts;
292 	link_srv->dp_trace_get_link_loss_count = dp_trace_get_link_loss_count;
293 	link_srv->dp_trace_set_edp_power_timestamp =
294 			dp_trace_set_edp_power_timestamp;
295 	link_srv->dp_trace_get_edp_poweron_timestamp =
296 			dp_trace_get_edp_poweron_timestamp;
297 	link_srv->dp_trace_get_edp_poweroff_timestamp =
298 			dp_trace_get_edp_poweroff_timestamp;
299 	link_srv->dp_trace_source_sequence = dp_trace_source_sequence;
300 }
301 
302 static void construct_link_service(struct link_service *link_srv)
303 {
304 	/* All link service functions should fall under some sub categories.
305 	 * If a new function doesn't perfectly fall under an existing sub
306 	 * category, it must be that you are either adding a whole new aspect of
307 	 * responsibility to link service or something doesn't belong to link
308 	 * service. In that case please contact the arch owner to arrange a
309 	 * design review meeting.
310 	 */
311 	construct_link_service_factory(link_srv);
312 	construct_link_service_detection(link_srv);
313 	construct_link_service_resource(link_srv);
314 	construct_link_service_validation(link_srv);
315 	construct_link_service_dpms(link_srv);
316 	construct_link_service_ddc(link_srv);
317 	construct_link_service_dp_capability(link_srv);
318 	construct_link_service_dp_phy_or_dpia(link_srv);
319 	construct_link_service_dp_irq_handler(link_srv);
320 	construct_link_service_edp_panel_control(link_srv);
321 	construct_link_service_dp_panel_replay(link_srv);
322 	construct_link_service_hdmi_frl(link_srv);
323 	construct_link_service_dp_cts(link_srv);
324 	construct_link_service_dp_trace(link_srv);
325 }
326 
327 struct link_service *link_create_link_service(void)
328 {
329 	struct link_service *link_srv = kzalloc_obj(*link_srv);
330 
331 	if (link_srv == NULL)
332 		goto fail;
333 
334 	construct_link_service(link_srv);
335 
336 	return link_srv;
337 fail:
338 	return NULL;
339 }
340 
341 void link_destroy_link_service(struct link_service **link_srv)
342 {
343 	kfree(*link_srv);
344 	*link_srv = NULL;
345 }
346 
347 static enum transmitter translate_encoder_to_transmitter(
348 		struct graphics_object_id encoder)
349 {
350 	switch (encoder.id) {
351 	case ENCODER_ID_INTERNAL_UNIPHY:
352 		switch (encoder.enum_id) {
353 		case ENUM_ID_1:
354 			return TRANSMITTER_UNIPHY_A;
355 		case ENUM_ID_2:
356 			return TRANSMITTER_UNIPHY_B;
357 		default:
358 			return TRANSMITTER_UNKNOWN;
359 		}
360 	break;
361 	case ENCODER_ID_INTERNAL_UNIPHY1:
362 		switch (encoder.enum_id) {
363 		case ENUM_ID_1:
364 			return TRANSMITTER_UNIPHY_C;
365 		case ENUM_ID_2:
366 			return TRANSMITTER_UNIPHY_D;
367 		default:
368 			return TRANSMITTER_UNKNOWN;
369 		}
370 	break;
371 	case ENCODER_ID_INTERNAL_UNIPHY2:
372 		switch (encoder.enum_id) {
373 		case ENUM_ID_1:
374 			return TRANSMITTER_UNIPHY_E;
375 		case ENUM_ID_2:
376 			return TRANSMITTER_UNIPHY_F;
377 		default:
378 			return TRANSMITTER_UNKNOWN;
379 		}
380 	break;
381 	case ENCODER_ID_INTERNAL_UNIPHY3:
382 		switch (encoder.enum_id) {
383 		case ENUM_ID_1:
384 			return TRANSMITTER_UNIPHY_G;
385 		default:
386 			return TRANSMITTER_UNKNOWN;
387 		}
388 	break;
389 	default:
390 		return TRANSMITTER_UNKNOWN;
391 	}
392 }
393 
394 static bool encoder_is_external_dp(
395 		struct graphics_object_id encoder)
396 {
397 	switch (encoder.id) {
398 	case ENCODER_ID_EXTERNAL_NUTMEG:
399 	case ENCODER_ID_EXTERNAL_TRAVIS:
400 		return true;
401 	default:
402 		return false;
403 	}
404 }
405 
406 static void link_destruct(struct dc_link *link)
407 {
408 	unsigned int i;
409 
410 	if (link->ddc)
411 		link_destroy_ddc_service(&link->ddc);
412 
413 	if (link->panel_cntl)
414 		link->panel_cntl->funcs->destroy(&link->panel_cntl);
415 
416 	if (link->link_enc && !link->is_dig_mapping_flexible) {
417 		/* Update link encoder resource tracking variables. These are used for
418 		 * the dynamic assignment of link encoders to streams. Virtual links
419 		 * are not assigned encoder resources on creation.
420 		 */
421 		if (link->link_id.id != CONNECTOR_ID_VIRTUAL && link->eng_id != ENGINE_ID_UNKNOWN) {
422 			link->dc->res_pool->link_encoders[link->eng_id - ENGINE_ID_DIGA] = NULL;
423 			link->dc->res_pool->dig_link_enc_count--;
424 		}
425 		link->link_enc->funcs->destroy(&link->link_enc);
426 	}
427 
428 	if (link->hpo_frl_link_enc)
429 		link->hpo_frl_link_enc->funcs->destroy(&link->hpo_frl_link_enc);
430 	if (link->local_sink)
431 		dc_sink_release(link->local_sink);
432 
433 	for (i = 0; i < link->sink_count; ++i)
434 		dc_sink_release(link->remote_sinks[i]);
435 }
436 
437 static enum channel_id get_ddc_line(struct dc_link *link)
438 {
439 	struct ddc *ddc;
440 	enum channel_id channel;
441 
442 	channel = CHANNEL_ID_UNKNOWN;
443 
444 	if (link->ctx->dc->config.dp_connector_no_native_i2c && link->no_ddc_pin) {
445 		channel = link->aux_hw_inst + 1;
446 	} else {
447 		ddc = get_ddc_pin(link->ddc);
448 
449 		if (ddc) {
450 			switch (dal_ddc_get_line(ddc)) {
451 			case GPIO_DDC_LINE_DDC1:
452 				channel = CHANNEL_ID_DDC1;
453 				break;
454 			case GPIO_DDC_LINE_DDC2:
455 				channel = CHANNEL_ID_DDC2;
456 				break;
457 			case GPIO_DDC_LINE_DDC3:
458 				channel = CHANNEL_ID_DDC3;
459 				break;
460 			case GPIO_DDC_LINE_DDC4:
461 				channel = CHANNEL_ID_DDC4;
462 				break;
463 			case GPIO_DDC_LINE_DDC5:
464 				channel = CHANNEL_ID_DDC5;
465 				break;
466 			case GPIO_DDC_LINE_DDC6:
467 				channel = CHANNEL_ID_DDC6;
468 				break;
469 			case GPIO_DDC_LINE_DDC_VGA:
470 				channel = CHANNEL_ID_DDC_VGA;
471 				break;
472 			case GPIO_DDC_LINE_I2C_PAD:
473 				channel = CHANNEL_ID_I2C_PAD;
474 				break;
475 			default:
476 				BREAK_TO_DEBUGGER();
477 				break;
478 			}
479 		}
480 	}
481 	return channel;
482 }
483 
484 static enum engine_id find_analog_engine(struct dc_link *link, struct graphics_object_id *enc)
485 {
486 	struct dc_bios *bp = link->ctx->dc_bios;
487 	enum bp_result bp_result = BP_RESULT_OK;
488 	int i;
489 
490 	for (i = 0; i < 3; i++) {
491 		bp_result = bp->funcs->get_src_obj(bp, link->link_id, i, enc);
492 
493 		if (bp_result != BP_RESULT_OK)
494 			return ENGINE_ID_UNKNOWN;
495 
496 		switch (enc->id) {
497 		case ENCODER_ID_INTERNAL_DAC1:
498 		case ENCODER_ID_INTERNAL_KLDSCP_DAC1:
499 			return ENGINE_ID_DACA;
500 		case ENCODER_ID_INTERNAL_DAC2:
501 		case ENCODER_ID_INTERNAL_KLDSCP_DAC2:
502 			return ENGINE_ID_DACB;
503 		}
504 	}
505 
506 	memset(enc, 0, sizeof(*enc));
507 	return ENGINE_ID_UNKNOWN;
508 }
509 
510 static bool analog_engine_supported(const enum engine_id engine_id)
511 {
512 	return engine_id == ENGINE_ID_DACA ||
513 		engine_id == ENGINE_ID_DACB;
514 }
515 
516 static bool construct_phy(struct dc_link *link,
517 			      const struct link_init_data *init_params)
518 {
519 	uint8_t i;
520 	struct ddc_service_init_data ddc_service_init_data = { 0 };
521 	struct dc_context *dc_ctx = init_params->ctx;
522 	struct encoder_init_data enc_init_data = { 0 };
523 	struct panel_cntl_init_data panel_cntl_init_data = { 0 };
524 	struct dc_bios *bios = init_params->dc->ctx->dc_bios;
525 	const struct dc_vbios_funcs *bp_funcs = bios->funcs;
526 	struct bp_disp_connector_caps_info disp_connect_caps_info = { 0 };
527 	struct graphics_object_id link_encoder = { 0 };
528 	enum transmitter transmitter_from_encoder;
529 	enum engine_id link_analog_engine;
530 
531 	DC_LOGGER_INIT(dc_ctx->logger);
532 
533 	link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
534 	link->irq_source_hpd_rx = DC_IRQ_SOURCE_INVALID;
535 	link->irq_source_read_request = DC_IRQ_SOURCE_INVALID;
536 	link->link_status.dpcd_caps = &link->dpcd_caps;
537 
538 	link->dc = init_params->dc;
539 	link->ctx = dc_ctx;
540 	link->link_index = init_params->link_index;
541 
542 	memset(&link->preferred_training_settings, 0,
543 	       sizeof(struct dc_link_training_overrides));
544 	memset(&link->preferred_link_setting, 0,
545 	       sizeof(struct dc_link_settings));
546 
547 	link->link_id =
548 		bios->funcs->get_connector_id(bios, (uint8_t)init_params->connector_index);
549 
550 	link->ep_type = DISPLAY_ENDPOINT_PHY;
551 
552 	DC_LOG_DC("BIOS object table - link_id: %d", link->link_id.id);
553 
554 	/* Determine early if the link has any supported encoders,
555 	 * so that we avoid initializing DDC and HPD, etc.
556 	 */
557 	bp_funcs->get_src_obj(bios, link->link_id, 0, &link_encoder);
558 
559 	if (encoder_is_external_dp(link_encoder)) {
560 		/* External DP bridge encoders: find the actual link encoder and use that. */
561 		link->ext_enc_id = link_encoder;
562 		bp_funcs->get_src_obj(bios, link->ext_enc_id, 0, &link_encoder);
563 	}
564 
565 	transmitter_from_encoder = translate_encoder_to_transmitter(link_encoder);
566 	link_analog_engine = find_analog_engine(link, &enc_init_data.analog_encoder);
567 
568 	if (transmitter_from_encoder == TRANSMITTER_UNKNOWN &&
569 	    !analog_engine_supported(link_analog_engine)) {
570 		DC_LOG_WARNING("link_id %d has unsupported encoder\n", link->link_id.id);
571 		goto create_fail;
572 	}
573 
574 	if (bios->funcs->get_disp_connector_caps_info) {
575 		bios->funcs->get_disp_connector_caps_info(bios, link->link_id, &disp_connect_caps_info);
576 		link->is_internal_display = (disp_connect_caps_info.INTERNAL_DISPLAY != 0);
577 		DC_LOG_DC("BIOS object table - is_internal_display: %d", link->is_internal_display);
578 		link->no_ddc_pin = disp_connect_caps_info.NO_DDC_PIN != 0;
579 	}
580 
581 	if (link->link_id.type != OBJECT_TYPE_CONNECTOR) {
582 		dm_output_to_console("%s: Invalid Connector ObjectID from Adapter Service for connector index:%d! type %d expected %d\n",
583 				     __func__, init_params->connector_index,
584 				     link->link_id.type, OBJECT_TYPE_CONNECTOR);
585 		goto create_fail;
586 	}
587 
588 	if (link->dc->res_pool->funcs->link_init)
589 		link->dc->res_pool->funcs->link_init(link);
590 
591 	ddc_service_init_data.ctx = link->ctx;
592 	ddc_service_init_data.id = link->link_id;
593 	ddc_service_init_data.link = link;
594 	link->ddc = link_create_ddc_service(&ddc_service_init_data);
595 
596 	if (!link->ddc) {
597 		DC_ERROR("Failed to create ddc_service!\n");
598 		goto ddc_create_fail;
599 	}
600 
601 	if (link->ctx->dc->config.dp_connector_no_native_i2c && link->no_ddc_pin) {
602 		link->ddc_hw_inst = link->aux_hw_inst;
603 	} else {
604 		/* Embedded display connectors such as LVDS may not have DDC. */
605 		if (!link->ddc->ddc_pin &&
606 		    !dc_is_embedded_signal(link->connector_signal)) {
607 			DC_ERROR("Failed to get I2C info for connector!\n");
608 			goto ddc_create_fail;
609 		}
610 
611 		link->ddc_hw_inst =
612 			dal_ddc_get_line(get_ddc_pin(link->ddc));
613 	}
614 
615 	enc_init_data.ctx = dc_ctx;
616 	enc_init_data.connector = link->link_id;
617 	enc_init_data.channel = get_ddc_line(link);
618 	enc_init_data.transmitter = transmitter_from_encoder;
619 	enc_init_data.encoder = link_encoder;
620 	enc_init_data.analog_engine = link_analog_engine;
621 	if (link->ctx->dce_version <= DCN_VERSION_4_01)
622 		enc_init_data.hpd_gpio = link_get_hpd_gpio(link->ctx->dc_bios, link->link_id,
623 					      link->ctx->gpio_service);
624 	else
625 		enc_init_data.hpd_gpio = NULL;
626 	if (enc_init_data.hpd_gpio) {
627 		dal_gpio_open(enc_init_data.hpd_gpio, GPIO_MODE_INTERRUPT);
628 		dal_gpio_unlock_pin(enc_init_data.hpd_gpio);
629 		link->irq_source_hpd = dal_irq_get_source(enc_init_data.hpd_gpio);
630 		enc_init_data.hpd_source = get_hpd_line(link);
631 		link->hpd_src = enc_init_data.hpd_source;
632 
633 		DC_LOG_DC("BIOS object table - hpd_gpio id: %d", enc_init_data.hpd_gpio->id);
634 		DC_LOG_DC("BIOS object table - hpd_gpio en: %d", enc_init_data.hpd_gpio->en);
635 	} else {
636 		struct graphics_object_hpd_info hpd_info;
637 
638 		if (link->ctx->dc_bios->funcs->get_hpd_info(link->ctx->dc_bios, link->link_id, &hpd_info) == BP_RESULT_OK) {
639 			link->hpd_src = hpd_info.hpd_int_gpio_uid - 1;
640 			link->irq_source_hpd =  DC_IRQ_SOURCE_HPD1 + link->hpd_src;
641 			enc_init_data.hpd_source = link->hpd_src;
642 			DC_LOG_DC("BIOS object table - hpd_int_gpio_uid id: %d", hpd_info.hpd_int_gpio_uid);
643 		} else {
644 			ASSERT(0);
645 			enc_init_data.hpd_source = HPD_SOURCEID_UNKNOWN;
646 		}
647 	}
648 
649 	link->link_enc =
650 		link->dc->res_pool->funcs->link_enc_create(dc_ctx, &enc_init_data);
651 
652 	if (!link->link_enc) {
653 		DC_ERROR("Failed to create link encoder!\n");
654 		goto link_enc_create_fail;
655 	}
656 
657 	DC_LOG_DC("BIOS object table - DP_IS_USB_C: %d", link->link_enc->features.flags.bits.DP_IS_USB_C);
658 	DC_LOG_DC("BIOS object table - IS_DP2_CAPABLE: %d", link->link_enc->features.flags.bits.IS_DP2_CAPABLE);
659 	DC_LOG_DC("BIOS object table - IS_HDMI_FRL_CAPABLE: %d", link->link_enc->features.flags.bits.IS_HDMI_FRL_CAPABLE);
660 
661 	switch (link->link_id.id) {
662 	case CONNECTOR_ID_HDMI_TYPE_A:
663 		link->connector_signal = SIGNAL_TYPE_HDMI_TYPE_A;
664 
665 		if (link->link_enc->hpd_gpio)
666 			link->irq_source_read_request =
667 					dal_irq_get_read_request(link->link_enc->hpd_gpio);
668 		else if (link->hpd_src != HPD_SOURCEID_UNKNOWN)
669 			link->irq_source_read_request = DC_IRQ_SOURCE_DCI2C_RR_DDC1 + link->hpd_src;
670 		break;
671 	case CONNECTOR_ID_SINGLE_LINK_DVID:
672 	case CONNECTOR_ID_SINGLE_LINK_DVII:
673 		link->connector_signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
674 		break;
675 	case CONNECTOR_ID_DUAL_LINK_DVID:
676 	case CONNECTOR_ID_DUAL_LINK_DVII:
677 		link->connector_signal = SIGNAL_TYPE_DVI_DUAL_LINK;
678 		break;
679 	case CONNECTOR_ID_VGA:
680 		link->connector_signal = SIGNAL_TYPE_RGB;
681 		break;
682 	case CONNECTOR_ID_DISPLAY_PORT:
683 	case CONNECTOR_ID_MXM:
684 	case CONNECTOR_ID_USBC:
685 		link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT;
686 
687 		if (link->link_enc->hpd_gpio)
688 			link->irq_source_hpd_rx =
689 					dal_irq_get_rx_source(link->link_enc->hpd_gpio);
690 		else if (link->hpd_src != HPD_SOURCEID_UNKNOWN)
691 			link->irq_source_hpd_rx = DC_IRQ_SOURCE_HPD1RX + link->hpd_src;
692 
693 		break;
694 	case CONNECTOR_ID_EDP:
695 		// If smartmux is supported, only create the link on the primary eDP.
696 		// Dual eDP is not supported with smartmux.
697 		if (!(!link->dc->config.smart_mux_version || dc_ctx->dc_edp_id_count == 0))
698 			goto create_fail;
699 
700 		link->connector_signal = SIGNAL_TYPE_EDP;
701 		if (!link->dc->config.allow_edp_hotplug_detection
702 			&& !is_smartmux_suported(link))
703 			link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
704 
705 		switch (link->dc->config.allow_edp_hotplug_detection) {
706 		case HPD_EN_FOR_ALL_EDP:
707 			if (link->link_enc->hpd_gpio) {
708 				link->irq_source_hpd_rx =
709 						dal_irq_get_rx_source(link->link_enc->hpd_gpio);
710 				} else if (link->hpd_src != HPD_SOURCEID_UNKNOWN) {
711 					link->irq_source_hpd_rx = DC_IRQ_SOURCE_HPD1RX + link->hpd_src;
712 				}
713 			break;
714 		case HPD_EN_FOR_PRIMARY_EDP_ONLY:
715 			if (link->link_index == 0) {
716 				if (link->link_enc->hpd_gpio) {
717 					link->irq_source_hpd_rx =
718 						dal_irq_get_rx_source(link->link_enc->hpd_gpio);
719 				} else if (link->hpd_src != HPD_SOURCEID_UNKNOWN) {
720 					link->irq_source_hpd_rx = DC_IRQ_SOURCE_HPD1RX + link->hpd_src;
721 				}
722 			} else
723 				link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
724 			break;
725 		case HPD_EN_FOR_SECONDARY_EDP_ONLY:
726 			if (link->link_index == 1) {
727 				if (link->link_enc->hpd_gpio) {
728 					link->irq_source_hpd_rx =
729 						dal_irq_get_rx_source(link->link_enc->hpd_gpio);
730 				} else if (link->hpd_src != HPD_SOURCEID_UNKNOWN) {
731 					link->irq_source_hpd_rx = DC_IRQ_SOURCE_HPD1RX + link->hpd_src;
732 				}
733 			} else
734 				link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
735 			break;
736 		default:
737 			link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
738 			break;
739 		}
740 		break;
741 	case CONNECTOR_ID_LVDS:
742 		link->connector_signal = SIGNAL_TYPE_LVDS;
743 		break;
744 	default:
745 		DC_LOG_WARNING("Unsupported Connector type:%d!\n",
746 			       link->link_id.id);
747 		goto create_fail;
748 	}
749 
750 	/* For external DP bridge encoders:
751 	 * Set the connector signal to DisplayPort so that they can work with
752 	 * the pre-existing code paths for DP without a lot of code churn.
753 	 */
754 	if (link->ext_enc_id.id != ENCODER_ID_UNKNOWN)
755 		link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT;
756 
757 	LINK_INFO("Connector[%d] description: signal: %s\n",
758 		  init_params->connector_index,
759 		  signal_type_to_string(link->connector_signal));
760 
761 	/* Update link encoder tracking variables. These are used for the dynamic
762 	 * assignment of link encoders to streams.
763 	 */
764 	link->eng_id = link->link_enc->preferred_engine;
765 	link->dc->res_pool->link_encoders[link->eng_id - ENGINE_ID_DIGA] = link->link_enc;
766 	link->dc->res_pool->dig_link_enc_count++;
767 
768 	link->link_enc_hw_inst = link->link_enc->transmitter;
769 
770 	if (link->dc->res_pool->funcs->panel_cntl_create &&
771 		(link->link_id.id == CONNECTOR_ID_EDP ||
772 			link->link_id.id == CONNECTOR_ID_LVDS)) {
773 		panel_cntl_init_data.ctx = dc_ctx;
774 		panel_cntl_init_data.inst = panel_cntl_init_data.ctx->dc_edp_id_count;
775 		panel_cntl_init_data.eng_id = link->eng_id;
776 		link->panel_cntl =
777 			link->dc->res_pool->funcs->panel_cntl_create(
778 								&panel_cntl_init_data);
779 		panel_cntl_init_data.ctx->dc_edp_id_count++;
780 
781 		if (link->panel_cntl == NULL) {
782 			DC_ERROR("Failed to create link panel_cntl!\n");
783 			goto panel_cntl_create_fail;
784 		}
785 	}
786 	for (i = 0; i < 4; i++) {
787 		if (bp_funcs->get_device_tag(dc_ctx->dc_bios,
788 					     link->link_id, i,
789 					     &link->device_tag) != BP_RESULT_OK) {
790 			DC_ERROR("Failed to find device tag!\n");
791 			goto device_tag_fail;
792 		}
793 
794 		/* Look for device tag that matches connector signal,
795 		 * CRT for rgb, LCD for other supported signal types
796 		 */
797 		if (!bp_funcs->is_device_id_supported(dc_ctx->dc_bios,
798 						      link->device_tag.dev_id))
799 			continue;
800 		if (link->device_tag.dev_id.device_type == DEVICE_TYPE_CRT &&
801 		    link->connector_signal != SIGNAL_TYPE_RGB &&
802 		    link->ext_enc_id.id == ENCODER_ID_UNKNOWN)
803 			continue;
804 		if (link->device_tag.dev_id.device_type == DEVICE_TYPE_LCD &&
805 		    link->connector_signal == SIGNAL_TYPE_RGB)
806 			continue;
807 
808 		DC_LOG_DC("BIOS object table - device_tag.acpi_device: %d", link->device_tag.acpi_device);
809 		DC_LOG_DC("BIOS object table - device_tag.dev_id.device_type: %d", link->device_tag.dev_id.device_type);
810 		DC_LOG_DC("BIOS object table - device_tag.dev_id.enum_id: %d", link->device_tag.dev_id.enum_id);
811 		break;
812 	}
813 
814 	if (bios->integrated_info) {
815 		/* Look for channel mapping corresponding to connector and device tag */
816 		for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; i++) {
817 			struct external_display_path *path =
818 				&bios->integrated_info->ext_disp_conn_info.path[i];
819 
820 			if (path->device_connector_id.enum_id == link->link_id.enum_id &&
821 			    path->device_connector_id.id == link->link_id.id &&
822 			    path->device_connector_id.type == link->link_id.type) {
823 				if (link->device_tag.acpi_device != 0 &&
824 				    path->device_acpi_enum == link->device_tag.acpi_device) {
825 					link->ddi_channel_mapping = path->channel_mapping;
826 					link->chip_caps = path->caps;
827 					DC_LOG_DC("BIOS object table - ddi_channel_mapping: 0x%04X",
828 						  link->ddi_channel_mapping.raw);
829 					DC_LOG_DC("BIOS object table - chip_caps: %d",
830 						  link->chip_caps);
831 				} else if (path->device_tag ==
832 					   link->device_tag.dev_id.raw_device_tag) {
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 				}
840 
841 				if ((link->chip_caps & AMD_EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK) == AMD_EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) {
842 					link->bios_forced_drive_settings.VOLTAGE_SWING =
843 						(bios->integrated_info->ext_disp_conn_info.fixdpvoltageswing & 0x3);
844 					link->bios_forced_drive_settings.PRE_EMPHASIS =
845 						((bios->integrated_info->ext_disp_conn_info.fixdpvoltageswing >> 2) & 0x3);
846 				}
847 
848 				break;
849 			}
850 		}
851 	}
852 	if (bios->funcs->get_atom_dc_golden_table)
853 		bios->funcs->get_atom_dc_golden_table(bios);
854 
855 	/*
856 	 * TODO check if GPIO programmed correctly
857 	 *
858 	 * If GPIO isn't programmed correctly HPD might not rise or drain
859 	 * fast enough, leading to bounces.
860 	 */
861 	program_hpd_filter(link);
862 
863 	/* If the connector is HDMI FRL capable, also create an HPO link encoder */
864 	if ((link->link_enc->features.flags.bits.IS_HDMI_FRL_CAPABLE) &&
865 		(!link->link_enc->features.flags.bits.DP_IS_USB_C) &&
866 			(link->dc->res_pool->funcs->hpo_frl_link_enc_create)) {
867 		enum engine_id hpo_eng_id;
868 		hpo_eng_id = ENGINE_ID_HPO_0;
869 
870 		link->hpo_frl_link_enc = link->dc->res_pool->funcs->hpo_frl_link_enc_create(
871 				hpo_eng_id,
872 				dc_ctx);
873 		if (link->hpo_frl_link_enc == NULL) {
874 			DC_ERROR("Failed to create HPO link encoder!\n");
875 			goto hpo_enc_create_fail;
876 		}
877 	}
878 
879 	link->psr_settings.psr_vtotal_control_support = false;
880 	link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED;
881 	link->replay_settings.config.replay_version = DC_REPLAY_VERSION_UNSUPPORTED;
882 
883 	DC_LOG_DC("BIOS object table - %s finished successfully.\n", __func__);
884 	return true;
885 hpo_enc_create_fail:
886 device_tag_fail:
887 link_enc_create_fail:
888 panel_cntl_create_fail:
889 ddc_create_fail:
890 create_fail:
891 	if (link->ddc)
892 		link_destroy_ddc_service(&link->ddc);
893 	if (link->panel_cntl)
894 		link->panel_cntl->funcs->destroy(&link->panel_cntl);
895 	if (link->link_enc)
896 		link->link_enc->funcs->destroy(&link->link_enc);
897 
898 	DC_LOG_DC("BIOS object table - %s failed.\n", __func__);
899 	return false;
900 }
901 
902 static bool construct_dpia(struct dc_link *link,
903 			      const struct link_init_data *init_params)
904 {
905 	struct ddc_service_init_data ddc_service_init_data = { 0 };
906 	struct dc_context *dc_ctx = init_params->ctx;
907 
908 	DC_LOGGER_INIT(dc_ctx->logger);
909 
910 	/* Initialized irq source for hpd and hpd rx */
911 	link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
912 	link->irq_source_hpd_rx = DC_IRQ_SOURCE_INVALID;
913 	link->link_status.dpcd_caps = &link->dpcd_caps;
914 
915 	link->dc = init_params->dc;
916 	link->ctx = dc_ctx;
917 	link->link_index = init_params->link_index;
918 
919 	memset(&link->preferred_training_settings, 0,
920 	       sizeof(struct dc_link_training_overrides));
921 	memset(&link->preferred_link_setting, 0,
922 	       sizeof(struct dc_link_settings));
923 
924 	/* Dummy Init for linkid */
925 	link->link_id.type = OBJECT_TYPE_CONNECTOR;
926 	link->link_id.id = CONNECTOR_ID_DISPLAY_PORT;
927 	link->link_id.enum_id = ENUM_ID_1 + init_params->connector_index;
928 	link->is_internal_display = false;
929 	link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT;
930 	LINK_INFO("Connector[%d] description:signal %d\n",
931 		  init_params->connector_index,
932 		  link->connector_signal);
933 
934 	link->ep_type = DISPLAY_ENDPOINT_USB4_DPIA;
935 	link->is_dig_mapping_flexible = true;
936 
937 	/* TODO: Initialize link : funcs->link_init */
938 
939 	ddc_service_init_data.ctx = link->ctx;
940 	ddc_service_init_data.id = link->link_id;
941 	ddc_service_init_data.link = link;
942 	/* Set indicator for dpia link so that ddc wont be created */
943 	ddc_service_init_data.is_dpia_link = true;
944 
945 	link->ddc = link_create_ddc_service(&ddc_service_init_data);
946 	if (!link->ddc) {
947 		DC_ERROR("Failed to create ddc_service!\n");
948 		goto ddc_create_fail;
949 	}
950 
951 	/* Set dpia port index : 0 to number of dpia ports */
952 	link->ddc_hw_inst = (uint8_t)init_params->connector_index;
953 
954 	// Assign Dpia preferred eng_id
955 	if (link->dc->res_pool->funcs->get_preferred_eng_id_dpia)
956 		link->dpia_preferred_eng_id = link->dc->res_pool->funcs->get_preferred_eng_id_dpia(link->ddc_hw_inst);
957 
958 	/* TODO: Create link encoder */
959 
960 	link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED;
961 	link->replay_settings.config.replay_version = DC_REPLAY_VERSION_UNSUPPORTED;
962 
963 	return true;
964 
965 ddc_create_fail:
966 	return false;
967 }
968 
969 static bool link_construct(struct dc_link *link,
970 			      const struct link_init_data *init_params)
971 {
972 	/* Handle dpia case */
973 	if (init_params->is_dpia_link == true)
974 		return construct_dpia(link, init_params);
975 	else
976 		return construct_phy(link, init_params);
977 }
978 
979 struct dc_link *link_create(const struct link_init_data *init_params)
980 {
981 	struct dc_link *link = kzalloc_obj(*link);
982 
983 	if (NULL == link)
984 		goto alloc_fail;
985 
986 	if (false == link_construct(link, init_params))
987 		goto construct_fail;
988 
989 	return link;
990 
991 construct_fail:
992 	kfree(link);
993 
994 alloc_fail:
995 	return NULL;
996 }
997 
998 void link_destroy(struct dc_link **link)
999 {
1000 	link_destruct(*link);
1001 	kfree(*link);
1002 	*link = NULL;
1003 }
1004