File Index
Files and directories
Sign in
FILE

dcn10_optc.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.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
  27#include "reg_helper.h"
  28#include "dcn10_optc.h"
  29#include "dc.h"
  30#include "dc_trace.h"
  31
  32#define REG(reg)\
  33	optc1->tg_regs->reg
  34
  35#define CTX \
  36	optc1->base.ctx
  37
  38#undef FN
  39#define FN(reg_name, field_name) \
  40	optc1->tg_shift->field_name, optc1->tg_mask->field_name
  41
  42#define STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN 0x100
  43
  44/**
  45 * apply_front_porch_workaround() - This is a workaround for a bug that has
  46 *                                  existed since R5xx and has not been fixed
  47 *                                  keep Front porch at minimum 2 for Interlaced
  48 *                                  mode or 1 for progressive.
  49 *
  50 * @timing: Timing parameters used to configure DCN blocks.
  51 */
  52static void apply_front_porch_workaround(struct dc_crtc_timing *timing)
  53{
  54	if (timing->flags.INTERLACE == 1) {
  55		if (timing->v_front_porch < 2)
  56			timing->v_front_porch = 2;
  57	} else {
  58		if (timing->v_front_porch < 1)
  59			timing->v_front_porch = 1;
  60	}
  61}
  62
  63void optc1_program_global_sync(
  64		struct timing_generator *optc,
  65		int vready_offset,
  66		int vstartup_start,
  67		int vupdate_offset,
  68		int vupdate_width,
  69		int pstate_keepout)
  70{
  71	struct optc *optc1 = DCN10TG_FROM_TG(optc);
  72
  73	optc1->vready_offset = vready_offset;
  74	optc1->vstartup_start = vstartup_start;
  75	optc1->vupdate_offset = vupdate_offset;
  76	optc1->vupdate_width = vupdate_width;
  77	optc1->pstate_keepout = pstate_keepout;
  78
  79	if (optc1->vstartup_start == 0) {
  80		BREAK_TO_DEBUGGER();
  81		return;
  82	}
  83
  84	REG_SET(OTG_VSTARTUP_PARAM, 0,
  85		VSTARTUP_START, optc1->vstartup_start);
  86
  87	REG_SET_2(OTG_VUPDATE_PARAM, 0,
  88			VUPDATE_OFFSET, optc1->vupdate_offset,
  89			VUPDATE_WIDTH, optc1->vupdate_width);
  90
  91	REG_SET(OTG_VREADY_PARAM, 0,
  92			VREADY_OFFSET, optc1->vready_offset);
  93}
  94
  95static void optc1_disable_stereo(struct timing_generator *optc)
  96{
  97	struct optc *optc1 = DCN10TG_FROM_TG(optc);
  98
  99	REG_SET(OTG_STEREO_CONTROL, 0,
 100		OTG_STEREO_EN, 0);
 101
 102	REG_SET_2(OTG_3D_STRUCTURE_CONTROL, 0,
 103		OTG_3D_STRUCTURE_EN, 0,
 104		OTG_3D_STRUCTURE_STEREO_SEL_OVR, 0);
 105}
 106
 107void optc1_setup_vertical_interrupt0(
 108		struct timing_generator *optc,
 109		uint32_t start_line,
 110		uint32_t end_line)
 111{
 112	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 113
 114	REG_SET_2(OTG_VERTICAL_INTERRUPT0_POSITION, 0,
 115			OTG_VERTICAL_INTERRUPT0_LINE_START, start_line,
 116			OTG_VERTICAL_INTERRUPT0_LINE_END, end_line);
 117}
 118
 119void optc1_setup_vertical_interrupt1(
 120		struct timing_generator *optc,
 121		uint32_t start_line)
 122{
 123	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 124
 125	REG_SET(OTG_VERTICAL_INTERRUPT1_POSITION, 0,
 126				OTG_VERTICAL_INTERRUPT1_LINE_START, start_line);
 127}
 128
 129void optc1_setup_vertical_interrupt2(
 130		struct timing_generator *optc,
 131		uint32_t start_line)
 132{
 133	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 134
 135	REG_SET(OTG_VERTICAL_INTERRUPT2_POSITION, 0,
 136			OTG_VERTICAL_INTERRUPT2_LINE_START, start_line);
 137}
 138
 139/**
 140 * optc1_program_timing() - used by mode timing set Program
 141 *                          CRTC Timing Registers - OTG_H_*,
 142 *                          OTG_V_*, Pixel repetition.
 143 *                          Including SYNC. Call BIOS command table to program Timings.
 144 *
 145 * @optc: timing_generator instance.
 146 * @dc_crtc_timing: Timing parameters used to configure DCN blocks.
 147 * @vready_offset: Vready's starting position.
 148 * @vstartup_start: Vstartup period.
 149 * @vupdate_offset: Vupdate starting position.
 150 * @vupdate_width: Vupdate duration.
 151 * @pstate_keepout: determines low power mode timing during refresh
 152 * @signal: DC signal types.
 153 * @use_vbios: to program timings from BIOS command table.
 154 *
 155 */
 156void optc1_program_timing(
 157	struct timing_generator *optc,
 158	const struct dc_crtc_timing *dc_crtc_timing,
 159	int vready_offset,
 160	int vstartup_start,
 161	int vupdate_offset,
 162	int vupdate_width,
 163	int pstate_keepout,
 164	const enum signal_type signal,
 165	bool use_vbios)
 166{
 167	struct dc_crtc_timing patched_crtc_timing;
 168	uint32_t asic_blank_end;
 169	uint32_t asic_blank_start;
 170	uint32_t v_total;
 171	uint32_t v_sync_end;
 172	uint32_t h_sync_polarity, v_sync_polarity;
 173	uint32_t start_point = 0;
 174	uint32_t field_num = 0;
 175	enum h_timing_div_mode h_div = H_TIMING_NO_DIV;
 176
 177	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 178
 179	optc1->signal = signal;
 180	optc1->vready_offset = vready_offset;
 181	optc1->vstartup_start = vstartup_start;
 182	optc1->vupdate_offset = vupdate_offset;
 183	optc1->vupdate_width = vupdate_width;
 184	optc1->pstate_keepout = pstate_keepout;
 185	patched_crtc_timing = *dc_crtc_timing;
 186	apply_front_porch_workaround(&patched_crtc_timing);
 187	optc1->orginal_patched_timing = patched_crtc_timing;
 188
 189	/* Load horizontal timing */
 190
 191	/* CRTC_H_TOTAL = vesa.h_total - 1 */
 192	REG_SET(OTG_H_TOTAL, 0,
 193			OTG_H_TOTAL,  patched_crtc_timing.h_total - 1);
 194
 195	/* h_sync_start = 0, h_sync_end = vesa.h_sync_width */
 196	REG_UPDATE_2(OTG_H_SYNC_A,
 197			OTG_H_SYNC_A_START, 0,
 198			OTG_H_SYNC_A_END, patched_crtc_timing.h_sync_width);
 199
 200	/* blank_start = line end - front porch */
 201	asic_blank_start = patched_crtc_timing.h_total -
 202			patched_crtc_timing.h_front_porch;
 203
 204	/* blank_end = blank_start - active */
 205	asic_blank_end = asic_blank_start -
 206			patched_crtc_timing.h_border_right -
 207			patched_crtc_timing.h_addressable -
 208			patched_crtc_timing.h_border_left;
 209
 210	REG_UPDATE_2(OTG_H_BLANK_START_END,
 211			OTG_H_BLANK_START, asic_blank_start,
 212			OTG_H_BLANK_END, asic_blank_end);
 213
 214	/* h_sync polarity */
 215	h_sync_polarity = patched_crtc_timing.flags.HSYNC_POSITIVE_POLARITY ?
 216			0 : 1;
 217
 218	REG_UPDATE(OTG_H_SYNC_A_CNTL,
 219			OTG_H_SYNC_A_POL, h_sync_polarity);
 220
 221	v_total = patched_crtc_timing.v_total - 1;
 222
 223	REG_SET(OTG_V_TOTAL, 0,
 224			OTG_V_TOTAL, v_total);
 225
 226	/* In case of V_TOTAL_CONTROL is on, make sure OTG_V_TOTAL_MAX and
 227	 * OTG_V_TOTAL_MIN are equal to V_TOTAL.
 228	 */
 229	optc->funcs->set_vtotal_min_max(optc, v_total, v_total);
 230
 231	/* v_sync_start = 0, v_sync_end = v_sync_width */
 232	v_sync_end = patched_crtc_timing.v_sync_width;
 233
 234	REG_UPDATE_2(OTG_V_SYNC_A,
 235			OTG_V_SYNC_A_START, 0,
 236			OTG_V_SYNC_A_END, v_sync_end);
 237
 238	/* blank_start = frame end - front porch */
 239	asic_blank_start = patched_crtc_timing.v_total -
 240			patched_crtc_timing.v_front_porch;
 241
 242	/* blank_end = blank_start - active */
 243	asic_blank_end = asic_blank_start -
 244			patched_crtc_timing.v_border_bottom -
 245			patched_crtc_timing.v_addressable -
 246			patched_crtc_timing.v_border_top;
 247
 248	REG_UPDATE_2(OTG_V_BLANK_START_END,
 249			OTG_V_BLANK_START, asic_blank_start,
 250			OTG_V_BLANK_END, asic_blank_end);
 251
 252	/* v_sync polarity */
 253	v_sync_polarity = patched_crtc_timing.flags.VSYNC_POSITIVE_POLARITY ?
 254			0 : 1;
 255
 256	REG_UPDATE(OTG_V_SYNC_A_CNTL,
 257		OTG_V_SYNC_A_POL, v_sync_polarity);
 258
 259	if (optc1->signal == SIGNAL_TYPE_DISPLAY_PORT ||
 260			optc1->signal == SIGNAL_TYPE_DISPLAY_PORT_MST ||
 261			optc1->signal == SIGNAL_TYPE_EDP) {
 262		start_point = 1;
 263		if (patched_crtc_timing.flags.INTERLACE == 1)
 264			field_num = 1;
 265	}
 266
 267	/* Interlace */
 268	if (REG(OTG_INTERLACE_CONTROL)) {
 269		if (patched_crtc_timing.flags.INTERLACE == 1)
 270			REG_UPDATE(OTG_INTERLACE_CONTROL,
 271					OTG_INTERLACE_ENABLE, 1);
 272		else
 273			REG_UPDATE(OTG_INTERLACE_CONTROL,
 274					OTG_INTERLACE_ENABLE, 0);
 275	}
 276
 277	/* VTG enable set to 0 first VInit */
 278	REG_UPDATE(CONTROL,
 279			VTG0_ENABLE, 0);
 280
 281	/* original code is using VTG offset to address OTG reg, seems wrong */
 282	REG_UPDATE_2(OTG_CONTROL,
 283			OTG_START_POINT_CNTL, start_point,
 284			OTG_FIELD_NUMBER_CNTL, field_num);
 285
 286	optc->funcs->program_global_sync(optc,
 287			vready_offset,
 288			vstartup_start,
 289			vupdate_offset,
 290			vupdate_width,
 291			pstate_keepout);
 292
 293	optc->funcs->set_vtg_params(optc, dc_crtc_timing, true);
 294
 295	/* TODO
 296	 * patched_crtc_timing.flags.HORZ_COUNT_BY_TWO == 1
 297	 * program_horz_count_by_2
 298	 * for DVI 30bpp mode, 0 otherwise
 299	 * program_horz_count_by_2(optc, &patched_crtc_timing);
 300	 */
 301
 302	/* Enable stereo - only when we need to pack 3D frame. Other types
 303	 * of stereo handled in explicit call
 304	 */
 305	if (optc->funcs->is_two_pixels_per_container(&patched_crtc_timing) || optc1->opp_count == 2)
 306		h_div = H_TIMING_DIV_BY2;
 307
 308	if (REG(OPTC_DATA_FORMAT_CONTROL) && optc1->tg_mask->OPTC_DATA_FORMAT != 0) {
 309		uint32_t data_fmt = 0;
 310
 311		if (patched_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR422)
 312			data_fmt = 1;
 313		else if (patched_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR420)
 314			data_fmt = 2;
 315
 316		REG_UPDATE(OPTC_DATA_FORMAT_CONTROL, OPTC_DATA_FORMAT, data_fmt);
 317	}
 318
 319	if (optc1->tg_mask->OTG_H_TIMING_DIV_MODE != 0) {
 320		if (optc1->opp_count == 4)
 321			h_div = H_TIMING_DIV_BY4;
 322
 323		REG_UPDATE(OTG_H_TIMING_CNTL,
 324		OTG_H_TIMING_DIV_MODE, h_div);
 325	} else {
 326		REG_UPDATE(OTG_H_TIMING_CNTL,
 327		OTG_H_TIMING_DIV_BY2, h_div);
 328	}
 329}
 330
 331/**
 332 * optc1_set_vtg_params - Set Vertical Timing Generator (VTG) parameters
 333 *
 334 * @optc: timing_generator struct used to extract the optc parameters
 335 * @dc_crtc_timing: Timing parameters configured
 336 * @program_fp2: Boolean value indicating if FP2 will be programmed or not
 337 *
 338 * OTG is responsible for generating the global sync signals, including
 339 * vertical timing information for each HUBP in the dcfclk domain. Each VTG is
 340 * associated with one OTG that provides HUBP with vertical timing information
 341 * (i.e., there is 1:1 correspondence between OTG and VTG). This function is
 342 * responsible for setting the OTG parameters to the VTG during the pipe
 343 * programming.
 344 */
 345void optc1_set_vtg_params(struct timing_generator *optc,
 346		const struct dc_crtc_timing *dc_crtc_timing, bool program_fp2)
 347{
 348	struct dc_crtc_timing patched_crtc_timing;
 349	uint32_t asic_blank_end;
 350	uint32_t v_init;
 351	uint32_t v_fp2 = 0;
 352	int32_t vertical_line_start;
 353
 354	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 355
 356	patched_crtc_timing = *dc_crtc_timing;
 357	apply_front_porch_workaround(&patched_crtc_timing);
 358
 359	/* VCOUNT_INIT is the start of blank */
 360	v_init = patched_crtc_timing.v_total - patched_crtc_timing.v_front_porch;
 361
 362	/* end of blank = v_init - active */
 363	asic_blank_end = v_init -
 364			patched_crtc_timing.v_border_bottom -
 365			patched_crtc_timing.v_addressable -
 366			patched_crtc_timing.v_border_top;
 367
 368	/* if VSTARTUP is before VSYNC, FP2 is the offset, otherwise 0 */
 369	vertical_line_start = asic_blank_end - optc1->vstartup_start + 1;
 370	if (vertical_line_start < 0)
 371		v_fp2 = -vertical_line_start;
 372
 373	/* Interlace */
 374	if (REG(OTG_INTERLACE_CONTROL)) {
 375		if (patched_crtc_timing.flags.INTERLACE == 1) {
 376			v_init = v_init / 2;
 377			if ((optc1->vstartup_start/2)*2 > asic_blank_end)
 378				v_fp2 = v_fp2 / 2;
 379		}
 380	}
 381
 382	if (program_fp2)
 383		REG_UPDATE_2(CONTROL,
 384				VTG0_FP2, v_fp2,
 385				VTG0_VCOUNT_INIT, v_init);
 386	else
 387		REG_UPDATE(CONTROL, VTG0_VCOUNT_INIT, v_init);
 388}
 389
 390void optc1_set_blank_data_double_buffer(struct timing_generator *optc, bool enable)
 391{
 392	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 393
 394	uint32_t blank_data_double_buffer_enable = enable ? 1 : 0;
 395
 396	REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL,
 397			OTG_BLANK_DATA_DOUBLE_BUFFER_EN, blank_data_double_buffer_enable);
 398}
 399
 400/**
 401 * optc1_set_timing_double_buffer() - DRR double buffering control
 402 *
 403 * Sets double buffer point for V_TOTAL, H_TOTAL, VTOTAL_MIN,
 404 * VTOTAL_MAX, VTOTAL_MIN_SEL and VTOTAL_MAX_SEL registers.
 405 *
 406 * @optc: timing_generator instance.
 407 * @enable: Enable DRR double buffering control if true, disable otherwise.
 408 *
 409 * Options: any time,  start of frame, dp start of frame (range timing)
 410 */
 411void optc1_set_timing_double_buffer(struct timing_generator *optc, bool enable)
 412{
 413	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 414	uint32_t mode = enable ? 2 : 0;
 415
 416	REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL,
 417		   OTG_RANGE_TIMING_DBUF_UPDATE_MODE, mode);
 418}
 419
 420/**
 421 * optc1_unblank_crtc() - Call ASIC Control Object to UnBlank CRTC.
 422 *
 423 * @optc: timing_generator instance.
 424 */
 425static void optc1_unblank_crtc(struct timing_generator *optc)
 426{
 427	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 428
 429	REG_UPDATE_2(OTG_BLANK_CONTROL,
 430			OTG_BLANK_DATA_EN, 0,
 431			OTG_BLANK_DE_MODE, 0);
 432
 433	/* W/A for automated testing
 434	 * Automated testing will fail underflow test as there
 435	 * sporadic underflows which occur during the optc blank
 436	 * sequence.  As a w/a, clear underflow on unblank.
 437	 * This prevents the failure, but will not mask actual
 438	 * underflow that affect real use cases.
 439	 */
 440	optc1_clear_optc_underflow(optc);
 441}
 442
 443/**
 444 * optc1_blank_crtc() - Call ASIC Control Object to Blank CRTC.
 445 *
 446 * @optc: timing_generator instance.
 447 */
 448
 449static void optc1_blank_crtc(struct timing_generator *optc)
 450{
 451	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 452
 453	REG_UPDATE_2(OTG_BLANK_CONTROL,
 454			OTG_BLANK_DATA_EN, 1,
 455			OTG_BLANK_DE_MODE, 0);
 456
 457	optc1_set_blank_data_double_buffer(optc, false);
 458}
 459
 460void optc1_set_blank(struct timing_generator *optc,
 461		bool enable_blanking)
 462{
 463	if (enable_blanking)
 464		optc1_blank_crtc(optc);
 465	else
 466		optc1_unblank_crtc(optc);
 467}
 468
 469bool optc1_is_blanked(struct timing_generator *optc)
 470{
 471	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 472	uint32_t blank_en;
 473	uint32_t blank_state;
 474
 475	REG_GET_2(OTG_BLANK_CONTROL,
 476			OTG_BLANK_DATA_EN, &blank_en,
 477			OTG_CURRENT_BLANK_STATE, &blank_state);
 478
 479	return blank_en && blank_state;
 480}
 481
 482void optc1_enable_optc_clock(struct timing_generator *optc, bool enable)
 483{
 484	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 485
 486	if (enable) {
 487		REG_UPDATE_2(OPTC_INPUT_CLOCK_CONTROL,
 488				OPTC_INPUT_CLK_EN, 1,
 489				OPTC_INPUT_CLK_GATE_DIS, 1);
 490
 491		REG_WAIT(OPTC_INPUT_CLOCK_CONTROL,
 492				OPTC_INPUT_CLK_ON, 1,
 493				1, 1000);
 494
 495		/* Enable clock */
 496		REG_UPDATE_2(OTG_CLOCK_CONTROL,
 497				OTG_CLOCK_EN, 1,
 498				OTG_CLOCK_GATE_DIS, 1);
 499		REG_WAIT(OTG_CLOCK_CONTROL,
 500				OTG_CLOCK_ON, 1,
 501				1, 1000);
 502	} else  {
 503
 504		//last chance to clear underflow, otherwise, it will always there due to clock is off.
 505		if (optc->funcs->is_optc_underflow_occurred(optc) == true)
 506			optc->funcs->clear_optc_underflow(optc);
 507
 508		REG_UPDATE_2(OTG_CLOCK_CONTROL,
 509				OTG_CLOCK_GATE_DIS, 0,
 510				OTG_CLOCK_EN, 0);
 511
 512		REG_UPDATE_2(OPTC_INPUT_CLOCK_CONTROL,
 513				OPTC_INPUT_CLK_GATE_DIS, 0,
 514				OPTC_INPUT_CLK_EN, 0);
 515	}
 516}
 517
 518/**
 519 * optc1_enable_crtc() - Enable CRTC - call ASIC Control Object to enable Timing generator.
 520 *
 521 * @optc: timing_generator instance.
 522 */
 523static bool optc1_enable_crtc(struct timing_generator *optc)
 524{
 525	/* TODO FPGA wait for answer
 526	 * OTG_MASTER_UPDATE_MODE != CRTC_MASTER_UPDATE_MODE
 527	 * OTG_MASTER_UPDATE_LOCK != CRTC_MASTER_UPDATE_LOCK
 528	 */
 529	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 530
 531	/* opp instance for OTG. For DCN1.0, ODM is remoed.
 532	 * OPP and OPTC should 1:1 mapping
 533	 */
 534	REG_UPDATE(OPTC_DATA_SOURCE_SELECT,
 535			OPTC_SRC_SEL, optc->inst);
 536
 537	/* VTG enable first is for HW workaround */
 538	REG_UPDATE(CONTROL,
 539			VTG0_ENABLE, 1);
 540
 541	REG_SEQ_START();
 542
 543	/* Enable CRTC */
 544	REG_UPDATE_2(OTG_CONTROL,
 545			OTG_DISABLE_POINT_CNTL, 3,
 546			OTG_MASTER_EN, 1);
 547
 548	REG_SEQ_SUBMIT();
 549	REG_SEQ_WAIT_DONE();
 550
 551	return true;
 552}
 553
 554/* disable_crtc - call ASIC Control Object to disable Timing generator. */
 555bool optc1_disable_crtc(struct timing_generator *optc)
 556{
 557	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 558
 559	/* disable otg request until end of the first line
 560	 * in the vertical blank region
 561	 */
 562	REG_UPDATE_2(OTG_CONTROL,
 563			OTG_DISABLE_POINT_CNTL, 3,
 564			OTG_MASTER_EN, 0);
 565
 566	REG_UPDATE(CONTROL,
 567			VTG0_ENABLE, 0);
 568
 569	/* CRTC disabled, so disable  clock. */
 570	REG_WAIT(OTG_CLOCK_CONTROL,
 571			OTG_BUSY, 0,
 572			1, 100000);
 573
 574	return true;
 575}
 576
 577
 578void optc1_program_blank_color(
 579		struct timing_generator *optc,
 580		const struct tg_color *black_color)
 581{
 582	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 583
 584	REG_SET_3(OTG_BLACK_COLOR, 0,
 585			OTG_BLACK_COLOR_B_CB, black_color->color_b_cb,
 586			OTG_BLACK_COLOR_G_Y, black_color->color_g_y,
 587			OTG_BLACK_COLOR_R_CR, black_color->color_r_cr);
 588}
 589
 590bool optc1_validate_timing(
 591	struct timing_generator *optc,
 592	const struct dc_crtc_timing *timing)
 593{
 594	uint32_t v_blank;
 595	uint32_t h_blank;
 596	uint32_t min_v_blank;
 597	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 598
 599	ASSERT(timing != NULL);
 600
 601	v_blank = (timing->v_total - timing->v_addressable -
 602					timing->v_border_top - timing->v_border_bottom);
 603
 604	h_blank = (timing->h_total - timing->h_addressable -
 605		timing->h_border_right -
 606		timing->h_border_left);
 607
 608	if (timing->timing_3d_format != TIMING_3D_FORMAT_NONE &&
 609		timing->timing_3d_format != TIMING_3D_FORMAT_HW_FRAME_PACKING &&
 610		timing->timing_3d_format != TIMING_3D_FORMAT_TOP_AND_BOTTOM &&
 611		timing->timing_3d_format != TIMING_3D_FORMAT_SIDE_BY_SIDE &&
 612		timing->timing_3d_format != TIMING_3D_FORMAT_FRAME_ALTERNATE &&
 613		timing->timing_3d_format != TIMING_3D_FORMAT_INBAND_FA)
 614		return false;
 615
 616	/* Temporarily blocking interlacing mode until it's supported */
 617	if (timing->flags.INTERLACE == 1)
 618		return false;
 619
 620	/* Check maximum number of pixels supported by Timing Generator
 621	 * (Currently will never fail, in order to fail needs display which
 622	 * needs more than 8192 horizontal and
 623	 * more than 8192 vertical total pixels)
 624	 */
 625	if (timing->h_total > optc1->max_h_total ||
 626		timing->v_total > optc1->max_v_total)
 627		return false;
 628
 629
 630	if (h_blank < optc1->min_h_blank)
 631		return false;
 632
 633	if (timing->h_sync_width  < optc1->min_h_sync_width ||
 634		 timing->v_sync_width  < optc1->min_v_sync_width)
 635		return false;
 636
 637	min_v_blank = timing->flags.INTERLACE?optc1->min_v_blank_interlace:optc1->min_v_blank;
 638
 639	if (v_blank < min_v_blank)
 640		return false;
 641
 642	return true;
 643
 644}
 645
 646/*
 647 * get_vblank_counter
 648 *
 649 * @brief
 650 * Get counter for vertical blanks. use register CRTC_STATUS_FRAME_COUNT which
 651 * holds the counter of frames.
 652 *
 653 * @param
 654 * struct timing_generator *optc - [in] timing generator which controls the
 655 * desired CRTC
 656 *
 657 * @return
 658 * Counter of frames, which should equal to number of vblanks.
 659 */
 660uint32_t optc1_get_vblank_counter(struct timing_generator *optc)
 661{
 662	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 663	uint32_t frame_count;
 664
 665	REG_GET(OTG_STATUS_FRAME_COUNT,
 666		OTG_FRAME_COUNT, &frame_count);
 667
 668	return frame_count;
 669}
 670
 671void optc1_lock(struct timing_generator *optc)
 672{
 673	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 674
 675	REG_SET(OTG_GLOBAL_CONTROL0, 0,
 676			OTG_MASTER_UPDATE_LOCK_SEL, optc->inst);
 677	REG_SET(OTG_MASTER_UPDATE_LOCK, 0,
 678			OTG_MASTER_UPDATE_LOCK, 1);
 679
 680	REG_WAIT(OTG_MASTER_UPDATE_LOCK,
 681			UPDATE_LOCK_STATUS, 1,
 682			1, 10);
 683
 684	TRACE_OPTC_LOCK_UNLOCK_STATE(optc1, optc->inst, true);
 685}
 686
 687void optc1_unlock(struct timing_generator *optc)
 688{
 689	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 690
 691	REG_SET(OTG_MASTER_UPDATE_LOCK, 0,
 692			OTG_MASTER_UPDATE_LOCK, 0);
 693
 694	TRACE_OPTC_LOCK_UNLOCK_STATE(optc1, optc->inst, false);
 695}
 696
 697void optc1_get_position(struct timing_generator *optc,
 698		struct crtc_position *position)
 699{
 700	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 701
 702	REG_GET_2(OTG_STATUS_POSITION,
 703			OTG_HORZ_COUNT, &position->horizontal_count,
 704			OTG_VERT_COUNT, &position->vertical_count);
 705
 706	REG_GET(OTG_NOM_VERT_POSITION,
 707			OTG_VERT_COUNT_NOM, &position->nominal_vcount);
 708}
 709
 710bool optc1_is_counter_moving(struct timing_generator *optc)
 711{
 712	struct crtc_position position1, position2;
 713
 714	optc->funcs->get_position(optc, &position1);
 715	optc->funcs->get_position(optc, &position2);
 716
 717	if (position1.horizontal_count == position2.horizontal_count &&
 718		position1.vertical_count == position2.vertical_count)
 719		return false;
 720	else
 721		return true;
 722}
 723
 724bool optc1_did_triggered_reset_occur(
 725	struct timing_generator *optc)
 726{
 727	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 728	uint32_t occurred_force, occurred_vsync;
 729
 730	REG_GET(OTG_FORCE_COUNT_NOW_CNTL,
 731		OTG_FORCE_COUNT_NOW_OCCURRED, &occurred_force);
 732
 733	REG_GET(OTG_VERT_SYNC_CONTROL,
 734		OTG_FORCE_VSYNC_NEXT_LINE_OCCURRED, &occurred_vsync);
 735
 736	return occurred_vsync != 0 || occurred_force != 0;
 737}
 738
 739void optc1_disable_reset_trigger(struct timing_generator *optc)
 740{
 741	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 742
 743	REG_WRITE(OTG_TRIGA_CNTL, 0);
 744
 745	REG_SET(OTG_FORCE_COUNT_NOW_CNTL, 0,
 746		OTG_FORCE_COUNT_NOW_CLEAR, 1);
 747
 748	REG_SET(OTG_VERT_SYNC_CONTROL, 0,
 749		OTG_FORCE_VSYNC_NEXT_LINE_CLEAR, 1);
 750}
 751
 752void optc1_enable_reset_trigger(struct timing_generator *optc, int source_tg_inst)
 753{
 754	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 755	uint32_t falling_edge;
 756
 757	REG_GET(OTG_V_SYNC_A_CNTL,
 758			OTG_V_SYNC_A_POL, &falling_edge);
 759
 760	if (falling_edge)
 761		REG_SET_3(OTG_TRIGA_CNTL, 0,
 762				/* vsync signal from selected OTG pipe based
 763				 * on OTG_TRIG_SOURCE_PIPE_SELECT setting
 764				 */
 765				OTG_TRIGA_SOURCE_SELECT, 20,
 766				OTG_TRIGA_SOURCE_PIPE_SELECT, source_tg_inst,
 767				/* always detect falling edge */
 768				OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, 1);
 769	else
 770		REG_SET_3(OTG_TRIGA_CNTL, 0,
 771				/* vsync signal from selected OTG pipe based
 772				 * on OTG_TRIG_SOURCE_PIPE_SELECT setting
 773				 */
 774				OTG_TRIGA_SOURCE_SELECT, 20,
 775				OTG_TRIGA_SOURCE_PIPE_SELECT, source_tg_inst,
 776				/* always detect rising edge */
 777				OTG_TRIGA_RISING_EDGE_DETECT_CNTL, 1);
 778
 779	REG_SET(OTG_FORCE_COUNT_NOW_CNTL, 0,
 780			/* force H count to H_TOTAL and V count to V_TOTAL in
 781			 * progressive mode and V_TOTAL-1 in interlaced mode
 782			 */
 783			OTG_FORCE_COUNT_NOW_MODE, 2);
 784}
 785
 786void optc1_enable_crtc_reset(
 787		struct timing_generator *optc,
 788		int source_tg_inst,
 789		struct crtc_trigger_info *crtc_tp)
 790{
 791	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 792	uint32_t falling_edge = 0;
 793	uint32_t rising_edge = 0;
 794
 795	switch (crtc_tp->event) {
 796
 797	case CRTC_EVENT_VSYNC_RISING:
 798		rising_edge = 1;
 799		break;
 800
 801	case CRTC_EVENT_VSYNC_FALLING:
 802		falling_edge = 1;
 803		break;
 804	}
 805
 806	REG_SET_4(OTG_TRIGA_CNTL, 0,
 807		 /* vsync signal from selected OTG pipe based
 808		  * on OTG_TRIG_SOURCE_PIPE_SELECT setting
 809		  */
 810		  OTG_TRIGA_SOURCE_SELECT, 20,
 811		  OTG_TRIGA_SOURCE_PIPE_SELECT, source_tg_inst,
 812		  /* always detect falling edge */
 813		  OTG_TRIGA_RISING_EDGE_DETECT_CNTL, rising_edge,
 814		  OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, falling_edge);
 815
 816	switch (crtc_tp->delay) {
 817	case TRIGGER_DELAY_NEXT_LINE:
 818		REG_SET(OTG_VERT_SYNC_CONTROL, 0,
 819				OTG_AUTO_FORCE_VSYNC_MODE, 1);
 820		break;
 821	case TRIGGER_DELAY_NEXT_PIXEL:
 822		REG_SET(OTG_FORCE_COUNT_NOW_CNTL, 0,
 823			/* force H count to H_TOTAL and V count to V_TOTAL in
 824			 * progressive mode and V_TOTAL-1 in interlaced mode
 825			 */
 826			OTG_FORCE_COUNT_NOW_MODE, 2);
 827		break;
 828	}
 829}
 830
 831void optc1_wait_for_state(struct timing_generator *optc,
 832		enum crtc_state state)
 833{
 834	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 835
 836	switch (state) {
 837	case CRTC_STATE_VBLANK:
 838		REG_WAIT(OTG_STATUS,
 839				OTG_V_BLANK, 1,
 840				1, 100000); /* 1 vupdate at 10hz */
 841		break;
 842
 843	case CRTC_STATE_VACTIVE:
 844		REG_WAIT(OTG_STATUS,
 845				OTG_V_ACTIVE_DISP, 1,
 846				1, 100000); /* 1 vupdate at 10hz */
 847		break;
 848
 849	default:
 850		break;
 851	}
 852}
 853
 854void optc1_set_early_control(
 855	struct timing_generator *optc,
 856	uint32_t early_cntl)
 857{
 858	/* asic design change, do not need this control
 859	 * empty for share caller logic
 860	 */
 861}
 862
 863
 864void optc1_set_static_screen_control(
 865	struct timing_generator *optc,
 866	uint32_t event_triggers,
 867	uint32_t num_frames)
 868{
 869	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 870
 871	// By register spec, it only takes 8 bit value
 872	if (num_frames > 0xFF)
 873		num_frames = 0xFF;
 874
 875	/* Bit 8 is no longer applicable in RV for PSR case,
 876	 * set bit 8 to 0 if given
 877	 */
 878	if ((event_triggers & STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN)
 879			!= 0)
 880		event_triggers = event_triggers &
 881		~STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN;
 882
 883	REG_SET_2(OTG_STATIC_SCREEN_CONTROL, 0,
 884			OTG_STATIC_SCREEN_EVENT_MASK, event_triggers,
 885			OTG_STATIC_SCREEN_FRAME_COUNT, num_frames);
 886}
 887
 888static void optc1_setup_manual_trigger(struct timing_generator *optc)
 889{
 890	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 891
 892	REG_SET(OTG_GLOBAL_CONTROL2, 0,
 893			MANUAL_FLOW_CONTROL_SEL, optc->inst);
 894
 895	REG_SET_8(OTG_TRIGA_CNTL, 0,
 896			OTG_TRIGA_SOURCE_SELECT, 22,
 897			OTG_TRIGA_SOURCE_PIPE_SELECT, optc->inst,
 898			OTG_TRIGA_RISING_EDGE_DETECT_CNTL, 1,
 899			OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, 0,
 900			OTG_TRIGA_POLARITY_SELECT, 0,
 901			OTG_TRIGA_FREQUENCY_SELECT, 0,
 902			OTG_TRIGA_DELAY, 0,
 903			OTG_TRIGA_CLEAR, 1);
 904}
 905
 906static void optc1_program_manual_trigger(struct timing_generator *optc)
 907{
 908	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 909
 910	REG_SET(OTG_MANUAL_FLOW_CONTROL, 0,
 911			MANUAL_FLOW_CONTROL, 1);
 912
 913	REG_SET(OTG_MANUAL_FLOW_CONTROL, 0,
 914			MANUAL_FLOW_CONTROL, 0);
 915}
 916
 917/**
 918 * optc1_set_drr() - Program dynamic refresh rate registers m_OTGx_OTG_V_TOTAL_*.
 919 *
 920 * @optc: timing_generator instance.
 921 * @params: parameters used for Dynamic Refresh Rate.
 922 */
 923void optc1_set_drr(
 924	struct timing_generator *optc,
 925	const struct drr_params *params)
 926{
 927	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 928
 929	if (params != NULL &&
 930		params->vertical_total_max > 0 &&
 931		params->vertical_total_min > 0) {
 932
 933		if (params->vertical_total_mid != 0) {
 934
 935			REG_SET(OTG_V_TOTAL_MID, 0,
 936				OTG_V_TOTAL_MID, params->vertical_total_mid - 1);
 937
 938			REG_UPDATE_2(OTG_V_TOTAL_CONTROL,
 939					OTG_VTOTAL_MID_REPLACING_MAX_EN, 1,
 940					OTG_VTOTAL_MID_FRAME_NUM,
 941					(uint8_t)params->vertical_total_mid_frame_num);
 942
 943		}
 944
 945		optc->funcs->set_vtotal_min_max(optc, params->vertical_total_min - 1, params->vertical_total_max - 1);
 946
 947		REG_UPDATE_5(OTG_V_TOTAL_CONTROL,
 948				OTG_V_TOTAL_MIN_SEL, 1,
 949				OTG_V_TOTAL_MAX_SEL, 1,
 950				OTG_FORCE_LOCK_ON_EVENT, 0,
 951				OTG_SET_V_TOTAL_MIN_MASK_EN, 0,
 952				OTG_SET_V_TOTAL_MIN_MASK, 0);
 953	}
 954
 955	// Setup manual flow control for EOF via TRIG_A
 956	optc->funcs->setup_manual_trigger(optc);
 957}
 958
 959void optc1_set_vtotal_min_max(struct timing_generator *optc, int vtotal_min, int vtotal_max)
 960{
 961	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 962
 963	REG_SET(OTG_V_TOTAL_MAX, 0,
 964		OTG_V_TOTAL_MAX, vtotal_max);
 965
 966	REG_SET(OTG_V_TOTAL_MIN, 0,
 967		OTG_V_TOTAL_MIN, vtotal_min);
 968}
 969
 970static void optc1_set_test_pattern(
 971	struct timing_generator *optc,
 972	/* TODO: replace 'controller_dp_test_pattern' by 'test_pattern_mode'
 973	 * because this is not DP-specific (which is probably somewhere in DP
 974	 * encoder) */
 975	enum controller_dp_test_pattern test_pattern,
 976	enum dc_color_depth color_depth)
 977{
 978	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 979	enum test_pattern_color_format bit_depth;
 980	enum test_pattern_dyn_range dyn_range;
 981	enum test_pattern_mode mode;
 982	uint32_t pattern_mask;
 983	uint32_t pattern_data;
 984	/* color ramp generator mixes 16-bits color */
 985	uint32_t src_bpc = 16;
 986	/* requested bpc */
 987	uint32_t dst_bpc;
 988	uint32_t index;
 989	/* RGB values of the color bars.
 990	 * Produce two RGB colors: RGB0 - white (all Fs)
 991	 * and RGB1 - black (all 0s)
 992	 * (three RGB components for two colors)
 993	 */
 994	uint16_t src_color[6] = {0xFFFF, 0xFFFF, 0xFFFF, 0x0000,
 995						0x0000, 0x0000};
 996	/* dest color (converted to the specified color format) */
 997	uint16_t dst_color[6];
 998	uint32_t inc_base;
 999
1000	/* translate to bit depth */
1001	switch (color_depth) {
1002	case COLOR_DEPTH_666:
1003		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_6;
1004	break;
1005	case COLOR_DEPTH_888:
1006		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
1007	break;
1008	case COLOR_DEPTH_101010:
1009		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_10;
1010	break;
1011	case COLOR_DEPTH_121212:
1012		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_12;
1013	break;
1014	default:
1015		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
1016	break;
1017	}
1018
1019	switch (test_pattern) {
1020	case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES:
1021	case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA:
1022	{
1023		dyn_range = (test_pattern ==
1024				CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA ?
1025				TEST_PATTERN_DYN_RANGE_CEA :
1026				TEST_PATTERN_DYN_RANGE_VESA);
1027		mode = TEST_PATTERN_MODE_COLORSQUARES_RGB;
1028
1029		REG_UPDATE_2(OTG_TEST_PATTERN_PARAMETERS,
1030				OTG_TEST_PATTERN_VRES, 6,
1031				OTG_TEST_PATTERN_HRES, 6);
1032
1033		REG_UPDATE_4(OTG_TEST_PATTERN_CONTROL,
1034				OTG_TEST_PATTERN_EN, 1,
1035				OTG_TEST_PATTERN_MODE, mode,
1036				OTG_TEST_PATTERN_DYNAMIC_RANGE, dyn_range,
1037				OTG_TEST_PATTERN_COLOR_FORMAT, bit_depth);
1038	}
1039	break;
1040
1041	case CONTROLLER_DP_TEST_PATTERN_VERTICALBARS:
1042	case CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS:
1043	{
1044		mode = (test_pattern ==
1045			CONTROLLER_DP_TEST_PATTERN_VERTICALBARS ?
1046			TEST_PATTERN_MODE_VERTICALBARS :
1047			TEST_PATTERN_MODE_HORIZONTALBARS);
1048
1049		switch (bit_depth) {
1050		case TEST_PATTERN_COLOR_FORMAT_BPC_6:
1051			dst_bpc = 6;
1052		break;
1053		case TEST_PATTERN_COLOR_FORMAT_BPC_8:
1054			dst_bpc = 8;
1055		break;
1056		case TEST_PATTERN_COLOR_FORMAT_BPC_10:
1057			dst_bpc = 10;
1058		break;
1059		default:
1060			dst_bpc = 8;
1061		break;
1062		}
1063
1064		/* adjust color to the required colorFormat */
1065		for (index = 0; index < 6; index++) {
1066			/* dst = 2^dstBpc * src / 2^srcBpc = src >>
1067			 * (srcBpc - dstBpc);
1068			 */
1069			dst_color[index] =
1070				src_color[index] >> (src_bpc - dst_bpc);
1071		/* CRTC_TEST_PATTERN_DATA has 16 bits,
1072		 * lowest 6 are hardwired to ZERO
1073		 * color bits should be left aligned to MSB
1074		 * XXXXXXXXXX000000 for 10 bit,
1075		 * XXXXXXXX00000000 for 8 bit and XXXXXX0000000000 for 6
1076		 */
1077			dst_color[index] <<= (16 - dst_bpc);
1078		}
1079
1080		REG_WRITE(OTG_TEST_PATTERN_PARAMETERS, 0);
1081
1082		/* We have to write the mask before data, similar to pipeline.
1083		 * For example, for 8 bpc, if we want RGB0 to be magenta,
1084		 * and RGB1 to be cyan,
1085		 * we need to make 7 writes:
1086		 * MASK   DATA
1087		 * 000001 00000000 00000000                     set mask to R0
1088		 * 000010 11111111 00000000     R0 255, 0xFF00, set mask to G0
1089		 * 000100 00000000 00000000     G0 0,   0x0000, set mask to B0
1090		 * 001000 11111111 00000000     B0 255, 0xFF00, set mask to R1
1091		 * 010000 00000000 00000000     R1 0,   0x0000, set mask to G1
1092		 * 100000 11111111 00000000     G1 255, 0xFF00, set mask to B1
1093		 * 100000 11111111 00000000     B1 255, 0xFF00
1094		 *
1095		 * we will make a loop of 6 in which we prepare the mask,
1096		 * then write, then prepare the color for next write.
1097		 * first iteration will write mask only,
1098		 * but each next iteration color prepared in
1099		 * previous iteration will be written within new mask,
1100		 * the last component will written separately,
1101		 * mask is not changing between 6th and 7th write
1102		 * and color will be prepared by last iteration
1103		 */
1104
1105		/* write color, color values mask in CRTC_TEST_PATTERN_MASK
1106		 * is B1, G1, R1, B0, G0, R0
1107		 */
1108		pattern_data = 0;
1109		for (index = 0; index < 6; index++) {
1110			/* prepare color mask, first write PATTERN_DATA
1111			 * will have all zeros
1112			 */
1113			pattern_mask = (1 << index);
1114
1115			/* write color component */
1116			REG_SET_2(OTG_TEST_PATTERN_COLOR, 0,
1117					OTG_TEST_PATTERN_MASK, pattern_mask,
1118					OTG_TEST_PATTERN_DATA, pattern_data);
1119
1120			/* prepare next color component,
1121			 * will be written in the next iteration
1122			 */
1123			pattern_data = dst_color[index];
1124		}
1125		/* write last color component,
1126		 * it's been already prepared in the loop
1127		 */
1128		REG_SET_2(OTG_TEST_PATTERN_COLOR, 0,
1129				OTG_TEST_PATTERN_MASK, pattern_mask,
1130				OTG_TEST_PATTERN_DATA, pattern_data);
1131
1132		/* enable test pattern */
1133		REG_UPDATE_4(OTG_TEST_PATTERN_CONTROL,
1134				OTG_TEST_PATTERN_EN, 1,
1135				OTG_TEST_PATTERN_MODE, mode,
1136				OTG_TEST_PATTERN_DYNAMIC_RANGE, 0,
1137				OTG_TEST_PATTERN_COLOR_FORMAT, bit_depth);
1138	}
1139	break;
1140
1141	case CONTROLLER_DP_TEST_PATTERN_COLORRAMP:
1142	{
1143		mode = (bit_depth ==
1144			TEST_PATTERN_COLOR_FORMAT_BPC_10 ?
1145			TEST_PATTERN_MODE_DUALRAMP_RGB :
1146			TEST_PATTERN_MODE_SINGLERAMP_RGB);
1147
1148		switch (bit_depth) {
1149		case TEST_PATTERN_COLOR_FORMAT_BPC_6:
1150			dst_bpc = 6;
1151		break;
1152		case TEST_PATTERN_COLOR_FORMAT_BPC_8:
1153			dst_bpc = 8;
1154		break;
1155		case TEST_PATTERN_COLOR_FORMAT_BPC_10:
1156			dst_bpc = 10;
1157		break;
1158		default:
1159			dst_bpc = 8;
1160		break;
1161		}
1162
1163		/* increment for the first ramp for one color gradation
1164		 * 1 gradation for 6-bit color is 2^10
1165		 * gradations in 16-bit color
1166		 */
1167		inc_base = (src_bpc - dst_bpc);
1168
1169		switch (bit_depth) {
1170		case TEST_PATTERN_COLOR_FORMAT_BPC_6:
1171		{
1172			REG_UPDATE_5(OTG_TEST_PATTERN_PARAMETERS,
1173					OTG_TEST_PATTERN_INC0, inc_base,
1174					OTG_TEST_PATTERN_INC1, 0,
1175					OTG_TEST_PATTERN_HRES, 6,
1176					OTG_TEST_PATTERN_VRES, 6,
1177					OTG_TEST_PATTERN_RAMP0_OFFSET, 0);
1178		}
1179		break;
1180		case TEST_PATTERN_COLOR_FORMAT_BPC_8:
1181		{
1182			REG_UPDATE_5(OTG_TEST_PATTERN_PARAMETERS,
1183					OTG_TEST_PATTERN_INC0, inc_base,
1184					OTG_TEST_PATTERN_INC1, 0,
1185					OTG_TEST_PATTERN_HRES, 8,
1186					OTG_TEST_PATTERN_VRES, 6,
1187					OTG_TEST_PATTERN_RAMP0_OFFSET, 0);
1188		}
1189		break;
1190		case TEST_PATTERN_COLOR_FORMAT_BPC_10:
1191		{
1192			REG_UPDATE_5(OTG_TEST_PATTERN_PARAMETERS,
1193					OTG_TEST_PATTERN_INC0, inc_base,
1194					OTG_TEST_PATTERN_INC1, inc_base + 2,
1195					OTG_TEST_PATTERN_HRES, 8,
1196					OTG_TEST_PATTERN_VRES, 5,
1197					OTG_TEST_PATTERN_RAMP0_OFFSET, 384 << 6);
1198		}
1199		break;
1200		default:
1201		break;
1202		}
1203
1204		REG_WRITE(OTG_TEST_PATTERN_COLOR, 0);
1205
1206		/* enable test pattern */
1207		REG_WRITE(OTG_TEST_PATTERN_CONTROL, 0);
1208
1209		REG_SET_4(OTG_TEST_PATTERN_CONTROL, 0,
1210				OTG_TEST_PATTERN_EN, 1,
1211				OTG_TEST_PATTERN_MODE, mode,
1212				OTG_TEST_PATTERN_DYNAMIC_RANGE, 0,
1213				OTG_TEST_PATTERN_COLOR_FORMAT, bit_depth);
1214	}
1215	break;
1216	case CONTROLLER_DP_TEST_PATTERN_VIDEOMODE:
1217	{
1218		REG_WRITE(OTG_TEST_PATTERN_CONTROL, 0);
1219		REG_WRITE(OTG_TEST_PATTERN_COLOR, 0);
1220		REG_WRITE(OTG_TEST_PATTERN_PARAMETERS, 0);
1221	}
1222	break;
1223	default:
1224		break;
1225
1226	}
1227}
1228
1229void optc1_get_crtc_scanoutpos(
1230	struct timing_generator *optc,
1231	uint32_t *v_blank_start,
1232	uint32_t *v_blank_end,
1233	uint32_t *h_position,
1234	uint32_t *v_position)
1235{
1236	struct optc *optc1 = DCN10TG_FROM_TG(optc);
1237	struct crtc_position position;
1238
1239	REG_GET_2(OTG_V_BLANK_START_END,
1240			OTG_V_BLANK_START, v_blank_start,
1241			OTG_V_BLANK_END, v_blank_end);
1242
1243	optc1_get_position(optc, &position);
1244
1245	*h_position = position.horizontal_count;
1246	*v_position = position.vertical_count;
1247}
1248
1249static void optc1_enable_stereo(struct timing_generator *optc,
1250	const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags)
1251{
1252	struct optc *optc1 = DCN10TG_FROM_TG(optc);
1253
1254	if (flags) {
1255		uint32_t stereo_en;
1256		stereo_en = flags->FRAME_PACKED == 0 ? 1 : 0;
1257
1258		if (flags->PROGRAM_STEREO)
1259			REG_UPDATE_3(OTG_STEREO_CONTROL,
1260				OTG_STEREO_EN, stereo_en,
1261				OTG_STEREO_SYNC_OUTPUT_LINE_NUM, 0,
1262				OTG_STEREO_SYNC_OUTPUT_POLARITY, flags->RIGHT_EYE_POLARITY == 0 ? 0 : 1);
1263
1264		if (flags->PROGRAM_POLARITY)
1265			REG_UPDATE(OTG_STEREO_CONTROL,
1266				OTG_STEREO_EYE_FLAG_POLARITY,
1267				flags->RIGHT_EYE_POLARITY == 0 ? 0 : 1);
1268
1269		if (flags->DISABLE_STEREO_DP_SYNC)
1270			REG_UPDATE(OTG_STEREO_CONTROL,
1271				OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, 1);
1272
1273		if (flags->PROGRAM_STEREO)
1274			REG_UPDATE_2(OTG_3D_STRUCTURE_CONTROL,
1275				OTG_3D_STRUCTURE_EN, flags->FRAME_PACKED,
1276				OTG_3D_STRUCTURE_STEREO_SEL_OVR, flags->FRAME_PACKED);
1277
1278	}
1279}
1280
1281void optc1_program_stereo(struct timing_generator *optc,
1282	const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags)
1283{
1284	if (flags->PROGRAM_STEREO)
1285		optc1_enable_stereo(optc, timing, flags);
1286	else
1287		optc1_disable_stereo(optc);
1288}
1289
1290
1291bool optc1_is_stereo_left_eye(struct timing_generator *optc)
1292{
1293	bool ret = false;
1294	uint32_t left_eye = 0;
1295	struct optc *optc1 = DCN10TG_FROM_TG(optc);
1296
1297	REG_GET(OTG_STEREO_STATUS,
1298		OTG_STEREO_CURRENT_EYE, &left_eye);
1299	if (left_eye == 1)
1300		ret = true;
1301	else
1302		ret = false;
1303
1304	return ret;
1305}
1306
1307bool optc1_get_hw_timing(struct timing_generator *tg,
1308		struct dc_crtc_timing *hw_crtc_timing)
1309{
1310	struct dcn_otg_state s = {0};
1311
1312	if (tg == NULL || hw_crtc_timing == NULL)
1313		return false;
1314
1315	optc1_read_otg_state(tg, &s);
1316
1317	hw_crtc_timing->h_total = s.h_total + 1;
1318	hw_crtc_timing->h_addressable = s.h_total - ((s.h_total - s.h_blank_start) + s.h_blank_end);
1319	hw_crtc_timing->h_front_porch = s.h_total + 1 - s.h_blank_start;
1320	hw_crtc_timing->h_sync_width = s.h_sync_a_end - s.h_sync_a_start;
1321
1322	hw_crtc_timing->v_total = s.v_total + 1;
1323	hw_crtc_timing->v_addressable = s.v_total - ((s.v_total - s.v_blank_start) + s.v_blank_end);
1324	hw_crtc_timing->v_front_porch = s.v_total + 1 - s.v_blank_start;
1325	hw_crtc_timing->v_sync_width = s.v_sync_a_end - s.v_sync_a_start;
1326
1327	return true;
1328}
1329
1330
1331void optc1_read_otg_state(struct timing_generator *optc,
1332		struct dcn_otg_state *s)
1333{
1334	struct optc *optc1 = DCN10TG_FROM_TG(optc);
1335
1336	REG_GET(OTG_CONTROL,
1337			OTG_MASTER_EN, &s->otg_enabled);
1338
1339	REG_GET_2(OTG_V_BLANK_START_END,
1340			OTG_V_BLANK_START, &s->v_blank_start,
1341			OTG_V_BLANK_END, &s->v_blank_end);
1342
1343	REG_GET(OTG_V_SYNC_A_CNTL,
1344			OTG_V_SYNC_A_POL, &s->v_sync_a_pol);
1345
1346	REG_GET(OTG_V_TOTAL,
1347			OTG_V_TOTAL, &s->v_total);
1348
1349	REG_GET(OTG_V_TOTAL_MAX,
1350			OTG_V_TOTAL_MAX, &s->v_total_max);
1351
1352	REG_GET(OTG_V_TOTAL_MIN,
1353			OTG_V_TOTAL_MIN, &s->v_total_min);
1354
1355	REG_GET(OTG_V_TOTAL_CONTROL,
1356			OTG_V_TOTAL_MAX_SEL, &s->v_total_max_sel);
1357
1358	REG_GET(OTG_V_TOTAL_CONTROL,
1359			OTG_V_TOTAL_MIN_SEL, &s->v_total_min_sel);
1360
1361	REG_GET_2(OTG_V_SYNC_A,
1362			OTG_V_SYNC_A_START, &s->v_sync_a_start,
1363			OTG_V_SYNC_A_END, &s->v_sync_a_end);
1364
1365	REG_GET_2(OTG_H_BLANK_START_END,
1366			OTG_H_BLANK_START, &s->h_blank_start,
1367			OTG_H_BLANK_END, &s->h_blank_end);
1368
1369	REG_GET_2(OTG_H_SYNC_A,
1370			OTG_H_SYNC_A_START, &s->h_sync_a_start,
1371			OTG_H_SYNC_A_END, &s->h_sync_a_end);
1372
1373	REG_GET(OTG_H_SYNC_A_CNTL,
1374			OTG_H_SYNC_A_POL, &s->h_sync_a_pol);
1375
1376	REG_GET(OTG_H_TOTAL,
1377			OTG_H_TOTAL, &s->h_total);
1378
1379	REG_GET(OPTC_INPUT_GLOBAL_CONTROL,
1380			OPTC_UNDERFLOW_OCCURRED_STATUS, &s->underflow_occurred_status);
1381
1382	REG_GET(OTG_VERTICAL_INTERRUPT1_CONTROL,
1383			OTG_VERTICAL_INTERRUPT1_INT_ENABLE, &s->vertical_interrupt1_en);
1384
1385	REG_GET(OTG_VERTICAL_INTERRUPT1_POSITION,
1386				OTG_VERTICAL_INTERRUPT1_LINE_START, &s->vertical_interrupt1_line);
1387
1388	REG_GET(OTG_VERTICAL_INTERRUPT2_CONTROL,
1389			OTG_VERTICAL_INTERRUPT2_INT_ENABLE, &s->vertical_interrupt2_en);
1390
1391	REG_GET(OTG_VERTICAL_INTERRUPT2_POSITION,
1392			OTG_VERTICAL_INTERRUPT2_LINE_START, &s->vertical_interrupt2_line);
1393
1394	s->otg_master_update_lock = REG_READ(OTG_MASTER_UPDATE_LOCK);
1395	s->otg_double_buffer_control = REG_READ(OTG_DOUBLE_BUFFER_CONTROL);
1396}
1397
1398bool optc1_get_otg_active_size(struct timing_generator *optc,
1399		uint32_t *otg_active_width,
1400		uint32_t *otg_active_height)
1401{
1402	uint32_t otg_enabled;
1403	uint32_t v_blank_start;
1404	uint32_t v_blank_end;
1405	uint32_t h_blank_start;
1406	uint32_t h_blank_end;
1407	struct optc *optc1 = DCN10TG_FROM_TG(optc);
1408
1409
1410	REG_GET(OTG_CONTROL,
1411			OTG_MASTER_EN, &otg_enabled);
1412
1413	if (otg_enabled == 0)
1414		return false;
1415
1416	REG_GET_2(OTG_V_BLANK_START_END,
1417			OTG_V_BLANK_START, &v_blank_start,
1418			OTG_V_BLANK_END, &v_blank_end);
1419
1420	REG_GET_2(OTG_H_BLANK_START_END,
1421			OTG_H_BLANK_START, &h_blank_start,
1422			OTG_H_BLANK_END, &h_blank_end);
1423
1424	*otg_active_width = h_blank_start - h_blank_end;
1425	*otg_active_height = v_blank_start - v_blank_end;
1426	return true;
1427}
1428
1429void optc1_clear_optc_underflow(struct timing_generator *optc)
1430{
1431	struct optc *optc1 = DCN10TG_FROM_TG(optc);
1432
1433	REG_UPDATE(OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_CLEAR, 1);
1434}
1435
1436void optc1_tg_init(struct timing_generator *optc)
1437{
1438	optc1_set_blank_data_double_buffer(optc, true);
1439	optc1_set_timing_double_buffer(optc, true);
1440	optc1_clear_optc_underflow(optc);
1441}
1442
1443bool optc1_is_tg_enabled(struct timing_generator *optc)
1444{
1445	struct optc *optc1 = DCN10TG_FROM_TG(optc);
1446	uint32_t otg_enabled = 0;
1447
1448	REG_GET(OTG_CONTROL, OTG_MASTER_EN, &otg_enabled);
1449
1450	return (otg_enabled != 0);
1451
1452}
1453
1454bool optc1_is_optc_underflow_occurred(struct timing_generator *optc)
1455{
1456	struct optc *optc1 = DCN10TG_FROM_TG(optc);
1457	uint32_t underflow_occurred = 0;
1458
1459	REG_GET(OPTC_INPUT_GLOBAL_CONTROL,
1460			OPTC_UNDERFLOW_OCCURRED_STATUS,
1461			&underflow_occurred);
1462
1463	return (underflow_occurred == 1);
1464}
1465
1466bool optc1_configure_crc(struct timing_generator *optc,
1467			  const struct crc_params *params)
1468{
1469	struct optc *optc1 = DCN10TG_FROM_TG(optc);
1470
1471	/* Cannot configure crc on a CRTC that is disabled */
1472	if (!optc1_is_tg_enabled(optc))
1473		return false;
1474
1475	if (!params->enable || params->reset)
1476		REG_WRITE(OTG_CRC_CNTL, 0);
1477
1478	if (!params->enable)
1479		return true;
1480
1481	/* Program frame boundaries */
1482	switch (params->crc_eng_inst) {
1483	case 0:
1484		/* Window A x axis start and end. */
1485		REG_UPDATE_2(OTG_CRC0_WINDOWA_X_CONTROL,
1486				OTG_CRC0_WINDOWA_X_START, params->windowa_x_start,
1487				OTG_CRC0_WINDOWA_X_END, params->windowa_x_end);
1488
1489		/* Window A y axis start and end. */
1490		REG_UPDATE_2(OTG_CRC0_WINDOWA_Y_CONTROL,
1491				OTG_CRC0_WINDOWA_Y_START, params->windowa_y_start,
1492				OTG_CRC0_WINDOWA_Y_END, params->windowa_y_end);
1493
1494		/* Window B x axis start and end. */
1495		REG_UPDATE_2(OTG_CRC0_WINDOWB_X_CONTROL,
1496				OTG_CRC0_WINDOWB_X_START, params->windowb_x_start,
1497				OTG_CRC0_WINDOWB_X_END, params->windowb_x_end);
1498
1499		/* Window B y axis start and end. */
1500		REG_UPDATE_2(OTG_CRC0_WINDOWB_Y_CONTROL,
1501				OTG_CRC0_WINDOWB_Y_START, params->windowb_y_start,
1502				OTG_CRC0_WINDOWB_Y_END, params->windowb_y_end);
1503
1504		/* Set crc mode and selection, and enable.*/
1505		REG_UPDATE_3(OTG_CRC_CNTL,
1506				OTG_CRC_CONT_EN, params->continuous_mode ? 1 : 0,
1507				OTG_CRC0_SELECT, params->selection,
1508				OTG_CRC_EN, 1);
1509		break;
1510	case 1:
1511		/* Window A x axis start and end. */
1512		REG_UPDATE_2(OTG_CRC1_WINDOWA_X_CONTROL,
1513				OTG_CRC1_WINDOWA_X_START, params->windowa_x_start,
1514				OTG_CRC1_WINDOWA_X_END, params->windowa_x_end);
1515
1516		/* Window A y axis start and end. */
1517		REG_UPDATE_2(OTG_CRC1_WINDOWA_Y_CONTROL,
1518				OTG_CRC1_WINDOWA_Y_START, params->windowa_y_start,
1519				OTG_CRC1_WINDOWA_Y_END, params->windowa_y_end);
1520
1521		/* Window B x axis start and end. */
1522		REG_UPDATE_2(OTG_CRC1_WINDOWB_X_CONTROL,
1523				OTG_CRC1_WINDOWB_X_START, params->windowb_x_start,
1524				OTG_CRC1_WINDOWB_X_END, params->windowb_x_end);
1525
1526		/* Window B y axis start and end. */
1527		REG_UPDATE_2(OTG_CRC1_WINDOWB_Y_CONTROL,
1528				OTG_CRC1_WINDOWB_Y_START, params->windowb_y_start,
1529				OTG_CRC1_WINDOWB_Y_END, params->windowb_y_end);
1530
1531		/* Set crc mode and selection, and enable.*/
1532		REG_UPDATE_3(OTG_CRC_CNTL,
1533				OTG_CRC_CONT_EN, params->continuous_mode ? 1 : 0,
1534				OTG_CRC1_SELECT, params->selection,
1535				OTG_CRC_EN, 1);
1536		break;
1537	default:
1538		return false;
1539	}
1540
1541	return true;
1542}
1543
1544/**
1545 * optc1_get_crc - Capture CRC result per component
1546 *
1547 * @optc: timing_generator instance.
1548 * @idx: index of crc engine to get CRC from
1549 * @r_cr: 16-bit primary CRC signature for red data.
1550 * @g_y: 16-bit primary CRC signature for green data.
1551 * @b_cb: 16-bit primary CRC signature for blue data.
1552 *
1553 * This function reads the CRC signature from the OPTC registers. Notice that
1554 * we have three registers to keep the CRC result per color component (RGB).
1555 *
1556 * Returns:
1557 * If CRC is disabled, return false; otherwise, return true, and the CRC
1558 * results in the parameters.
1559 */
1560bool optc1_get_crc(struct timing_generator *optc, uint8_t idx,
1561		   uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb)
1562{
1563	uint32_t field = 0;
1564	struct optc *optc1 = DCN10TG_FROM_TG(optc);
1565
1566	REG_GET(OTG_CRC_CNTL, OTG_CRC_EN, &field);
1567
1568	/* Early return if CRC is not enabled for this CRTC */
1569	if (!field)
1570		return false;
1571
1572	switch (idx) {
1573	case 0:
1574		/* OTG_CRC0_DATA_RG has the CRC16 results for the red and green component */
1575		REG_GET_2(OTG_CRC0_DATA_RG,
1576			  CRC0_R_CR, r_cr,
1577			  CRC0_G_Y, g_y);
1578
1579		/* OTG_CRC0_DATA_B has the CRC16 results for the blue component */
1580		REG_GET(OTG_CRC0_DATA_B,
1581			CRC0_B_CB, b_cb);
1582		break;
1583	case 1:
1584		/* OTG_CRC1_DATA_RG has the CRC16 results for the red and green component */
1585		REG_GET_2(OTG_CRC1_DATA_RG,
1586			  CRC1_R_CR, r_cr,
1587			  CRC1_G_Y, g_y);
1588
1589		/* OTG_CRC1_DATA_B has the CRC16 results for the blue component */
1590		REG_GET(OTG_CRC1_DATA_B,
1591			CRC1_B_CB, b_cb);
1592		break;
1593	default:
1594		return false;
1595	}
1596
1597	return true;
1598}
1599
1600/* "Container" vs. "pixel" is a concept within HW blocks, mostly those closer to the back-end. It works like this:
1601 *
1602 * - In most of the formats (RGB or YCbCr 4:4:4, 4:2:2 uncompressed and DSC 4:2:2 Simple) pixel rate is the same as
1603 *   container rate.
1604 *
1605 * - In 4:2:0 (DSC or uncompressed) there are two pixels per container, hence the target container rate has to be
1606 *   halved to maintain the correct pixel rate.
1607 *
1608 * - Unlike 4:2:2 uncompressed, DSC 4:2:2 Native also has two pixels per container (this happens when DSC is applied
1609 *   to it) and has to be treated the same as 4:2:0, i.e. target containter rate has to be halved in this case as well.
1610 *
1611 */
1612bool optc1_is_two_pixels_per_container(const struct dc_crtc_timing *timing)
1613{
1614	bool two_pix = timing->pixel_encoding == PIXEL_ENCODING_YCBCR420;
1615
1616	two_pix = two_pix || (timing->flags.DSC && timing->pixel_encoding == PIXEL_ENCODING_YCBCR422
1617			&& !timing->dsc_cfg.ycbcr422_simple);
1618	return two_pix;
1619}
1620
1621static const struct timing_generator_funcs dcn10_tg_funcs = {
1622		.validate_timing = optc1_validate_timing,
1623		.program_timing = optc1_program_timing,
1624		.setup_vertical_interrupt0 = optc1_setup_vertical_interrupt0,
1625		.setup_vertical_interrupt1 = optc1_setup_vertical_interrupt1,
1626		.setup_vertical_interrupt2 = optc1_setup_vertical_interrupt2,
1627		.program_global_sync = optc1_program_global_sync,
1628		.enable_crtc = optc1_enable_crtc,
1629		.disable_crtc = optc1_disable_crtc,
1630		/* used by enable_timing_synchronization. Not need for FPGA */
1631		.is_counter_moving = optc1_is_counter_moving,
1632		.get_position = optc1_get_position,
1633		.get_frame_count = optc1_get_vblank_counter,
1634		.get_scanoutpos = optc1_get_crtc_scanoutpos,
1635		.get_otg_active_size = optc1_get_otg_active_size,
1636		.set_early_control = optc1_set_early_control,
1637		/* used by enable_timing_synchronization. Not need for FPGA */
1638		.wait_for_state = optc1_wait_for_state,
1639		.set_blank = optc1_set_blank,
1640		.is_blanked = optc1_is_blanked,
1641		.set_blank_color = optc1_program_blank_color,
1642		.did_triggered_reset_occur = optc1_did_triggered_reset_occur,
1643		.enable_reset_trigger = optc1_enable_reset_trigger,
1644		.enable_crtc_reset = optc1_enable_crtc_reset,
1645		.disable_reset_trigger = optc1_disable_reset_trigger,
1646		.lock = optc1_lock,
1647		.unlock = optc1_unlock,
1648		.enable_optc_clock = optc1_enable_optc_clock,
1649		.set_drr = optc1_set_drr,
1650		.get_last_used_drr_vtotal = NULL,
1651		.set_vtotal_min_max = optc1_set_vtotal_min_max,
1652		.set_static_screen_control = optc1_set_static_screen_control,
1653		.set_test_pattern = optc1_set_test_pattern,
1654		.program_stereo = optc1_program_stereo,
1655		.is_stereo_left_eye = optc1_is_stereo_left_eye,
1656		.set_blank_data_double_buffer = optc1_set_blank_data_double_buffer,
1657		.tg_init = optc1_tg_init,
1658		.is_tg_enabled = optc1_is_tg_enabled,
1659		.is_optc_underflow_occurred = optc1_is_optc_underflow_occurred,
1660		.clear_optc_underflow = optc1_clear_optc_underflow,
1661		.get_crc = optc1_get_crc,
1662		.configure_crc = optc1_configure_crc,
1663		.set_vtg_params = optc1_set_vtg_params,
1664		.program_manual_trigger = optc1_program_manual_trigger,
1665		.setup_manual_trigger = optc1_setup_manual_trigger,
1666		.get_hw_timing = optc1_get_hw_timing,
1667		.is_two_pixels_per_container = optc1_is_two_pixels_per_container,
1668		.read_otg_state = optc1_read_otg_state,
1669};
1670
1671void dcn10_timing_generator_init(struct optc *optc1)
1672{
1673	optc1->base.funcs = &dcn10_tg_funcs;
1674
1675	optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1;
1676	optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1;
1677
1678	optc1->min_h_blank = 32;
1679	optc1->min_v_blank = 3;
1680	optc1->min_v_blank_interlace = 5;
1681	optc1->min_h_sync_width = 4;
1682	optc1->min_v_sync_width = 1;
1683}
~/ Read-only file preview.