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