File Index
Files and directories
Sign in
FILE

link_dp_cts.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c C
   1/*
   2 * Copyright 2022 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#include "link_dp_cts.h"
  26#include "link/link_resource.h"
  27#include "link/protocols/link_dpcd.h"
  28#include "link/protocols/link_dp_training.h"
  29#include "link/protocols/link_dp_phy.h"
  30#include "link/protocols/link_dp_training_fixed_vs_pe_retimer.h"
  31#include "link/protocols/link_dp_capability.h"
  32#include "link/link_dpms.h"
  33#include "resource.h"
  34#include "dm_helpers.h"
  35#include "dc_dmub_srv.h"
  36#include "dce/dmub_hw_lock_mgr.h"
  37#include "clk_mgr.h"
  38
  39#define DC_LOGGER \
  40	link->ctx->logger
  41
  42static enum dc_link_rate get_link_rate_from_test_link_rate(uint8_t test_rate)
  43{
  44	switch (test_rate) {
  45	case DP_TEST_LINK_RATE_RBR:
  46		return LINK_RATE_LOW;
  47	case DP_TEST_LINK_RATE_HBR:
  48		return LINK_RATE_HIGH;
  49	case DP_TEST_LINK_RATE_HBR2:
  50		return LINK_RATE_HIGH2;
  51	case DP_TEST_LINK_RATE_HBR3:
  52		return LINK_RATE_HIGH3;
  53	case DP_TEST_LINK_RATE_UHBR10:
  54		return LINK_RATE_UHBR10;
  55	case DP_TEST_LINK_RATE_UHBR20:
  56		return LINK_RATE_UHBR20;
  57	case DP_TEST_LINK_RATE_UHBR13_5_LEGACY:
  58	case DP_TEST_LINK_RATE_UHBR13_5:
  59		return LINK_RATE_UHBR13_5;
  60	default:
  61		return LINK_RATE_UNKNOWN;
  62	}
  63}
  64
  65static void dp_retrain_link_dp_test(struct dc_link *link,
  66			struct dc_link_settings *link_setting,
  67			bool skip_video_pattern)
  68{
  69	struct pipe_ctx *pipes[MAX_PIPES];
  70	struct dc_state *state = link->dc->current_state;
  71	struct dc_stream_update stream_update = { 0 };
  72	bool dpms_off = false;
  73	bool needs_divider_update = false;
  74	bool was_hpo_acquired = resource_is_hpo_acquired(link->dc->current_state);
  75	bool is_hpo_acquired;
  76	uint8_t count;
  77	int i;
  78	struct audio_output audio_output[MAX_PIPES];
  79	struct dc_stream_state *streams_on_link[MAX_PIPES];
  80	int num_streams_on_link = 0;
  81	struct dc *dc = (struct dc *)link->dc;
  82
  83	needs_divider_update = (link->dc->link_srv->dp_get_encoding_format(link_setting) !=
  84	link->dc->link_srv->dp_get_encoding_format((const struct dc_link_settings *) &link->cur_link_settings));
  85
  86	udelay(100);
  87
  88	link_get_master_pipes_with_dpms_on(link, state, &count, pipes);
  89
  90	for (i = 0; i < count; i++) {
  91		link_set_dpms_off(pipes[i]);
  92		pipes[i]->link_config.dp_link_settings = *link_setting;
  93		update_dp_encoder_resources_for_test_harness(
  94				link->dc,
  95				state,
  96				pipes[i]);
  97
  98		// Disable OTG and re-enable after updating clocks
  99		pipes[i]->stream_res.tg->funcs->disable_crtc(pipes[i]->stream_res.tg);
 100	}
 101
 102	if (needs_divider_update && link->dc->res_pool->funcs->update_dc_state_for_encoder_switch) {
 103		link->dc->res_pool->funcs->update_dc_state_for_encoder_switch(link,
 104				link_setting, count,
 105				*pipes, &audio_output[0]);
 106		for (i = 0; i < count; i++) {
 107			pipes[i]->clock_source->funcs->program_pix_clk(
 108					pipes[i]->clock_source,
 109					&pipes[i]->stream_res.pix_clk_params,
 110					link->dc->link_srv->dp_get_encoding_format(&pipes[i]->link_config.dp_link_settings),
 111					&pipes[i]->pll_settings);
 112
 113			if (pipes[i]->stream_res.audio != NULL) {
 114				const struct link_hwss *link_hwss = get_link_hwss(
 115					link, &pipes[i]->link_res);
 116
 117				link_hwss->setup_audio_output(pipes[i], &audio_output[i],
 118						pipes[i]->stream_res.audio->inst);
 119
 120				pipes[i]->stream_res.audio->funcs->az_configure(
 121						pipes[i]->stream_res.audio,
 122						pipes[i]->stream->signal,
 123						&audio_output[i].crtc_info,
 124						&pipes[i]->stream->audio_info,
 125						&audio_output[i].dp_link_info);
 126
 127				if (link->dc->config.disable_hbr_audio_dp2 &&
 128						pipes[i]->stream_res.audio->funcs->az_disable_hbr_audio &&
 129						link->dc->link_srv->dp_is_128b_132b_signal(pipes[i]))
 130					pipes[i]->stream_res.audio->funcs->az_disable_hbr_audio(pipes[i]->stream_res.audio);
 131			}
 132		}
 133	}
 134
 135	// Toggle on HPO I/O if necessary
 136	is_hpo_acquired = resource_is_hpo_acquired(state);
 137	if (was_hpo_acquired != is_hpo_acquired && link->dc->hwss.setup_hpo_hw_control)
 138		link->dc->hwss.setup_hpo_hw_control(link->dc->hwseq, is_hpo_acquired);
 139
 140	for (i = 0; i < count; i++)
 141		pipes[i]->stream_res.tg->funcs->enable_crtc(pipes[i]->stream_res.tg);
 142
 143	// Set DPMS on with stream update
 144	// Cache all streams on current link since dc_update_planes_and_stream might kill current_state
 145	for (i = 0; i < MAX_PIPES; i++) {
 146		if (state->streams[i] && state->streams[i]->link && state->streams[i]->link == link)
 147			streams_on_link[num_streams_on_link++] = state->streams[i];
 148	}
 149
 150	for (i = 0; i < num_streams_on_link; i++) {
 151		if (streams_on_link[i] && streams_on_link[i]->link && streams_on_link[i]->link == link) {
 152			stream_update.stream = streams_on_link[i];
 153			stream_update.dpms_off = &dpms_off;
 154			dc_update_planes_and_stream(dc, NULL, 0, streams_on_link[i], &stream_update);
 155		}
 156	}
 157}
 158
 159static void dp_test_send_link_training(struct dc_link *link)
 160{
 161	struct dc_link_settings link_settings = {0};
 162	uint8_t test_rate = 0;
 163
 164	core_link_read_dpcd(
 165			link,
 166			DP_TEST_LANE_COUNT,
 167			(unsigned char *)(&link_settings.lane_count),
 168			1);
 169	core_link_read_dpcd(
 170			link,
 171			DP_TEST_LINK_RATE,
 172			&test_rate,
 173			1);
 174	link_settings.link_rate = get_link_rate_from_test_link_rate(test_rate);
 175
 176	if (link_settings.link_rate == LINK_RATE_UNKNOWN) {
 177		DC_LOG_ERROR("%s: Invalid test link rate.", __func__);
 178		ASSERT(0);
 179	}
 180
 181	/* Set preferred link settings */
 182	link->verified_link_cap.lane_count = link_settings.lane_count;
 183	link->verified_link_cap.link_rate = link_settings.link_rate;
 184
 185	dp_retrain_link_dp_test(link, &link_settings, false);
 186}
 187
 188static void dp_test_get_audio_test_data(struct dc_link *link, bool disable_video)
 189{
 190	union audio_test_mode            dpcd_test_mode = {0};
 191	struct audio_test_pattern_type   dpcd_pattern_type = {0};
 192	union audio_test_pattern_period  dpcd_pattern_period[AUDIO_CHANNELS_COUNT] = {0};
 193	enum dp_test_pattern test_pattern = DP_TEST_PATTERN_AUDIO_OPERATOR_DEFINED;
 194
 195	struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
 196	struct pipe_ctx *pipe_ctx = &pipes[0];
 197	unsigned int channel_count;
 198	unsigned int channel = 0;
 199	unsigned int modes = 0;
 200	unsigned int sampling_rate_in_hz = 0;
 201
 202	// get audio test mode and test pattern parameters
 203	core_link_read_dpcd(
 204		link,
 205		DP_TEST_AUDIO_MODE,
 206		&dpcd_test_mode.raw,
 207		sizeof(dpcd_test_mode));
 208
 209	core_link_read_dpcd(
 210		link,
 211		DP_TEST_AUDIO_PATTERN_TYPE,
 212		&dpcd_pattern_type.value,
 213		sizeof(dpcd_pattern_type));
 214
 215	channel_count = min(dpcd_test_mode.bits.channel_count + 1, AUDIO_CHANNELS_COUNT);
 216
 217	// read pattern periods for requested channels when sawTooth pattern is requested
 218	if (dpcd_pattern_type.value == AUDIO_TEST_PATTERN_SAWTOOTH ||
 219			dpcd_pattern_type.value == AUDIO_TEST_PATTERN_OPERATOR_DEFINED) {
 220
 221		test_pattern = (dpcd_pattern_type.value == AUDIO_TEST_PATTERN_SAWTOOTH) ?
 222				DP_TEST_PATTERN_AUDIO_SAWTOOTH : DP_TEST_PATTERN_AUDIO_OPERATOR_DEFINED;
 223		// read period for each channel
 224		for (channel = 0; channel < channel_count; channel++) {
 225			core_link_read_dpcd(
 226							link,
 227							DP_TEST_AUDIO_PERIOD_CH1 + channel,
 228							&dpcd_pattern_period[channel].raw,
 229							sizeof(dpcd_pattern_period[channel]));
 230		}
 231	}
 232
 233	// translate sampling rate
 234	switch (dpcd_test_mode.bits.sampling_rate) {
 235	case AUDIO_SAMPLING_RATE_32KHZ:
 236		sampling_rate_in_hz = 32000;
 237		break;
 238	case AUDIO_SAMPLING_RATE_44_1KHZ:
 239		sampling_rate_in_hz = 44100;
 240		break;
 241	case AUDIO_SAMPLING_RATE_48KHZ:
 242		sampling_rate_in_hz = 48000;
 243		break;
 244	case AUDIO_SAMPLING_RATE_88_2KHZ:
 245		sampling_rate_in_hz = 88200;
 246		break;
 247	case AUDIO_SAMPLING_RATE_96KHZ:
 248		sampling_rate_in_hz = 96000;
 249		break;
 250	case AUDIO_SAMPLING_RATE_176_4KHZ:
 251		sampling_rate_in_hz = 176400;
 252		break;
 253	case AUDIO_SAMPLING_RATE_192KHZ:
 254		sampling_rate_in_hz = 192000;
 255		break;
 256	default:
 257		sampling_rate_in_hz = 0;
 258		break;
 259	}
 260
 261	link->audio_test_data.flags.test_requested = 1;
 262	link->audio_test_data.flags.disable_video = disable_video;
 263	link->audio_test_data.sampling_rate = sampling_rate_in_hz;
 264	link->audio_test_data.channel_count = channel_count;
 265	link->audio_test_data.pattern_type = test_pattern;
 266
 267	if (test_pattern == DP_TEST_PATTERN_AUDIO_SAWTOOTH) {
 268		for (modes = 0; modes < pipe_ctx->stream->audio_info.mode_count; modes++) {
 269			link->audio_test_data.pattern_period[modes] = dpcd_pattern_period[modes].bits.pattern_period;
 270		}
 271	}
 272}
 273
 274/* TODO Raven hbr2 compliance eye output is unstable
 275 * (toggling on and off) with debugger break
 276 * This caueses intermittent PHY automation failure
 277 * Need to look into the root cause */
 278static void dp_test_send_phy_test_pattern(struct dc_link *link)
 279{
 280	union phy_test_pattern dpcd_test_pattern;
 281	union lane_adjust dpcd_lane_adjustment[2];
 282	unsigned char dpcd_post_cursor_2_adjustment = 0;
 283	unsigned char test_pattern_buffer[
 284			(DP_TEST_264BIT_CUSTOM_PATTERN_263_256 -
 285			DP_TEST_264BIT_CUSTOM_PATTERN_7_0)+1] = {0};
 286	unsigned int test_pattern_size = 0;
 287	enum dp_test_pattern test_pattern;
 288	union lane_adjust dpcd_lane_adjust;
 289	unsigned int lane;
 290	struct link_training_settings link_training_settings;
 291	unsigned char no_preshoot = 0;
 292	unsigned char no_deemphasis = 0;
 293
 294	dpcd_test_pattern.raw = 0;
 295	memset(dpcd_lane_adjustment, 0, sizeof(dpcd_lane_adjustment));
 296	memset(&link_training_settings, 0, sizeof(link_training_settings));
 297
 298	/* get phy test pattern and pattern parameters from DP receiver */
 299	core_link_read_dpcd(
 300			link,
 301			DP_PHY_TEST_PATTERN,
 302			&dpcd_test_pattern.raw,
 303			sizeof(dpcd_test_pattern));
 304	core_link_read_dpcd(
 305			link,
 306			DP_ADJUST_REQUEST_LANE0_1,
 307			&dpcd_lane_adjustment[0].raw,
 308			sizeof(dpcd_lane_adjustment));
 309
 310	/* prepare link training settings */
 311	link_training_settings.link_settings = link->cur_link_settings;
 312
 313	link_training_settings.lttpr_mode = dp_decide_lttpr_mode(link, &link->cur_link_settings);
 314
 315	if (((link->chip_caps & AMD_EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK) == AMD_EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
 316			link_training_settings.lttpr_mode == LTTPR_MODE_TRANSPARENT)
 317		dp_fixed_vs_pe_read_lane_adjust(
 318				link,
 319				link_training_settings.dpcd_lane_settings);
 320
 321	/*get post cursor 2 parameters
 322	 * For DP 1.1a or eariler, this DPCD register's value is 0
 323	 * For DP 1.2 or later:
 324	 * Bits 1:0 = POST_CURSOR2_LANE0; Bits 3:2 = POST_CURSOR2_LANE1
 325	 * Bits 5:4 = POST_CURSOR2_LANE2; Bits 7:6 = POST_CURSOR2_LANE3
 326	 */
 327	core_link_read_dpcd(
 328			link,
 329			DP_ADJUST_REQUEST_POST_CURSOR2,
 330			&dpcd_post_cursor_2_adjustment,
 331			sizeof(dpcd_post_cursor_2_adjustment));
 332
 333	/* translate request */
 334	switch (dpcd_test_pattern.bits.PATTERN) {
 335	case PHY_TEST_PATTERN_D10_2:
 336		test_pattern = DP_TEST_PATTERN_D102;
 337		break;
 338	case PHY_TEST_PATTERN_SYMBOL_ERROR:
 339		test_pattern = DP_TEST_PATTERN_SYMBOL_ERROR;
 340		break;
 341	case PHY_TEST_PATTERN_PRBS7:
 342		test_pattern = DP_TEST_PATTERN_PRBS7;
 343		break;
 344	case PHY_TEST_PATTERN_80BIT_CUSTOM:
 345		test_pattern = DP_TEST_PATTERN_80BIT_CUSTOM;
 346		break;
 347	case PHY_TEST_PATTERN_CP2520_1:
 348		/* CP2520 pattern is unstable, temporarily use TPS4 instead */
 349		test_pattern = (link->dc->caps.force_dp_tps4_for_cp2520 == 1) ?
 350				DP_TEST_PATTERN_TRAINING_PATTERN4 :
 351				DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE;
 352		break;
 353	case PHY_TEST_PATTERN_CP2520_2:
 354		/* CP2520 pattern is unstable, temporarily use TPS4 instead */
 355		test_pattern = (link->dc->caps.force_dp_tps4_for_cp2520 == 1) ?
 356				DP_TEST_PATTERN_TRAINING_PATTERN4 :
 357				DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE;
 358		break;
 359	case PHY_TEST_PATTERN_CP2520_3:
 360		test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4;
 361		break;
 362	case PHY_TEST_PATTERN_128b_132b_TPS1:
 363		test_pattern = DP_TEST_PATTERN_128b_132b_TPS1;
 364		break;
 365	case PHY_TEST_PATTERN_128b_132b_TPS2:
 366		test_pattern = DP_TEST_PATTERN_128b_132b_TPS2;
 367		break;
 368	case PHY_TEST_PATTERN_PRBS9:
 369		test_pattern = DP_TEST_PATTERN_PRBS9;
 370		break;
 371	case PHY_TEST_PATTERN_PRBS11:
 372		test_pattern = DP_TEST_PATTERN_PRBS11;
 373		break;
 374	case PHY_TEST_PATTERN_PRBS15:
 375		test_pattern = DP_TEST_PATTERN_PRBS15;
 376		break;
 377	case PHY_TEST_PATTERN_PRBS23:
 378		test_pattern = DP_TEST_PATTERN_PRBS23;
 379		break;
 380	case PHY_TEST_PATTERN_PRBS31:
 381		test_pattern = DP_TEST_PATTERN_PRBS31;
 382		break;
 383	case PHY_TEST_PATTERN_264BIT_CUSTOM:
 384		test_pattern = DP_TEST_PATTERN_264BIT_CUSTOM;
 385		break;
 386	case PHY_TEST_PATTERN_SQUARE:
 387		test_pattern = DP_TEST_PATTERN_SQUARE;
 388		break;
 389	case PHY_TEST_PATTERN_SQUARE_PRESHOOT_DISABLED:
 390		test_pattern = DP_TEST_PATTERN_SQUARE_PRESHOOT_DISABLED;
 391		no_preshoot = 1;
 392		break;
 393	case PHY_TEST_PATTERN_SQUARE_DEEMPHASIS_DISABLED:
 394		test_pattern = DP_TEST_PATTERN_SQUARE_DEEMPHASIS_DISABLED;
 395		no_deemphasis = 1;
 396		break;
 397	case PHY_TEST_PATTERN_SQUARE_PRESHOOT_DEEMPHASIS_DISABLED:
 398		test_pattern = DP_TEST_PATTERN_SQUARE_PRESHOOT_DEEMPHASIS_DISABLED;
 399		no_preshoot = 1;
 400		no_deemphasis = 1;
 401		break;
 402	default:
 403		test_pattern = DP_TEST_PATTERN_VIDEO_MODE;
 404	break;
 405	}
 406
 407	if (test_pattern == DP_TEST_PATTERN_80BIT_CUSTOM) {
 408		test_pattern_size = (DP_TEST_80BIT_CUSTOM_PATTERN_79_72 -
 409				DP_TEST_80BIT_CUSTOM_PATTERN_7_0) + 1;
 410		core_link_read_dpcd(
 411				link,
 412				DP_TEST_80BIT_CUSTOM_PATTERN_7_0,
 413				test_pattern_buffer,
 414				test_pattern_size);
 415	}
 416
 417	if (IS_DP_PHY_SQUARE_PATTERN(test_pattern)) {
 418		test_pattern_size = 1; // Square pattern data is 1 byte (DP spec)
 419		core_link_read_dpcd(
 420				link,
 421				DP_PHY_SQUARE_PATTERN,
 422				test_pattern_buffer,
 423				test_pattern_size);
 424	}
 425
 426	if (test_pattern == DP_TEST_PATTERN_264BIT_CUSTOM) {
 427		test_pattern_size = (DP_TEST_264BIT_CUSTOM_PATTERN_263_256-
 428				DP_TEST_264BIT_CUSTOM_PATTERN_7_0) + 1;
 429		core_link_read_dpcd(
 430				link,
 431				DP_TEST_264BIT_CUSTOM_PATTERN_7_0,
 432				test_pattern_buffer,
 433				test_pattern_size);
 434	}
 435
 436	for (lane = 0; lane <
 437		(unsigned int)(link->cur_link_settings.lane_count);
 438		lane++) {
 439		dpcd_lane_adjust.raw =
 440			dp_get_nibble_at_index(&dpcd_lane_adjustment[0].raw, lane);
 441		if (link_dp_get_encoding_format(&link->cur_link_settings) ==
 442				DP_8b_10b_ENCODING) {
 443			link_training_settings.hw_lane_settings[lane].VOLTAGE_SWING =
 444				(enum dc_voltage_swing)
 445				(dpcd_lane_adjust.bits.VOLTAGE_SWING_LANE);
 446			link_training_settings.hw_lane_settings[lane].PRE_EMPHASIS =
 447				(enum dc_pre_emphasis)
 448				(dpcd_lane_adjust.bits.PRE_EMPHASIS_LANE);
 449			link_training_settings.hw_lane_settings[lane].POST_CURSOR2 =
 450				(enum dc_post_cursor2)
 451				((dpcd_post_cursor_2_adjustment >> (lane * 2)) & 0x03);
 452		} else if (link_dp_get_encoding_format(&link->cur_link_settings) ==
 453				DP_128b_132b_ENCODING) {
 454			link_training_settings.hw_lane_settings[lane].FFE_PRESET.settings.level =
 455					dpcd_lane_adjust.tx_ffe.PRESET_VALUE;
 456			link_training_settings.hw_lane_settings[lane].FFE_PRESET.settings.no_preshoot = no_preshoot;
 457			link_training_settings.hw_lane_settings[lane].FFE_PRESET.settings.no_deemphasis = no_deemphasis;
 458		}
 459	}
 460
 461	dp_hw_to_dpcd_lane_settings(&link_training_settings,
 462			link_training_settings.hw_lane_settings,
 463			link_training_settings.dpcd_lane_settings);
 464	/*Usage: Measure DP physical lane signal
 465	 * by DP SI test equipment automatically.
 466	 * PHY test pattern request is generated by equipment via HPD interrupt.
 467	 * HPD needs to be active all the time. HPD should be active
 468	 * all the time. Do not touch it.
 469	 * forward request to DS
 470	 */
 471	dp_set_test_pattern(
 472		link,
 473		test_pattern,
 474		DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED,
 475		&link_training_settings,
 476		test_pattern_buffer,
 477		test_pattern_size);
 478}
 479
 480static void set_crtc_test_pattern(struct dc_link *link,
 481				struct pipe_ctx *pipe_ctx,
 482				enum dp_test_pattern test_pattern,
 483				enum dp_test_pattern_color_space test_pattern_color_space)
 484{
 485	enum controller_dp_test_pattern controller_test_pattern;
 486	enum dc_color_depth color_depth = pipe_ctx->
 487		stream->timing.display_color_depth;
 488	struct bit_depth_reduction_params params;
 489	struct output_pixel_processor *opp = pipe_ctx->stream_res.opp;
 490	struct pipe_ctx *odm_pipe;
 491	struct test_pattern_params *tp_params;
 492
 493	memset(&params, 0, sizeof(params));
 494
 495	resource_build_test_pattern_params(&link->dc->current_state->res_ctx,
 496			pipe_ctx);
 497	controller_test_pattern = pipe_ctx->stream_res.test_pattern_params.test_pattern;
 498
 499	switch (test_pattern) {
 500	case DP_TEST_PATTERN_COLOR_SQUARES:
 501	case DP_TEST_PATTERN_COLOR_SQUARES_CEA:
 502	case DP_TEST_PATTERN_VERTICAL_BARS:
 503	case DP_TEST_PATTERN_HORIZONTAL_BARS:
 504	case DP_TEST_PATTERN_COLOR_RAMP:
 505	{
 506		/* disable bit depth reduction */
 507		pipe_ctx->stream->bit_depth_params = params;
 508		if (pipe_ctx->stream_res.tg->funcs->set_test_pattern) {
 509			opp->funcs->opp_program_bit_depth_reduction(opp, &params);
 510			pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg,
 511				controller_test_pattern, color_depth);
 512		} else if (link->dc->hwss.set_disp_pattern_generator) {
 513			enum controller_dp_color_space controller_color_space;
 514			struct output_pixel_processor *odm_opp;
 515
 516			controller_color_space = pipe_ctx->stream_res.test_pattern_params.color_space;
 517
 518			if (controller_color_space == CONTROLLER_DP_COLOR_SPACE_UDEFINED) {
 519				DC_LOG_ERROR("%s: Color space must be defined for test pattern", __func__);
 520				ASSERT(0);
 521			}
 522
 523			odm_pipe = pipe_ctx;
 524			while (odm_pipe) {
 525				tp_params = &odm_pipe->stream_res.test_pattern_params;
 526				odm_opp = odm_pipe->stream_res.opp;
 527				odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, &params);
 528				link->dc->hwss.set_disp_pattern_generator(link->dc,
 529						odm_pipe,
 530						tp_params->test_pattern,
 531						tp_params->color_space,
 532						tp_params->color_depth,
 533						NULL,
 534						tp_params->width,
 535						tp_params->height,
 536						tp_params->offset);
 537				odm_pipe = odm_pipe->next_odm_pipe;
 538			}
 539		}
 540	}
 541	break;
 542	case DP_TEST_PATTERN_VIDEO_MODE:
 543	{
 544		/* restore bitdepth reduction */
 545		resource_build_bit_depth_reduction_params(pipe_ctx->stream, &params);
 546		pipe_ctx->stream->bit_depth_params = params;
 547		if (pipe_ctx->stream_res.tg->funcs->set_test_pattern) {
 548			opp->funcs->opp_program_bit_depth_reduction(opp, &params);
 549			pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg,
 550					CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
 551					color_depth);
 552		} else if (link->dc->hwss.set_disp_pattern_generator) {
 553			struct output_pixel_processor *odm_opp;
 554
 555			odm_pipe = pipe_ctx;
 556			while (odm_pipe) {
 557				tp_params = &odm_pipe->stream_res.test_pattern_params;
 558				odm_opp = odm_pipe->stream_res.opp;
 559				odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, &params);
 560				link->dc->hwss.set_disp_pattern_generator(link->dc,
 561						odm_pipe,
 562						tp_params->test_pattern,
 563						tp_params->color_space,
 564						tp_params->color_depth,
 565						NULL,
 566						tp_params->width,
 567						tp_params->height,
 568						tp_params->offset);
 569				odm_pipe = odm_pipe->next_odm_pipe;
 570			}
 571		}
 572	}
 573	break;
 574
 575	default:
 576	break;
 577	}
 578}
 579
 580void dp_handle_automated_test(struct dc_link *link)
 581{
 582	union test_request test_request;
 583	union test_response test_response;
 584
 585	memset(&test_request, 0, sizeof(test_request));
 586	memset(&test_response, 0, sizeof(test_response));
 587
 588	core_link_read_dpcd(
 589		link,
 590		DP_TEST_REQUEST,
 591		&test_request.raw,
 592		sizeof(union test_request));
 593	if (test_request.bits.LINK_TRAINING) {
 594		/* ACK first to let DP RX test box monitor LT sequence */
 595		test_response.bits.ACK = 1;
 596		core_link_write_dpcd(
 597			link,
 598			DP_TEST_RESPONSE,
 599			&test_response.raw,
 600			sizeof(test_response));
 601		dp_test_send_link_training(link);
 602		/* no acknowledge request is needed again */
 603		test_response.bits.ACK = 0;
 604	}
 605	if (test_request.bits.LINK_TEST_PATTRN) {
 606		union test_misc dpcd_test_params;
 607		union link_test_pattern dpcd_test_pattern;
 608
 609		memset(&dpcd_test_pattern, 0, sizeof(dpcd_test_pattern));
 610		memset(&dpcd_test_params, 0, sizeof(dpcd_test_params));
 611
 612		/* get link test pattern and pattern parameters */
 613		core_link_read_dpcd(
 614				link,
 615				DP_TEST_PATTERN,
 616				&dpcd_test_pattern.raw,
 617				sizeof(dpcd_test_pattern));
 618		core_link_read_dpcd(
 619				link,
 620				DP_TEST_MISC0,
 621				&dpcd_test_params.raw,
 622				sizeof(dpcd_test_params));
 623		test_response.bits.ACK = dm_helpers_dp_handle_test_pattern_request(link->ctx, link,
 624				dpcd_test_pattern, dpcd_test_params) ? 1 : 0;
 625	}
 626
 627	if (test_request.bits.AUDIO_TEST_PATTERN) {
 628		dp_test_get_audio_test_data(link, test_request.bits.TEST_AUDIO_DISABLED_VIDEO);
 629		test_response.bits.ACK = 1;
 630	}
 631
 632	if (test_request.bits.PHY_TEST_PATTERN) {
 633		dp_test_send_phy_test_pattern(link);
 634		test_response.bits.ACK = 1;
 635	}
 636
 637	/* send request acknowledgment */
 638	if (test_response.bits.ACK)
 639		core_link_write_dpcd(
 640			link,
 641			DP_TEST_RESPONSE,
 642			&test_response.raw,
 643			sizeof(test_response));
 644}
 645
 646bool dp_set_test_pattern(
 647	struct dc_link *link,
 648	enum dp_test_pattern test_pattern,
 649	enum dp_test_pattern_color_space test_pattern_color_space,
 650	const struct link_training_settings *p_link_settings,
 651	const unsigned char *p_custom_pattern,
 652	unsigned int cust_pattern_size)
 653{
 654	const struct link_hwss *link_hwss;
 655	struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
 656	struct pipe_ctx *pipe_ctx = NULL;
 657	unsigned int lane;
 658	unsigned int i;
 659	unsigned char link_qual_pattern[LANE_COUNT_DP_MAX] = {0};
 660	union dpcd_training_pattern training_pattern;
 661	enum dpcd_phy_test_patterns pattern;
 662
 663	memset(&training_pattern, 0, sizeof(training_pattern));
 664
 665	for (i = 0; i < MAX_PIPES; i++) {
 666		if (pipes[i].stream == NULL)
 667			continue;
 668
 669		if (resource_is_pipe_type(&pipes[i], OTG_MASTER) &&
 670				pipes[i].stream->link == link) {
 671			pipe_ctx = &pipes[i];
 672			break;
 673		}
 674	}
 675
 676	if (pipe_ctx == NULL)
 677		return false;
 678
 679	link->pending_test_pattern = test_pattern;
 680
 681	/* Reset CRTC Test Pattern if it is currently running and request is VideoMode */
 682	if (link->test_pattern_enabled && test_pattern ==
 683			DP_TEST_PATTERN_VIDEO_MODE) {
 684		/* Set CRTC Test Pattern */
 685		set_crtc_test_pattern(link, pipe_ctx, test_pattern, test_pattern_color_space);
 686		dp_set_hw_test_pattern(link, &pipe_ctx->link_res, test_pattern,
 687				(uint8_t *)p_custom_pattern,
 688				(uint32_t)cust_pattern_size);
 689
 690		/* Unblank Stream */
 691		link->dc->hwss.unblank_stream(
 692			pipe_ctx,
 693			&link->verified_link_cap);
 694		/* TODO:m_pHwss->MuteAudioEndpoint
 695		 * (pPathMode->pDisplayPath, false);
 696		 */
 697
 698		/* Reset Test Pattern state */
 699		link->test_pattern_enabled = false;
 700		link->current_test_pattern = test_pattern;
 701		link->pending_test_pattern = DP_TEST_PATTERN_UNSUPPORTED;
 702
 703		return true;
 704	}
 705
 706	/* Check for PHY Test Patterns */
 707	if (IS_DP_PHY_PATTERN(test_pattern)) {
 708		/* Set DPCD Lane Settings before running test pattern */
 709		if (p_link_settings != NULL) {
 710			if (((link->chip_caps & AMD_EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK) == AMD_EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
 711					p_link_settings->lttpr_mode == LTTPR_MODE_TRANSPARENT) {
 712				dp_fixed_vs_pe_set_retimer_lane_settings(
 713						link,
 714						p_link_settings->dpcd_lane_settings,
 715						p_link_settings->link_settings.lane_count);
 716			} else {
 717				dp_set_hw_lane_settings(link, &pipe_ctx->link_res, p_link_settings, DPRX);
 718			}
 719			dpcd_set_lane_settings(link, p_link_settings, DPRX);
 720		}
 721
 722		/* Blank stream if running test pattern */
 723		if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) {
 724			/*TODO:
 725			 * m_pHwss->
 726			 * MuteAudioEndpoint(pPathMode->pDisplayPath, true);
 727			 */
 728			/* Blank stream */
 729			link->dc->hwss.blank_stream(pipe_ctx);
 730		}
 731
 732		dp_set_hw_test_pattern(link, &pipe_ctx->link_res, test_pattern,
 733				(uint8_t *)p_custom_pattern,
 734				(uint32_t)cust_pattern_size);
 735
 736		if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) {
 737			/* Set Test Pattern state */
 738			link->test_pattern_enabled = true;
 739			link->current_test_pattern = test_pattern;
 740			link->pending_test_pattern = DP_TEST_PATTERN_UNSUPPORTED;
 741			if (p_link_settings != NULL)
 742				dpcd_set_link_settings(link,
 743						p_link_settings);
 744		}
 745
 746		switch (test_pattern) {
 747		case DP_TEST_PATTERN_VIDEO_MODE:
 748			pattern = PHY_TEST_PATTERN_NONE;
 749			break;
 750		case DP_TEST_PATTERN_D102:
 751			pattern = PHY_TEST_PATTERN_D10_2;
 752			break;
 753		case DP_TEST_PATTERN_SYMBOL_ERROR:
 754			pattern = PHY_TEST_PATTERN_SYMBOL_ERROR;
 755			break;
 756		case DP_TEST_PATTERN_PRBS7:
 757			pattern = PHY_TEST_PATTERN_PRBS7;
 758			break;
 759		case DP_TEST_PATTERN_80BIT_CUSTOM:
 760			pattern = PHY_TEST_PATTERN_80BIT_CUSTOM;
 761			break;
 762		case DP_TEST_PATTERN_CP2520_1:
 763			pattern = PHY_TEST_PATTERN_CP2520_1;
 764			break;
 765		case DP_TEST_PATTERN_CP2520_2:
 766			pattern = PHY_TEST_PATTERN_CP2520_2;
 767			break;
 768		case DP_TEST_PATTERN_CP2520_3:
 769			pattern = PHY_TEST_PATTERN_CP2520_3;
 770			break;
 771		case DP_TEST_PATTERN_128b_132b_TPS1:
 772			pattern = PHY_TEST_PATTERN_128b_132b_TPS1;
 773			break;
 774		case DP_TEST_PATTERN_128b_132b_TPS2:
 775			pattern = PHY_TEST_PATTERN_128b_132b_TPS2;
 776			break;
 777		case DP_TEST_PATTERN_PRBS9:
 778			pattern = PHY_TEST_PATTERN_PRBS9;
 779			break;
 780		case DP_TEST_PATTERN_PRBS11:
 781			pattern = PHY_TEST_PATTERN_PRBS11;
 782			break;
 783		case DP_TEST_PATTERN_PRBS15:
 784			pattern = PHY_TEST_PATTERN_PRBS15;
 785			break;
 786		case DP_TEST_PATTERN_PRBS23:
 787			pattern = PHY_TEST_PATTERN_PRBS23;
 788			break;
 789		case DP_TEST_PATTERN_PRBS31:
 790			pattern = PHY_TEST_PATTERN_PRBS31;
 791			break;
 792		case DP_TEST_PATTERN_264BIT_CUSTOM:
 793			pattern = PHY_TEST_PATTERN_264BIT_CUSTOM;
 794			break;
 795		case DP_TEST_PATTERN_SQUARE:
 796			pattern = PHY_TEST_PATTERN_SQUARE;
 797			break;
 798		case DP_TEST_PATTERN_SQUARE_PRESHOOT_DISABLED:
 799			pattern = PHY_TEST_PATTERN_SQUARE_PRESHOOT_DISABLED;
 800			break;
 801		case DP_TEST_PATTERN_SQUARE_DEEMPHASIS_DISABLED:
 802			pattern = PHY_TEST_PATTERN_SQUARE_DEEMPHASIS_DISABLED;
 803			break;
 804		case DP_TEST_PATTERN_SQUARE_PRESHOOT_DEEMPHASIS_DISABLED:
 805			pattern = PHY_TEST_PATTERN_SQUARE_PRESHOOT_DEEMPHASIS_DISABLED;
 806			break;
 807		default:
 808			return false;
 809		}
 810
 811		if (test_pattern == DP_TEST_PATTERN_VIDEO_MODE
 812		/*TODO:&& !pPathMode->pDisplayPath->IsTargetPoweredOn()*/)
 813			return false;
 814
 815		if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) {
 816			if (IS_DP_PHY_SQUARE_PATTERN(test_pattern))
 817				core_link_write_dpcd(link,
 818						DP_LINK_SQUARE_PATTERN,
 819						p_custom_pattern,
 820						1);
 821
 822			/* tell receiver that we are sending qualification
 823			 * pattern DP 1.2 or later - DP receiver's link quality
 824			 * pattern is set using DPCD LINK_QUAL_LANEx_SET
 825			 * register (0x10B~0x10E)\
 826			 */
 827			for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++)
 828				link_qual_pattern[lane] =
 829						(unsigned char)(pattern);
 830
 831			core_link_write_dpcd(link,
 832					DP_LINK_QUAL_LANE0_SET,
 833					link_qual_pattern,
 834					sizeof(link_qual_pattern));
 835		} else if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_10 ||
 836			   link->dpcd_caps.dpcd_rev.raw == 0) {
 837			/* tell receiver that we are sending qualification
 838			 * pattern DP 1.1a or earlier - DP receiver's link
 839			 * quality pattern is set using
 840			 * DPCD TRAINING_PATTERN_SET -> LINK_QUAL_PATTERN_SET
 841			 * register (0x102). We will use v_1.3 when we are
 842			 * setting test pattern for DP 1.1.
 843			 */
 844			core_link_read_dpcd(link, DP_TRAINING_PATTERN_SET,
 845					    &training_pattern.raw,
 846					    sizeof(training_pattern));
 847			training_pattern.v1_3.LINK_QUAL_PATTERN_SET = pattern;
 848			core_link_write_dpcd(link, DP_TRAINING_PATTERN_SET,
 849					     &training_pattern.raw,
 850					     sizeof(training_pattern));
 851		}
 852	} else {
 853		enum dc_color_space color_space = COLOR_SPACE_UNKNOWN;
 854
 855		switch (test_pattern_color_space) {
 856		case DP_TEST_PATTERN_COLOR_SPACE_RGB:
 857			color_space = COLOR_SPACE_SRGB;
 858			if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
 859				color_space = COLOR_SPACE_SRGB_LIMITED;
 860			break;
 861
 862		case DP_TEST_PATTERN_COLOR_SPACE_YCBCR601:
 863			color_space = COLOR_SPACE_YCBCR601;
 864			if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
 865				color_space = COLOR_SPACE_YCBCR601_LIMITED;
 866			break;
 867		case DP_TEST_PATTERN_COLOR_SPACE_YCBCR709:
 868			color_space = COLOR_SPACE_YCBCR709;
 869			if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
 870				color_space = COLOR_SPACE_YCBCR709_LIMITED;
 871			break;
 872		default:
 873			break;
 874		}
 875
 876		if (!pipe_ctx->stream)
 877			return false;
 878
 879		if (pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_enable) {
 880			if (should_use_dmub_inbox1_lock(pipe_ctx->stream->link->dc, pipe_ctx->stream->link)) {
 881				union dmub_hw_lock_flags hw_locks = { 0 };
 882				struct dmub_hw_lock_inst_flags inst_flags = { 0 };
 883
 884				hw_locks.bits.lock_dig = 1;
 885				inst_flags.dig_inst = pipe_ctx->stream_res.tg->inst;
 886
 887				dmub_hw_lock_mgr_cmd(link->ctx->dmub_srv,
 888							true,
 889							&hw_locks,
 890							&inst_flags);
 891			} else
 892				pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_enable(
 893						pipe_ctx->stream_res.tg);
 894		}
 895
 896		pipe_ctx->stream_res.tg->funcs->lock(pipe_ctx->stream_res.tg);
 897		/* update MSA to requested color space */
 898		link_hwss = get_link_hwss(link, &pipe_ctx->link_res);
 899		pipe_ctx->stream->output_color_space = color_space;
 900		link_hwss->setup_stream_attribute(pipe_ctx);
 901
 902		if (pipe_ctx->stream->use_vsc_sdp_for_colorimetry) {
 903			if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
 904				pipe_ctx->stream->vsc_infopacket.sb[17] |= (1 << 7); // sb17 bit 7 Dynamic Range: 0 = VESA range, 1 = CTA range
 905			else
 906				pipe_ctx->stream->vsc_infopacket.sb[17] &= ~(1 << 7);
 907
 908			if (color_space == COLOR_SPACE_YCBCR601_LIMITED)
 909				pipe_ctx->stream->vsc_infopacket.sb[16] &= 0xf0;
 910			else if (color_space == COLOR_SPACE_YCBCR709_LIMITED)
 911				pipe_ctx->stream->vsc_infopacket.sb[16] |= 1;
 912
 913			resource_build_info_frame(pipe_ctx);
 914			link->dc->hwss.update_info_frame(pipe_ctx);
 915		}
 916
 917		/* CRTC Patterns */
 918		set_crtc_test_pattern(link, pipe_ctx, test_pattern, test_pattern_color_space);
 919		pipe_ctx->stream_res.tg->funcs->unlock(pipe_ctx->stream_res.tg);
 920		pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg,
 921				CRTC_STATE_VACTIVE);
 922		pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg,
 923				CRTC_STATE_VBLANK);
 924		pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg,
 925				CRTC_STATE_VACTIVE);
 926
 927		if (pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_disable) {
 928			if (should_use_dmub_inbox1_lock(pipe_ctx->stream->link->dc, pipe_ctx->stream->link)) {
 929				union dmub_hw_lock_flags hw_locks = { 0 };
 930				struct dmub_hw_lock_inst_flags inst_flags = { 0 };
 931
 932				hw_locks.bits.lock_dig = 1;
 933				inst_flags.dig_inst = pipe_ctx->stream_res.tg->inst;
 934
 935				dmub_hw_lock_mgr_cmd(link->ctx->dmub_srv,
 936							false,
 937							&hw_locks,
 938							&inst_flags);
 939			} else
 940				pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_disable(
 941						pipe_ctx->stream_res.tg);
 942		}
 943
 944		/* Set Test Pattern state */
 945		link->test_pattern_enabled = true;
 946		link->current_test_pattern = test_pattern;
 947		link->pending_test_pattern = DP_TEST_PATTERN_UNSUPPORTED;
 948	}
 949
 950	return true;
 951}
 952
 953void dp_set_preferred_link_settings(struct dc *dc,
 954		struct dc_link_settings *link_setting,
 955		struct dc_link *link)
 956{
 957	int i;
 958	struct pipe_ctx *pipe;
 959	struct dc_stream_state *link_stream = 0;
 960	struct dc_link_settings store_settings = *link_setting;
 961
 962	link->preferred_link_setting = store_settings;
 963
 964	/* Retrain with preferred link settings only relevant for
 965	 * DP signal type
 966	 * Check for non-DP signal or if passive dongle present
 967	 */
 968	if (!dc_is_dp_signal(link->connector_signal) ||
 969		link->dongle_max_pix_clk > 0)
 970		return;
 971
 972	for (i = 0; i < MAX_PIPES; i++) {
 973		pipe = &dc->current_state->res_ctx.pipe_ctx[i];
 974		if (pipe->stream && pipe->stream->link) {
 975			if (pipe->stream->link == link) {
 976				link_stream = pipe->stream;
 977				break;
 978			}
 979		}
 980	}
 981
 982	/* Stream not found */
 983	if (i == MAX_PIPES)
 984		return;
 985
 986	/* Cannot retrain link if backend is off */
 987	if (link_stream->dpms_off)
 988		return;
 989
 990	if (link_decide_link_settings(link_stream, &store_settings))
 991		dp_retrain_link_dp_test(link, &store_settings, false);
 992}
 993
 994void dp_set_preferred_training_settings(struct dc *dc,
 995		struct dc_link_settings *link_setting,
 996		struct dc_link_training_overrides *lt_overrides,
 997		struct dc_link *link,
 998		bool skip_immediate_retrain)
 999{
1000	if (lt_overrides != NULL)
1001		link->preferred_training_settings = *lt_overrides;
1002	else
1003		memset(&link->preferred_training_settings, 0, sizeof(link->preferred_training_settings));
1004
1005	if (link_setting != NULL) {
1006		link->preferred_link_setting = *link_setting;
1007	} else {
1008		link->preferred_link_setting.lane_count = LANE_COUNT_UNKNOWN;
1009		link->preferred_link_setting.link_rate = LINK_RATE_UNKNOWN;
1010	}
1011
1012	if (link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT &&
1013			link->type == dc_connection_mst_branch)
1014		dm_helpers_dp_mst_update_branch_bandwidth(dc->ctx, link);
1015
1016	/* Retrain now, or wait until next stream update to apply */
1017	if (skip_immediate_retrain == false)
1018		dp_set_preferred_link_settings(dc, &link->preferred_link_setting, link);
1019}
~/ Read-only file preview.