2 * Copyright 2023 Advanced Micro Devices, Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
26 /* FILE POLICY AND INTENDED USAGE:
27 * This file owns the creation/destruction of link structure.
29 #include "link_factory.h"
30 #include "protocols/link_ddc.h"
31 #include "protocols/link_edp_panel_control.h"
32 #include "protocols/link_hpd.h"
33 #include "gpio_service_interface.h"
34 #include "atomfirmware.h"
36 #define DC_LOGGER_INIT(logger)
38 #define LINK_INFO(...) \
42 static enum transmitter translate_encoder_to_transmitter(struct graphics_object_id encoder)
45 case ENCODER_ID_INTERNAL_UNIPHY:
46 switch (encoder.enum_id) {
48 return TRANSMITTER_UNIPHY_A;
50 return TRANSMITTER_UNIPHY_B;
52 return TRANSMITTER_UNKNOWN;
55 case ENCODER_ID_INTERNAL_UNIPHY1:
56 switch (encoder.enum_id) {
58 return TRANSMITTER_UNIPHY_C;
60 return TRANSMITTER_UNIPHY_D;
62 return TRANSMITTER_UNKNOWN;
65 case ENCODER_ID_INTERNAL_UNIPHY2:
66 switch (encoder.enum_id) {
68 return TRANSMITTER_UNIPHY_E;
70 return TRANSMITTER_UNIPHY_F;
72 return TRANSMITTER_UNKNOWN;
75 case ENCODER_ID_INTERNAL_UNIPHY3:
76 switch (encoder.enum_id) {
78 return TRANSMITTER_UNIPHY_G;
80 return TRANSMITTER_UNKNOWN;
83 case ENCODER_ID_EXTERNAL_NUTMEG:
84 switch (encoder.enum_id) {
86 return TRANSMITTER_NUTMEG_CRT;
88 return TRANSMITTER_UNKNOWN;
91 case ENCODER_ID_EXTERNAL_TRAVIS:
92 switch (encoder.enum_id) {
94 return TRANSMITTER_TRAVIS_CRT;
96 return TRANSMITTER_TRAVIS_LCD;
98 return TRANSMITTER_UNKNOWN;
102 return TRANSMITTER_UNKNOWN;
106 static void link_destruct(struct dc_link *link)
110 if (link->hpd_gpio) {
111 dal_gpio_destroy_irq(&link->hpd_gpio);
112 link->hpd_gpio = NULL;
116 link_destroy_ddc_service(&link->ddc);
118 if (link->panel_cntl)
119 link->panel_cntl->funcs->destroy(&link->panel_cntl);
121 if (link->link_enc) {
122 /* Update link encoder resource tracking variables. These are used for
123 * the dynamic assignment of link encoders to streams. Virtual links
124 * are not assigned encoder resources on creation.
126 if (link->link_id.id != CONNECTOR_ID_VIRTUAL) {
127 link->dc->res_pool->link_encoders[link->eng_id - ENGINE_ID_DIGA] = NULL;
128 link->dc->res_pool->dig_link_enc_count--;
130 link->link_enc->funcs->destroy(&link->link_enc);
133 if (link->local_sink)
134 dc_sink_release(link->local_sink);
136 for (i = 0; i < link->sink_count; ++i)
137 dc_sink_release(link->remote_sinks[i]);
140 static enum channel_id get_ddc_line(struct dc_link *link)
143 enum channel_id channel;
145 channel = CHANNEL_ID_UNKNOWN;
147 ddc = get_ddc_pin(link->ddc);
150 switch (dal_ddc_get_line(ddc)) {
151 case GPIO_DDC_LINE_DDC1:
152 channel = CHANNEL_ID_DDC1;
154 case GPIO_DDC_LINE_DDC2:
155 channel = CHANNEL_ID_DDC2;
157 case GPIO_DDC_LINE_DDC3:
158 channel = CHANNEL_ID_DDC3;
160 case GPIO_DDC_LINE_DDC4:
161 channel = CHANNEL_ID_DDC4;
163 case GPIO_DDC_LINE_DDC5:
164 channel = CHANNEL_ID_DDC5;
166 case GPIO_DDC_LINE_DDC6:
167 channel = CHANNEL_ID_DDC6;
169 case GPIO_DDC_LINE_DDC_VGA:
170 channel = CHANNEL_ID_DDC_VGA;
172 case GPIO_DDC_LINE_I2C_PAD:
173 channel = CHANNEL_ID_I2C_PAD;
184 static bool dc_link_construct_phy(struct dc_link *link,
185 const struct link_init_data *init_params)
188 struct ddc_service_init_data ddc_service_init_data = { 0 };
189 struct dc_context *dc_ctx = init_params->ctx;
190 struct encoder_init_data enc_init_data = { 0 };
191 struct panel_cntl_init_data panel_cntl_init_data = { 0 };
192 struct integrated_info info = { 0 };
193 struct dc_bios *bios = init_params->dc->ctx->dc_bios;
194 const struct dc_vbios_funcs *bp_funcs = bios->funcs;
195 struct bp_disp_connector_caps_info disp_connect_caps_info = { 0 };
197 DC_LOGGER_INIT(dc_ctx->logger);
199 link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
200 link->irq_source_hpd_rx = DC_IRQ_SOURCE_INVALID;
201 link->link_status.dpcd_caps = &link->dpcd_caps;
203 link->dc = init_params->dc;
205 link->link_index = init_params->link_index;
207 memset(&link->preferred_training_settings, 0,
208 sizeof(struct dc_link_training_overrides));
209 memset(&link->preferred_link_setting, 0,
210 sizeof(struct dc_link_settings));
213 bios->funcs->get_connector_id(bios, init_params->connector_index);
215 link->ep_type = DISPLAY_ENDPOINT_PHY;
217 DC_LOG_DC("BIOS object table - link_id: %d", link->link_id.id);
219 if (bios->funcs->get_disp_connector_caps_info) {
220 bios->funcs->get_disp_connector_caps_info(bios, link->link_id, &disp_connect_caps_info);
221 link->is_internal_display = disp_connect_caps_info.INTERNAL_DISPLAY;
222 DC_LOG_DC("BIOS object table - is_internal_display: %d", link->is_internal_display);
225 if (link->link_id.type != OBJECT_TYPE_CONNECTOR) {
226 dm_output_to_console("%s: Invalid Connector ObjectID from Adapter Service for connector index:%d! type %d expected %d\n",
227 __func__, init_params->connector_index,
228 link->link_id.type, OBJECT_TYPE_CONNECTOR);
232 if (link->dc->res_pool->funcs->link_init)
233 link->dc->res_pool->funcs->link_init(link);
235 link->hpd_gpio = link_get_hpd_gpio(link->ctx->dc_bios, link->link_id,
236 link->ctx->gpio_service);
238 if (link->hpd_gpio) {
239 dal_gpio_open(link->hpd_gpio, GPIO_MODE_INTERRUPT);
240 dal_gpio_unlock_pin(link->hpd_gpio);
241 link->irq_source_hpd = dal_irq_get_source(link->hpd_gpio);
243 DC_LOG_DC("BIOS object table - hpd_gpio id: %d", link->hpd_gpio->id);
244 DC_LOG_DC("BIOS object table - hpd_gpio en: %d", link->hpd_gpio->en);
247 switch (link->link_id.id) {
248 case CONNECTOR_ID_HDMI_TYPE_A:
249 link->connector_signal = SIGNAL_TYPE_HDMI_TYPE_A;
252 case CONNECTOR_ID_SINGLE_LINK_DVID:
253 case CONNECTOR_ID_SINGLE_LINK_DVII:
254 link->connector_signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
256 case CONNECTOR_ID_DUAL_LINK_DVID:
257 case CONNECTOR_ID_DUAL_LINK_DVII:
258 link->connector_signal = SIGNAL_TYPE_DVI_DUAL_LINK;
260 case CONNECTOR_ID_DISPLAY_PORT:
261 case CONNECTOR_ID_USBC:
262 link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT;
265 link->irq_source_hpd_rx =
266 dal_irq_get_rx_source(link->hpd_gpio);
269 case CONNECTOR_ID_EDP:
270 link->connector_signal = SIGNAL_TYPE_EDP;
272 if (link->hpd_gpio) {
273 if (!link->dc->config.allow_edp_hotplug_detection)
274 link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
276 switch (link->dc->config.allow_edp_hotplug_detection) {
277 case 1: // only the 1st eDP handles hotplug
278 if (link->link_index == 0)
279 link->irq_source_hpd_rx =
280 dal_irq_get_rx_source(link->hpd_gpio);
282 link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
284 case 2: // only the 2nd eDP handles hotplug
285 if (link->link_index == 1)
286 link->irq_source_hpd_rx =
287 dal_irq_get_rx_source(link->hpd_gpio);
289 link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
297 case CONNECTOR_ID_LVDS:
298 link->connector_signal = SIGNAL_TYPE_LVDS;
301 DC_LOG_WARNING("Unsupported Connector type:%d!\n",
306 /* TODO: #DAL3 Implement id to str function.*/
307 LINK_INFO("Connector[%d] description:"
309 init_params->connector_index,
310 link->connector_signal);
312 ddc_service_init_data.ctx = link->ctx;
313 ddc_service_init_data.id = link->link_id;
314 ddc_service_init_data.link = link;
315 link->ddc = link_create_ddc_service(&ddc_service_init_data);
318 DC_ERROR("Failed to create ddc_service!\n");
319 goto ddc_create_fail;
322 if (!link->ddc->ddc_pin) {
323 DC_ERROR("Failed to get I2C info for connector!\n");
324 goto ddc_create_fail;
328 dal_ddc_get_line(get_ddc_pin(link->ddc));
331 if (link->dc->res_pool->funcs->panel_cntl_create &&
332 (link->link_id.id == CONNECTOR_ID_EDP ||
333 link->link_id.id == CONNECTOR_ID_LVDS)) {
334 panel_cntl_init_data.ctx = dc_ctx;
335 panel_cntl_init_data.inst =
336 panel_cntl_init_data.ctx->dc_edp_id_count;
338 link->dc->res_pool->funcs->panel_cntl_create(
339 &panel_cntl_init_data);
340 panel_cntl_init_data.ctx->dc_edp_id_count++;
342 if (link->panel_cntl == NULL) {
343 DC_ERROR("Failed to create link panel_cntl!\n");
344 goto panel_cntl_create_fail;
348 enc_init_data.ctx = dc_ctx;
349 bp_funcs->get_src_obj(dc_ctx->dc_bios, link->link_id, 0,
350 &enc_init_data.encoder);
351 enc_init_data.connector = link->link_id;
352 enc_init_data.channel = get_ddc_line(link);
353 enc_init_data.hpd_source = get_hpd_line(link);
355 link->hpd_src = enc_init_data.hpd_source;
357 enc_init_data.transmitter =
358 translate_encoder_to_transmitter(enc_init_data.encoder);
360 link->dc->res_pool->funcs->link_enc_create(dc_ctx, &enc_init_data);
362 DC_LOG_DC("BIOS object table - DP_IS_USB_C: %d", link->link_enc->features.flags.bits.DP_IS_USB_C);
363 DC_LOG_DC("BIOS object table - IS_DP2_CAPABLE: %d", link->link_enc->features.flags.bits.IS_DP2_CAPABLE);
365 if (!link->link_enc) {
366 DC_ERROR("Failed to create link encoder!\n");
367 goto link_enc_create_fail;
370 /* Update link encoder tracking variables. These are used for the dynamic
371 * assignment of link encoders to streams.
373 link->eng_id = link->link_enc->preferred_engine;
374 link->dc->res_pool->link_encoders[link->eng_id - ENGINE_ID_DIGA] = link->link_enc;
375 link->dc->res_pool->dig_link_enc_count++;
377 link->link_enc_hw_inst = link->link_enc->transmitter;
378 for (i = 0; i < 4; i++) {
379 if (bp_funcs->get_device_tag(dc_ctx->dc_bios,
381 &link->device_tag) != BP_RESULT_OK) {
382 DC_ERROR("Failed to find device tag!\n");
383 goto device_tag_fail;
386 /* Look for device tag that matches connector signal,
387 * CRT for rgb, LCD for other supported signal tyes
389 if (!bp_funcs->is_device_id_supported(dc_ctx->dc_bios,
390 link->device_tag.dev_id))
392 if (link->device_tag.dev_id.device_type == DEVICE_TYPE_CRT &&
393 link->connector_signal != SIGNAL_TYPE_RGB)
395 if (link->device_tag.dev_id.device_type == DEVICE_TYPE_LCD &&
396 link->connector_signal == SIGNAL_TYPE_RGB)
399 DC_LOG_DC("BIOS object table - device_tag.acpi_device: %d", link->device_tag.acpi_device);
400 DC_LOG_DC("BIOS object table - device_tag.dev_id.device_type: %d", link->device_tag.dev_id.device_type);
401 DC_LOG_DC("BIOS object table - device_tag.dev_id.enum_id: %d", link->device_tag.dev_id.enum_id);
405 if (bios->integrated_info)
406 info = *bios->integrated_info;
408 /* Look for channel mapping corresponding to connector and device tag */
409 for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; i++) {
410 struct external_display_path *path =
411 &info.ext_disp_conn_info.path[i];
413 if (path->device_connector_id.enum_id == link->link_id.enum_id &&
414 path->device_connector_id.id == link->link_id.id &&
415 path->device_connector_id.type == link->link_id.type) {
416 if (link->device_tag.acpi_device != 0 &&
417 path->device_acpi_enum == link->device_tag.acpi_device) {
418 link->ddi_channel_mapping = path->channel_mapping;
419 link->chip_caps = path->caps;
420 DC_LOG_DC("BIOS object table - ddi_channel_mapping: 0x%04X", link->ddi_channel_mapping.raw);
421 DC_LOG_DC("BIOS object table - chip_caps: %d", link->chip_caps);
422 } else if (path->device_tag ==
423 link->device_tag.dev_id.raw_device_tag) {
424 link->ddi_channel_mapping = path->channel_mapping;
425 link->chip_caps = path->caps;
426 DC_LOG_DC("BIOS object table - ddi_channel_mapping: 0x%04X", link->ddi_channel_mapping.raw);
427 DC_LOG_DC("BIOS object table - chip_caps: %d", link->chip_caps);
430 if (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) {
431 link->bios_forced_drive_settings.VOLTAGE_SWING =
432 (info.ext_disp_conn_info.fixdpvoltageswing & 0x3);
433 link->bios_forced_drive_settings.PRE_EMPHASIS =
434 ((info.ext_disp_conn_info.fixdpvoltageswing >> 2) & 0x3);
441 if (bios->funcs->get_atom_dc_golden_table)
442 bios->funcs->get_atom_dc_golden_table(bios);
445 * TODO check if GPIO programmed correctly
447 * If GPIO isn't programmed correctly HPD might not rise or drain
448 * fast enough, leading to bounces.
450 program_hpd_filter(link);
452 link->psr_settings.psr_vtotal_control_support = false;
453 link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED;
455 DC_LOG_DC("BIOS object table - dc_link_contruct finished successfully.\n");
458 link->link_enc->funcs->destroy(&link->link_enc);
459 link_enc_create_fail:
460 if (link->panel_cntl != NULL)
461 link->panel_cntl->funcs->destroy(&link->panel_cntl);
462 panel_cntl_create_fail:
463 link_destroy_ddc_service(&link->ddc);
467 if (link->hpd_gpio) {
468 dal_gpio_destroy_irq(&link->hpd_gpio);
469 link->hpd_gpio = NULL;
472 DC_LOG_DC("BIOS object table - dc_link_contruct failed.\n");
476 static bool dc_link_construct_dpia(struct dc_link *link,
477 const struct link_init_data *init_params)
479 struct ddc_service_init_data ddc_service_init_data = { 0 };
480 struct dc_context *dc_ctx = init_params->ctx;
482 DC_LOGGER_INIT(dc_ctx->logger);
484 /* Initialized irq source for hpd and hpd rx */
485 link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
486 link->irq_source_hpd_rx = DC_IRQ_SOURCE_INVALID;
487 link->link_status.dpcd_caps = &link->dpcd_caps;
489 link->dc = init_params->dc;
491 link->link_index = init_params->link_index;
493 memset(&link->preferred_training_settings, 0,
494 sizeof(struct dc_link_training_overrides));
495 memset(&link->preferred_link_setting, 0,
496 sizeof(struct dc_link_settings));
498 /* Dummy Init for linkid */
499 link->link_id.type = OBJECT_TYPE_CONNECTOR;
500 link->link_id.id = CONNECTOR_ID_DISPLAY_PORT;
501 link->link_id.enum_id = ENUM_ID_1 + init_params->connector_index;
502 link->is_internal_display = false;
503 link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT;
504 LINK_INFO("Connector[%d] description:signal %d\n",
505 init_params->connector_index,
506 link->connector_signal);
508 link->ep_type = DISPLAY_ENDPOINT_USB4_DPIA;
509 link->is_dig_mapping_flexible = true;
511 /* TODO: Initialize link : funcs->link_init */
513 ddc_service_init_data.ctx = link->ctx;
514 ddc_service_init_data.id = link->link_id;
515 ddc_service_init_data.link = link;
516 /* Set indicator for dpia link so that ddc wont be created */
517 ddc_service_init_data.is_dpia_link = true;
519 link->ddc = link_create_ddc_service(&ddc_service_init_data);
521 DC_ERROR("Failed to create ddc_service!\n");
522 goto ddc_create_fail;
525 /* Set dpia port index : 0 to number of dpia ports */
526 link->ddc_hw_inst = init_params->connector_index;
528 /* TODO: Create link encoder */
530 link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED;
532 /* Some docks seem to NAK I2C writes to segment pointer with mot=0. */
533 link->wa_flags.dp_mot_reset_segment = true;
541 static bool link_construct(struct dc_link *link,
542 const struct link_init_data *init_params)
544 /* Handle dpia case */
545 if (init_params->is_dpia_link == true)
546 return dc_link_construct_dpia(link, init_params);
548 return dc_link_construct_phy(link, init_params);
551 struct dc_link *link_create(const struct link_init_data *init_params)
553 struct dc_link *link =
554 kzalloc(sizeof(*link), GFP_KERNEL);
559 if (false == link_construct(link, init_params))
571 void link_destroy(struct dc_link **link)
573 link_destruct(*link);