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