brintos

brintos / linux-shallow public Read only

0
0
Text · 81.2 KiB · c4e0348 Raw
2614 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 programming sequence of stream's dpms state associated28 * with the link and link's enable/disable sequences as result of the stream's29 * dpms state change.30 *31 * TODO - The reason link owns stream's dpms programming sequence is32 * because dpms programming sequence is highly dependent on underlying signal33 * specific link protocols. This unfortunately causes link to own a portion of34 * stream state programming sequence. This creates a gray area where the35 * boundary between link and stream is not clearly defined.36 */37 38#include "link_dpms.h"39#include "link_hwss.h"40#include "link_validation.h"41#include "accessories/link_dp_trace.h"42#include "protocols/link_dpcd.h"43#include "protocols/link_ddc.h"44#include "protocols/link_hpd.h"45#include "protocols/link_dp_phy.h"46#include "protocols/link_dp_capability.h"47#include "protocols/link_dp_training.h"48#include "protocols/link_edp_panel_control.h"49#include "protocols/link_dp_dpia_bw.h"50 51#include "dm_helpers.h"52#include "link_enc_cfg.h"53#include "resource.h"54#include "dsc.h"55#include "dccg.h"56#include "clk_mgr.h"57#include "atomfirmware.h"58#include "vpg.h"59 60#define DC_LOGGER \61	dc_logger62#define DC_LOGGER_INIT(logger) \63	struct dal_logger *dc_logger = logger64 65#define LINK_INFO(...) \66	DC_LOG_HW_HOTPLUG(  \67		__VA_ARGS__)68 69#define RETIMER_REDRIVER_INFO(...) \70	DC_LOG_RETIMER_REDRIVER(  \71		__VA_ARGS__)72 73#define MAX_MTP_SLOT_COUNT 6474#define LINK_TRAINING_ATTEMPTS 475#define PEAK_FACTOR_X1000 100676 77void link_blank_all_dp_displays(struct dc *dc)78{79	unsigned int i;80	uint8_t dpcd_power_state = '\0';81	enum dc_status status = DC_ERROR_UNEXPECTED;82 83	for (i = 0; i < dc->link_count; i++) {84		if ((dc->links[i]->connector_signal != SIGNAL_TYPE_DISPLAY_PORT) ||85			(dc->links[i]->priv == NULL) || (dc->links[i]->local_sink == NULL))86			continue;87 88		/* DP 2.0 spec requires that we read LTTPR caps first */89		dp_retrieve_lttpr_cap(dc->links[i]);90		/* if any of the displays are lit up turn them off */91		status = core_link_read_dpcd(dc->links[i], DP_SET_POWER,92							&dpcd_power_state, sizeof(dpcd_power_state));93 94		if (status == DC_OK && dpcd_power_state == DP_POWER_STATE_D0)95			link_blank_dp_stream(dc->links[i], true);96	}97 98}99 100void link_blank_all_edp_displays(struct dc *dc)101{102	unsigned int i;103	uint8_t dpcd_power_state = '\0';104	enum dc_status status = DC_ERROR_UNEXPECTED;105 106	for (i = 0; i < dc->link_count; i++) {107		if ((dc->links[i]->connector_signal != SIGNAL_TYPE_EDP) ||108			(!dc->links[i]->edp_sink_present))109			continue;110 111		/* if any of the displays are lit up turn them off */112		status = core_link_read_dpcd(dc->links[i], DP_SET_POWER,113							&dpcd_power_state, sizeof(dpcd_power_state));114 115		if (status == DC_OK && dpcd_power_state == DP_POWER_STATE_D0)116			link_blank_dp_stream(dc->links[i], true);117	}118}119 120void link_blank_dp_stream(struct dc_link *link, bool hw_init)121{122	unsigned int j;123	struct dc  *dc = link->ctx->dc;124	enum signal_type signal = link->connector_signal;125 126	if ((signal == SIGNAL_TYPE_EDP) ||127		(signal == SIGNAL_TYPE_DISPLAY_PORT)) {128		if (link->ep_type == DISPLAY_ENDPOINT_PHY &&129			link->link_enc->funcs->get_dig_frontend &&130			link->link_enc->funcs->is_dig_enabled(link->link_enc)) {131			int fe = link->link_enc->funcs->get_dig_frontend(link->link_enc);132 133			if (fe != ENGINE_ID_UNKNOWN)134				for (j = 0; j < dc->res_pool->stream_enc_count; j++) {135					if (fe == dc->res_pool->stream_enc[j]->id) {136						dc->res_pool->stream_enc[j]->funcs->dp_blank(link,137									dc->res_pool->stream_enc[j]);138						break;139					}140				}141		}142 143		if ((!link->wa_flags.dp_keep_receiver_powered) || hw_init)144			dpcd_write_rx_power_ctrl(link, false);145	}146}147 148void link_set_all_streams_dpms_off_for_link(struct dc_link *link)149{150	struct pipe_ctx *pipes[MAX_PIPES];151	struct dc_state *state = link->dc->current_state;152	uint8_t count;153	int i;154	struct dc_stream_update stream_update;155	bool dpms_off = true;156	struct link_resource link_res = {0};157 158	memset(&stream_update, 0, sizeof(stream_update));159	stream_update.dpms_off = &dpms_off;160 161	link_get_master_pipes_with_dpms_on(link, state, &count, pipes);162 163	for (i = 0; i < count; i++) {164		stream_update.stream = pipes[i]->stream;165		dc_commit_updates_for_stream(link->ctx->dc, NULL, 0,166				pipes[i]->stream, &stream_update,167				state);168	}169 170	/* link can be also enabled by vbios. In this case it is not recorded171	 * in pipe_ctx. Disable link phy here to make sure it is completely off172	 */173	dp_disable_link_phy(link, &link_res, link->connector_signal);174}175 176void link_resume(struct dc_link *link)177{178	if (link->connector_signal != SIGNAL_TYPE_VIRTUAL)179		program_hpd_filter(link);180}181 182/* This function returns true if the pipe is used to feed video signal directly183 * to the link.184 */185static bool is_master_pipe_for_link(const struct dc_link *link,186		const struct pipe_ctx *pipe)187{188	return resource_is_pipe_type(pipe, OTG_MASTER) &&189			pipe->stream->link == link;190}191 192/*193 * This function finds all master pipes feeding to a given link with dpms set to194 * on in given dc state.195 */196void link_get_master_pipes_with_dpms_on(const struct dc_link *link,197		struct dc_state *state,198		uint8_t *count,199		struct pipe_ctx *pipes[MAX_PIPES])200{201	int i;202	struct pipe_ctx *pipe = NULL;203 204	*count = 0;205	for (i = 0; i < MAX_PIPES; i++) {206		pipe = &state->res_ctx.pipe_ctx[i];207 208		if (is_master_pipe_for_link(link, pipe) &&209				pipe->stream->dpms_off == false) {210			pipes[(*count)++] = pipe;211		}212	}213}214 215static bool get_ext_hdmi_settings(struct pipe_ctx *pipe_ctx,216		enum engine_id eng_id,217		struct ext_hdmi_settings *settings)218{219	bool result = false;220	int i = 0;221	struct integrated_info *integrated_info =222			pipe_ctx->stream->ctx->dc_bios->integrated_info;223 224	if (integrated_info == NULL)225		return false;226 227	/*228	 * Get retimer settings from sbios for passing SI eye test for DCE11229	 * The setting values are varied based on board revision and port id230	 * Therefore the setting values of each ports is passed by sbios.231	 */232 233	// Check if current bios contains ext Hdmi settings234	if (integrated_info->gpu_cap_info & 0x20) {235		switch (eng_id) {236		case ENGINE_ID_DIGA:237			settings->slv_addr = integrated_info->dp0_ext_hdmi_slv_addr;238			settings->reg_num = integrated_info->dp0_ext_hdmi_6g_reg_num;239			settings->reg_num_6g = integrated_info->dp0_ext_hdmi_6g_reg_num;240			memmove(settings->reg_settings,241					integrated_info->dp0_ext_hdmi_reg_settings,242					sizeof(integrated_info->dp0_ext_hdmi_reg_settings));243			memmove(settings->reg_settings_6g,244					integrated_info->dp0_ext_hdmi_6g_reg_settings,245					sizeof(integrated_info->dp0_ext_hdmi_6g_reg_settings));246			result = true;247			break;248		case ENGINE_ID_DIGB:249			settings->slv_addr = integrated_info->dp1_ext_hdmi_slv_addr;250			settings->reg_num = integrated_info->dp1_ext_hdmi_6g_reg_num;251			settings->reg_num_6g = integrated_info->dp1_ext_hdmi_6g_reg_num;252			memmove(settings->reg_settings,253					integrated_info->dp1_ext_hdmi_reg_settings,254					sizeof(integrated_info->dp1_ext_hdmi_reg_settings));255			memmove(settings->reg_settings_6g,256					integrated_info->dp1_ext_hdmi_6g_reg_settings,257					sizeof(integrated_info->dp1_ext_hdmi_6g_reg_settings));258			result = true;259			break;260		case ENGINE_ID_DIGC:261			settings->slv_addr = integrated_info->dp2_ext_hdmi_slv_addr;262			settings->reg_num = integrated_info->dp2_ext_hdmi_6g_reg_num;263			settings->reg_num_6g = integrated_info->dp2_ext_hdmi_6g_reg_num;264			memmove(settings->reg_settings,265					integrated_info->dp2_ext_hdmi_reg_settings,266					sizeof(integrated_info->dp2_ext_hdmi_reg_settings));267			memmove(settings->reg_settings_6g,268					integrated_info->dp2_ext_hdmi_6g_reg_settings,269					sizeof(integrated_info->dp2_ext_hdmi_6g_reg_settings));270			result = true;271			break;272		case ENGINE_ID_DIGD:273			settings->slv_addr = integrated_info->dp3_ext_hdmi_slv_addr;274			settings->reg_num = integrated_info->dp3_ext_hdmi_6g_reg_num;275			settings->reg_num_6g = integrated_info->dp3_ext_hdmi_6g_reg_num;276			memmove(settings->reg_settings,277					integrated_info->dp3_ext_hdmi_reg_settings,278					sizeof(integrated_info->dp3_ext_hdmi_reg_settings));279			memmove(settings->reg_settings_6g,280					integrated_info->dp3_ext_hdmi_6g_reg_settings,281					sizeof(integrated_info->dp3_ext_hdmi_6g_reg_settings));282			result = true;283			break;284		default:285			break;286		}287 288		if (result == true) {289			// Validate settings from bios integrated info table290			if (settings->slv_addr == 0)291				return false;292			if (settings->reg_num > 9)293				return false;294			if (settings->reg_num_6g > 3)295				return false;296 297			for (i = 0; i < settings->reg_num; i++) {298				if (settings->reg_settings[i].i2c_reg_index > 0x20)299					return false;300			}301 302			for (i = 0; i < settings->reg_num_6g; i++) {303				if (settings->reg_settings_6g[i].i2c_reg_index > 0x20)304					return false;305			}306		}307	}308 309	return result;310}311 312static bool write_i2c(struct pipe_ctx *pipe_ctx,313		uint8_t address, uint8_t *buffer, uint32_t length)314{315	struct i2c_command cmd = {0};316	struct i2c_payload payload = {0};317 318	memset(&payload, 0, sizeof(payload));319	memset(&cmd, 0, sizeof(cmd));320 321	cmd.number_of_payloads = 1;322	cmd.engine = I2C_COMMAND_ENGINE_DEFAULT;323	cmd.speed = pipe_ctx->stream->ctx->dc->caps.i2c_speed_in_khz;324 325	payload.address = address;326	payload.data = buffer;327	payload.length = length;328	payload.write = true;329	cmd.payloads = &payload;330 331	if (dm_helpers_submit_i2c(pipe_ctx->stream->ctx,332			pipe_ctx->stream->link, &cmd))333		return true;334 335	return false;336}337 338static void write_i2c_retimer_setting(339		struct pipe_ctx *pipe_ctx,340		bool is_vga_mode,341		bool is_over_340mhz,342		struct ext_hdmi_settings *settings)343{344	uint8_t slave_address = (settings->slv_addr >> 1);345	uint8_t buffer[2];346	const uint8_t apply_rx_tx_change = 0x4;347	uint8_t offset = 0xA;348	uint8_t value = 0;349	int i = 0;350	bool i2c_success = false;351	DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);352 353	memset(&buffer, 0, sizeof(buffer));354 355	/* Start Ext-Hdmi programming*/356 357	for (i = 0; i < settings->reg_num; i++) {358		/* Apply 3G settings */359		if (settings->reg_settings[i].i2c_reg_index <= 0x20) {360 361			buffer[0] = settings->reg_settings[i].i2c_reg_index;362			buffer[1] = settings->reg_settings[i].i2c_reg_val;363			i2c_success = write_i2c(pipe_ctx, slave_address,364						buffer, sizeof(buffer));365			RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\366				offset = 0x%x, reg_val= 0x%x, i2c_success = %d\n",367				slave_address, buffer[0], buffer[1], i2c_success?1:0);368 369			if (!i2c_success)370				goto i2c_write_fail;371 372			/* Based on DP159 specs, APPLY_RX_TX_CHANGE bit in 0x0A373			 * needs to be set to 1 on every 0xA-0xC write.374			 */375			if (settings->reg_settings[i].i2c_reg_index == 0xA ||376				settings->reg_settings[i].i2c_reg_index == 0xB ||377				settings->reg_settings[i].i2c_reg_index == 0xC) {378 379				/* Query current value from offset 0xA */380				if (settings->reg_settings[i].i2c_reg_index == 0xA)381					value = settings->reg_settings[i].i2c_reg_val;382				else {383					i2c_success =384						link_query_ddc_data(385						pipe_ctx->stream->link->ddc,386						slave_address, &offset, 1, &value, 1);387					if (!i2c_success)388						goto i2c_write_fail;389				}390 391				buffer[0] = offset;392				/* Set APPLY_RX_TX_CHANGE bit to 1 */393				buffer[1] = value | apply_rx_tx_change;394				i2c_success = write_i2c(pipe_ctx, slave_address,395						buffer, sizeof(buffer));396				RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\397					offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",398					slave_address, buffer[0], buffer[1], i2c_success?1:0);399				if (!i2c_success)400					goto i2c_write_fail;401			}402		}403	}404 405	/* Apply 3G settings */406	if (is_over_340mhz) {407		for (i = 0; i < settings->reg_num_6g; i++) {408			/* Apply 3G settings */409			if (settings->reg_settings[i].i2c_reg_index <= 0x20) {410 411				buffer[0] = settings->reg_settings_6g[i].i2c_reg_index;412				buffer[1] = settings->reg_settings_6g[i].i2c_reg_val;413				i2c_success = write_i2c(pipe_ctx, slave_address,414							buffer, sizeof(buffer));415				RETIMER_REDRIVER_INFO("above 340Mhz: retimer write to slave_address = 0x%x,\416					offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",417					slave_address, buffer[0], buffer[1], i2c_success?1:0);418 419				if (!i2c_success)420					goto i2c_write_fail;421 422				/* Based on DP159 specs, APPLY_RX_TX_CHANGE bit in 0x0A423				 * needs to be set to 1 on every 0xA-0xC write.424				 */425				if (settings->reg_settings_6g[i].i2c_reg_index == 0xA ||426					settings->reg_settings_6g[i].i2c_reg_index == 0xB ||427					settings->reg_settings_6g[i].i2c_reg_index == 0xC) {428 429					/* Query current value from offset 0xA */430					if (settings->reg_settings_6g[i].i2c_reg_index == 0xA)431						value = settings->reg_settings_6g[i].i2c_reg_val;432					else {433						i2c_success =434								link_query_ddc_data(435								pipe_ctx->stream->link->ddc,436								slave_address, &offset, 1, &value, 1);437						if (!i2c_success)438							goto i2c_write_fail;439					}440 441					buffer[0] = offset;442					/* Set APPLY_RX_TX_CHANGE bit to 1 */443					buffer[1] = value | apply_rx_tx_change;444					i2c_success = write_i2c(pipe_ctx, slave_address,445							buffer, sizeof(buffer));446					RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\447						offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",448						slave_address, buffer[0], buffer[1], i2c_success?1:0);449					if (!i2c_success)450						goto i2c_write_fail;451				}452			}453		}454	}455 456	if (is_vga_mode) {457		/* Program additional settings if using 640x480 resolution */458 459		/* Write offset 0xFF to 0x01 */460		buffer[0] = 0xff;461		buffer[1] = 0x01;462		i2c_success = write_i2c(pipe_ctx, slave_address,463				buffer, sizeof(buffer));464		RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\465				offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",466				slave_address, buffer[0], buffer[1], i2c_success?1:0);467		if (!i2c_success)468			goto i2c_write_fail;469 470		/* Write offset 0x00 to 0x23 */471		buffer[0] = 0x00;472		buffer[1] = 0x23;473		i2c_success = write_i2c(pipe_ctx, slave_address,474				buffer, sizeof(buffer));475		RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\476			offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",477			slave_address, buffer[0], buffer[1], i2c_success?1:0);478		if (!i2c_success)479			goto i2c_write_fail;480 481		/* Write offset 0xff to 0x00 */482		buffer[0] = 0xff;483		buffer[1] = 0x00;484		i2c_success = write_i2c(pipe_ctx, slave_address,485				buffer, sizeof(buffer));486		RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\487			offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",488			slave_address, buffer[0], buffer[1], i2c_success?1:0);489		if (!i2c_success)490			goto i2c_write_fail;491 492	}493 494	return;495 496i2c_write_fail:497	DC_LOG_DEBUG("Set retimer failed");498}499 500static void write_i2c_default_retimer_setting(501		struct pipe_ctx *pipe_ctx,502		bool is_vga_mode,503		bool is_over_340mhz)504{505	uint8_t slave_address = (0xBA >> 1);506	uint8_t buffer[2];507	bool i2c_success = false;508	DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);509 510	memset(&buffer, 0, sizeof(buffer));511 512	/* Program Slave Address for tuning single integrity */513	/* Write offset 0x0A to 0x13 */514	buffer[0] = 0x0A;515	buffer[1] = 0x13;516	i2c_success = write_i2c(pipe_ctx, slave_address,517			buffer, sizeof(buffer));518	RETIMER_REDRIVER_INFO("retimer writes default setting to slave_address = 0x%x,\519		offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",520		slave_address, buffer[0], buffer[1], i2c_success?1:0);521	if (!i2c_success)522		goto i2c_write_fail;523 524	/* Write offset 0x0A to 0x17 */525	buffer[0] = 0x0A;526	buffer[1] = 0x17;527	i2c_success = write_i2c(pipe_ctx, slave_address,528			buffer, sizeof(buffer));529	RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\530		offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",531		slave_address, buffer[0], buffer[1], i2c_success?1:0);532	if (!i2c_success)533		goto i2c_write_fail;534 535	/* Write offset 0x0B to 0xDA or 0xD8 */536	buffer[0] = 0x0B;537	buffer[1] = is_over_340mhz ? 0xDA : 0xD8;538	i2c_success = write_i2c(pipe_ctx, slave_address,539			buffer, sizeof(buffer));540	RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\541		offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",542		slave_address, buffer[0], buffer[1], i2c_success?1:0);543	if (!i2c_success)544		goto i2c_write_fail;545 546	/* Write offset 0x0A to 0x17 */547	buffer[0] = 0x0A;548	buffer[1] = 0x17;549	i2c_success = write_i2c(pipe_ctx, slave_address,550			buffer, sizeof(buffer));551	RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\552		offset = 0x%x, reg_val= 0x%x, i2c_success = %d\n",553		slave_address, buffer[0], buffer[1], i2c_success?1:0);554	if (!i2c_success)555		goto i2c_write_fail;556 557	/* Write offset 0x0C to 0x1D or 0x91 */558	buffer[0] = 0x0C;559	buffer[1] = is_over_340mhz ? 0x1D : 0x91;560	i2c_success = write_i2c(pipe_ctx, slave_address,561			buffer, sizeof(buffer));562	RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\563		offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",564		slave_address, buffer[0], buffer[1], i2c_success?1:0);565	if (!i2c_success)566		goto i2c_write_fail;567 568	/* Write offset 0x0A to 0x17 */569	buffer[0] = 0x0A;570	buffer[1] = 0x17;571	i2c_success = write_i2c(pipe_ctx, slave_address,572			buffer, sizeof(buffer));573	RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\574		offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",575		slave_address, buffer[0], buffer[1], i2c_success?1:0);576	if (!i2c_success)577		goto i2c_write_fail;578 579 580	if (is_vga_mode) {581		/* Program additional settings if using 640x480 resolution */582 583		/* Write offset 0xFF to 0x01 */584		buffer[0] = 0xff;585		buffer[1] = 0x01;586		i2c_success = write_i2c(pipe_ctx, slave_address,587				buffer, sizeof(buffer));588		RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\589			offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",590			slave_address, buffer[0], buffer[1], i2c_success?1:0);591		if (!i2c_success)592			goto i2c_write_fail;593 594		/* Write offset 0x00 to 0x23 */595		buffer[0] = 0x00;596		buffer[1] = 0x23;597		i2c_success = write_i2c(pipe_ctx, slave_address,598				buffer, sizeof(buffer));599		RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\600			offset = 0x%x, reg_val= 0x%x, i2c_success = %d\n",601			slave_address, buffer[0], buffer[1], i2c_success?1:0);602		if (!i2c_success)603			goto i2c_write_fail;604 605		/* Write offset 0xff to 0x00 */606		buffer[0] = 0xff;607		buffer[1] = 0x00;608		i2c_success = write_i2c(pipe_ctx, slave_address,609				buffer, sizeof(buffer));610		RETIMER_REDRIVER_INFO("retimer write default setting to slave_addr = 0x%x,\611			offset = 0x%x, reg_val= 0x%x, i2c_success = %d end here\n",612			slave_address, buffer[0], buffer[1], i2c_success?1:0);613		if (!i2c_success)614			goto i2c_write_fail;615	}616 617	return;618 619i2c_write_fail:620	DC_LOG_DEBUG("Set default retimer failed");621}622 623static void write_i2c_redriver_setting(624		struct pipe_ctx *pipe_ctx,625		bool is_over_340mhz)626{627	uint8_t slave_address = (0xF0 >> 1);628	uint8_t buffer[16];629	bool i2c_success = false;630	DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);631 632	memset(&buffer, 0, sizeof(buffer));633 634	// Program Slave Address for tuning single integrity635	buffer[3] = 0x4E;636	buffer[4] = 0x4E;637	buffer[5] = 0x4E;638	buffer[6] = is_over_340mhz ? 0x4E : 0x4A;639 640	i2c_success = write_i2c(pipe_ctx, slave_address,641					buffer, sizeof(buffer));642	RETIMER_REDRIVER_INFO("redriver write 0 to all 16 reg offset expect following:\n\643		\t slave_addr = 0x%x, offset[3] = 0x%x, offset[4] = 0x%x,\644		offset[5] = 0x%x,offset[6] is_over_340mhz = 0x%x,\645		i2c_success = %d\n",646		slave_address, buffer[3], buffer[4], buffer[5], buffer[6], i2c_success?1:0);647 648	if (!i2c_success)649		DC_LOG_DEBUG("Set redriver failed");650}651 652static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off)653{654	struct cp_psp *cp_psp = &pipe_ctx->stream->ctx->cp_psp;655	struct link_encoder *link_enc = NULL;656	struct cp_psp_stream_config config = {0};657	enum dp_panel_mode panel_mode =658			dp_get_panel_mode(pipe_ctx->stream->link);659 660	if (cp_psp == NULL || cp_psp->funcs.update_stream_config == NULL)661		return;662 663	link_enc = link_enc_cfg_get_link_enc(pipe_ctx->stream->link);664	ASSERT(link_enc);665	if (link_enc == NULL)666		return;667 668	/* otg instance */669	config.otg_inst = (uint8_t) pipe_ctx->stream_res.tg->inst;670 671	/* dig front end */672	config.dig_fe = (uint8_t) pipe_ctx->stream_res.stream_enc->stream_enc_inst;673 674	/* stream encoder index */675	config.stream_enc_idx = pipe_ctx->stream_res.stream_enc->id - ENGINE_ID_DIGA;676	if (dp_is_128b_132b_signal(pipe_ctx))677		config.stream_enc_idx =678				pipe_ctx->stream_res.hpo_dp_stream_enc->id - ENGINE_ID_HPO_DP_0;679 680	/* dig back end */681	config.dig_be = pipe_ctx->stream->link->link_enc_hw_inst;682 683	/* link encoder index */684	config.link_enc_idx = link_enc->transmitter - TRANSMITTER_UNIPHY_A;685	if (dp_is_128b_132b_signal(pipe_ctx))686		config.link_enc_idx = pipe_ctx->link_res.hpo_dp_link_enc->inst;687 688	/* dio output index is dpia index for DPIA endpoint & dcio index by default */689	if (pipe_ctx->stream->link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA)690		config.dio_output_idx = pipe_ctx->stream->link->link_id.enum_id - ENUM_ID_1;691	else692		config.dio_output_idx = link_enc->transmitter - TRANSMITTER_UNIPHY_A;693 694 695	/* phy index */696	config.phy_idx = resource_transmitter_to_phy_idx(697			pipe_ctx->stream->link->dc, link_enc->transmitter);698	if (pipe_ctx->stream->link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA)699		/* USB4 DPIA doesn't use PHY in our soc, initialize it to 0 */700		config.phy_idx = 0;701 702	/* stream properties */703	config.assr_enabled = (panel_mode == DP_PANEL_MODE_EDP) ? 1 : 0;704	config.mst_enabled = (pipe_ctx->stream->signal ==705			SIGNAL_TYPE_DISPLAY_PORT_MST) ? 1 : 0;706	config.dp2_enabled = dp_is_128b_132b_signal(pipe_ctx) ? 1 : 0;707	config.usb4_enabled = (pipe_ctx->stream->link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) ?708			1 : 0;709	config.dpms_off = dpms_off;710 711	/* dm stream context */712	config.dm_stream_ctx = pipe_ctx->stream->dm_stream_context;713 714	cp_psp->funcs.update_stream_config(cp_psp->handle, &config);715}716 717static void set_avmute(struct pipe_ctx *pipe_ctx, bool enable)718{719	struct dc  *dc = pipe_ctx->stream->ctx->dc;720 721	if (!dc_is_hdmi_signal(pipe_ctx->stream->signal))722		return;723 724	dc->hwss.set_avmute(pipe_ctx, enable);725}726 727static void enable_mst_on_sink(struct dc_link *link, bool enable)728{729	unsigned char mstmCntl = 0;730 731	core_link_read_dpcd(link, DP_MSTM_CTRL, &mstmCntl, 1);732	if (enable)733		mstmCntl |= DP_MST_EN;734	else735		mstmCntl &= (~DP_MST_EN);736 737	core_link_write_dpcd(link, DP_MSTM_CTRL, &mstmCntl, 1);738}739 740static void dsc_optc_config_log(struct display_stream_compressor *dsc,741		struct dsc_optc_config *config)742{743	uint32_t precision = 1 << 28;744	uint32_t bytes_per_pixel_int = config->bytes_per_pixel / precision;745	uint32_t bytes_per_pixel_mod = config->bytes_per_pixel % precision;746	uint64_t ll_bytes_per_pix_fraq = bytes_per_pixel_mod;747	DC_LOGGER_INIT(dsc->ctx->logger);748 749	/* 7 fractional digits decimal precision for bytes per pixel is enough because DSC750	 * bits per pixel precision is 1/16th of a pixel, which means bytes per pixel precision is751	 * 1/16/8 = 1/128 of a byte, or 0.0078125 decimal752	 */753	ll_bytes_per_pix_fraq *= 10000000;754	ll_bytes_per_pix_fraq /= precision;755 756	DC_LOG_DSC("\tbytes_per_pixel 0x%08x (%d.%07d)",757			config->bytes_per_pixel, bytes_per_pixel_int, (uint32_t)ll_bytes_per_pix_fraq);758	DC_LOG_DSC("\tis_pixel_format_444 %d", config->is_pixel_format_444);759	DC_LOG_DSC("\tslice_width %d", config->slice_width);760}761 762static bool dp_set_dsc_on_rx(struct pipe_ctx *pipe_ctx, bool enable)763{764	struct dc *dc = pipe_ctx->stream->ctx->dc;765	struct dc_stream_state *stream = pipe_ctx->stream;766	bool result = false;767 768	if (dc_is_virtual_signal(stream->signal))769		result = true;770	else771		result = dm_helpers_dp_write_dsc_enable(dc->ctx, stream, enable);772	return result;773}774 775/* The stream with these settings can be sent (unblanked) only after DSC was enabled on RX first,776 * i.e. after dp_enable_dsc_on_rx() had been called777 */778void link_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)779{780	/* TODO: Move this to HWSS as this is hardware programming sequence not a781	 * link layer sequence782	 */783	struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;784	struct dc *dc = pipe_ctx->stream->ctx->dc;785	struct dc_stream_state *stream = pipe_ctx->stream;786	struct pipe_ctx *odm_pipe;787	int opp_cnt = 1;788	struct dccg *dccg = dc->res_pool->dccg;789	/* It has been found that when DSCCLK is lower than 16Mhz, we will get DCN790	 * register access hung. When DSCCLk is based on refclk, DSCCLk is always a791	 * fixed value higher than 16Mhz so the issue doesn't occur. When DSCCLK is792	 * generated by DTO, DSCCLK would be based on 1/3 dispclk. For small timings793	 * with DSC such as 480p60Hz, the dispclk could be low enough to trigger794	 * this problem. We are implementing a workaround here to keep using dscclk795	 * based on fixed value refclk when timing is smaller than 3x16Mhz (i.e796	 * 48Mhz) pixel clock to avoid hitting this problem.797	 */798	bool should_use_dto_dscclk = (dccg->funcs->set_dto_dscclk != NULL) &&799			stream->timing.pix_clk_100hz > 480000;800	DC_LOGGER_INIT(dsc->ctx->logger);801 802	for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)803		opp_cnt++;804 805	if (enable) {806		struct dsc_config dsc_cfg;807		struct dsc_optc_config dsc_optc_cfg = {0};808		enum optc_dsc_mode optc_dsc_mode;809 810		/* Enable DSC hw block */811		dsc_cfg.pic_width = (stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right) / opp_cnt;812		dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom;813		dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;814		dsc_cfg.color_depth = stream->timing.display_color_depth;815		dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false;816		dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;817		ASSERT(dsc_cfg.dc_dsc_cfg.num_slices_h % opp_cnt == 0);818		dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt;819 820		if (should_use_dto_dscclk)821			dccg->funcs->set_dto_dscclk(dccg, dsc->inst);822		dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg);823		dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst);824		for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {825			struct display_stream_compressor *odm_dsc = odm_pipe->stream_res.dsc;826 827			if (should_use_dto_dscclk)828				dccg->funcs->set_dto_dscclk(dccg, odm_dsc->inst);829			odm_dsc->funcs->dsc_set_config(odm_dsc, &dsc_cfg, &dsc_optc_cfg);830			odm_dsc->funcs->dsc_enable(odm_dsc, odm_pipe->stream_res.opp->inst);831		}832		dsc_cfg.dc_dsc_cfg.num_slices_h *= opp_cnt;833		dsc_cfg.pic_width *= opp_cnt;834 835		optc_dsc_mode = dsc_optc_cfg.is_pixel_format_444 ? OPTC_DSC_ENABLED_444 : OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED;836 837		/* Enable DSC in encoder */838		if (dc_is_dp_signal(stream->signal) && !dp_is_128b_132b_signal(pipe_ctx)) {839			DC_LOG_DSC("Setting stream encoder DSC config for engine %d:", (int)pipe_ctx->stream_res.stream_enc->id);840			dsc_optc_config_log(dsc, &dsc_optc_cfg);841			if (pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config)842				pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(pipe_ctx->stream_res.stream_enc,843										optc_dsc_mode,844										dsc_optc_cfg.bytes_per_pixel,845										dsc_optc_cfg.slice_width);846 847			/* PPS SDP is set elsewhere because it has to be done after DIG FE is connected to DIG BE */848		}849 850		/* Enable DSC in OPTC */851		DC_LOG_DSC("Setting optc DSC config for tg instance %d:", pipe_ctx->stream_res.tg->inst);852		dsc_optc_config_log(dsc, &dsc_optc_cfg);853		pipe_ctx->stream_res.tg->funcs->set_dsc_config(pipe_ctx->stream_res.tg,854							optc_dsc_mode,855							dsc_optc_cfg.bytes_per_pixel,856							dsc_optc_cfg.slice_width);857	} else {858		/* disable DSC in OPTC */859		pipe_ctx->stream_res.tg->funcs->set_dsc_config(860				pipe_ctx->stream_res.tg,861				OPTC_DSC_DISABLED, 0, 0);862 863		/* disable DSC in stream encoder */864		if (dc_is_dp_signal(stream->signal)) {865			if (dp_is_128b_132b_signal(pipe_ctx))866				pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet(867										pipe_ctx->stream_res.hpo_dp_stream_enc,868										false,869										NULL,870										true);871			else {872				if (pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config)873					pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(874							pipe_ctx->stream_res.stream_enc,875							OPTC_DSC_DISABLED, 0, 0);876				pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet(877							pipe_ctx->stream_res.stream_enc, false, NULL, true);878			}879		}880 881		/* disable DSC block */882		for (odm_pipe = pipe_ctx; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {883			odm_pipe->stream_res.dsc->funcs->dsc_disconnect(odm_pipe->stream_res.dsc);884			/*885			 * TODO - dsc_disconnect is a double buffered register.886			 * by the time we call dsc_disable, dsc may still remain887			 * connected to OPP. In this case OPTC will no longer888			 * get correct pixel data because DSCC is off. However889			 * we also can't wait for the  disconnect pending890			 * complete, because this function can be called891			 * with/without OTG master lock acquired. When the lock892			 * is acquired we will never get pending complete until893			 * we release the lock later. So there is no easy way to894			 * solve this problem especially when the lock is895			 * acquired. DSC is a front end hw block it should be896			 * programmed as part of front end sequence, where the897			 * commit sequence without lock and update sequence898			 * with lock are completely separated. However because899			 * we are programming dsc as part of back end link900			 * programming sequence, we don't know if front end OPTC901			 * master lock is acquired. The back end should be902			 * agnostic to front end lock. DSC programming shouldn't903			 * belong to this sequence.904			 */905			odm_pipe->stream_res.dsc->funcs->dsc_disable(odm_pipe->stream_res.dsc);906			if (dccg->funcs->set_ref_dscclk)907				dccg->funcs->set_ref_dscclk(dccg, odm_pipe->stream_res.dsc->inst);908		}909	}910}911 912/*913 * For dynamic bpp change case, dsc is programmed with MASTER_UPDATE_LOCK enabled;914 * hence PPS info packet update need to use frame update instead of immediate update.915 * Added parameter immediate_update for this purpose.916 * The decision to use frame update is hard-coded in function dp_update_dsc_config(),917 * which is the only place where a "false" would be passed in for param immediate_update.918 *919 * immediate_update is only applicable when DSC is enabled.920 */921bool link_set_dsc_pps_packet(struct pipe_ctx *pipe_ctx, bool enable, bool immediate_update)922{923	struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;924	struct dc_stream_state *stream = pipe_ctx->stream;925 926	if (!pipe_ctx->stream->timing.flags.DSC)927		return false;928 929	if (!dsc)930		return false;931 932	DC_LOGGER_INIT(dsc->ctx->logger);933 934	if (enable) {935		struct dsc_config dsc_cfg;936		uint8_t dsc_packed_pps[128];937 938		memset(&dsc_cfg, 0, sizeof(dsc_cfg));939		memset(dsc_packed_pps, 0, 128);940 941		/* Enable DSC hw block */942		dsc_cfg.pic_width = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right;943		dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom;944		dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;945		dsc_cfg.color_depth = stream->timing.display_color_depth;946		dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false;947		dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;948 949		dsc->funcs->dsc_get_packed_pps(dsc, &dsc_cfg, &dsc_packed_pps[0]);950		memcpy(&stream->dsc_packed_pps[0], &dsc_packed_pps[0], sizeof(stream->dsc_packed_pps));951		if (dc_is_dp_signal(stream->signal)) {952			DC_LOG_DSC("Setting stream encoder DSC PPS SDP for engine %d\n", (int)pipe_ctx->stream_res.stream_enc->id);953			if (dp_is_128b_132b_signal(pipe_ctx))954				pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet(955										pipe_ctx->stream_res.hpo_dp_stream_enc,956										true,957										&dsc_packed_pps[0],958										immediate_update);959			else960				pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet(961						pipe_ctx->stream_res.stream_enc,962						true,963						&dsc_packed_pps[0],964						immediate_update);965		}966	} else {967		/* disable DSC PPS in stream encoder */968		memset(&stream->dsc_packed_pps[0], 0, sizeof(stream->dsc_packed_pps));969		if (dc_is_dp_signal(stream->signal)) {970			if (dp_is_128b_132b_signal(pipe_ctx))971				pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet(972										pipe_ctx->stream_res.hpo_dp_stream_enc,973										false,974										NULL,975										true);976			else977				pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet(978						pipe_ctx->stream_res.stream_enc, false, NULL, true);979		}980	}981 982	return true;983}984 985bool link_set_dsc_enable(struct pipe_ctx *pipe_ctx, bool enable)986{987	struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;988	bool result = false;989 990	if (!pipe_ctx->stream->timing.flags.DSC)991		goto out;992	if (!dsc)993		goto out;994 995	if (enable) {996		{997			link_set_dsc_on_stream(pipe_ctx, true);998			result = true;999		}1000	} else {1001		dp_set_dsc_on_rx(pipe_ctx, false);1002		link_set_dsc_on_stream(pipe_ctx, false);1003		result = true;1004	}1005out:1006	return result;1007}1008 1009bool link_update_dsc_config(struct pipe_ctx *pipe_ctx)1010{1011	struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;1012 1013	if (!pipe_ctx->stream->timing.flags.DSC)1014		return false;1015	if (!dsc)1016		return false;1017 1018	link_set_dsc_on_stream(pipe_ctx, true);1019	link_set_dsc_pps_packet(pipe_ctx, true, false);1020	return true;1021}1022 1023static void enable_stream_features(struct pipe_ctx *pipe_ctx)1024{1025	struct dc_stream_state *stream = pipe_ctx->stream;1026 1027	if (pipe_ctx->stream->signal != SIGNAL_TYPE_DISPLAY_PORT_MST) {1028		struct dc_link *link = stream->link;1029		union down_spread_ctrl old_downspread;1030		union down_spread_ctrl new_downspread;1031 1032		memset(&old_downspread, 0, sizeof(old_downspread));1033 1034		core_link_read_dpcd(link, DP_DOWNSPREAD_CTRL,1035				&old_downspread.raw, sizeof(old_downspread));1036 1037		new_downspread.raw = old_downspread.raw;1038 1039		new_downspread.bits.IGNORE_MSA_TIMING_PARAM =1040				(stream->ignore_msa_timing_param) ? 1 : 0;1041 1042		if (new_downspread.raw != old_downspread.raw) {1043			core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL,1044				&new_downspread.raw, sizeof(new_downspread));1045		}1046 1047	} else {1048		dm_helpers_mst_enable_stream_features(stream);1049	}1050}1051 1052static void log_vcp_x_y(const struct dc_link *link, struct fixed31_32 avg_time_slots_per_mtp)1053{1054	const uint32_t VCP_Y_PRECISION = 1000;1055	uint64_t vcp_x, vcp_y;1056	DC_LOGGER_INIT(link->ctx->logger);1057 1058	// Add 0.5*(1/VCP_Y_PRECISION) to round up to decimal precision1059	avg_time_slots_per_mtp = dc_fixpt_add(1060			avg_time_slots_per_mtp,1061			dc_fixpt_from_fraction(1062				1,1063				2*VCP_Y_PRECISION));1064 1065	vcp_x = dc_fixpt_floor(1066			avg_time_slots_per_mtp);1067	vcp_y = dc_fixpt_floor(1068			dc_fixpt_mul_int(1069				dc_fixpt_sub_int(1070					avg_time_slots_per_mtp,1071					dc_fixpt_floor(1072							avg_time_slots_per_mtp)),1073				VCP_Y_PRECISION));1074 1075 1076	if (link->type == dc_connection_mst_branch)1077		DC_LOG_DP2("MST Update Payload: set_throttled_vcp_size slot X.Y for MST stream "1078				"X: %llu "1079				"Y: %llu/%d",1080				vcp_x,1081				vcp_y,1082				VCP_Y_PRECISION);1083	else1084		DC_LOG_DP2("SST Update Payload: set_throttled_vcp_size slot X.Y for SST stream "1085				"X: %llu "1086				"Y: %llu/%d",1087				vcp_x,1088				vcp_y,1089				VCP_Y_PRECISION);1090}1091 1092static struct fixed31_32 get_pbn_per_slot(struct dc_stream_state *stream)1093{1094	struct fixed31_32 mbytes_per_sec;1095	uint32_t link_rate_in_mbytes_per_sec = dp_link_bandwidth_kbps(stream->link,1096			&stream->link->cur_link_settings);1097	link_rate_in_mbytes_per_sec /= 8000; /* Kbits to MBytes */1098 1099	mbytes_per_sec = dc_fixpt_from_int(link_rate_in_mbytes_per_sec);1100 1101	return dc_fixpt_div_int(mbytes_per_sec, 54);1102}1103 1104static struct fixed31_32 get_pbn_from_bw_in_kbps(uint64_t kbps)1105{1106	struct fixed31_32 peak_kbps;1107	uint32_t numerator = 0;1108	uint32_t denominator = 1;1109 1110	/*1111	 * The 1.006 factor (margin 5300ppm + 300ppm ~ 0.6% as per spec) is not1112	 * required when determining PBN/time slot utilization on the link between1113	 * us and the branch, since that overhead is already accounted for in1114	 * the get_pbn_per_slot function.1115	 *1116	 * The unit of 54/64Mbytes/sec is an arbitrary unit chosen based on1117	 * common multiplier to render an integer PBN for all link rate/lane1118	 * counts combinations1119	 * calculate1120	 * peak_kbps *= (64/54)1121	 * peak_kbps /= (8 * 1000) convert to bytes1122	 */1123 1124	numerator = 64;1125	denominator = 54 * 8 * 1000;1126	kbps *= numerator;1127	peak_kbps = dc_fixpt_from_fraction(kbps, denominator);1128 1129	return peak_kbps;1130}1131 1132static struct fixed31_32 get_pbn_from_timing(struct pipe_ctx *pipe_ctx)1133{1134	uint64_t kbps;1135	enum dc_link_encoding_format link_encoding;1136 1137	if (dp_is_128b_132b_signal(pipe_ctx))1138		link_encoding = DC_LINK_ENCODING_DP_128b_132b;1139	else1140		link_encoding = DC_LINK_ENCODING_DP_8b_10b;1141 1142	kbps = dc_bandwidth_in_kbps_from_timing(&pipe_ctx->stream->timing, link_encoding);1143	return get_pbn_from_bw_in_kbps(kbps);1144}1145 1146 1147// TODO - DP2.0 Link: Fix get_lane_status to handle LTTPR offset (SST and MST)1148static void get_lane_status(1149	struct dc_link *link,1150	uint32_t lane_count,1151	union lane_status *status,1152	union lane_align_status_updated *status_updated)1153{1154	unsigned int lane;1155	uint8_t dpcd_buf[3] = {0};1156 1157	if (status == NULL || status_updated == NULL) {1158		return;1159	}1160 1161	core_link_read_dpcd(1162			link,1163			DP_LANE0_1_STATUS,1164			dpcd_buf,1165			sizeof(dpcd_buf));1166 1167	for (lane = 0; lane < lane_count; lane++) {1168		status[lane].raw = dp_get_nibble_at_index(&dpcd_buf[0], lane);1169	}1170 1171	status_updated->raw = dpcd_buf[2];1172}1173 1174static bool poll_for_allocation_change_trigger(struct dc_link *link)1175{1176	/*1177	 * wait for ACT handled1178	 */1179	int i;1180	const int act_retries = 30;1181	enum act_return_status result = ACT_FAILED;1182	enum dc_connection_type display_connected = (link->type != dc_connection_none);1183	union payload_table_update_status update_status = {0};1184	union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];1185	union lane_align_status_updated lane_status_updated;1186	DC_LOGGER_INIT(link->ctx->logger);1187 1188	if (!display_connected || link->aux_access_disabled)1189		return true;1190	for (i = 0; i < act_retries; i++) {1191		get_lane_status(link, link->cur_link_settings.lane_count, dpcd_lane_status, &lane_status_updated);1192 1193		if (!dp_is_cr_done(link->cur_link_settings.lane_count, dpcd_lane_status) ||1194				!dp_is_ch_eq_done(link->cur_link_settings.lane_count, dpcd_lane_status) ||1195				!dp_is_symbol_locked(link->cur_link_settings.lane_count, dpcd_lane_status) ||1196				!dp_is_interlane_aligned(lane_status_updated)) {1197			DC_LOG_ERROR("SST Update Payload: Link loss occurred while "1198					"polling for ACT handled.");1199			result = ACT_LINK_LOST;1200			break;1201		}1202		core_link_read_dpcd(1203				link,1204				DP_PAYLOAD_TABLE_UPDATE_STATUS,1205				&update_status.raw,1206				1);1207 1208		if (update_status.bits.ACT_HANDLED == 1) {1209			DC_LOG_DP2("SST Update Payload: ACT handled by downstream.");1210			result = ACT_SUCCESS;1211			break;1212		}1213 1214		fsleep(5000);1215	}1216 1217	if (result == ACT_FAILED) {1218		DC_LOG_ERROR("SST Update Payload: ACT still not handled after retries, "1219				"continue on. Something is wrong with the branch.");1220	}1221 1222	return (result == ACT_SUCCESS);1223}1224 1225static void update_mst_stream_alloc_table(1226	struct dc_link *link,1227	struct stream_encoder *stream_enc,1228	struct hpo_dp_stream_encoder *hpo_dp_stream_enc, // TODO: Rename stream_enc to dio_stream_enc?1229	const struct dc_dp_mst_stream_allocation_table *proposed_table)1230{1231	struct link_mst_stream_allocation work_table[MAX_CONTROLLER_NUM] = { 0 };1232	struct link_mst_stream_allocation *dc_alloc;1233 1234	int i;1235	int j;1236 1237	/* if DRM proposed_table has more than one new payload */1238	ASSERT(proposed_table->stream_count -1239			link->mst_stream_alloc_table.stream_count < 2);1240 1241	/* copy proposed_table to link, add stream encoder */1242	for (i = 0; i < proposed_table->stream_count; i++) {1243 1244		for (j = 0; j < link->mst_stream_alloc_table.stream_count; j++) {1245			dc_alloc =1246			&link->mst_stream_alloc_table.stream_allocations[j];1247 1248			if (dc_alloc->vcp_id ==1249				proposed_table->stream_allocations[i].vcp_id) {1250 1251				work_table[i] = *dc_alloc;1252				work_table[i].slot_count = proposed_table->stream_allocations[i].slot_count;1253				break; /* exit j loop */1254			}1255		}1256 1257		/* new vcp_id */1258		if (j == link->mst_stream_alloc_table.stream_count) {1259			work_table[i].vcp_id =1260				proposed_table->stream_allocations[i].vcp_id;1261			work_table[i].slot_count =1262				proposed_table->stream_allocations[i].slot_count;1263			work_table[i].stream_enc = stream_enc;1264			work_table[i].hpo_dp_stream_enc = hpo_dp_stream_enc;1265		}1266	}1267 1268	/* update link->mst_stream_alloc_table with work_table */1269	link->mst_stream_alloc_table.stream_count =1270			proposed_table->stream_count;1271	for (i = 0; i < MAX_CONTROLLER_NUM; i++)1272		link->mst_stream_alloc_table.stream_allocations[i] =1273				work_table[i];1274}1275 1276static void remove_stream_from_alloc_table(1277		struct dc_link *link,1278		struct stream_encoder *dio_stream_enc,1279		struct hpo_dp_stream_encoder *hpo_dp_stream_enc)1280{1281	int i = 0;1282	struct link_mst_stream_allocation_table *table =1283			&link->mst_stream_alloc_table;1284 1285	if (hpo_dp_stream_enc) {1286		for (; i < table->stream_count; i++)1287			if (hpo_dp_stream_enc == table->stream_allocations[i].hpo_dp_stream_enc)1288				break;1289	} else {1290		for (; i < table->stream_count; i++)1291			if (dio_stream_enc == table->stream_allocations[i].stream_enc)1292				break;1293	}1294 1295	if (i < table->stream_count) {1296		i++;1297		for (; i < table->stream_count; i++)1298			table->stream_allocations[i-1] = table->stream_allocations[i];1299		memset(&table->stream_allocations[table->stream_count-1], 0,1300				sizeof(struct link_mst_stream_allocation));1301		table->stream_count--;1302	}1303}1304 1305static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)1306{1307	struct dc_stream_state *stream = pipe_ctx->stream;1308	struct dc_link *link = stream->link;1309	struct dc_dp_mst_stream_allocation_table proposed_table = {0};1310	struct fixed31_32 avg_time_slots_per_mtp = dc_fixpt_from_int(0);1311	int i;1312	bool mst_mode = (link->type == dc_connection_mst_branch);1313	const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);1314	const struct dc_link_settings empty_link_settings = {0};1315	DC_LOGGER_INIT(link->ctx->logger);1316 1317	/* deallocate_mst_payload is called before disable link. When mode or1318	 * disable/enable monitor, new stream is created which is not in link1319	 * stream[] yet. For this, payload is not allocated yet, so de-alloc1320	 * should not done. For new mode set, map_resources will get engine1321	 * for new stream, so stream_enc->id should be validated until here.1322	 */1323 1324	/* slot X.Y */1325	if (link_hwss->ext.set_throttled_vcp_size)1326		link_hwss->ext.set_throttled_vcp_size(pipe_ctx, avg_time_slots_per_mtp);1327	if (link_hwss->ext.set_hblank_min_symbol_width)1328		link_hwss->ext.set_hblank_min_symbol_width(pipe_ctx,1329				&empty_link_settings,1330				avg_time_slots_per_mtp);1331 1332	if (mst_mode) {1333		/* when link is in mst mode, reply on mst manager to remove1334		 * payload1335		 */1336		if (dm_helpers_dp_mst_write_payload_allocation_table(1337				stream->ctx,1338				stream,1339				&proposed_table,1340				false))1341			update_mst_stream_alloc_table(1342					link,1343					pipe_ctx->stream_res.stream_enc,1344					pipe_ctx->stream_res.hpo_dp_stream_enc,1345					&proposed_table);1346		else1347			DC_LOG_WARNING("Failed to update"1348					"MST allocation table for"1349					"pipe idx:%d\n",1350					pipe_ctx->pipe_idx);1351	} else {1352		/* when link is no longer in mst mode (mst hub unplugged),1353		 * remove payload with default dc logic1354		 */1355		remove_stream_from_alloc_table(link, pipe_ctx->stream_res.stream_enc,1356				pipe_ctx->stream_res.hpo_dp_stream_enc);1357	}1358 1359	DC_LOG_MST("%s"1360			"stream_count: %d: ",1361			__func__,1362			link->mst_stream_alloc_table.stream_count);1363 1364	for (i = 0; i < MAX_CONTROLLER_NUM; i++) {1365		DC_LOG_MST("stream_enc[%d]: %p      "1366		"stream[%d].hpo_dp_stream_enc: %p      "1367		"stream[%d].vcp_id: %d      "1368		"stream[%d].slot_count: %d\n",1369		i,1370		(void *) link->mst_stream_alloc_table.stream_allocations[i].stream_enc,1371		i,1372		(void *) link->mst_stream_alloc_table.stream_allocations[i].hpo_dp_stream_enc,1373		i,1374		link->mst_stream_alloc_table.stream_allocations[i].vcp_id,1375		i,1376		link->mst_stream_alloc_table.stream_allocations[i].slot_count);1377	}1378 1379	/* update mst stream allocation table hardware state */1380	if (link_hwss->ext.update_stream_allocation_table == NULL ||1381			link_dp_get_encoding_format(&link->cur_link_settings) == DP_UNKNOWN_ENCODING) {1382		DC_LOG_DEBUG("Unknown encoding format\n");1383		return DC_ERROR_UNEXPECTED;1384	}1385 1386	link_hwss->ext.update_stream_allocation_table(link, &pipe_ctx->link_res,1387			&link->mst_stream_alloc_table);1388 1389	if (mst_mode)1390		dm_helpers_dp_mst_poll_for_allocation_change_trigger(1391			stream->ctx,1392			stream);1393 1394	dm_helpers_dp_mst_update_mst_mgr_for_deallocation(1395			stream->ctx,1396			stream);1397 1398	return DC_OK;1399}1400 1401/* convert link_mst_stream_alloc_table to dm dp_mst_stream_alloc_table1402 * because stream_encoder is not exposed to dm1403 */1404static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx)1405{1406	struct dc_stream_state *stream = pipe_ctx->stream;1407	struct dc_link *link = stream->link;1408	struct dc_dp_mst_stream_allocation_table proposed_table = {0};1409	struct fixed31_32 avg_time_slots_per_mtp;1410	struct fixed31_32 pbn;1411	struct fixed31_32 pbn_per_slot;1412	int i;1413	enum act_return_status ret;1414	const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);1415	DC_LOGGER_INIT(link->ctx->logger);1416 1417	/* enable_link_dp_mst already check link->enabled_stream_count1418	 * and stream is in link->stream[]. This is called during set mode,1419	 * stream_enc is available.1420	 */1421 1422	/* get calculate VC payload for stream: stream_alloc */1423	if (dm_helpers_dp_mst_write_payload_allocation_table(1424		stream->ctx,1425		stream,1426		&proposed_table,1427		true))1428		update_mst_stream_alloc_table(1429					link,1430					pipe_ctx->stream_res.stream_enc,1431					pipe_ctx->stream_res.hpo_dp_stream_enc,1432					&proposed_table);1433	else1434		DC_LOG_WARNING("Failed to update"1435				"MST allocation table for"1436				"pipe idx:%d\n",1437				pipe_ctx->pipe_idx);1438 1439	DC_LOG_MST("%s  "1440			"stream_count: %d: \n ",1441			__func__,1442			link->mst_stream_alloc_table.stream_count);1443 1444	for (i = 0; i < MAX_CONTROLLER_NUM; i++) {1445		DC_LOG_MST("stream_enc[%d]: %p      "1446		"stream[%d].hpo_dp_stream_enc: %p      "1447		"stream[%d].vcp_id: %d      "1448		"stream[%d].slot_count: %d\n",1449		i,1450		(void *) link->mst_stream_alloc_table.stream_allocations[i].stream_enc,1451		i,1452		(void *) link->mst_stream_alloc_table.stream_allocations[i].hpo_dp_stream_enc,1453		i,1454		link->mst_stream_alloc_table.stream_allocations[i].vcp_id,1455		i,1456		link->mst_stream_alloc_table.stream_allocations[i].slot_count);1457	}1458 1459	ASSERT(proposed_table.stream_count > 0);1460 1461	/* program DP source TX for payload */1462	if (link_hwss->ext.update_stream_allocation_table == NULL ||1463			link_dp_get_encoding_format(&link->cur_link_settings) == DP_UNKNOWN_ENCODING) {1464		DC_LOG_ERROR("Failure: unknown encoding format\n");1465		return DC_ERROR_UNEXPECTED;1466	}1467 1468	link_hwss->ext.update_stream_allocation_table(link,1469			&pipe_ctx->link_res,1470			&link->mst_stream_alloc_table);1471 1472	/* send down message */1473	ret = dm_helpers_dp_mst_poll_for_allocation_change_trigger(1474			stream->ctx,1475			stream);1476 1477	if (ret != ACT_LINK_LOST)1478		dm_helpers_dp_mst_send_payload_allocation(1479				stream->ctx,1480				stream);1481 1482	/* slot X.Y for only current stream */1483	pbn_per_slot = get_pbn_per_slot(stream);1484	if (pbn_per_slot.value == 0) {1485		DC_LOG_ERROR("Failure: pbn_per_slot==0 not allowed. Cannot continue, returning DC_UNSUPPORTED_VALUE.\n");1486		return DC_UNSUPPORTED_VALUE;1487	}1488	pbn = get_pbn_from_timing(pipe_ctx);1489	avg_time_slots_per_mtp = dc_fixpt_div(pbn, pbn_per_slot);1490 1491	log_vcp_x_y(link, avg_time_slots_per_mtp);1492 1493	if (link_hwss->ext.set_throttled_vcp_size)1494		link_hwss->ext.set_throttled_vcp_size(pipe_ctx, avg_time_slots_per_mtp);1495	if (link_hwss->ext.set_hblank_min_symbol_width)1496		link_hwss->ext.set_hblank_min_symbol_width(pipe_ctx,1497				&link->cur_link_settings,1498				avg_time_slots_per_mtp);1499 1500	return DC_OK;1501}1502 1503struct fixed31_32 link_calculate_sst_avg_time_slots_per_mtp(1504		const struct dc_stream_state *stream,1505		const struct dc_link *link)1506{1507	struct fixed31_32 link_bw_effective =1508			dc_fixpt_from_int(1509					dp_link_bandwidth_kbps(link, &link->cur_link_settings));1510	struct fixed31_32 timeslot_bw_effective =1511			dc_fixpt_div_int(link_bw_effective, MAX_MTP_SLOT_COUNT);1512	struct fixed31_32 timing_bw =1513			dc_fixpt_from_int(1514					dc_bandwidth_in_kbps_from_timing(&stream->timing,1515							dc_link_get_highest_encoding_format(link)));1516	struct fixed31_32 avg_time_slots_per_mtp =1517			dc_fixpt_div(timing_bw, timeslot_bw_effective);1518 1519	return avg_time_slots_per_mtp;1520}1521 1522 1523static bool write_128b_132b_sst_payload_allocation_table(1524		const struct dc_stream_state *stream,1525		struct dc_link *link,1526		struct link_mst_stream_allocation_table *proposed_table,1527		bool allocate)1528{1529	const uint8_t vc_id = 1; /// VC ID always 1 for SST1530	const uint8_t start_time_slot = 0; /// Always start at time slot 0 for SST1531	bool result = false;1532	uint8_t req_slot_count = 0;1533	struct fixed31_32 avg_time_slots_per_mtp = { 0 };1534	union payload_table_update_status update_status = { 0 };1535	const uint32_t max_retries = 30;1536	uint32_t retries = 0;1537	enum dc_connection_type display_connected = (link->type != dc_connection_none);1538	DC_LOGGER_INIT(link->ctx->logger);1539 1540	if (allocate)	{1541		avg_time_slots_per_mtp = link_calculate_sst_avg_time_slots_per_mtp(stream, link);1542		req_slot_count = dc_fixpt_ceil(avg_time_slots_per_mtp);1543		/// Validation should filter out modes that exceed link BW1544		ASSERT(req_slot_count <= MAX_MTP_SLOT_COUNT);1545		if (req_slot_count > MAX_MTP_SLOT_COUNT)1546			return false;1547	} else {1548		/// Leave req_slot_count = 0 if allocate is false.1549	}1550 1551	proposed_table->stream_count = 1; /// Always 1 stream for SST1552	proposed_table->stream_allocations[0].slot_count = req_slot_count;1553	proposed_table->stream_allocations[0].vcp_id = vc_id;1554 1555	if (!display_connected || link->aux_access_disabled)1556		return true;1557 1558	/// Write DPCD 2C0 = 1 to start updating1559	update_status.bits.VC_PAYLOAD_TABLE_UPDATED = 1;1560	core_link_write_dpcd(1561			link,1562			DP_PAYLOAD_TABLE_UPDATE_STATUS,1563			&update_status.raw,1564			1);1565 1566	/// Program the changes in DPCD 1C0 - 1C21567	ASSERT(vc_id == 1);1568	core_link_write_dpcd(1569			link,1570			DP_PAYLOAD_ALLOCATE_SET,1571			&vc_id,1572			1);1573 1574	ASSERT(start_time_slot == 0);1575	core_link_write_dpcd(1576			link,1577			DP_PAYLOAD_ALLOCATE_START_TIME_SLOT,1578			&start_time_slot,1579			1);1580 1581	core_link_write_dpcd(1582			link,1583			DP_PAYLOAD_ALLOCATE_TIME_SLOT_COUNT,1584			&req_slot_count,1585			1);1586 1587	/// Poll till DPCD 2C0 read 11588	/// Try for at least 150ms (30 retries, with 5ms delay after each attempt)1589 1590	while (retries < max_retries) {1591		if (core_link_read_dpcd(1592				link,1593				DP_PAYLOAD_TABLE_UPDATE_STATUS,1594				&update_status.raw,1595				1) == DC_OK) {1596			if (update_status.bits.VC_PAYLOAD_TABLE_UPDATED == 1) {1597				DC_LOG_DP2("SST Update Payload: downstream payload table updated.");1598				result = true;1599				break;1600			}1601		} else {1602			union dpcd_rev dpcdRev = {0};1603 1604			if (core_link_read_dpcd(1605					link,1606					DP_DPCD_REV,1607					&dpcdRev.raw,1608					1) != DC_OK) {1609				DC_LOG_ERROR("SST Update Payload: Unable to read DPCD revision "1610						"of sink while polling payload table "1611						"updated status bit.");1612				break;1613			}1614		}1615		retries++;1616		fsleep(5000);1617	}1618 1619	if (!result && retries == max_retries) {1620		DC_LOG_ERROR("SST Update Payload: Payload table not updated after retries, "1621				"continue on. Something is wrong with the branch.");1622		// TODO - DP2.0 Payload: Read and log the payload table from downstream branch1623	}1624 1625	return result;1626}1627 1628/*1629 * Payload allocation/deallocation for SST introduced in DP2.01630 */1631static enum dc_status update_sst_payload(struct pipe_ctx *pipe_ctx,1632						 bool allocate)1633{1634	struct dc_stream_state *stream = pipe_ctx->stream;1635	struct dc_link *link = stream->link;1636	struct link_mst_stream_allocation_table proposed_table = {0};1637	struct fixed31_32 avg_time_slots_per_mtp;1638	const struct dc_link_settings empty_link_settings = {0};1639	const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);1640	DC_LOGGER_INIT(link->ctx->logger);1641 1642	/* slot X.Y for SST payload deallocate */1643	if (!allocate) {1644		avg_time_slots_per_mtp = dc_fixpt_from_int(0);1645 1646		log_vcp_x_y(link, avg_time_slots_per_mtp);1647 1648		if (link_hwss->ext.set_throttled_vcp_size)1649			link_hwss->ext.set_throttled_vcp_size(pipe_ctx,1650					avg_time_slots_per_mtp);1651		if (link_hwss->ext.set_hblank_min_symbol_width)1652			link_hwss->ext.set_hblank_min_symbol_width(pipe_ctx,1653					&empty_link_settings,1654					avg_time_slots_per_mtp);1655	}1656 1657	/* calculate VC payload and update branch with new payload allocation table*/1658	if (!write_128b_132b_sst_payload_allocation_table(1659			stream,1660			link,1661			&proposed_table,1662			allocate)) {1663		DC_LOG_ERROR("SST Update Payload: Failed to update "1664						"allocation table for "1665						"pipe idx: %d\n",1666						pipe_ctx->pipe_idx);1667		return DC_FAIL_DP_PAYLOAD_ALLOCATION;1668	}1669 1670	proposed_table.stream_allocations[0].hpo_dp_stream_enc = pipe_ctx->stream_res.hpo_dp_stream_enc;1671 1672	ASSERT(proposed_table.stream_count == 1);1673 1674	//TODO - DP2.0 Logging: Instead of hpo_dp_stream_enc pointer, log instance id1675	DC_LOG_DP2("SST Update Payload: hpo_dp_stream_enc: %p      "1676		"vcp_id: %d      "1677		"slot_count: %d\n",1678		(void *) proposed_table.stream_allocations[0].hpo_dp_stream_enc,1679		proposed_table.stream_allocations[0].vcp_id,1680		proposed_table.stream_allocations[0].slot_count);1681 1682	/* program DP source TX for payload */1683	link_hwss->ext.update_stream_allocation_table(link, &pipe_ctx->link_res,1684			&proposed_table);1685 1686	/* poll for ACT handled */1687	if (!poll_for_allocation_change_trigger(link)) {1688		// Failures will result in blackscreen and errors logged1689		BREAK_TO_DEBUGGER();1690	}1691 1692	/* slot X.Y for SST payload allocate */1693	if (allocate && link_dp_get_encoding_format(&link->cur_link_settings) ==1694			DP_128b_132b_ENCODING) {1695		avg_time_slots_per_mtp = link_calculate_sst_avg_time_slots_per_mtp(stream, link);1696 1697		log_vcp_x_y(link, avg_time_slots_per_mtp);1698 1699		if (link_hwss->ext.set_throttled_vcp_size)1700			link_hwss->ext.set_throttled_vcp_size(pipe_ctx,1701					avg_time_slots_per_mtp);1702		if (link_hwss->ext.set_hblank_min_symbol_width)1703			link_hwss->ext.set_hblank_min_symbol_width(pipe_ctx,1704					&link->cur_link_settings,1705					avg_time_slots_per_mtp);1706	}1707 1708	/* Always return DC_OK.1709	 * If part of sequence fails, log failure(s) and show blackscreen1710	 */1711	return DC_OK;1712}1713 1714enum dc_status link_reduce_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t bw_in_kbps)1715{1716	struct dc_stream_state *stream = pipe_ctx->stream;1717	struct dc_link *link = stream->link;1718	struct fixed31_32 avg_time_slots_per_mtp;1719	struct fixed31_32 pbn;1720	struct fixed31_32 pbn_per_slot;1721	struct dc_dp_mst_stream_allocation_table proposed_table = {0};1722	uint8_t i;1723	const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);1724	DC_LOGGER_INIT(link->ctx->logger);1725 1726	/* decrease throttled vcp size */1727	pbn_per_slot = get_pbn_per_slot(stream);1728	pbn = get_pbn_from_bw_in_kbps(bw_in_kbps);1729	avg_time_slots_per_mtp = dc_fixpt_div(pbn, pbn_per_slot);1730 1731	if (link_hwss->ext.set_throttled_vcp_size)1732		link_hwss->ext.set_throttled_vcp_size(pipe_ctx, avg_time_slots_per_mtp);1733	if (link_hwss->ext.set_hblank_min_symbol_width)1734		link_hwss->ext.set_hblank_min_symbol_width(pipe_ctx,1735				&link->cur_link_settings,1736				avg_time_slots_per_mtp);1737 1738	/* send ALLOCATE_PAYLOAD sideband message with updated pbn */1739	dm_helpers_dp_mst_send_payload_allocation(1740			stream->ctx,1741			stream);1742 1743	/* notify immediate branch device table update */1744	if (dm_helpers_dp_mst_write_payload_allocation_table(1745			stream->ctx,1746			stream,1747			&proposed_table,1748			true)) {1749		/* update mst stream allocation table software state */1750		update_mst_stream_alloc_table(1751				link,1752				pipe_ctx->stream_res.stream_enc,1753				pipe_ctx->stream_res.hpo_dp_stream_enc,1754				&proposed_table);1755	} else {1756		DC_LOG_WARNING("Failed to update"1757				"MST allocation table for"1758				"pipe idx:%d\n",1759				pipe_ctx->pipe_idx);1760	}1761 1762	DC_LOG_MST("%s  "1763			"stream_count: %d: \n ",1764			__func__,1765			link->mst_stream_alloc_table.stream_count);1766 1767	for (i = 0; i < MAX_CONTROLLER_NUM; i++) {1768		DC_LOG_MST("stream_enc[%d]: %p      "1769		"stream[%d].hpo_dp_stream_enc: %p      "1770		"stream[%d].vcp_id: %d      "1771		"stream[%d].slot_count: %d\n",1772		i,1773		(void *) link->mst_stream_alloc_table.stream_allocations[i].stream_enc,1774		i,1775		(void *) link->mst_stream_alloc_table.stream_allocations[i].hpo_dp_stream_enc,1776		i,1777		link->mst_stream_alloc_table.stream_allocations[i].vcp_id,1778		i,1779		link->mst_stream_alloc_table.stream_allocations[i].slot_count);1780	}1781 1782	ASSERT(proposed_table.stream_count > 0);1783 1784	/* update mst stream allocation table hardware state */1785	if (link_hwss->ext.update_stream_allocation_table == NULL ||1786			link_dp_get_encoding_format(&link->cur_link_settings) == DP_UNKNOWN_ENCODING) {1787		DC_LOG_ERROR("Failure: unknown encoding format\n");1788		return DC_ERROR_UNEXPECTED;1789	}1790 1791	link_hwss->ext.update_stream_allocation_table(link, &pipe_ctx->link_res,1792			&link->mst_stream_alloc_table);1793 1794	/* poll for immediate branch device ACT handled */1795	dm_helpers_dp_mst_poll_for_allocation_change_trigger(1796			stream->ctx,1797			stream);1798 1799	return DC_OK;1800}1801 1802enum dc_status link_increase_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t bw_in_kbps)1803{1804	struct dc_stream_state *stream = pipe_ctx->stream;1805	struct dc_link *link = stream->link;1806	struct fixed31_32 avg_time_slots_per_mtp;1807	struct fixed31_32 pbn;1808	struct fixed31_32 pbn_per_slot;1809	struct dc_dp_mst_stream_allocation_table proposed_table = {0};1810	uint8_t i;1811	enum act_return_status ret;1812	const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);1813	DC_LOGGER_INIT(link->ctx->logger);1814 1815	/* notify immediate branch device table update */1816	if (dm_helpers_dp_mst_write_payload_allocation_table(1817				stream->ctx,1818				stream,1819				&proposed_table,1820				true)) {1821		/* update mst stream allocation table software state */1822		update_mst_stream_alloc_table(1823				link,1824				pipe_ctx->stream_res.stream_enc,1825				pipe_ctx->stream_res.hpo_dp_stream_enc,1826				&proposed_table);1827	}1828 1829	DC_LOG_MST("%s  "1830			"stream_count: %d: \n ",1831			__func__,1832			link->mst_stream_alloc_table.stream_count);1833 1834	for (i = 0; i < MAX_CONTROLLER_NUM; i++) {1835		DC_LOG_MST("stream_enc[%d]: %p      "1836		"stream[%d].hpo_dp_stream_enc: %p      "1837		"stream[%d].vcp_id: %d      "1838		"stream[%d].slot_count: %d\n",1839		i,1840		(void *) link->mst_stream_alloc_table.stream_allocations[i].stream_enc,1841		i,1842		(void *) link->mst_stream_alloc_table.stream_allocations[i].hpo_dp_stream_enc,1843		i,1844		link->mst_stream_alloc_table.stream_allocations[i].vcp_id,1845		i,1846		link->mst_stream_alloc_table.stream_allocations[i].slot_count);1847	}1848 1849	ASSERT(proposed_table.stream_count > 0);1850 1851	/* update mst stream allocation table hardware state */1852	if (link_hwss->ext.update_stream_allocation_table == NULL ||1853			link_dp_get_encoding_format(&link->cur_link_settings) == DP_UNKNOWN_ENCODING) {1854		DC_LOG_ERROR("Failure: unknown encoding format\n");1855		return DC_ERROR_UNEXPECTED;1856	}1857 1858	link_hwss->ext.update_stream_allocation_table(link, &pipe_ctx->link_res,1859			&link->mst_stream_alloc_table);1860 1861	/* poll for immediate branch device ACT handled */1862	ret = dm_helpers_dp_mst_poll_for_allocation_change_trigger(1863			stream->ctx,1864			stream);1865 1866	if (ret != ACT_LINK_LOST) {1867		/* send ALLOCATE_PAYLOAD sideband message with updated pbn */1868		dm_helpers_dp_mst_send_payload_allocation(1869				stream->ctx,1870				stream);1871	}1872 1873	/* increase throttled vcp size */1874	pbn = get_pbn_from_bw_in_kbps(bw_in_kbps);1875	pbn_per_slot = get_pbn_per_slot(stream);1876	avg_time_slots_per_mtp = dc_fixpt_div(pbn, pbn_per_slot);1877 1878	if (link_hwss->ext.set_throttled_vcp_size)1879		link_hwss->ext.set_throttled_vcp_size(pipe_ctx, avg_time_slots_per_mtp);1880	if (link_hwss->ext.set_hblank_min_symbol_width)1881		link_hwss->ext.set_hblank_min_symbol_width(pipe_ctx,1882				&link->cur_link_settings,1883				avg_time_slots_per_mtp);1884 1885	return DC_OK;1886}1887 1888static void disable_link_dp(struct dc_link *link,1889		const struct link_resource *link_res,1890		enum signal_type signal)1891{1892	struct dc_link_settings link_settings = link->cur_link_settings;1893 1894	if (signal == SIGNAL_TYPE_DISPLAY_PORT_MST &&1895			link->mst_stream_alloc_table.stream_count > 0)1896		/* disable MST link only when last vc payload is deallocated */1897		return;1898 1899	dp_disable_link_phy(link, link_res, signal);1900 1901	if (link->connector_signal == SIGNAL_TYPE_EDP) {1902		if (!link->skip_implict_edp_power_control)1903			link->dc->hwss.edp_power_control(link, false);1904	}1905 1906	if (signal == SIGNAL_TYPE_DISPLAY_PORT_MST)1907		/* set the sink to SST mode after disabling the link */1908		enable_mst_on_sink(link, false);1909 1910	if (link_dp_get_encoding_format(&link_settings) ==1911			DP_8b_10b_ENCODING) {1912		dp_set_fec_enable(link, false);1913		dp_set_fec_ready(link, link_res, false);1914	}1915}1916 1917static void disable_link(struct dc_link *link,1918		const struct link_resource *link_res,1919		enum signal_type signal)1920{1921	if (dc_is_dp_signal(signal)) {1922		disable_link_dp(link, link_res, signal);1923	} else if (signal == SIGNAL_TYPE_VIRTUAL) {1924		link->dc->hwss.disable_link_output(link, link_res, SIGNAL_TYPE_DISPLAY_PORT);1925	} else {1926		link->dc->hwss.disable_link_output(link, link_res, signal);1927	}1928 1929	if (signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {1930		/* MST disable link only when no stream use the link */1931		if (link->mst_stream_alloc_table.stream_count <= 0)1932			link->link_status.link_active = false;1933	} else {1934		link->link_status.link_active = false;1935	}1936}1937 1938static void enable_link_hdmi(struct pipe_ctx *pipe_ctx)1939{1940	struct dc_stream_state *stream = pipe_ctx->stream;1941	struct dc_link *link = stream->link;1942	enum dc_color_depth display_color_depth;1943	enum engine_id eng_id;1944	struct ext_hdmi_settings settings = {0};1945	bool is_over_340mhz = false;1946	bool is_vga_mode = (stream->timing.h_addressable == 640)1947			&& (stream->timing.v_addressable == 480);1948	struct dc *dc = pipe_ctx->stream->ctx->dc;1949	const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);1950 1951	if (stream->phy_pix_clk == 0)1952		stream->phy_pix_clk = stream->timing.pix_clk_100hz / 10;1953	if (stream->phy_pix_clk > 340000)1954		is_over_340mhz = true;1955 1956	if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) {1957		unsigned short masked_chip_caps = pipe_ctx->stream->link->chip_caps &1958				EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK;1959		if (masked_chip_caps == EXT_DISPLAY_PATH_CAPS__HDMI20_TISN65DP159RSBT) {1960			/* DP159, Retimer settings */1961			eng_id = pipe_ctx->stream_res.stream_enc->id;1962 1963			if (get_ext_hdmi_settings(pipe_ctx, eng_id, &settings)) {1964				write_i2c_retimer_setting(pipe_ctx,1965						is_vga_mode, is_over_340mhz, &settings);1966			} else {1967				write_i2c_default_retimer_setting(pipe_ctx,1968						is_vga_mode, is_over_340mhz);1969			}1970		} else if (masked_chip_caps == EXT_DISPLAY_PATH_CAPS__HDMI20_PI3EQX1204) {1971			/* PI3EQX1204, Redriver settings */1972			write_i2c_redriver_setting(pipe_ctx, is_over_340mhz);1973		}1974	}1975 1976	if (dc_is_hdmi_signal(pipe_ctx->stream->signal))1977		write_scdc_data(1978			stream->link->ddc,1979			stream->phy_pix_clk,1980			stream->timing.flags.LTE_340MCSC_SCRAMBLE);1981 1982	memset(&stream->link->cur_link_settings, 0,1983			sizeof(struct dc_link_settings));1984 1985	display_color_depth = stream->timing.display_color_depth;1986	if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR422)1987		display_color_depth = COLOR_DEPTH_888;1988 1989	/* We need to enable stream encoder for TMDS first to apply 1/4 TMDS1990	 * character clock in case that beyond 340MHz.1991	 */1992	if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal) || dc_is_dvi_signal(pipe_ctx->stream->signal))1993		link_hwss->setup_stream_encoder(pipe_ctx);1994 1995	dc->hwss.enable_tmds_link_output(1996			link,1997			&pipe_ctx->link_res,1998			pipe_ctx->stream->signal,1999			pipe_ctx->clock_source->id,2000			display_color_depth,2001			stream->phy_pix_clk);2002 2003	if (dc_is_hdmi_signal(pipe_ctx->stream->signal))2004		read_scdc_data(link->ddc);2005}2006 2007static enum dc_status enable_link_dp(struct dc_state *state,2008				     struct pipe_ctx *pipe_ctx)2009{2010	struct dc_stream_state *stream = pipe_ctx->stream;2011	enum dc_status status;2012	bool skip_video_pattern;2013	struct dc_link *link = stream->link;2014	const struct dc_link_settings *link_settings =2015			&pipe_ctx->link_config.dp_link_settings;2016	bool fec_enable;2017	int i;2018	bool apply_seamless_boot_optimization = false;2019	uint32_t bl_oled_enable_delay = 50; // in ms2020	uint32_t post_oui_delay = 30; // 30ms2021	/* Reduce link bandwidth between failed link training attempts. */2022	bool do_fallback = false;2023	int lt_attempts = LINK_TRAINING_ATTEMPTS;2024 2025	// Increase retry count if attempting DP1.x on FIXED_VS link2026	if ((link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&2027			link_dp_get_encoding_format(link_settings) == DP_8b_10b_ENCODING)2028		lt_attempts = 10;2029 2030	// check for seamless boot2031	for (i = 0; i < state->stream_count; i++) {2032		if (state->streams[i]->apply_seamless_boot_optimization) {2033			apply_seamless_boot_optimization = true;2034			break;2035		}2036	}2037 2038	/* Train with fallback when enabling DPIA link. Conventional links are2039	 * trained with fallback during sink detection.2040	 */2041	if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA)2042		do_fallback = true;2043 2044	/*2045	 * Temporary w/a to get DP2.0 link rates to work with SST.2046	 * TODO DP2.0 - Workaround: Remove w/a if and when the issue is resolved.2047	 */2048	if (link_dp_get_encoding_format(link_settings) == DP_128b_132b_ENCODING &&2049			pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT &&2050			link->dc->debug.set_mst_en_for_sst) {2051		enable_mst_on_sink(link, true);2052	}2053	if (pipe_ctx->stream->signal == SIGNAL_TYPE_EDP) {2054		/*in case it is not on*/2055		if (!link->dc->config.edp_no_power_sequencing)2056			link->dc->hwss.edp_power_control(link, true);2057		link->dc->hwss.edp_wait_for_hpd_ready(link, true);2058	}2059 2060	if (link_dp_get_encoding_format(link_settings) == DP_128b_132b_ENCODING) {2061		/* TODO - DP2.0 HW: calculate 32 symbol clock for HPO encoder */2062	} else {2063		pipe_ctx->stream_res.pix_clk_params.requested_sym_clk =2064				link_settings->link_rate * LINK_RATE_REF_FREQ_IN_KHZ;2065		if (state->clk_mgr && !apply_seamless_boot_optimization)2066			state->clk_mgr->funcs->update_clocks(state->clk_mgr,2067					state, false);2068	}2069 2070	// during mode switch we do DP_SET_POWER off then on, and OUI is lost2071	dpcd_set_source_specific_data(link);2072	if (link->dpcd_sink_ext_caps.raw != 0) {2073		post_oui_delay += link->panel_config.pps.extra_post_OUI_ms;2074		msleep(post_oui_delay);2075	}2076 2077	// similarly, mode switch can cause loss of cable ID2078	dpcd_write_cable_id_to_dprx(link);2079 2080	skip_video_pattern = true;2081 2082	if (link_settings->link_rate == LINK_RATE_LOW)2083		skip_video_pattern = false;2084 2085	if (perform_link_training_with_retries(link_settings,2086					       skip_video_pattern,2087					       lt_attempts,2088					       pipe_ctx,2089					       pipe_ctx->stream->signal,2090					       do_fallback)) {2091		status = DC_OK;2092	} else {2093		status = DC_FAIL_DP_LINK_TRAINING;2094	}2095 2096	if (link->preferred_training_settings.fec_enable)2097		fec_enable = *link->preferred_training_settings.fec_enable;2098	else2099		fec_enable = true;2100 2101	if (link_dp_get_encoding_format(link_settings) == DP_8b_10b_ENCODING)2102		dp_set_fec_enable(link, fec_enable);2103 2104	// during mode set we do DP_SET_POWER off then on, aux writes are lost2105	if (link->dpcd_sink_ext_caps.bits.oled == 1 ||2106		link->dpcd_sink_ext_caps.bits.sdr_aux_backlight_control == 1 ||2107		link->dpcd_sink_ext_caps.bits.hdr_aux_backlight_control == 1) {2108		set_default_brightness_aux(link);2109		if (link->dpcd_sink_ext_caps.bits.oled == 1)2110			msleep(bl_oled_enable_delay);2111		edp_backlight_enable_aux(link, true);2112	}2113 2114	return status;2115}2116 2117static enum dc_status enable_link_edp(2118		struct dc_state *state,2119		struct pipe_ctx *pipe_ctx)2120{2121	return enable_link_dp(state, pipe_ctx);2122}2123 2124static void enable_link_lvds(struct pipe_ctx *pipe_ctx)2125{2126	struct dc_stream_state *stream = pipe_ctx->stream;2127	struct dc_link *link = stream->link;2128	struct dc *dc = stream->ctx->dc;2129 2130	if (stream->phy_pix_clk == 0)2131		stream->phy_pix_clk = stream->timing.pix_clk_100hz / 10;2132 2133	memset(&stream->link->cur_link_settings, 0,2134			sizeof(struct dc_link_settings));2135	dc->hwss.enable_lvds_link_output(2136			link,2137			&pipe_ctx->link_res,2138			pipe_ctx->clock_source->id,2139			stream->phy_pix_clk);2140 2141}2142 2143static enum dc_status enable_link_dp_mst(2144		struct dc_state *state,2145		struct pipe_ctx *pipe_ctx)2146{2147	struct dc_link *link = pipe_ctx->stream->link;2148	unsigned char mstm_cntl = 0;2149 2150	/* sink signal type after MST branch is MST. Multiple MST sinks2151	 * share one link. Link DP PHY is enable or training only once.2152	 */2153	if (link->link_status.link_active)2154		return DC_OK;2155 2156	/* clear payload table */2157	core_link_read_dpcd(link, DP_MSTM_CTRL, &mstm_cntl, 1);2158	if (mstm_cntl & DP_MST_EN)2159		dm_helpers_dp_mst_clear_payload_allocation_table(link->ctx, link);2160 2161	/* to make sure the pending down rep can be processed2162	 * before enabling the link2163	 */2164	dm_helpers_dp_mst_poll_pending_down_reply(link->ctx, link);2165 2166	/* set the sink to MST mode before enabling the link */2167	enable_mst_on_sink(link, true);2168 2169	return enable_link_dp(state, pipe_ctx);2170}2171 2172static enum dc_status enable_link_virtual(struct pipe_ctx *pipe_ctx)2173{2174	struct dc_link *link = pipe_ctx->stream->link;2175 2176	link->dc->hwss.enable_dp_link_output(link,2177			&pipe_ctx->link_res,2178			SIGNAL_TYPE_DISPLAY_PORT,2179			pipe_ctx->clock_source->id,2180			&pipe_ctx->link_config.dp_link_settings);2181	return DC_OK;2182}2183 2184static enum dc_status enable_link(2185		struct dc_state *state,2186		struct pipe_ctx *pipe_ctx)2187{2188	enum dc_status status = DC_ERROR_UNEXPECTED;2189	struct dc_stream_state *stream = pipe_ctx->stream;2190	struct dc_link *link = stream->link;2191 2192	/* There's some scenarios where driver is unloaded with display2193	 * still enabled. When driver is reloaded, it may cause a display2194	 * to not light up if there is a mismatch between old and new2195	 * link settings. Need to call disable first before enabling at2196	 * new link settings.2197	 */2198	if (link->link_status.link_active)2199		disable_link(link, &pipe_ctx->link_res, pipe_ctx->stream->signal);2200 2201	switch (pipe_ctx->stream->signal) {2202	case SIGNAL_TYPE_DISPLAY_PORT:2203		status = enable_link_dp(state, pipe_ctx);2204		break;2205	case SIGNAL_TYPE_EDP:2206		status = enable_link_edp(state, pipe_ctx);2207		break;2208	case SIGNAL_TYPE_DISPLAY_PORT_MST:2209		status = enable_link_dp_mst(state, pipe_ctx);2210		msleep(200);2211		break;2212	case SIGNAL_TYPE_DVI_SINGLE_LINK:2213	case SIGNAL_TYPE_DVI_DUAL_LINK:2214	case SIGNAL_TYPE_HDMI_TYPE_A:2215		enable_link_hdmi(pipe_ctx);2216		status = DC_OK;2217		break;2218	case SIGNAL_TYPE_LVDS:2219		enable_link_lvds(pipe_ctx);2220		status = DC_OK;2221		break;2222	case SIGNAL_TYPE_VIRTUAL:2223		status = enable_link_virtual(pipe_ctx);2224		break;2225	default:2226		break;2227	}2228 2229	if (status == DC_OK) {2230		pipe_ctx->stream->link->link_status.link_active = true;2231	}2232 2233	return status;2234}2235 2236static bool allocate_usb4_bandwidth_for_stream(struct dc_stream_state *stream, int bw)2237{2238	struct dc_link *link = stream->sink->link;2239	int req_bw = bw;2240 2241	DC_LOGGER_INIT(link->ctx->logger);2242 2243	if (!link->dpia_bw_alloc_config.bw_alloc_enabled)2244		return false;2245 2246	if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {2247		int sink_index = 0;2248		int i = 0;2249 2250		for (i = 0; i < link->sink_count; i++) {2251			if (link->remote_sinks[i] == NULL)2252				continue;2253 2254			if (stream->sink->sink_id != link->remote_sinks[i]->sink_id)2255				req_bw += link->dpia_bw_alloc_config.remote_sink_req_bw[i];2256			else2257				sink_index = i;2258		}2259 2260		link->dpia_bw_alloc_config.remote_sink_req_bw[sink_index] = bw;2261	}2262 2263	/* get dp overhead for dp tunneling */2264	link->dpia_bw_alloc_config.dp_overhead = link_dp_dpia_get_dp_overhead_in_dp_tunneling(link);2265	req_bw += link->dpia_bw_alloc_config.dp_overhead;2266 2267	if (link_dp_dpia_allocate_usb4_bandwidth_for_stream(link, req_bw)) {2268		if (req_bw <= link->dpia_bw_alloc_config.allocated_bw) {2269			DC_LOG_DEBUG("%s, Success in allocate bw for link(%d), allocated_bw(%d), dp_overhead(%d)\n",2270					__func__, link->link_index, link->dpia_bw_alloc_config.allocated_bw,2271					link->dpia_bw_alloc_config.dp_overhead);2272		} else {2273			// Cannot get the required bandwidth.2274			DC_LOG_ERROR("%s, Failed to allocate bw for link(%d), allocated_bw(%d), dp_overhead(%d)\n",2275					__func__, link->link_index, link->dpia_bw_alloc_config.allocated_bw,2276					link->dpia_bw_alloc_config.dp_overhead);2277			return false;2278		}2279	} else {2280		DC_LOG_DEBUG("%s, usb4 request bw timeout\n", __func__);2281		return false;2282	}2283 2284	if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {2285		int i = 0;2286 2287		for (i = 0; i < link->sink_count; i++) {2288			if (link->remote_sinks[i] == NULL)2289				continue;2290			DC_LOG_DEBUG("%s, remote_sink=%s, request_bw=%d\n", __func__,2291					(const char *)(&link->remote_sinks[i]->edid_caps.display_name[0]),2292					link->dpia_bw_alloc_config.remote_sink_req_bw[i]);2293		}2294	}2295 2296	return true;2297}2298 2299static bool allocate_usb4_bandwidth(struct dc_stream_state *stream)2300{2301	bool ret;2302 2303	int bw = dc_bandwidth_in_kbps_from_timing(&stream->timing,2304			dc_link_get_highest_encoding_format(stream->sink->link));2305 2306	ret = allocate_usb4_bandwidth_for_stream(stream, bw);2307 2308	return ret;2309}2310 2311static bool deallocate_usb4_bandwidth(struct dc_stream_state *stream)2312{2313	bool ret;2314 2315	ret = allocate_usb4_bandwidth_for_stream(stream, 0);2316 2317	return ret;2318}2319 2320void link_set_dpms_off(struct pipe_ctx *pipe_ctx)2321{2322	struct dc  *dc = pipe_ctx->stream->ctx->dc;2323	struct dc_stream_state *stream = pipe_ctx->stream;2324	struct dc_link *link = stream->sink->link;2325	struct vpg *vpg = pipe_ctx->stream_res.stream_enc->vpg;2326	enum dp_panel_mode panel_mode_dp = dp_get_panel_mode(link);2327 2328	DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);2329 2330	ASSERT(is_master_pipe_for_link(link, pipe_ctx));2331 2332	if (dp_is_128b_132b_signal(pipe_ctx))2333		vpg = pipe_ctx->stream_res.hpo_dp_stream_enc->vpg;2334	if (dc_is_virtual_signal(pipe_ctx->stream->signal))2335		return;2336 2337	if (pipe_ctx->stream->sink) {2338		if (pipe_ctx->stream->sink->sink_signal != SIGNAL_TYPE_VIRTUAL &&2339			pipe_ctx->stream->sink->sink_signal != SIGNAL_TYPE_NONE) {2340			DC_LOG_DC("%s pipe_ctx dispname=%s signal=%x\n", __func__,2341			pipe_ctx->stream->sink->edid_caps.display_name,2342			pipe_ctx->stream->signal);2343		}2344	}2345 2346	if (!pipe_ctx->stream->sink->edid_caps.panel_patch.skip_avmute) {2347		if (dc_is_hdmi_signal(pipe_ctx->stream->signal))2348			set_avmute(pipe_ctx, true);2349	}2350 2351	dc->hwss.disable_audio_stream(pipe_ctx);2352 2353	update_psp_stream_config(pipe_ctx, true);2354	dc->hwss.blank_stream(pipe_ctx);2355 2356	if (pipe_ctx->stream->link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA)2357		deallocate_usb4_bandwidth(pipe_ctx->stream);2358 2359	if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)2360		deallocate_mst_payload(pipe_ctx);2361	else if (dc_is_dp_sst_signal(pipe_ctx->stream->signal) &&2362			dp_is_128b_132b_signal(pipe_ctx))2363		update_sst_payload(pipe_ctx, false);2364 2365	if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) {2366		struct ext_hdmi_settings settings = {0};2367		enum engine_id eng_id = pipe_ctx->stream_res.stream_enc->id;2368 2369		unsigned short masked_chip_caps = link->chip_caps &2370				EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK;2371		//Need to inform that sink is going to use legacy HDMI mode.2372		write_scdc_data(2373			link->ddc,2374			165000,//vbios only handles 165Mhz.2375			false);2376		if (masked_chip_caps == EXT_DISPLAY_PATH_CAPS__HDMI20_TISN65DP159RSBT) {2377			/* DP159, Retimer settings */2378			if (get_ext_hdmi_settings(pipe_ctx, eng_id, &settings))2379				write_i2c_retimer_setting(pipe_ctx,2380						false, false, &settings);2381			else2382				write_i2c_default_retimer_setting(pipe_ctx,2383						false, false);2384		} else if (masked_chip_caps == EXT_DISPLAY_PATH_CAPS__HDMI20_PI3EQX1204) {2385			/* PI3EQX1204, Redriver settings */2386			write_i2c_redriver_setting(pipe_ctx, false);2387		}2388	}2389 2390	if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT &&2391			!dp_is_128b_132b_signal(pipe_ctx)) {2392 2393		/* In DP1.x SST mode, our encoder will go to TPS12394		 * when link is on but stream is off.2395		 * Disabling link before stream will avoid exposing TPS1 pattern2396		 * during the disable sequence as it will confuse some receivers2397		 * state machine.2398		 * In DP2 or MST mode, our encoder will stay video active2399		 */2400		disable_link(pipe_ctx->stream->link, &pipe_ctx->link_res, pipe_ctx->stream->signal);2401		dc->hwss.disable_stream(pipe_ctx);2402	} else {2403		dc->hwss.disable_stream(pipe_ctx);2404		disable_link(pipe_ctx->stream->link, &pipe_ctx->link_res, pipe_ctx->stream->signal);2405	}2406	edp_set_panel_assr(link, pipe_ctx, &panel_mode_dp, false);2407 2408	if (pipe_ctx->stream->timing.flags.DSC) {2409		if (dc_is_dp_signal(pipe_ctx->stream->signal))2410			link_set_dsc_enable(pipe_ctx, false);2411	}2412	if (dp_is_128b_132b_signal(pipe_ctx)) {2413		if (pipe_ctx->stream_res.tg->funcs->set_out_mux)2414			pipe_ctx->stream_res.tg->funcs->set_out_mux(pipe_ctx->stream_res.tg, OUT_MUX_DIO);2415	}2416 2417	if (vpg && vpg->funcs->vpg_powerdown)2418		vpg->funcs->vpg_powerdown(vpg);2419 2420	/* for psp not exist case */2421	if (link->connector_signal == SIGNAL_TYPE_EDP && dc->debug.psp_disabled_wa) {2422		/* reset internal save state to default since eDP is  off */2423		enum dp_panel_mode panel_mode = dp_get_panel_mode(pipe_ctx->stream->link);2424		/* since current psp not loaded, we need to reset it to default*/2425		link->panel_mode = panel_mode;2426	}2427}2428 2429void link_set_dpms_on(2430		struct dc_state *state,2431		struct pipe_ctx *pipe_ctx)2432{2433	struct dc *dc = pipe_ctx->stream->ctx->dc;2434	struct dc_stream_state *stream = pipe_ctx->stream;2435	struct dc_link *link = stream->sink->link;2436	enum dc_status status;2437	struct link_encoder *link_enc;2438	enum otg_out_mux_dest otg_out_dest = OUT_MUX_DIO;2439	struct vpg *vpg = pipe_ctx->stream_res.stream_enc->vpg;2440	const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);2441	bool apply_edp_fast_boot_optimization =2442		pipe_ctx->stream->apply_edp_fast_boot_optimization;2443 2444	DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);2445 2446	ASSERT(is_master_pipe_for_link(link, pipe_ctx));2447 2448	if (dp_is_128b_132b_signal(pipe_ctx))2449		vpg = pipe_ctx->stream_res.hpo_dp_stream_enc->vpg;2450	if (dc_is_virtual_signal(pipe_ctx->stream->signal))2451		return;2452 2453	if (pipe_ctx->stream->sink) {2454		if (pipe_ctx->stream->sink->sink_signal != SIGNAL_TYPE_VIRTUAL &&2455			pipe_ctx->stream->sink->sink_signal != SIGNAL_TYPE_NONE) {2456			DC_LOG_DC("%s pipe_ctx dispname=%s signal=%x\n", __func__,2457			pipe_ctx->stream->sink->edid_caps.display_name,2458			pipe_ctx->stream->signal);2459		}2460	}2461 2462	link_enc = link_enc_cfg_get_link_enc(link);2463	ASSERT(link_enc);2464 2465	if (!dc_is_virtual_signal(pipe_ctx->stream->signal)2466			&& !dp_is_128b_132b_signal(pipe_ctx)) {2467		if (link_enc)2468			link_enc->funcs->setup(2469				link_enc,2470				pipe_ctx->stream->signal);2471	}2472 2473	pipe_ctx->stream->link->link_state_valid = true;2474 2475	if (pipe_ctx->stream_res.tg->funcs->set_out_mux) {2476		if (dp_is_128b_132b_signal(pipe_ctx))2477			otg_out_dest = OUT_MUX_HPO_DP;2478		else2479			otg_out_dest = OUT_MUX_DIO;2480		pipe_ctx->stream_res.tg->funcs->set_out_mux(pipe_ctx->stream_res.tg, otg_out_dest);2481	}2482 2483	link_hwss->setup_stream_attribute(pipe_ctx);2484 2485	pipe_ctx->stream->apply_edp_fast_boot_optimization = false;2486 2487	// Enable VPG before building infoframe2488	if (vpg && vpg->funcs->vpg_poweron)2489		vpg->funcs->vpg_poweron(vpg);2490 2491	resource_build_info_frame(pipe_ctx);2492	dc->hwss.update_info_frame(pipe_ctx);2493 2494	if (dc_is_dp_signal(pipe_ctx->stream->signal))2495		dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_UPDATE_INFO_FRAME);2496 2497	/* Do not touch link on seamless boot optimization. */2498	if (pipe_ctx->stream->apply_seamless_boot_optimization) {2499		pipe_ctx->stream->dpms_off = false;2500 2501		/* Still enable stream features & audio on seamless boot for DP external displays */2502		if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT) {2503			enable_stream_features(pipe_ctx);2504			dc->hwss.enable_audio_stream(pipe_ctx);2505		}2506 2507		update_psp_stream_config(pipe_ctx, false);2508		return;2509	}2510 2511	/* eDP lit up by bios already, no need to enable again. */2512	if (pipe_ctx->stream->signal == SIGNAL_TYPE_EDP &&2513				apply_edp_fast_boot_optimization &&2514				!pipe_ctx->stream->timing.flags.DSC &&2515				!pipe_ctx->next_odm_pipe) {2516		pipe_ctx->stream->dpms_off = false;2517		update_psp_stream_config(pipe_ctx, false);2518		return;2519	}2520 2521	if (pipe_ctx->stream->dpms_off)2522		return;2523 2524	/* Have to setup DSC before DIG FE and BE are connected (which happens before the2525	 * link training). This is to make sure the bandwidth sent to DIG BE won't be2526	 * bigger than what the link and/or DIG BE can handle. VBID[6]/CompressedStream_flag2527	 * will be automatically set at a later time when the video is enabled2528	 * (DP_VID_STREAM_EN = 1).2529	 */2530	if (pipe_ctx->stream->timing.flags.DSC) {2531		if (dc_is_dp_signal(pipe_ctx->stream->signal) ||2532		    dc_is_virtual_signal(pipe_ctx->stream->signal))2533			link_set_dsc_enable(pipe_ctx, true);2534	}2535 2536	status = enable_link(state, pipe_ctx);2537 2538	if (status != DC_OK) {2539		DC_LOG_WARNING("enabling link %u failed: %d\n",2540		pipe_ctx->stream->link->link_index,2541		status);2542 2543		/* Abort stream enable *unless* the failure was due to2544		 * DP link training - some DP monitors will recover and2545		 * show the stream anyway. But MST displays can't proceed2546		 * without link training.2547		 */2548		if (status != DC_FAIL_DP_LINK_TRAINING ||2549				pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {2550			if (false == stream->link->link_status.link_active)2551				disable_link(stream->link, &pipe_ctx->link_res,2552						pipe_ctx->stream->signal);2553			BREAK_TO_DEBUGGER();2554			return;2555		}2556	}2557 2558	/* turn off otg test pattern if enable */2559	if (pipe_ctx->stream_res.tg->funcs->set_test_pattern)2560		pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg,2561				CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,2562				COLOR_DEPTH_UNDEFINED);2563 2564	/* This second call is needed to reconfigure the DIG2565	 * as a workaround for the incorrect value being applied2566	 * from transmitter control.2567	 */2568	if (!(dc_is_virtual_signal(pipe_ctx->stream->signal) ||2569			dp_is_128b_132b_signal(pipe_ctx))) {2570 2571			if (link_enc)2572				link_enc->funcs->setup(2573					link_enc,2574					pipe_ctx->stream->signal);2575 2576		}2577 2578	dc->hwss.enable_stream(pipe_ctx);2579 2580	/* Set DPS PPS SDP (AKA "info frames") */2581	if (pipe_ctx->stream->timing.flags.DSC) {2582		if (dc_is_dp_signal(pipe_ctx->stream->signal) ||2583				dc_is_virtual_signal(pipe_ctx->stream->signal)) {2584			dp_set_dsc_on_rx(pipe_ctx, true);2585			link_set_dsc_pps_packet(pipe_ctx, true, true);2586		}2587	}2588 2589	if (pipe_ctx->stream->link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA)2590		allocate_usb4_bandwidth(pipe_ctx->stream);2591 2592	if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)2593		allocate_mst_payload(pipe_ctx);2594	else if (dc_is_dp_sst_signal(pipe_ctx->stream->signal) &&2595			dp_is_128b_132b_signal(pipe_ctx))2596		update_sst_payload(pipe_ctx, true);2597 2598	dc->hwss.unblank_stream(pipe_ctx,2599		&pipe_ctx->stream->link->cur_link_settings);2600 2601	if (stream->sink_patches.delay_ignore_msa > 0)2602		msleep(stream->sink_patches.delay_ignore_msa);2603 2604	if (dc_is_dp_signal(pipe_ctx->stream->signal))2605		enable_stream_features(pipe_ctx);2606	update_psp_stream_config(pipe_ctx, false);2607 2608	dc->hwss.enable_audio_stream(pipe_ctx);2609 2610	if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) {2611		set_avmute(pipe_ctx, false);2612	}2613}2614