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 */
dce120_timing_generator_is_in_vertical_blank(struct timing_generator * tg)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
dce120_timing_generator_validate_timing(struct timing_generator * tg,const struct dc_crtc_timing * timing,enum signal_type signal)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);
dce120_tg_validate_timing(struct timing_generator * tg,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
dce120_timing_generator_enable_crtc(struct timing_generator * tg)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
dce120_timing_generator_set_early_control(struct timing_generator * tg,uint32_t early_cntl)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
dce120_timing_generator_get_vblank_counter(struct timing_generator * tg)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
dce120_timing_generator_get_crtc_position(struct timing_generator * tg,struct crtc_position * position)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
dce120_timing_generator_wait_for_vblank(struct timing_generator * tg)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
dce120_timing_generator_wait_for_vactive(struct timing_generator * tg)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
dce120_timing_generator_setup_global_swap_lock(struct timing_generator * tg,const struct dcp_gsl_params * gsl_params)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
dce120_timing_generator_tear_down_global_swap_lock(struct timing_generator * tg)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
dce120_timing_generator_enable_reset_trigger(struct timing_generator * tg,int source)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
dce120_timing_generator_disable_reset_trigger(struct timing_generator * tg)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
dce120_timing_generator_did_triggered_reset_occur(struct timing_generator * tg)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
dce120_timing_generator_disable_vga(struct timing_generator * tg)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
dce120_timing_generator_program_blanking(struct timing_generator * tg,const struct dc_crtc_timing * timing)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
dce120_timing_generator_program_blank_color(struct timing_generator * tg,const struct tg_color * black_color)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
dce120_timing_generator_set_overscan_color_black(struct timing_generator * tg,const struct tg_color * color)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
dce120_timing_generator_set_drr(struct timing_generator * tg,const struct drr_params * params)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
dce120_timing_generator_get_crtc_scanoutpos(struct timing_generator * tg,uint32_t * v_blank_start,uint32_t * v_blank_end,uint32_t * h_position,uint32_t * v_position)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
dce120_timing_generator_enable_advanced_request(struct timing_generator * tg,bool enable,const struct dc_crtc_timing * timing)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
dce120_tg_program_blank_color(struct timing_generator * tg,const struct tg_color * black_color)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
dce120_tg_set_overscan_color(struct timing_generator * tg,const struct tg_color * overscan_color)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
dce120_tg_program_timing(struct timing_generator * tg,const struct dc_crtc_timing * timing,bool use_vbios)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
dce120_tg_is_blanked(struct timing_generator * tg)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
dce120_tg_set_blank(struct timing_generator * tg,bool enable_blanking)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
dce120_tg_wait_for_state(struct timing_generator * tg,enum crtc_state state)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
dce120_tg_set_colors(struct timing_generator * tg,const struct tg_color * blank_color,const struct tg_color * overscan_color)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
dce120_timing_generator_set_static_screen_control(struct timing_generator * tg,uint32_t value)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
dce120_timing_generator_set_test_pattern(struct timing_generator * tg,enum controller_dp_test_pattern test_pattern,enum dc_color_depth color_depth)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
dce120_arm_vert_intr(struct timing_generator * tg,uint8_t width)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
dce120_timing_generator_construct(struct dce110_timing_generator * tg110,struct dc_context * ctx,uint32_t instance,const struct dce110_timing_generator_offsets * offsets)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