Home | History | Annotate | Line # | Download | only in dce110
      1 /*	$NetBSD: amdgpu_dce110_timing_generator.c,v 1.3 2021/12/19 10:59:02 riastradh Exp $	*/
      2 
      3 /*
      4  * Copyright 2012-15 Advanced Micro Devices, Inc.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included in
     14  * all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     19  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
     20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     22  * OTHER DEALINGS IN THE SOFTWARE.
     23  *
     24  * Authors: AMD
     25  *
     26  */
     27 
     28 #include <sys/cdefs.h>
     29 __KERNEL_RCSID(0, "$NetBSD: amdgpu_dce110_timing_generator.c,v 1.3 2021/12/19 10:59:02 riastradh Exp $");
     30 
     31 #include "dm_services.h"
     32 
     33 /* include DCE11 register header files */
     34 #include "dce/dce_11_0_d.h"
     35 #include "dce/dce_11_0_sh_mask.h"
     36 
     37 #include "dc_types.h"
     38 #include "dc_bios_types.h"
     39 #include "dc.h"
     40 
     41 #include "include/grph_object_id.h"
     42 #include "include/logger_interface.h"
     43 #include "dce110_timing_generator.h"
     44 
     45 #include "timing_generator.h"
     46 
     47 
     48 #define NUMBER_OF_FRAME_TO_WAIT_ON_TRIGGERED_RESET 10
     49 
     50 #define MAX_H_TOTAL (CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1)
     51 #define MAX_V_TOTAL (CRTC_V_TOTAL__CRTC_V_TOTAL_MASKhw + 1)
     52 
     53 #define CRTC_REG(reg) (reg + tg110->offsets.crtc)
     54 #define DCP_REG(reg) (reg + tg110->offsets.dcp)
     55 
     56 /* Flowing register offsets are same in files of
     57  * dce/dce_11_0_d.h
     58  * dce/vi_polaris10_p/vi_polaris10_d.h
     59  *
     60  * So we can create dce110 timing generator to use it.
     61  */
     62 
     63 
     64 /*
     65 * apply_front_porch_workaround
     66 *
     67 * This is a workaround for a bug that has existed since R5xx and has not been
     68 * fixed keep Front porch at minimum 2 for Interlaced mode or 1 for progressive.
     69 */
     70 static void dce110_timing_generator_apply_front_porch_workaround(
     71 	struct timing_generator *tg,
     72 	struct dc_crtc_timing *timing)
     73 {
     74 	if (timing->flags.INTERLACE == 1) {
     75 		if (timing->v_front_porch < 2)
     76 			timing->v_front_porch = 2;
     77 	} else {
     78 		if (timing->v_front_porch < 1)
     79 			timing->v_front_porch = 1;
     80 	}
     81 }
     82 
     83 /**
     84  *****************************************************************************
     85  *  Function: is_in_vertical_blank
     86  *
     87  *  @brief
     88  *     check the current status of CRTC to check if we are in Vertical Blank
     89  *     regioneased" state
     90  *
     91  *  @return
     92  *     true if currently in blank region, false otherwise
     93  *
     94  *****************************************************************************
     95  */
     96 static bool dce110_timing_generator_is_in_vertical_blank(
     97 		struct timing_generator *tg)
     98 {
     99 	uint32_t addr = 0;
    100 	uint32_t value = 0;
    101 	uint32_t field = 0;
    102 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
    103 
    104 	addr = CRTC_REG(mmCRTC_STATUS);
    105 	value = dm_read_reg(tg->ctx, addr);
    106 	field = get_reg_field_value(value, CRTC_STATUS, CRTC_V_BLANK);
    107 	return field == 1;
    108 }
    109 
    110 void dce110_timing_generator_set_early_control(
    111 		struct timing_generator *tg,
    112 		uint32_t early_cntl)
    113 {
    114 	uint32_t regval;
    115 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
    116 	uint32_t address = CRTC_REG(mmCRTC_CONTROL);
    117 
    118 	regval = dm_read_reg(tg->ctx, address);
    119 	set_reg_field_value(regval, early_cntl,
    120 			CRTC_CONTROL, CRTC_HBLANK_EARLY_CONTROL);
    121 	dm_write_reg(tg->ctx, address, regval);
    122 }
    123 
    124 /**
    125  * Enable CRTC
    126  * Enable CRTC - call ASIC Control Object to enable Timing generator.
    127  */
    128 bool dce110_timing_generator_enable_crtc(struct timing_generator *tg)
    129 {
    130 	enum bp_result result;
    131 
    132 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
    133 	uint32_t value = 0;
    134 
    135 	/*
    136 	 * 3 is used to make sure V_UPDATE occurs at the beginning of the first
    137 	 * line of vertical front porch
    138 	 */
    139 	set_reg_field_value(
    140 		value,
    141 		0,
    142 		CRTC_MASTER_UPDATE_MODE,
    143 		MASTER_UPDATE_MODE);
    144 
    145 	dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_MASTER_UPDATE_MODE), value);
    146 
    147 	/* TODO: may want this on to catch underflow */
    148 	value = 0;
    149 	dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_MASTER_UPDATE_LOCK), value);
    150 
    151 	result = tg->bp->funcs->enable_crtc(tg->bp, tg110->controller_id, true);
    152 
    153 	return result == BP_RESULT_OK;
    154 }
    155 
    156 void dce110_timing_generator_program_blank_color(
    157 		struct timing_generator *tg,
    158 		const struct tg_color *black_color)
    159 {
    160 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
    161 	uint32_t addr = CRTC_REG(mmCRTC_BLACK_COLOR);
    162 	uint32_t value = dm_read_reg(tg->ctx, addr);
    163 
    164 	set_reg_field_value(
    165 		value,
    166 		black_color->color_b_cb,
    167 		CRTC_BLACK_COLOR,
    168 		CRTC_BLACK_COLOR_B_CB);
    169 	set_reg_field_value(
    170 		value,
    171 		black_color->color_g_y,
    172 		CRTC_BLACK_COLOR,
    173 		CRTC_BLACK_COLOR_G_Y);
    174 	set_reg_field_value(
    175 		value,
    176 		black_color->color_r_cr,
    177 		CRTC_BLACK_COLOR,
    178 		CRTC_BLACK_COLOR_R_CR);
    179 
    180 	dm_write_reg(tg->ctx, addr, value);
    181 }
    182 
    183 /**
    184  *****************************************************************************
    185  *  Function: disable_stereo
    186  *
    187  *  @brief
    188  *     Disables active stereo on controller
    189  *     Frame Packing need to be disabled in vBlank or when CRTC not running
    190  *****************************************************************************
    191  */
    192 #if 0
    193 @TODOSTEREO
    194 static void disable_stereo(struct timing_generator *tg)
    195 {
    196 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
    197 	uint32_t addr = CRTC_REG(mmCRTC_3D_STRUCTURE_CONTROL);
    198 	uint32_t value = 0;
    199 	uint32_t test = 0;
    200 	uint32_t field = 0;
    201 	uint32_t struc_en = 0;
    202 	uint32_t struc_stereo_sel_ovr = 0;
    203 
    204 	value = dm_read_reg(tg->ctx, addr);
    205 	struc_en = get_reg_field_value(
    206 			value,
    207 			CRTC_3D_STRUCTURE_CONTROL,
    208 			CRTC_3D_STRUCTURE_EN);
    209 
    210 	struc_stereo_sel_ovr = get_reg_field_value(
    211 			value,
    212 			CRTC_3D_STRUCTURE_CONTROL,
    213 			CRTC_3D_STRUCTURE_STEREO_SEL_OVR);
    214 
    215 	/*
    216 	 * When disabling Frame Packing in 2 step mode, we need to program both
    217 	 * registers at the same frame
    218 	 * Programming it in the beginning of VActive makes sure we are ok
    219 	 */
    220 
    221 	if (struc_en != 0 && struc_stereo_sel_ovr == 0) {
    222 		tg->funcs->wait_for_vblank(tg);
    223 		tg->funcs->wait_for_vactive(tg);
    224 	}
    225 
    226 	value = 0;
    227 	dm_write_reg(tg->ctx, addr, value);
    228 
    229 	addr = tg->regs[IDX_CRTC_STEREO_CONTROL];
    230 	dm_write_reg(tg->ctx, addr, value);
    231 }
    232 #endif
    233 
    234 /**
    235  * disable_crtc - call ASIC Control Object to disable Timing generator.
    236  */
    237 bool dce110_timing_generator_disable_crtc(struct timing_generator *tg)
    238 {
    239 	enum bp_result result;
    240 
    241 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
    242 
    243 	result = tg->bp->funcs->enable_crtc(tg->bp, tg110->controller_id, false);
    244 
    245 	/* Need to make sure stereo is disabled according to the DCE5.0 spec */
    246 
    247 	/*
    248 	 * @TODOSTEREO call this when adding stereo support
    249 	 * tg->funcs->disable_stereo(tg);
    250 	 */
    251 
    252 	return result == BP_RESULT_OK;
    253 }
    254 
    255 /**
    256 * program_horz_count_by_2
    257 * Programs DxCRTC_HORZ_COUNT_BY2_EN - 1 for DVI 30bpp mode, 0 otherwise
    258 *
    259 */
    260 static void program_horz_count_by_2(
    261 	struct timing_generator *tg,
    262 	const struct dc_crtc_timing *timing)
    263 {
    264 	uint32_t regval;
    265 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
    266 
    267 	regval = dm_read_reg(tg->ctx,
    268 			CRTC_REG(mmCRTC_COUNT_CONTROL));
    269 
    270 	set_reg_field_value(regval, 0, CRTC_COUNT_CONTROL,
    271 			CRTC_HORZ_COUNT_BY2_EN);
    272 
    273 	if (timing->flags.HORZ_COUNT_BY_TWO)
    274 		set_reg_field_value(regval, 1, CRTC_COUNT_CONTROL,
    275 					CRTC_HORZ_COUNT_BY2_EN);
    276 
    277 	dm_write_reg(tg->ctx,
    278 			CRTC_REG(mmCRTC_COUNT_CONTROL), regval);
    279 }
    280 
    281 /**
    282  * program_timing_generator
    283  * Program CRTC Timing Registers - DxCRTC_H_*, DxCRTC_V_*, Pixel repetition.
    284  * Call ASIC Control Object to program Timings.
    285  */
    286 bool dce110_timing_generator_program_timing_generator(
    287 	struct timing_generator *tg,
    288 	const struct dc_crtc_timing *dc_crtc_timing)
    289 {
    290 	enum bp_result result;
    291 	struct bp_hw_crtc_timing_parameters bp_params;
    292 	struct dc_crtc_timing patched_crtc_timing;
    293 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
    294 
    295 	uint32_t vsync_offset = dc_crtc_timing->v_border_bottom +
    296 			dc_crtc_timing->v_front_porch;
    297 	uint32_t v_sync_start =dc_crtc_timing->v_addressable + vsync_offset;
    298 
    299 	uint32_t hsync_offset = dc_crtc_timing->h_border_right +
    300 			dc_crtc_timing->h_front_porch;
    301 	uint32_t h_sync_start = dc_crtc_timing->h_addressable + hsync_offset;
    302 
    303 	memset(&bp_params, 0, sizeof(struct bp_hw_crtc_timing_parameters));
    304 
    305 	/* Due to an asic bug we need to apply the Front Porch workaround prior
    306 	 * to programming the timing.
    307 	 */
    308 
    309 	patched_crtc_timing = *dc_crtc_timing;
    310 
    311 	dce110_timing_generator_apply_front_porch_workaround(tg, &patched_crtc_timing);
    312 
    313 	bp_params.controller_id = tg110->controller_id;
    314 
    315 	bp_params.h_total = patched_crtc_timing.h_total;
    316 	bp_params.h_addressable =
    317 		patched_crtc_timing.h_addressable;
    318 	bp_params.v_total = patched_crtc_timing.v_total;
    319 	bp_params.v_addressable = patched_crtc_timing.v_addressable;
    320 
    321 	bp_params.h_sync_start = h_sync_start;
    322 	bp_params.h_sync_width = patched_crtc_timing.h_sync_width;
    323 	bp_params.v_sync_start = v_sync_start;
    324 	bp_params.v_sync_width = patched_crtc_timing.v_sync_width;
    325 
    326 	/* Set overscan */
    327 	bp_params.h_overscan_left =
    328 		patched_crtc_timing.h_border_left;
    329 	bp_params.h_overscan_right =
    330 		patched_crtc_timing.h_border_right;
    331 	bp_params.v_overscan_top = patched_crtc_timing.v_border_top;
    332 	bp_params.v_overscan_bottom =
    333 		patched_crtc_timing.v_border_bottom;
    334 
    335 	/* Set flags */
    336 	if (patched_crtc_timing.flags.HSYNC_POSITIVE_POLARITY == 1)
    337 		bp_params.flags.HSYNC_POSITIVE_POLARITY = 1;
    338 
    339 	if (patched_crtc_timing.flags.VSYNC_POSITIVE_POLARITY == 1)
    340 		bp_params.flags.VSYNC_POSITIVE_POLARITY = 1;
    341 
    342 	if (patched_crtc_timing.flags.INTERLACE == 1)
    343 		bp_params.flags.INTERLACE = 1;
    344 
    345 	if (patched_crtc_timing.flags.HORZ_COUNT_BY_TWO == 1)
    346 		bp_params.flags.HORZ_COUNT_BY_TWO = 1;
    347 
    348 	result = tg->bp->funcs->program_crtc_timing(tg->bp, &bp_params);
    349 
    350 	program_horz_count_by_2(tg, &patched_crtc_timing);
    351 
    352 	tg110->base.funcs->enable_advanced_request(tg, true, &patched_crtc_timing);
    353 
    354 	/* Enable stereo - only when we need to pack 3D frame. Other types
    355 	 * of stereo handled in explicit call */
    356 
    357 	return result == BP_RESULT_OK;
    358 }
    359 
    360 /**
    361  *****************************************************************************
    362  *  Function: set_drr
    363  *
    364  *  @brief
    365  *     Program dynamic refresh rate registers m_DxCRTC_V_TOTAL_*.
    366  *
    367  *  @param [in] pHwCrtcTiming: point to H
    368  *  wCrtcTiming struct
    369  *****************************************************************************
    370  */
    371 void dce110_timing_generator_set_drr(
    372 	struct timing_generator *tg,
    373 	const struct drr_params *params)
    374 {
    375 	/* register values */
    376 	uint32_t v_total_min = 0;
    377 	uint32_t v_total_max = 0;
    378 	uint32_t v_total_cntl = 0;
    379 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
    380 
    381 	uint32_t addr = 0;
    382 
    383 	addr = CRTC_REG(mmCRTC_V_TOTAL_MIN);
    384 	v_total_min = dm_read_reg(tg->ctx, addr);
    385 
    386 	addr = CRTC_REG(mmCRTC_V_TOTAL_MAX);
    387 	v_total_max = dm_read_reg(tg->ctx, addr);
    388 
    389 	addr = CRTC_REG(mmCRTC_V_TOTAL_CONTROL);
    390 	v_total_cntl = dm_read_reg(tg->ctx, addr);
    391 
    392 	if (params != NULL &&
    393 		params->vertical_total_max > 0 &&
    394 		params->vertical_total_min > 0) {
    395 
    396 		set_reg_field_value(v_total_max,
    397 				params->vertical_total_max - 1,
    398 				CRTC_V_TOTAL_MAX,
    399 				CRTC_V_TOTAL_MAX);
    400 
    401 		set_reg_field_value(v_total_min,
    402 				params->vertical_total_min - 1,
    403 				CRTC_V_TOTAL_MIN,
    404 				CRTC_V_TOTAL_MIN);
    405 
    406 		set_reg_field_value(v_total_cntl,
    407 				1,
    408 				CRTC_V_TOTAL_CONTROL,
    409 				CRTC_V_TOTAL_MIN_SEL);
    410 
    411 		set_reg_field_value(v_total_cntl,
    412 				1,
    413 				CRTC_V_TOTAL_CONTROL,
    414 				CRTC_V_TOTAL_MAX_SEL);
    415 
    416 		set_reg_field_value(v_total_cntl,
    417 				0,
    418 				CRTC_V_TOTAL_CONTROL,
    419 				CRTC_FORCE_LOCK_ON_EVENT);
    420 		set_reg_field_value(v_total_cntl,
    421 				0,
    422 				CRTC_V_TOTAL_CONTROL,
    423 				CRTC_FORCE_LOCK_TO_MASTER_VSYNC);
    424 
    425 		set_reg_field_value(v_total_cntl,
    426 				0,
    427 				CRTC_V_TOTAL_CONTROL,
    428 				CRTC_SET_V_TOTAL_MIN_MASK_EN);
    429 
    430 		set_reg_field_value(v_total_cntl,
    431 				0,
    432 				CRTC_V_TOTAL_CONTROL,
    433 				CRTC_SET_V_TOTAL_MIN_MASK);
    434 	} else {
    435 		set_reg_field_value(v_total_cntl,
    436 			0,
    437 			CRTC_V_TOTAL_CONTROL,
    438 			CRTC_SET_V_TOTAL_MIN_MASK);
    439 		set_reg_field_value(v_total_cntl,
    440 				0,
    441 				CRTC_V_TOTAL_CONTROL,
    442 				CRTC_V_TOTAL_MIN_SEL);
    443 		set_reg_field_value(v_total_cntl,
    444 				0,
    445 				CRTC_V_TOTAL_CONTROL,
    446 				CRTC_V_TOTAL_MAX_SEL);
    447 		set_reg_field_value(v_total_min,
    448 				0,
    449 				CRTC_V_TOTAL_MIN,
    450 				CRTC_V_TOTAL_MIN);
    451 		set_reg_field_value(v_total_max,
    452 				0,
    453 				CRTC_V_TOTAL_MAX,
    454 				CRTC_V_TOTAL_MAX);
    455 		set_reg_field_value(v_total_cntl,
    456 				0,
    457 				CRTC_V_TOTAL_CONTROL,
    458 				CRTC_FORCE_LOCK_ON_EVENT);
    459 		set_reg_field_value(v_total_cntl,
    460 				0,
    461 				CRTC_V_TOTAL_CONTROL,
    462 				CRTC_FORCE_LOCK_TO_MASTER_VSYNC);
    463 	}
    464 
    465 	addr = CRTC_REG(mmCRTC_V_TOTAL_MIN);
    466 	dm_write_reg(tg->ctx, addr, v_total_min);
    467 
    468 	addr = CRTC_REG(mmCRTC_V_TOTAL_MAX);
    469 	dm_write_reg(tg->ctx, addr, v_total_max);
    470 
    471 	addr = CRTC_REG(mmCRTC_V_TOTAL_CONTROL);
    472 	dm_write_reg(tg->ctx, addr, v_total_cntl);
    473 }
    474 
    475 void dce110_timing_generator_set_static_screen_control(
    476 	struct timing_generator *tg,
    477 	uint32_t event_triggers,
    478 	uint32_t num_frames)
    479 {
    480 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
    481 	uint32_t static_screen_cntl = 0;
    482 	uint32_t addr = 0;
    483 
    484 	// By register spec, it only takes 8 bit value
    485 	if (num_frames > 0xFF)
    486 		num_frames = 0xFF;
    487 
    488 	addr = CRTC_REG(mmCRTC_STATIC_SCREEN_CONTROL);
    489 	static_screen_cntl = dm_read_reg(tg->ctx, addr);
    490 
    491 	set_reg_field_value(static_screen_cntl,
    492 				event_triggers,
    493 				CRTC_STATIC_SCREEN_CONTROL,
    494 				CRTC_STATIC_SCREEN_EVENT_MASK);
    495 
    496 	set_reg_field_value(static_screen_cntl,
    497 				num_frames,
    498 				CRTC_STATIC_SCREEN_CONTROL,
    499 				CRTC_STATIC_SCREEN_FRAME_COUNT);
    500 
    501 	dm_write_reg(tg->ctx, addr, static_screen_cntl);
    502 }
    503 
    504 /*
    505  * get_vblank_counter
    506  *
    507  * @brief
    508  * Get counter for vertical blanks. use register CRTC_STATUS_FRAME_COUNT which
    509  * holds the counter of frames.
    510  *
    511  * @param
    512  * struct timing_generator *tg - [in] timing generator which controls the
    513  * desired CRTC
    514  *
    515  * @return
    516  * Counter of frames, which should equal to number of vblanks.
    517  */
    518 uint32_t dce110_timing_generator_get_vblank_counter(struct timing_generator *tg)
    519 {
    520 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
    521 	uint32_t addr = CRTC_REG(mmCRTC_STATUS_FRAME_COUNT);
    522 	uint32_t value = dm_read_reg(tg->ctx, addr);
    523 	uint32_t field = get_reg_field_value(
    524 			value, CRTC_STATUS_FRAME_COUNT, CRTC_FRAME_COUNT);
    525 
    526 	return field;
    527 }
    528 
    529 /**
    530  *****************************************************************************
    531  *  Function: dce110_timing_generator_get_position
    532  *
    533  *  @brief
    534  *     Returns CRTC vertical/horizontal counters
    535  *
    536  *  @param [out] position
    537  *****************************************************************************
    538  */
    539 void dce110_timing_generator_get_position(struct timing_generator *tg,
    540 	struct crtc_position *position)
    541 {
    542 	uint32_t value;
    543 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
    544 
    545 	value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_STATUS_POSITION));
    546 
    547 	position->horizontal_count = get_reg_field_value(
    548 			value,
    549 			CRTC_STATUS_POSITION,
    550 			CRTC_HORZ_COUNT);
    551 
    552 	position->vertical_count = get_reg_field_value(
    553 			value,
    554 			CRTC_STATUS_POSITION,
    555 			CRTC_VERT_COUNT);
    556 
    557 	value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_NOM_VERT_POSITION));
    558 
    559 	position->nominal_vcount = get_reg_field_value(
    560 			value,
    561 			CRTC_NOM_VERT_POSITION,
    562 			CRTC_VERT_COUNT_NOM);
    563 }
    564 
    565 /**
    566  *****************************************************************************
    567  *  Function: get_crtc_scanoutpos
    568  *
    569  *  @brief
    570  *     Returns CRTC vertical/horizontal counters
    571  *
    572  *  @param [out] vpos, hpos
    573  *****************************************************************************
    574  */
    575 void dce110_timing_generator_get_crtc_scanoutpos(
    576 	struct timing_generator *tg,
    577 	uint32_t *v_blank_start,
    578 	uint32_t *v_blank_end,
    579 	uint32_t *h_position,
    580 	uint32_t *v_position)
    581 {
    582 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
    583 	struct crtc_position position;
    584 
    585 	uint32_t value  = dm_read_reg(tg->ctx,
    586 			CRTC_REG(mmCRTC_V_BLANK_START_END));
    587 
    588 	*v_blank_start = get_reg_field_value(value,
    589 					     CRTC_V_BLANK_START_END,
    590 					     CRTC_V_BLANK_START);
    591 	*v_blank_end = get_reg_field_value(value,
    592 					   CRTC_V_BLANK_START_END,
    593 					   CRTC_V_BLANK_END);
    594 
    595 	dce110_timing_generator_get_position(
    596 			tg, &position);
    597 
    598 	*h_position = position.horizontal_count;
    599 	*v_position = position.vertical_count;
    600 }
    601 
    602 /* TODO: is it safe to assume that mask/shift of Primary and Underlay
    603  * are the same?
    604  * For example: today CRTC_H_TOTAL == CRTCV_H_TOTAL but is it always
    605  * guaranteed? */
    606 void dce110_timing_generator_program_blanking(
    607 	struct timing_generator *tg,
    608 	const struct dc_crtc_timing *timing)
    609 {
    610 	uint32_t vsync_offset = timing->v_border_bottom +
    611 			timing->v_front_porch;
    612 	uint32_t v_sync_start =timing->v_addressable + vsync_offset;
    613 
    614 	uint32_t hsync_offset = timing->h_border_right +
    615 			timing->h_front_porch;
    616 	uint32_t h_sync_start = timing->h_addressable + hsync_offset;
    617 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
    618 
    619 	struct dc_context *ctx = tg->ctx;
    620 	uint32_t value = 0;
    621 	uint32_t addr = 0;
    622 	uint32_t tmp = 0;
    623 
    624 	addr = CRTC_REG(mmCRTC_H_TOTAL);
    625 	value = dm_read_reg(ctx, addr);
    626 	set_reg_field_value(
    627 		value,
    628 		timing->h_total - 1,
    629 		CRTC_H_TOTAL,
    630 		CRTC_H_TOTAL);
    631 	dm_write_reg(ctx, addr, value);
    632 
    633 	addr = CRTC_REG(mmCRTC_V_TOTAL);
    634 	value = dm_read_reg(ctx, addr);
    635 	set_reg_field_value(
    636 		value,
    637 		timing->v_total - 1,
    638 		CRTC_V_TOTAL,
    639 		CRTC_V_TOTAL);
    640 	dm_write_reg(ctx, addr, value);
    641 
    642 	/* In case of V_TOTAL_CONTROL is on, make sure V_TOTAL_MAX and
    643 	 * V_TOTAL_MIN are equal to V_TOTAL.
    644 	 */
    645 	addr = CRTC_REG(mmCRTC_V_TOTAL_MAX);
    646 	value = dm_read_reg(ctx, addr);
    647 	set_reg_field_value(
    648 		value,
    649 		timing->v_total - 1,
    650 		CRTC_V_TOTAL_MAX,
    651 		CRTC_V_TOTAL_MAX);
    652 	dm_write_reg(ctx, addr, value);
    653 
    654 	addr = CRTC_REG(mmCRTC_V_TOTAL_MIN);
    655 	value = dm_read_reg(ctx, addr);
    656 	set_reg_field_value(
    657 		value,
    658 		timing->v_total - 1,
    659 		CRTC_V_TOTAL_MIN,
    660 		CRTC_V_TOTAL_MIN);
    661 	dm_write_reg(ctx, addr, value);
    662 
    663 	addr = CRTC_REG(mmCRTC_H_BLANK_START_END);
    664 	value = dm_read_reg(ctx, addr);
    665 
    666 	tmp = timing->h_total -
    667 		(h_sync_start + timing->h_border_left);
    668 
    669 	set_reg_field_value(
    670 		value,
    671 		tmp,
    672 		CRTC_H_BLANK_START_END,
    673 		CRTC_H_BLANK_END);
    674 
    675 	tmp = tmp + timing->h_addressable +
    676 		timing->h_border_left + timing->h_border_right;
    677 
    678 	set_reg_field_value(
    679 		value,
    680 		tmp,
    681 		CRTC_H_BLANK_START_END,
    682 		CRTC_H_BLANK_START);
    683 
    684 	dm_write_reg(ctx, addr, value);
    685 
    686 	addr = CRTC_REG(mmCRTC_V_BLANK_START_END);
    687 	value = dm_read_reg(ctx, addr);
    688 
    689 	tmp = timing->v_total - (v_sync_start + timing->v_border_top);
    690 
    691 	set_reg_field_value(
    692 		value,
    693 		tmp,
    694 		CRTC_V_BLANK_START_END,
    695 		CRTC_V_BLANK_END);
    696 
    697 	tmp = tmp + timing->v_addressable + timing->v_border_top +
    698 		timing->v_border_bottom;
    699 
    700 	set_reg_field_value(
    701 		value,
    702 		tmp,
    703 		CRTC_V_BLANK_START_END,
    704 		CRTC_V_BLANK_START);
    705 
    706 	dm_write_reg(ctx, addr, value);
    707 }
    708 
    709 void dce110_timing_generator_set_test_pattern(
    710 	struct timing_generator *tg,
    711 	/* TODO: replace 'controller_dp_test_pattern' by 'test_pattern_mode'
    712 	 * because this is not DP-specific (which is probably somewhere in DP
    713 	 * encoder) */
    714 	enum controller_dp_test_pattern test_pattern,
    715 	enum dc_color_depth color_depth)
    716 {
    717 	struct dc_context *ctx = tg->ctx;
    718 	uint32_t value;
    719 	uint32_t addr;
    720 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
    721 	enum test_pattern_color_format bit_depth;
    722 	enum test_pattern_dyn_range dyn_range;
    723 	enum test_pattern_mode mode;
    724 	/* color ramp generator mixes 16-bits color */
    725 	uint32_t src_bpc = 16;
    726 	/* requested bpc */
    727 	uint32_t dst_bpc;
    728 	uint32_t index;
    729 	/* RGB values of the color bars.
    730 	 * Produce two RGB colors: RGB0 - white (all Fs)
    731 	 * and RGB1 - black (all 0s)
    732 	 * (three RGB components for two colors)
    733 	 */
    734 	uint16_t src_color[6] = {0xFFFF, 0xFFFF, 0xFFFF, 0x0000,
    735 						0x0000, 0x0000};
    736 	/* dest color (converted to the specified color format) */
    737 	uint16_t dst_color[6];
    738 	uint32_t inc_base;
    739 
    740 	/* translate to bit depth */
    741 	switch (color_depth) {
    742 	case COLOR_DEPTH_666:
    743 		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_6;
    744 	break;
    745 	case COLOR_DEPTH_888:
    746 		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
    747 	break;
    748 	case COLOR_DEPTH_101010:
    749 		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_10;
    750 	break;
    751 	case COLOR_DEPTH_121212:
    752 		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_12;
    753 	break;
    754 	default:
    755 		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
    756 	break;
    757 	}
    758 
    759 	switch (test_pattern) {
    760 	case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES:
    761 	case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA:
    762 	{
    763 		dyn_range = (test_pattern ==
    764 				CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA ?
    765 				TEST_PATTERN_DYN_RANGE_CEA :
    766 				TEST_PATTERN_DYN_RANGE_VESA);
    767 		mode = TEST_PATTERN_MODE_COLORSQUARES_RGB;
    768 		value = 0;
    769 		addr = CRTC_REG(mmCRTC_TEST_PATTERN_PARAMETERS);
    770 
    771 		set_reg_field_value(
    772 			value,
    773 			6,
    774 			CRTC_TEST_PATTERN_PARAMETERS,
    775 			CRTC_TEST_PATTERN_VRES);
    776 		set_reg_field_value(
    777 			value,
    778 			6,
    779 			CRTC_TEST_PATTERN_PARAMETERS,
    780 			CRTC_TEST_PATTERN_HRES);
    781 
    782 		dm_write_reg(ctx, addr, value);
    783 
    784 		addr = CRTC_REG(mmCRTC_TEST_PATTERN_CONTROL);
    785 		value = 0;
    786 
    787 		set_reg_field_value(
    788 			value,
    789 			1,
    790 			CRTC_TEST_PATTERN_CONTROL,
    791 			CRTC_TEST_PATTERN_EN);
    792 
    793 		set_reg_field_value(
    794 			value,
    795 			mode,
    796 			CRTC_TEST_PATTERN_CONTROL,
    797 			CRTC_TEST_PATTERN_MODE);
    798 
    799 		set_reg_field_value(
    800 			value,
    801 			dyn_range,
    802 			CRTC_TEST_PATTERN_CONTROL,
    803 			CRTC_TEST_PATTERN_DYNAMIC_RANGE);
    804 		set_reg_field_value(
    805 			value,
    806 			bit_depth,
    807 			CRTC_TEST_PATTERN_CONTROL,
    808 			CRTC_TEST_PATTERN_COLOR_FORMAT);
    809 		dm_write_reg(ctx, addr, value);
    810 	}
    811 	break;
    812 
    813 	case CONTROLLER_DP_TEST_PATTERN_VERTICALBARS:
    814 	case CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS:
    815 	{
    816 		mode = (test_pattern ==
    817 			CONTROLLER_DP_TEST_PATTERN_VERTICALBARS ?
    818 			TEST_PATTERN_MODE_VERTICALBARS :
    819 			TEST_PATTERN_MODE_HORIZONTALBARS);
    820 
    821 		switch (bit_depth) {
    822 		case TEST_PATTERN_COLOR_FORMAT_BPC_6:
    823 			dst_bpc = 6;
    824 		break;
    825 		case TEST_PATTERN_COLOR_FORMAT_BPC_8:
    826 			dst_bpc = 8;
    827 		break;
    828 		case TEST_PATTERN_COLOR_FORMAT_BPC_10:
    829 			dst_bpc = 10;
    830 		break;
    831 		default:
    832 			dst_bpc = 8;
    833 		break;
    834 		}
    835 
    836 		/* adjust color to the required colorFormat */
    837 		for (index = 0; index < 6; index++) {
    838 			/* dst = 2^dstBpc * src / 2^srcBpc = src >>
    839 			 * (srcBpc - dstBpc);
    840 			 */
    841 			dst_color[index] =
    842 				src_color[index] >> (src_bpc - dst_bpc);
    843 		/* CRTC_TEST_PATTERN_DATA has 16 bits,
    844 		 * lowest 6 are hardwired to ZERO
    845 		 * color bits should be left aligned aligned to MSB
    846 		 * XXXXXXXXXX000000 for 10 bit,
    847 		 * XXXXXXXX00000000 for 8 bit and XXXXXX0000000000 for 6
    848 		 */
    849 			dst_color[index] <<= (16 - dst_bpc);
    850 		}
    851 
    852 		value = 0;
    853 		addr = CRTC_REG(mmCRTC_TEST_PATTERN_PARAMETERS);
    854 		dm_write_reg(ctx, addr, value);
    855 
    856 		/* We have to write the mask before data, similar to pipeline.
    857 		 * For example, for 8 bpc, if we want RGB0 to be magenta,
    858 		 * and RGB1 to be cyan,
    859 		 * we need to make 7 writes:
    860 		 * MASK   DATA
    861 		 * 000001 00000000 00000000                     set mask to R0
    862 		 * 000010 11111111 00000000     R0 255, 0xFF00, set mask to G0
    863 		 * 000100 00000000 00000000     G0 0,   0x0000, set mask to B0
    864 		 * 001000 11111111 00000000     B0 255, 0xFF00, set mask to R1
    865 		 * 010000 00000000 00000000     R1 0,   0x0000, set mask to G1
    866 		 * 100000 11111111 00000000     G1 255, 0xFF00, set mask to B1
    867 		 * 100000 11111111 00000000     B1 255, 0xFF00
    868 		 *
    869 		 * we will make a loop of 6 in which we prepare the mask,
    870 		 * then write, then prepare the color for next write.
    871 		 * first iteration will write mask only,
    872 		 * but each next iteration color prepared in
    873 		 * previous iteration will be written within new mask,
    874 		 * the last component will written separately,
    875 		 * mask is not changing between 6th and 7th write
    876 		 * and color will be prepared by last iteration
    877 		 */
    878 
    879 		/* write color, color values mask in CRTC_TEST_PATTERN_MASK
    880 		 * is B1, G1, R1, B0, G0, R0
    881 		 */
    882 		value = 0;
    883 		addr = CRTC_REG(mmCRTC_TEST_PATTERN_COLOR);
    884 		for (index = 0; index < 6; index++) {
    885 			/* prepare color mask, first write PATTERN_DATA
    886 			 * will have all zeros
    887 			 */
    888 			set_reg_field_value(
    889 				value,
    890 				(1 << index),
    891 				CRTC_TEST_PATTERN_COLOR,
    892 				CRTC_TEST_PATTERN_MASK);
    893 			/* write color component */
    894 			dm_write_reg(ctx, addr, value);
    895 			/* prepare next color component,
    896 			 * will be written in the next iteration
    897 			 */
    898 			set_reg_field_value(
    899 				value,
    900 				dst_color[index],
    901 				CRTC_TEST_PATTERN_COLOR,
    902 				CRTC_TEST_PATTERN_DATA);
    903 		}
    904 		/* write last color component,
    905 		 * it's been already prepared in the loop
    906 		 */
    907 		dm_write_reg(ctx, addr, value);
    908 
    909 		/* enable test pattern */
    910 		addr = CRTC_REG(mmCRTC_TEST_PATTERN_CONTROL);
    911 		value = 0;
    912 
    913 		set_reg_field_value(
    914 			value,
    915 			1,
    916 			CRTC_TEST_PATTERN_CONTROL,
    917 			CRTC_TEST_PATTERN_EN);
    918 
    919 		set_reg_field_value(
    920 			value,
    921 			mode,
    922 			CRTC_TEST_PATTERN_CONTROL,
    923 			CRTC_TEST_PATTERN_MODE);
    924 
    925 		set_reg_field_value(
    926 			value,
    927 			0,
    928 			CRTC_TEST_PATTERN_CONTROL,
    929 			CRTC_TEST_PATTERN_DYNAMIC_RANGE);
    930 
    931 		set_reg_field_value(
    932 			value,
    933 			bit_depth,
    934 			CRTC_TEST_PATTERN_CONTROL,
    935 			CRTC_TEST_PATTERN_COLOR_FORMAT);
    936 
    937 		dm_write_reg(ctx, addr, value);
    938 	}
    939 	break;
    940 
    941 	case CONTROLLER_DP_TEST_PATTERN_COLORRAMP:
    942 	{
    943 		mode = (bit_depth ==
    944 			TEST_PATTERN_COLOR_FORMAT_BPC_10 ?
    945 			TEST_PATTERN_MODE_DUALRAMP_RGB :
    946 			TEST_PATTERN_MODE_SINGLERAMP_RGB);
    947 
    948 		switch (bit_depth) {
    949 		case TEST_PATTERN_COLOR_FORMAT_BPC_6:
    950 			dst_bpc = 6;
    951 		break;
    952 		case TEST_PATTERN_COLOR_FORMAT_BPC_8:
    953 			dst_bpc = 8;
    954 		break;
    955 		case TEST_PATTERN_COLOR_FORMAT_BPC_10:
    956 			dst_bpc = 10;
    957 		break;
    958 		default:
    959 			dst_bpc = 8;
    960 		break;
    961 		}
    962 
    963 		/* increment for the first ramp for one color gradation
    964 		 * 1 gradation for 6-bit color is 2^10
    965 		 * gradations in 16-bit color
    966 		 */
    967 		inc_base = (src_bpc - dst_bpc);
    968 
    969 		value = 0;
    970 		addr = CRTC_REG(mmCRTC_TEST_PATTERN_PARAMETERS);
    971 
    972 		switch (bit_depth) {
    973 		case TEST_PATTERN_COLOR_FORMAT_BPC_6:
    974 		{
    975 			set_reg_field_value(
    976 				value,
    977 				inc_base,
    978 				CRTC_TEST_PATTERN_PARAMETERS,
    979 				CRTC_TEST_PATTERN_INC0);
    980 			set_reg_field_value(
    981 				value,
    982 				0,
    983 				CRTC_TEST_PATTERN_PARAMETERS,
    984 				CRTC_TEST_PATTERN_INC1);
    985 			set_reg_field_value(
    986 				value,
    987 				6,
    988 				CRTC_TEST_PATTERN_PARAMETERS,
    989 				CRTC_TEST_PATTERN_HRES);
    990 			set_reg_field_value(
    991 				value,
    992 				6,
    993 				CRTC_TEST_PATTERN_PARAMETERS,
    994 				CRTC_TEST_PATTERN_VRES);
    995 			set_reg_field_value(
    996 				value,
    997 				0,
    998 				CRTC_TEST_PATTERN_PARAMETERS,
    999 				CRTC_TEST_PATTERN_RAMP0_OFFSET);
   1000 		}
   1001 		break;
   1002 		case TEST_PATTERN_COLOR_FORMAT_BPC_8:
   1003 		{
   1004 			set_reg_field_value(
   1005 				value,
   1006 				inc_base,
   1007 				CRTC_TEST_PATTERN_PARAMETERS,
   1008 				CRTC_TEST_PATTERN_INC0);
   1009 			set_reg_field_value(
   1010 				value,
   1011 				0,
   1012 				CRTC_TEST_PATTERN_PARAMETERS,
   1013 				CRTC_TEST_PATTERN_INC1);
   1014 			set_reg_field_value(
   1015 				value,
   1016 				8,
   1017 				CRTC_TEST_PATTERN_PARAMETERS,
   1018 				CRTC_TEST_PATTERN_HRES);
   1019 			set_reg_field_value(
   1020 				value,
   1021 				6,
   1022 				CRTC_TEST_PATTERN_PARAMETERS,
   1023 				CRTC_TEST_PATTERN_VRES);
   1024 			set_reg_field_value(
   1025 				value,
   1026 				0,
   1027 				CRTC_TEST_PATTERN_PARAMETERS,
   1028 				CRTC_TEST_PATTERN_RAMP0_OFFSET);
   1029 		}
   1030 		break;
   1031 		case TEST_PATTERN_COLOR_FORMAT_BPC_10:
   1032 		{
   1033 			set_reg_field_value(
   1034 				value,
   1035 				inc_base,
   1036 				CRTC_TEST_PATTERN_PARAMETERS,
   1037 				CRTC_TEST_PATTERN_INC0);
   1038 			set_reg_field_value(
   1039 				value,
   1040 				inc_base + 2,
   1041 				CRTC_TEST_PATTERN_PARAMETERS,
   1042 				CRTC_TEST_PATTERN_INC1);
   1043 			set_reg_field_value(
   1044 				value,
   1045 				8,
   1046 				CRTC_TEST_PATTERN_PARAMETERS,
   1047 				CRTC_TEST_PATTERN_HRES);
   1048 			set_reg_field_value(
   1049 				value,
   1050 				5,
   1051 				CRTC_TEST_PATTERN_PARAMETERS,
   1052 				CRTC_TEST_PATTERN_VRES);
   1053 			set_reg_field_value(
   1054 				value,
   1055 				384 << 6,
   1056 				CRTC_TEST_PATTERN_PARAMETERS,
   1057 				CRTC_TEST_PATTERN_RAMP0_OFFSET);
   1058 		}
   1059 		break;
   1060 		default:
   1061 		break;
   1062 		}
   1063 		dm_write_reg(ctx, addr, value);
   1064 
   1065 		value = 0;
   1066 		addr = CRTC_REG(mmCRTC_TEST_PATTERN_COLOR);
   1067 		dm_write_reg(ctx, addr, value);
   1068 
   1069 		/* enable test pattern */
   1070 		addr = CRTC_REG(mmCRTC_TEST_PATTERN_CONTROL);
   1071 		value = 0;
   1072 
   1073 		set_reg_field_value(
   1074 			value,
   1075 			1,
   1076 			CRTC_TEST_PATTERN_CONTROL,
   1077 			CRTC_TEST_PATTERN_EN);
   1078 
   1079 		set_reg_field_value(
   1080 			value,
   1081 			mode,
   1082 			CRTC_TEST_PATTERN_CONTROL,
   1083 			CRTC_TEST_PATTERN_MODE);
   1084 
   1085 		set_reg_field_value(
   1086 			value,
   1087 			0,
   1088 			CRTC_TEST_PATTERN_CONTROL,
   1089 			CRTC_TEST_PATTERN_DYNAMIC_RANGE);
   1090 		/* add color depth translation here */
   1091 		set_reg_field_value(
   1092 			value,
   1093 			bit_depth,
   1094 			CRTC_TEST_PATTERN_CONTROL,
   1095 			CRTC_TEST_PATTERN_COLOR_FORMAT);
   1096 
   1097 		dm_write_reg(ctx, addr, value);
   1098 	}
   1099 	break;
   1100 	case CONTROLLER_DP_TEST_PATTERN_VIDEOMODE:
   1101 	{
   1102 		value = 0;
   1103 		dm_write_reg(ctx, CRTC_REG(mmCRTC_TEST_PATTERN_CONTROL), value);
   1104 		dm_write_reg(ctx, CRTC_REG(mmCRTC_TEST_PATTERN_COLOR), value);
   1105 		dm_write_reg(ctx, CRTC_REG(mmCRTC_TEST_PATTERN_PARAMETERS),
   1106 				value);
   1107 	}
   1108 	break;
   1109 	default:
   1110 	break;
   1111 	}
   1112 }
   1113 
   1114 /**
   1115 * dce110_timing_generator_validate_timing
   1116 * The timing generators support a maximum display size of is 8192 x 8192 pixels,
   1117 * including both active display and blanking periods. Check H Total and V Total.
   1118 */
   1119 bool dce110_timing_generator_validate_timing(
   1120 	struct timing_generator *tg,
   1121 	const struct dc_crtc_timing *timing,
   1122 	enum signal_type signal)
   1123 {
   1124 	uint32_t h_blank;
   1125 	uint32_t h_back_porch, hsync_offset, h_sync_start;
   1126 
   1127 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
   1128 
   1129 	ASSERT(timing != NULL);
   1130 
   1131 	if (!timing)
   1132 		return false;
   1133 
   1134 	hsync_offset = timing->h_border_right + timing->h_front_porch;
   1135 	h_sync_start = timing->h_addressable + hsync_offset;
   1136 
   1137 	/* Currently we don't support 3D, so block all 3D timings */
   1138 	if (timing->timing_3d_format != TIMING_3D_FORMAT_NONE)
   1139 		return false;
   1140 
   1141 	/* Temporarily blocking interlacing mode until it's supported */
   1142 	if (timing->flags.INTERLACE == 1)
   1143 		return false;
   1144 
   1145 	/* Check maximum number of pixels supported by Timing Generator
   1146 	 * (Currently will never fail, in order to fail needs display which
   1147 	 * needs more than 8192 horizontal and
   1148 	 * more than 8192 vertical total pixels)
   1149 	 */
   1150 	if (timing->h_total > tg110->max_h_total ||
   1151 		timing->v_total > tg110->max_v_total)
   1152 		return false;
   1153 
   1154 	h_blank = (timing->h_total - timing->h_addressable -
   1155 		timing->h_border_right -
   1156 		timing->h_border_left);
   1157 
   1158 	if (h_blank < tg110->min_h_blank)
   1159 		return false;
   1160 
   1161 	if (timing->h_front_porch < tg110->min_h_front_porch)
   1162 		return false;
   1163 
   1164 	h_back_porch = h_blank - (h_sync_start -
   1165 		timing->h_addressable -
   1166 		timing->h_border_right -
   1167 		timing->h_sync_width);
   1168 
   1169 	if (h_back_porch < tg110->min_h_back_porch)
   1170 		return false;
   1171 
   1172 	return true;
   1173 }
   1174 
   1175 /**
   1176 * Wait till we are at the beginning of VBlank.
   1177 */
   1178 void dce110_timing_generator_wait_for_vblank(struct timing_generator *tg)
   1179 {
   1180 	/* We want to catch beginning of VBlank here, so if the first try are
   1181 	 * in VBlank, we might be very close to Active, in this case wait for
   1182 	 * another frame
   1183 	 */
   1184 	while (dce110_timing_generator_is_in_vertical_blank(tg)) {
   1185 		if (!dce110_timing_generator_is_counter_moving(tg)) {
   1186 			/* error - no point to wait if counter is not moving */
   1187 			break;
   1188 		}
   1189 	}
   1190 
   1191 	while (!dce110_timing_generator_is_in_vertical_blank(tg)) {
   1192 		if (!dce110_timing_generator_is_counter_moving(tg)) {
   1193 			/* error - no point to wait if counter is not moving */
   1194 			break;
   1195 		}
   1196 	}
   1197 }
   1198 
   1199 /**
   1200 * Wait till we are in VActive (anywhere in VActive)
   1201 */
   1202 void dce110_timing_generator_wait_for_vactive(struct timing_generator *tg)
   1203 {
   1204 	while (dce110_timing_generator_is_in_vertical_blank(tg)) {
   1205 		if (!dce110_timing_generator_is_counter_moving(tg)) {
   1206 			/* error - no point to wait if counter is not moving */
   1207 			break;
   1208 		}
   1209 	}
   1210 }
   1211 
   1212 /**
   1213  *****************************************************************************
   1214  *  Function: dce110_timing_generator_setup_global_swap_lock
   1215  *
   1216  *  @brief
   1217  *     Setups Global Swap Lock group for current pipe
   1218  *     Pipe can join or leave GSL group, become a TimingServer or TimingClient
   1219  *
   1220  *  @param [in] gsl_params: setup data
   1221  *****************************************************************************
   1222  */
   1223 
   1224 void dce110_timing_generator_setup_global_swap_lock(
   1225 	struct timing_generator *tg,
   1226 	const struct dcp_gsl_params *gsl_params)
   1227 {
   1228 	uint32_t value;
   1229 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
   1230 	uint32_t address = DCP_REG(mmDCP_GSL_CONTROL);
   1231 	uint32_t check_point = FLIP_READY_BACK_LOOKUP;
   1232 
   1233 	value = dm_read_reg(tg->ctx, address);
   1234 
   1235 	/* This pipe will belong to GSL Group zero. */
   1236 	set_reg_field_value(value,
   1237 			    1,
   1238 			    DCP_GSL_CONTROL,
   1239 			    DCP_GSL0_EN);
   1240 
   1241 	set_reg_field_value(value,
   1242 			    gsl_params->gsl_master == tg->inst,
   1243 			    DCP_GSL_CONTROL,
   1244 			    DCP_GSL_MASTER_EN);
   1245 
   1246 	set_reg_field_value(value,
   1247 			    HFLIP_READY_DELAY,
   1248 			    DCP_GSL_CONTROL,
   1249 			    DCP_GSL_HSYNC_FLIP_FORCE_DELAY);
   1250 
   1251 	/* Keep signal low (pending high) during 6 lines.
   1252 	 * Also defines minimum interval before re-checking signal. */
   1253 	set_reg_field_value(value,
   1254 			    HFLIP_CHECK_DELAY,
   1255 			    DCP_GSL_CONTROL,
   1256 			    DCP_GSL_HSYNC_FLIP_CHECK_DELAY);
   1257 
   1258 	dm_write_reg(tg->ctx, CRTC_REG(mmDCP_GSL_CONTROL), value);
   1259 	value = 0;
   1260 
   1261 	set_reg_field_value(value,
   1262 			    gsl_params->gsl_master,
   1263 			    DCIO_GSL0_CNTL,
   1264 			    DCIO_GSL0_VSYNC_SEL);
   1265 
   1266 	set_reg_field_value(value,
   1267 			    0,
   1268 			    DCIO_GSL0_CNTL,
   1269 			    DCIO_GSL0_TIMING_SYNC_SEL);
   1270 
   1271 	set_reg_field_value(value,
   1272 			    0,
   1273 			    DCIO_GSL0_CNTL,
   1274 			    DCIO_GSL0_GLOBAL_UNLOCK_SEL);
   1275 
   1276 	dm_write_reg(tg->ctx, CRTC_REG(mmDCIO_GSL0_CNTL), value);
   1277 
   1278 
   1279 	{
   1280 		uint32_t value_crtc_vtotal;
   1281 
   1282 		value_crtc_vtotal = dm_read_reg(tg->ctx,
   1283 				CRTC_REG(mmCRTC_V_TOTAL));
   1284 
   1285 		set_reg_field_value(value,
   1286 				    0,/* DCP_GSL_PURPOSE_SURFACE_FLIP */
   1287 				    DCP_GSL_CONTROL,
   1288 				    DCP_GSL_SYNC_SOURCE);
   1289 
   1290 		/* Checkpoint relative to end of frame */
   1291 		check_point = get_reg_field_value(value_crtc_vtotal,
   1292 						  CRTC_V_TOTAL,
   1293 						  CRTC_V_TOTAL);
   1294 
   1295 		dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_GSL_WINDOW), 0);
   1296 	}
   1297 
   1298 	set_reg_field_value(value,
   1299 			    1,
   1300 			    DCP_GSL_CONTROL,
   1301 			    DCP_GSL_DELAY_SURFACE_UPDATE_PENDING);
   1302 
   1303 	dm_write_reg(tg->ctx, address, value);
   1304 
   1305 	/********************************************************************/
   1306 	address = CRTC_REG(mmCRTC_GSL_CONTROL);
   1307 
   1308 	value = dm_read_reg(tg->ctx, address);
   1309 	set_reg_field_value(value,
   1310 			    check_point - FLIP_READY_BACK_LOOKUP,
   1311 			    CRTC_GSL_CONTROL,
   1312 			    CRTC_GSL_CHECK_LINE_NUM);
   1313 
   1314 	set_reg_field_value(value,
   1315 			    VFLIP_READY_DELAY,
   1316 			    CRTC_GSL_CONTROL,
   1317 			    CRTC_GSL_FORCE_DELAY);
   1318 
   1319 	dm_write_reg(tg->ctx, address, value);
   1320 }
   1321 
   1322 void dce110_timing_generator_tear_down_global_swap_lock(
   1323 	struct timing_generator *tg)
   1324 {
   1325 	/* Clear all the register writes done by
   1326 	 * dce110_timing_generator_setup_global_swap_lock
   1327 	 */
   1328 
   1329 	uint32_t value;
   1330 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
   1331 	uint32_t address = DCP_REG(mmDCP_GSL_CONTROL);
   1332 
   1333 	value = 0;
   1334 
   1335 	/* This pipe will belong to GSL Group zero. */
   1336 	/* Settig HW default values from reg specs */
   1337 	set_reg_field_value(value,
   1338 			0,
   1339 			DCP_GSL_CONTROL,
   1340 			DCP_GSL0_EN);
   1341 
   1342 	set_reg_field_value(value,
   1343 			0,
   1344 			DCP_GSL_CONTROL,
   1345 			DCP_GSL_MASTER_EN);
   1346 
   1347 	set_reg_field_value(value,
   1348 			0x2,
   1349 			DCP_GSL_CONTROL,
   1350 			DCP_GSL_HSYNC_FLIP_FORCE_DELAY);
   1351 
   1352 	set_reg_field_value(value,
   1353 			0x6,
   1354 			DCP_GSL_CONTROL,
   1355 			DCP_GSL_HSYNC_FLIP_CHECK_DELAY);
   1356 
   1357 	/* Restore DCP_GSL_PURPOSE_SURFACE_FLIP */
   1358 	{
   1359 		uint32_t value_crtc_vtotal __unused;
   1360 
   1361 		value_crtc_vtotal = dm_read_reg(tg->ctx,
   1362 				CRTC_REG(mmCRTC_V_TOTAL));
   1363 
   1364 		set_reg_field_value(value,
   1365 				0,
   1366 				DCP_GSL_CONTROL,
   1367 				DCP_GSL_SYNC_SOURCE);
   1368 	}
   1369 
   1370 	set_reg_field_value(value,
   1371 			0,
   1372 			DCP_GSL_CONTROL,
   1373 			DCP_GSL_DELAY_SURFACE_UPDATE_PENDING);
   1374 
   1375 	dm_write_reg(tg->ctx, address, value);
   1376 
   1377 	/********************************************************************/
   1378 	address = CRTC_REG(mmCRTC_GSL_CONTROL);
   1379 
   1380 	value = 0;
   1381 	set_reg_field_value(value,
   1382 			0,
   1383 			CRTC_GSL_CONTROL,
   1384 			CRTC_GSL_CHECK_LINE_NUM);
   1385 
   1386 	set_reg_field_value(value,
   1387 			0x2,
   1388 			CRTC_GSL_CONTROL,
   1389 			CRTC_GSL_FORCE_DELAY);
   1390 
   1391 	dm_write_reg(tg->ctx, address, value);
   1392 }
   1393 /**
   1394  *****************************************************************************
   1395  *  Function: is_counter_moving
   1396  *
   1397  *  @brief
   1398  *     check if the timing generator is currently going
   1399  *
   1400  *  @return
   1401  *     true if currently going, false if currently paused or stopped.
   1402  *
   1403  *****************************************************************************
   1404  */
   1405 bool dce110_timing_generator_is_counter_moving(struct timing_generator *tg)
   1406 {
   1407 	struct crtc_position position1, position2;
   1408 
   1409 	tg->funcs->get_position(tg, &position1);
   1410 	tg->funcs->get_position(tg, &position2);
   1411 
   1412 	if (position1.horizontal_count == position2.horizontal_count &&
   1413 		position1.vertical_count == position2.vertical_count)
   1414 		return false;
   1415 	else
   1416 		return true;
   1417 }
   1418 
   1419 void dce110_timing_generator_enable_advanced_request(
   1420 	struct timing_generator *tg,
   1421 	bool enable,
   1422 	const struct dc_crtc_timing *timing)
   1423 {
   1424 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
   1425 	uint32_t addr = CRTC_REG(mmCRTC_START_LINE_CONTROL);
   1426 	uint32_t value = dm_read_reg(tg->ctx, addr);
   1427 
   1428 	if (enable) {
   1429 		set_reg_field_value(
   1430 			value,
   1431 			0,
   1432 			CRTC_START_LINE_CONTROL,
   1433 			CRTC_LEGACY_REQUESTOR_EN);
   1434 	} else {
   1435 		set_reg_field_value(
   1436 			value,
   1437 			1,
   1438 			CRTC_START_LINE_CONTROL,
   1439 			CRTC_LEGACY_REQUESTOR_EN);
   1440 	}
   1441 
   1442 	if ((timing->v_sync_width + timing->v_front_porch) <= 3) {
   1443 		set_reg_field_value(
   1444 			value,
   1445 			3,
   1446 			CRTC_START_LINE_CONTROL,
   1447 			CRTC_ADVANCED_START_LINE_POSITION);
   1448 		set_reg_field_value(
   1449 			value,
   1450 			0,
   1451 			CRTC_START_LINE_CONTROL,
   1452 			CRTC_PREFETCH_EN);
   1453 	} else {
   1454 		set_reg_field_value(
   1455 			value,
   1456 			4,
   1457 			CRTC_START_LINE_CONTROL,
   1458 			CRTC_ADVANCED_START_LINE_POSITION);
   1459 		set_reg_field_value(
   1460 			value,
   1461 			1,
   1462 			CRTC_START_LINE_CONTROL,
   1463 			CRTC_PREFETCH_EN);
   1464 	}
   1465 
   1466 	set_reg_field_value(
   1467 		value,
   1468 		1,
   1469 		CRTC_START_LINE_CONTROL,
   1470 		CRTC_PROGRESSIVE_START_LINE_EARLY);
   1471 
   1472 	set_reg_field_value(
   1473 		value,
   1474 		1,
   1475 		CRTC_START_LINE_CONTROL,
   1476 		CRTC_INTERLACE_START_LINE_EARLY);
   1477 
   1478 	dm_write_reg(tg->ctx, addr, value);
   1479 }
   1480 
   1481 /*TODO: Figure out if we need this function. */
   1482 void dce110_timing_generator_set_lock_master(struct timing_generator *tg,
   1483 		bool lock)
   1484 {
   1485 	struct dc_context *ctx = tg->ctx;
   1486 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
   1487 	uint32_t addr = CRTC_REG(mmCRTC_MASTER_UPDATE_LOCK);
   1488 	uint32_t value = dm_read_reg(ctx, addr);
   1489 
   1490 	set_reg_field_value(
   1491 		value,
   1492 		lock ? 1 : 0,
   1493 		CRTC_MASTER_UPDATE_LOCK,
   1494 		MASTER_UPDATE_LOCK);
   1495 
   1496 	dm_write_reg(ctx, addr, value);
   1497 }
   1498 
   1499 void dce110_timing_generator_enable_reset_trigger(
   1500 	struct timing_generator *tg,
   1501 	int source_tg_inst)
   1502 {
   1503 	uint32_t value;
   1504 	uint32_t rising_edge = 0;
   1505 	uint32_t falling_edge = 0;
   1506 	enum trigger_source_select trig_src_select = TRIGGER_SOURCE_SELECT_LOGIC_ZERO;
   1507 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
   1508 
   1509 	/* Setup trigger edge */
   1510 	{
   1511 		uint32_t pol_value = dm_read_reg(tg->ctx,
   1512 				CRTC_REG(mmCRTC_V_SYNC_A_CNTL));
   1513 
   1514 		/* Register spec has reversed definition:
   1515 		 *	0 for positive, 1 for negative */
   1516 		if (get_reg_field_value(pol_value,
   1517 				CRTC_V_SYNC_A_CNTL,
   1518 				CRTC_V_SYNC_A_POL) == 0) {
   1519 			rising_edge = 1;
   1520 		} else {
   1521 			falling_edge = 1;
   1522 		}
   1523 	}
   1524 
   1525 	value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL));
   1526 
   1527 	trig_src_select = TRIGGER_SOURCE_SELECT_GSL_GROUP0;
   1528 
   1529 	set_reg_field_value(value,
   1530 			trig_src_select,
   1531 			CRTC_TRIGB_CNTL,
   1532 			CRTC_TRIGB_SOURCE_SELECT);
   1533 
   1534 	set_reg_field_value(value,
   1535 			TRIGGER_POLARITY_SELECT_LOGIC_ZERO,
   1536 			CRTC_TRIGB_CNTL,
   1537 			CRTC_TRIGB_POLARITY_SELECT);
   1538 
   1539 	set_reg_field_value(value,
   1540 			rising_edge,
   1541 			CRTC_TRIGB_CNTL,
   1542 			CRTC_TRIGB_RISING_EDGE_DETECT_CNTL);
   1543 
   1544 	set_reg_field_value(value,
   1545 			falling_edge,
   1546 			CRTC_TRIGB_CNTL,
   1547 			CRTC_TRIGB_FALLING_EDGE_DETECT_CNTL);
   1548 
   1549 	set_reg_field_value(value,
   1550 			0, /* send every signal */
   1551 			CRTC_TRIGB_CNTL,
   1552 			CRTC_TRIGB_FREQUENCY_SELECT);
   1553 
   1554 	set_reg_field_value(value,
   1555 			0, /* no delay */
   1556 			CRTC_TRIGB_CNTL,
   1557 			CRTC_TRIGB_DELAY);
   1558 
   1559 	set_reg_field_value(value,
   1560 			1, /* clear trigger status */
   1561 			CRTC_TRIGB_CNTL,
   1562 			CRTC_TRIGB_CLEAR);
   1563 
   1564 	dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL), value);
   1565 
   1566 	/**************************************************************/
   1567 
   1568 	value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL));
   1569 
   1570 	set_reg_field_value(value,
   1571 			2, /* force H count to H_TOTAL and V count to V_TOTAL */
   1572 			CRTC_FORCE_COUNT_NOW_CNTL,
   1573 			CRTC_FORCE_COUNT_NOW_MODE);
   1574 
   1575 	set_reg_field_value(value,
   1576 			1, /* TriggerB - we never use TriggerA */
   1577 			CRTC_FORCE_COUNT_NOW_CNTL,
   1578 			CRTC_FORCE_COUNT_NOW_TRIG_SEL);
   1579 
   1580 	set_reg_field_value(value,
   1581 			1, /* clear trigger status */
   1582 			CRTC_FORCE_COUNT_NOW_CNTL,
   1583 			CRTC_FORCE_COUNT_NOW_CLEAR);
   1584 
   1585 	dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL), value);
   1586 }
   1587 
   1588 void dce110_timing_generator_enable_crtc_reset(
   1589 		struct timing_generator *tg,
   1590 		int source_tg_inst,
   1591 		struct crtc_trigger_info *crtc_tp)
   1592 {
   1593 	uint32_t value = 0;
   1594 	uint32_t rising_edge = 0;
   1595 	uint32_t falling_edge = 0;
   1596 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
   1597 
   1598 	/* Setup trigger edge */
   1599 	switch (crtc_tp->event) {
   1600 	case CRTC_EVENT_VSYNC_RISING:
   1601 			rising_edge = 1;
   1602 			break;
   1603 
   1604 	case CRTC_EVENT_VSYNC_FALLING:
   1605 		falling_edge = 1;
   1606 		break;
   1607 	}
   1608 
   1609 	value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL));
   1610 
   1611 	set_reg_field_value(value,
   1612 			    source_tg_inst,
   1613 			    CRTC_TRIGB_CNTL,
   1614 			    CRTC_TRIGB_SOURCE_SELECT);
   1615 
   1616 	set_reg_field_value(value,
   1617 			    TRIGGER_POLARITY_SELECT_LOGIC_ZERO,
   1618 			    CRTC_TRIGB_CNTL,
   1619 			    CRTC_TRIGB_POLARITY_SELECT);
   1620 
   1621 	set_reg_field_value(value,
   1622 			    rising_edge,
   1623 			    CRTC_TRIGB_CNTL,
   1624 			    CRTC_TRIGB_RISING_EDGE_DETECT_CNTL);
   1625 
   1626 	set_reg_field_value(value,
   1627 			    falling_edge,
   1628 			    CRTC_TRIGB_CNTL,
   1629 			    CRTC_TRIGB_FALLING_EDGE_DETECT_CNTL);
   1630 
   1631 	set_reg_field_value(value,
   1632 			    1, /* clear trigger status */
   1633 			    CRTC_TRIGB_CNTL,
   1634 			    CRTC_TRIGB_CLEAR);
   1635 
   1636 	dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL), value);
   1637 
   1638 	/**************************************************************/
   1639 
   1640 	switch (crtc_tp->delay) {
   1641 	case TRIGGER_DELAY_NEXT_LINE:
   1642 		value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL));
   1643 
   1644 		set_reg_field_value(value,
   1645 				    0, /* force H count to H_TOTAL and V count to V_TOTAL */
   1646 				    CRTC_FORCE_COUNT_NOW_CNTL,
   1647 				    CRTC_FORCE_COUNT_NOW_MODE);
   1648 
   1649 		set_reg_field_value(value,
   1650 				    0, /* TriggerB - we never use TriggerA */
   1651 				    CRTC_FORCE_COUNT_NOW_CNTL,
   1652 				    CRTC_FORCE_COUNT_NOW_TRIG_SEL);
   1653 
   1654 		set_reg_field_value(value,
   1655 				    1, /* clear trigger status */
   1656 				    CRTC_FORCE_COUNT_NOW_CNTL,
   1657 				    CRTC_FORCE_COUNT_NOW_CLEAR);
   1658 
   1659 		dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL), value);
   1660 
   1661 		value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_VERT_SYNC_CONTROL));
   1662 
   1663 		set_reg_field_value(value,
   1664 				    1,
   1665 				    CRTC_VERT_SYNC_CONTROL,
   1666 				    CRTC_FORCE_VSYNC_NEXT_LINE_CLEAR);
   1667 
   1668 		set_reg_field_value(value,
   1669 				    2,
   1670 				    CRTC_VERT_SYNC_CONTROL,
   1671 				    CRTC_AUTO_FORCE_VSYNC_MODE);
   1672 
   1673 		break;
   1674 
   1675 	case TRIGGER_DELAY_NEXT_PIXEL:
   1676 		value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_VERT_SYNC_CONTROL));
   1677 
   1678 		set_reg_field_value(value,
   1679 				    1,
   1680 				    CRTC_VERT_SYNC_CONTROL,
   1681 				    CRTC_FORCE_VSYNC_NEXT_LINE_CLEAR);
   1682 
   1683 		set_reg_field_value(value,
   1684 				    0,
   1685 				    CRTC_VERT_SYNC_CONTROL,
   1686 				    CRTC_AUTO_FORCE_VSYNC_MODE);
   1687 
   1688 		dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_VERT_SYNC_CONTROL), value);
   1689 
   1690 		value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL));
   1691 
   1692 		set_reg_field_value(value,
   1693 				    2, /* force H count to H_TOTAL and V count to V_TOTAL */
   1694 				    CRTC_FORCE_COUNT_NOW_CNTL,
   1695 				    CRTC_FORCE_COUNT_NOW_MODE);
   1696 
   1697 		set_reg_field_value(value,
   1698 				    1, /* TriggerB - we never use TriggerA */
   1699 				    CRTC_FORCE_COUNT_NOW_CNTL,
   1700 				    CRTC_FORCE_COUNT_NOW_TRIG_SEL);
   1701 
   1702 		set_reg_field_value(value,
   1703 				    1, /* clear trigger status */
   1704 				    CRTC_FORCE_COUNT_NOW_CNTL,
   1705 				    CRTC_FORCE_COUNT_NOW_CLEAR);
   1706 
   1707 		dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL), value);
   1708 		break;
   1709 	}
   1710 
   1711 	value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_MASTER_UPDATE_MODE));
   1712 
   1713 	set_reg_field_value(value,
   1714 			    2,
   1715 			    CRTC_MASTER_UPDATE_MODE,
   1716 			    MASTER_UPDATE_MODE);
   1717 
   1718 	dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_MASTER_UPDATE_MODE), value);
   1719 }
   1720 void dce110_timing_generator_disable_reset_trigger(
   1721 	struct timing_generator *tg)
   1722 {
   1723 	uint32_t value;
   1724 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
   1725 
   1726 	value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL));
   1727 
   1728 	set_reg_field_value(value,
   1729 			    0, /* force counter now mode is disabled */
   1730 			    CRTC_FORCE_COUNT_NOW_CNTL,
   1731 			    CRTC_FORCE_COUNT_NOW_MODE);
   1732 
   1733 	set_reg_field_value(value,
   1734 			    1, /* clear trigger status */
   1735 			    CRTC_FORCE_COUNT_NOW_CNTL,
   1736 			    CRTC_FORCE_COUNT_NOW_CLEAR);
   1737 
   1738 	dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL), value);
   1739 
   1740 	value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_VERT_SYNC_CONTROL));
   1741 
   1742 	set_reg_field_value(value,
   1743 			    1,
   1744 			    CRTC_VERT_SYNC_CONTROL,
   1745 			    CRTC_FORCE_VSYNC_NEXT_LINE_CLEAR);
   1746 
   1747 	set_reg_field_value(value,
   1748 			    0,
   1749 			    CRTC_VERT_SYNC_CONTROL,
   1750 			    CRTC_AUTO_FORCE_VSYNC_MODE);
   1751 
   1752 	dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_VERT_SYNC_CONTROL), value);
   1753 
   1754 	/********************************************************************/
   1755 	value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL));
   1756 
   1757 	set_reg_field_value(value,
   1758 			    TRIGGER_SOURCE_SELECT_LOGIC_ZERO,
   1759 			    CRTC_TRIGB_CNTL,
   1760 			    CRTC_TRIGB_SOURCE_SELECT);
   1761 
   1762 	set_reg_field_value(value,
   1763 			    TRIGGER_POLARITY_SELECT_LOGIC_ZERO,
   1764 			    CRTC_TRIGB_CNTL,
   1765 			    CRTC_TRIGB_POLARITY_SELECT);
   1766 
   1767 	set_reg_field_value(value,
   1768 			    1, /* clear trigger status */
   1769 			    CRTC_TRIGB_CNTL,
   1770 			    CRTC_TRIGB_CLEAR);
   1771 
   1772 	dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL), value);
   1773 }
   1774 
   1775 /**
   1776  *****************************************************************************
   1777  *  @brief
   1778  *     Checks whether CRTC triggered reset occurred
   1779  *
   1780  *  @return
   1781  *     true if triggered reset occurred, false otherwise
   1782  *****************************************************************************
   1783  */
   1784 bool dce110_timing_generator_did_triggered_reset_occur(
   1785 	struct timing_generator *tg)
   1786 {
   1787 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
   1788 	uint32_t value = dm_read_reg(tg->ctx,
   1789 			CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL));
   1790 	uint32_t value1 = dm_read_reg(tg->ctx,
   1791 			CRTC_REG(mmCRTC_VERT_SYNC_CONTROL));
   1792 	bool force = get_reg_field_value(value,
   1793 					 CRTC_FORCE_COUNT_NOW_CNTL,
   1794 					 CRTC_FORCE_COUNT_NOW_OCCURRED) != 0;
   1795 	bool vert_sync = get_reg_field_value(value1,
   1796 					     CRTC_VERT_SYNC_CONTROL,
   1797 					     CRTC_FORCE_VSYNC_NEXT_LINE_OCCURRED) != 0;
   1798 
   1799 	return (force || vert_sync);
   1800 }
   1801 
   1802 /**
   1803  * dce110_timing_generator_disable_vga
   1804  * Turn OFF VGA Mode and Timing  - DxVGA_CONTROL
   1805  * VGA Mode and VGA Timing is used by VBIOS on CRT Monitors;
   1806  */
   1807 void dce110_timing_generator_disable_vga(
   1808 	struct timing_generator *tg)
   1809 {
   1810 	uint32_t addr = 0;
   1811 	uint32_t value = 0;
   1812 
   1813 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
   1814 
   1815 	switch (tg110->controller_id) {
   1816 	case CONTROLLER_ID_D0:
   1817 		addr = mmD1VGA_CONTROL;
   1818 		break;
   1819 	case CONTROLLER_ID_D1:
   1820 		addr = mmD2VGA_CONTROL;
   1821 		break;
   1822 	case CONTROLLER_ID_D2:
   1823 		addr = mmD3VGA_CONTROL;
   1824 		break;
   1825 	case CONTROLLER_ID_D3:
   1826 		addr = mmD4VGA_CONTROL;
   1827 		break;
   1828 	case CONTROLLER_ID_D4:
   1829 		addr = mmD5VGA_CONTROL;
   1830 		break;
   1831 	case CONTROLLER_ID_D5:
   1832 		addr = mmD6VGA_CONTROL;
   1833 		break;
   1834 	default:
   1835 		break;
   1836 	}
   1837 	value = dm_read_reg(tg->ctx, addr);
   1838 
   1839 	set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_MODE_ENABLE);
   1840 	set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_TIMING_SELECT);
   1841 	set_reg_field_value(
   1842 			value, 0, D1VGA_CONTROL, D1VGA_SYNC_POLARITY_SELECT);
   1843 	set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_OVERSCAN_COLOR_EN);
   1844 
   1845 	dm_write_reg(tg->ctx, addr, value);
   1846 }
   1847 
   1848 /**
   1849 * set_overscan_color_black
   1850 *
   1851 * @param :black_color is one of the color space
   1852 *    :this routine will set overscan black color according to the color space.
   1853 * @return none
   1854 */
   1855 
   1856 void dce110_timing_generator_set_overscan_color_black(
   1857 	struct timing_generator *tg,
   1858 	const struct tg_color *color)
   1859 {
   1860 	struct dc_context *ctx = tg->ctx;
   1861 	uint32_t addr;
   1862 	uint32_t value = 0;
   1863 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
   1864 
   1865 	set_reg_field_value(
   1866 			value,
   1867 			color->color_b_cb,
   1868 			CRTC_OVERSCAN_COLOR,
   1869 			CRTC_OVERSCAN_COLOR_BLUE);
   1870 
   1871 	set_reg_field_value(
   1872 			value,
   1873 			color->color_r_cr,
   1874 			CRTC_OVERSCAN_COLOR,
   1875 			CRTC_OVERSCAN_COLOR_RED);
   1876 
   1877 	set_reg_field_value(
   1878 			value,
   1879 			color->color_g_y,
   1880 			CRTC_OVERSCAN_COLOR,
   1881 			CRTC_OVERSCAN_COLOR_GREEN);
   1882 
   1883 	addr = CRTC_REG(mmCRTC_OVERSCAN_COLOR);
   1884 	dm_write_reg(ctx, addr, value);
   1885 	addr = CRTC_REG(mmCRTC_BLACK_COLOR);
   1886 	dm_write_reg(ctx, addr, value);
   1887 	/* This is desirable to have a constant DAC output voltage during the
   1888 	 * blank time that is higher than the 0 volt reference level that the
   1889 	 * DAC outputs when the NBLANK signal
   1890 	 * is asserted low, such as for output to an analog TV. */
   1891 	addr = CRTC_REG(mmCRTC_BLANK_DATA_COLOR);
   1892 	dm_write_reg(ctx, addr, value);
   1893 
   1894 	/* TO DO we have to program EXT registers and we need to know LB DATA
   1895 	 * format because it is used when more 10 , i.e. 12 bits per color
   1896 	 *
   1897 	 * m_mmDxCRTC_OVERSCAN_COLOR_EXT
   1898 	 * m_mmDxCRTC_BLACK_COLOR_EXT
   1899 	 * m_mmDxCRTC_BLANK_DATA_COLOR_EXT
   1900 	 */
   1901 
   1902 }
   1903 
   1904 void dce110_tg_program_blank_color(struct timing_generator *tg,
   1905 		const struct tg_color *black_color)
   1906 {
   1907 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
   1908 	uint32_t addr = CRTC_REG(mmCRTC_BLACK_COLOR);
   1909 	uint32_t value = dm_read_reg(tg->ctx, addr);
   1910 
   1911 	set_reg_field_value(
   1912 		value,
   1913 		black_color->color_b_cb,
   1914 		CRTC_BLACK_COLOR,
   1915 		CRTC_BLACK_COLOR_B_CB);
   1916 	set_reg_field_value(
   1917 		value,
   1918 		black_color->color_g_y,
   1919 		CRTC_BLACK_COLOR,
   1920 		CRTC_BLACK_COLOR_G_Y);
   1921 	set_reg_field_value(
   1922 		value,
   1923 		black_color->color_r_cr,
   1924 		CRTC_BLACK_COLOR,
   1925 		CRTC_BLACK_COLOR_R_CR);
   1926 
   1927 	dm_write_reg(tg->ctx, addr, value);
   1928 
   1929 	addr = CRTC_REG(mmCRTC_BLANK_DATA_COLOR);
   1930 	dm_write_reg(tg->ctx, addr, value);
   1931 }
   1932 
   1933 void dce110_tg_set_overscan_color(struct timing_generator *tg,
   1934 	const struct tg_color *overscan_color)
   1935 {
   1936 	struct dc_context *ctx = tg->ctx;
   1937 	uint32_t value = 0;
   1938 	uint32_t addr;
   1939 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
   1940 
   1941 	set_reg_field_value(
   1942 		value,
   1943 		overscan_color->color_b_cb,
   1944 		CRTC_OVERSCAN_COLOR,
   1945 		CRTC_OVERSCAN_COLOR_BLUE);
   1946 
   1947 	set_reg_field_value(
   1948 		value,
   1949 		overscan_color->color_g_y,
   1950 		CRTC_OVERSCAN_COLOR,
   1951 		CRTC_OVERSCAN_COLOR_GREEN);
   1952 
   1953 	set_reg_field_value(
   1954 		value,
   1955 		overscan_color->color_r_cr,
   1956 		CRTC_OVERSCAN_COLOR,
   1957 		CRTC_OVERSCAN_COLOR_RED);
   1958 
   1959 	addr = CRTC_REG(mmCRTC_OVERSCAN_COLOR);
   1960 	dm_write_reg(ctx, addr, value);
   1961 }
   1962 
   1963 void dce110_tg_program_timing(struct timing_generator *tg,
   1964 	const struct dc_crtc_timing *timing,
   1965 	int vready_offset,
   1966 	int vstartup_start,
   1967 	int vupdate_offset,
   1968 	int vupdate_width,
   1969 	const enum signal_type signal,
   1970 	bool use_vbios)
   1971 {
   1972 	if (use_vbios)
   1973 		dce110_timing_generator_program_timing_generator(tg, timing);
   1974 	else
   1975 		dce110_timing_generator_program_blanking(tg, timing);
   1976 }
   1977 
   1978 bool dce110_tg_is_blanked(struct timing_generator *tg)
   1979 {
   1980 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
   1981 	uint32_t value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL));
   1982 
   1983 	if (get_reg_field_value(
   1984 			value,
   1985 			CRTC_BLANK_CONTROL,
   1986 			CRTC_BLANK_DATA_EN) == 1 &&
   1987 		get_reg_field_value(
   1988 			value,
   1989 			CRTC_BLANK_CONTROL,
   1990 			CRTC_CURRENT_BLANK_STATE) == 1)
   1991 		return true;
   1992 	return false;
   1993 }
   1994 
   1995 void dce110_tg_set_blank(struct timing_generator *tg,
   1996 		bool enable_blanking)
   1997 {
   1998 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
   1999 	uint32_t value = 0;
   2000 
   2001 	set_reg_field_value(
   2002 		value,
   2003 		1,
   2004 		CRTC_DOUBLE_BUFFER_CONTROL,
   2005 		CRTC_BLANK_DATA_DOUBLE_BUFFER_EN);
   2006 
   2007 	dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_DOUBLE_BUFFER_CONTROL), value);
   2008 	value = 0;
   2009 
   2010 	if (enable_blanking) {
   2011 		set_reg_field_value(
   2012 			value,
   2013 			1,
   2014 			CRTC_BLANK_CONTROL,
   2015 			CRTC_BLANK_DATA_EN);
   2016 
   2017 		dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL), value);
   2018 
   2019 	} else
   2020 		dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL), 0);
   2021 }
   2022 
   2023 bool dce110_tg_validate_timing(struct timing_generator *tg,
   2024 	const struct dc_crtc_timing *timing)
   2025 {
   2026 	return dce110_timing_generator_validate_timing(tg, timing, SIGNAL_TYPE_NONE);
   2027 }
   2028 
   2029 void dce110_tg_wait_for_state(struct timing_generator *tg,
   2030 	enum crtc_state state)
   2031 {
   2032 	switch (state) {
   2033 	case CRTC_STATE_VBLANK:
   2034 		dce110_timing_generator_wait_for_vblank(tg);
   2035 		break;
   2036 
   2037 	case CRTC_STATE_VACTIVE:
   2038 		dce110_timing_generator_wait_for_vactive(tg);
   2039 		break;
   2040 
   2041 	default:
   2042 		break;
   2043 	}
   2044 }
   2045 
   2046 void dce110_tg_set_colors(struct timing_generator *tg,
   2047 	const struct tg_color *blank_color,
   2048 	const struct tg_color *overscan_color)
   2049 {
   2050 	if (blank_color != NULL)
   2051 		dce110_tg_program_blank_color(tg, blank_color);
   2052 	if (overscan_color != NULL)
   2053 		dce110_tg_set_overscan_color(tg, overscan_color);
   2054 }
   2055 
   2056 /* Gets first line of blank region of the display timing for CRTC
   2057  * and programms is as a trigger to fire vertical interrupt
   2058  */
   2059 bool dce110_arm_vert_intr(struct timing_generator *tg, uint8_t width)
   2060 {
   2061 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
   2062 	uint32_t v_blank_start = 0;
   2063 	uint32_t v_blank_end = 0;
   2064 	uint32_t val = 0;
   2065 	uint32_t h_position, v_position;
   2066 
   2067 	tg->funcs->get_scanoutpos(
   2068 			tg,
   2069 			&v_blank_start,
   2070 			&v_blank_end,
   2071 			&h_position,
   2072 			&v_position);
   2073 
   2074 	if (v_blank_start == 0 || v_blank_end == 0)
   2075 		return false;
   2076 
   2077 	set_reg_field_value(
   2078 		val,
   2079 		v_blank_start,
   2080 		CRTC_VERTICAL_INTERRUPT0_POSITION,
   2081 		CRTC_VERTICAL_INTERRUPT0_LINE_START);
   2082 
   2083 	/* Set interval width for interrupt to fire to 1 scanline */
   2084 	set_reg_field_value(
   2085 		val,
   2086 		v_blank_start + width,
   2087 		CRTC_VERTICAL_INTERRUPT0_POSITION,
   2088 		CRTC_VERTICAL_INTERRUPT0_LINE_END);
   2089 
   2090 	dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_VERTICAL_INTERRUPT0_POSITION), val);
   2091 
   2092 	return true;
   2093 }
   2094 
   2095 static bool dce110_is_tg_enabled(struct timing_generator *tg)
   2096 {
   2097 	uint32_t addr = 0;
   2098 	uint32_t value = 0;
   2099 	uint32_t field = 0;
   2100 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
   2101 
   2102 	addr = CRTC_REG(mmCRTC_CONTROL);
   2103 	value = dm_read_reg(tg->ctx, addr);
   2104 	field = get_reg_field_value(value, CRTC_CONTROL,
   2105 				    CRTC_CURRENT_MASTER_EN_STATE);
   2106 	return field == 1;
   2107 }
   2108 
   2109 bool dce110_configure_crc(struct timing_generator *tg,
   2110 			  const struct crc_params *params)
   2111 {
   2112 	uint32_t cntl_addr = 0;
   2113 	uint32_t addr = 0;
   2114 	uint32_t value;
   2115 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
   2116 
   2117 	/* Cannot configure crc on a CRTC that is disabled */
   2118 	if (!dce110_is_tg_enabled(tg))
   2119 		return false;
   2120 
   2121 	cntl_addr = CRTC_REG(mmCRTC_CRC_CNTL);
   2122 
   2123 	/* First, disable CRC before we configure it. */
   2124 	dm_write_reg(tg->ctx, cntl_addr, 0);
   2125 
   2126 	if (!params->enable)
   2127 		return true;
   2128 
   2129 	/* Program frame boundaries */
   2130 	/* Window A x axis start and end. */
   2131 	value = 0;
   2132 	addr = CRTC_REG(mmCRTC_CRC0_WINDOWA_X_CONTROL);
   2133 	set_reg_field_value(value, params->windowa_x_start,
   2134 			    CRTC_CRC0_WINDOWA_X_CONTROL,
   2135 			    CRTC_CRC0_WINDOWA_X_START);
   2136 	set_reg_field_value(value, params->windowa_x_end,
   2137 			    CRTC_CRC0_WINDOWA_X_CONTROL,
   2138 			    CRTC_CRC0_WINDOWA_X_END);
   2139 	dm_write_reg(tg->ctx, addr, value);
   2140 
   2141 	/* Window A y axis start and end. */
   2142 	value = 0;
   2143 	addr = CRTC_REG(mmCRTC_CRC0_WINDOWA_Y_CONTROL);
   2144 	set_reg_field_value(value, params->windowa_y_start,
   2145 			    CRTC_CRC0_WINDOWA_Y_CONTROL,
   2146 			    CRTC_CRC0_WINDOWA_Y_START);
   2147 	set_reg_field_value(value, params->windowa_y_end,
   2148 			    CRTC_CRC0_WINDOWA_Y_CONTROL,
   2149 			    CRTC_CRC0_WINDOWA_Y_END);
   2150 	dm_write_reg(tg->ctx, addr, value);
   2151 
   2152 	/* Window B x axis start and end. */
   2153 	value = 0;
   2154 	addr = CRTC_REG(mmCRTC_CRC0_WINDOWB_X_CONTROL);
   2155 	set_reg_field_value(value, params->windowb_x_start,
   2156 			    CRTC_CRC0_WINDOWB_X_CONTROL,
   2157 			    CRTC_CRC0_WINDOWB_X_START);
   2158 	set_reg_field_value(value, params->windowb_x_end,
   2159 			    CRTC_CRC0_WINDOWB_X_CONTROL,
   2160 			    CRTC_CRC0_WINDOWB_X_END);
   2161 	dm_write_reg(tg->ctx, addr, value);
   2162 
   2163 	/* Window B y axis start and end. */
   2164 	value = 0;
   2165 	addr = CRTC_REG(mmCRTC_CRC0_WINDOWB_Y_CONTROL);
   2166 	set_reg_field_value(value, params->windowb_y_start,
   2167 			    CRTC_CRC0_WINDOWB_Y_CONTROL,
   2168 			    CRTC_CRC0_WINDOWB_Y_START);
   2169 	set_reg_field_value(value, params->windowb_y_end,
   2170 			    CRTC_CRC0_WINDOWB_Y_CONTROL,
   2171 			    CRTC_CRC0_WINDOWB_Y_END);
   2172 	dm_write_reg(tg->ctx, addr, value);
   2173 
   2174 	/* Set crc mode and selection, and enable. Only using CRC0*/
   2175 	value = 0;
   2176 	set_reg_field_value(value, params->continuous_mode ? 1 : 0,
   2177 			    CRTC_CRC_CNTL, CRTC_CRC_CONT_EN);
   2178 	set_reg_field_value(value, params->selection,
   2179 			    CRTC_CRC_CNTL, CRTC_CRC0_SELECT);
   2180 	set_reg_field_value(value, 1, CRTC_CRC_CNTL, CRTC_CRC_EN);
   2181 	dm_write_reg(tg->ctx, cntl_addr, value);
   2182 
   2183 	return true;
   2184 }
   2185 
   2186 bool dce110_get_crc(struct timing_generator *tg,
   2187 		    uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb)
   2188 {
   2189 	uint32_t addr = 0;
   2190 	uint32_t value = 0;
   2191 	uint32_t field = 0;
   2192 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
   2193 
   2194 	addr = CRTC_REG(mmCRTC_CRC_CNTL);
   2195 	value = dm_read_reg(tg->ctx, addr);
   2196 	field = get_reg_field_value(value, CRTC_CRC_CNTL, CRTC_CRC_EN);
   2197 
   2198 	/* Early return if CRC is not enabled for this CRTC */
   2199 	if (!field)
   2200 		return false;
   2201 
   2202 	addr = CRTC_REG(mmCRTC_CRC0_DATA_RG);
   2203 	value = dm_read_reg(tg->ctx, addr);
   2204 	*r_cr = get_reg_field_value(value, CRTC_CRC0_DATA_RG, CRC0_R_CR);
   2205 	*g_y = get_reg_field_value(value, CRTC_CRC0_DATA_RG, CRC0_G_Y);
   2206 
   2207 	addr = CRTC_REG(mmCRTC_CRC0_DATA_B);
   2208 	value = dm_read_reg(tg->ctx, addr);
   2209 	*b_cb = get_reg_field_value(value, CRTC_CRC0_DATA_B, CRC0_B_CB);
   2210 
   2211 	return true;
   2212 }
   2213 
   2214 static const struct timing_generator_funcs dce110_tg_funcs = {
   2215 		.validate_timing = dce110_tg_validate_timing,
   2216 		.program_timing = dce110_tg_program_timing,
   2217 		.enable_crtc = dce110_timing_generator_enable_crtc,
   2218 		.disable_crtc = dce110_timing_generator_disable_crtc,
   2219 		.is_counter_moving = dce110_timing_generator_is_counter_moving,
   2220 		.get_position = dce110_timing_generator_get_position,
   2221 		.get_frame_count = dce110_timing_generator_get_vblank_counter,
   2222 		.get_scanoutpos = dce110_timing_generator_get_crtc_scanoutpos,
   2223 		.set_early_control = dce110_timing_generator_set_early_control,
   2224 		.wait_for_state = dce110_tg_wait_for_state,
   2225 		.set_blank = dce110_tg_set_blank,
   2226 		.is_blanked = dce110_tg_is_blanked,
   2227 		.set_colors = dce110_tg_set_colors,
   2228 		.set_overscan_blank_color =
   2229 				dce110_timing_generator_set_overscan_color_black,
   2230 		.set_blank_color = dce110_timing_generator_program_blank_color,
   2231 		.disable_vga = dce110_timing_generator_disable_vga,
   2232 		.did_triggered_reset_occur =
   2233 				dce110_timing_generator_did_triggered_reset_occur,
   2234 		.setup_global_swap_lock =
   2235 				dce110_timing_generator_setup_global_swap_lock,
   2236 		.enable_reset_trigger = dce110_timing_generator_enable_reset_trigger,
   2237 		.enable_crtc_reset = dce110_timing_generator_enable_crtc_reset,
   2238 		.disable_reset_trigger = dce110_timing_generator_disable_reset_trigger,
   2239 		.tear_down_global_swap_lock =
   2240 				dce110_timing_generator_tear_down_global_swap_lock,
   2241 		.enable_advanced_request =
   2242 				dce110_timing_generator_enable_advanced_request,
   2243 		.set_drr =
   2244 				dce110_timing_generator_set_drr,
   2245 		.set_static_screen_control =
   2246 			dce110_timing_generator_set_static_screen_control,
   2247 		.set_test_pattern = dce110_timing_generator_set_test_pattern,
   2248 		.arm_vert_intr = dce110_arm_vert_intr,
   2249 		.is_tg_enabled = dce110_is_tg_enabled,
   2250 		.configure_crc = dce110_configure_crc,
   2251 		.get_crc = dce110_get_crc,
   2252 };
   2253 
   2254 void dce110_timing_generator_construct(
   2255 	struct dce110_timing_generator *tg110,
   2256 	struct dc_context *ctx,
   2257 	uint32_t instance,
   2258 	const struct dce110_timing_generator_offsets *offsets)
   2259 {
   2260 	tg110->controller_id = CONTROLLER_ID_D0 + instance;
   2261 	tg110->base.inst = instance;
   2262 
   2263 	tg110->offsets = *offsets;
   2264 
   2265 	tg110->base.funcs = &dce110_tg_funcs;
   2266 
   2267 	tg110->base.ctx = ctx;
   2268 	tg110->base.bp = ctx->dc_bios;
   2269 
   2270 	tg110->max_h_total = CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1;
   2271 	tg110->max_v_total = CRTC_V_TOTAL__CRTC_V_TOTAL_MASK + 1;
   2272 
   2273 	tg110->min_h_blank = 56;
   2274 	tg110->min_h_front_porch = 4;
   2275 	tg110->min_h_back_porch = 4;
   2276 }
   2277