File Index
Files and directories
Sign in
FILE

link_factory.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/amd/display/dc/link/link_factory.c C
  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_hpd.h"
 45#include "gpio_service_interface.h"
 46#include "atomfirmware.h"
 47
 48#define DC_LOGGER \
 49	dc_ctx->logger
 50#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 using
 65 * various link protocols. It also provides helper functions to interpret
 66 * certain capabilities or status based on the states it manages or retrieve
 67 * 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 also
 97 * 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_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 */
111static 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 */
131static 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 */
149static 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 */
177static 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 */
188static 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 */
201static 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_setup_replay = edp_setup_replay;
219	link_srv->edp_send_replay_cmd = edp_send_replay_cmd;
220	link_srv->edp_set_coasting_vtotal = edp_set_coasting_vtotal;
221	link_srv->edp_replay_residency = edp_replay_residency;
222	link_srv->edp_set_replay_power_opt_and_coasting_vtotal = edp_set_replay_power_opt_and_coasting_vtotal;
223
224	link_srv->edp_wait_for_t12 = edp_wait_for_t12;
225	link_srv->edp_is_ilr_optimization_required =
226			edp_is_ilr_optimization_required;
227	link_srv->edp_backlight_enable_aux = edp_backlight_enable_aux;
228	link_srv->edp_add_delay_for_T9 = edp_add_delay_for_T9;
229	link_srv->edp_receiver_ready_T9 = edp_receiver_ready_T9;
230	link_srv->edp_receiver_ready_T7 = edp_receiver_ready_T7;
231	link_srv->edp_power_alpm_dpcd_enable = edp_power_alpm_dpcd_enable;
232	link_srv->edp_set_panel_power = edp_set_panel_power;
233}
234
235/* link dp cts implements dp compliance test automation protocols and manual
236 * testing interfaces for debugging and certification purpose.
237 */
238static void construct_link_service_dp_cts(struct link_service *link_srv)
239{
240	link_srv->dp_handle_automated_test = dp_handle_automated_test;
241	link_srv->dp_set_test_pattern = dp_set_test_pattern;
242	link_srv->dp_set_preferred_link_settings =
243			dp_set_preferred_link_settings;
244	link_srv->dp_set_preferred_training_settings =
245			dp_set_preferred_training_settings;
246}
247
248/* link dp trace implements tracing interfaces for tracking major dp sequences
249 * including execution status and timestamps
250 */
251static void construct_link_service_dp_trace(struct link_service *link_srv)
252{
253	link_srv->dp_trace_is_initialized = dp_trace_is_initialized;
254	link_srv->dp_trace_set_is_logged_flag = dp_trace_set_is_logged_flag;
255	link_srv->dp_trace_is_logged = dp_trace_is_logged;
256	link_srv->dp_trace_get_lt_end_timestamp = dp_trace_get_lt_end_timestamp;
257	link_srv->dp_trace_get_lt_counts = dp_trace_get_lt_counts;
258	link_srv->dp_trace_get_link_loss_count = dp_trace_get_link_loss_count;
259	link_srv->dp_trace_set_edp_power_timestamp =
260			dp_trace_set_edp_power_timestamp;
261	link_srv->dp_trace_get_edp_poweron_timestamp =
262			dp_trace_get_edp_poweron_timestamp;
263	link_srv->dp_trace_get_edp_poweroff_timestamp =
264			dp_trace_get_edp_poweroff_timestamp;
265	link_srv->dp_trace_source_sequence = dp_trace_source_sequence;
266}
267
268static void construct_link_service(struct link_service *link_srv)
269{
270	/* All link service functions should fall under some sub categories.
271	 * If a new function doesn't perfectly fall under an existing sub
272	 * category, it must be that you are either adding a whole new aspect of
273	 * responsibility to link service or something doesn't belong to link
274	 * service. In that case please contact the arch owner to arrange a
275	 * design review meeting.
276	 */
277	construct_link_service_factory(link_srv);
278	construct_link_service_detection(link_srv);
279	construct_link_service_resource(link_srv);
280	construct_link_service_validation(link_srv);
281	construct_link_service_dpms(link_srv);
282	construct_link_service_ddc(link_srv);
283	construct_link_service_dp_capability(link_srv);
284	construct_link_service_dp_phy_or_dpia(link_srv);
285	construct_link_service_dp_irq_handler(link_srv);
286	construct_link_service_edp_panel_control(link_srv);
287	construct_link_service_dp_cts(link_srv);
288	construct_link_service_dp_trace(link_srv);
289}
290
291struct link_service *link_create_link_service(void)
292{
293	struct link_service *link_srv = kzalloc(sizeof(*link_srv), GFP_KERNEL);
294
295	if (link_srv == NULL)
296		goto fail;
297
298	construct_link_service(link_srv);
299
300	return link_srv;
301fail:
302	return NULL;
303}
304
305void link_destroy_link_service(struct link_service **link_srv)
306{
307	kfree(*link_srv);
308	*link_srv = NULL;
309}
310
311static enum transmitter translate_encoder_to_transmitter(
312		struct graphics_object_id encoder)
313{
314	switch (encoder.id) {
315	case ENCODER_ID_INTERNAL_UNIPHY:
316		switch (encoder.enum_id) {
317		case ENUM_ID_1:
318			return TRANSMITTER_UNIPHY_A;
319		case ENUM_ID_2:
320			return TRANSMITTER_UNIPHY_B;
321		default:
322			return TRANSMITTER_UNKNOWN;
323		}
324	break;
325	case ENCODER_ID_INTERNAL_UNIPHY1:
326		switch (encoder.enum_id) {
327		case ENUM_ID_1:
328			return TRANSMITTER_UNIPHY_C;
329		case ENUM_ID_2:
330			return TRANSMITTER_UNIPHY_D;
331		default:
332			return TRANSMITTER_UNKNOWN;
333		}
334	break;
335	case ENCODER_ID_INTERNAL_UNIPHY2:
336		switch (encoder.enum_id) {
337		case ENUM_ID_1:
338			return TRANSMITTER_UNIPHY_E;
339		case ENUM_ID_2:
340			return TRANSMITTER_UNIPHY_F;
341		default:
342			return TRANSMITTER_UNKNOWN;
343		}
344	break;
345	case ENCODER_ID_INTERNAL_UNIPHY3:
346		switch (encoder.enum_id) {
347		case ENUM_ID_1:
348			return TRANSMITTER_UNIPHY_G;
349		default:
350			return TRANSMITTER_UNKNOWN;
351		}
352	break;
353	default:
354		return TRANSMITTER_UNKNOWN;
355	}
356}
357
358static void link_destruct(struct dc_link *link)
359{
360	int i;
361
362	if (link->hpd_gpio) {
363		dal_gpio_destroy_irq(&link->hpd_gpio);
364		link->hpd_gpio = NULL;
365	}
366
367	if (link->ddc)
368		link_destroy_ddc_service(&link->ddc);
369
370	if (link->panel_cntl)
371		link->panel_cntl->funcs->destroy(&link->panel_cntl);
372
373	if (link->link_enc && !link->is_dig_mapping_flexible) {
374		/* Update link encoder resource tracking variables. These are used for
375		 * the dynamic assignment of link encoders to streams. Virtual links
376		 * are not assigned encoder resources on creation.
377		 */
378		if (link->link_id.id != CONNECTOR_ID_VIRTUAL && link->eng_id != ENGINE_ID_UNKNOWN) {
379			link->dc->res_pool->link_encoders[link->eng_id - ENGINE_ID_DIGA] = NULL;
380			link->dc->res_pool->dig_link_enc_count--;
381		}
382		link->link_enc->funcs->destroy(&link->link_enc);
383	}
384
385	if (link->local_sink)
386		dc_sink_release(link->local_sink);
387
388	for (i = 0; i < link->sink_count; ++i)
389		dc_sink_release(link->remote_sinks[i]);
390}
391
392static enum channel_id get_ddc_line(struct dc_link *link)
393{
394	struct ddc *ddc;
395	enum channel_id channel;
396
397	channel = CHANNEL_ID_UNKNOWN;
398
399	ddc = get_ddc_pin(link->ddc);
400
401	if (ddc) {
402		switch (dal_ddc_get_line(ddc)) {
403		case GPIO_DDC_LINE_DDC1:
404			channel = CHANNEL_ID_DDC1;
405			break;
406		case GPIO_DDC_LINE_DDC2:
407			channel = CHANNEL_ID_DDC2;
408			break;
409		case GPIO_DDC_LINE_DDC3:
410			channel = CHANNEL_ID_DDC3;
411			break;
412		case GPIO_DDC_LINE_DDC4:
413			channel = CHANNEL_ID_DDC4;
414			break;
415		case GPIO_DDC_LINE_DDC5:
416			channel = CHANNEL_ID_DDC5;
417			break;
418		case GPIO_DDC_LINE_DDC6:
419			channel = CHANNEL_ID_DDC6;
420			break;
421		case GPIO_DDC_LINE_DDC_VGA:
422			channel = CHANNEL_ID_DDC_VGA;
423			break;
424		case GPIO_DDC_LINE_I2C_PAD:
425			channel = CHANNEL_ID_I2C_PAD;
426			break;
427		default:
428			BREAK_TO_DEBUGGER();
429			break;
430		}
431	}
432
433	return channel;
434}
435
436static enum engine_id find_analog_engine(struct dc_link *link, struct graphics_object_id *enc)
437{
438	struct dc_bios *bp = link->ctx->dc_bios;
439	enum bp_result bp_result = BP_RESULT_OK;
440	int i;
441
442	for (i = 0; i < 3; i++) {
443		bp_result = bp->funcs->get_src_obj(bp, link->link_id, i, enc);
444
445		if (bp_result != BP_RESULT_OK)
446			return ENGINE_ID_UNKNOWN;
447
448		switch (enc->id) {
449		case ENCODER_ID_INTERNAL_DAC1:
450		case ENCODER_ID_INTERNAL_KLDSCP_DAC1:
451			return ENGINE_ID_DACA;
452		case ENCODER_ID_INTERNAL_DAC2:
453		case ENCODER_ID_INTERNAL_KLDSCP_DAC2:
454			return ENGINE_ID_DACB;
455		}
456	}
457
458	memset(enc, 0, sizeof(*enc));
459	return ENGINE_ID_UNKNOWN;
460}
461
462static bool analog_engine_supported(const enum engine_id engine_id)
463{
464	return engine_id == ENGINE_ID_DACA ||
465		engine_id == ENGINE_ID_DACB;
466}
467
468static bool construct_phy(struct dc_link *link,
469			      const struct link_init_data *init_params)
470{
471	uint8_t i;
472	struct ddc_service_init_data ddc_service_init_data = { 0 };
473	struct dc_context *dc_ctx = init_params->ctx;
474	struct encoder_init_data enc_init_data = { 0 };
475	struct panel_cntl_init_data panel_cntl_init_data = { 0 };
476	struct dc_bios *bios = init_params->dc->ctx->dc_bios;
477	const struct dc_vbios_funcs *bp_funcs = bios->funcs;
478	struct bp_disp_connector_caps_info disp_connect_caps_info = { 0 };
479	struct graphics_object_id link_encoder = { 0 };
480	enum transmitter transmitter_from_encoder;
481	enum engine_id link_analog_engine;
482
483	DC_LOGGER_INIT(dc_ctx->logger);
484
485	link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
486	link->irq_source_hpd_rx = DC_IRQ_SOURCE_INVALID;
487	link->irq_source_read_request = DC_IRQ_SOURCE_INVALID;
488	link->link_status.dpcd_caps = &link->dpcd_caps;
489
490	link->dc = init_params->dc;
491	link->ctx = dc_ctx;
492	link->link_index = init_params->link_index;
493
494	memset(&link->preferred_training_settings, 0,
495	       sizeof(struct dc_link_training_overrides));
496	memset(&link->preferred_link_setting, 0,
497	       sizeof(struct dc_link_settings));
498
499	link->link_id =
500		bios->funcs->get_connector_id(bios, init_params->connector_index);
501
502	link->ep_type = DISPLAY_ENDPOINT_PHY;
503
504	DC_LOG_DC("BIOS object table - link_id: %d", link->link_id.id);
505
506	/* Determine early if the link has any supported encoders,
507	 * so that we avoid initializing DDC and HPD, etc.
508	 */
509	bp_funcs->get_src_obj(bios, link->link_id, 0, &link_encoder);
510	transmitter_from_encoder = translate_encoder_to_transmitter(link_encoder);
511	link_analog_engine = find_analog_engine(link, &enc_init_data.analog_encoder);
512
513	if (transmitter_from_encoder == TRANSMITTER_UNKNOWN &&
514	    !analog_engine_supported(link_analog_engine)) {
515		DC_LOG_WARNING("link_id %d has unsupported encoder\n", link->link_id.id);
516		goto create_fail;
517	}
518
519	if (bios->funcs->get_disp_connector_caps_info) {
520		bios->funcs->get_disp_connector_caps_info(bios, link->link_id, &disp_connect_caps_info);
521		link->is_internal_display = disp_connect_caps_info.INTERNAL_DISPLAY;
522		DC_LOG_DC("BIOS object table - is_internal_display: %d", link->is_internal_display);
523	}
524
525	if (link->link_id.type != OBJECT_TYPE_CONNECTOR) {
526		dm_output_to_console("%s: Invalid Connector ObjectID from Adapter Service for connector index:%d! type %d expected %d\n",
527				     __func__, init_params->connector_index,
528				     link->link_id.type, OBJECT_TYPE_CONNECTOR);
529		goto create_fail;
530	}
531
532	if (link->dc->res_pool->funcs->link_init)
533		link->dc->res_pool->funcs->link_init(link);
534
535	link->hpd_gpio = link_get_hpd_gpio(link->ctx->dc_bios, link->link_id,
536				      link->ctx->gpio_service);
537
538	if (link->hpd_gpio) {
539		dal_gpio_open(link->hpd_gpio, GPIO_MODE_INTERRUPT);
540		dal_gpio_unlock_pin(link->hpd_gpio);
541		link->irq_source_hpd = dal_irq_get_source(link->hpd_gpio);
542
543		DC_LOG_DC("BIOS object table - hpd_gpio id: %d", link->hpd_gpio->id);
544		DC_LOG_DC("BIOS object table - hpd_gpio en: %d", link->hpd_gpio->en);
545	}
546
547	switch (link->link_id.id) {
548	case CONNECTOR_ID_HDMI_TYPE_A:
549		link->connector_signal = SIGNAL_TYPE_HDMI_TYPE_A;
550
551		if (link->hpd_gpio)
552			link->irq_source_read_request =
553					dal_irq_get_read_request(link->hpd_gpio);
554		break;
555	case CONNECTOR_ID_SINGLE_LINK_DVID:
556	case CONNECTOR_ID_SINGLE_LINK_DVII:
557		link->connector_signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
558		break;
559	case CONNECTOR_ID_DUAL_LINK_DVID:
560	case CONNECTOR_ID_DUAL_LINK_DVII:
561		link->connector_signal = SIGNAL_TYPE_DVI_DUAL_LINK;
562		break;
563	case CONNECTOR_ID_VGA:
564		link->connector_signal = SIGNAL_TYPE_RGB;
565		break;
566	case CONNECTOR_ID_DISPLAY_PORT:
567	case CONNECTOR_ID_MXM:
568	case CONNECTOR_ID_USBC:
569		link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT;
570
571		if (link->hpd_gpio)
572			link->irq_source_hpd_rx =
573					dal_irq_get_rx_source(link->hpd_gpio);
574
575		break;
576	case CONNECTOR_ID_EDP:
577		// If smartmux is supported, only create the link on the primary eDP.
578		// Dual eDP is not supported with smartmux.
579		if (!(!link->dc->config.smart_mux_version || dc_ctx->dc_edp_id_count == 0))
580			goto create_fail;
581
582		link->connector_signal = SIGNAL_TYPE_EDP;
583
584		if (link->hpd_gpio) {
585			if (!link->dc->config.allow_edp_hotplug_detection
586				&& !is_smartmux_suported(link))
587				link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
588
589			switch (link->dc->config.allow_edp_hotplug_detection) {
590			case HPD_EN_FOR_ALL_EDP:
591				link->irq_source_hpd_rx =
592						dal_irq_get_rx_source(link->hpd_gpio);
593				break;
594			case HPD_EN_FOR_PRIMARY_EDP_ONLY:
595				if (link->link_index == 0)
596					link->irq_source_hpd_rx =
597						dal_irq_get_rx_source(link->hpd_gpio);
598				else
599					link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
600				break;
601			case HPD_EN_FOR_SECONDARY_EDP_ONLY:
602				if (link->link_index == 1)
603					link->irq_source_hpd_rx =
604						dal_irq_get_rx_source(link->hpd_gpio);
605				else
606					link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
607				break;
608			default:
609				link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
610				break;
611			}
612		}
613
614		break;
615	case CONNECTOR_ID_LVDS:
616		link->connector_signal = SIGNAL_TYPE_LVDS;
617		break;
618	default:
619		DC_LOG_WARNING("Unsupported Connector type:%d!\n",
620			       link->link_id.id);
621		goto create_fail;
622	}
623
624	LINK_INFO("Connector[%d] description: signal: %s\n",
625		  init_params->connector_index,
626		  signal_type_to_string(link->connector_signal));
627
628	ddc_service_init_data.ctx = link->ctx;
629	ddc_service_init_data.id = link->link_id;
630	ddc_service_init_data.link = link;
631	link->ddc = link_create_ddc_service(&ddc_service_init_data);
632
633	if (!link->ddc) {
634		DC_ERROR("Failed to create ddc_service!\n");
635		goto ddc_create_fail;
636	}
637
638	if (!link->ddc->ddc_pin) {
639		DC_ERROR("Failed to get I2C info for connector!\n");
640		goto ddc_create_fail;
641	}
642
643	link->ddc_hw_inst =
644		dal_ddc_get_line(get_ddc_pin(link->ddc));
645
646	enc_init_data.ctx = dc_ctx;
647	enc_init_data.connector = link->link_id;
648	enc_init_data.channel = get_ddc_line(link);
649	enc_init_data.hpd_source = get_hpd_line(link);
650	enc_init_data.transmitter = transmitter_from_encoder;
651	enc_init_data.encoder = link_encoder;
652	enc_init_data.analog_engine = link_analog_engine;
653
654	link->hpd_src = enc_init_data.hpd_source;
655
656	link->link_enc =
657		link->dc->res_pool->funcs->link_enc_create(dc_ctx, &enc_init_data);
658
659	if (!link->link_enc) {
660		DC_ERROR("Failed to create link encoder!\n");
661		goto link_enc_create_fail;
662	}
663
664	DC_LOG_DC("BIOS object table - DP_IS_USB_C: %d", link->link_enc->features.flags.bits.DP_IS_USB_C);
665	DC_LOG_DC("BIOS object table - IS_DP2_CAPABLE: %d", link->link_enc->features.flags.bits.IS_DP2_CAPABLE);
666
667	/* Update link encoder tracking variables. These are used for the dynamic
668	 * assignment of link encoders to streams.
669	 */
670	link->eng_id = link->link_enc->preferred_engine;
671	link->dc->res_pool->link_encoders[link->eng_id - ENGINE_ID_DIGA] = link->link_enc;
672	link->dc->res_pool->dig_link_enc_count++;
673
674	link->link_enc_hw_inst = link->link_enc->transmitter;
675
676	if (link->dc->res_pool->funcs->panel_cntl_create &&
677		(link->link_id.id == CONNECTOR_ID_EDP ||
678			link->link_id.id == CONNECTOR_ID_LVDS)) {
679		panel_cntl_init_data.ctx = dc_ctx;
680		panel_cntl_init_data.inst = panel_cntl_init_data.ctx->dc_edp_id_count;
681		panel_cntl_init_data.eng_id = link->eng_id;
682		link->panel_cntl =
683			link->dc->res_pool->funcs->panel_cntl_create(
684								&panel_cntl_init_data);
685		panel_cntl_init_data.ctx->dc_edp_id_count++;
686
687		if (link->panel_cntl == NULL) {
688			DC_ERROR("Failed to create link panel_cntl!\n");
689			goto panel_cntl_create_fail;
690		}
691	}
692	for (i = 0; i < 4; i++) {
693		if (bp_funcs->get_device_tag(dc_ctx->dc_bios,
694					     link->link_id, i,
695					     &link->device_tag) != BP_RESULT_OK) {
696			DC_ERROR("Failed to find device tag!\n");
697			goto device_tag_fail;
698		}
699
700		/* Look for device tag that matches connector signal,
701		 * CRT for rgb, LCD for other supported signal types
702		 */
703		if (!bp_funcs->is_device_id_supported(dc_ctx->dc_bios,
704						      link->device_tag.dev_id))
705			continue;
706		if (link->device_tag.dev_id.device_type == DEVICE_TYPE_CRT &&
707		    link->connector_signal != SIGNAL_TYPE_RGB)
708			continue;
709		if (link->device_tag.dev_id.device_type == DEVICE_TYPE_LCD &&
710		    link->connector_signal == SIGNAL_TYPE_RGB)
711			continue;
712
713		DC_LOG_DC("BIOS object table - device_tag.acpi_device: %d", link->device_tag.acpi_device);
714		DC_LOG_DC("BIOS object table - device_tag.dev_id.device_type: %d", link->device_tag.dev_id.device_type);
715		DC_LOG_DC("BIOS object table - device_tag.dev_id.enum_id: %d", link->device_tag.dev_id.enum_id);
716		break;
717	}
718
719	if (bios->integrated_info) {
720		/* Look for channel mapping corresponding to connector and device tag */
721		for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; i++) {
722			struct external_display_path *path =
723				&bios->integrated_info->ext_disp_conn_info.path[i];
724
725			if (path->device_connector_id.enum_id == link->link_id.enum_id &&
726			    path->device_connector_id.id == link->link_id.id &&
727			    path->device_connector_id.type == link->link_id.type) {
728				if (link->device_tag.acpi_device != 0 &&
729				    path->device_acpi_enum == link->device_tag.acpi_device) {
730					link->ddi_channel_mapping = path->channel_mapping;
731					link->chip_caps = path->caps;
732					DC_LOG_DC("BIOS object table - ddi_channel_mapping: 0x%04X",
733						  link->ddi_channel_mapping.raw);
734					DC_LOG_DC("BIOS object table - chip_caps: %d",
735						  link->chip_caps);
736				} else if (path->device_tag ==
737					   link->device_tag.dev_id.raw_device_tag) {
738					link->ddi_channel_mapping = path->channel_mapping;
739					link->chip_caps = path->caps;
740					DC_LOG_DC("BIOS object table - ddi_channel_mapping: 0x%04X",
741						  link->ddi_channel_mapping.raw);
742					DC_LOG_DC("BIOS object table - chip_caps: %d",
743						  link->chip_caps);
744				}
745
746				if ((link->chip_caps & AMD_EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK) == AMD_EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) {
747					link->bios_forced_drive_settings.VOLTAGE_SWING =
748						(bios->integrated_info->ext_disp_conn_info.fixdpvoltageswing & 0x3);
749					link->bios_forced_drive_settings.PRE_EMPHASIS =
750						((bios->integrated_info->ext_disp_conn_info.fixdpvoltageswing >> 2) & 0x3);
751				}
752
753				break;
754			}
755		}
756	}
757	if (bios->funcs->get_atom_dc_golden_table)
758		bios->funcs->get_atom_dc_golden_table(bios);
759
760	/*
761	 * TODO check if GPIO programmed correctly
762	 *
763	 * If GPIO isn't programmed correctly HPD might not rise or drain
764	 * fast enough, leading to bounces.
765	 */
766	program_hpd_filter(link);
767
768	link->psr_settings.psr_vtotal_control_support = false;
769	link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED;
770	link->replay_settings.config.replay_version = DC_REPLAY_VERSION_UNSUPPORTED;
771
772	DC_LOG_DC("BIOS object table - %s finished successfully.\n", __func__);
773	return true;
774device_tag_fail:
775	link->link_enc->funcs->destroy(&link->link_enc);
776link_enc_create_fail:
777	if (link->panel_cntl != NULL)
778		link->panel_cntl->funcs->destroy(&link->panel_cntl);
779panel_cntl_create_fail:
780	link_destroy_ddc_service(&link->ddc);
781ddc_create_fail:
782create_fail:
783
784	if (link->hpd_gpio) {
785		dal_gpio_destroy_irq(&link->hpd_gpio);
786		link->hpd_gpio = NULL;
787	}
788
789	DC_LOG_DC("BIOS object table - %s failed.\n", __func__);
790	return false;
791}
792
793static bool construct_dpia(struct dc_link *link,
794			      const struct link_init_data *init_params)
795{
796	struct ddc_service_init_data ddc_service_init_data = { 0 };
797	struct dc_context *dc_ctx = init_params->ctx;
798
799	DC_LOGGER_INIT(dc_ctx->logger);
800
801	/* Initialized irq source for hpd and hpd rx */
802	link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
803	link->irq_source_hpd_rx = DC_IRQ_SOURCE_INVALID;
804	link->link_status.dpcd_caps = &link->dpcd_caps;
805
806	link->dc = init_params->dc;
807	link->ctx = dc_ctx;
808	link->link_index = init_params->link_index;
809
810	memset(&link->preferred_training_settings, 0,
811	       sizeof(struct dc_link_training_overrides));
812	memset(&link->preferred_link_setting, 0,
813	       sizeof(struct dc_link_settings));
814
815	/* Dummy Init for linkid */
816	link->link_id.type = OBJECT_TYPE_CONNECTOR;
817	link->link_id.id = CONNECTOR_ID_DISPLAY_PORT;
818	link->link_id.enum_id = ENUM_ID_1 + init_params->connector_index;
819	link->is_internal_display = false;
820	link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT;
821	LINK_INFO("Connector[%d] description:signal %d\n",
822		  init_params->connector_index,
823		  link->connector_signal);
824
825	link->ep_type = DISPLAY_ENDPOINT_USB4_DPIA;
826	link->is_dig_mapping_flexible = true;
827
828	/* TODO: Initialize link : funcs->link_init */
829
830	ddc_service_init_data.ctx = link->ctx;
831	ddc_service_init_data.id = link->link_id;
832	ddc_service_init_data.link = link;
833	/* Set indicator for dpia link so that ddc wont be created */
834	ddc_service_init_data.is_dpia_link = true;
835
836	link->ddc = link_create_ddc_service(&ddc_service_init_data);
837	if (!link->ddc) {
838		DC_ERROR("Failed to create ddc_service!\n");
839		goto ddc_create_fail;
840	}
841
842	/* Set dpia port index : 0 to number of dpia ports */
843	link->ddc_hw_inst = init_params->connector_index;
844
845	// Assign Dpia preferred eng_id
846	if (link->dc->res_pool->funcs->get_preferred_eng_id_dpia)
847		link->dpia_preferred_eng_id = link->dc->res_pool->funcs->get_preferred_eng_id_dpia(link->ddc_hw_inst);
848
849	/* TODO: Create link encoder */
850
851	link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED;
852	link->replay_settings.config.replay_version = DC_REPLAY_VERSION_UNSUPPORTED;
853
854	return true;
855
856ddc_create_fail:
857	return false;
858}
859
860static bool link_construct(struct dc_link *link,
861			      const struct link_init_data *init_params)
862{
863	/* Handle dpia case */
864	if (init_params->is_dpia_link == true)
865		return construct_dpia(link, init_params);
866	else
867		return construct_phy(link, init_params);
868}
869
870struct dc_link *link_create(const struct link_init_data *init_params)
871{
872	struct dc_link *link =
873			kzalloc(sizeof(*link), GFP_KERNEL);
874
875	if (NULL == link)
876		goto alloc_fail;
877
878	if (false == link_construct(link, init_params))
879		goto construct_fail;
880
881	return link;
882
883construct_fail:
884	kfree(link);
885
886alloc_fail:
887	return NULL;
888}
889
890void link_destroy(struct dc_link **link)
891{
892	link_destruct(*link);
893	kfree(*link);
894	*link = NULL;
895}
~/ Read-only file preview.