2 * Copyright 2012-15 Advanced Micro Devices, Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
26 #include "reg_helper.h"
27 #include "dcn10_timing_generator.h"
37 #define FN(reg_name, field_name) \
38 tgn10->tg_shift->field_name, tgn10->tg_mask->field_name
40 #define STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN 0x100
43 * apply_front_porch_workaround TODO FPGA still need?
45 * This is a workaround for a bug that has existed since R5xx and has not been
46 * fixed keep Front porch at minimum 2 for Interlaced mode or 1 for progressive.
48 static void tgn10_apply_front_porch_workaround(
49 struct timing_generator
*tg
,
50 struct dc_crtc_timing
*timing
)
52 if (timing
->flags
.INTERLACE
== 1) {
53 if (timing
->v_front_porch
< 2)
54 timing
->v_front_porch
= 2;
56 if (timing
->v_front_porch
< 1)
57 timing
->v_front_porch
= 1;
61 static void tgn10_program_global_sync(
62 struct timing_generator
*tg
)
64 struct dcn10_timing_generator
*tgn10
= DCN10TG_FROM_TG(tg
);
66 if (tg
->dlg_otg_param
.vstartup_start
== 0) {
71 REG_SET(OTG_VSTARTUP_PARAM
, 0,
72 VSTARTUP_START
, tg
->dlg_otg_param
.vstartup_start
);
74 REG_SET_2(OTG_VUPDATE_PARAM
, 0,
75 VUPDATE_OFFSET
, tg
->dlg_otg_param
.vupdate_offset
,
76 VUPDATE_WIDTH
, tg
->dlg_otg_param
.vupdate_width
);
78 REG_SET(OTG_VREADY_PARAM
, 0,
79 VREADY_OFFSET
, tg
->dlg_otg_param
.vready_offset
);
82 static void tgn10_disable_stereo(struct timing_generator
*tg
)
84 struct dcn10_timing_generator
*tgn10
= DCN10TG_FROM_TG(tg
);
86 REG_SET(OTG_STEREO_CONTROL
, 0,
89 REG_SET_3(OTG_3D_STRUCTURE_CONTROL
, 0,
90 OTG_3D_STRUCTURE_EN
, 0,
91 OTG_3D_STRUCTURE_V_UPDATE_MODE
, 0,
92 OTG_3D_STRUCTURE_STEREO_SEL_OVR
, 0);
94 REG_UPDATE(OPPBUF_CONTROL
,
95 OPPBUF_ACTIVE_WIDTH
, 0);
96 REG_UPDATE(OPPBUF_3D_PARAMETERS_0
,
97 OPPBUF_3D_VACT_SPACE1_SIZE
, 0);
101 * program_timing_generator used by mode timing set
102 * Program CRTC Timing Registers - OTG_H_*, OTG_V_*, Pixel repetition.
103 * Including SYNC. Call BIOS command table to program Timings.
105 static void tgn10_program_timing(
106 struct timing_generator
*tg
,
107 const struct dc_crtc_timing
*dc_crtc_timing
,
110 struct dc_crtc_timing patched_crtc_timing
;
111 uint32_t vesa_sync_start
;
112 uint32_t asic_blank_end
;
113 uint32_t asic_blank_start
;
116 uint32_t v_init
, v_fp2
;
117 uint32_t h_sync_polarity
, v_sync_polarity
;
118 uint32_t interlace_factor
;
119 uint32_t start_point
= 0;
120 uint32_t field_num
= 0;
122 int32_t vertical_line_start
;
124 struct dcn10_timing_generator
*tgn10
= DCN10TG_FROM_TG(tg
);
126 patched_crtc_timing
= *dc_crtc_timing
;
127 tgn10_apply_front_porch_workaround(tg
, &patched_crtc_timing
);
129 /* Load horizontal timing */
131 /* CRTC_H_TOTAL = vesa.h_total - 1 */
132 REG_SET(OTG_H_TOTAL
, 0,
133 OTG_H_TOTAL
, patched_crtc_timing
.h_total
- 1);
135 /* h_sync_start = 0, h_sync_end = vesa.h_sync_width */
136 REG_UPDATE_2(OTG_H_SYNC_A
,
137 OTG_H_SYNC_A_START
, 0,
138 OTG_H_SYNC_A_END
, patched_crtc_timing
.h_sync_width
);
140 /* asic_h_blank_end = HsyncWidth + HbackPorch =
141 * vesa. usHorizontalTotal - vesa. usHorizontalSyncStart -
144 vesa_sync_start
= patched_crtc_timing
.h_addressable
+
145 patched_crtc_timing
.h_border_right
+
146 patched_crtc_timing
.h_front_porch
;
148 asic_blank_end
= patched_crtc_timing
.h_total
-
150 patched_crtc_timing
.h_border_left
;
152 /* h_blank_start = v_blank_end + v_active */
153 asic_blank_start
= asic_blank_end
+
154 patched_crtc_timing
.h_border_left
+
155 patched_crtc_timing
.h_addressable
+
156 patched_crtc_timing
.h_border_right
;
158 REG_UPDATE_2(OTG_H_BLANK_START_END
,
159 OTG_H_BLANK_START
, asic_blank_start
,
160 OTG_H_BLANK_END
, asic_blank_end
);
162 /* h_sync polarity */
163 h_sync_polarity
= patched_crtc_timing
.flags
.HSYNC_POSITIVE_POLARITY
?
166 REG_UPDATE(OTG_H_SYNC_A_CNTL
,
167 OTG_H_SYNC_A_POL
, h_sync_polarity
);
169 /* Load vertical timing */
171 /* CRTC_V_TOTAL = v_total - 1 */
172 if (patched_crtc_timing
.flags
.INTERLACE
) {
173 interlace_factor
= 2;
174 v_total
= 2 * patched_crtc_timing
.v_total
;
176 interlace_factor
= 1;
177 v_total
= patched_crtc_timing
.v_total
- 1;
179 REG_SET(OTG_V_TOTAL
, 0,
180 OTG_V_TOTAL
, v_total
);
182 /* In case of V_TOTAL_CONTROL is on, make sure OTG_V_TOTAL_MAX and
183 * OTG_V_TOTAL_MIN are equal to V_TOTAL.
185 REG_SET(OTG_V_TOTAL_MAX
, 0,
186 OTG_V_TOTAL_MAX
, v_total
);
187 REG_SET(OTG_V_TOTAL_MIN
, 0,
188 OTG_V_TOTAL_MIN
, v_total
);
190 /* v_sync_start = 0, v_sync_end = v_sync_width */
191 v_sync_end
= patched_crtc_timing
.v_sync_width
* interlace_factor
;
193 REG_UPDATE_2(OTG_V_SYNC_A
,
194 OTG_V_SYNC_A_START
, 0,
195 OTG_V_SYNC_A_END
, v_sync_end
);
197 vesa_sync_start
= patched_crtc_timing
.v_addressable
+
198 patched_crtc_timing
.v_border_bottom
+
199 patched_crtc_timing
.v_front_porch
;
201 asic_blank_end
= (patched_crtc_timing
.v_total
-
203 patched_crtc_timing
.v_border_top
)
206 /* v_blank_start = v_blank_end + v_active */
207 asic_blank_start
= asic_blank_end
+
208 (patched_crtc_timing
.v_border_top
+
209 patched_crtc_timing
.v_addressable
+
210 patched_crtc_timing
.v_border_bottom
)
213 REG_UPDATE_2(OTG_V_BLANK_START_END
,
214 OTG_V_BLANK_START
, asic_blank_start
,
215 OTG_V_BLANK_END
, asic_blank_end
);
217 /* Use OTG_VERTICAL_INTERRUPT2 replace VUPDATE interrupt,
218 * program the reg for interrupt postition.
220 vertical_line_start
= asic_blank_end
- tg
->dlg_otg_param
.vstartup_start
+ 1;
221 if (vertical_line_start
< 0) {
223 vertical_line_start
= 0;
225 REG_SET(OTG_VERTICAL_INTERRUPT2_POSITION
, 0,
226 OTG_VERTICAL_INTERRUPT2_LINE_START
, vertical_line_start
);
228 /* v_sync polarity */
229 v_sync_polarity
= patched_crtc_timing
.flags
.VSYNC_POSITIVE_POLARITY
?
232 REG_UPDATE(OTG_V_SYNC_A_CNTL
,
233 OTG_V_SYNC_A_POL
, v_sync_polarity
);
235 v_init
= asic_blank_start
;
236 if (tg
->dlg_otg_param
.signal
== SIGNAL_TYPE_DISPLAY_PORT
||
237 tg
->dlg_otg_param
.signal
== SIGNAL_TYPE_DISPLAY_PORT_MST
||
238 tg
->dlg_otg_param
.signal
== SIGNAL_TYPE_EDP
) {
240 if (patched_crtc_timing
.flags
.INTERLACE
== 1)
244 if (tg
->dlg_otg_param
.vstartup_start
> asic_blank_end
)
245 v_fp2
= tg
->dlg_otg_param
.vstartup_start
> asic_blank_end
;
248 if (patched_crtc_timing
.flags
.INTERLACE
== 1) {
249 REG_UPDATE(OTG_INTERLACE_CONTROL
,
250 OTG_INTERLACE_ENABLE
, 1);
252 if ((tg
->dlg_otg_param
.vstartup_start
/2)*2 > asic_blank_end
)
256 REG_UPDATE(OTG_INTERLACE_CONTROL
,
257 OTG_INTERLACE_ENABLE
, 0);
260 /* VTG enable set to 0 first VInit */
264 REG_UPDATE_2(CONTROL
,
266 VTG0_VCOUNT_INIT
, v_init
);
268 /* original code is using VTG offset to address OTG reg, seems wrong */
269 REG_UPDATE_2(OTG_CONTROL
,
270 OTG_START_POINT_CNTL
, start_point
,
271 OTG_FIELD_NUMBER_CNTL
, field_num
);
273 tgn10_program_global_sync(tg
);
276 * patched_crtc_timing.flags.HORZ_COUNT_BY_TWO == 1
277 * program_horz_count_by_2
278 * for DVI 30bpp mode, 0 otherwise
279 * program_horz_count_by_2(tg, &patched_crtc_timing);
282 /* Enable stereo - only when we need to pack 3D frame. Other types
283 * of stereo handled in explicit call
285 h_div_2
= (dc_crtc_timing
->pixel_encoding
== PIXEL_ENCODING_YCBCR420
) ?
288 REG_UPDATE(OTG_H_TIMING_CNTL
,
289 OTG_H_TIMING_DIV_BY2
, h_div_2
);
295 * Call ASIC Control Object to UnBlank CRTC.
297 static void tgn10_unblank_crtc(struct timing_generator
*tg
)
299 struct dcn10_timing_generator
*tgn10
= DCN10TG_FROM_TG(tg
);
300 uint32_t vertical_interrupt_enable
= 0;
302 REG_GET(OTG_VERTICAL_INTERRUPT2_CONTROL
,
303 OTG_VERTICAL_INTERRUPT2_INT_ENABLE
, &vertical_interrupt_enable
);
305 /* temporary work around for vertical interrupt, once vertical interrupt enabled,
306 * this check will be removed.
308 if (vertical_interrupt_enable
)
309 REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL
,
310 OTG_BLANK_DATA_DOUBLE_BUFFER_EN
, 1);
312 REG_UPDATE_2(OTG_BLANK_CONTROL
,
313 OTG_BLANK_DATA_EN
, 0,
314 OTG_BLANK_DE_MODE
, 0);
319 * Call ASIC Control Object to Blank CRTC.
322 static void tgn10_blank_crtc(struct timing_generator
*tg
)
324 struct dcn10_timing_generator
*tgn10
= DCN10TG_FROM_TG(tg
);
326 REG_UPDATE_2(OTG_BLANK_CONTROL
,
327 OTG_BLANK_DATA_EN
, 1,
328 OTG_BLANK_DE_MODE
, 0);
330 /* todo: why are we waiting for BLANK_DATA_EN? shouldn't we be waiting
333 REG_WAIT(OTG_BLANK_CONTROL
,
334 OTG_BLANK_DATA_EN
, 1,
337 REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL
,
338 OTG_BLANK_DATA_DOUBLE_BUFFER_EN
, 0);
341 static void tgn10_set_blank(struct timing_generator
*tg
,
342 bool enable_blanking
)
345 tgn10_blank_crtc(tg
);
347 tgn10_unblank_crtc(tg
);
350 static bool tgn10_is_blanked(struct timing_generator
*tg
)
352 struct dcn10_timing_generator
*tgn10
= DCN10TG_FROM_TG(tg
);
354 uint32_t blank_state
;
356 REG_GET_2(OTG_BLANK_CONTROL
,
357 OTG_BLANK_DATA_EN
, &blank_en
,
358 OTG_CURRENT_BLANK_STATE
, &blank_state
);
360 return blank_en
&& blank_state
;
363 static void tgn10_enable_optc_clock(struct timing_generator
*tg
, bool enable
)
365 struct dcn10_timing_generator
*tgn10
= DCN10TG_FROM_TG(tg
);
368 REG_UPDATE_2(OPTC_INPUT_CLOCK_CONTROL
,
369 OPTC_INPUT_CLK_EN
, 1,
370 OPTC_INPUT_CLK_GATE_DIS
, 1);
372 REG_WAIT(OPTC_INPUT_CLOCK_CONTROL
,
373 OPTC_INPUT_CLK_ON
, 1,
377 REG_UPDATE_2(OTG_CLOCK_CONTROL
,
379 OTG_CLOCK_GATE_DIS
, 1);
380 REG_WAIT(OTG_CLOCK_CONTROL
,
384 REG_UPDATE_2(OTG_CLOCK_CONTROL
,
385 OTG_CLOCK_GATE_DIS
, 0,
388 if (tg
->ctx
->dce_environment
!= DCE_ENV_FPGA_MAXIMUS
)
389 REG_WAIT(OTG_CLOCK_CONTROL
,
393 REG_UPDATE_2(OPTC_INPUT_CLOCK_CONTROL
,
394 OPTC_INPUT_CLK_GATE_DIS
, 0,
395 OPTC_INPUT_CLK_EN
, 0);
397 if (tg
->ctx
->dce_environment
!= DCE_ENV_FPGA_MAXIMUS
)
398 REG_WAIT(OPTC_INPUT_CLOCK_CONTROL
,
399 OPTC_INPUT_CLK_ON
, 0,
406 * Enable CRTC - call ASIC Control Object to enable Timing generator.
408 static bool tgn10_enable_crtc(struct timing_generator
*tg
)
410 /* TODO FPGA wait for answer
411 * OTG_MASTER_UPDATE_MODE != CRTC_MASTER_UPDATE_MODE
412 * OTG_MASTER_UPDATE_LOCK != CRTC_MASTER_UPDATE_LOCK
414 struct dcn10_timing_generator
*tgn10
= DCN10TG_FROM_TG(tg
);
416 /* opp instance for OTG. For DCN1.0, ODM is remoed.
417 * OPP and OPTC should 1:1 mapping
419 REG_UPDATE(OPTC_DATA_SOURCE_SELECT
,
420 OPTC_SRC_SEL
, tg
->inst
);
422 /* VTG enable first is for HW workaround */
427 REG_UPDATE_2(OTG_CONTROL
,
428 OTG_DISABLE_POINT_CNTL
, 3,
434 /* disable_crtc - call ASIC Control Object to disable Timing generator. */
435 static bool tgn10_disable_crtc(struct timing_generator
*tg
)
437 struct dcn10_timing_generator
*tgn10
= DCN10TG_FROM_TG(tg
);
439 /* disable otg request until end of the first line
440 * in the vertical blank region
442 REG_UPDATE_2(OTG_CONTROL
,
443 OTG_DISABLE_POINT_CNTL
, 3,
449 /* CRTC disabled, so disable clock. */
450 REG_WAIT(OTG_CLOCK_CONTROL
,
458 static void tgn10_program_blank_color(
459 struct timing_generator
*tg
,
460 const struct tg_color
*black_color
)
462 struct dcn10_timing_generator
*tgn10
= DCN10TG_FROM_TG(tg
);
464 REG_SET_3(OTG_BLACK_COLOR
, 0,
465 OTG_BLACK_COLOR_B_CB
, black_color
->color_b_cb
,
466 OTG_BLACK_COLOR_G_Y
, black_color
->color_g_y
,
467 OTG_BLACK_COLOR_R_CR
, black_color
->color_r_cr
);
470 static bool tgn10_validate_timing(
471 struct timing_generator
*tg
,
472 const struct dc_crtc_timing
*timing
)
474 uint32_t interlace_factor
;
477 uint32_t min_v_blank
;
478 struct dcn10_timing_generator
*tgn10
= DCN10TG_FROM_TG(tg
);
480 ASSERT(timing
!= NULL
);
482 interlace_factor
= timing
->flags
.INTERLACE
? 2 : 1;
483 v_blank
= (timing
->v_total
- timing
->v_addressable
-
484 timing
->v_border_top
- timing
->v_border_bottom
) *
487 h_blank
= (timing
->h_total
- timing
->h_addressable
-
488 timing
->h_border_right
-
489 timing
->h_border_left
);
491 if (timing
->timing_3d_format
!= TIMING_3D_FORMAT_NONE
&&
492 timing
->timing_3d_format
!= TIMING_3D_FORMAT_HW_FRAME_PACKING
&&
493 timing
->timing_3d_format
!= TIMING_3D_FORMAT_TOP_AND_BOTTOM
&&
494 timing
->timing_3d_format
!= TIMING_3D_FORMAT_SIDE_BY_SIDE
&&
495 timing
->timing_3d_format
!= TIMING_3D_FORMAT_FRAME_ALTERNATE
&&
496 timing
->timing_3d_format
!= TIMING_3D_FORMAT_INBAND_FA
)
499 if (timing
->timing_3d_format
!= TIMING_3D_FORMAT_NONE
&&
500 tg
->ctx
->dc
->debug
.disable_stereo_support
)
502 /* Temporarily blocking interlacing mode until it's supported */
503 if (timing
->flags
.INTERLACE
== 1)
506 /* Check maximum number of pixels supported by Timing Generator
507 * (Currently will never fail, in order to fail needs display which
508 * needs more than 8192 horizontal and
509 * more than 8192 vertical total pixels)
511 if (timing
->h_total
> tgn10
->max_h_total
||
512 timing
->v_total
> tgn10
->max_v_total
)
516 if (h_blank
< tgn10
->min_h_blank
)
519 if (timing
->h_sync_width
< tgn10
->min_h_sync_width
||
520 timing
->v_sync_width
< tgn10
->min_v_sync_width
)
523 min_v_blank
= timing
->flags
.INTERLACE
?tgn10
->min_v_blank_interlace
:tgn10
->min_v_blank
;
525 if (v_blank
< min_v_blank
)
536 * Get counter for vertical blanks. use register CRTC_STATUS_FRAME_COUNT which
537 * holds the counter of frames.
540 * struct timing_generator *tg - [in] timing generator which controls the
544 * Counter of frames, which should equal to number of vblanks.
546 static uint32_t tgn10_get_vblank_counter(struct timing_generator
*tg
)
548 struct dcn10_timing_generator
*tgn10
= DCN10TG_FROM_TG(tg
);
549 uint32_t frame_count
;
551 REG_GET(OTG_STATUS_FRAME_COUNT
,
552 OTG_FRAME_COUNT
, &frame_count
);
557 static void tgn10_lock(struct timing_generator
*tg
)
559 struct dcn10_timing_generator
*tgn10
= DCN10TG_FROM_TG(tg
);
561 REG_SET(OTG_GLOBAL_CONTROL0
, 0,
562 OTG_MASTER_UPDATE_LOCK_SEL
, tg
->inst
);
563 REG_SET(OTG_MASTER_UPDATE_LOCK
, 0,
564 OTG_MASTER_UPDATE_LOCK
, 1);
566 if (tg
->ctx
->dce_environment
!= DCE_ENV_FPGA_MAXIMUS
)
567 REG_WAIT(OTG_MASTER_UPDATE_LOCK
,
568 UPDATE_LOCK_STATUS
, 1,
572 static void tgn10_unlock(struct timing_generator
*tg
)
574 struct dcn10_timing_generator
*tgn10
= DCN10TG_FROM_TG(tg
);
576 REG_SET(OTG_MASTER_UPDATE_LOCK
, 0,
577 OTG_MASTER_UPDATE_LOCK
, 0);
579 /* why are we waiting here? */
580 REG_WAIT(OTG_DOUBLE_BUFFER_CONTROL
,
581 OTG_UPDATE_PENDING
, 0,
585 static void tgn10_get_position(struct timing_generator
*tg
,
586 struct crtc_position
*position
)
588 struct dcn10_timing_generator
*tgn10
= DCN10TG_FROM_TG(tg
);
590 REG_GET_2(OTG_STATUS_POSITION
,
591 OTG_HORZ_COUNT
, &position
->horizontal_count
,
592 OTG_VERT_COUNT
, &position
->vertical_count
);
594 REG_GET(OTG_NOM_VERT_POSITION
,
595 OTG_VERT_COUNT_NOM
, &position
->nominal_vcount
);
598 static bool tgn10_is_counter_moving(struct timing_generator
*tg
)
600 struct crtc_position position1
, position2
;
602 tg
->funcs
->get_position(tg
, &position1
);
603 tg
->funcs
->get_position(tg
, &position2
);
605 if (position1
.horizontal_count
== position2
.horizontal_count
&&
606 position1
.vertical_count
== position2
.vertical_count
)
612 static bool tgn10_did_triggered_reset_occur(
613 struct timing_generator
*tg
)
615 struct dcn10_timing_generator
*tgn10
= DCN10TG_FROM_TG(tg
);
618 REG_GET(OTG_FORCE_COUNT_NOW_CNTL
,
619 OTG_FORCE_COUNT_NOW_OCCURRED
, &occurred
);
621 return occurred
!= 0;
624 static void tgn10_enable_reset_trigger(struct timing_generator
*tg
, int source_tg_inst
)
626 struct dcn10_timing_generator
*tgn10
= DCN10TG_FROM_TG(tg
);
627 uint32_t falling_edge
;
629 REG_GET(OTG_V_SYNC_A_CNTL
,
630 OTG_V_SYNC_A_POL
, &falling_edge
);
633 REG_SET_3(OTG_TRIGA_CNTL
, 0,
634 /* vsync signal from selected OTG pipe based
635 * on OTG_TRIG_SOURCE_PIPE_SELECT setting
637 OTG_TRIGA_SOURCE_SELECT
, 20,
638 OTG_TRIGA_SOURCE_PIPE_SELECT
, source_tg_inst
,
639 /* always detect falling edge */
640 OTG_TRIGA_FALLING_EDGE_DETECT_CNTL
, 1);
642 REG_SET_3(OTG_TRIGA_CNTL
, 0,
643 /* vsync signal from selected OTG pipe based
644 * on OTG_TRIG_SOURCE_PIPE_SELECT setting
646 OTG_TRIGA_SOURCE_SELECT
, 20,
647 OTG_TRIGA_SOURCE_PIPE_SELECT
, source_tg_inst
,
648 /* always detect rising edge */
649 OTG_TRIGA_RISING_EDGE_DETECT_CNTL
, 1);
651 REG_SET(OTG_FORCE_COUNT_NOW_CNTL
, 0,
652 /* force H count to H_TOTAL and V count to V_TOTAL in
653 * progressive mode and V_TOTAL-1 in interlaced mode
655 OTG_FORCE_COUNT_NOW_MODE
, 2);
658 static void tgn10_disable_reset_trigger(struct timing_generator
*tg
)
660 struct dcn10_timing_generator
*tgn10
= DCN10TG_FROM_TG(tg
);
662 REG_WRITE(OTG_TRIGA_CNTL
, 0);
664 REG_SET(OTG_FORCE_COUNT_NOW_CNTL
, 0,
665 OTG_FORCE_COUNT_NOW_CLEAR
, 1);
668 static void tgn10_wait_for_state(struct timing_generator
*tg
,
669 enum crtc_state state
)
671 struct dcn10_timing_generator
*tgn10
= DCN10TG_FROM_TG(tg
);
674 case CRTC_STATE_VBLANK
:
677 1, 100000); /* 1 vupdate at 10hz */
680 case CRTC_STATE_VACTIVE
:
682 OTG_V_ACTIVE_DISP
, 1,
683 1, 100000); /* 1 vupdate at 10hz */
691 static void tgn10_set_early_control(
692 struct timing_generator
*tg
,
695 /* asic design change, do not need this control
696 * empty for share caller logic
701 static void tgn10_set_static_screen_control(
702 struct timing_generator
*tg
,
705 struct dcn10_timing_generator
*tgn10
= DCN10TG_FROM_TG(tg
);
707 /* Bit 8 is no longer applicable in RV for PSR case,
708 * set bit 8 to 0 if given
710 if ((value
& STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN
)
713 ~STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN
;
715 REG_SET_2(OTG_STATIC_SCREEN_CONTROL
, 0,
716 OTG_STATIC_SCREEN_EVENT_MASK
, value
,
717 OTG_STATIC_SCREEN_FRAME_COUNT
, 2);
722 *****************************************************************************
726 * Program dynamic refresh rate registers m_OTGx_OTG_V_TOTAL_*.
728 *****************************************************************************
730 static void tgn10_set_drr(
731 struct timing_generator
*tg
,
732 const struct drr_params
*params
)
734 struct dcn10_timing_generator
*tgn10
= DCN10TG_FROM_TG(tg
);
736 if (params
!= NULL
&&
737 params
->vertical_total_max
> 0 &&
738 params
->vertical_total_min
> 0) {
740 REG_SET(OTG_V_TOTAL_MAX
, 0,
741 OTG_V_TOTAL_MAX
, params
->vertical_total_max
- 1);
743 REG_SET(OTG_V_TOTAL_MIN
, 0,
744 OTG_V_TOTAL_MIN
, params
->vertical_total_min
- 1);
746 REG_UPDATE_5(OTG_V_TOTAL_CONTROL
,
747 OTG_V_TOTAL_MIN_SEL
, 1,
748 OTG_V_TOTAL_MAX_SEL
, 1,
749 OTG_FORCE_LOCK_ON_EVENT
, 0,
750 OTG_SET_V_TOTAL_MIN_MASK_EN
, 0,
751 OTG_SET_V_TOTAL_MIN_MASK
, 0);
753 REG_SET(OTG_V_TOTAL_MIN
, 0,
756 REG_SET(OTG_V_TOTAL_MAX
, 0,
759 REG_UPDATE_4(OTG_V_TOTAL_CONTROL
,
760 OTG_SET_V_TOTAL_MIN_MASK
, 0,
761 OTG_V_TOTAL_MIN_SEL
, 0,
762 OTG_V_TOTAL_MAX_SEL
, 0,
763 OTG_FORCE_LOCK_ON_EVENT
, 0);
767 static void tgn10_set_test_pattern(
768 struct timing_generator
*tg
,
769 /* TODO: replace 'controller_dp_test_pattern' by 'test_pattern_mode'
770 * because this is not DP-specific (which is probably somewhere in DP
772 enum controller_dp_test_pattern test_pattern
,
773 enum dc_color_depth color_depth
)
775 struct dcn10_timing_generator
*tgn10
= DCN10TG_FROM_TG(tg
);
776 enum test_pattern_color_format bit_depth
;
777 enum test_pattern_dyn_range dyn_range
;
778 enum test_pattern_mode mode
;
779 uint32_t pattern_mask
;
780 uint32_t pattern_data
;
781 /* color ramp generator mixes 16-bits color */
782 uint32_t src_bpc
= 16;
786 /* RGB values of the color bars.
787 * Produce two RGB colors: RGB0 - white (all Fs)
788 * and RGB1 - black (all 0s)
789 * (three RGB components for two colors)
791 uint16_t src_color
[6] = {0xFFFF, 0xFFFF, 0xFFFF, 0x0000,
793 /* dest color (converted to the specified color format) */
794 uint16_t dst_color
[6];
797 /* translate to bit depth */
798 switch (color_depth
) {
799 case COLOR_DEPTH_666
:
800 bit_depth
= TEST_PATTERN_COLOR_FORMAT_BPC_6
;
802 case COLOR_DEPTH_888
:
803 bit_depth
= TEST_PATTERN_COLOR_FORMAT_BPC_8
;
805 case COLOR_DEPTH_101010
:
806 bit_depth
= TEST_PATTERN_COLOR_FORMAT_BPC_10
;
808 case COLOR_DEPTH_121212
:
809 bit_depth
= TEST_PATTERN_COLOR_FORMAT_BPC_12
;
812 bit_depth
= TEST_PATTERN_COLOR_FORMAT_BPC_8
;
816 switch (test_pattern
) {
817 case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES
:
818 case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA
:
820 dyn_range
= (test_pattern
==
821 CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA
?
822 TEST_PATTERN_DYN_RANGE_CEA
:
823 TEST_PATTERN_DYN_RANGE_VESA
);
824 mode
= TEST_PATTERN_MODE_COLORSQUARES_RGB
;
826 REG_UPDATE_2(OTG_TEST_PATTERN_PARAMETERS
,
827 OTG_TEST_PATTERN_VRES
, 6,
828 OTG_TEST_PATTERN_HRES
, 6);
830 REG_UPDATE_4(OTG_TEST_PATTERN_CONTROL
,
831 OTG_TEST_PATTERN_EN
, 1,
832 OTG_TEST_PATTERN_MODE
, mode
,
833 OTG_TEST_PATTERN_DYNAMIC_RANGE
, dyn_range
,
834 OTG_TEST_PATTERN_COLOR_FORMAT
, bit_depth
);
838 case CONTROLLER_DP_TEST_PATTERN_VERTICALBARS
:
839 case CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS
:
841 mode
= (test_pattern
==
842 CONTROLLER_DP_TEST_PATTERN_VERTICALBARS
?
843 TEST_PATTERN_MODE_VERTICALBARS
:
844 TEST_PATTERN_MODE_HORIZONTALBARS
);
847 case TEST_PATTERN_COLOR_FORMAT_BPC_6
:
850 case TEST_PATTERN_COLOR_FORMAT_BPC_8
:
853 case TEST_PATTERN_COLOR_FORMAT_BPC_10
:
861 /* adjust color to the required colorFormat */
862 for (index
= 0; index
< 6; index
++) {
863 /* dst = 2^dstBpc * src / 2^srcBpc = src >>
867 src_color
[index
] >> (src_bpc
- dst_bpc
);
868 /* CRTC_TEST_PATTERN_DATA has 16 bits,
869 * lowest 6 are hardwired to ZERO
870 * color bits should be left aligned aligned to MSB
871 * XXXXXXXXXX000000 for 10 bit,
872 * XXXXXXXX00000000 for 8 bit and XXXXXX0000000000 for 6
874 dst_color
[index
] <<= (16 - dst_bpc
);
877 REG_WRITE(OTG_TEST_PATTERN_PARAMETERS
, 0);
879 /* We have to write the mask before data, similar to pipeline.
880 * For example, for 8 bpc, if we want RGB0 to be magenta,
881 * and RGB1 to be cyan,
882 * we need to make 7 writes:
884 * 000001 00000000 00000000 set mask to R0
885 * 000010 11111111 00000000 R0 255, 0xFF00, set mask to G0
886 * 000100 00000000 00000000 G0 0, 0x0000, set mask to B0
887 * 001000 11111111 00000000 B0 255, 0xFF00, set mask to R1
888 * 010000 00000000 00000000 R1 0, 0x0000, set mask to G1
889 * 100000 11111111 00000000 G1 255, 0xFF00, set mask to B1
890 * 100000 11111111 00000000 B1 255, 0xFF00
892 * we will make a loop of 6 in which we prepare the mask,
893 * then write, then prepare the color for next write.
894 * first iteration will write mask only,
895 * but each next iteration color prepared in
896 * previous iteration will be written within new mask,
897 * the last component will written separately,
898 * mask is not changing between 6th and 7th write
899 * and color will be prepared by last iteration
902 /* write color, color values mask in CRTC_TEST_PATTERN_MASK
903 * is B1, G1, R1, B0, G0, R0
906 for (index
= 0; index
< 6; index
++) {
907 /* prepare color mask, first write PATTERN_DATA
908 * will have all zeros
910 pattern_mask
= (1 << index
);
912 /* write color component */
913 REG_SET_2(OTG_TEST_PATTERN_COLOR
, 0,
914 OTG_TEST_PATTERN_MASK
, pattern_mask
,
915 OTG_TEST_PATTERN_DATA
, pattern_data
);
917 /* prepare next color component,
918 * will be written in the next iteration
920 pattern_data
= dst_color
[index
];
922 /* write last color component,
923 * it's been already prepared in the loop
925 REG_SET_2(OTG_TEST_PATTERN_COLOR
, 0,
926 OTG_TEST_PATTERN_MASK
, pattern_mask
,
927 OTG_TEST_PATTERN_DATA
, pattern_data
);
929 /* enable test pattern */
930 REG_UPDATE_4(OTG_TEST_PATTERN_CONTROL
,
931 OTG_TEST_PATTERN_EN
, 1,
932 OTG_TEST_PATTERN_MODE
, mode
,
933 OTG_TEST_PATTERN_DYNAMIC_RANGE
, 0,
934 OTG_TEST_PATTERN_COLOR_FORMAT
, bit_depth
);
938 case CONTROLLER_DP_TEST_PATTERN_COLORRAMP
:
941 TEST_PATTERN_COLOR_FORMAT_BPC_10
?
942 TEST_PATTERN_MODE_DUALRAMP_RGB
:
943 TEST_PATTERN_MODE_SINGLERAMP_RGB
);
946 case TEST_PATTERN_COLOR_FORMAT_BPC_6
:
949 case TEST_PATTERN_COLOR_FORMAT_BPC_8
:
952 case TEST_PATTERN_COLOR_FORMAT_BPC_10
:
960 /* increment for the first ramp for one color gradation
961 * 1 gradation for 6-bit color is 2^10
962 * gradations in 16-bit color
964 inc_base
= (src_bpc
- dst_bpc
);
967 case TEST_PATTERN_COLOR_FORMAT_BPC_6
:
969 REG_UPDATE_5(OTG_TEST_PATTERN_PARAMETERS
,
970 OTG_TEST_PATTERN_INC0
, inc_base
,
971 OTG_TEST_PATTERN_INC1
, 0,
972 OTG_TEST_PATTERN_HRES
, 6,
973 OTG_TEST_PATTERN_VRES
, 6,
974 OTG_TEST_PATTERN_RAMP0_OFFSET
, 0);
977 case TEST_PATTERN_COLOR_FORMAT_BPC_8
:
979 REG_UPDATE_5(OTG_TEST_PATTERN_PARAMETERS
,
980 OTG_TEST_PATTERN_INC0
, inc_base
,
981 OTG_TEST_PATTERN_INC1
, 0,
982 OTG_TEST_PATTERN_HRES
, 8,
983 OTG_TEST_PATTERN_VRES
, 6,
984 OTG_TEST_PATTERN_RAMP0_OFFSET
, 0);
987 case TEST_PATTERN_COLOR_FORMAT_BPC_10
:
989 REG_UPDATE_5(OTG_TEST_PATTERN_PARAMETERS
,
990 OTG_TEST_PATTERN_INC0
, inc_base
,
991 OTG_TEST_PATTERN_INC1
, inc_base
+ 2,
992 OTG_TEST_PATTERN_HRES
, 8,
993 OTG_TEST_PATTERN_VRES
, 5,
994 OTG_TEST_PATTERN_RAMP0_OFFSET
, 384 << 6);
1001 REG_WRITE(OTG_TEST_PATTERN_COLOR
, 0);
1003 /* enable test pattern */
1004 REG_WRITE(OTG_TEST_PATTERN_CONTROL
, 0);
1006 REG_SET_4(OTG_TEST_PATTERN_CONTROL
, 0,
1007 OTG_TEST_PATTERN_EN
, 1,
1008 OTG_TEST_PATTERN_MODE
, mode
,
1009 OTG_TEST_PATTERN_DYNAMIC_RANGE
, 0,
1010 OTG_TEST_PATTERN_COLOR_FORMAT
, bit_depth
);
1013 case CONTROLLER_DP_TEST_PATTERN_VIDEOMODE
:
1015 REG_WRITE(OTG_TEST_PATTERN_CONTROL
, 0);
1016 REG_WRITE(OTG_TEST_PATTERN_COLOR
, 0);
1017 REG_WRITE(OTG_TEST_PATTERN_PARAMETERS
, 0);
1026 static void tgn10_get_crtc_scanoutpos(
1027 struct timing_generator
*tg
,
1028 uint32_t *v_blank_start
,
1029 uint32_t *v_blank_end
,
1030 uint32_t *h_position
,
1031 uint32_t *v_position
)
1033 struct dcn10_timing_generator
*tgn10
= DCN10TG_FROM_TG(tg
);
1034 struct crtc_position position
;
1036 REG_GET_2(OTG_V_BLANK_START_END
,
1037 OTG_V_BLANK_START
, v_blank_start
,
1038 OTG_V_BLANK_END
, v_blank_end
);
1040 tgn10_get_position(tg
, &position
);
1042 *h_position
= position
.horizontal_count
;
1043 *v_position
= position
.vertical_count
;
1048 static void tgn10_enable_stereo(struct timing_generator
*tg
,
1049 const struct dc_crtc_timing
*timing
, struct crtc_stereo_flags
*flags
)
1051 struct dcn10_timing_generator
*tgn10
= DCN10TG_FROM_TG(tg
);
1053 uint32_t active_width
= timing
->h_addressable
;
1054 uint32_t space1_size
= timing
->v_total
- timing
->v_addressable
;
1058 stereo_en
= flags
->FRAME_PACKED
== 0 ? 1 : 0;
1060 if (flags
->PROGRAM_STEREO
)
1061 REG_UPDATE_3(OTG_STEREO_CONTROL
,
1062 OTG_STEREO_EN
, stereo_en
,
1063 OTG_STEREO_SYNC_OUTPUT_LINE_NUM
, 0,
1064 OTG_STEREO_SYNC_OUTPUT_POLARITY
, 0);
1066 if (flags
->PROGRAM_POLARITY
)
1067 REG_UPDATE(OTG_STEREO_CONTROL
,
1068 OTG_STEREO_EYE_FLAG_POLARITY
,
1069 flags
->RIGHT_EYE_POLARITY
== 0 ? 0 : 1);
1071 if (flags
->DISABLE_STEREO_DP_SYNC
)
1072 REG_UPDATE(OTG_STEREO_CONTROL
,
1073 OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP
, 1);
1075 if (flags
->PROGRAM_STEREO
)
1076 REG_UPDATE_3(OTG_3D_STRUCTURE_CONTROL
,
1077 OTG_3D_STRUCTURE_EN
, flags
->FRAME_PACKED
,
1078 OTG_3D_STRUCTURE_V_UPDATE_MODE
, flags
->FRAME_PACKED
,
1079 OTG_3D_STRUCTURE_STEREO_SEL_OVR
, flags
->FRAME_PACKED
);
1083 REG_UPDATE(OPPBUF_CONTROL
,
1084 OPPBUF_ACTIVE_WIDTH
, active_width
);
1086 REG_UPDATE(OPPBUF_3D_PARAMETERS_0
,
1087 OPPBUF_3D_VACT_SPACE1_SIZE
, space1_size
);
1090 static void tgn10_program_stereo(struct timing_generator
*tg
,
1091 const struct dc_crtc_timing
*timing
, struct crtc_stereo_flags
*flags
)
1093 if (flags
->PROGRAM_STEREO
)
1094 tgn10_enable_stereo(tg
, timing
, flags
);
1096 tgn10_disable_stereo(tg
);
1100 static bool tgn10_is_stereo_left_eye(struct timing_generator
*tg
)
1103 uint32_t left_eye
= 0;
1104 struct dcn10_timing_generator
*tgn10
= DCN10TG_FROM_TG(tg
);
1106 REG_GET(OTG_STEREO_STATUS
,
1107 OTG_STEREO_CURRENT_EYE
, &left_eye
);
1116 void tgn10_read_otg_state(struct dcn10_timing_generator
*tgn10
,
1117 struct dcn_otg_state
*s
)
1119 REG_GET(OTG_CONTROL
,
1120 OTG_MASTER_EN
, &s
->otg_enabled
);
1122 REG_GET_2(OTG_V_BLANK_START_END
,
1123 OTG_V_BLANK_START
, &s
->v_blank_start
,
1124 OTG_V_BLANK_END
, &s
->v_blank_end
);
1126 REG_GET(OTG_V_SYNC_A_CNTL
,
1127 OTG_V_SYNC_A_POL
, &s
->v_sync_a_pol
);
1129 REG_GET(OTG_V_TOTAL
,
1130 OTG_V_TOTAL
, &s
->v_total
);
1132 REG_GET(OTG_V_TOTAL_MAX
,
1133 OTG_V_TOTAL_MAX
, &s
->v_total_max
);
1135 REG_GET(OTG_V_TOTAL_MIN
,
1136 OTG_V_TOTAL_MIN
, &s
->v_total_min
);
1138 REG_GET_2(OTG_V_SYNC_A
,
1139 OTG_V_SYNC_A_START
, &s
->v_sync_a_start
,
1140 OTG_V_SYNC_A_END
, &s
->v_sync_a_end
);
1142 REG_GET_2(OTG_H_BLANK_START_END
,
1143 OTG_H_BLANK_START
, &s
->h_blank_start
,
1144 OTG_H_BLANK_END
, &s
->h_blank_end
);
1146 REG_GET_2(OTG_H_SYNC_A
,
1147 OTG_H_SYNC_A_START
, &s
->h_sync_a_start
,
1148 OTG_H_SYNC_A_END
, &s
->h_sync_a_end
);
1150 REG_GET(OTG_H_SYNC_A_CNTL
,
1151 OTG_H_SYNC_A_POL
, &s
->h_sync_a_pol
);
1153 REG_GET(OTG_H_TOTAL
,
1154 OTG_H_TOTAL
, &s
->h_total
);
1156 REG_GET(OPTC_INPUT_GLOBAL_CONTROL
,
1157 OPTC_UNDERFLOW_OCCURRED_STATUS
, &s
->underflow_occurred_status
);
1161 static const struct timing_generator_funcs dcn10_tg_funcs
= {
1162 .validate_timing
= tgn10_validate_timing
,
1163 .program_timing
= tgn10_program_timing
,
1164 .program_global_sync
= tgn10_program_global_sync
,
1165 .enable_crtc
= tgn10_enable_crtc
,
1166 .disable_crtc
= tgn10_disable_crtc
,
1167 /* used by enable_timing_synchronization. Not need for FPGA */
1168 .is_counter_moving
= tgn10_is_counter_moving
,
1169 .get_position
= tgn10_get_position
,
1170 .get_frame_count
= tgn10_get_vblank_counter
,
1171 .get_scanoutpos
= tgn10_get_crtc_scanoutpos
,
1172 .set_early_control
= tgn10_set_early_control
,
1173 /* used by enable_timing_synchronization. Not need for FPGA */
1174 .wait_for_state
= tgn10_wait_for_state
,
1175 .set_blank
= tgn10_set_blank
,
1176 .is_blanked
= tgn10_is_blanked
,
1177 .set_blank_color
= tgn10_program_blank_color
,
1178 .did_triggered_reset_occur
= tgn10_did_triggered_reset_occur
,
1179 .enable_reset_trigger
= tgn10_enable_reset_trigger
,
1180 .disable_reset_trigger
= tgn10_disable_reset_trigger
,
1182 .unlock
= tgn10_unlock
,
1183 .enable_optc_clock
= tgn10_enable_optc_clock
,
1184 .set_drr
= tgn10_set_drr
,
1185 .set_static_screen_control
= tgn10_set_static_screen_control
,
1186 .set_test_pattern
= tgn10_set_test_pattern
,
1187 .program_stereo
= tgn10_program_stereo
,
1188 .is_stereo_left_eye
= tgn10_is_stereo_left_eye
1191 void dcn10_timing_generator_init(struct dcn10_timing_generator
*tgn10
)
1193 tgn10
->base
.funcs
= &dcn10_tg_funcs
;
1195 tgn10
->max_h_total
= tgn10
->tg_mask
->OTG_H_TOTAL
+ 1;
1196 tgn10
->max_v_total
= tgn10
->tg_mask
->OTG_V_TOTAL
+ 1;
1198 tgn10
->min_h_blank
= 32;
1199 tgn10
->min_v_blank
= 3;
1200 tgn10
->min_v_blank_interlace
= 5;
1201 tgn10
->min_h_sync_width
= 8;
1202 tgn10
->min_v_sync_width
= 1;