xref: /netbsd-src/sys/external/bsd/drm2/dist/drm/amd/display/dc/dce110/amdgpu_dce110_timing_generator_v.c (revision 41ec02673d281bbb3d38e6c78504ce6e30c228c1)
1 /*	$NetBSD: amdgpu_dce110_timing_generator_v.c,v 1.2 2021/12/18 23:45:02 riastradh Exp $	*/
2 
3 /*
4  * Copyright 2017 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  */
25 
26 #include <sys/cdefs.h>
27 __KERNEL_RCSID(0, "$NetBSD: amdgpu_dce110_timing_generator_v.c,v 1.2 2021/12/18 23:45:02 riastradh Exp $");
28 
29 #include "dm_services.h"
30 
31 /* include DCE11 register header files */
32 #include "dce/dce_11_0_d.h"
33 #include "dce/dce_11_0_sh_mask.h"
34 
35 #include "dc_types.h"
36 #include "dc_bios_types.h"
37 #include "dc.h"
38 
39 #include "include/grph_object_id.h"
40 #include "include/logger_interface.h"
41 #include "dce110_timing_generator.h"
42 #include "dce110_timing_generator_v.h"
43 
44 #include "timing_generator.h"
45 
46 #define DC_LOGGER \
47 	tg->ctx->logger
48 /** ********************************************************************************
49  *
50  * DCE11 Timing Generator Implementation
51  *
52  **********************************************************************************/
53 
54 /**
55 * Enable CRTCV
56 */
57 
dce110_timing_generator_v_enable_crtc(struct timing_generator * tg)58 static bool dce110_timing_generator_v_enable_crtc(struct timing_generator *tg)
59 {
60 /*
61 * Set MASTER_UPDATE_MODE to 0
62 * This is needed for DRR, and also suggested to be default value by Syed.
63 */
64 
65 	uint32_t value;
66 
67 	value = 0;
68 	set_reg_field_value(value, 0,
69 			CRTCV_MASTER_UPDATE_MODE, MASTER_UPDATE_MODE);
70 	dm_write_reg(tg->ctx,
71 			mmCRTCV_MASTER_UPDATE_MODE, value);
72 
73 	/* TODO: may want this on for looking for underflow */
74 	value = 0;
75 	dm_write_reg(tg->ctx, mmCRTCV_MASTER_UPDATE_MODE, value);
76 
77 	value = 0;
78 	set_reg_field_value(value, 1,
79 			CRTCV_MASTER_EN, CRTC_MASTER_EN);
80 	dm_write_reg(tg->ctx,
81 			mmCRTCV_MASTER_EN, value);
82 
83 	return true;
84 }
85 
dce110_timing_generator_v_disable_crtc(struct timing_generator * tg)86 static bool dce110_timing_generator_v_disable_crtc(struct timing_generator *tg)
87 {
88 	uint32_t value;
89 
90 	value = dm_read_reg(tg->ctx,
91 			mmCRTCV_CONTROL);
92 	set_reg_field_value(value, 0,
93 			CRTCV_CONTROL, CRTC_DISABLE_POINT_CNTL);
94 	set_reg_field_value(value, 0,
95 				CRTCV_CONTROL, CRTC_MASTER_EN);
96 	dm_write_reg(tg->ctx,
97 			mmCRTCV_CONTROL, value);
98 	/*
99 	 * TODO: call this when adding stereo support
100 	 * tg->funcs->disable_stereo(tg);
101 	 */
102 	return true;
103 }
104 
dce110_timing_generator_v_blank_crtc(struct timing_generator * tg)105 static void dce110_timing_generator_v_blank_crtc(struct timing_generator *tg)
106 {
107 	uint32_t addr = mmCRTCV_BLANK_CONTROL;
108 	uint32_t value = dm_read_reg(tg->ctx, addr);
109 
110 	set_reg_field_value(
111 		value,
112 		1,
113 		CRTCV_BLANK_CONTROL,
114 		CRTC_BLANK_DATA_EN);
115 
116 	set_reg_field_value(
117 		value,
118 		0,
119 		CRTCV_BLANK_CONTROL,
120 		CRTC_BLANK_DE_MODE);
121 
122 	dm_write_reg(tg->ctx, addr, value);
123 }
124 
dce110_timing_generator_v_unblank_crtc(struct timing_generator * tg)125 static void dce110_timing_generator_v_unblank_crtc(struct timing_generator *tg)
126 {
127 	uint32_t addr = mmCRTCV_BLANK_CONTROL;
128 	uint32_t value = dm_read_reg(tg->ctx, addr);
129 
130 	set_reg_field_value(
131 		value,
132 		0,
133 		CRTCV_BLANK_CONTROL,
134 		CRTC_BLANK_DATA_EN);
135 
136 	set_reg_field_value(
137 		value,
138 		0,
139 		CRTCV_BLANK_CONTROL,
140 		CRTC_BLANK_DE_MODE);
141 
142 	dm_write_reg(tg->ctx, addr, value);
143 }
144 
dce110_timing_generator_v_is_in_vertical_blank(struct timing_generator * tg)145 static bool dce110_timing_generator_v_is_in_vertical_blank(
146 		struct timing_generator *tg)
147 {
148 	uint32_t addr = 0;
149 	uint32_t value = 0;
150 	uint32_t field = 0;
151 
152 	addr = mmCRTCV_STATUS;
153 	value = dm_read_reg(tg->ctx, addr);
154 	field = get_reg_field_value(value, CRTCV_STATUS, CRTC_V_BLANK);
155 	return field == 1;
156 }
157 
dce110_timing_generator_v_is_counter_moving(struct timing_generator * tg)158 static bool dce110_timing_generator_v_is_counter_moving(struct timing_generator *tg)
159 {
160 	uint32_t value;
161 	uint32_t h1 = 0;
162 	uint32_t h2 = 0;
163 	uint32_t v1 = 0;
164 	uint32_t v2 = 0;
165 
166 	value = dm_read_reg(tg->ctx, mmCRTCV_STATUS_POSITION);
167 
168 	h1 = get_reg_field_value(
169 			value,
170 			CRTCV_STATUS_POSITION,
171 			CRTC_HORZ_COUNT);
172 
173 	v1 = get_reg_field_value(
174 			value,
175 			CRTCV_STATUS_POSITION,
176 			CRTC_VERT_COUNT);
177 
178 	value = dm_read_reg(tg->ctx, mmCRTCV_STATUS_POSITION);
179 
180 	h2 = get_reg_field_value(
181 			value,
182 			CRTCV_STATUS_POSITION,
183 			CRTC_HORZ_COUNT);
184 
185 	v2 = get_reg_field_value(
186 			value,
187 			CRTCV_STATUS_POSITION,
188 			CRTC_VERT_COUNT);
189 
190 	if (h1 == h2 && v1 == v2)
191 		return false;
192 	else
193 		return true;
194 }
195 
dce110_timing_generator_v_wait_for_vblank(struct timing_generator * tg)196 static void dce110_timing_generator_v_wait_for_vblank(struct timing_generator *tg)
197 {
198 	/* We want to catch beginning of VBlank here, so if the first try are
199 	 * in VBlank, we might be very close to Active, in this case wait for
200 	 * another frame
201 	 */
202 	while (dce110_timing_generator_v_is_in_vertical_blank(tg)) {
203 		if (!dce110_timing_generator_v_is_counter_moving(tg)) {
204 			/* error - no point to wait if counter is not moving */
205 			break;
206 		}
207 	}
208 
209 	while (!dce110_timing_generator_v_is_in_vertical_blank(tg)) {
210 		if (!dce110_timing_generator_v_is_counter_moving(tg)) {
211 			/* error - no point to wait if counter is not moving */
212 			break;
213 		}
214 	}
215 }
216 
217 /**
218 * Wait till we are in VActive (anywhere in VActive)
219 */
dce110_timing_generator_v_wait_for_vactive(struct timing_generator * tg)220 static void dce110_timing_generator_v_wait_for_vactive(struct timing_generator *tg)
221 {
222 	while (dce110_timing_generator_v_is_in_vertical_blank(tg)) {
223 		if (!dce110_timing_generator_v_is_counter_moving(tg)) {
224 			/* error - no point to wait if counter is not moving */
225 			break;
226 		}
227 	}
228 }
229 
dce110_timing_generator_v_wait_for_state(struct timing_generator * tg,enum crtc_state state)230 static void dce110_timing_generator_v_wait_for_state(struct timing_generator *tg,
231 	enum crtc_state state)
232 {
233 	switch (state) {
234 	case CRTC_STATE_VBLANK:
235 		dce110_timing_generator_v_wait_for_vblank(tg);
236 		break;
237 
238 	case CRTC_STATE_VACTIVE:
239 		dce110_timing_generator_v_wait_for_vactive(tg);
240 		break;
241 
242 	default:
243 		break;
244 	}
245 }
246 
dce110_timing_generator_v_program_blanking(struct timing_generator * tg,const struct dc_crtc_timing * timing)247 static void dce110_timing_generator_v_program_blanking(
248 	struct timing_generator *tg,
249 	const struct dc_crtc_timing *timing)
250 {
251 	uint32_t vsync_offset = timing->v_border_bottom +
252 			timing->v_front_porch;
253 	uint32_t v_sync_start = timing->v_addressable + vsync_offset;
254 
255 	uint32_t hsync_offset = timing->h_border_right +
256 			timing->h_front_porch;
257 	uint32_t h_sync_start = timing->h_addressable + hsync_offset;
258 
259 	struct dc_context *ctx = tg->ctx;
260 	uint32_t value = 0;
261 	uint32_t addr = 0;
262 	uint32_t tmp = 0;
263 
264 	addr = mmCRTCV_H_TOTAL;
265 	value = dm_read_reg(ctx, addr);
266 	set_reg_field_value(
267 		value,
268 		timing->h_total - 1,
269 		CRTCV_H_TOTAL,
270 		CRTC_H_TOTAL);
271 	dm_write_reg(ctx, addr, value);
272 
273 	addr = mmCRTCV_V_TOTAL;
274 	value = dm_read_reg(ctx, addr);
275 	set_reg_field_value(
276 		value,
277 		timing->v_total - 1,
278 		CRTCV_V_TOTAL,
279 		CRTC_V_TOTAL);
280 	dm_write_reg(ctx, addr, value);
281 
282 	addr = mmCRTCV_H_BLANK_START_END;
283 	value = dm_read_reg(ctx, addr);
284 
285 	tmp = timing->h_total -
286 		(h_sync_start + timing->h_border_left);
287 
288 	set_reg_field_value(
289 		value,
290 		tmp,
291 		CRTCV_H_BLANK_START_END,
292 		CRTC_H_BLANK_END);
293 
294 	tmp = tmp + timing->h_addressable +
295 		timing->h_border_left + timing->h_border_right;
296 
297 	set_reg_field_value(
298 		value,
299 		tmp,
300 		CRTCV_H_BLANK_START_END,
301 		CRTC_H_BLANK_START);
302 
303 	dm_write_reg(ctx, addr, value);
304 
305 	addr = mmCRTCV_V_BLANK_START_END;
306 	value = dm_read_reg(ctx, addr);
307 
308 	tmp = timing->v_total - (v_sync_start + timing->v_border_top);
309 
310 	set_reg_field_value(
311 		value,
312 		tmp,
313 		CRTCV_V_BLANK_START_END,
314 		CRTC_V_BLANK_END);
315 
316 	tmp = tmp + timing->v_addressable + timing->v_border_top +
317 		timing->v_border_bottom;
318 
319 	set_reg_field_value(
320 		value,
321 		tmp,
322 		CRTCV_V_BLANK_START_END,
323 		CRTC_V_BLANK_START);
324 
325 	dm_write_reg(ctx, addr, value);
326 
327 	addr = mmCRTCV_H_SYNC_A;
328 	value = 0;
329 	set_reg_field_value(
330 		value,
331 		timing->h_sync_width,
332 		CRTCV_H_SYNC_A,
333 		CRTC_H_SYNC_A_END);
334 	dm_write_reg(ctx, addr, value);
335 
336 	addr = mmCRTCV_H_SYNC_A_CNTL;
337 	value = dm_read_reg(ctx, addr);
338 	if (timing->flags.HSYNC_POSITIVE_POLARITY) {
339 		set_reg_field_value(
340 			value,
341 			0,
342 			CRTCV_H_SYNC_A_CNTL,
343 			CRTC_H_SYNC_A_POL);
344 	} else {
345 		set_reg_field_value(
346 			value,
347 			1,
348 			CRTCV_H_SYNC_A_CNTL,
349 			CRTC_H_SYNC_A_POL);
350 	}
351 	dm_write_reg(ctx, addr, value);
352 
353 	addr = mmCRTCV_V_SYNC_A;
354 	value = 0;
355 	set_reg_field_value(
356 		value,
357 		timing->v_sync_width,
358 		CRTCV_V_SYNC_A,
359 		CRTC_V_SYNC_A_END);
360 	dm_write_reg(ctx, addr, value);
361 
362 	addr = mmCRTCV_V_SYNC_A_CNTL;
363 	value = dm_read_reg(ctx, addr);
364 	if (timing->flags.VSYNC_POSITIVE_POLARITY) {
365 		set_reg_field_value(
366 			value,
367 			0,
368 			CRTCV_V_SYNC_A_CNTL,
369 			CRTC_V_SYNC_A_POL);
370 	} else {
371 		set_reg_field_value(
372 			value,
373 			1,
374 			CRTCV_V_SYNC_A_CNTL,
375 			CRTC_V_SYNC_A_POL);
376 	}
377 	dm_write_reg(ctx, addr, value);
378 
379 	addr = mmCRTCV_INTERLACE_CONTROL;
380 	value = dm_read_reg(ctx, addr);
381 	set_reg_field_value(
382 		value,
383 		timing->flags.INTERLACE,
384 		CRTCV_INTERLACE_CONTROL,
385 		CRTC_INTERLACE_ENABLE);
386 	dm_write_reg(ctx, addr, value);
387 }
388 
dce110_timing_generator_v_enable_advanced_request(struct timing_generator * tg,bool enable,const struct dc_crtc_timing * timing)389 static void dce110_timing_generator_v_enable_advanced_request(
390 	struct timing_generator *tg,
391 	bool enable,
392 	const struct dc_crtc_timing *timing)
393 {
394 	uint32_t addr = mmCRTCV_START_LINE_CONTROL;
395 	uint32_t value = dm_read_reg(tg->ctx, addr);
396 
397 	if (enable) {
398 		if ((timing->v_sync_width + timing->v_front_porch) <= 3) {
399 			set_reg_field_value(
400 				value,
401 				3,
402 				CRTCV_START_LINE_CONTROL,
403 				CRTC_ADVANCED_START_LINE_POSITION);
404 		} else {
405 			set_reg_field_value(
406 				value,
407 				4,
408 				CRTCV_START_LINE_CONTROL,
409 				CRTC_ADVANCED_START_LINE_POSITION);
410 		}
411 		set_reg_field_value(
412 			value,
413 			0,
414 			CRTCV_START_LINE_CONTROL,
415 			CRTC_LEGACY_REQUESTOR_EN);
416 	} else {
417 		set_reg_field_value(
418 			value,
419 			2,
420 			CRTCV_START_LINE_CONTROL,
421 			CRTC_ADVANCED_START_LINE_POSITION);
422 		set_reg_field_value(
423 			value,
424 			1,
425 			CRTCV_START_LINE_CONTROL,
426 			CRTC_LEGACY_REQUESTOR_EN);
427 	}
428 
429 	dm_write_reg(tg->ctx, addr, value);
430 }
431 
dce110_timing_generator_v_set_blank(struct timing_generator * tg,bool enable_blanking)432 static void dce110_timing_generator_v_set_blank(struct timing_generator *tg,
433 		bool enable_blanking)
434 {
435 	if (enable_blanking)
436 		dce110_timing_generator_v_blank_crtc(tg);
437 	else
438 		dce110_timing_generator_v_unblank_crtc(tg);
439 }
440 
dce110_timing_generator_v_program_timing(struct timing_generator * tg,const struct dc_crtc_timing * timing,int vready_offset,int vstartup_start,int vupdate_offset,int vupdate_width,const enum signal_type signal,bool use_vbios)441 static void dce110_timing_generator_v_program_timing(struct timing_generator *tg,
442 	const struct dc_crtc_timing *timing,
443 	int vready_offset,
444 	int vstartup_start,
445 	int vupdate_offset,
446 	int vupdate_width,
447 	const enum signal_type signal,
448 	bool use_vbios)
449 {
450 	if (use_vbios)
451 		dce110_timing_generator_program_timing_generator(tg, timing);
452 	else
453 		dce110_timing_generator_v_program_blanking(tg, timing);
454 }
455 
dce110_timing_generator_v_program_blank_color(struct timing_generator * tg,const struct tg_color * black_color)456 static void dce110_timing_generator_v_program_blank_color(
457 		struct timing_generator *tg,
458 		const struct tg_color *black_color)
459 {
460 	uint32_t addr = mmCRTCV_BLACK_COLOR;
461 	uint32_t value = dm_read_reg(tg->ctx, addr);
462 
463 	set_reg_field_value(
464 		value,
465 		black_color->color_b_cb,
466 		CRTCV_BLACK_COLOR,
467 		CRTC_BLACK_COLOR_B_CB);
468 	set_reg_field_value(
469 		value,
470 		black_color->color_g_y,
471 		CRTCV_BLACK_COLOR,
472 		CRTC_BLACK_COLOR_G_Y);
473 	set_reg_field_value(
474 		value,
475 		black_color->color_r_cr,
476 		CRTCV_BLACK_COLOR,
477 		CRTC_BLACK_COLOR_R_CR);
478 
479 	dm_write_reg(tg->ctx, addr, value);
480 }
481 
dce110_timing_generator_v_set_overscan_color_black(struct timing_generator * tg,const struct tg_color * color)482 static void dce110_timing_generator_v_set_overscan_color_black(
483 	struct timing_generator *tg,
484 	const struct tg_color *color)
485 {
486 	struct dc_context *ctx = tg->ctx;
487 	uint32_t addr;
488 	uint32_t value = 0;
489 
490 	set_reg_field_value(
491 			value,
492 			color->color_b_cb,
493 			CRTC_OVERSCAN_COLOR,
494 			CRTC_OVERSCAN_COLOR_BLUE);
495 
496 	set_reg_field_value(
497 			value,
498 			color->color_r_cr,
499 			CRTC_OVERSCAN_COLOR,
500 			CRTC_OVERSCAN_COLOR_RED);
501 
502 	set_reg_field_value(
503 			value,
504 			color->color_g_y,
505 			CRTC_OVERSCAN_COLOR,
506 			CRTC_OVERSCAN_COLOR_GREEN);
507 
508 	addr = mmCRTCV_OVERSCAN_COLOR;
509 	dm_write_reg(ctx, addr, value);
510 	addr = mmCRTCV_BLACK_COLOR;
511 	dm_write_reg(ctx, addr, value);
512 	/* This is desirable to have a constant DAC output voltage during the
513 	 * blank time that is higher than the 0 volt reference level that the
514 	 * DAC outputs when the NBLANK signal
515 	 * is asserted low, such as for output to an analog TV. */
516 	addr = mmCRTCV_BLANK_DATA_COLOR;
517 	dm_write_reg(ctx, addr, value);
518 
519 	/* TO DO we have to program EXT registers and we need to know LB DATA
520 	 * format because it is used when more 10 , i.e. 12 bits per color
521 	 *
522 	 * m_mmDxCRTC_OVERSCAN_COLOR_EXT
523 	 * m_mmDxCRTC_BLACK_COLOR_EXT
524 	 * m_mmDxCRTC_BLANK_DATA_COLOR_EXT
525 	 */
526 }
527 
dce110_tg_v_program_blank_color(struct timing_generator * tg,const struct tg_color * black_color)528 static void dce110_tg_v_program_blank_color(struct timing_generator *tg,
529 		const struct tg_color *black_color)
530 {
531 	uint32_t addr = mmCRTCV_BLACK_COLOR;
532 	uint32_t value = dm_read_reg(tg->ctx, addr);
533 
534 	set_reg_field_value(
535 		value,
536 		black_color->color_b_cb,
537 		CRTCV_BLACK_COLOR,
538 		CRTC_BLACK_COLOR_B_CB);
539 	set_reg_field_value(
540 		value,
541 		black_color->color_g_y,
542 		CRTCV_BLACK_COLOR,
543 		CRTC_BLACK_COLOR_G_Y);
544 	set_reg_field_value(
545 		value,
546 		black_color->color_r_cr,
547 		CRTCV_BLACK_COLOR,
548 		CRTC_BLACK_COLOR_R_CR);
549 
550 	dm_write_reg(tg->ctx, addr, value);
551 
552 	addr = mmCRTCV_BLANK_DATA_COLOR;
553 	dm_write_reg(tg->ctx, addr, value);
554 }
555 
dce110_timing_generator_v_set_overscan_color(struct timing_generator * tg,const struct tg_color * overscan_color)556 static void dce110_timing_generator_v_set_overscan_color(struct timing_generator *tg,
557 	const struct tg_color *overscan_color)
558 {
559 	struct dc_context *ctx = tg->ctx;
560 	uint32_t value = 0;
561 	uint32_t addr;
562 
563 	set_reg_field_value(
564 		value,
565 		overscan_color->color_b_cb,
566 		CRTCV_OVERSCAN_COLOR,
567 		CRTC_OVERSCAN_COLOR_BLUE);
568 
569 	set_reg_field_value(
570 		value,
571 		overscan_color->color_g_y,
572 		CRTCV_OVERSCAN_COLOR,
573 		CRTC_OVERSCAN_COLOR_GREEN);
574 
575 	set_reg_field_value(
576 		value,
577 		overscan_color->color_r_cr,
578 		CRTCV_OVERSCAN_COLOR,
579 		CRTC_OVERSCAN_COLOR_RED);
580 
581 	addr = mmCRTCV_OVERSCAN_COLOR;
582 	dm_write_reg(ctx, addr, value);
583 }
584 
dce110_timing_generator_v_set_colors(struct timing_generator * tg,const struct tg_color * blank_color,const struct tg_color * overscan_color)585 static void dce110_timing_generator_v_set_colors(struct timing_generator *tg,
586 	const struct tg_color *blank_color,
587 	const struct tg_color *overscan_color)
588 {
589 	if (blank_color != NULL)
590 		dce110_tg_v_program_blank_color(tg, blank_color);
591 	if (overscan_color != NULL)
592 		dce110_timing_generator_v_set_overscan_color(tg, overscan_color);
593 }
594 
dce110_timing_generator_v_set_early_control(struct timing_generator * tg,uint32_t early_cntl)595 static void dce110_timing_generator_v_set_early_control(
596 		struct timing_generator *tg,
597 		uint32_t early_cntl)
598 {
599 	uint32_t regval;
600 	uint32_t address = mmCRTC_CONTROL;
601 
602 	regval = dm_read_reg(tg->ctx, address);
603 	set_reg_field_value(regval, early_cntl,
604 			CRTCV_CONTROL, CRTC_HBLANK_EARLY_CONTROL);
605 	dm_write_reg(tg->ctx, address, regval);
606 }
607 
dce110_timing_generator_v_get_vblank_counter(struct timing_generator * tg)608 static uint32_t dce110_timing_generator_v_get_vblank_counter(struct timing_generator *tg)
609 {
610 	uint32_t addr = mmCRTCV_STATUS_FRAME_COUNT;
611 	uint32_t value = dm_read_reg(tg->ctx, addr);
612 	uint32_t field = get_reg_field_value(
613 			value, CRTCV_STATUS_FRAME_COUNT, CRTC_FRAME_COUNT);
614 
615 	return field;
616 }
617 
dce110_timing_generator_v_did_triggered_reset_occur(struct timing_generator * tg)618 static bool dce110_timing_generator_v_did_triggered_reset_occur(
619 	struct timing_generator *tg)
620 {
621 	DC_LOG_ERROR("Timing Sync not supported on underlay pipe\n");
622 	return false;
623 }
624 
dce110_timing_generator_v_setup_global_swap_lock(struct timing_generator * tg,const struct dcp_gsl_params * gsl_params)625 static void dce110_timing_generator_v_setup_global_swap_lock(
626 	struct timing_generator *tg,
627 	const struct dcp_gsl_params *gsl_params)
628 {
629 	DC_LOG_ERROR("Timing Sync not supported on underlay pipe\n");
630 	return;
631 }
632 
dce110_timing_generator_v_enable_reset_trigger(struct timing_generator * tg,int source_tg_inst)633 static void dce110_timing_generator_v_enable_reset_trigger(
634 	struct timing_generator *tg,
635 	int source_tg_inst)
636 {
637 	DC_LOG_ERROR("Timing Sync not supported on underlay pipe\n");
638 	return;
639 }
640 
dce110_timing_generator_v_disable_reset_trigger(struct timing_generator * tg)641 static void dce110_timing_generator_v_disable_reset_trigger(
642 	struct timing_generator *tg)
643 {
644 	DC_LOG_ERROR("Timing Sync not supported on underlay pipe\n");
645 	return;
646 }
647 
dce110_timing_generator_v_tear_down_global_swap_lock(struct timing_generator * tg)648 static void dce110_timing_generator_v_tear_down_global_swap_lock(
649 	struct timing_generator *tg)
650 {
651 	DC_LOG_ERROR("Timing Sync not supported on underlay pipe\n");
652 	return;
653 }
654 
dce110_timing_generator_v_disable_vga(struct timing_generator * tg)655 static void dce110_timing_generator_v_disable_vga(
656 	struct timing_generator *tg)
657 {
658 	return;
659 }
660 
661 /** ********************************************************************************************
662  *
663  * DCE11 Timing Generator Constructor / Destructor
664  *
665  *********************************************************************************************/
666 static const struct timing_generator_funcs dce110_tg_v_funcs = {
667 		.validate_timing = dce110_tg_validate_timing,
668 		.program_timing = dce110_timing_generator_v_program_timing,
669 		.enable_crtc = dce110_timing_generator_v_enable_crtc,
670 		.disable_crtc = dce110_timing_generator_v_disable_crtc,
671 		.is_counter_moving = dce110_timing_generator_v_is_counter_moving,
672 		.get_position = NULL, /* Not to be implemented for underlay*/
673 		.get_frame_count = dce110_timing_generator_v_get_vblank_counter,
674 		.set_early_control = dce110_timing_generator_v_set_early_control,
675 		.wait_for_state = dce110_timing_generator_v_wait_for_state,
676 		.set_blank = dce110_timing_generator_v_set_blank,
677 		.set_colors = dce110_timing_generator_v_set_colors,
678 		.set_overscan_blank_color =
679 				dce110_timing_generator_v_set_overscan_color_black,
680 		.set_blank_color = dce110_timing_generator_v_program_blank_color,
681 		.disable_vga = dce110_timing_generator_v_disable_vga,
682 		.did_triggered_reset_occur =
683 				dce110_timing_generator_v_did_triggered_reset_occur,
684 		.setup_global_swap_lock =
685 				dce110_timing_generator_v_setup_global_swap_lock,
686 		.enable_reset_trigger = dce110_timing_generator_v_enable_reset_trigger,
687 		.disable_reset_trigger = dce110_timing_generator_v_disable_reset_trigger,
688 		.tear_down_global_swap_lock =
689 				dce110_timing_generator_v_tear_down_global_swap_lock,
690 		.enable_advanced_request =
691 				dce110_timing_generator_v_enable_advanced_request
692 };
693 
dce110_timing_generator_v_construct(struct dce110_timing_generator * tg110,struct dc_context * ctx)694 void dce110_timing_generator_v_construct(
695 	struct dce110_timing_generator *tg110,
696 	struct dc_context *ctx)
697 {
698 	tg110->controller_id = CONTROLLER_ID_UNDERLAY0;
699 
700 	tg110->base.funcs = &dce110_tg_v_funcs;
701 
702 	tg110->base.ctx = ctx;
703 	tg110->base.bp = ctx->dc_bios;
704 
705 	tg110->max_h_total = CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1;
706 	tg110->max_v_total = CRTC_V_TOTAL__CRTC_V_TOTAL_MASK + 1;
707 
708 	tg110->min_h_blank = 56;
709 	tg110->min_h_front_porch = 4;
710 	tg110->min_h_back_porch = 4;
711 }
712