brintos

brintos / linux-shallow public Read only

0
0
Text · 28.1 KiB · 5e1b5ab Raw
852 lines · c
1/*2 * Copyright 2023 Advanced Micro Devices, Inc.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice shall be included in12 * all copies or substantial portions of the Software.13 *14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR18 * 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 OR20 * OTHER DEALINGS IN THE SOFTWARE.21 *22 * Authors: AMD23 *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_hpd.h"45#include "gpio_service_interface.h"46#include "atomfirmware.h"47 48#define DC_LOGGER \49	dc_ctx->logger50#define DC_LOGGER_INIT(logger)51 52#define LINK_INFO(...) \53	DC_LOG_HW_HOTPLUG(  \54		__VA_ARGS__)55 56/* link factory owns the creation/destruction of link structures. */57static void construct_link_service_factory(struct link_service *link_srv)58{59 60	link_srv->create_link = link_create;61	link_srv->destroy_link = link_destroy;62}63 64/* link_detection manages link detection states and receiver states by using65 * various link protocols. It also provides helper functions to interpret66 * certain capabilities or status based on the states it manages or retrieve67 * them directly from connected receivers.68 */69static void construct_link_service_detection(struct link_service *link_srv)70{71	link_srv->detect_link = link_detect;72	link_srv->detect_connection_type = link_detect_connection_type;73	link_srv->add_remote_sink = link_add_remote_sink;74	link_srv->remove_remote_sink = link_remove_remote_sink;75	link_srv->get_hpd_state = link_get_hpd_state;76	link_srv->get_hpd_gpio = link_get_hpd_gpio;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. */88static 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 also97 * provides helper functions exposing bandwidth formulas used in validation.98 */99static 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_dpia_bandwidth = link_validate_dpia_bandwidth;104}105 106/* link dpms owns the programming sequence of stream's dpms state associated107 * with the link and link's enable/disable sequences as result of the stream's108 * dpms state change.109 */110static void construct_link_service_dpms(struct link_service *link_srv)111{112	link_srv->set_dpms_on = link_set_dpms_on;113	link_srv->set_dpms_off = link_set_dpms_off;114	link_srv->resume = link_resume;115	link_srv->blank_all_dp_displays = link_blank_all_dp_displays;116	link_srv->blank_all_edp_displays = link_blank_all_edp_displays;117	link_srv->blank_dp_stream = link_blank_dp_stream;118	link_srv->increase_mst_payload = link_increase_mst_payload;119	link_srv->reduce_mst_payload = link_reduce_mst_payload;120	link_srv->set_dsc_on_stream = link_set_dsc_on_stream;121	link_srv->set_dsc_enable = link_set_dsc_enable;122	link_srv->update_dsc_config = link_update_dsc_config;123}124 125/* link ddc implements generic display communication protocols such as i2c, aux126 * and scdc. It should not contain any specific applications of these127 * protocols such as display capability query, detection, or handshaking such as128 * link training.129 */130static void construct_link_service_ddc(struct link_service *link_srv)131{132	link_srv->create_ddc_service = link_create_ddc_service;133	link_srv->destroy_ddc_service = link_destroy_ddc_service;134	link_srv->query_ddc_data = link_query_ddc_data;135	link_srv->aux_transfer_raw = link_aux_transfer_raw;136	link_srv->configure_fixed_vs_pe_retimer = link_configure_fixed_vs_pe_retimer;137	link_srv->aux_transfer_with_retries_no_mutex =138			link_aux_transfer_with_retries_no_mutex;139	link_srv->is_in_aux_transaction_mode = link_is_in_aux_transaction_mode;140	link_srv->get_aux_defer_delay = link_get_aux_defer_delay;141}142 143/* link dp capability implements dp specific link capability retrieval sequence.144 * It is responsible for retrieving, parsing, overriding, deciding capability145 * obtained from dp link. Link capability consists of encoders, DPRXs, cables,146 * retimers, usb and all other possible backend capabilities.147 */148static void construct_link_service_dp_capability(struct link_service *link_srv)149{150	link_srv->dp_is_sink_present = dp_is_sink_present;151	link_srv->dp_is_fec_supported = dp_is_fec_supported;152	link_srv->dp_is_128b_132b_signal = dp_is_128b_132b_signal;153	link_srv->dp_get_max_link_enc_cap = dp_get_max_link_enc_cap;154	link_srv->dp_get_verified_link_cap = dp_get_verified_link_cap;155	link_srv->dp_get_encoding_format = link_dp_get_encoding_format;156	link_srv->dp_should_enable_fec = dp_should_enable_fec;157	link_srv->dp_decide_link_settings = link_decide_link_settings;158	link_srv->mst_decide_link_encoding_format =159			mst_decide_link_encoding_format;160	link_srv->edp_decide_link_settings = edp_decide_link_settings;161	link_srv->bw_kbps_from_raw_frl_link_rate_data =162			link_bw_kbps_from_raw_frl_link_rate_data;163	link_srv->dp_overwrite_extended_receiver_cap =164			dp_overwrite_extended_receiver_cap;165	link_srv->dp_decide_lttpr_mode = dp_decide_lttpr_mode;166}167 168/* link dp phy/dpia implements basic dp phy/dpia functionality such as169 * enable/disable output and set lane/drive settings. It is responsible for170 * maintaining and update software state representing current phy/dpia status171 * such as current link settings.172 */173static void construct_link_service_dp_phy_or_dpia(struct link_service *link_srv)174{175	link_srv->dpia_handle_usb4_bandwidth_allocation_for_link =176			dpia_handle_usb4_bandwidth_allocation_for_link;177	link_srv->dpia_handle_bw_alloc_response = dpia_handle_bw_alloc_response;178	link_srv->dp_set_drive_settings = dp_set_drive_settings;179	link_srv->dpcd_write_rx_power_ctrl = dpcd_write_rx_power_ctrl;180}181 182/* link dp irq handler implements DP HPD short pulse handling sequence according183 * to DP specifications184 */185static void construct_link_service_dp_irq_handler(struct link_service *link_srv)186{187	link_srv->dp_parse_link_loss_status = dp_parse_link_loss_status;188	link_srv->dp_should_allow_hpd_rx_irq = dp_should_allow_hpd_rx_irq;189	link_srv->dp_handle_link_loss = dp_handle_link_loss;190	link_srv->dp_read_hpd_rx_irq_data = dp_read_hpd_rx_irq_data;191	link_srv->dp_handle_hpd_rx_irq = dp_handle_hpd_rx_irq;192}193 194/* link edp panel control implements retrieval and configuration of eDP panel195 * features such as PSR and ABM and it also manages specs defined eDP panel196 * power sequences.197 */198static void construct_link_service_edp_panel_control(struct link_service *link_srv)199{200	link_srv->edp_panel_backlight_power_on = edp_panel_backlight_power_on;201	link_srv->edp_get_backlight_level = edp_get_backlight_level;202	link_srv->edp_get_backlight_level_nits = edp_get_backlight_level_nits;203	link_srv->edp_set_backlight_level = edp_set_backlight_level;204	link_srv->edp_set_backlight_level_nits = edp_set_backlight_level_nits;205	link_srv->edp_get_target_backlight_pwm = edp_get_target_backlight_pwm;206	link_srv->edp_get_psr_state = edp_get_psr_state;207	link_srv->edp_set_psr_allow_active = edp_set_psr_allow_active;208	link_srv->edp_setup_psr = edp_setup_psr;209	link_srv->edp_set_sink_vtotal_in_psr_active =210			edp_set_sink_vtotal_in_psr_active;211	link_srv->edp_get_psr_residency = edp_get_psr_residency;212 213	link_srv->edp_get_replay_state = edp_get_replay_state;214	link_srv->edp_set_replay_allow_active = edp_set_replay_allow_active;215	link_srv->edp_setup_replay = edp_setup_replay;216	link_srv->edp_send_replay_cmd = edp_send_replay_cmd;217	link_srv->edp_set_coasting_vtotal = edp_set_coasting_vtotal;218	link_srv->edp_replay_residency = edp_replay_residency;219	link_srv->edp_set_replay_power_opt_and_coasting_vtotal = edp_set_replay_power_opt_and_coasting_vtotal;220 221	link_srv->edp_wait_for_t12 = edp_wait_for_t12;222	link_srv->edp_is_ilr_optimization_required =223			edp_is_ilr_optimization_required;224	link_srv->edp_backlight_enable_aux = edp_backlight_enable_aux;225	link_srv->edp_add_delay_for_T9 = edp_add_delay_for_T9;226	link_srv->edp_receiver_ready_T9 = edp_receiver_ready_T9;227	link_srv->edp_receiver_ready_T7 = edp_receiver_ready_T7;228	link_srv->edp_power_alpm_dpcd_enable = edp_power_alpm_dpcd_enable;229	link_srv->edp_set_panel_power = edp_set_panel_power;230}231 232/* link dp cts implements dp compliance test automation protocols and manual233 * testing interfaces for debugging and certification purpose.234 */235static void construct_link_service_dp_cts(struct link_service *link_srv)236{237	link_srv->dp_handle_automated_test = dp_handle_automated_test;238	link_srv->dp_set_test_pattern = dp_set_test_pattern;239	link_srv->dp_set_preferred_link_settings =240			dp_set_preferred_link_settings;241	link_srv->dp_set_preferred_training_settings =242			dp_set_preferred_training_settings;243}244 245/* link dp trace implements tracing interfaces for tracking major dp sequences246 * including execution status and timestamps247 */248static void construct_link_service_dp_trace(struct link_service *link_srv)249{250	link_srv->dp_trace_is_initialized = dp_trace_is_initialized;251	link_srv->dp_trace_set_is_logged_flag = dp_trace_set_is_logged_flag;252	link_srv->dp_trace_is_logged = dp_trace_is_logged;253	link_srv->dp_trace_get_lt_end_timestamp = dp_trace_get_lt_end_timestamp;254	link_srv->dp_trace_get_lt_counts = dp_trace_get_lt_counts;255	link_srv->dp_trace_get_link_loss_count = dp_trace_get_link_loss_count;256	link_srv->dp_trace_set_edp_power_timestamp =257			dp_trace_set_edp_power_timestamp;258	link_srv->dp_trace_get_edp_poweron_timestamp =259			dp_trace_get_edp_poweron_timestamp;260	link_srv->dp_trace_get_edp_poweroff_timestamp =261			dp_trace_get_edp_poweroff_timestamp;262	link_srv->dp_trace_source_sequence = dp_trace_source_sequence;263}264 265static void construct_link_service(struct link_service *link_srv)266{267	/* All link service functions should fall under some sub categories.268	 * If a new function doesn't perfectly fall under an existing sub269	 * category, it must be that you are either adding a whole new aspect of270	 * responsibility to link service or something doesn't belong to link271	 * service. In that case please contact the arch owner to arrange a272	 * design review meeting.273	 */274	construct_link_service_factory(link_srv);275	construct_link_service_detection(link_srv);276	construct_link_service_resource(link_srv);277	construct_link_service_validation(link_srv);278	construct_link_service_dpms(link_srv);279	construct_link_service_ddc(link_srv);280	construct_link_service_dp_capability(link_srv);281	construct_link_service_dp_phy_or_dpia(link_srv);282	construct_link_service_dp_irq_handler(link_srv);283	construct_link_service_edp_panel_control(link_srv);284	construct_link_service_dp_cts(link_srv);285	construct_link_service_dp_trace(link_srv);286}287 288struct link_service *link_create_link_service(void)289{290	struct link_service *link_srv = kzalloc(sizeof(*link_srv), GFP_KERNEL);291 292	if (link_srv == NULL)293		goto fail;294 295	construct_link_service(link_srv);296 297	return link_srv;298fail:299	return NULL;300}301 302void link_destroy_link_service(struct link_service **link_srv)303{304	kfree(*link_srv);305	*link_srv = NULL;306}307 308static enum transmitter translate_encoder_to_transmitter(309		struct graphics_object_id encoder)310{311	switch (encoder.id) {312	case ENCODER_ID_INTERNAL_UNIPHY:313		switch (encoder.enum_id) {314		case ENUM_ID_1:315			return TRANSMITTER_UNIPHY_A;316		case ENUM_ID_2:317			return TRANSMITTER_UNIPHY_B;318		default:319			return TRANSMITTER_UNKNOWN;320		}321	break;322	case ENCODER_ID_INTERNAL_UNIPHY1:323		switch (encoder.enum_id) {324		case ENUM_ID_1:325			return TRANSMITTER_UNIPHY_C;326		case ENUM_ID_2:327			return TRANSMITTER_UNIPHY_D;328		default:329			return TRANSMITTER_UNKNOWN;330		}331	break;332	case ENCODER_ID_INTERNAL_UNIPHY2:333		switch (encoder.enum_id) {334		case ENUM_ID_1:335			return TRANSMITTER_UNIPHY_E;336		case ENUM_ID_2:337			return TRANSMITTER_UNIPHY_F;338		default:339			return TRANSMITTER_UNKNOWN;340		}341	break;342	case ENCODER_ID_INTERNAL_UNIPHY3:343		switch (encoder.enum_id) {344		case ENUM_ID_1:345			return TRANSMITTER_UNIPHY_G;346		default:347			return TRANSMITTER_UNKNOWN;348		}349	break;350	case ENCODER_ID_EXTERNAL_NUTMEG:351		switch (encoder.enum_id) {352		case ENUM_ID_1:353			return TRANSMITTER_NUTMEG_CRT;354		default:355			return TRANSMITTER_UNKNOWN;356		}357	break;358	case ENCODER_ID_EXTERNAL_TRAVIS:359		switch (encoder.enum_id) {360		case ENUM_ID_1:361			return TRANSMITTER_TRAVIS_CRT;362		case ENUM_ID_2:363			return TRANSMITTER_TRAVIS_LCD;364		default:365			return TRANSMITTER_UNKNOWN;366		}367	break;368	default:369		return TRANSMITTER_UNKNOWN;370	}371}372 373static void link_destruct(struct dc_link *link)374{375	int i;376 377	if (link->hpd_gpio) {378		dal_gpio_destroy_irq(&link->hpd_gpio);379		link->hpd_gpio = NULL;380	}381 382	if (link->ddc)383		link_destroy_ddc_service(&link->ddc);384 385	if (link->panel_cntl)386		link->panel_cntl->funcs->destroy(&link->panel_cntl);387 388	if (link->link_enc && !link->is_dig_mapping_flexible) {389		/* Update link encoder resource tracking variables. These are used for390		 * the dynamic assignment of link encoders to streams. Virtual links391		 * are not assigned encoder resources on creation.392		 */393		if (link->link_id.id != CONNECTOR_ID_VIRTUAL && link->eng_id != ENGINE_ID_UNKNOWN) {394			link->dc->res_pool->link_encoders[link->eng_id - ENGINE_ID_DIGA] = NULL;395			link->dc->res_pool->dig_link_enc_count--;396		}397		link->link_enc->funcs->destroy(&link->link_enc);398	}399 400	if (link->local_sink)401		dc_sink_release(link->local_sink);402 403	for (i = 0; i < link->sink_count; ++i)404		dc_sink_release(link->remote_sinks[i]);405}406 407static enum channel_id get_ddc_line(struct dc_link *link)408{409	struct ddc *ddc;410	enum channel_id channel;411 412	channel = CHANNEL_ID_UNKNOWN;413 414	ddc = get_ddc_pin(link->ddc);415 416	if (ddc) {417		switch (dal_ddc_get_line(ddc)) {418		case GPIO_DDC_LINE_DDC1:419			channel = CHANNEL_ID_DDC1;420			break;421		case GPIO_DDC_LINE_DDC2:422			channel = CHANNEL_ID_DDC2;423			break;424		case GPIO_DDC_LINE_DDC3:425			channel = CHANNEL_ID_DDC3;426			break;427		case GPIO_DDC_LINE_DDC4:428			channel = CHANNEL_ID_DDC4;429			break;430		case GPIO_DDC_LINE_DDC5:431			channel = CHANNEL_ID_DDC5;432			break;433		case GPIO_DDC_LINE_DDC6:434			channel = CHANNEL_ID_DDC6;435			break;436		case GPIO_DDC_LINE_DDC_VGA:437			channel = CHANNEL_ID_DDC_VGA;438			break;439		case GPIO_DDC_LINE_I2C_PAD:440			channel = CHANNEL_ID_I2C_PAD;441			break;442		default:443			BREAK_TO_DEBUGGER();444			break;445		}446	}447 448	return channel;449}450 451static bool construct_phy(struct dc_link *link,452			      const struct link_init_data *init_params)453{454	uint8_t i;455	struct ddc_service_init_data ddc_service_init_data = { 0 };456	struct dc_context *dc_ctx = init_params->ctx;457	struct encoder_init_data enc_init_data = { 0 };458	struct panel_cntl_init_data panel_cntl_init_data = { 0 };459	struct dc_bios *bios = init_params->dc->ctx->dc_bios;460	const struct dc_vbios_funcs *bp_funcs = bios->funcs;461	struct bp_disp_connector_caps_info disp_connect_caps_info = { 0 };462 463	DC_LOGGER_INIT(dc_ctx->logger);464 465	link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;466	link->irq_source_hpd_rx = DC_IRQ_SOURCE_INVALID;467	link->link_status.dpcd_caps = &link->dpcd_caps;468 469	link->dc = init_params->dc;470	link->ctx = dc_ctx;471	link->link_index = init_params->link_index;472 473	memset(&link->preferred_training_settings, 0,474	       sizeof(struct dc_link_training_overrides));475	memset(&link->preferred_link_setting, 0,476	       sizeof(struct dc_link_settings));477 478	link->link_id =479		bios->funcs->get_connector_id(bios, init_params->connector_index);480 481	link->ep_type = DISPLAY_ENDPOINT_PHY;482 483	DC_LOG_DC("BIOS object table - link_id: %d", link->link_id.id);484 485	if (bios->funcs->get_disp_connector_caps_info) {486		bios->funcs->get_disp_connector_caps_info(bios, link->link_id, &disp_connect_caps_info);487		link->is_internal_display = disp_connect_caps_info.INTERNAL_DISPLAY;488		DC_LOG_DC("BIOS object table - is_internal_display: %d", link->is_internal_display);489	}490 491	if (link->link_id.type != OBJECT_TYPE_CONNECTOR) {492		dm_output_to_console("%s: Invalid Connector ObjectID from Adapter Service for connector index:%d! type %d expected %d\n",493				     __func__, init_params->connector_index,494				     link->link_id.type, OBJECT_TYPE_CONNECTOR);495		goto create_fail;496	}497 498	if (link->dc->res_pool->funcs->link_init)499		link->dc->res_pool->funcs->link_init(link);500 501	link->hpd_gpio = link_get_hpd_gpio(link->ctx->dc_bios, link->link_id,502				      link->ctx->gpio_service);503 504	if (link->hpd_gpio) {505		dal_gpio_open(link->hpd_gpio, GPIO_MODE_INTERRUPT);506		dal_gpio_unlock_pin(link->hpd_gpio);507		link->irq_source_hpd = dal_irq_get_source(link->hpd_gpio);508 509		DC_LOG_DC("BIOS object table - hpd_gpio id: %d", link->hpd_gpio->id);510		DC_LOG_DC("BIOS object table - hpd_gpio en: %d", link->hpd_gpio->en);511	}512 513	switch (link->link_id.id) {514	case CONNECTOR_ID_HDMI_TYPE_A:515		link->connector_signal = SIGNAL_TYPE_HDMI_TYPE_A;516 517		break;518	case CONNECTOR_ID_SINGLE_LINK_DVID:519	case CONNECTOR_ID_SINGLE_LINK_DVII:520		link->connector_signal = SIGNAL_TYPE_DVI_SINGLE_LINK;521		break;522	case CONNECTOR_ID_DUAL_LINK_DVID:523	case CONNECTOR_ID_DUAL_LINK_DVII:524		link->connector_signal = SIGNAL_TYPE_DVI_DUAL_LINK;525		break;526	case CONNECTOR_ID_DISPLAY_PORT:527	case CONNECTOR_ID_MXM:528	case CONNECTOR_ID_USBC:529		link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT;530 531		if (link->hpd_gpio)532			link->irq_source_hpd_rx =533					dal_irq_get_rx_source(link->hpd_gpio);534 535		break;536	case CONNECTOR_ID_EDP:537		link->connector_signal = SIGNAL_TYPE_EDP;538 539		if (link->hpd_gpio) {540			if (!link->dc->config.allow_edp_hotplug_detection)541				link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;542 543			switch (link->dc->config.allow_edp_hotplug_detection) {544			case HPD_EN_FOR_ALL_EDP:545				link->irq_source_hpd_rx =546						dal_irq_get_rx_source(link->hpd_gpio);547				break;548			case HPD_EN_FOR_PRIMARY_EDP_ONLY:549				if (link->link_index == 0)550					link->irq_source_hpd_rx =551						dal_irq_get_rx_source(link->hpd_gpio);552				else553					link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;554				break;555			case HPD_EN_FOR_SECONDARY_EDP_ONLY:556				if (link->link_index == 1)557					link->irq_source_hpd_rx =558						dal_irq_get_rx_source(link->hpd_gpio);559				else560					link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;561				break;562			default:563				link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;564				break;565			}566		}567 568		break;569	case CONNECTOR_ID_LVDS:570		link->connector_signal = SIGNAL_TYPE_LVDS;571		break;572	default:573		DC_LOG_WARNING("Unsupported Connector type:%d!\n",574			       link->link_id.id);575		goto create_fail;576	}577 578	LINK_INFO("Connector[%d] description: signal: %s\n",579		  init_params->connector_index,580		  signal_type_to_string(link->connector_signal));581 582	ddc_service_init_data.ctx = link->ctx;583	ddc_service_init_data.id = link->link_id;584	ddc_service_init_data.link = link;585	link->ddc = link_create_ddc_service(&ddc_service_init_data);586 587	if (!link->ddc) {588		DC_ERROR("Failed to create ddc_service!\n");589		goto ddc_create_fail;590	}591 592	if (!link->ddc->ddc_pin) {593		DC_ERROR("Failed to get I2C info for connector!\n");594		goto ddc_create_fail;595	}596 597	link->ddc_hw_inst =598		dal_ddc_get_line(get_ddc_pin(link->ddc));599 600	enc_init_data.ctx = dc_ctx;601	bp_funcs->get_src_obj(dc_ctx->dc_bios, link->link_id, 0,602			      &enc_init_data.encoder);603	enc_init_data.connector = link->link_id;604	enc_init_data.channel = get_ddc_line(link);605	enc_init_data.hpd_source = get_hpd_line(link);606 607	link->hpd_src = enc_init_data.hpd_source;608 609	enc_init_data.transmitter =610		translate_encoder_to_transmitter(enc_init_data.encoder);611	link->link_enc =612		link->dc->res_pool->funcs->link_enc_create(dc_ctx, &enc_init_data);613 614	if (!link->link_enc) {615		DC_ERROR("Failed to create link encoder!\n");616		goto link_enc_create_fail;617	}618 619	DC_LOG_DC("BIOS object table - DP_IS_USB_C: %d", link->link_enc->features.flags.bits.DP_IS_USB_C);620	DC_LOG_DC("BIOS object table - IS_DP2_CAPABLE: %d", link->link_enc->features.flags.bits.IS_DP2_CAPABLE);621 622	/* Update link encoder tracking variables. These are used for the dynamic623	 * assignment of link encoders to streams.624	 */625	link->eng_id = link->link_enc->preferred_engine;626	link->dc->res_pool->link_encoders[link->eng_id - ENGINE_ID_DIGA] = link->link_enc;627	link->dc->res_pool->dig_link_enc_count++;628 629	link->link_enc_hw_inst = link->link_enc->transmitter;630 631	if (link->dc->res_pool->funcs->panel_cntl_create &&632		(link->link_id.id == CONNECTOR_ID_EDP ||633			link->link_id.id == CONNECTOR_ID_LVDS)) {634		panel_cntl_init_data.ctx = dc_ctx;635		panel_cntl_init_data.inst = panel_cntl_init_data.ctx->dc_edp_id_count;636		panel_cntl_init_data.eng_id = link->eng_id;637		link->panel_cntl =638			link->dc->res_pool->funcs->panel_cntl_create(639								&panel_cntl_init_data);640		panel_cntl_init_data.ctx->dc_edp_id_count++;641 642		if (link->panel_cntl == NULL) {643			DC_ERROR("Failed to create link panel_cntl!\n");644			goto panel_cntl_create_fail;645		}646	}647	for (i = 0; i < 4; i++) {648		if (bp_funcs->get_device_tag(dc_ctx->dc_bios,649					     link->link_id, i,650					     &link->device_tag) != BP_RESULT_OK) {651			DC_ERROR("Failed to find device tag!\n");652			goto device_tag_fail;653		}654 655		/* Look for device tag that matches connector signal,656		 * CRT for rgb, LCD for other supported signal tyes657		 */658		if (!bp_funcs->is_device_id_supported(dc_ctx->dc_bios,659						      link->device_tag.dev_id))660			continue;661		if (link->device_tag.dev_id.device_type == DEVICE_TYPE_CRT &&662		    link->connector_signal != SIGNAL_TYPE_RGB)663			continue;664		if (link->device_tag.dev_id.device_type == DEVICE_TYPE_LCD &&665		    link->connector_signal == SIGNAL_TYPE_RGB)666			continue;667 668		DC_LOG_DC("BIOS object table - device_tag.acpi_device: %d", link->device_tag.acpi_device);669		DC_LOG_DC("BIOS object table - device_tag.dev_id.device_type: %d", link->device_tag.dev_id.device_type);670		DC_LOG_DC("BIOS object table - device_tag.dev_id.enum_id: %d", link->device_tag.dev_id.enum_id);671		break;672	}673 674	if (bios->integrated_info) {675		/* Look for channel mapping corresponding to connector and device tag */676		for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; i++) {677			struct external_display_path *path =678				&bios->integrated_info->ext_disp_conn_info.path[i];679 680			if (path->device_connector_id.enum_id == link->link_id.enum_id &&681			    path->device_connector_id.id == link->link_id.id &&682			    path->device_connector_id.type == link->link_id.type) {683				if (link->device_tag.acpi_device != 0 &&684				    path->device_acpi_enum == link->device_tag.acpi_device) {685					link->ddi_channel_mapping = path->channel_mapping;686					link->chip_caps = path->caps;687					DC_LOG_DC("BIOS object table - ddi_channel_mapping: 0x%04X",688						  link->ddi_channel_mapping.raw);689					DC_LOG_DC("BIOS object table - chip_caps: %d",690						  link->chip_caps);691				} else if (path->device_tag ==692					   link->device_tag.dev_id.raw_device_tag) {693					link->ddi_channel_mapping = path->channel_mapping;694					link->chip_caps = path->caps;695					DC_LOG_DC("BIOS object table - ddi_channel_mapping: 0x%04X",696						  link->ddi_channel_mapping.raw);697					DC_LOG_DC("BIOS object table - chip_caps: %d",698						  link->chip_caps);699				}700 701				if (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) {702					link->bios_forced_drive_settings.VOLTAGE_SWING =703						(bios->integrated_info->ext_disp_conn_info.fixdpvoltageswing & 0x3);704					link->bios_forced_drive_settings.PRE_EMPHASIS =705						((bios->integrated_info->ext_disp_conn_info.fixdpvoltageswing >> 2) & 0x3);706				}707 708				break;709			}710		}711	}712	if (bios->funcs->get_atom_dc_golden_table)713		bios->funcs->get_atom_dc_golden_table(bios);714 715	/*716	 * TODO check if GPIO programmed correctly717	 *718	 * If GPIO isn't programmed correctly HPD might not rise or drain719	 * fast enough, leading to bounces.720	 */721	program_hpd_filter(link);722 723	link->psr_settings.psr_vtotal_control_support = false;724	link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED;725 726	DC_LOG_DC("BIOS object table - %s finished successfully.\n", __func__);727	return true;728device_tag_fail:729	link->link_enc->funcs->destroy(&link->link_enc);730link_enc_create_fail:731	if (link->panel_cntl != NULL)732		link->panel_cntl->funcs->destroy(&link->panel_cntl);733panel_cntl_create_fail:734	link_destroy_ddc_service(&link->ddc);735ddc_create_fail:736create_fail:737 738	if (link->hpd_gpio) {739		dal_gpio_destroy_irq(&link->hpd_gpio);740		link->hpd_gpio = NULL;741	}742 743	DC_LOG_DC("BIOS object table - %s failed.\n", __func__);744	return false;745}746 747static bool construct_dpia(struct dc_link *link,748			      const struct link_init_data *init_params)749{750	struct ddc_service_init_data ddc_service_init_data = { 0 };751	struct dc_context *dc_ctx = init_params->ctx;752 753	DC_LOGGER_INIT(dc_ctx->logger);754 755	/* Initialized irq source for hpd and hpd rx */756	link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;757	link->irq_source_hpd_rx = DC_IRQ_SOURCE_INVALID;758	link->link_status.dpcd_caps = &link->dpcd_caps;759 760	link->dc = init_params->dc;761	link->ctx = dc_ctx;762	link->link_index = init_params->link_index;763 764	memset(&link->preferred_training_settings, 0,765	       sizeof(struct dc_link_training_overrides));766	memset(&link->preferred_link_setting, 0,767	       sizeof(struct dc_link_settings));768 769	/* Dummy Init for linkid */770	link->link_id.type = OBJECT_TYPE_CONNECTOR;771	link->link_id.id = CONNECTOR_ID_DISPLAY_PORT;772	link->link_id.enum_id = ENUM_ID_1 + init_params->connector_index;773	link->is_internal_display = false;774	link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT;775	LINK_INFO("Connector[%d] description:signal %d\n",776		  init_params->connector_index,777		  link->connector_signal);778 779	link->ep_type = DISPLAY_ENDPOINT_USB4_DPIA;780	link->is_dig_mapping_flexible = true;781 782	/* TODO: Initialize link : funcs->link_init */783 784	ddc_service_init_data.ctx = link->ctx;785	ddc_service_init_data.id = link->link_id;786	ddc_service_init_data.link = link;787	/* Set indicator for dpia link so that ddc wont be created */788	ddc_service_init_data.is_dpia_link = true;789 790	link->ddc = link_create_ddc_service(&ddc_service_init_data);791	if (!link->ddc) {792		DC_ERROR("Failed to create ddc_service!\n");793		goto ddc_create_fail;794	}795 796	/* Set dpia port index : 0 to number of dpia ports */797	link->ddc_hw_inst = init_params->connector_index;798 799	// Assign Dpia preferred eng_id800	if (link->dc->res_pool->funcs->get_preferred_eng_id_dpia)801		link->dpia_preferred_eng_id = link->dc->res_pool->funcs->get_preferred_eng_id_dpia(link->ddc_hw_inst);802 803	/* TODO: Create link encoder */804 805	link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED;806 807	/* Some docks seem to NAK I2C writes to segment pointer with mot=0. */808	link->wa_flags.dp_mot_reset_segment = true;809 810	return true;811 812ddc_create_fail:813	return false;814}815 816static bool link_construct(struct dc_link *link,817			      const struct link_init_data *init_params)818{819	/* Handle dpia case */820	if (init_params->is_dpia_link == true)821		return construct_dpia(link, init_params);822	else823		return construct_phy(link, init_params);824}825 826struct dc_link *link_create(const struct link_init_data *init_params)827{828	struct dc_link *link =829			kzalloc(sizeof(*link), GFP_KERNEL);830 831	if (NULL == link)832		goto alloc_fail;833 834	if (false == link_construct(link, init_params))835		goto construct_fail;836 837	return link;838 839construct_fail:840	kfree(link);841 842alloc_fail:843	return NULL;844}845 846void link_destroy(struct dc_link **link)847{848	link_destruct(*link);849	kfree(*link);850	*link = NULL;851}852