File Index
Files and directories
Sign in
FILE

dce120_timing_generator.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c C
   1/*
   2 * Copyright 2012-15 Advanced Micro Devices, Inc.
   3 *
   4 * Permission is hereby granted, free of charge, to any person obtaining a
   5 * copy of this software and associated documentation files (the "Software"),
   6 * to deal in the Software without restriction, including without limitation
   7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8 * and/or sell copies of the Software, and to permit persons to whom the
   9 * Software is furnished to do so, subject to the following conditions:
  10 *
  11 * The above copyright notice and this permission notice shall be included in
  12 * all copies or substantial portions of the Software.
  13 *
  14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20 * OTHER DEALINGS IN THE SOFTWARE.
  21 *
  22 * Authors: AMD
  23 *
  24 */
  25
  26#include "dm_services.h"
  27
  28#include "dce/dce_12_0_offset.h"
  29#include "dce/dce_12_0_sh_mask.h"
  30#include "soc15_hw_ip.h"
  31#include "vega10_ip_offset.h"
  32
  33#include "dc_types.h"
  34#include "dc_bios_types.h"
  35
  36#include "include/grph_object_id.h"
  37#include "include/logger_interface.h"
  38#include "dce120_timing_generator.h"
  39
  40#include "timing_generator.h"
  41
  42#define CRTC_REG_UPDATE_N(reg_name, n, ...)	\
  43		generic_reg_update_soc15(tg110->base.ctx, tg110->offsets.crtc, reg_name, n, __VA_ARGS__)
  44
  45#define CRTC_REG_SET_N(reg_name, n, ...)	\
  46		generic_reg_set_soc15(tg110->base.ctx, tg110->offsets.crtc, reg_name, n, __VA_ARGS__)
  47
  48#define CRTC_REG_UPDATE(reg, field, val)	\
  49		CRTC_REG_UPDATE_N(reg, 1, FD(reg##__##field), val)
  50
  51#define CRTC_REG_UPDATE_2(reg, field1, val1, field2, val2)	\
  52		CRTC_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2)
  53
  54#define CRTC_REG_UPDATE_3(reg, field1, val1, field2, val2, field3, val3)	\
  55		CRTC_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3)
  56
  57#define CRTC_REG_UPDATE_4(reg, field1, val1, field2, val2, field3, val3, field4, val4)	\
  58		CRTC_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3, FD(reg##__##field4), val4)
  59
  60#define CRTC_REG_UPDATE_5(reg, field1, val1, field2, val2, field3, val3, field4, val4, field5, val5)	\
  61		CRTC_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3, FD(reg##__##field4), val4, FD(reg##__##field5), val5)
  62
  63#define CRTC_REG_SET(reg, field, val)	\
  64		CRTC_REG_SET_N(reg, 1, FD(reg##__##field), val)
  65
  66#define CRTC_REG_SET_2(reg, field1, val1, field2, val2)	\
  67		CRTC_REG_SET_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2)
  68
  69#define CRTC_REG_SET_3(reg, field1, val1, field2, val2, field3, val3)	\
  70		CRTC_REG_SET_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3)
  71
  72/*
  73 *****************************************************************************
  74 *  Function: is_in_vertical_blank
  75 *
  76 *  @brief
  77 *     check the current status of CRTC to check if we are in Vertical Blank
  78 *     regioneased" state
  79 *
  80 *  @return
  81 *     true if currently in blank region, false otherwise
  82 *
  83 *****************************************************************************
  84 */
  85static bool dce120_timing_generator_is_in_vertical_blank(
  86		struct timing_generator *tg)
  87{
  88	uint32_t field = 0;
  89	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
  90	uint32_t value = dm_read_reg_soc15(
  91					tg->ctx,
  92					mmCRTC0_CRTC_STATUS,
  93					tg110->offsets.crtc);
  94
  95	field = get_reg_field_value(value, CRTC0_CRTC_STATUS, CRTC_V_BLANK);
  96	return field == 1;
  97}
  98
  99
 100/* determine if given timing can be supported by TG */
 101static bool dce120_timing_generator_validate_timing(
 102	struct timing_generator *tg,
 103	const struct dc_crtc_timing *timing,
 104	enum signal_type signal)
 105{
 106	uint32_t interlace_factor = timing->flags.INTERLACE ? 2 : 1;
 107	uint32_t v_blank =
 108					(timing->v_total - timing->v_addressable -
 109					timing->v_border_top - timing->v_border_bottom) *
 110					interlace_factor;
 111	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 112
 113	if (!dce110_timing_generator_validate_timing(
 114					tg,
 115					timing,
 116					signal))
 117		return false;
 118
 119
 120	if (v_blank < tg110->min_v_blank	||
 121		 timing->h_sync_width  < tg110->min_h_sync_width ||
 122		 timing->v_sync_width  < tg110->min_v_sync_width)
 123		return false;
 124
 125	return true;
 126}
 127
 128static bool dce120_tg_validate_timing(struct timing_generator *tg,
 129	const struct dc_crtc_timing *timing)
 130{
 131	return dce120_timing_generator_validate_timing(tg, timing, SIGNAL_TYPE_NONE);
 132}
 133
 134/******** HW programming ************/
 135/* Disable/Enable Timing Generator */
 136static bool dce120_timing_generator_enable_crtc(struct timing_generator *tg)
 137{
 138	enum bp_result result;
 139	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 140
 141	/* Set MASTER_UPDATE_MODE to 0
 142	 * This is needed for DRR, and also suggested to be default value by Syed.*/
 143
 144	CRTC_REG_UPDATE(CRTC0_CRTC_MASTER_UPDATE_MODE,
 145			MASTER_UPDATE_MODE, 0);
 146
 147	CRTC_REG_UPDATE(CRTC0_CRTC_MASTER_UPDATE_LOCK,
 148			UNDERFLOW_UPDATE_LOCK, 0);
 149
 150	/* TODO API for AtomFirmware didn't change*/
 151	result = tg->bp->funcs->enable_crtc(tg->bp, tg110->controller_id, true);
 152
 153	return result == BP_RESULT_OK;
 154}
 155
 156static void dce120_timing_generator_set_early_control(
 157		struct timing_generator *tg,
 158		uint32_t early_cntl)
 159{
 160	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 161
 162	CRTC_REG_UPDATE(CRTC0_CRTC_CONTROL,
 163			CRTC_HBLANK_EARLY_CONTROL, early_cntl);
 164}
 165
 166/**************** TG current status ******************/
 167
 168/* return the current frame counter. Used by Linux kernel DRM */
 169static uint32_t dce120_timing_generator_get_vblank_counter(
 170		struct timing_generator *tg)
 171{
 172	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 173	uint32_t value = dm_read_reg_soc15(
 174				tg->ctx,
 175				mmCRTC0_CRTC_STATUS_FRAME_COUNT,
 176				tg110->offsets.crtc);
 177	uint32_t field = get_reg_field_value(
 178				value, CRTC0_CRTC_STATUS_FRAME_COUNT, CRTC_FRAME_COUNT);
 179
 180	return field;
 181}
 182
 183/* Get current H and V position */
 184static void dce120_timing_generator_get_crtc_position(
 185	struct timing_generator *tg,
 186	struct crtc_position *position)
 187{
 188	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 189	uint32_t value = dm_read_reg_soc15(
 190				tg->ctx,
 191				mmCRTC0_CRTC_STATUS_POSITION,
 192				tg110->offsets.crtc);
 193
 194	position->horizontal_count = get_reg_field_value(value,
 195			CRTC0_CRTC_STATUS_POSITION, CRTC_HORZ_COUNT);
 196
 197	position->vertical_count = get_reg_field_value(value,
 198			CRTC0_CRTC_STATUS_POSITION, CRTC_VERT_COUNT);
 199
 200	value = dm_read_reg_soc15(
 201				tg->ctx,
 202				mmCRTC0_CRTC_NOM_VERT_POSITION,
 203				tg110->offsets.crtc);
 204
 205	position->nominal_vcount = get_reg_field_value(value,
 206			CRTC0_CRTC_NOM_VERT_POSITION, CRTC_VERT_COUNT_NOM);
 207}
 208
 209/* wait until TG is in beginning of vertical blank region */
 210static void dce120_timing_generator_wait_for_vblank(struct timing_generator *tg)
 211{
 212	/* We want to catch beginning of VBlank here, so if the first try are
 213	 * in VBlank, we might be very close to Active, in this case wait for
 214	 * another frame
 215	 */
 216	while (dce120_timing_generator_is_in_vertical_blank(tg)) {
 217		if (!tg->funcs->is_counter_moving(tg)) {
 218			/* error - no point to wait if counter is not moving */
 219			break;
 220		}
 221	}
 222
 223	while (!dce120_timing_generator_is_in_vertical_blank(tg)) {
 224		if (!tg->funcs->is_counter_moving(tg)) {
 225			/* error - no point to wait if counter is not moving */
 226			break;
 227		}
 228	}
 229}
 230
 231/* wait until TG is in beginning of active region */
 232static void dce120_timing_generator_wait_for_vactive(struct timing_generator *tg)
 233{
 234	while (dce120_timing_generator_is_in_vertical_blank(tg)) {
 235		if (!tg->funcs->is_counter_moving(tg)) {
 236			/* error - no point to wait if counter is not moving */
 237			break;
 238		}
 239	}
 240}
 241
 242/*********** Timing Generator Synchronization routines ****/
 243
 244/* Setups Global Swap Lock group, TimingServer or TimingClient*/
 245static void dce120_timing_generator_setup_global_swap_lock(
 246	struct timing_generator *tg,
 247	const struct dcp_gsl_params *gsl_params)
 248{
 249	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 250	uint32_t value_crtc_vtotal =
 251							dm_read_reg_soc15(tg->ctx,
 252							mmCRTC0_CRTC_V_TOTAL,
 253							tg110->offsets.crtc);
 254	/* Checkpoint relative to end of frame */
 255	uint32_t check_point =
 256							get_reg_field_value(value_crtc_vtotal,
 257							CRTC0_CRTC_V_TOTAL,
 258							CRTC_V_TOTAL);
 259
 260
 261	dm_write_reg_soc15(tg->ctx, mmCRTC0_CRTC_GSL_WINDOW, tg110->offsets.crtc, 0);
 262
 263	CRTC_REG_UPDATE_N(DCP0_DCP_GSL_CONTROL, 6,
 264		/* This pipe will belong to GSL Group zero. */
 265		FD(DCP0_DCP_GSL_CONTROL__DCP_GSL0_EN), 1,
 266		FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_MASTER_EN), gsl_params->gsl_master == tg->inst,
 267		FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_FORCE_DELAY), HFLIP_READY_DELAY,
 268		/* Keep signal low (pending high) during 6 lines.
 269		 * Also defines minimum interval before re-checking signal. */
 270		FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_CHECK_DELAY), HFLIP_CHECK_DELAY,
 271		/* DCP_GSL_PURPOSE_SURFACE_FLIP */
 272		FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_SYNC_SOURCE), 0,
 273		FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_DELAY_SURFACE_UPDATE_PENDING), 1);
 274
 275	CRTC_REG_SET_2(
 276			CRTC0_CRTC_GSL_CONTROL,
 277			CRTC_GSL_CHECK_LINE_NUM, check_point - FLIP_READY_BACK_LOOKUP,
 278			CRTC_GSL_FORCE_DELAY, VFLIP_READY_DELAY);
 279}
 280
 281/* Clear all the register writes done by setup_global_swap_lock */
 282static void dce120_timing_generator_tear_down_global_swap_lock(
 283	struct timing_generator *tg)
 284{
 285	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 286
 287	/* Settig HW default values from reg specs */
 288	CRTC_REG_SET_N(DCP0_DCP_GSL_CONTROL, 6,
 289			FD(DCP0_DCP_GSL_CONTROL__DCP_GSL0_EN), 0,
 290			FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_MASTER_EN), 0,
 291			FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_FORCE_DELAY), HFLIP_READY_DELAY,
 292			FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_CHECK_DELAY), HFLIP_CHECK_DELAY,
 293			/* DCP_GSL_PURPOSE_SURFACE_FLIP */
 294			FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_SYNC_SOURCE), 0,
 295			FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_DELAY_SURFACE_UPDATE_PENDING), 0);
 296
 297	CRTC_REG_SET_2(CRTC0_CRTC_GSL_CONTROL,
 298		       CRTC_GSL_CHECK_LINE_NUM, 0,
 299		       CRTC_GSL_FORCE_DELAY, 0x2); /*TODO Why this value here ?*/
 300}
 301
 302/* Reset slave controllers on master VSync */
 303static void dce120_timing_generator_enable_reset_trigger(
 304	struct timing_generator *tg,
 305	int source)
 306{
 307	enum trigger_source_select trig_src_select = TRIGGER_SOURCE_SELECT_LOGIC_ZERO;
 308	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 309	uint32_t rising_edge = 0;
 310	uint32_t falling_edge = 0;
 311	/* Setup trigger edge */
 312	uint32_t pol_value = dm_read_reg_soc15(
 313									tg->ctx,
 314									mmCRTC0_CRTC_V_SYNC_A_CNTL,
 315									tg110->offsets.crtc);
 316
 317	/* Register spec has reversed definition:
 318	 *	0 for positive, 1 for negative */
 319	if (get_reg_field_value(pol_value,
 320			CRTC0_CRTC_V_SYNC_A_CNTL,
 321			CRTC_V_SYNC_A_POL) == 0) {
 322		rising_edge = 1;
 323	} else {
 324		falling_edge = 1;
 325	}
 326
 327	/* TODO What about other sources ?*/
 328	trig_src_select = TRIGGER_SOURCE_SELECT_GSL_GROUP0;
 329
 330	CRTC_REG_UPDATE_N(CRTC0_CRTC_TRIGB_CNTL, 7,
 331		FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_SOURCE_SELECT), trig_src_select,
 332		FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_POLARITY_SELECT), TRIGGER_POLARITY_SELECT_LOGIC_ZERO,
 333		FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_RISING_EDGE_DETECT_CNTL), rising_edge,
 334		FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_FALLING_EDGE_DETECT_CNTL), falling_edge,
 335		/* send every signal */
 336		FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_FREQUENCY_SELECT), 0,
 337		/* no delay */
 338		FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_DELAY), 0,
 339		/* clear trigger status */
 340		FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_CLEAR), 1);
 341
 342	CRTC_REG_UPDATE_3(
 343			CRTC0_CRTC_FORCE_COUNT_NOW_CNTL,
 344			CRTC_FORCE_COUNT_NOW_MODE, 2,
 345			CRTC_FORCE_COUNT_NOW_TRIG_SEL, 1,
 346			CRTC_FORCE_COUNT_NOW_CLEAR, 1);
 347}
 348
 349/* disabling trigger-reset */
 350static void dce120_timing_generator_disable_reset_trigger(
 351	struct timing_generator *tg)
 352{
 353	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 354
 355	CRTC_REG_UPDATE_2(
 356		CRTC0_CRTC_FORCE_COUNT_NOW_CNTL,
 357		CRTC_FORCE_COUNT_NOW_MODE, 0,
 358		CRTC_FORCE_COUNT_NOW_CLEAR, 1);
 359
 360	CRTC_REG_UPDATE_3(
 361		CRTC0_CRTC_TRIGB_CNTL,
 362		CRTC_TRIGB_SOURCE_SELECT, TRIGGER_SOURCE_SELECT_LOGIC_ZERO,
 363		CRTC_TRIGB_POLARITY_SELECT, TRIGGER_POLARITY_SELECT_LOGIC_ZERO,
 364		/* clear trigger status */
 365		CRTC_TRIGB_CLEAR, 1);
 366
 367}
 368
 369/* Checks whether CRTC triggered reset occurred */
 370static bool dce120_timing_generator_did_triggered_reset_occur(
 371	struct timing_generator *tg)
 372{
 373	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 374	uint32_t value = dm_read_reg_soc15(
 375			tg->ctx,
 376			mmCRTC0_CRTC_FORCE_COUNT_NOW_CNTL,
 377			tg110->offsets.crtc);
 378
 379	return get_reg_field_value(value,
 380			CRTC0_CRTC_FORCE_COUNT_NOW_CNTL,
 381			CRTC_FORCE_COUNT_NOW_OCCURRED) != 0;
 382}
 383
 384
 385/******** Stuff to move to other virtual HW objects *****************/
 386/* Move to enable accelerated mode */
 387static void dce120_timing_generator_disable_vga(struct timing_generator *tg)
 388{
 389	uint32_t offset = 0;
 390	uint32_t value = 0;
 391	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 392
 393	switch (tg110->controller_id) {
 394	case CONTROLLER_ID_D0:
 395		offset = 0;
 396		break;
 397	case CONTROLLER_ID_D1:
 398		offset = mmD2VGA_CONTROL - mmD1VGA_CONTROL;
 399		break;
 400	case CONTROLLER_ID_D2:
 401		offset = mmD3VGA_CONTROL - mmD1VGA_CONTROL;
 402		break;
 403	case CONTROLLER_ID_D3:
 404		offset = mmD4VGA_CONTROL - mmD1VGA_CONTROL;
 405		break;
 406	case CONTROLLER_ID_D4:
 407		offset = mmD5VGA_CONTROL - mmD1VGA_CONTROL;
 408		break;
 409	case CONTROLLER_ID_D5:
 410		offset = mmD6VGA_CONTROL - mmD1VGA_CONTROL;
 411		break;
 412	default:
 413		break;
 414	}
 415
 416	value = dm_read_reg_soc15(tg->ctx, mmD1VGA_CONTROL, offset);
 417
 418	set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_MODE_ENABLE);
 419	set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_TIMING_SELECT);
 420	set_reg_field_value(
 421			value, 0, D1VGA_CONTROL, D1VGA_SYNC_POLARITY_SELECT);
 422	set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_OVERSCAN_COLOR_EN);
 423
 424	dm_write_reg_soc15(tg->ctx, mmD1VGA_CONTROL, offset, value);
 425}
 426/* TODO: Should we move it to transform */
 427/* Fully program CRTC timing in timing generator */
 428static void dce120_timing_generator_program_blanking(
 429	struct timing_generator *tg,
 430	const struct dc_crtc_timing *timing)
 431{
 432	uint32_t tmp1 = 0;
 433	uint32_t tmp2 = 0;
 434	uint32_t vsync_offset = timing->v_border_bottom +
 435			timing->v_front_porch;
 436	uint32_t v_sync_start = timing->v_addressable + vsync_offset;
 437
 438	uint32_t hsync_offset = timing->h_border_right +
 439			timing->h_front_porch;
 440	uint32_t h_sync_start = timing->h_addressable + hsync_offset;
 441	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 442
 443	CRTC_REG_UPDATE(
 444		CRTC0_CRTC_H_TOTAL,
 445		CRTC_H_TOTAL,
 446		timing->h_total - 1);
 447
 448	CRTC_REG_UPDATE(
 449		CRTC0_CRTC_V_TOTAL,
 450		CRTC_V_TOTAL,
 451		timing->v_total - 1);
 452
 453	/* In case of V_TOTAL_CONTROL is on, make sure V_TOTAL_MAX and
 454	 * V_TOTAL_MIN are equal to V_TOTAL.
 455	 */
 456	CRTC_REG_UPDATE(
 457		CRTC0_CRTC_V_TOTAL_MAX,
 458		CRTC_V_TOTAL_MAX,
 459		timing->v_total - 1);
 460
 461	CRTC_REG_UPDATE(
 462		CRTC0_CRTC_V_TOTAL_MIN,
 463		CRTC_V_TOTAL_MIN,
 464		timing->v_total - 1);
 465
 466	tmp1 = timing->h_total -
 467			(h_sync_start + timing->h_border_left);
 468	tmp2 = tmp1 + timing->h_addressable +
 469			timing->h_border_left + timing->h_border_right;
 470
 471	CRTC_REG_UPDATE_2(
 472			CRTC0_CRTC_H_BLANK_START_END,
 473			CRTC_H_BLANK_END, tmp1,
 474			CRTC_H_BLANK_START, tmp2);
 475
 476	tmp1 = timing->v_total - (v_sync_start + timing->v_border_top);
 477	tmp2 = tmp1 + timing->v_addressable + timing->v_border_top +
 478			timing->v_border_bottom;
 479
 480	CRTC_REG_UPDATE_2(
 481		CRTC0_CRTC_V_BLANK_START_END,
 482		CRTC_V_BLANK_END, tmp1,
 483		CRTC_V_BLANK_START, tmp2);
 484}
 485
 486/* TODO: Should we move it to opp? */
 487/* Combine with below and move YUV/RGB color conversion to SW layer */
 488static void dce120_timing_generator_program_blank_color(
 489	struct timing_generator *tg,
 490	const struct tg_color *black_color)
 491{
 492	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 493
 494	CRTC_REG_UPDATE_3(
 495		CRTC0_CRTC_BLACK_COLOR,
 496		CRTC_BLACK_COLOR_B_CB, black_color->color_b_cb,
 497		CRTC_BLACK_COLOR_G_Y, black_color->color_g_y,
 498		CRTC_BLACK_COLOR_R_CR, black_color->color_r_cr);
 499}
 500/* Combine with above and move YUV/RGB color conversion to SW layer */
 501static void dce120_timing_generator_set_overscan_color_black(
 502	struct timing_generator *tg,
 503	const struct tg_color *color)
 504{
 505	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 506	uint32_t value = 0;
 507	CRTC_REG_SET_3(
 508		CRTC0_CRTC_OVERSCAN_COLOR,
 509		CRTC_OVERSCAN_COLOR_BLUE, color->color_b_cb,
 510		CRTC_OVERSCAN_COLOR_GREEN, color->color_g_y,
 511		CRTC_OVERSCAN_COLOR_RED, color->color_r_cr);
 512
 513	value = dm_read_reg_soc15(
 514			tg->ctx,
 515			mmCRTC0_CRTC_OVERSCAN_COLOR,
 516			tg110->offsets.crtc);
 517
 518	dm_write_reg_soc15(
 519			tg->ctx,
 520			mmCRTC0_CRTC_BLACK_COLOR,
 521			tg110->offsets.crtc,
 522			value);
 523
 524	/* This is desirable to have a constant DAC output voltage during the
 525	 * blank time that is higher than the 0 volt reference level that the
 526	 * DAC outputs when the NBLANK signal
 527	 * is asserted low, such as for output to an analog TV. */
 528	dm_write_reg_soc15(
 529		tg->ctx,
 530		mmCRTC0_CRTC_BLANK_DATA_COLOR,
 531		tg110->offsets.crtc,
 532		value);
 533
 534	/* TO DO we have to program EXT registers and we need to know LB DATA
 535	 * format because it is used when more 10 , i.e. 12 bits per color
 536	 *
 537	 * m_mmDxCRTC_OVERSCAN_COLOR_EXT
 538	 * m_mmDxCRTC_BLACK_COLOR_EXT
 539	 * m_mmDxCRTC_BLANK_DATA_COLOR_EXT
 540	 */
 541}
 542
 543static void dce120_timing_generator_set_drr(
 544	struct timing_generator *tg,
 545	const struct drr_params *params)
 546{
 547
 548	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 549
 550	if (params != NULL &&
 551		params->vertical_total_max > 0 &&
 552		params->vertical_total_min > 0) {
 553
 554		CRTC_REG_UPDATE(
 555				CRTC0_CRTC_V_TOTAL_MIN,
 556				CRTC_V_TOTAL_MIN, params->vertical_total_min - 1);
 557		CRTC_REG_UPDATE(
 558				CRTC0_CRTC_V_TOTAL_MAX,
 559				CRTC_V_TOTAL_MAX, params->vertical_total_max - 1);
 560		CRTC_REG_SET_N(CRTC0_CRTC_V_TOTAL_CONTROL, 6,
 561				FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MIN_SEL), 1,
 562				FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MAX_SEL), 1,
 563				FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_ON_EVENT), 0,
 564				FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_TO_MASTER_VSYNC), 0,
 565				FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_SET_V_TOTAL_MIN_MASK_EN), 0,
 566				FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_SET_V_TOTAL_MIN_MASK), 0);
 567		CRTC_REG_UPDATE(
 568				CRTC0_CRTC_STATIC_SCREEN_CONTROL,
 569				CRTC_STATIC_SCREEN_EVENT_MASK,
 570				0x180);
 571
 572	} else {
 573		CRTC_REG_SET_N(CRTC0_CRTC_V_TOTAL_CONTROL, 5,
 574				FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MIN_SEL), 0,
 575				FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MAX_SEL), 0,
 576				FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_ON_EVENT), 0,
 577				FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_TO_MASTER_VSYNC), 0,
 578				FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_SET_V_TOTAL_MIN_MASK), 0);
 579		CRTC_REG_UPDATE(
 580				CRTC0_CRTC_V_TOTAL_MIN,
 581				CRTC_V_TOTAL_MIN, 0);
 582		CRTC_REG_UPDATE(
 583				CRTC0_CRTC_V_TOTAL_MAX,
 584				CRTC_V_TOTAL_MAX, 0);
 585		CRTC_REG_UPDATE(
 586				CRTC0_CRTC_STATIC_SCREEN_CONTROL,
 587				CRTC_STATIC_SCREEN_EVENT_MASK,
 588				0);
 589	}
 590}
 591
 592static void dce120_timing_generator_get_crtc_scanoutpos(
 593	struct timing_generator *tg,
 594	uint32_t *v_blank_start,
 595	uint32_t *v_blank_end,
 596	uint32_t *h_position,
 597	uint32_t *v_position)
 598{
 599	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 600	struct crtc_position position;
 601
 602	uint32_t v_blank_start_end = dm_read_reg_soc15(
 603			tg->ctx,
 604			mmCRTC0_CRTC_V_BLANK_START_END,
 605			tg110->offsets.crtc);
 606
 607	*v_blank_start = get_reg_field_value(v_blank_start_end,
 608					     CRTC0_CRTC_V_BLANK_START_END,
 609					     CRTC_V_BLANK_START);
 610	*v_blank_end = get_reg_field_value(v_blank_start_end,
 611					   CRTC0_CRTC_V_BLANK_START_END,
 612					   CRTC_V_BLANK_END);
 613
 614	dce120_timing_generator_get_crtc_position(
 615			tg, &position);
 616
 617	*h_position = position.horizontal_count;
 618	*v_position = position.vertical_count;
 619}
 620
 621static void dce120_timing_generator_enable_advanced_request(
 622	struct timing_generator *tg,
 623	bool enable,
 624	const struct dc_crtc_timing *timing)
 625{
 626	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 627	uint32_t v_sync_width_and_b_porch =
 628				timing->v_total - timing->v_addressable -
 629				timing->v_border_bottom - timing->v_front_porch;
 630	uint32_t value = dm_read_reg_soc15(
 631				tg->ctx,
 632				mmCRTC0_CRTC_START_LINE_CONTROL,
 633				tg110->offsets.crtc);
 634
 635	set_reg_field_value(
 636		value,
 637		enable ? 0 : 1,
 638		CRTC0_CRTC_START_LINE_CONTROL,
 639		CRTC_LEGACY_REQUESTOR_EN);
 640
 641	/* Program advanced line position acc.to the best case from fetching data perspective to hide MC latency
 642	 * and prefilling Line Buffer in V Blank (to 10 lines as LB can store max 10 lines)
 643	 */
 644	if (v_sync_width_and_b_porch > 10)
 645		v_sync_width_and_b_porch = 10;
 646
 647	set_reg_field_value(
 648		value,
 649		v_sync_width_and_b_porch,
 650		CRTC0_CRTC_START_LINE_CONTROL,
 651		CRTC_ADVANCED_START_LINE_POSITION);
 652
 653	dm_write_reg_soc15(tg->ctx,
 654			mmCRTC0_CRTC_START_LINE_CONTROL,
 655			tg110->offsets.crtc,
 656			value);
 657}
 658
 659static void dce120_tg_program_blank_color(struct timing_generator *tg,
 660	const struct tg_color *black_color)
 661{
 662	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 663	uint32_t value = 0;
 664
 665	CRTC_REG_UPDATE_3(
 666		CRTC0_CRTC_BLACK_COLOR,
 667		CRTC_BLACK_COLOR_B_CB, black_color->color_b_cb,
 668		CRTC_BLACK_COLOR_G_Y, black_color->color_g_y,
 669		CRTC_BLACK_COLOR_R_CR, black_color->color_r_cr);
 670
 671	value = dm_read_reg_soc15(
 672				tg->ctx,
 673				mmCRTC0_CRTC_BLACK_COLOR,
 674				tg110->offsets.crtc);
 675	dm_write_reg_soc15(
 676		tg->ctx,
 677		mmCRTC0_CRTC_BLANK_DATA_COLOR,
 678		tg110->offsets.crtc,
 679		value);
 680}
 681
 682static void dce120_tg_set_overscan_color(struct timing_generator *tg,
 683	const struct tg_color *overscan_color)
 684{
 685	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 686
 687	CRTC_REG_SET_3(
 688		CRTC0_CRTC_OVERSCAN_COLOR,
 689		CRTC_OVERSCAN_COLOR_BLUE, overscan_color->color_b_cb,
 690		CRTC_OVERSCAN_COLOR_GREEN, overscan_color->color_g_y,
 691		CRTC_OVERSCAN_COLOR_RED, overscan_color->color_r_cr);
 692}
 693
 694static void dce120_tg_program_timing(struct timing_generator *tg,
 695	const struct dc_crtc_timing *timing,
 696	int vready_offset,
 697	int vstartup_start,
 698	int vupdate_offset,
 699	int vupdate_width,
 700	int pstate_keepout,
 701	const enum signal_type signal,
 702	bool use_vbios)
 703{
 704	if (use_vbios)
 705		dce110_timing_generator_program_timing_generator(tg, timing);
 706	else
 707		dce120_timing_generator_program_blanking(tg, timing);
 708}
 709
 710static bool dce120_tg_is_blanked(struct timing_generator *tg)
 711{
 712	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 713	uint32_t value = dm_read_reg_soc15(
 714			tg->ctx,
 715			mmCRTC0_CRTC_BLANK_CONTROL,
 716			tg110->offsets.crtc);
 717
 718	if (get_reg_field_value(
 719		value,
 720		CRTC0_CRTC_BLANK_CONTROL,
 721		CRTC_BLANK_DATA_EN) == 1 &&
 722	    get_reg_field_value(
 723		value,
 724		CRTC0_CRTC_BLANK_CONTROL,
 725		CRTC_CURRENT_BLANK_STATE) == 1)
 726			return true;
 727
 728	return false;
 729}
 730
 731static void dce120_tg_set_blank(struct timing_generator *tg,
 732		bool enable_blanking)
 733{
 734	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 735
 736	CRTC_REG_SET(
 737		CRTC0_CRTC_DOUBLE_BUFFER_CONTROL,
 738		CRTC_BLANK_DATA_DOUBLE_BUFFER_EN, 1);
 739
 740	if (enable_blanking)
 741		CRTC_REG_SET(CRTC0_CRTC_BLANK_CONTROL, CRTC_BLANK_DATA_EN, 1);
 742	else
 743		dm_write_reg_soc15(tg->ctx, mmCRTC0_CRTC_BLANK_CONTROL,
 744			tg110->offsets.crtc, 0);
 745}
 746
 747bool dce120_tg_validate_timing(struct timing_generator *tg,
 748	const struct dc_crtc_timing *timing);
 749
 750static void dce120_tg_wait_for_state(struct timing_generator *tg,
 751	enum crtc_state state)
 752{
 753	switch (state) {
 754	case CRTC_STATE_VBLANK:
 755		dce120_timing_generator_wait_for_vblank(tg);
 756		break;
 757
 758	case CRTC_STATE_VACTIVE:
 759		dce120_timing_generator_wait_for_vactive(tg);
 760		break;
 761
 762	default:
 763		break;
 764	}
 765}
 766
 767static void dce120_tg_set_colors(struct timing_generator *tg,
 768	const struct tg_color *blank_color,
 769	const struct tg_color *overscan_color)
 770{
 771	if (blank_color != NULL)
 772		dce120_tg_program_blank_color(tg, blank_color);
 773
 774	if (overscan_color != NULL)
 775		dce120_tg_set_overscan_color(tg, overscan_color);
 776}
 777
 778static void dce120_timing_generator_set_static_screen_control(
 779	struct timing_generator *tg,
 780	uint32_t event_triggers,
 781	uint32_t num_frames)
 782{
 783	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 784
 785	// By register spec, it only takes 8 bit value
 786	if (num_frames > 0xFF)
 787		num_frames = 0xFF;
 788
 789	CRTC_REG_UPDATE_2(CRTC0_CRTC_STATIC_SCREEN_CONTROL,
 790			CRTC_STATIC_SCREEN_EVENT_MASK, event_triggers,
 791			CRTC_STATIC_SCREEN_FRAME_COUNT, num_frames);
 792}
 793
 794static void dce120_timing_generator_set_test_pattern(
 795	struct timing_generator *tg,
 796	/* TODO: replace 'controller_dp_test_pattern' by 'test_pattern_mode'
 797	 * because this is not DP-specific (which is probably somewhere in DP
 798	 * encoder) */
 799	enum controller_dp_test_pattern test_pattern,
 800	enum dc_color_depth color_depth)
 801{
 802	struct dc_context *ctx = tg->ctx;
 803	uint32_t value;
 804	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 805	enum test_pattern_color_format bit_depth;
 806	enum test_pattern_dyn_range dyn_range;
 807	enum test_pattern_mode mode;
 808	/* color ramp generator mixes 16-bits color */
 809	uint32_t src_bpc = 16;
 810	/* requested bpc */
 811	uint32_t dst_bpc;
 812	uint32_t index;
 813	/* RGB values of the color bars.
 814	 * Produce two RGB colors: RGB0 - white (all Fs)
 815	 * and RGB1 - black (all 0s)
 816	 * (three RGB components for two colors)
 817	 */
 818	uint16_t src_color[6] = {0xFFFF, 0xFFFF, 0xFFFF, 0x0000,
 819						0x0000, 0x0000};
 820	/* dest color (converted to the specified color format) */
 821	uint16_t dst_color[6];
 822	uint32_t inc_base;
 823
 824	/* translate to bit depth */
 825	switch (color_depth) {
 826	case COLOR_DEPTH_666:
 827		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_6;
 828	break;
 829	case COLOR_DEPTH_888:
 830		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
 831	break;
 832	case COLOR_DEPTH_101010:
 833		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_10;
 834	break;
 835	case COLOR_DEPTH_121212:
 836		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_12;
 837	break;
 838	default:
 839		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
 840	break;
 841	}
 842
 843	switch (test_pattern) {
 844	case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES:
 845	case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA:
 846	{
 847		dyn_range = (test_pattern ==
 848				CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA ?
 849				TEST_PATTERN_DYN_RANGE_CEA :
 850				TEST_PATTERN_DYN_RANGE_VESA);
 851		mode = TEST_PATTERN_MODE_COLORSQUARES_RGB;
 852
 853		CRTC_REG_UPDATE_2(CRTC0_CRTC_TEST_PATTERN_PARAMETERS,
 854				CRTC_TEST_PATTERN_VRES, 6,
 855				CRTC_TEST_PATTERN_HRES, 6);
 856
 857		CRTC_REG_UPDATE_4(CRTC0_CRTC_TEST_PATTERN_CONTROL,
 858				CRTC_TEST_PATTERN_EN, 1,
 859				CRTC_TEST_PATTERN_MODE, mode,
 860				CRTC_TEST_PATTERN_DYNAMIC_RANGE, dyn_range,
 861				CRTC_TEST_PATTERN_COLOR_FORMAT, bit_depth);
 862	}
 863	break;
 864
 865	case CONTROLLER_DP_TEST_PATTERN_VERTICALBARS:
 866	case CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS:
 867	{
 868		mode = (test_pattern ==
 869			CONTROLLER_DP_TEST_PATTERN_VERTICALBARS ?
 870			TEST_PATTERN_MODE_VERTICALBARS :
 871			TEST_PATTERN_MODE_HORIZONTALBARS);
 872
 873		switch (bit_depth) {
 874		case TEST_PATTERN_COLOR_FORMAT_BPC_6:
 875			dst_bpc = 6;
 876		break;
 877		case TEST_PATTERN_COLOR_FORMAT_BPC_8:
 878			dst_bpc = 8;
 879		break;
 880		case TEST_PATTERN_COLOR_FORMAT_BPC_10:
 881			dst_bpc = 10;
 882		break;
 883		default:
 884			dst_bpc = 8;
 885		break;
 886		}
 887
 888		/* adjust color to the required colorFormat */
 889		for (index = 0; index < 6; index++) {
 890			/* dst = 2^dstBpc * src / 2^srcBpc = src >>
 891			 * (srcBpc - dstBpc);
 892			 */
 893			dst_color[index] =
 894				src_color[index] >> (src_bpc - dst_bpc);
 895		/* CRTC_TEST_PATTERN_DATA has 16 bits,
 896		 * lowest 6 are hardwired to ZERO
 897		 * color bits should be left aligned aligned to MSB
 898		 * XXXXXXXXXX000000 for 10 bit,
 899		 * XXXXXXXX00000000 for 8 bit and XXXXXX0000000000 for 6
 900		 */
 901			dst_color[index] <<= (16 - dst_bpc);
 902		}
 903
 904		dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_PARAMETERS, tg110->offsets.crtc, 0);
 905
 906		/* We have to write the mask before data, similar to pipeline.
 907		 * For example, for 8 bpc, if we want RGB0 to be magenta,
 908		 * and RGB1 to be cyan,
 909		 * we need to make 7 writes:
 910		 * MASK   DATA
 911		 * 000001 00000000 00000000                     set mask to R0
 912		 * 000010 11111111 00000000     R0 255, 0xFF00, set mask to G0
 913		 * 000100 00000000 00000000     G0 0,   0x0000, set mask to B0
 914		 * 001000 11111111 00000000     B0 255, 0xFF00, set mask to R1
 915		 * 010000 00000000 00000000     R1 0,   0x0000, set mask to G1
 916		 * 100000 11111111 00000000     G1 255, 0xFF00, set mask to B1
 917		 * 100000 11111111 00000000     B1 255, 0xFF00
 918		 *
 919		 * we will make a loop of 6 in which we prepare the mask,
 920		 * then write, then prepare the color for next write.
 921		 * first iteration will write mask only,
 922		 * but each next iteration color prepared in
 923		 * previous iteration will be written within new mask,
 924		 * the last component will written separately,
 925		 * mask is not changing between 6th and 7th write
 926		 * and color will be prepared by last iteration
 927		 */
 928
 929		/* write color, color values mask in CRTC_TEST_PATTERN_MASK
 930		 * is B1, G1, R1, B0, G0, R0
 931		 */
 932		value = 0;
 933		for (index = 0; index < 6; index++) {
 934			/* prepare color mask, first write PATTERN_DATA
 935			 * will have all zeros
 936			 */
 937			set_reg_field_value(
 938				value,
 939				(1 << index),
 940				CRTC0_CRTC_TEST_PATTERN_COLOR,
 941				CRTC_TEST_PATTERN_MASK);
 942			/* write color component */
 943			dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, value);
 944			/* prepare next color component,
 945			 * will be written in the next iteration
 946			 */
 947			set_reg_field_value(
 948				value,
 949				dst_color[index],
 950				CRTC0_CRTC_TEST_PATTERN_COLOR,
 951				CRTC_TEST_PATTERN_DATA);
 952		}
 953		/* write last color component,
 954		 * it's been already prepared in the loop
 955		 */
 956		dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, value);
 957
 958		/* enable test pattern */
 959		CRTC_REG_UPDATE_4(CRTC0_CRTC_TEST_PATTERN_CONTROL,
 960				CRTC_TEST_PATTERN_EN, 1,
 961				CRTC_TEST_PATTERN_MODE, mode,
 962				CRTC_TEST_PATTERN_DYNAMIC_RANGE, 0,
 963				CRTC_TEST_PATTERN_COLOR_FORMAT, bit_depth);
 964	}
 965	break;
 966
 967	case CONTROLLER_DP_TEST_PATTERN_COLORRAMP:
 968	{
 969		mode = (bit_depth ==
 970			TEST_PATTERN_COLOR_FORMAT_BPC_10 ?
 971			TEST_PATTERN_MODE_DUALRAMP_RGB :
 972			TEST_PATTERN_MODE_SINGLERAMP_RGB);
 973
 974		switch (bit_depth) {
 975		case TEST_PATTERN_COLOR_FORMAT_BPC_6:
 976			dst_bpc = 6;
 977		break;
 978		case TEST_PATTERN_COLOR_FORMAT_BPC_8:
 979			dst_bpc = 8;
 980		break;
 981		case TEST_PATTERN_COLOR_FORMAT_BPC_10:
 982			dst_bpc = 10;
 983		break;
 984		default:
 985			dst_bpc = 8;
 986		break;
 987		}
 988
 989		/* increment for the first ramp for one color gradation
 990		 * 1 gradation for 6-bit color is 2^10
 991		 * gradations in 16-bit color
 992		 */
 993		inc_base = (src_bpc - dst_bpc);
 994
 995		switch (bit_depth) {
 996		case TEST_PATTERN_COLOR_FORMAT_BPC_6:
 997		{
 998			CRTC_REG_UPDATE_5(CRTC0_CRTC_TEST_PATTERN_PARAMETERS,
 999					CRTC_TEST_PATTERN_INC0, inc_base,
1000					CRTC_TEST_PATTERN_INC1, 0,
1001					CRTC_TEST_PATTERN_HRES, 6,
1002					CRTC_TEST_PATTERN_VRES, 6,
1003					CRTC_TEST_PATTERN_RAMP0_OFFSET, 0);
1004		}
1005		break;
1006		case TEST_PATTERN_COLOR_FORMAT_BPC_8:
1007		{
1008			CRTC_REG_UPDATE_5(CRTC0_CRTC_TEST_PATTERN_PARAMETERS,
1009					CRTC_TEST_PATTERN_INC0, inc_base,
1010					CRTC_TEST_PATTERN_INC1, 0,
1011					CRTC_TEST_PATTERN_HRES, 8,
1012					CRTC_TEST_PATTERN_VRES, 6,
1013					CRTC_TEST_PATTERN_RAMP0_OFFSET, 0);
1014		}
1015		break;
1016		case TEST_PATTERN_COLOR_FORMAT_BPC_10:
1017		{
1018			CRTC_REG_UPDATE_5(CRTC0_CRTC_TEST_PATTERN_PARAMETERS,
1019					CRTC_TEST_PATTERN_INC0, inc_base,
1020					CRTC_TEST_PATTERN_INC1, inc_base + 2,
1021					CRTC_TEST_PATTERN_HRES, 8,
1022					CRTC_TEST_PATTERN_VRES, 5,
1023					CRTC_TEST_PATTERN_RAMP0_OFFSET, 384 << 6);
1024		}
1025		break;
1026		default:
1027		break;
1028		}
1029
1030		dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, 0);
1031
1032		/* enable test pattern */
1033		dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_CONTROL, tg110->offsets.crtc, 0);
1034
1035		CRTC_REG_UPDATE_4(CRTC0_CRTC_TEST_PATTERN_CONTROL,
1036				CRTC_TEST_PATTERN_EN, 1,
1037				CRTC_TEST_PATTERN_MODE, mode,
1038				CRTC_TEST_PATTERN_DYNAMIC_RANGE, 0,
1039				CRTC_TEST_PATTERN_COLOR_FORMAT, bit_depth);
1040	}
1041	break;
1042	case CONTROLLER_DP_TEST_PATTERN_VIDEOMODE:
1043	{
1044		value = 0;
1045		dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_CONTROL, tg110->offsets.crtc,  value);
1046		dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, value);
1047		dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_PARAMETERS, tg110->offsets.crtc, value);
1048	}
1049	break;
1050	default:
1051	break;
1052	}
1053}
1054
1055static bool dce120_arm_vert_intr(
1056		struct timing_generator *tg,
1057		uint8_t width)
1058{
1059	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1060	uint32_t v_blank_start, v_blank_end, h_position, v_position;
1061
1062	tg->funcs->get_scanoutpos(
1063				tg,
1064				&v_blank_start,
1065				&v_blank_end,
1066				&h_position,
1067				&v_position);
1068
1069	if (v_blank_start == 0 || v_blank_end == 0)
1070		return false;
1071
1072	CRTC_REG_SET_2(
1073			CRTC0_CRTC_VERTICAL_INTERRUPT0_POSITION,
1074			CRTC_VERTICAL_INTERRUPT0_LINE_START, v_blank_start,
1075			CRTC_VERTICAL_INTERRUPT0_LINE_END, v_blank_start + width);
1076
1077	return true;
1078}
1079
1080
1081static bool dce120_is_tg_enabled(struct timing_generator *tg)
1082{
1083	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1084	uint32_t value, field;
1085
1086	value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CONTROL,
1087				  tg110->offsets.crtc);
1088	field = get_reg_field_value(value, CRTC0_CRTC_CONTROL,
1089				    CRTC_CURRENT_MASTER_EN_STATE);
1090
1091	return field == 1;
1092}
1093
1094static bool dce120_configure_crc(struct timing_generator *tg,
1095				 const struct crc_params *params)
1096{
1097	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1098
1099	/* Cannot configure crc on a CRTC that is disabled */
1100	if (!dce120_is_tg_enabled(tg))
1101		return false;
1102
1103	if (!params->enable || params->reset)
1104		/* First, disable CRC before we configure it. */
1105		dm_write_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC_CNTL,
1106				   tg110->offsets.crtc, 0);
1107
1108	if (!params->enable)
1109		return true;
1110
1111	/* Program frame boundaries */
1112	switch (params->crc_eng_inst) {
1113	case 0:
1114		/* Window A x axis start and end. */
1115		CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWA_X_CONTROL,
1116				  CRTC_CRC0_WINDOWA_X_START, params->windowa_x_start,
1117				  CRTC_CRC0_WINDOWA_X_END, params->windowa_x_end);
1118
1119		/* Window A y axis start and end. */
1120		CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWA_Y_CONTROL,
1121				  CRTC_CRC0_WINDOWA_Y_START, params->windowa_y_start,
1122				  CRTC_CRC0_WINDOWA_Y_END, params->windowa_y_end);
1123
1124		/* Window B x axis start and end. */
1125		CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWB_X_CONTROL,
1126				  CRTC_CRC0_WINDOWB_X_START, params->windowb_x_start,
1127				  CRTC_CRC0_WINDOWB_X_END, params->windowb_x_end);
1128
1129		/* Window B y axis start and end. */
1130		CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWB_Y_CONTROL,
1131				  CRTC_CRC0_WINDOWB_Y_START, params->windowb_y_start,
1132				  CRTC_CRC0_WINDOWB_Y_END, params->windowb_y_end);
1133
1134		/* Set crc mode and selection, and enable.*/
1135		CRTC_REG_UPDATE_3(CRTC0_CRTC_CRC_CNTL,
1136				  CRTC_CRC_CONT_EN, params->continuous_mode ? 1 : 0,
1137				  CRTC_CRC0_SELECT, params->selection,
1138				  CRTC_CRC_EN, 1);
1139		break;
1140	case 1:
1141		/* Window A x axis start and end. */
1142		CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC1_WINDOWA_X_CONTROL,
1143				  CRTC_CRC1_WINDOWA_X_START, params->windowa_x_start,
1144				  CRTC_CRC1_WINDOWA_X_END, params->windowa_x_end);
1145
1146		/* Window A y axis start and end. */
1147		CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC1_WINDOWA_Y_CONTROL,
1148				  CRTC_CRC1_WINDOWA_Y_START, params->windowa_y_start,
1149				  CRTC_CRC1_WINDOWA_Y_END, params->windowa_y_end);
1150
1151		/* Window B x axis start and end. */
1152		CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC1_WINDOWB_X_CONTROL,
1153				  CRTC_CRC1_WINDOWB_X_START, params->windowb_x_start,
1154				  CRTC_CRC1_WINDOWB_X_END, params->windowb_x_end);
1155
1156		/* Window B y axis start and end. */
1157		CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC1_WINDOWB_Y_CONTROL,
1158				  CRTC_CRC1_WINDOWB_Y_START, params->windowb_y_start,
1159				  CRTC_CRC1_WINDOWB_Y_END, params->windowb_y_end);
1160
1161		/* Set crc mode and selection, and enable */
1162		CRTC_REG_UPDATE_3(CRTC0_CRTC_CRC_CNTL,
1163				  CRTC_CRC_CONT_EN, params->continuous_mode ? 1 : 0,
1164				  CRTC_CRC1_SELECT, params->selection,
1165				  CRTC_CRC_EN, 1);
1166		break;
1167	default:
1168		return false;
1169	}
1170
1171	return true;
1172}
1173
1174static bool dce120_get_crc(struct timing_generator *tg, uint8_t idx,
1175			uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb)
1176{
1177	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1178	uint32_t value, field;
1179
1180	value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC_CNTL,
1181				  tg110->offsets.crtc);
1182	field = get_reg_field_value(value, CRTC0_CRTC_CRC_CNTL, CRTC_CRC_EN);
1183
1184	/* Early return if CRC is not enabled for this CRTC */
1185	if (!field)
1186		return false;
1187
1188	switch (idx) {
1189	case 0:
1190		value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC0_DATA_RG,
1191					  tg110->offsets.crtc);
1192		*r_cr = get_reg_field_value(value, CRTC0_CRTC_CRC0_DATA_RG, CRC0_R_CR);
1193		*g_y = get_reg_field_value(value, CRTC0_CRTC_CRC0_DATA_RG, CRC0_G_Y);
1194
1195		value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC0_DATA_B,
1196					  tg110->offsets.crtc);
1197		*b_cb = get_reg_field_value(value, CRTC0_CRTC_CRC0_DATA_B, CRC0_B_CB);
1198		break;
1199	case 1:
1200		value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC1_DATA_RG,
1201					  tg110->offsets.crtc);
1202		*r_cr = get_reg_field_value(value, CRTC0_CRTC_CRC1_DATA_RG, CRC1_R_CR);
1203		*g_y = get_reg_field_value(value, CRTC0_CRTC_CRC1_DATA_RG, CRC1_G_Y);
1204
1205		value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC1_DATA_B,
1206					  tg110->offsets.crtc);
1207		*b_cb = get_reg_field_value(value, CRTC0_CRTC_CRC1_DATA_B, CRC1_B_CB);
1208		break;
1209	default:
1210		return false;
1211	}
1212
1213	return true;
1214}
1215
1216static const struct timing_generator_funcs dce120_tg_funcs = {
1217		.validate_timing = dce120_tg_validate_timing,
1218		.program_timing = dce120_tg_program_timing,
1219		.enable_crtc = dce120_timing_generator_enable_crtc,
1220		.disable_crtc = dce110_timing_generator_disable_crtc,
1221		/* used by enable_timing_synchronization. Not need for FPGA */
1222		.is_counter_moving = dce110_timing_generator_is_counter_moving,
1223		/* never be called */
1224		.get_position = dce120_timing_generator_get_crtc_position,
1225		.get_frame_count = dce120_timing_generator_get_vblank_counter,
1226		.get_scanoutpos = dce120_timing_generator_get_crtc_scanoutpos,
1227		.set_early_control = dce120_timing_generator_set_early_control,
1228		/* used by enable_timing_synchronization. Not need for FPGA */
1229		.wait_for_state = dce120_tg_wait_for_state,
1230		.set_blank = dce120_tg_set_blank,
1231		.is_blanked = dce120_tg_is_blanked,
1232		/* never be called */
1233		.set_colors = dce120_tg_set_colors,
1234		.set_overscan_blank_color = dce120_timing_generator_set_overscan_color_black,
1235		.set_blank_color = dce120_timing_generator_program_blank_color,
1236		.disable_vga = dce120_timing_generator_disable_vga,
1237		.did_triggered_reset_occur = dce120_timing_generator_did_triggered_reset_occur,
1238		.setup_global_swap_lock = dce120_timing_generator_setup_global_swap_lock,
1239		.enable_reset_trigger = dce120_timing_generator_enable_reset_trigger,
1240		.disable_reset_trigger = dce120_timing_generator_disable_reset_trigger,
1241		.tear_down_global_swap_lock = dce120_timing_generator_tear_down_global_swap_lock,
1242		.enable_advanced_request = dce120_timing_generator_enable_advanced_request,
1243		.set_drr = dce120_timing_generator_set_drr,
1244		.get_last_used_drr_vtotal = NULL,
1245		.set_static_screen_control = dce120_timing_generator_set_static_screen_control,
1246		.set_test_pattern = dce120_timing_generator_set_test_pattern,
1247		.arm_vert_intr = dce120_arm_vert_intr,
1248		.is_tg_enabled = dce120_is_tg_enabled,
1249		.configure_crc = dce120_configure_crc,
1250		.get_crc = dce120_get_crc,
1251		.is_two_pixels_per_container = dce110_is_two_pixels_per_container,
1252};
1253
1254
1255void dce120_timing_generator_construct(
1256	struct dce110_timing_generator *tg110,
1257	struct dc_context *ctx,
1258	uint32_t instance,
1259	const struct dce110_timing_generator_offsets *offsets)
1260{
1261	tg110->controller_id = CONTROLLER_ID_D0 + instance;
1262	tg110->base.inst = instance;
1263
1264	tg110->offsets = *offsets;
1265
1266	tg110->base.funcs = &dce120_tg_funcs;
1267
1268	tg110->base.ctx = ctx;
1269	tg110->base.bp = ctx->dc_bios;
1270
1271	tg110->max_h_total = CRTC0_CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1;
1272	tg110->max_v_total = CRTC0_CRTC_V_TOTAL__CRTC_V_TOTAL_MASK + 1;
1273
1274	/*//CRTC requires a minimum HBLANK = 32 pixels and o
1275	 * Minimum HSYNC = 8 pixels*/
1276	tg110->min_h_blank = 32;
1277	/*DCE12_CRTC_Block_ARch.doc*/
1278	tg110->min_h_front_porch = 0;
1279	tg110->min_h_back_porch = 0;
1280
1281	tg110->min_h_sync_width = 4;
1282	tg110->min_v_sync_width = 1;
1283	tg110->min_v_blank = 3;
1284}
~/ Read-only file preview.