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