Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.9.4.
   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
  27#include "reg_helper.h"
  28#include "dcn10_optc.h"
  29#include "dc.h"
  30
  31#define REG(reg)\
  32	optc1->tg_regs->reg
  33
  34#define CTX \
  35	optc1->base.ctx
  36
  37#undef FN
  38#define FN(reg_name, field_name) \
  39	optc1->tg_shift->field_name, optc1->tg_mask->field_name
  40
  41#define STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN 0x100
  42
  43/**
  44* apply_front_porch_workaround  TODO FPGA still need?
  45*
  46* This is a workaround for a bug that has existed since R5xx and has not been
  47* fixed keep Front porch at minimum 2 for Interlaced mode or 1 for progressive.
  48*/
  49static void optc1_apply_front_porch_workaround(
  50	struct timing_generator *optc,
  51	struct dc_crtc_timing *timing)
  52{
  53	if (timing->flags.INTERLACE == 1) {
  54		if (timing->v_front_porch < 2)
  55			timing->v_front_porch = 2;
  56	} else {
  57		if (timing->v_front_porch < 1)
  58			timing->v_front_porch = 1;
  59	}
  60}
  61
  62void optc1_program_global_sync(
  63		struct timing_generator *optc)
  64{
  65	struct optc *optc1 = DCN10TG_FROM_TG(optc);
  66
  67	if (optc->dlg_otg_param.vstartup_start == 0) {
  68		BREAK_TO_DEBUGGER();
  69		return;
  70	}
  71
  72	REG_SET(OTG_VSTARTUP_PARAM, 0,
  73		VSTARTUP_START, optc->dlg_otg_param.vstartup_start);
  74
  75	REG_SET_2(OTG_VUPDATE_PARAM, 0,
  76			VUPDATE_OFFSET, optc->dlg_otg_param.vupdate_offset,
  77			VUPDATE_WIDTH, optc->dlg_otg_param.vupdate_width);
  78
  79	REG_SET(OTG_VREADY_PARAM, 0,
  80			VREADY_OFFSET, optc->dlg_otg_param.vready_offset);
  81}
  82
  83static void optc1_disable_stereo(struct timing_generator *optc)
  84{
  85	struct optc *optc1 = DCN10TG_FROM_TG(optc);
  86
  87	REG_SET(OTG_STEREO_CONTROL, 0,
  88		OTG_STEREO_EN, 0);
  89
  90	REG_SET_3(OTG_3D_STRUCTURE_CONTROL, 0,
  91		OTG_3D_STRUCTURE_EN, 0,
  92		OTG_3D_STRUCTURE_V_UPDATE_MODE, 0,
  93		OTG_3D_STRUCTURE_STEREO_SEL_OVR, 0);
  94}
  95
  96/**
  97 * program_timing_generator   used by mode timing set
  98 * Program CRTC Timing Registers - OTG_H_*, OTG_V_*, Pixel repetition.
  99 * Including SYNC. Call BIOS command table to program Timings.
 100 */
 101void optc1_program_timing(
 102	struct timing_generator *optc,
 103	const struct dc_crtc_timing *dc_crtc_timing,
 104	bool use_vbios)
 105{
 106	struct dc_crtc_timing patched_crtc_timing;
 107	uint32_t vesa_sync_start;
 108	uint32_t asic_blank_end;
 109	uint32_t asic_blank_start;
 110	uint32_t v_total;
 111	uint32_t v_sync_end;
 112	uint32_t v_init, v_fp2;
 113	uint32_t h_sync_polarity, v_sync_polarity;
 114	uint32_t interlace_factor;
 115	uint32_t start_point = 0;
 116	uint32_t field_num = 0;
 117	uint32_t h_div_2;
 118	int32_t vertical_line_start;
 119
 120	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 121
 122	patched_crtc_timing = *dc_crtc_timing;
 123	optc1_apply_front_porch_workaround(optc, &patched_crtc_timing);
 124
 125	/* Load horizontal timing */
 126
 127	/* CRTC_H_TOTAL = vesa.h_total - 1 */
 128	REG_SET(OTG_H_TOTAL, 0,
 129			OTG_H_TOTAL,  patched_crtc_timing.h_total - 1);
 130
 131	/* h_sync_start = 0, h_sync_end = vesa.h_sync_width */
 132	REG_UPDATE_2(OTG_H_SYNC_A,
 133			OTG_H_SYNC_A_START, 0,
 134			OTG_H_SYNC_A_END, patched_crtc_timing.h_sync_width);
 135
 136	/* asic_h_blank_end = HsyncWidth + HbackPorch =
 137	 * vesa. usHorizontalTotal - vesa. usHorizontalSyncStart -
 138	 * vesa.h_left_border
 139	 */
 140	vesa_sync_start = patched_crtc_timing.h_addressable +
 141			patched_crtc_timing.h_border_right +
 142			patched_crtc_timing.h_front_porch;
 143
 144	asic_blank_end = patched_crtc_timing.h_total -
 145			vesa_sync_start -
 146			patched_crtc_timing.h_border_left;
 147
 148	/* h_blank_start = v_blank_end + v_active */
 149	asic_blank_start = asic_blank_end +
 150			patched_crtc_timing.h_border_left +
 151			patched_crtc_timing.h_addressable +
 152			patched_crtc_timing.h_border_right;
 153
 154	REG_UPDATE_2(OTG_H_BLANK_START_END,
 155			OTG_H_BLANK_START, asic_blank_start,
 156			OTG_H_BLANK_END, asic_blank_end);
 157
 158	/* h_sync polarity */
 159	h_sync_polarity = patched_crtc_timing.flags.HSYNC_POSITIVE_POLARITY ?
 160			0 : 1;
 161
 162	REG_UPDATE(OTG_H_SYNC_A_CNTL,
 163			OTG_H_SYNC_A_POL, h_sync_polarity);
 164
 165	/* Load vertical timing */
 166
 167	/* CRTC_V_TOTAL = v_total - 1 */
 168	if (patched_crtc_timing.flags.INTERLACE) {
 169		interlace_factor = 2;
 170		v_total = 2 * patched_crtc_timing.v_total;
 171	} else {
 172		interlace_factor = 1;
 173		v_total = patched_crtc_timing.v_total - 1;
 174	}
 175	REG_SET(OTG_V_TOTAL, 0,
 176			OTG_V_TOTAL, v_total);
 177
 178	/* In case of V_TOTAL_CONTROL is on, make sure OTG_V_TOTAL_MAX and
 179	 * OTG_V_TOTAL_MIN are equal to V_TOTAL.
 180	 */
 181	REG_SET(OTG_V_TOTAL_MAX, 0,
 182		OTG_V_TOTAL_MAX, v_total);
 183	REG_SET(OTG_V_TOTAL_MIN, 0,
 184		OTG_V_TOTAL_MIN, v_total);
 185
 186	/* v_sync_start = 0, v_sync_end = v_sync_width */
 187	v_sync_end = patched_crtc_timing.v_sync_width * interlace_factor;
 188
 189	REG_UPDATE_2(OTG_V_SYNC_A,
 190			OTG_V_SYNC_A_START, 0,
 191			OTG_V_SYNC_A_END, v_sync_end);
 192
 193	vesa_sync_start = patched_crtc_timing.v_addressable +
 194			patched_crtc_timing.v_border_bottom +
 195			patched_crtc_timing.v_front_porch;
 196
 197	asic_blank_end = (patched_crtc_timing.v_total -
 198			vesa_sync_start -
 199			patched_crtc_timing.v_border_top)
 200			* interlace_factor;
 201
 202	/* v_blank_start = v_blank_end + v_active */
 203	asic_blank_start = asic_blank_end +
 204			(patched_crtc_timing.v_border_top +
 205			patched_crtc_timing.v_addressable +
 206			patched_crtc_timing.v_border_bottom)
 207			* interlace_factor;
 208
 209	REG_UPDATE_2(OTG_V_BLANK_START_END,
 210			OTG_V_BLANK_START, asic_blank_start,
 211			OTG_V_BLANK_END, asic_blank_end);
 212
 213	/* Use OTG_VERTICAL_INTERRUPT2 replace VUPDATE interrupt,
 214	 * program the reg for interrupt postition.
 215	 */
 216	vertical_line_start = asic_blank_end - optc->dlg_otg_param.vstartup_start + 1;
 217	if (vertical_line_start < 0) {
 218		ASSERT(0);
 219		vertical_line_start = 0;
 220	}
 221	REG_SET(OTG_VERTICAL_INTERRUPT2_POSITION, 0,
 222			OTG_VERTICAL_INTERRUPT2_LINE_START, vertical_line_start);
 223
 224	/* v_sync polarity */
 225	v_sync_polarity = patched_crtc_timing.flags.VSYNC_POSITIVE_POLARITY ?
 226			0 : 1;
 227
 228	REG_UPDATE(OTG_V_SYNC_A_CNTL,
 229			OTG_V_SYNC_A_POL, v_sync_polarity);
 230
 231	v_init = asic_blank_start;
 232	if (optc->dlg_otg_param.signal == SIGNAL_TYPE_DISPLAY_PORT ||
 233		optc->dlg_otg_param.signal == SIGNAL_TYPE_DISPLAY_PORT_MST ||
 234		optc->dlg_otg_param.signal == SIGNAL_TYPE_EDP) {
 235		start_point = 1;
 236		if (patched_crtc_timing.flags.INTERLACE == 1)
 237			field_num = 1;
 238	}
 239	v_fp2 = 0;
 240	if (optc->dlg_otg_param.vstartup_start > asic_blank_end)
 241		v_fp2 = optc->dlg_otg_param.vstartup_start > asic_blank_end;
 242
 243	/* Interlace */
 244	if (patched_crtc_timing.flags.INTERLACE == 1) {
 245		REG_UPDATE(OTG_INTERLACE_CONTROL,
 246				OTG_INTERLACE_ENABLE, 1);
 247		v_init = v_init / 2;
 248		if ((optc->dlg_otg_param.vstartup_start/2)*2 > asic_blank_end)
 249			v_fp2 = v_fp2 / 2;
 250	} else
 251		REG_UPDATE(OTG_INTERLACE_CONTROL,
 252				OTG_INTERLACE_ENABLE, 0);
 253
 254
 255	/* VTG enable set to 0 first VInit */
 256	REG_UPDATE(CONTROL,
 257			VTG0_ENABLE, 0);
 258
 259	REG_UPDATE_2(CONTROL,
 260			VTG0_FP2, v_fp2,
 261			VTG0_VCOUNT_INIT, v_init);
 262
 263	/* original code is using VTG offset to address OTG reg, seems wrong */
 264	REG_UPDATE_2(OTG_CONTROL,
 265			OTG_START_POINT_CNTL, start_point,
 266			OTG_FIELD_NUMBER_CNTL, field_num);
 267
 268	optc1_program_global_sync(optc);
 269
 270	/* TODO
 271	 * patched_crtc_timing.flags.HORZ_COUNT_BY_TWO == 1
 272	 * program_horz_count_by_2
 273	 * for DVI 30bpp mode, 0 otherwise
 274	 * program_horz_count_by_2(optc, &patched_crtc_timing);
 275	 */
 276
 277	/* Enable stereo - only when we need to pack 3D frame. Other types
 278	 * of stereo handled in explicit call
 279	 */
 280	h_div_2 = (dc_crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) ?
 281			1 : 0;
 282
 283	REG_UPDATE(OTG_H_TIMING_CNTL,
 284			OTG_H_TIMING_DIV_BY2, h_div_2);
 285
 286}
 287
 288static void optc1_set_blank_data_double_buffer(struct timing_generator *optc, bool enable)
 289{
 290	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 291
 292	uint32_t blank_data_double_buffer_enable = enable ? 1 : 0;
 293
 294	REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL,
 295			OTG_BLANK_DATA_DOUBLE_BUFFER_EN, blank_data_double_buffer_enable);
 296}
 297
 298/**
 299 * unblank_crtc
 300 * Call ASIC Control Object to UnBlank CRTC.
 301 */
 302static void optc1_unblank_crtc(struct timing_generator *optc)
 303{
 304	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 305	uint32_t vertical_interrupt_enable = 0;
 306
 307	REG_GET(OTG_VERTICAL_INTERRUPT2_CONTROL,
 308			OTG_VERTICAL_INTERRUPT2_INT_ENABLE, &vertical_interrupt_enable);
 309
 310	/* temporary work around for vertical interrupt, once vertical interrupt enabled,
 311	 * this check will be removed.
 312	 */
 313	if (vertical_interrupt_enable)
 314		optc1_set_blank_data_double_buffer(optc, true);
 315
 316	REG_UPDATE_2(OTG_BLANK_CONTROL,
 317			OTG_BLANK_DATA_EN, 0,
 318			OTG_BLANK_DE_MODE, 0);
 319}
 320
 321/**
 322 * blank_crtc
 323 * Call ASIC Control Object to Blank CRTC.
 324 */
 325
 326static void optc1_blank_crtc(struct timing_generator *optc)
 327{
 328	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 329
 330	REG_UPDATE_2(OTG_BLANK_CONTROL,
 331			OTG_BLANK_DATA_EN, 1,
 332			OTG_BLANK_DE_MODE, 0);
 333
 334	optc1_set_blank_data_double_buffer(optc, false);
 335}
 336
 337void optc1_set_blank(struct timing_generator *optc,
 338		bool enable_blanking)
 339{
 340	if (enable_blanking)
 341		optc1_blank_crtc(optc);
 342	else
 343		optc1_unblank_crtc(optc);
 344}
 345
 346bool optc1_is_blanked(struct timing_generator *optc)
 347{
 348	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 349	uint32_t blank_en;
 350	uint32_t blank_state;
 351
 352	REG_GET_2(OTG_BLANK_CONTROL,
 353			OTG_BLANK_DATA_EN, &blank_en,
 354			OTG_CURRENT_BLANK_STATE, &blank_state);
 355
 356	return blank_en && blank_state;
 357}
 358
 359void optc1_enable_optc_clock(struct timing_generator *optc, bool enable)
 360{
 361	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 362
 363	if (enable) {
 364		REG_UPDATE_2(OPTC_INPUT_CLOCK_CONTROL,
 365				OPTC_INPUT_CLK_EN, 1,
 366				OPTC_INPUT_CLK_GATE_DIS, 1);
 367
 368		REG_WAIT(OPTC_INPUT_CLOCK_CONTROL,
 369				OPTC_INPUT_CLK_ON, 1,
 370				1, 1000);
 371
 372		/* Enable clock */
 373		REG_UPDATE_2(OTG_CLOCK_CONTROL,
 374				OTG_CLOCK_EN, 1,
 375				OTG_CLOCK_GATE_DIS, 1);
 376		REG_WAIT(OTG_CLOCK_CONTROL,
 377				OTG_CLOCK_ON, 1,
 378				1, 1000);
 379	} else  {
 380		REG_UPDATE_2(OTG_CLOCK_CONTROL,
 381				OTG_CLOCK_GATE_DIS, 0,
 382				OTG_CLOCK_EN, 0);
 383
 384		REG_UPDATE_2(OPTC_INPUT_CLOCK_CONTROL,
 385				OPTC_INPUT_CLK_GATE_DIS, 0,
 386				OPTC_INPUT_CLK_EN, 0);
 387	}
 388}
 389
 390/**
 391 * Enable CRTC
 392 * Enable CRTC - call ASIC Control Object to enable Timing generator.
 393 */
 394static bool optc1_enable_crtc(struct timing_generator *optc)
 395{
 396	/* TODO FPGA wait for answer
 397	 * OTG_MASTER_UPDATE_MODE != CRTC_MASTER_UPDATE_MODE
 398	 * OTG_MASTER_UPDATE_LOCK != CRTC_MASTER_UPDATE_LOCK
 399	 */
 400	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 401
 402	/* opp instance for OTG. For DCN1.0, ODM is remoed.
 403	 * OPP and OPTC should 1:1 mapping
 404	 */
 405	REG_UPDATE(OPTC_DATA_SOURCE_SELECT,
 406			OPTC_SRC_SEL, optc->inst);
 407
 408	/* VTG enable first is for HW workaround */
 409	REG_UPDATE(CONTROL,
 410			VTG0_ENABLE, 1);
 411
 412	/* Enable CRTC */
 413	REG_UPDATE_2(OTG_CONTROL,
 414			OTG_DISABLE_POINT_CNTL, 3,
 415			OTG_MASTER_EN, 1);
 416
 417	return true;
 418}
 419
 420/* disable_crtc - call ASIC Control Object to disable Timing generator. */
 421bool optc1_disable_crtc(struct timing_generator *optc)
 422{
 423	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 424
 425	/* disable otg request until end of the first line
 426	 * in the vertical blank region
 427	 */
 428	REG_UPDATE_2(OTG_CONTROL,
 429			OTG_DISABLE_POINT_CNTL, 3,
 430			OTG_MASTER_EN, 0);
 431
 432	REG_UPDATE(CONTROL,
 433			VTG0_ENABLE, 0);
 434
 435	/* CRTC disabled, so disable  clock. */
 436	REG_WAIT(OTG_CLOCK_CONTROL,
 437			OTG_BUSY, 0,
 438			1, 100000);
 439
 440	return true;
 441}
 442
 443
 444void optc1_program_blank_color(
 445		struct timing_generator *optc,
 446		const struct tg_color *black_color)
 447{
 448	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 449
 450	REG_SET_3(OTG_BLACK_COLOR, 0,
 451			OTG_BLACK_COLOR_B_CB, black_color->color_b_cb,
 452			OTG_BLACK_COLOR_G_Y, black_color->color_g_y,
 453			OTG_BLACK_COLOR_R_CR, black_color->color_r_cr);
 454}
 455
 456bool optc1_validate_timing(
 457	struct timing_generator *optc,
 458	const struct dc_crtc_timing *timing)
 459{
 460	uint32_t interlace_factor;
 461	uint32_t v_blank;
 462	uint32_t h_blank;
 463	uint32_t min_v_blank;
 464	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 465
 466	ASSERT(timing != NULL);
 467
 468	interlace_factor = timing->flags.INTERLACE ? 2 : 1;
 469	v_blank = (timing->v_total - timing->v_addressable -
 470					timing->v_border_top - timing->v_border_bottom) *
 471					interlace_factor;
 472
 473	h_blank = (timing->h_total - timing->h_addressable -
 474		timing->h_border_right -
 475		timing->h_border_left);
 476
 477	if (timing->timing_3d_format != TIMING_3D_FORMAT_NONE &&
 478		timing->timing_3d_format != TIMING_3D_FORMAT_HW_FRAME_PACKING &&
 479		timing->timing_3d_format != TIMING_3D_FORMAT_TOP_AND_BOTTOM &&
 480		timing->timing_3d_format != TIMING_3D_FORMAT_SIDE_BY_SIDE &&
 481		timing->timing_3d_format != TIMING_3D_FORMAT_FRAME_ALTERNATE &&
 482		timing->timing_3d_format != TIMING_3D_FORMAT_INBAND_FA)
 483		return false;
 484
 485	/* Temporarily blocking interlacing mode until it's supported */
 486	if (timing->flags.INTERLACE == 1)
 487		return false;
 488
 489	/* Check maximum number of pixels supported by Timing Generator
 490	 * (Currently will never fail, in order to fail needs display which
 491	 * needs more than 8192 horizontal and
 492	 * more than 8192 vertical total pixels)
 493	 */
 494	if (timing->h_total > optc1->max_h_total ||
 495		timing->v_total > optc1->max_v_total)
 496		return false;
 497
 498
 499	if (h_blank < optc1->min_h_blank)
 500		return false;
 501
 502	if (timing->h_sync_width  < optc1->min_h_sync_width ||
 503		 timing->v_sync_width  < optc1->min_v_sync_width)
 504		return false;
 505
 506	min_v_blank = timing->flags.INTERLACE?optc1->min_v_blank_interlace:optc1->min_v_blank;
 507
 508	if (v_blank < min_v_blank)
 509		return false;
 510
 511	return true;
 512
 513}
 514
 515/*
 516 * get_vblank_counter
 517 *
 518 * @brief
 519 * Get counter for vertical blanks. use register CRTC_STATUS_FRAME_COUNT which
 520 * holds the counter of frames.
 521 *
 522 * @param
 523 * struct timing_generator *optc - [in] timing generator which controls the
 524 * desired CRTC
 525 *
 526 * @return
 527 * Counter of frames, which should equal to number of vblanks.
 528 */
 529uint32_t optc1_get_vblank_counter(struct timing_generator *optc)
 530{
 531	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 532	uint32_t frame_count;
 533
 534	REG_GET(OTG_STATUS_FRAME_COUNT,
 535		OTG_FRAME_COUNT, &frame_count);
 536
 537	return frame_count;
 538}
 539
 540void optc1_lock(struct timing_generator *optc)
 541{
 542	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 543
 544	REG_SET(OTG_GLOBAL_CONTROL0, 0,
 545			OTG_MASTER_UPDATE_LOCK_SEL, optc->inst);
 546	REG_SET(OTG_MASTER_UPDATE_LOCK, 0,
 547			OTG_MASTER_UPDATE_LOCK, 1);
 548
 549	/* Should be fast, status does not update on maximus */
 550	if (optc->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS)
 551		REG_WAIT(OTG_MASTER_UPDATE_LOCK,
 552				UPDATE_LOCK_STATUS, 1,
 553				1, 10);
 554}
 555
 556void optc1_unlock(struct timing_generator *optc)
 557{
 558	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 559
 560	REG_SET(OTG_MASTER_UPDATE_LOCK, 0,
 561			OTG_MASTER_UPDATE_LOCK, 0);
 562}
 563
 564void optc1_get_position(struct timing_generator *optc,
 565		struct crtc_position *position)
 566{
 567	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 568
 569	REG_GET_2(OTG_STATUS_POSITION,
 570			OTG_HORZ_COUNT, &position->horizontal_count,
 571			OTG_VERT_COUNT, &position->vertical_count);
 572
 573	REG_GET(OTG_NOM_VERT_POSITION,
 574			OTG_VERT_COUNT_NOM, &position->nominal_vcount);
 575}
 576
 577bool optc1_is_counter_moving(struct timing_generator *optc)
 578{
 579	struct crtc_position position1, position2;
 580
 581	optc->funcs->get_position(optc, &position1);
 582	optc->funcs->get_position(optc, &position2);
 583
 584	if (position1.horizontal_count == position2.horizontal_count &&
 585		position1.vertical_count == position2.vertical_count)
 586		return false;
 587	else
 588		return true;
 589}
 590
 591bool optc1_did_triggered_reset_occur(
 592	struct timing_generator *optc)
 593{
 594	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 595	uint32_t occurred_force, occurred_vsync;
 596
 597	REG_GET(OTG_FORCE_COUNT_NOW_CNTL,
 598		OTG_FORCE_COUNT_NOW_OCCURRED, &occurred_force);
 599
 600	REG_GET(OTG_VERT_SYNC_CONTROL,
 601		OTG_FORCE_VSYNC_NEXT_LINE_OCCURRED, &occurred_vsync);
 602
 603	return occurred_vsync != 0 || occurred_force != 0;
 604}
 605
 606void optc1_disable_reset_trigger(struct timing_generator *optc)
 607{
 608	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 609
 610	REG_WRITE(OTG_TRIGA_CNTL, 0);
 611
 612	REG_SET(OTG_FORCE_COUNT_NOW_CNTL, 0,
 613		OTG_FORCE_COUNT_NOW_CLEAR, 1);
 614
 615	REG_SET(OTG_VERT_SYNC_CONTROL, 0,
 616		OTG_FORCE_VSYNC_NEXT_LINE_CLEAR, 1);
 617}
 618
 619void optc1_enable_reset_trigger(struct timing_generator *optc, int source_tg_inst)
 620{
 621	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 622	uint32_t falling_edge;
 623
 624	REG_GET(OTG_V_SYNC_A_CNTL,
 625			OTG_V_SYNC_A_POL, &falling_edge);
 626
 627	if (falling_edge)
 628		REG_SET_3(OTG_TRIGA_CNTL, 0,
 629				/* vsync signal from selected OTG pipe based
 630				 * on OTG_TRIG_SOURCE_PIPE_SELECT setting
 631				 */
 632				OTG_TRIGA_SOURCE_SELECT, 20,
 633				OTG_TRIGA_SOURCE_PIPE_SELECT, source_tg_inst,
 634				/* always detect falling edge */
 635				OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, 1);
 636	else
 637		REG_SET_3(OTG_TRIGA_CNTL, 0,
 638				/* vsync signal from selected OTG pipe based
 639				 * on OTG_TRIG_SOURCE_PIPE_SELECT setting
 640				 */
 641				OTG_TRIGA_SOURCE_SELECT, 20,
 642				OTG_TRIGA_SOURCE_PIPE_SELECT, source_tg_inst,
 643				/* always detect rising edge */
 644				OTG_TRIGA_RISING_EDGE_DETECT_CNTL, 1);
 645
 646	REG_SET(OTG_FORCE_COUNT_NOW_CNTL, 0,
 647			/* force H count to H_TOTAL and V count to V_TOTAL in
 648			 * progressive mode and V_TOTAL-1 in interlaced mode
 649			 */
 650			OTG_FORCE_COUNT_NOW_MODE, 2);
 651}
 652
 653void optc1_enable_crtc_reset(
 654		struct timing_generator *optc,
 655		int source_tg_inst,
 656		struct crtc_trigger_info *crtc_tp)
 657{
 658	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 659	uint32_t falling_edge = 0;
 660	uint32_t rising_edge = 0;
 661
 662	switch (crtc_tp->event) {
 663
 664	case CRTC_EVENT_VSYNC_RISING:
 665		rising_edge = 1;
 666		break;
 667
 668	case CRTC_EVENT_VSYNC_FALLING:
 669		falling_edge = 1;
 670		break;
 671	}
 672
 673	REG_SET_4(OTG_TRIGA_CNTL, 0,
 674		 /* vsync signal from selected OTG pipe based
 675		  * on OTG_TRIG_SOURCE_PIPE_SELECT setting
 676		  */
 677		  OTG_TRIGA_SOURCE_SELECT, 20,
 678		  OTG_TRIGA_SOURCE_PIPE_SELECT, source_tg_inst,
 679		  /* always detect falling edge */
 680		  OTG_TRIGA_RISING_EDGE_DETECT_CNTL, rising_edge,
 681		  OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, falling_edge);
 682
 683	switch (crtc_tp->delay) {
 684	case TRIGGER_DELAY_NEXT_LINE:
 685		REG_SET(OTG_VERT_SYNC_CONTROL, 0,
 686				OTG_AUTO_FORCE_VSYNC_MODE, 1);
 687		break;
 688	case TRIGGER_DELAY_NEXT_PIXEL:
 689		REG_SET(OTG_FORCE_COUNT_NOW_CNTL, 0,
 690			/* force H count to H_TOTAL and V count to V_TOTAL in
 691			 * progressive mode and V_TOTAL-1 in interlaced mode
 692			 */
 693			OTG_FORCE_COUNT_NOW_MODE, 2);
 694		break;
 695	}
 696}
 697
 698void optc1_wait_for_state(struct timing_generator *optc,
 699		enum crtc_state state)
 700{
 701	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 702
 703	switch (state) {
 704	case CRTC_STATE_VBLANK:
 705		REG_WAIT(OTG_STATUS,
 706				OTG_V_BLANK, 1,
 707				1, 100000); /* 1 vupdate at 10hz */
 708		break;
 709
 710	case CRTC_STATE_VACTIVE:
 711		REG_WAIT(OTG_STATUS,
 712				OTG_V_ACTIVE_DISP, 1,
 713				1, 100000); /* 1 vupdate at 10hz */
 714		break;
 715
 716	default:
 717		break;
 718	}
 719}
 720
 721void optc1_set_early_control(
 722	struct timing_generator *optc,
 723	uint32_t early_cntl)
 724{
 725	/* asic design change, do not need this control
 726	 * empty for share caller logic
 727	 */
 728}
 729
 730
 731void optc1_set_static_screen_control(
 732	struct timing_generator *optc,
 733	uint32_t value)
 734{
 735	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 736
 737	/* Bit 8 is no longer applicable in RV for PSR case,
 738	 * set bit 8 to 0 if given
 739	 */
 740	if ((value & STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN)
 741			!= 0)
 742		value = value &
 743		~STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN;
 744
 745	REG_SET_2(OTG_STATIC_SCREEN_CONTROL, 0,
 746			OTG_STATIC_SCREEN_EVENT_MASK, value,
 747			OTG_STATIC_SCREEN_FRAME_COUNT, 2);
 748}
 749
 750
 751/**
 752 *****************************************************************************
 753 *  Function: set_drr
 754 *
 755 *  @brief
 756 *     Program dynamic refresh rate registers m_OTGx_OTG_V_TOTAL_*.
 757 *
 758 *****************************************************************************
 759 */
 760void optc1_set_drr(
 761	struct timing_generator *optc,
 762	const struct drr_params *params)
 763{
 764	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 765
 766	if (params != NULL &&
 767		params->vertical_total_max > 0 &&
 768		params->vertical_total_min > 0) {
 769
 770		REG_SET(OTG_V_TOTAL_MAX, 0,
 771			OTG_V_TOTAL_MAX, params->vertical_total_max - 1);
 772
 773		REG_SET(OTG_V_TOTAL_MIN, 0,
 774			OTG_V_TOTAL_MIN, params->vertical_total_min - 1);
 775
 776		REG_UPDATE_5(OTG_V_TOTAL_CONTROL,
 777				OTG_V_TOTAL_MIN_SEL, 1,
 778				OTG_V_TOTAL_MAX_SEL, 1,
 779				OTG_FORCE_LOCK_ON_EVENT, 0,
 780				OTG_SET_V_TOTAL_MIN_MASK_EN, 0,
 781				OTG_SET_V_TOTAL_MIN_MASK, 0);
 782	} else {
 783		REG_SET(OTG_V_TOTAL_MIN, 0,
 784			OTG_V_TOTAL_MIN, 0);
 785
 786		REG_SET(OTG_V_TOTAL_MAX, 0,
 787			OTG_V_TOTAL_MAX, 0);
 788
 789		REG_UPDATE_4(OTG_V_TOTAL_CONTROL,
 790				OTG_SET_V_TOTAL_MIN_MASK, 0,
 791				OTG_V_TOTAL_MIN_SEL, 0,
 792				OTG_V_TOTAL_MAX_SEL, 0,
 793				OTG_FORCE_LOCK_ON_EVENT, 0);
 794	}
 795}
 796
 797static void optc1_set_test_pattern(
 798	struct timing_generator *optc,
 799	/* TODO: replace 'controller_dp_test_pattern' by 'test_pattern_mode'
 800	 * because this is not DP-specific (which is probably somewhere in DP
 801	 * encoder) */
 802	enum controller_dp_test_pattern test_pattern,
 803	enum dc_color_depth color_depth)
 804{
 805	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 806	enum test_pattern_color_format bit_depth;
 807	enum test_pattern_dyn_range dyn_range;
 808	enum test_pattern_mode mode;
 809	uint32_t pattern_mask;
 810	uint32_t pattern_data;
 811	/* color ramp generator mixes 16-bits color */
 812	uint32_t src_bpc = 16;
 813	/* requested bpc */
 814	uint32_t dst_bpc;
 815	uint32_t index;
 816	/* RGB values of the color bars.
 817	 * Produce two RGB colors: RGB0 - white (all Fs)
 818	 * and RGB1 - black (all 0s)
 819	 * (three RGB components for two colors)
 820	 */
 821	uint16_t src_color[6] = {0xFFFF, 0xFFFF, 0xFFFF, 0x0000,
 822						0x0000, 0x0000};
 823	/* dest color (converted to the specified color format) */
 824	uint16_t dst_color[6];
 825	uint32_t inc_base;
 826
 827	/* translate to bit depth */
 828	switch (color_depth) {
 829	case COLOR_DEPTH_666:
 830		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_6;
 831	break;
 832	case COLOR_DEPTH_888:
 833		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
 834	break;
 835	case COLOR_DEPTH_101010:
 836		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_10;
 837	break;
 838	case COLOR_DEPTH_121212:
 839		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_12;
 840	break;
 841	default:
 842		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
 843	break;
 844	}
 845
 846	switch (test_pattern) {
 847	case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES:
 848	case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA:
 849	{
 850		dyn_range = (test_pattern ==
 851				CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA ?
 852				TEST_PATTERN_DYN_RANGE_CEA :
 853				TEST_PATTERN_DYN_RANGE_VESA);
 854		mode = TEST_PATTERN_MODE_COLORSQUARES_RGB;
 855
 856		REG_UPDATE_2(OTG_TEST_PATTERN_PARAMETERS,
 857				OTG_TEST_PATTERN_VRES, 6,
 858				OTG_TEST_PATTERN_HRES, 6);
 859
 860		REG_UPDATE_4(OTG_TEST_PATTERN_CONTROL,
 861				OTG_TEST_PATTERN_EN, 1,
 862				OTG_TEST_PATTERN_MODE, mode,
 863				OTG_TEST_PATTERN_DYNAMIC_RANGE, dyn_range,
 864				OTG_TEST_PATTERN_COLOR_FORMAT, bit_depth);
 865	}
 866	break;
 867
 868	case CONTROLLER_DP_TEST_PATTERN_VERTICALBARS:
 869	case CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS:
 870	{
 871		mode = (test_pattern ==
 872			CONTROLLER_DP_TEST_PATTERN_VERTICALBARS ?
 873			TEST_PATTERN_MODE_VERTICALBARS :
 874			TEST_PATTERN_MODE_HORIZONTALBARS);
 875
 876		switch (bit_depth) {
 877		case TEST_PATTERN_COLOR_FORMAT_BPC_6:
 878			dst_bpc = 6;
 879		break;
 880		case TEST_PATTERN_COLOR_FORMAT_BPC_8:
 881			dst_bpc = 8;
 882		break;
 883		case TEST_PATTERN_COLOR_FORMAT_BPC_10:
 884			dst_bpc = 10;
 885		break;
 886		default:
 887			dst_bpc = 8;
 888		break;
 889		}
 890
 891		/* adjust color to the required colorFormat */
 892		for (index = 0; index < 6; index++) {
 893			/* dst = 2^dstBpc * src / 2^srcBpc = src >>
 894			 * (srcBpc - dstBpc);
 895			 */
 896			dst_color[index] =
 897				src_color[index] >> (src_bpc - dst_bpc);
 898		/* CRTC_TEST_PATTERN_DATA has 16 bits,
 899		 * lowest 6 are hardwired to ZERO
 900		 * color bits should be left aligned aligned to MSB
 901		 * XXXXXXXXXX000000 for 10 bit,
 902		 * XXXXXXXX00000000 for 8 bit and XXXXXX0000000000 for 6
 903		 */
 904			dst_color[index] <<= (16 - dst_bpc);
 905		}
 906
 907		REG_WRITE(OTG_TEST_PATTERN_PARAMETERS, 0);
 908
 909		/* We have to write the mask before data, similar to pipeline.
 910		 * For example, for 8 bpc, if we want RGB0 to be magenta,
 911		 * and RGB1 to be cyan,
 912		 * we need to make 7 writes:
 913		 * MASK   DATA
 914		 * 000001 00000000 00000000                     set mask to R0
 915		 * 000010 11111111 00000000     R0 255, 0xFF00, set mask to G0
 916		 * 000100 00000000 00000000     G0 0,   0x0000, set mask to B0
 917		 * 001000 11111111 00000000     B0 255, 0xFF00, set mask to R1
 918		 * 010000 00000000 00000000     R1 0,   0x0000, set mask to G1
 919		 * 100000 11111111 00000000     G1 255, 0xFF00, set mask to B1
 920		 * 100000 11111111 00000000     B1 255, 0xFF00
 921		 *
 922		 * we will make a loop of 6 in which we prepare the mask,
 923		 * then write, then prepare the color for next write.
 924		 * first iteration will write mask only,
 925		 * but each next iteration color prepared in
 926		 * previous iteration will be written within new mask,
 927		 * the last component will written separately,
 928		 * mask is not changing between 6th and 7th write
 929		 * and color will be prepared by last iteration
 930		 */
 931
 932		/* write color, color values mask in CRTC_TEST_PATTERN_MASK
 933		 * is B1, G1, R1, B0, G0, R0
 934		 */
 935		pattern_data = 0;
 936		for (index = 0; index < 6; index++) {
 937			/* prepare color mask, first write PATTERN_DATA
 938			 * will have all zeros
 939			 */
 940			pattern_mask = (1 << index);
 941
 942			/* write color component */
 943			REG_SET_2(OTG_TEST_PATTERN_COLOR, 0,
 944					OTG_TEST_PATTERN_MASK, pattern_mask,
 945					OTG_TEST_PATTERN_DATA, pattern_data);
 946
 947			/* prepare next color component,
 948			 * will be written in the next iteration
 949			 */
 950			pattern_data = dst_color[index];
 951		}
 952		/* write last color component,
 953		 * it's been already prepared in the loop
 954		 */
 955		REG_SET_2(OTG_TEST_PATTERN_COLOR, 0,
 956				OTG_TEST_PATTERN_MASK, pattern_mask,
 957				OTG_TEST_PATTERN_DATA, pattern_data);
 958
 959		/* enable test pattern */
 960		REG_UPDATE_4(OTG_TEST_PATTERN_CONTROL,
 961				OTG_TEST_PATTERN_EN, 1,
 962				OTG_TEST_PATTERN_MODE, mode,
 963				OTG_TEST_PATTERN_DYNAMIC_RANGE, 0,
 964				OTG_TEST_PATTERN_COLOR_FORMAT, bit_depth);
 965	}
 966	break;
 967
 968	case CONTROLLER_DP_TEST_PATTERN_COLORRAMP:
 969	{
 970		mode = (bit_depth ==
 971			TEST_PATTERN_COLOR_FORMAT_BPC_10 ?
 972			TEST_PATTERN_MODE_DUALRAMP_RGB :
 973			TEST_PATTERN_MODE_SINGLERAMP_RGB);
 974
 975		switch (bit_depth) {
 976		case TEST_PATTERN_COLOR_FORMAT_BPC_6:
 977			dst_bpc = 6;
 978		break;
 979		case TEST_PATTERN_COLOR_FORMAT_BPC_8:
 980			dst_bpc = 8;
 981		break;
 982		case TEST_PATTERN_COLOR_FORMAT_BPC_10:
 983			dst_bpc = 10;
 984		break;
 985		default:
 986			dst_bpc = 8;
 987		break;
 988		}
 989
 990		/* increment for the first ramp for one color gradation
 991		 * 1 gradation for 6-bit color is 2^10
 992		 * gradations in 16-bit color
 993		 */
 994		inc_base = (src_bpc - dst_bpc);
 995
 996		switch (bit_depth) {
 997		case TEST_PATTERN_COLOR_FORMAT_BPC_6:
 998		{
 999			REG_UPDATE_5(OTG_TEST_PATTERN_PARAMETERS,
1000					OTG_TEST_PATTERN_INC0, inc_base,
1001					OTG_TEST_PATTERN_INC1, 0,
1002					OTG_TEST_PATTERN_HRES, 6,
1003					OTG_TEST_PATTERN_VRES, 6,
1004					OTG_TEST_PATTERN_RAMP0_OFFSET, 0);
1005		}
1006		break;
1007		case TEST_PATTERN_COLOR_FORMAT_BPC_8:
1008		{
1009			REG_UPDATE_5(OTG_TEST_PATTERN_PARAMETERS,
1010					OTG_TEST_PATTERN_INC0, inc_base,
1011					OTG_TEST_PATTERN_INC1, 0,
1012					OTG_TEST_PATTERN_HRES, 8,
1013					OTG_TEST_PATTERN_VRES, 6,
1014					OTG_TEST_PATTERN_RAMP0_OFFSET, 0);
1015		}
1016		break;
1017		case TEST_PATTERN_COLOR_FORMAT_BPC_10:
1018		{
1019			REG_UPDATE_5(OTG_TEST_PATTERN_PARAMETERS,
1020					OTG_TEST_PATTERN_INC0, inc_base,
1021					OTG_TEST_PATTERN_INC1, inc_base + 2,
1022					OTG_TEST_PATTERN_HRES, 8,
1023					OTG_TEST_PATTERN_VRES, 5,
1024					OTG_TEST_PATTERN_RAMP0_OFFSET, 384 << 6);
1025		}
1026		break;
1027		default:
1028		break;
1029		}
1030
1031		REG_WRITE(OTG_TEST_PATTERN_COLOR, 0);
1032
1033		/* enable test pattern */
1034		REG_WRITE(OTG_TEST_PATTERN_CONTROL, 0);
1035
1036		REG_SET_4(OTG_TEST_PATTERN_CONTROL, 0,
1037				OTG_TEST_PATTERN_EN, 1,
1038				OTG_TEST_PATTERN_MODE, mode,
1039				OTG_TEST_PATTERN_DYNAMIC_RANGE, 0,
1040				OTG_TEST_PATTERN_COLOR_FORMAT, bit_depth);
1041	}
1042	break;
1043	case CONTROLLER_DP_TEST_PATTERN_VIDEOMODE:
1044	{
1045		REG_WRITE(OTG_TEST_PATTERN_CONTROL, 0);
1046		REG_WRITE(OTG_TEST_PATTERN_COLOR, 0);
1047		REG_WRITE(OTG_TEST_PATTERN_PARAMETERS, 0);
1048	}
1049	break;
1050	default:
1051		break;
1052
1053	}
1054}
1055
1056void optc1_get_crtc_scanoutpos(
1057	struct timing_generator *optc,
1058	uint32_t *v_blank_start,
1059	uint32_t *v_blank_end,
1060	uint32_t *h_position,
1061	uint32_t *v_position)
1062{
1063	struct optc *optc1 = DCN10TG_FROM_TG(optc);
1064	struct crtc_position position;
1065
1066	REG_GET_2(OTG_V_BLANK_START_END,
1067			OTG_V_BLANK_START, v_blank_start,
1068			OTG_V_BLANK_END, v_blank_end);
1069
1070	optc1_get_position(optc, &position);
1071
1072	*h_position = position.horizontal_count;
1073	*v_position = position.vertical_count;
1074}
1075
1076static void optc1_enable_stereo(struct timing_generator *optc,
1077	const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags)
1078{
1079	struct optc *optc1 = DCN10TG_FROM_TG(optc);
1080
1081	if (flags) {
1082		uint32_t stereo_en;
1083		stereo_en = flags->FRAME_PACKED == 0 ? 1 : 0;
1084
1085		if (flags->PROGRAM_STEREO)
1086			REG_UPDATE_3(OTG_STEREO_CONTROL,
1087				OTG_STEREO_EN, stereo_en,
1088				OTG_STEREO_SYNC_OUTPUT_LINE_NUM, 0,
1089				OTG_STEREO_SYNC_OUTPUT_POLARITY, 0);
1090
1091		if (flags->PROGRAM_POLARITY)
1092			REG_UPDATE(OTG_STEREO_CONTROL,
1093				OTG_STEREO_EYE_FLAG_POLARITY,
1094				flags->RIGHT_EYE_POLARITY == 0 ? 0 : 1);
1095
1096		if (flags->DISABLE_STEREO_DP_SYNC)
1097			REG_UPDATE(OTG_STEREO_CONTROL,
1098				OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, 1);
1099
1100		if (flags->PROGRAM_STEREO)
1101			REG_UPDATE_3(OTG_3D_STRUCTURE_CONTROL,
1102				OTG_3D_STRUCTURE_EN, flags->FRAME_PACKED,
1103				OTG_3D_STRUCTURE_V_UPDATE_MODE, flags->FRAME_PACKED,
1104				OTG_3D_STRUCTURE_STEREO_SEL_OVR, flags->FRAME_PACKED);
1105
1106	}
1107}
1108
1109void optc1_program_stereo(struct timing_generator *optc,
1110	const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags)
1111{
1112	if (flags->PROGRAM_STEREO)
1113		optc1_enable_stereo(optc, timing, flags);
1114	else
1115		optc1_disable_stereo(optc);
1116}
1117
1118
1119bool optc1_is_stereo_left_eye(struct timing_generator *optc)
1120{
1121	bool ret = false;
1122	uint32_t left_eye = 0;
1123	struct optc *optc1 = DCN10TG_FROM_TG(optc);
1124
1125	REG_GET(OTG_STEREO_STATUS,
1126		OTG_STEREO_CURRENT_EYE, &left_eye);
1127	if (left_eye == 1)
1128		ret = true;
1129	else
1130		ret = false;
1131
1132	return ret;
1133}
1134
1135void optc1_read_otg_state(struct optc *optc1,
1136		struct dcn_otg_state *s)
1137{
1138	REG_GET(OTG_CONTROL,
1139			OTG_MASTER_EN, &s->otg_enabled);
1140
1141	REG_GET_2(OTG_V_BLANK_START_END,
1142			OTG_V_BLANK_START, &s->v_blank_start,
1143			OTG_V_BLANK_END, &s->v_blank_end);
1144
1145	REG_GET(OTG_V_SYNC_A_CNTL,
1146			OTG_V_SYNC_A_POL, &s->v_sync_a_pol);
1147
1148	REG_GET(OTG_V_TOTAL,
1149			OTG_V_TOTAL, &s->v_total);
1150
1151	REG_GET(OTG_V_TOTAL_MAX,
1152			OTG_V_TOTAL_MAX, &s->v_total_max);
1153
1154	REG_GET(OTG_V_TOTAL_MIN,
1155			OTG_V_TOTAL_MIN, &s->v_total_min);
1156
1157	REG_GET_2(OTG_V_SYNC_A,
1158			OTG_V_SYNC_A_START, &s->v_sync_a_start,
1159			OTG_V_SYNC_A_END, &s->v_sync_a_end);
1160
1161	REG_GET_2(OTG_H_BLANK_START_END,
1162			OTG_H_BLANK_START, &s->h_blank_start,
1163			OTG_H_BLANK_END, &s->h_blank_end);
1164
1165	REG_GET_2(OTG_H_SYNC_A,
1166			OTG_H_SYNC_A_START, &s->h_sync_a_start,
1167			OTG_H_SYNC_A_END, &s->h_sync_a_end);
1168
1169	REG_GET(OTG_H_SYNC_A_CNTL,
1170			OTG_H_SYNC_A_POL, &s->h_sync_a_pol);
1171
1172	REG_GET(OTG_H_TOTAL,
1173			OTG_H_TOTAL, &s->h_total);
1174
1175	REG_GET(OPTC_INPUT_GLOBAL_CONTROL,
1176			OPTC_UNDERFLOW_OCCURRED_STATUS, &s->underflow_occurred_status);
1177}
1178
1179static void optc1_clear_optc_underflow(struct timing_generator *optc)
1180{
1181	struct optc *optc1 = DCN10TG_FROM_TG(optc);
1182
1183	REG_UPDATE(OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_CLEAR, 1);
1184}
1185
1186static void optc1_tg_init(struct timing_generator *optc)
1187{
1188	optc1_set_blank_data_double_buffer(optc, true);
1189	optc1_clear_optc_underflow(optc);
1190}
1191
1192static bool optc1_is_tg_enabled(struct timing_generator *optc)
1193{
1194	struct optc *optc1 = DCN10TG_FROM_TG(optc);
1195	uint32_t otg_enabled = 0;
1196
1197	REG_GET(OTG_CONTROL, OTG_MASTER_EN, &otg_enabled);
1198
1199	return (otg_enabled != 0);
1200
1201}
1202
1203static bool optc1_is_optc_underflow_occurred(struct timing_generator *optc)
1204{
1205	struct optc *optc1 = DCN10TG_FROM_TG(optc);
1206	uint32_t underflow_occurred = 0;
1207
1208	REG_GET(OPTC_INPUT_GLOBAL_CONTROL,
1209			OPTC_UNDERFLOW_OCCURRED_STATUS,
1210			&underflow_occurred);
1211
1212	return (underflow_occurred == 1);
1213}
1214
1215static const struct timing_generator_funcs dcn10_tg_funcs = {
1216		.validate_timing = optc1_validate_timing,
1217		.program_timing = optc1_program_timing,
1218		.program_global_sync = optc1_program_global_sync,
1219		.enable_crtc = optc1_enable_crtc,
1220		.disable_crtc = optc1_disable_crtc,
1221		/* used by enable_timing_synchronization. Not need for FPGA */
1222		.is_counter_moving = optc1_is_counter_moving,
1223		.get_position = optc1_get_position,
1224		.get_frame_count = optc1_get_vblank_counter,
1225		.get_scanoutpos = optc1_get_crtc_scanoutpos,
1226		.set_early_control = optc1_set_early_control,
1227		/* used by enable_timing_synchronization. Not need for FPGA */
1228		.wait_for_state = optc1_wait_for_state,
1229		.set_blank = optc1_set_blank,
1230		.is_blanked = optc1_is_blanked,
1231		.set_blank_color = optc1_program_blank_color,
1232		.did_triggered_reset_occur = optc1_did_triggered_reset_occur,
1233		.enable_reset_trigger = optc1_enable_reset_trigger,
1234		.enable_crtc_reset = optc1_enable_crtc_reset,
1235		.disable_reset_trigger = optc1_disable_reset_trigger,
1236		.lock = optc1_lock,
1237		.unlock = optc1_unlock,
1238		.enable_optc_clock = optc1_enable_optc_clock,
1239		.set_drr = optc1_set_drr,
1240		.set_static_screen_control = optc1_set_static_screen_control,
1241		.set_test_pattern = optc1_set_test_pattern,
1242		.program_stereo = optc1_program_stereo,
1243		.is_stereo_left_eye = optc1_is_stereo_left_eye,
1244		.set_blank_data_double_buffer = optc1_set_blank_data_double_buffer,
1245		.tg_init = optc1_tg_init,
1246		.is_tg_enabled = optc1_is_tg_enabled,
1247		.is_optc_underflow_occurred = optc1_is_optc_underflow_occurred,
1248		.clear_optc_underflow = optc1_clear_optc_underflow,
1249};
1250
1251void dcn10_timing_generator_init(struct optc *optc1)
1252{
1253	optc1->base.funcs = &dcn10_tg_funcs;
1254
1255	optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1;
1256	optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1;
1257
1258	optc1->min_h_blank = 32;
1259	optc1->min_v_blank = 3;
1260	optc1->min_v_blank_interlace = 5;
1261	optc1->min_h_sync_width = 8;
1262	optc1->min_v_sync_width = 1;
1263}