0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 #include "dm_services.h"
0027
0028 #include "dce/dce_12_0_offset.h"
0029 #include "dce/dce_12_0_sh_mask.h"
0030 #include "soc15_hw_ip.h"
0031 #include "vega10_ip_offset.h"
0032
0033 #include "dc_types.h"
0034 #include "dc_bios_types.h"
0035
0036 #include "include/grph_object_id.h"
0037 #include "include/logger_interface.h"
0038 #include "dce120_timing_generator.h"
0039
0040 #include "timing_generator.h"
0041
0042 #define CRTC_REG_UPDATE_N(reg_name, n, ...) \
0043 generic_reg_update_soc15(tg110->base.ctx, tg110->offsets.crtc, reg_name, n, __VA_ARGS__)
0044
0045 #define CRTC_REG_SET_N(reg_name, n, ...) \
0046 generic_reg_set_soc15(tg110->base.ctx, tg110->offsets.crtc, reg_name, n, __VA_ARGS__)
0047
0048 #define CRTC_REG_UPDATE(reg, field, val) \
0049 CRTC_REG_UPDATE_N(reg, 1, FD(reg##__##field), val)
0050
0051 #define CRTC_REG_UPDATE_2(reg, field1, val1, field2, val2) \
0052 CRTC_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2)
0053
0054 #define CRTC_REG_UPDATE_3(reg, field1, val1, field2, val2, field3, val3) \
0055 CRTC_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3)
0056
0057 #define CRTC_REG_UPDATE_4(reg, field1, val1, field2, val2, field3, val3, field4, val4) \
0058 CRTC_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3, FD(reg##__##field4), val4)
0059
0060 #define CRTC_REG_UPDATE_5(reg, field1, val1, field2, val2, field3, val3, field4, val4, field5, val5) \
0061 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)
0062
0063 #define CRTC_REG_SET(reg, field, val) \
0064 CRTC_REG_SET_N(reg, 1, FD(reg##__##field), val)
0065
0066 #define CRTC_REG_SET_2(reg, field1, val1, field2, val2) \
0067 CRTC_REG_SET_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2)
0068
0069 #define CRTC_REG_SET_3(reg, field1, val1, field2, val2, field3, val3) \
0070 CRTC_REG_SET_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3)
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085 static bool dce120_timing_generator_is_in_vertical_blank(
0086 struct timing_generator *tg)
0087 {
0088 uint32_t field = 0;
0089 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0090 uint32_t value = dm_read_reg_soc15(
0091 tg->ctx,
0092 mmCRTC0_CRTC_STATUS,
0093 tg110->offsets.crtc);
0094
0095 field = get_reg_field_value(value, CRTC0_CRTC_STATUS, CRTC_V_BLANK);
0096 return field == 1;
0097 }
0098
0099
0100
0101 static bool dce120_timing_generator_validate_timing(
0102 struct timing_generator *tg,
0103 const struct dc_crtc_timing *timing,
0104 enum signal_type signal)
0105 {
0106 uint32_t interlace_factor = timing->flags.INTERLACE ? 2 : 1;
0107 uint32_t v_blank =
0108 (timing->v_total - timing->v_addressable -
0109 timing->v_border_top - timing->v_border_bottom) *
0110 interlace_factor;
0111 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0112
0113 if (!dce110_timing_generator_validate_timing(
0114 tg,
0115 timing,
0116 signal))
0117 return false;
0118
0119
0120 if (v_blank < tg110->min_v_blank ||
0121 timing->h_sync_width < tg110->min_h_sync_width ||
0122 timing->v_sync_width < tg110->min_v_sync_width)
0123 return false;
0124
0125 return true;
0126 }
0127
0128 static bool dce120_tg_validate_timing(struct timing_generator *tg,
0129 const struct dc_crtc_timing *timing)
0130 {
0131 return dce120_timing_generator_validate_timing(tg, timing, SIGNAL_TYPE_NONE);
0132 }
0133
0134
0135
0136 static bool dce120_timing_generator_enable_crtc(struct timing_generator *tg)
0137 {
0138 enum bp_result result;
0139 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0140
0141
0142
0143
0144 CRTC_REG_UPDATE(CRTC0_CRTC_MASTER_UPDATE_MODE,
0145 MASTER_UPDATE_MODE, 0);
0146
0147 CRTC_REG_UPDATE(CRTC0_CRTC_MASTER_UPDATE_LOCK,
0148 UNDERFLOW_UPDATE_LOCK, 0);
0149
0150
0151 result = tg->bp->funcs->enable_crtc(tg->bp, tg110->controller_id, true);
0152
0153 return result == BP_RESULT_OK;
0154 }
0155
0156 static void dce120_timing_generator_set_early_control(
0157 struct timing_generator *tg,
0158 uint32_t early_cntl)
0159 {
0160 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0161
0162 CRTC_REG_UPDATE(CRTC0_CRTC_CONTROL,
0163 CRTC_HBLANK_EARLY_CONTROL, early_cntl);
0164 }
0165
0166
0167
0168
0169 static uint32_t dce120_timing_generator_get_vblank_counter(
0170 struct timing_generator *tg)
0171 {
0172 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0173 uint32_t value = dm_read_reg_soc15(
0174 tg->ctx,
0175 mmCRTC0_CRTC_STATUS_FRAME_COUNT,
0176 tg110->offsets.crtc);
0177 uint32_t field = get_reg_field_value(
0178 value, CRTC0_CRTC_STATUS_FRAME_COUNT, CRTC_FRAME_COUNT);
0179
0180 return field;
0181 }
0182
0183
0184 static void dce120_timing_generator_get_crtc_position(
0185 struct timing_generator *tg,
0186 struct crtc_position *position)
0187 {
0188 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0189 uint32_t value = dm_read_reg_soc15(
0190 tg->ctx,
0191 mmCRTC0_CRTC_STATUS_POSITION,
0192 tg110->offsets.crtc);
0193
0194 position->horizontal_count = get_reg_field_value(value,
0195 CRTC0_CRTC_STATUS_POSITION, CRTC_HORZ_COUNT);
0196
0197 position->vertical_count = get_reg_field_value(value,
0198 CRTC0_CRTC_STATUS_POSITION, CRTC_VERT_COUNT);
0199
0200 value = dm_read_reg_soc15(
0201 tg->ctx,
0202 mmCRTC0_CRTC_NOM_VERT_POSITION,
0203 tg110->offsets.crtc);
0204
0205 position->nominal_vcount = get_reg_field_value(value,
0206 CRTC0_CRTC_NOM_VERT_POSITION, CRTC_VERT_COUNT_NOM);
0207 }
0208
0209
0210 static void dce120_timing_generator_wait_for_vblank(struct timing_generator *tg)
0211 {
0212
0213
0214
0215
0216 while (dce120_timing_generator_is_in_vertical_blank(tg)) {
0217 if (!tg->funcs->is_counter_moving(tg)) {
0218
0219 break;
0220 }
0221 }
0222
0223 while (!dce120_timing_generator_is_in_vertical_blank(tg)) {
0224 if (!tg->funcs->is_counter_moving(tg)) {
0225
0226 break;
0227 }
0228 }
0229 }
0230
0231
0232 static void dce120_timing_generator_wait_for_vactive(struct timing_generator *tg)
0233 {
0234 while (dce120_timing_generator_is_in_vertical_blank(tg)) {
0235 if (!tg->funcs->is_counter_moving(tg)) {
0236
0237 break;
0238 }
0239 }
0240 }
0241
0242
0243
0244
0245 static void dce120_timing_generator_setup_global_swap_lock(
0246 struct timing_generator *tg,
0247 const struct dcp_gsl_params *gsl_params)
0248 {
0249 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0250 uint32_t value_crtc_vtotal =
0251 dm_read_reg_soc15(tg->ctx,
0252 mmCRTC0_CRTC_V_TOTAL,
0253 tg110->offsets.crtc);
0254
0255 uint32_t check_point =
0256 get_reg_field_value(value_crtc_vtotal,
0257 CRTC0_CRTC_V_TOTAL,
0258 CRTC_V_TOTAL);
0259
0260
0261 dm_write_reg_soc15(tg->ctx, mmCRTC0_CRTC_GSL_WINDOW, tg110->offsets.crtc, 0);
0262
0263 CRTC_REG_UPDATE_N(DCP0_DCP_GSL_CONTROL, 6,
0264
0265 FD(DCP0_DCP_GSL_CONTROL__DCP_GSL0_EN), 1,
0266 FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_MASTER_EN), gsl_params->gsl_master == tg->inst,
0267 FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_FORCE_DELAY), HFLIP_READY_DELAY,
0268
0269
0270 FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_CHECK_DELAY), HFLIP_CHECK_DELAY,
0271
0272 FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_SYNC_SOURCE), 0,
0273 FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_DELAY_SURFACE_UPDATE_PENDING), 1);
0274
0275 CRTC_REG_SET_2(
0276 CRTC0_CRTC_GSL_CONTROL,
0277 CRTC_GSL_CHECK_LINE_NUM, check_point - FLIP_READY_BACK_LOOKUP,
0278 CRTC_GSL_FORCE_DELAY, VFLIP_READY_DELAY);
0279 }
0280
0281
0282 static void dce120_timing_generator_tear_down_global_swap_lock(
0283 struct timing_generator *tg)
0284 {
0285 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0286
0287
0288 CRTC_REG_SET_N(DCP0_DCP_GSL_CONTROL, 6,
0289 FD(DCP0_DCP_GSL_CONTROL__DCP_GSL0_EN), 0,
0290 FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_MASTER_EN), 0,
0291 FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_FORCE_DELAY), HFLIP_READY_DELAY,
0292 FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_CHECK_DELAY), HFLIP_CHECK_DELAY,
0293
0294 FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_SYNC_SOURCE), 0,
0295 FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_DELAY_SURFACE_UPDATE_PENDING), 0);
0296
0297 CRTC_REG_SET_2(CRTC0_CRTC_GSL_CONTROL,
0298 CRTC_GSL_CHECK_LINE_NUM, 0,
0299 CRTC_GSL_FORCE_DELAY, 0x2);
0300 }
0301
0302
0303 static void dce120_timing_generator_enable_reset_trigger(
0304 struct timing_generator *tg,
0305 int source)
0306 {
0307 enum trigger_source_select trig_src_select = TRIGGER_SOURCE_SELECT_LOGIC_ZERO;
0308 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0309 uint32_t rising_edge = 0;
0310 uint32_t falling_edge = 0;
0311
0312 uint32_t pol_value = dm_read_reg_soc15(
0313 tg->ctx,
0314 mmCRTC0_CRTC_V_SYNC_A_CNTL,
0315 tg110->offsets.crtc);
0316
0317
0318
0319 if (get_reg_field_value(pol_value,
0320 CRTC0_CRTC_V_SYNC_A_CNTL,
0321 CRTC_V_SYNC_A_POL) == 0) {
0322 rising_edge = 1;
0323 } else {
0324 falling_edge = 1;
0325 }
0326
0327
0328 trig_src_select = TRIGGER_SOURCE_SELECT_GSL_GROUP0;
0329
0330 CRTC_REG_UPDATE_N(CRTC0_CRTC_TRIGB_CNTL, 7,
0331 FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_SOURCE_SELECT), trig_src_select,
0332 FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_POLARITY_SELECT), TRIGGER_POLARITY_SELECT_LOGIC_ZERO,
0333 FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_RISING_EDGE_DETECT_CNTL), rising_edge,
0334 FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_FALLING_EDGE_DETECT_CNTL), falling_edge,
0335
0336 FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_FREQUENCY_SELECT), 0,
0337
0338 FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_DELAY), 0,
0339
0340 FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_CLEAR), 1);
0341
0342 CRTC_REG_UPDATE_3(
0343 CRTC0_CRTC_FORCE_COUNT_NOW_CNTL,
0344 CRTC_FORCE_COUNT_NOW_MODE, 2,
0345 CRTC_FORCE_COUNT_NOW_TRIG_SEL, 1,
0346 CRTC_FORCE_COUNT_NOW_CLEAR, 1);
0347 }
0348
0349
0350 static void dce120_timing_generator_disable_reset_trigger(
0351 struct timing_generator *tg)
0352 {
0353 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0354
0355 CRTC_REG_UPDATE_2(
0356 CRTC0_CRTC_FORCE_COUNT_NOW_CNTL,
0357 CRTC_FORCE_COUNT_NOW_MODE, 0,
0358 CRTC_FORCE_COUNT_NOW_CLEAR, 1);
0359
0360 CRTC_REG_UPDATE_3(
0361 CRTC0_CRTC_TRIGB_CNTL,
0362 CRTC_TRIGB_SOURCE_SELECT, TRIGGER_SOURCE_SELECT_LOGIC_ZERO,
0363 CRTC_TRIGB_POLARITY_SELECT, TRIGGER_POLARITY_SELECT_LOGIC_ZERO,
0364
0365 CRTC_TRIGB_CLEAR, 1);
0366
0367 }
0368
0369
0370 static bool dce120_timing_generator_did_triggered_reset_occur(
0371 struct timing_generator *tg)
0372 {
0373 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0374 uint32_t value = dm_read_reg_soc15(
0375 tg->ctx,
0376 mmCRTC0_CRTC_FORCE_COUNT_NOW_CNTL,
0377 tg110->offsets.crtc);
0378
0379 return get_reg_field_value(value,
0380 CRTC0_CRTC_FORCE_COUNT_NOW_CNTL,
0381 CRTC_FORCE_COUNT_NOW_OCCURRED) != 0;
0382 }
0383
0384
0385
0386
0387 static void dce120_timing_generator_disable_vga(struct timing_generator *tg)
0388 {
0389 uint32_t offset = 0;
0390 uint32_t value = 0;
0391 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0392
0393 switch (tg110->controller_id) {
0394 case CONTROLLER_ID_D0:
0395 offset = 0;
0396 break;
0397 case CONTROLLER_ID_D1:
0398 offset = mmD2VGA_CONTROL - mmD1VGA_CONTROL;
0399 break;
0400 case CONTROLLER_ID_D2:
0401 offset = mmD3VGA_CONTROL - mmD1VGA_CONTROL;
0402 break;
0403 case CONTROLLER_ID_D3:
0404 offset = mmD4VGA_CONTROL - mmD1VGA_CONTROL;
0405 break;
0406 case CONTROLLER_ID_D4:
0407 offset = mmD5VGA_CONTROL - mmD1VGA_CONTROL;
0408 break;
0409 case CONTROLLER_ID_D5:
0410 offset = mmD6VGA_CONTROL - mmD1VGA_CONTROL;
0411 break;
0412 default:
0413 break;
0414 }
0415
0416 value = dm_read_reg_soc15(tg->ctx, mmD1VGA_CONTROL, offset);
0417
0418 set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_MODE_ENABLE);
0419 set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_TIMING_SELECT);
0420 set_reg_field_value(
0421 value, 0, D1VGA_CONTROL, D1VGA_SYNC_POLARITY_SELECT);
0422 set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_OVERSCAN_COLOR_EN);
0423
0424 dm_write_reg_soc15(tg->ctx, mmD1VGA_CONTROL, offset, value);
0425 }
0426
0427
0428 static void dce120_timing_generator_program_blanking(
0429 struct timing_generator *tg,
0430 const struct dc_crtc_timing *timing)
0431 {
0432 uint32_t tmp1 = 0;
0433 uint32_t tmp2 = 0;
0434 uint32_t vsync_offset = timing->v_border_bottom +
0435 timing->v_front_porch;
0436 uint32_t v_sync_start = timing->v_addressable + vsync_offset;
0437
0438 uint32_t hsync_offset = timing->h_border_right +
0439 timing->h_front_porch;
0440 uint32_t h_sync_start = timing->h_addressable + hsync_offset;
0441 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0442
0443 CRTC_REG_UPDATE(
0444 CRTC0_CRTC_H_TOTAL,
0445 CRTC_H_TOTAL,
0446 timing->h_total - 1);
0447
0448 CRTC_REG_UPDATE(
0449 CRTC0_CRTC_V_TOTAL,
0450 CRTC_V_TOTAL,
0451 timing->v_total - 1);
0452
0453
0454
0455
0456 CRTC_REG_UPDATE(
0457 CRTC0_CRTC_V_TOTAL_MAX,
0458 CRTC_V_TOTAL_MAX,
0459 timing->v_total - 1);
0460
0461 CRTC_REG_UPDATE(
0462 CRTC0_CRTC_V_TOTAL_MIN,
0463 CRTC_V_TOTAL_MIN,
0464 timing->v_total - 1);
0465
0466 tmp1 = timing->h_total -
0467 (h_sync_start + timing->h_border_left);
0468 tmp2 = tmp1 + timing->h_addressable +
0469 timing->h_border_left + timing->h_border_right;
0470
0471 CRTC_REG_UPDATE_2(
0472 CRTC0_CRTC_H_BLANK_START_END,
0473 CRTC_H_BLANK_END, tmp1,
0474 CRTC_H_BLANK_START, tmp2);
0475
0476 tmp1 = timing->v_total - (v_sync_start + timing->v_border_top);
0477 tmp2 = tmp1 + timing->v_addressable + timing->v_border_top +
0478 timing->v_border_bottom;
0479
0480 CRTC_REG_UPDATE_2(
0481 CRTC0_CRTC_V_BLANK_START_END,
0482 CRTC_V_BLANK_END, tmp1,
0483 CRTC_V_BLANK_START, tmp2);
0484 }
0485
0486
0487
0488 static void dce120_timing_generator_program_blank_color(
0489 struct timing_generator *tg,
0490 const struct tg_color *black_color)
0491 {
0492 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0493
0494 CRTC_REG_UPDATE_3(
0495 CRTC0_CRTC_BLACK_COLOR,
0496 CRTC_BLACK_COLOR_B_CB, black_color->color_b_cb,
0497 CRTC_BLACK_COLOR_G_Y, black_color->color_g_y,
0498 CRTC_BLACK_COLOR_R_CR, black_color->color_r_cr);
0499 }
0500
0501 static void dce120_timing_generator_set_overscan_color_black(
0502 struct timing_generator *tg,
0503 const struct tg_color *color)
0504 {
0505 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0506 uint32_t value = 0;
0507 CRTC_REG_SET_3(
0508 CRTC0_CRTC_OVERSCAN_COLOR,
0509 CRTC_OVERSCAN_COLOR_BLUE, color->color_b_cb,
0510 CRTC_OVERSCAN_COLOR_GREEN, color->color_g_y,
0511 CRTC_OVERSCAN_COLOR_RED, color->color_r_cr);
0512
0513 value = dm_read_reg_soc15(
0514 tg->ctx,
0515 mmCRTC0_CRTC_OVERSCAN_COLOR,
0516 tg110->offsets.crtc);
0517
0518 dm_write_reg_soc15(
0519 tg->ctx,
0520 mmCRTC0_CRTC_BLACK_COLOR,
0521 tg110->offsets.crtc,
0522 value);
0523
0524
0525
0526
0527
0528 dm_write_reg_soc15(
0529 tg->ctx,
0530 mmCRTC0_CRTC_BLANK_DATA_COLOR,
0531 tg110->offsets.crtc,
0532 value);
0533
0534
0535
0536
0537
0538
0539
0540
0541 }
0542
0543 static void dce120_timing_generator_set_drr(
0544 struct timing_generator *tg,
0545 const struct drr_params *params)
0546 {
0547
0548 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0549
0550 if (params != NULL &&
0551 params->vertical_total_max > 0 &&
0552 params->vertical_total_min > 0) {
0553
0554 CRTC_REG_UPDATE(
0555 CRTC0_CRTC_V_TOTAL_MIN,
0556 CRTC_V_TOTAL_MIN, params->vertical_total_min - 1);
0557 CRTC_REG_UPDATE(
0558 CRTC0_CRTC_V_TOTAL_MAX,
0559 CRTC_V_TOTAL_MAX, params->vertical_total_max - 1);
0560 CRTC_REG_SET_N(CRTC0_CRTC_V_TOTAL_CONTROL, 6,
0561 FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MIN_SEL), 1,
0562 FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MAX_SEL), 1,
0563 FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_ON_EVENT), 0,
0564 FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_TO_MASTER_VSYNC), 0,
0565 FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_SET_V_TOTAL_MIN_MASK_EN), 0,
0566 FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_SET_V_TOTAL_MIN_MASK), 0);
0567 CRTC_REG_UPDATE(
0568 CRTC0_CRTC_STATIC_SCREEN_CONTROL,
0569 CRTC_STATIC_SCREEN_EVENT_MASK,
0570 0x180);
0571
0572 } else {
0573 CRTC_REG_SET_N(CRTC0_CRTC_V_TOTAL_CONTROL, 5,
0574 FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MIN_SEL), 0,
0575 FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MAX_SEL), 0,
0576 FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_ON_EVENT), 0,
0577 FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_TO_MASTER_VSYNC), 0,
0578 FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_SET_V_TOTAL_MIN_MASK), 0);
0579 CRTC_REG_UPDATE(
0580 CRTC0_CRTC_V_TOTAL_MIN,
0581 CRTC_V_TOTAL_MIN, 0);
0582 CRTC_REG_UPDATE(
0583 CRTC0_CRTC_V_TOTAL_MAX,
0584 CRTC_V_TOTAL_MAX, 0);
0585 CRTC_REG_UPDATE(
0586 CRTC0_CRTC_STATIC_SCREEN_CONTROL,
0587 CRTC_STATIC_SCREEN_EVENT_MASK,
0588 0);
0589 }
0590 }
0591
0592 static void dce120_timing_generator_get_crtc_scanoutpos(
0593 struct timing_generator *tg,
0594 uint32_t *v_blank_start,
0595 uint32_t *v_blank_end,
0596 uint32_t *h_position,
0597 uint32_t *v_position)
0598 {
0599 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0600 struct crtc_position position;
0601
0602 uint32_t v_blank_start_end = dm_read_reg_soc15(
0603 tg->ctx,
0604 mmCRTC0_CRTC_V_BLANK_START_END,
0605 tg110->offsets.crtc);
0606
0607 *v_blank_start = get_reg_field_value(v_blank_start_end,
0608 CRTC0_CRTC_V_BLANK_START_END,
0609 CRTC_V_BLANK_START);
0610 *v_blank_end = get_reg_field_value(v_blank_start_end,
0611 CRTC0_CRTC_V_BLANK_START_END,
0612 CRTC_V_BLANK_END);
0613
0614 dce120_timing_generator_get_crtc_position(
0615 tg, &position);
0616
0617 *h_position = position.horizontal_count;
0618 *v_position = position.vertical_count;
0619 }
0620
0621 static void dce120_timing_generator_enable_advanced_request(
0622 struct timing_generator *tg,
0623 bool enable,
0624 const struct dc_crtc_timing *timing)
0625 {
0626 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0627 uint32_t v_sync_width_and_b_porch =
0628 timing->v_total - timing->v_addressable -
0629 timing->v_border_bottom - timing->v_front_porch;
0630 uint32_t value = dm_read_reg_soc15(
0631 tg->ctx,
0632 mmCRTC0_CRTC_START_LINE_CONTROL,
0633 tg110->offsets.crtc);
0634
0635 set_reg_field_value(
0636 value,
0637 enable ? 0 : 1,
0638 CRTC0_CRTC_START_LINE_CONTROL,
0639 CRTC_LEGACY_REQUESTOR_EN);
0640
0641
0642
0643
0644 if (v_sync_width_and_b_porch > 10)
0645 v_sync_width_and_b_porch = 10;
0646
0647 set_reg_field_value(
0648 value,
0649 v_sync_width_and_b_porch,
0650 CRTC0_CRTC_START_LINE_CONTROL,
0651 CRTC_ADVANCED_START_LINE_POSITION);
0652
0653 dm_write_reg_soc15(tg->ctx,
0654 mmCRTC0_CRTC_START_LINE_CONTROL,
0655 tg110->offsets.crtc,
0656 value);
0657 }
0658
0659 static void dce120_tg_program_blank_color(struct timing_generator *tg,
0660 const struct tg_color *black_color)
0661 {
0662 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0663 uint32_t value = 0;
0664
0665 CRTC_REG_UPDATE_3(
0666 CRTC0_CRTC_BLACK_COLOR,
0667 CRTC_BLACK_COLOR_B_CB, black_color->color_b_cb,
0668 CRTC_BLACK_COLOR_G_Y, black_color->color_g_y,
0669 CRTC_BLACK_COLOR_R_CR, black_color->color_r_cr);
0670
0671 value = dm_read_reg_soc15(
0672 tg->ctx,
0673 mmCRTC0_CRTC_BLACK_COLOR,
0674 tg110->offsets.crtc);
0675 dm_write_reg_soc15(
0676 tg->ctx,
0677 mmCRTC0_CRTC_BLANK_DATA_COLOR,
0678 tg110->offsets.crtc,
0679 value);
0680 }
0681
0682 static void dce120_tg_set_overscan_color(struct timing_generator *tg,
0683 const struct tg_color *overscan_color)
0684 {
0685 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0686
0687 CRTC_REG_SET_3(
0688 CRTC0_CRTC_OVERSCAN_COLOR,
0689 CRTC_OVERSCAN_COLOR_BLUE, overscan_color->color_b_cb,
0690 CRTC_OVERSCAN_COLOR_GREEN, overscan_color->color_g_y,
0691 CRTC_OVERSCAN_COLOR_RED, overscan_color->color_r_cr);
0692 }
0693
0694 static void dce120_tg_program_timing(struct timing_generator *tg,
0695 const struct dc_crtc_timing *timing,
0696 int vready_offset,
0697 int vstartup_start,
0698 int vupdate_offset,
0699 int vupdate_width,
0700 const enum signal_type signal,
0701 bool use_vbios)
0702 {
0703 if (use_vbios)
0704 dce110_timing_generator_program_timing_generator(tg, timing);
0705 else
0706 dce120_timing_generator_program_blanking(tg, timing);
0707 }
0708
0709 static bool dce120_tg_is_blanked(struct timing_generator *tg)
0710 {
0711 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0712 uint32_t value = dm_read_reg_soc15(
0713 tg->ctx,
0714 mmCRTC0_CRTC_BLANK_CONTROL,
0715 tg110->offsets.crtc);
0716
0717 if (get_reg_field_value(
0718 value,
0719 CRTC0_CRTC_BLANK_CONTROL,
0720 CRTC_BLANK_DATA_EN) == 1 &&
0721 get_reg_field_value(
0722 value,
0723 CRTC0_CRTC_BLANK_CONTROL,
0724 CRTC_CURRENT_BLANK_STATE) == 1)
0725 return true;
0726
0727 return false;
0728 }
0729
0730 static void dce120_tg_set_blank(struct timing_generator *tg,
0731 bool enable_blanking)
0732 {
0733 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0734
0735 CRTC_REG_SET(
0736 CRTC0_CRTC_DOUBLE_BUFFER_CONTROL,
0737 CRTC_BLANK_DATA_DOUBLE_BUFFER_EN, 1);
0738
0739 if (enable_blanking)
0740 CRTC_REG_SET(CRTC0_CRTC_BLANK_CONTROL, CRTC_BLANK_DATA_EN, 1);
0741 else
0742 dm_write_reg_soc15(tg->ctx, mmCRTC0_CRTC_BLANK_CONTROL,
0743 tg110->offsets.crtc, 0);
0744 }
0745
0746 bool dce120_tg_validate_timing(struct timing_generator *tg,
0747 const struct dc_crtc_timing *timing);
0748
0749 static void dce120_tg_wait_for_state(struct timing_generator *tg,
0750 enum crtc_state state)
0751 {
0752 switch (state) {
0753 case CRTC_STATE_VBLANK:
0754 dce120_timing_generator_wait_for_vblank(tg);
0755 break;
0756
0757 case CRTC_STATE_VACTIVE:
0758 dce120_timing_generator_wait_for_vactive(tg);
0759 break;
0760
0761 default:
0762 break;
0763 }
0764 }
0765
0766 static void dce120_tg_set_colors(struct timing_generator *tg,
0767 const struct tg_color *blank_color,
0768 const struct tg_color *overscan_color)
0769 {
0770 if (blank_color != NULL)
0771 dce120_tg_program_blank_color(tg, blank_color);
0772
0773 if (overscan_color != NULL)
0774 dce120_tg_set_overscan_color(tg, overscan_color);
0775 }
0776
0777 static void dce120_timing_generator_set_static_screen_control(
0778 struct timing_generator *tg,
0779 uint32_t event_triggers,
0780 uint32_t num_frames)
0781 {
0782 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0783
0784
0785 if (num_frames > 0xFF)
0786 num_frames = 0xFF;
0787
0788 CRTC_REG_UPDATE_2(CRTC0_CRTC_STATIC_SCREEN_CONTROL,
0789 CRTC_STATIC_SCREEN_EVENT_MASK, event_triggers,
0790 CRTC_STATIC_SCREEN_FRAME_COUNT, num_frames);
0791 }
0792
0793 static void dce120_timing_generator_set_test_pattern(
0794 struct timing_generator *tg,
0795
0796
0797
0798 enum controller_dp_test_pattern test_pattern,
0799 enum dc_color_depth color_depth)
0800 {
0801 struct dc_context *ctx = tg->ctx;
0802 uint32_t value;
0803 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0804 enum test_pattern_color_format bit_depth;
0805 enum test_pattern_dyn_range dyn_range;
0806 enum test_pattern_mode mode;
0807
0808 uint32_t src_bpc = 16;
0809
0810 uint32_t dst_bpc;
0811 uint32_t index;
0812
0813
0814
0815
0816
0817 uint16_t src_color[6] = {0xFFFF, 0xFFFF, 0xFFFF, 0x0000,
0818 0x0000, 0x0000};
0819
0820 uint16_t dst_color[6];
0821 uint32_t inc_base;
0822
0823
0824 switch (color_depth) {
0825 case COLOR_DEPTH_666:
0826 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_6;
0827 break;
0828 case COLOR_DEPTH_888:
0829 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
0830 break;
0831 case COLOR_DEPTH_101010:
0832 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_10;
0833 break;
0834 case COLOR_DEPTH_121212:
0835 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_12;
0836 break;
0837 default:
0838 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
0839 break;
0840 }
0841
0842 switch (test_pattern) {
0843 case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES:
0844 case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA:
0845 {
0846 dyn_range = (test_pattern ==
0847 CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA ?
0848 TEST_PATTERN_DYN_RANGE_CEA :
0849 TEST_PATTERN_DYN_RANGE_VESA);
0850 mode = TEST_PATTERN_MODE_COLORSQUARES_RGB;
0851
0852 CRTC_REG_UPDATE_2(CRTC0_CRTC_TEST_PATTERN_PARAMETERS,
0853 CRTC_TEST_PATTERN_VRES, 6,
0854 CRTC_TEST_PATTERN_HRES, 6);
0855
0856 CRTC_REG_UPDATE_4(CRTC0_CRTC_TEST_PATTERN_CONTROL,
0857 CRTC_TEST_PATTERN_EN, 1,
0858 CRTC_TEST_PATTERN_MODE, mode,
0859 CRTC_TEST_PATTERN_DYNAMIC_RANGE, dyn_range,
0860 CRTC_TEST_PATTERN_COLOR_FORMAT, bit_depth);
0861 }
0862 break;
0863
0864 case CONTROLLER_DP_TEST_PATTERN_VERTICALBARS:
0865 case CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS:
0866 {
0867 mode = (test_pattern ==
0868 CONTROLLER_DP_TEST_PATTERN_VERTICALBARS ?
0869 TEST_PATTERN_MODE_VERTICALBARS :
0870 TEST_PATTERN_MODE_HORIZONTALBARS);
0871
0872 switch (bit_depth) {
0873 case TEST_PATTERN_COLOR_FORMAT_BPC_6:
0874 dst_bpc = 6;
0875 break;
0876 case TEST_PATTERN_COLOR_FORMAT_BPC_8:
0877 dst_bpc = 8;
0878 break;
0879 case TEST_PATTERN_COLOR_FORMAT_BPC_10:
0880 dst_bpc = 10;
0881 break;
0882 default:
0883 dst_bpc = 8;
0884 break;
0885 }
0886
0887
0888 for (index = 0; index < 6; index++) {
0889
0890
0891
0892 dst_color[index] =
0893 src_color[index] >> (src_bpc - dst_bpc);
0894
0895
0896
0897
0898
0899
0900 dst_color[index] <<= (16 - dst_bpc);
0901 }
0902
0903 dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_PARAMETERS, tg110->offsets.crtc, 0);
0904
0905
0906
0907
0908
0909
0910
0911
0912
0913
0914
0915
0916
0917
0918
0919
0920
0921
0922
0923
0924
0925
0926
0927
0928
0929
0930
0931 value = 0;
0932 for (index = 0; index < 6; index++) {
0933
0934
0935
0936 set_reg_field_value(
0937 value,
0938 (1 << index),
0939 CRTC0_CRTC_TEST_PATTERN_COLOR,
0940 CRTC_TEST_PATTERN_MASK);
0941
0942 dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, value);
0943
0944
0945
0946 set_reg_field_value(
0947 value,
0948 dst_color[index],
0949 CRTC0_CRTC_TEST_PATTERN_COLOR,
0950 CRTC_TEST_PATTERN_DATA);
0951 }
0952
0953
0954
0955 dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, value);
0956
0957
0958 CRTC_REG_UPDATE_4(CRTC0_CRTC_TEST_PATTERN_CONTROL,
0959 CRTC_TEST_PATTERN_EN, 1,
0960 CRTC_TEST_PATTERN_MODE, mode,
0961 CRTC_TEST_PATTERN_DYNAMIC_RANGE, 0,
0962 CRTC_TEST_PATTERN_COLOR_FORMAT, bit_depth);
0963 }
0964 break;
0965
0966 case CONTROLLER_DP_TEST_PATTERN_COLORRAMP:
0967 {
0968 mode = (bit_depth ==
0969 TEST_PATTERN_COLOR_FORMAT_BPC_10 ?
0970 TEST_PATTERN_MODE_DUALRAMP_RGB :
0971 TEST_PATTERN_MODE_SINGLERAMP_RGB);
0972
0973 switch (bit_depth) {
0974 case TEST_PATTERN_COLOR_FORMAT_BPC_6:
0975 dst_bpc = 6;
0976 break;
0977 case TEST_PATTERN_COLOR_FORMAT_BPC_8:
0978 dst_bpc = 8;
0979 break;
0980 case TEST_PATTERN_COLOR_FORMAT_BPC_10:
0981 dst_bpc = 10;
0982 break;
0983 default:
0984 dst_bpc = 8;
0985 break;
0986 }
0987
0988
0989
0990
0991
0992 inc_base = (src_bpc - dst_bpc);
0993
0994 switch (bit_depth) {
0995 case TEST_PATTERN_COLOR_FORMAT_BPC_6:
0996 {
0997 CRTC_REG_UPDATE_5(CRTC0_CRTC_TEST_PATTERN_PARAMETERS,
0998 CRTC_TEST_PATTERN_INC0, inc_base,
0999 CRTC_TEST_PATTERN_INC1, 0,
1000 CRTC_TEST_PATTERN_HRES, 6,
1001 CRTC_TEST_PATTERN_VRES, 6,
1002 CRTC_TEST_PATTERN_RAMP0_OFFSET, 0);
1003 }
1004 break;
1005 case TEST_PATTERN_COLOR_FORMAT_BPC_8:
1006 {
1007 CRTC_REG_UPDATE_5(CRTC0_CRTC_TEST_PATTERN_PARAMETERS,
1008 CRTC_TEST_PATTERN_INC0, inc_base,
1009 CRTC_TEST_PATTERN_INC1, 0,
1010 CRTC_TEST_PATTERN_HRES, 8,
1011 CRTC_TEST_PATTERN_VRES, 6,
1012 CRTC_TEST_PATTERN_RAMP0_OFFSET, 0);
1013 }
1014 break;
1015 case TEST_PATTERN_COLOR_FORMAT_BPC_10:
1016 {
1017 CRTC_REG_UPDATE_5(CRTC0_CRTC_TEST_PATTERN_PARAMETERS,
1018 CRTC_TEST_PATTERN_INC0, inc_base,
1019 CRTC_TEST_PATTERN_INC1, inc_base + 2,
1020 CRTC_TEST_PATTERN_HRES, 8,
1021 CRTC_TEST_PATTERN_VRES, 5,
1022 CRTC_TEST_PATTERN_RAMP0_OFFSET, 384 << 6);
1023 }
1024 break;
1025 default:
1026 break;
1027 }
1028
1029 dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, 0);
1030
1031
1032 dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_CONTROL, tg110->offsets.crtc, 0);
1033
1034 CRTC_REG_UPDATE_4(CRTC0_CRTC_TEST_PATTERN_CONTROL,
1035 CRTC_TEST_PATTERN_EN, 1,
1036 CRTC_TEST_PATTERN_MODE, mode,
1037 CRTC_TEST_PATTERN_DYNAMIC_RANGE, 0,
1038 CRTC_TEST_PATTERN_COLOR_FORMAT, bit_depth);
1039 }
1040 break;
1041 case CONTROLLER_DP_TEST_PATTERN_VIDEOMODE:
1042 {
1043 value = 0;
1044 dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_CONTROL, tg110->offsets.crtc, value);
1045 dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, value);
1046 dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_PARAMETERS, tg110->offsets.crtc, value);
1047 }
1048 break;
1049 default:
1050 break;
1051 }
1052 }
1053
1054 static bool dce120_arm_vert_intr(
1055 struct timing_generator *tg,
1056 uint8_t width)
1057 {
1058 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1059 uint32_t v_blank_start, v_blank_end, h_position, v_position;
1060
1061 tg->funcs->get_scanoutpos(
1062 tg,
1063 &v_blank_start,
1064 &v_blank_end,
1065 &h_position,
1066 &v_position);
1067
1068 if (v_blank_start == 0 || v_blank_end == 0)
1069 return false;
1070
1071 CRTC_REG_SET_2(
1072 CRTC0_CRTC_VERTICAL_INTERRUPT0_POSITION,
1073 CRTC_VERTICAL_INTERRUPT0_LINE_START, v_blank_start,
1074 CRTC_VERTICAL_INTERRUPT0_LINE_END, v_blank_start + width);
1075
1076 return true;
1077 }
1078
1079
1080 static bool dce120_is_tg_enabled(struct timing_generator *tg)
1081 {
1082 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1083 uint32_t value, field;
1084
1085 value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CONTROL,
1086 tg110->offsets.crtc);
1087 field = get_reg_field_value(value, CRTC0_CRTC_CONTROL,
1088 CRTC_CURRENT_MASTER_EN_STATE);
1089
1090 return field == 1;
1091 }
1092
1093 static bool dce120_configure_crc(struct timing_generator *tg,
1094 const struct crc_params *params)
1095 {
1096 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1097
1098
1099 if (!dce120_is_tg_enabled(tg))
1100 return false;
1101
1102
1103 dm_write_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC_CNTL,
1104 tg110->offsets.crtc, 0);
1105
1106 if (!params->enable)
1107 return true;
1108
1109
1110
1111 CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWA_X_CONTROL,
1112 CRTC_CRC0_WINDOWA_X_START, params->windowa_x_start,
1113 CRTC_CRC0_WINDOWA_X_END, params->windowa_x_end);
1114
1115
1116 CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWA_Y_CONTROL,
1117 CRTC_CRC0_WINDOWA_Y_START, params->windowa_y_start,
1118 CRTC_CRC0_WINDOWA_Y_END, params->windowa_y_end);
1119
1120
1121 CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWB_X_CONTROL,
1122 CRTC_CRC0_WINDOWB_X_START, params->windowb_x_start,
1123 CRTC_CRC0_WINDOWB_X_END, params->windowb_x_end);
1124
1125
1126 CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWB_Y_CONTROL,
1127 CRTC_CRC0_WINDOWB_Y_START, params->windowb_y_start,
1128 CRTC_CRC0_WINDOWB_Y_END, params->windowb_y_end);
1129
1130
1131 CRTC_REG_UPDATE_3(CRTC0_CRTC_CRC_CNTL,
1132 CRTC_CRC_EN, params->continuous_mode ? 1 : 0,
1133 CRTC_CRC0_SELECT, params->selection,
1134 CRTC_CRC_EN, 1);
1135
1136 return true;
1137 }
1138
1139 static bool dce120_get_crc(struct timing_generator *tg, uint32_t *r_cr,
1140 uint32_t *g_y, uint32_t *b_cb)
1141 {
1142 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1143 uint32_t value, field;
1144
1145 value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC_CNTL,
1146 tg110->offsets.crtc);
1147 field = get_reg_field_value(value, CRTC0_CRTC_CRC_CNTL, CRTC_CRC_EN);
1148
1149
1150 if (!field)
1151 return false;
1152
1153 value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC0_DATA_RG,
1154 tg110->offsets.crtc);
1155 *r_cr = get_reg_field_value(value, CRTC0_CRTC_CRC0_DATA_RG, CRC0_R_CR);
1156 *g_y = get_reg_field_value(value, CRTC0_CRTC_CRC0_DATA_RG, CRC0_G_Y);
1157
1158 value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC0_DATA_B,
1159 tg110->offsets.crtc);
1160 *b_cb = get_reg_field_value(value, CRTC0_CRTC_CRC0_DATA_B, CRC0_B_CB);
1161
1162 return true;
1163 }
1164
1165 static const struct timing_generator_funcs dce120_tg_funcs = {
1166 .validate_timing = dce120_tg_validate_timing,
1167 .program_timing = dce120_tg_program_timing,
1168 .enable_crtc = dce120_timing_generator_enable_crtc,
1169 .disable_crtc = dce110_timing_generator_disable_crtc,
1170
1171 .is_counter_moving = dce110_timing_generator_is_counter_moving,
1172
1173 .get_position = dce120_timing_generator_get_crtc_position,
1174 .get_frame_count = dce120_timing_generator_get_vblank_counter,
1175 .get_scanoutpos = dce120_timing_generator_get_crtc_scanoutpos,
1176 .set_early_control = dce120_timing_generator_set_early_control,
1177
1178 .wait_for_state = dce120_tg_wait_for_state,
1179 .set_blank = dce120_tg_set_blank,
1180 .is_blanked = dce120_tg_is_blanked,
1181
1182 .set_colors = dce120_tg_set_colors,
1183 .set_overscan_blank_color = dce120_timing_generator_set_overscan_color_black,
1184 .set_blank_color = dce120_timing_generator_program_blank_color,
1185 .disable_vga = dce120_timing_generator_disable_vga,
1186 .did_triggered_reset_occur = dce120_timing_generator_did_triggered_reset_occur,
1187 .setup_global_swap_lock = dce120_timing_generator_setup_global_swap_lock,
1188 .enable_reset_trigger = dce120_timing_generator_enable_reset_trigger,
1189 .disable_reset_trigger = dce120_timing_generator_disable_reset_trigger,
1190 .tear_down_global_swap_lock = dce120_timing_generator_tear_down_global_swap_lock,
1191 .enable_advanced_request = dce120_timing_generator_enable_advanced_request,
1192 .set_drr = dce120_timing_generator_set_drr,
1193 .get_last_used_drr_vtotal = NULL,
1194 .set_static_screen_control = dce120_timing_generator_set_static_screen_control,
1195 .set_test_pattern = dce120_timing_generator_set_test_pattern,
1196 .arm_vert_intr = dce120_arm_vert_intr,
1197 .is_tg_enabled = dce120_is_tg_enabled,
1198 .configure_crc = dce120_configure_crc,
1199 .get_crc = dce120_get_crc,
1200 };
1201
1202
1203 void dce120_timing_generator_construct(
1204 struct dce110_timing_generator *tg110,
1205 struct dc_context *ctx,
1206 uint32_t instance,
1207 const struct dce110_timing_generator_offsets *offsets)
1208 {
1209 tg110->controller_id = CONTROLLER_ID_D0 + instance;
1210 tg110->base.inst = instance;
1211
1212 tg110->offsets = *offsets;
1213
1214 tg110->base.funcs = &dce120_tg_funcs;
1215
1216 tg110->base.ctx = ctx;
1217 tg110->base.bp = ctx->dc_bios;
1218
1219 tg110->max_h_total = CRTC0_CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1;
1220 tg110->max_v_total = CRTC0_CRTC_V_TOTAL__CRTC_V_TOTAL_MASK + 1;
1221
1222
1223
1224 tg110->min_h_blank = 32;
1225
1226 tg110->min_h_front_porch = 0;
1227 tg110->min_h_back_porch = 0;
1228
1229 tg110->min_h_sync_width = 4;
1230 tg110->min_v_sync_width = 1;
1231 tg110->min_v_blank = 3;
1232 }