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
0029 #include "dce/dce_11_0_d.h"
0030 #include "dce/dce_11_0_sh_mask.h"
0031
0032 #include "dc_types.h"
0033 #include "dc_bios_types.h"
0034 #include "dc.h"
0035
0036 #include "include/grph_object_id.h"
0037 #include "include/logger_interface.h"
0038 #include "dce110_timing_generator.h"
0039
0040 #include "timing_generator.h"
0041
0042
0043 #define NUMBER_OF_FRAME_TO_WAIT_ON_TRIGGERED_RESET 10
0044
0045 #define MAX_H_TOTAL (CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1)
0046 #define MAX_V_TOTAL (CRTC_V_TOTAL__CRTC_V_TOTAL_MASKhw + 1)
0047
0048 #define CRTC_REG(reg) (reg + tg110->offsets.crtc)
0049 #define DCP_REG(reg) (reg + tg110->offsets.dcp)
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065 static void dce110_timing_generator_apply_front_porch_workaround(
0066 struct timing_generator *tg,
0067 struct dc_crtc_timing *timing)
0068 {
0069 if (timing->flags.INTERLACE == 1) {
0070 if (timing->v_front_porch < 2)
0071 timing->v_front_porch = 2;
0072 } else {
0073 if (timing->v_front_porch < 1)
0074 timing->v_front_porch = 1;
0075 }
0076 }
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091 static bool dce110_timing_generator_is_in_vertical_blank(
0092 struct timing_generator *tg)
0093 {
0094 uint32_t addr = 0;
0095 uint32_t value = 0;
0096 uint32_t field = 0;
0097 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0098
0099 addr = CRTC_REG(mmCRTC_STATUS);
0100 value = dm_read_reg(tg->ctx, addr);
0101 field = get_reg_field_value(value, CRTC_STATUS, CRTC_V_BLANK);
0102 return field == 1;
0103 }
0104
0105 void dce110_timing_generator_set_early_control(
0106 struct timing_generator *tg,
0107 uint32_t early_cntl)
0108 {
0109 uint32_t regval;
0110 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0111 uint32_t address = CRTC_REG(mmCRTC_CONTROL);
0112
0113 regval = dm_read_reg(tg->ctx, address);
0114 set_reg_field_value(regval, early_cntl,
0115 CRTC_CONTROL, CRTC_HBLANK_EARLY_CONTROL);
0116 dm_write_reg(tg->ctx, address, regval);
0117 }
0118
0119
0120
0121
0122
0123 bool dce110_timing_generator_enable_crtc(struct timing_generator *tg)
0124 {
0125 enum bp_result result;
0126
0127 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0128 uint32_t value = 0;
0129
0130
0131
0132
0133
0134 set_reg_field_value(
0135 value,
0136 0,
0137 CRTC_MASTER_UPDATE_MODE,
0138 MASTER_UPDATE_MODE);
0139
0140 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_MASTER_UPDATE_MODE), value);
0141
0142
0143 value = 0;
0144 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_MASTER_UPDATE_LOCK), value);
0145
0146 result = tg->bp->funcs->enable_crtc(tg->bp, tg110->controller_id, true);
0147
0148 return result == BP_RESULT_OK;
0149 }
0150
0151 void dce110_timing_generator_program_blank_color(
0152 struct timing_generator *tg,
0153 const struct tg_color *black_color)
0154 {
0155 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0156 uint32_t addr = CRTC_REG(mmCRTC_BLACK_COLOR);
0157 uint32_t value = dm_read_reg(tg->ctx, addr);
0158
0159 set_reg_field_value(
0160 value,
0161 black_color->color_b_cb,
0162 CRTC_BLACK_COLOR,
0163 CRTC_BLACK_COLOR_B_CB);
0164 set_reg_field_value(
0165 value,
0166 black_color->color_g_y,
0167 CRTC_BLACK_COLOR,
0168 CRTC_BLACK_COLOR_G_Y);
0169 set_reg_field_value(
0170 value,
0171 black_color->color_r_cr,
0172 CRTC_BLACK_COLOR,
0173 CRTC_BLACK_COLOR_R_CR);
0174
0175 dm_write_reg(tg->ctx, addr, value);
0176 }
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187 #if 0
0188 @TODOSTEREO
0189 static void disable_stereo(struct timing_generator *tg)
0190 {
0191 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0192 uint32_t addr = CRTC_REG(mmCRTC_3D_STRUCTURE_CONTROL);
0193 uint32_t value = 0;
0194 uint32_t test = 0;
0195 uint32_t field = 0;
0196 uint32_t struc_en = 0;
0197 uint32_t struc_stereo_sel_ovr = 0;
0198
0199 value = dm_read_reg(tg->ctx, addr);
0200 struc_en = get_reg_field_value(
0201 value,
0202 CRTC_3D_STRUCTURE_CONTROL,
0203 CRTC_3D_STRUCTURE_EN);
0204
0205 struc_stereo_sel_ovr = get_reg_field_value(
0206 value,
0207 CRTC_3D_STRUCTURE_CONTROL,
0208 CRTC_3D_STRUCTURE_STEREO_SEL_OVR);
0209
0210
0211
0212
0213
0214
0215
0216 if (struc_en != 0 && struc_stereo_sel_ovr == 0) {
0217 tg->funcs->wait_for_vblank(tg);
0218 tg->funcs->wait_for_vactive(tg);
0219 }
0220
0221 value = 0;
0222 dm_write_reg(tg->ctx, addr, value);
0223
0224 addr = tg->regs[IDX_CRTC_STEREO_CONTROL];
0225 dm_write_reg(tg->ctx, addr, value);
0226 }
0227 #endif
0228
0229
0230
0231
0232 bool dce110_timing_generator_disable_crtc(struct timing_generator *tg)
0233 {
0234 enum bp_result result;
0235
0236 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0237
0238 result = tg->bp->funcs->enable_crtc(tg->bp, tg110->controller_id, false);
0239
0240
0241
0242
0243
0244
0245
0246
0247 return result == BP_RESULT_OK;
0248 }
0249
0250
0251
0252
0253
0254 static void program_horz_count_by_2(
0255 struct timing_generator *tg,
0256 const struct dc_crtc_timing *timing)
0257 {
0258 uint32_t regval;
0259 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0260
0261 regval = dm_read_reg(tg->ctx,
0262 CRTC_REG(mmCRTC_COUNT_CONTROL));
0263
0264 set_reg_field_value(regval, 0, CRTC_COUNT_CONTROL,
0265 CRTC_HORZ_COUNT_BY2_EN);
0266
0267 if (timing->flags.HORZ_COUNT_BY_TWO)
0268 set_reg_field_value(regval, 1, CRTC_COUNT_CONTROL,
0269 CRTC_HORZ_COUNT_BY2_EN);
0270
0271 dm_write_reg(tg->ctx,
0272 CRTC_REG(mmCRTC_COUNT_CONTROL), regval);
0273 }
0274
0275
0276
0277
0278
0279
0280 bool dce110_timing_generator_program_timing_generator(
0281 struct timing_generator *tg,
0282 const struct dc_crtc_timing *dc_crtc_timing)
0283 {
0284 enum bp_result result;
0285 struct bp_hw_crtc_timing_parameters bp_params;
0286 struct dc_crtc_timing patched_crtc_timing;
0287 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0288
0289 uint32_t vsync_offset = dc_crtc_timing->v_border_bottom +
0290 dc_crtc_timing->v_front_porch;
0291 uint32_t v_sync_start =dc_crtc_timing->v_addressable + vsync_offset;
0292
0293 uint32_t hsync_offset = dc_crtc_timing->h_border_right +
0294 dc_crtc_timing->h_front_porch;
0295 uint32_t h_sync_start = dc_crtc_timing->h_addressable + hsync_offset;
0296
0297 memset(&bp_params, 0, sizeof(struct bp_hw_crtc_timing_parameters));
0298
0299
0300
0301
0302
0303 patched_crtc_timing = *dc_crtc_timing;
0304
0305 dce110_timing_generator_apply_front_porch_workaround(tg, &patched_crtc_timing);
0306
0307 bp_params.controller_id = tg110->controller_id;
0308
0309 bp_params.h_total = patched_crtc_timing.h_total;
0310 bp_params.h_addressable =
0311 patched_crtc_timing.h_addressable;
0312 bp_params.v_total = patched_crtc_timing.v_total;
0313 bp_params.v_addressable = patched_crtc_timing.v_addressable;
0314
0315 bp_params.h_sync_start = h_sync_start;
0316 bp_params.h_sync_width = patched_crtc_timing.h_sync_width;
0317 bp_params.v_sync_start = v_sync_start;
0318 bp_params.v_sync_width = patched_crtc_timing.v_sync_width;
0319
0320
0321 bp_params.h_overscan_left =
0322 patched_crtc_timing.h_border_left;
0323 bp_params.h_overscan_right =
0324 patched_crtc_timing.h_border_right;
0325 bp_params.v_overscan_top = patched_crtc_timing.v_border_top;
0326 bp_params.v_overscan_bottom =
0327 patched_crtc_timing.v_border_bottom;
0328
0329
0330 if (patched_crtc_timing.flags.HSYNC_POSITIVE_POLARITY == 1)
0331 bp_params.flags.HSYNC_POSITIVE_POLARITY = 1;
0332
0333 if (patched_crtc_timing.flags.VSYNC_POSITIVE_POLARITY == 1)
0334 bp_params.flags.VSYNC_POSITIVE_POLARITY = 1;
0335
0336 if (patched_crtc_timing.flags.INTERLACE == 1)
0337 bp_params.flags.INTERLACE = 1;
0338
0339 if (patched_crtc_timing.flags.HORZ_COUNT_BY_TWO == 1)
0340 bp_params.flags.HORZ_COUNT_BY_TWO = 1;
0341
0342 result = tg->bp->funcs->program_crtc_timing(tg->bp, &bp_params);
0343
0344 program_horz_count_by_2(tg, &patched_crtc_timing);
0345
0346 tg110->base.funcs->enable_advanced_request(tg, true, &patched_crtc_timing);
0347
0348
0349
0350
0351 return result == BP_RESULT_OK;
0352 }
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365 void dce110_timing_generator_set_drr(
0366 struct timing_generator *tg,
0367 const struct drr_params *params)
0368 {
0369
0370 uint32_t v_total_min = 0;
0371 uint32_t v_total_max = 0;
0372 uint32_t v_total_cntl = 0;
0373 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0374
0375 uint32_t addr = 0;
0376
0377 addr = CRTC_REG(mmCRTC_V_TOTAL_MIN);
0378 v_total_min = dm_read_reg(tg->ctx, addr);
0379
0380 addr = CRTC_REG(mmCRTC_V_TOTAL_MAX);
0381 v_total_max = dm_read_reg(tg->ctx, addr);
0382
0383 addr = CRTC_REG(mmCRTC_V_TOTAL_CONTROL);
0384 v_total_cntl = dm_read_reg(tg->ctx, addr);
0385
0386 if (params != NULL &&
0387 params->vertical_total_max > 0 &&
0388 params->vertical_total_min > 0) {
0389
0390 set_reg_field_value(v_total_max,
0391 params->vertical_total_max - 1,
0392 CRTC_V_TOTAL_MAX,
0393 CRTC_V_TOTAL_MAX);
0394
0395 set_reg_field_value(v_total_min,
0396 params->vertical_total_min - 1,
0397 CRTC_V_TOTAL_MIN,
0398 CRTC_V_TOTAL_MIN);
0399
0400 set_reg_field_value(v_total_cntl,
0401 1,
0402 CRTC_V_TOTAL_CONTROL,
0403 CRTC_V_TOTAL_MIN_SEL);
0404
0405 set_reg_field_value(v_total_cntl,
0406 1,
0407 CRTC_V_TOTAL_CONTROL,
0408 CRTC_V_TOTAL_MAX_SEL);
0409
0410 set_reg_field_value(v_total_cntl,
0411 0,
0412 CRTC_V_TOTAL_CONTROL,
0413 CRTC_FORCE_LOCK_ON_EVENT);
0414 set_reg_field_value(v_total_cntl,
0415 0,
0416 CRTC_V_TOTAL_CONTROL,
0417 CRTC_FORCE_LOCK_TO_MASTER_VSYNC);
0418
0419 set_reg_field_value(v_total_cntl,
0420 0,
0421 CRTC_V_TOTAL_CONTROL,
0422 CRTC_SET_V_TOTAL_MIN_MASK_EN);
0423
0424 set_reg_field_value(v_total_cntl,
0425 0,
0426 CRTC_V_TOTAL_CONTROL,
0427 CRTC_SET_V_TOTAL_MIN_MASK);
0428 } else {
0429 set_reg_field_value(v_total_cntl,
0430 0,
0431 CRTC_V_TOTAL_CONTROL,
0432 CRTC_SET_V_TOTAL_MIN_MASK);
0433 set_reg_field_value(v_total_cntl,
0434 0,
0435 CRTC_V_TOTAL_CONTROL,
0436 CRTC_V_TOTAL_MIN_SEL);
0437 set_reg_field_value(v_total_cntl,
0438 0,
0439 CRTC_V_TOTAL_CONTROL,
0440 CRTC_V_TOTAL_MAX_SEL);
0441 set_reg_field_value(v_total_min,
0442 0,
0443 CRTC_V_TOTAL_MIN,
0444 CRTC_V_TOTAL_MIN);
0445 set_reg_field_value(v_total_max,
0446 0,
0447 CRTC_V_TOTAL_MAX,
0448 CRTC_V_TOTAL_MAX);
0449 set_reg_field_value(v_total_cntl,
0450 0,
0451 CRTC_V_TOTAL_CONTROL,
0452 CRTC_FORCE_LOCK_ON_EVENT);
0453 set_reg_field_value(v_total_cntl,
0454 0,
0455 CRTC_V_TOTAL_CONTROL,
0456 CRTC_FORCE_LOCK_TO_MASTER_VSYNC);
0457 }
0458
0459 addr = CRTC_REG(mmCRTC_V_TOTAL_MIN);
0460 dm_write_reg(tg->ctx, addr, v_total_min);
0461
0462 addr = CRTC_REG(mmCRTC_V_TOTAL_MAX);
0463 dm_write_reg(tg->ctx, addr, v_total_max);
0464
0465 addr = CRTC_REG(mmCRTC_V_TOTAL_CONTROL);
0466 dm_write_reg(tg->ctx, addr, v_total_cntl);
0467 }
0468
0469 void dce110_timing_generator_set_static_screen_control(
0470 struct timing_generator *tg,
0471 uint32_t event_triggers,
0472 uint32_t num_frames)
0473 {
0474 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0475 uint32_t static_screen_cntl = 0;
0476 uint32_t addr = 0;
0477
0478
0479 if (num_frames > 0xFF)
0480 num_frames = 0xFF;
0481
0482 addr = CRTC_REG(mmCRTC_STATIC_SCREEN_CONTROL);
0483 static_screen_cntl = dm_read_reg(tg->ctx, addr);
0484
0485 set_reg_field_value(static_screen_cntl,
0486 event_triggers,
0487 CRTC_STATIC_SCREEN_CONTROL,
0488 CRTC_STATIC_SCREEN_EVENT_MASK);
0489
0490 set_reg_field_value(static_screen_cntl,
0491 num_frames,
0492 CRTC_STATIC_SCREEN_CONTROL,
0493 CRTC_STATIC_SCREEN_FRAME_COUNT);
0494
0495 dm_write_reg(tg->ctx, addr, static_screen_cntl);
0496 }
0497
0498
0499
0500
0501
0502
0503
0504
0505
0506
0507
0508
0509
0510
0511
0512 uint32_t dce110_timing_generator_get_vblank_counter(struct timing_generator *tg)
0513 {
0514 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0515 uint32_t addr = CRTC_REG(mmCRTC_STATUS_FRAME_COUNT);
0516 uint32_t value = dm_read_reg(tg->ctx, addr);
0517 uint32_t field = get_reg_field_value(
0518 value, CRTC_STATUS_FRAME_COUNT, CRTC_FRAME_COUNT);
0519
0520 return field;
0521 }
0522
0523
0524
0525
0526
0527
0528
0529
0530
0531
0532
0533 void dce110_timing_generator_get_position(struct timing_generator *tg,
0534 struct crtc_position *position)
0535 {
0536 uint32_t value;
0537 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0538
0539 value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_STATUS_POSITION));
0540
0541 position->horizontal_count = get_reg_field_value(
0542 value,
0543 CRTC_STATUS_POSITION,
0544 CRTC_HORZ_COUNT);
0545
0546 position->vertical_count = get_reg_field_value(
0547 value,
0548 CRTC_STATUS_POSITION,
0549 CRTC_VERT_COUNT);
0550
0551 value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_NOM_VERT_POSITION));
0552
0553 position->nominal_vcount = get_reg_field_value(
0554 value,
0555 CRTC_NOM_VERT_POSITION,
0556 CRTC_VERT_COUNT_NOM);
0557 }
0558
0559
0560
0561
0562
0563
0564
0565
0566
0567
0568
0569 void dce110_timing_generator_get_crtc_scanoutpos(
0570 struct timing_generator *tg,
0571 uint32_t *v_blank_start,
0572 uint32_t *v_blank_end,
0573 uint32_t *h_position,
0574 uint32_t *v_position)
0575 {
0576 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0577 struct crtc_position position;
0578
0579 uint32_t value = dm_read_reg(tg->ctx,
0580 CRTC_REG(mmCRTC_V_BLANK_START_END));
0581
0582 *v_blank_start = get_reg_field_value(value,
0583 CRTC_V_BLANK_START_END,
0584 CRTC_V_BLANK_START);
0585 *v_blank_end = get_reg_field_value(value,
0586 CRTC_V_BLANK_START_END,
0587 CRTC_V_BLANK_END);
0588
0589 dce110_timing_generator_get_position(
0590 tg, &position);
0591
0592 *h_position = position.horizontal_count;
0593 *v_position = position.vertical_count;
0594 }
0595
0596
0597
0598
0599
0600 void dce110_timing_generator_program_blanking(
0601 struct timing_generator *tg,
0602 const struct dc_crtc_timing *timing)
0603 {
0604 uint32_t vsync_offset = timing->v_border_bottom +
0605 timing->v_front_porch;
0606 uint32_t v_sync_start =timing->v_addressable + vsync_offset;
0607
0608 uint32_t hsync_offset = timing->h_border_right +
0609 timing->h_front_porch;
0610 uint32_t h_sync_start = timing->h_addressable + hsync_offset;
0611 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0612
0613 struct dc_context *ctx = tg->ctx;
0614 uint32_t value = 0;
0615 uint32_t addr = 0;
0616 uint32_t tmp = 0;
0617
0618 addr = CRTC_REG(mmCRTC_H_TOTAL);
0619 value = dm_read_reg(ctx, addr);
0620 set_reg_field_value(
0621 value,
0622 timing->h_total - 1,
0623 CRTC_H_TOTAL,
0624 CRTC_H_TOTAL);
0625 dm_write_reg(ctx, addr, value);
0626
0627 addr = CRTC_REG(mmCRTC_V_TOTAL);
0628 value = dm_read_reg(ctx, addr);
0629 set_reg_field_value(
0630 value,
0631 timing->v_total - 1,
0632 CRTC_V_TOTAL,
0633 CRTC_V_TOTAL);
0634 dm_write_reg(ctx, addr, value);
0635
0636
0637
0638
0639 addr = CRTC_REG(mmCRTC_V_TOTAL_MAX);
0640 value = dm_read_reg(ctx, addr);
0641 set_reg_field_value(
0642 value,
0643 timing->v_total - 1,
0644 CRTC_V_TOTAL_MAX,
0645 CRTC_V_TOTAL_MAX);
0646 dm_write_reg(ctx, addr, value);
0647
0648 addr = CRTC_REG(mmCRTC_V_TOTAL_MIN);
0649 value = dm_read_reg(ctx, addr);
0650 set_reg_field_value(
0651 value,
0652 timing->v_total - 1,
0653 CRTC_V_TOTAL_MIN,
0654 CRTC_V_TOTAL_MIN);
0655 dm_write_reg(ctx, addr, value);
0656
0657 addr = CRTC_REG(mmCRTC_H_BLANK_START_END);
0658 value = dm_read_reg(ctx, addr);
0659
0660 tmp = timing->h_total -
0661 (h_sync_start + timing->h_border_left);
0662
0663 set_reg_field_value(
0664 value,
0665 tmp,
0666 CRTC_H_BLANK_START_END,
0667 CRTC_H_BLANK_END);
0668
0669 tmp = tmp + timing->h_addressable +
0670 timing->h_border_left + timing->h_border_right;
0671
0672 set_reg_field_value(
0673 value,
0674 tmp,
0675 CRTC_H_BLANK_START_END,
0676 CRTC_H_BLANK_START);
0677
0678 dm_write_reg(ctx, addr, value);
0679
0680 addr = CRTC_REG(mmCRTC_V_BLANK_START_END);
0681 value = dm_read_reg(ctx, addr);
0682
0683 tmp = timing->v_total - (v_sync_start + timing->v_border_top);
0684
0685 set_reg_field_value(
0686 value,
0687 tmp,
0688 CRTC_V_BLANK_START_END,
0689 CRTC_V_BLANK_END);
0690
0691 tmp = tmp + timing->v_addressable + timing->v_border_top +
0692 timing->v_border_bottom;
0693
0694 set_reg_field_value(
0695 value,
0696 tmp,
0697 CRTC_V_BLANK_START_END,
0698 CRTC_V_BLANK_START);
0699
0700 dm_write_reg(ctx, addr, value);
0701 }
0702
0703 void dce110_timing_generator_set_test_pattern(
0704 struct timing_generator *tg,
0705
0706
0707
0708 enum controller_dp_test_pattern test_pattern,
0709 enum dc_color_depth color_depth)
0710 {
0711 struct dc_context *ctx = tg->ctx;
0712 uint32_t value;
0713 uint32_t addr;
0714 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0715 enum test_pattern_color_format bit_depth;
0716 enum test_pattern_dyn_range dyn_range;
0717 enum test_pattern_mode mode;
0718
0719 uint32_t src_bpc = 16;
0720
0721 uint32_t dst_bpc;
0722 uint32_t index;
0723
0724
0725
0726
0727
0728 uint16_t src_color[6] = {0xFFFF, 0xFFFF, 0xFFFF, 0x0000,
0729 0x0000, 0x0000};
0730
0731 uint16_t dst_color[6];
0732 uint32_t inc_base;
0733
0734
0735 switch (color_depth) {
0736 case COLOR_DEPTH_666:
0737 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_6;
0738 break;
0739 case COLOR_DEPTH_888:
0740 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
0741 break;
0742 case COLOR_DEPTH_101010:
0743 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_10;
0744 break;
0745 case COLOR_DEPTH_121212:
0746 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_12;
0747 break;
0748 default:
0749 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
0750 break;
0751 }
0752
0753 switch (test_pattern) {
0754 case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES:
0755 case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA:
0756 {
0757 dyn_range = (test_pattern ==
0758 CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA ?
0759 TEST_PATTERN_DYN_RANGE_CEA :
0760 TEST_PATTERN_DYN_RANGE_VESA);
0761 mode = TEST_PATTERN_MODE_COLORSQUARES_RGB;
0762 value = 0;
0763 addr = CRTC_REG(mmCRTC_TEST_PATTERN_PARAMETERS);
0764
0765 set_reg_field_value(
0766 value,
0767 6,
0768 CRTC_TEST_PATTERN_PARAMETERS,
0769 CRTC_TEST_PATTERN_VRES);
0770 set_reg_field_value(
0771 value,
0772 6,
0773 CRTC_TEST_PATTERN_PARAMETERS,
0774 CRTC_TEST_PATTERN_HRES);
0775
0776 dm_write_reg(ctx, addr, value);
0777
0778 addr = CRTC_REG(mmCRTC_TEST_PATTERN_CONTROL);
0779 value = 0;
0780
0781 set_reg_field_value(
0782 value,
0783 1,
0784 CRTC_TEST_PATTERN_CONTROL,
0785 CRTC_TEST_PATTERN_EN);
0786
0787 set_reg_field_value(
0788 value,
0789 mode,
0790 CRTC_TEST_PATTERN_CONTROL,
0791 CRTC_TEST_PATTERN_MODE);
0792
0793 set_reg_field_value(
0794 value,
0795 dyn_range,
0796 CRTC_TEST_PATTERN_CONTROL,
0797 CRTC_TEST_PATTERN_DYNAMIC_RANGE);
0798 set_reg_field_value(
0799 value,
0800 bit_depth,
0801 CRTC_TEST_PATTERN_CONTROL,
0802 CRTC_TEST_PATTERN_COLOR_FORMAT);
0803 dm_write_reg(ctx, addr, value);
0804 }
0805 break;
0806
0807 case CONTROLLER_DP_TEST_PATTERN_VERTICALBARS:
0808 case CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS:
0809 {
0810 mode = (test_pattern ==
0811 CONTROLLER_DP_TEST_PATTERN_VERTICALBARS ?
0812 TEST_PATTERN_MODE_VERTICALBARS :
0813 TEST_PATTERN_MODE_HORIZONTALBARS);
0814
0815 switch (bit_depth) {
0816 case TEST_PATTERN_COLOR_FORMAT_BPC_6:
0817 dst_bpc = 6;
0818 break;
0819 case TEST_PATTERN_COLOR_FORMAT_BPC_8:
0820 dst_bpc = 8;
0821 break;
0822 case TEST_PATTERN_COLOR_FORMAT_BPC_10:
0823 dst_bpc = 10;
0824 break;
0825 default:
0826 dst_bpc = 8;
0827 break;
0828 }
0829
0830
0831 for (index = 0; index < 6; index++) {
0832
0833
0834
0835 dst_color[index] =
0836 src_color[index] >> (src_bpc - dst_bpc);
0837
0838
0839
0840
0841
0842
0843 dst_color[index] <<= (16 - dst_bpc);
0844 }
0845
0846 value = 0;
0847 addr = CRTC_REG(mmCRTC_TEST_PATTERN_PARAMETERS);
0848 dm_write_reg(ctx, addr, value);
0849
0850
0851
0852
0853
0854
0855
0856
0857
0858
0859
0860
0861
0862
0863
0864
0865
0866
0867
0868
0869
0870
0871
0872
0873
0874
0875
0876 value = 0;
0877 addr = CRTC_REG(mmCRTC_TEST_PATTERN_COLOR);
0878 for (index = 0; index < 6; index++) {
0879
0880
0881
0882 set_reg_field_value(
0883 value,
0884 (1 << index),
0885 CRTC_TEST_PATTERN_COLOR,
0886 CRTC_TEST_PATTERN_MASK);
0887
0888 dm_write_reg(ctx, addr, value);
0889
0890
0891
0892 set_reg_field_value(
0893 value,
0894 dst_color[index],
0895 CRTC_TEST_PATTERN_COLOR,
0896 CRTC_TEST_PATTERN_DATA);
0897 }
0898
0899
0900
0901 dm_write_reg(ctx, addr, value);
0902
0903
0904 addr = CRTC_REG(mmCRTC_TEST_PATTERN_CONTROL);
0905 value = 0;
0906
0907 set_reg_field_value(
0908 value,
0909 1,
0910 CRTC_TEST_PATTERN_CONTROL,
0911 CRTC_TEST_PATTERN_EN);
0912
0913 set_reg_field_value(
0914 value,
0915 mode,
0916 CRTC_TEST_PATTERN_CONTROL,
0917 CRTC_TEST_PATTERN_MODE);
0918
0919 set_reg_field_value(
0920 value,
0921 0,
0922 CRTC_TEST_PATTERN_CONTROL,
0923 CRTC_TEST_PATTERN_DYNAMIC_RANGE);
0924
0925 set_reg_field_value(
0926 value,
0927 bit_depth,
0928 CRTC_TEST_PATTERN_CONTROL,
0929 CRTC_TEST_PATTERN_COLOR_FORMAT);
0930
0931 dm_write_reg(ctx, addr, value);
0932 }
0933 break;
0934
0935 case CONTROLLER_DP_TEST_PATTERN_COLORRAMP:
0936 {
0937 mode = (bit_depth ==
0938 TEST_PATTERN_COLOR_FORMAT_BPC_10 ?
0939 TEST_PATTERN_MODE_DUALRAMP_RGB :
0940 TEST_PATTERN_MODE_SINGLERAMP_RGB);
0941
0942 switch (bit_depth) {
0943 case TEST_PATTERN_COLOR_FORMAT_BPC_6:
0944 dst_bpc = 6;
0945 break;
0946 case TEST_PATTERN_COLOR_FORMAT_BPC_8:
0947 dst_bpc = 8;
0948 break;
0949 case TEST_PATTERN_COLOR_FORMAT_BPC_10:
0950 dst_bpc = 10;
0951 break;
0952 default:
0953 dst_bpc = 8;
0954 break;
0955 }
0956
0957
0958
0959
0960
0961 inc_base = (src_bpc - dst_bpc);
0962
0963 value = 0;
0964 addr = CRTC_REG(mmCRTC_TEST_PATTERN_PARAMETERS);
0965
0966 switch (bit_depth) {
0967 case TEST_PATTERN_COLOR_FORMAT_BPC_6:
0968 {
0969 set_reg_field_value(
0970 value,
0971 inc_base,
0972 CRTC_TEST_PATTERN_PARAMETERS,
0973 CRTC_TEST_PATTERN_INC0);
0974 set_reg_field_value(
0975 value,
0976 0,
0977 CRTC_TEST_PATTERN_PARAMETERS,
0978 CRTC_TEST_PATTERN_INC1);
0979 set_reg_field_value(
0980 value,
0981 6,
0982 CRTC_TEST_PATTERN_PARAMETERS,
0983 CRTC_TEST_PATTERN_HRES);
0984 set_reg_field_value(
0985 value,
0986 6,
0987 CRTC_TEST_PATTERN_PARAMETERS,
0988 CRTC_TEST_PATTERN_VRES);
0989 set_reg_field_value(
0990 value,
0991 0,
0992 CRTC_TEST_PATTERN_PARAMETERS,
0993 CRTC_TEST_PATTERN_RAMP0_OFFSET);
0994 }
0995 break;
0996 case TEST_PATTERN_COLOR_FORMAT_BPC_8:
0997 {
0998 set_reg_field_value(
0999 value,
1000 inc_base,
1001 CRTC_TEST_PATTERN_PARAMETERS,
1002 CRTC_TEST_PATTERN_INC0);
1003 set_reg_field_value(
1004 value,
1005 0,
1006 CRTC_TEST_PATTERN_PARAMETERS,
1007 CRTC_TEST_PATTERN_INC1);
1008 set_reg_field_value(
1009 value,
1010 8,
1011 CRTC_TEST_PATTERN_PARAMETERS,
1012 CRTC_TEST_PATTERN_HRES);
1013 set_reg_field_value(
1014 value,
1015 6,
1016 CRTC_TEST_PATTERN_PARAMETERS,
1017 CRTC_TEST_PATTERN_VRES);
1018 set_reg_field_value(
1019 value,
1020 0,
1021 CRTC_TEST_PATTERN_PARAMETERS,
1022 CRTC_TEST_PATTERN_RAMP0_OFFSET);
1023 }
1024 break;
1025 case TEST_PATTERN_COLOR_FORMAT_BPC_10:
1026 {
1027 set_reg_field_value(
1028 value,
1029 inc_base,
1030 CRTC_TEST_PATTERN_PARAMETERS,
1031 CRTC_TEST_PATTERN_INC0);
1032 set_reg_field_value(
1033 value,
1034 inc_base + 2,
1035 CRTC_TEST_PATTERN_PARAMETERS,
1036 CRTC_TEST_PATTERN_INC1);
1037 set_reg_field_value(
1038 value,
1039 8,
1040 CRTC_TEST_PATTERN_PARAMETERS,
1041 CRTC_TEST_PATTERN_HRES);
1042 set_reg_field_value(
1043 value,
1044 5,
1045 CRTC_TEST_PATTERN_PARAMETERS,
1046 CRTC_TEST_PATTERN_VRES);
1047 set_reg_field_value(
1048 value,
1049 384 << 6,
1050 CRTC_TEST_PATTERN_PARAMETERS,
1051 CRTC_TEST_PATTERN_RAMP0_OFFSET);
1052 }
1053 break;
1054 default:
1055 break;
1056 }
1057 dm_write_reg(ctx, addr, value);
1058
1059 value = 0;
1060 addr = CRTC_REG(mmCRTC_TEST_PATTERN_COLOR);
1061 dm_write_reg(ctx, addr, value);
1062
1063
1064 addr = CRTC_REG(mmCRTC_TEST_PATTERN_CONTROL);
1065 value = 0;
1066
1067 set_reg_field_value(
1068 value,
1069 1,
1070 CRTC_TEST_PATTERN_CONTROL,
1071 CRTC_TEST_PATTERN_EN);
1072
1073 set_reg_field_value(
1074 value,
1075 mode,
1076 CRTC_TEST_PATTERN_CONTROL,
1077 CRTC_TEST_PATTERN_MODE);
1078
1079 set_reg_field_value(
1080 value,
1081 0,
1082 CRTC_TEST_PATTERN_CONTROL,
1083 CRTC_TEST_PATTERN_DYNAMIC_RANGE);
1084
1085 set_reg_field_value(
1086 value,
1087 bit_depth,
1088 CRTC_TEST_PATTERN_CONTROL,
1089 CRTC_TEST_PATTERN_COLOR_FORMAT);
1090
1091 dm_write_reg(ctx, addr, value);
1092 }
1093 break;
1094 case CONTROLLER_DP_TEST_PATTERN_VIDEOMODE:
1095 {
1096 value = 0;
1097 dm_write_reg(ctx, CRTC_REG(mmCRTC_TEST_PATTERN_CONTROL), value);
1098 dm_write_reg(ctx, CRTC_REG(mmCRTC_TEST_PATTERN_COLOR), value);
1099 dm_write_reg(ctx, CRTC_REG(mmCRTC_TEST_PATTERN_PARAMETERS),
1100 value);
1101 }
1102 break;
1103 default:
1104 break;
1105 }
1106 }
1107
1108
1109
1110
1111
1112
1113 bool dce110_timing_generator_validate_timing(
1114 struct timing_generator *tg,
1115 const struct dc_crtc_timing *timing,
1116 enum signal_type signal)
1117 {
1118 uint32_t h_blank;
1119 uint32_t h_back_porch, hsync_offset, h_sync_start;
1120
1121 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1122
1123 ASSERT(timing != NULL);
1124
1125 if (!timing)
1126 return false;
1127
1128 hsync_offset = timing->h_border_right + timing->h_front_porch;
1129 h_sync_start = timing->h_addressable + hsync_offset;
1130
1131
1132 if (timing->timing_3d_format != TIMING_3D_FORMAT_NONE)
1133 return false;
1134
1135
1136 if (timing->flags.INTERLACE == 1)
1137 return false;
1138
1139
1140
1141
1142
1143
1144 if (timing->h_total > tg110->max_h_total ||
1145 timing->v_total > tg110->max_v_total)
1146 return false;
1147
1148 h_blank = (timing->h_total - timing->h_addressable -
1149 timing->h_border_right -
1150 timing->h_border_left);
1151
1152 if (h_blank < tg110->min_h_blank)
1153 return false;
1154
1155 if (timing->h_front_porch < tg110->min_h_front_porch)
1156 return false;
1157
1158 h_back_porch = h_blank - (h_sync_start -
1159 timing->h_addressable -
1160 timing->h_border_right -
1161 timing->h_sync_width);
1162
1163 if (h_back_porch < tg110->min_h_back_porch)
1164 return false;
1165
1166 return true;
1167 }
1168
1169
1170
1171
1172 void dce110_timing_generator_wait_for_vblank(struct timing_generator *tg)
1173 {
1174
1175
1176
1177
1178 while (dce110_timing_generator_is_in_vertical_blank(tg)) {
1179 if (!dce110_timing_generator_is_counter_moving(tg)) {
1180
1181 break;
1182 }
1183 }
1184
1185 while (!dce110_timing_generator_is_in_vertical_blank(tg)) {
1186 if (!dce110_timing_generator_is_counter_moving(tg)) {
1187
1188 break;
1189 }
1190 }
1191 }
1192
1193
1194
1195
1196 void dce110_timing_generator_wait_for_vactive(struct timing_generator *tg)
1197 {
1198 while (dce110_timing_generator_is_in_vertical_blank(tg)) {
1199 if (!dce110_timing_generator_is_counter_moving(tg)) {
1200
1201 break;
1202 }
1203 }
1204 }
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217 void dce110_timing_generator_setup_global_swap_lock(
1218 struct timing_generator *tg,
1219 const struct dcp_gsl_params *gsl_params)
1220 {
1221 uint32_t value;
1222 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1223 uint32_t address = DCP_REG(mmDCP_GSL_CONTROL);
1224 uint32_t check_point = FLIP_READY_BACK_LOOKUP;
1225
1226 value = dm_read_reg(tg->ctx, address);
1227
1228
1229 set_reg_field_value(value,
1230 1,
1231 DCP_GSL_CONTROL,
1232 DCP_GSL0_EN);
1233
1234 set_reg_field_value(value,
1235 gsl_params->gsl_master == tg->inst,
1236 DCP_GSL_CONTROL,
1237 DCP_GSL_MASTER_EN);
1238
1239 set_reg_field_value(value,
1240 HFLIP_READY_DELAY,
1241 DCP_GSL_CONTROL,
1242 DCP_GSL_HSYNC_FLIP_FORCE_DELAY);
1243
1244
1245
1246 set_reg_field_value(value,
1247 HFLIP_CHECK_DELAY,
1248 DCP_GSL_CONTROL,
1249 DCP_GSL_HSYNC_FLIP_CHECK_DELAY);
1250
1251 dm_write_reg(tg->ctx, CRTC_REG(mmDCP_GSL_CONTROL), value);
1252 value = 0;
1253
1254 set_reg_field_value(value,
1255 gsl_params->gsl_master,
1256 DCIO_GSL0_CNTL,
1257 DCIO_GSL0_VSYNC_SEL);
1258
1259 set_reg_field_value(value,
1260 0,
1261 DCIO_GSL0_CNTL,
1262 DCIO_GSL0_TIMING_SYNC_SEL);
1263
1264 set_reg_field_value(value,
1265 0,
1266 DCIO_GSL0_CNTL,
1267 DCIO_GSL0_GLOBAL_UNLOCK_SEL);
1268
1269 dm_write_reg(tg->ctx, CRTC_REG(mmDCIO_GSL0_CNTL), value);
1270
1271
1272 {
1273 uint32_t value_crtc_vtotal;
1274
1275 value_crtc_vtotal = dm_read_reg(tg->ctx,
1276 CRTC_REG(mmCRTC_V_TOTAL));
1277
1278 set_reg_field_value(value,
1279 0,
1280 DCP_GSL_CONTROL,
1281 DCP_GSL_SYNC_SOURCE);
1282
1283
1284 check_point = get_reg_field_value(value_crtc_vtotal,
1285 CRTC_V_TOTAL,
1286 CRTC_V_TOTAL);
1287
1288 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_GSL_WINDOW), 0);
1289 }
1290
1291 set_reg_field_value(value,
1292 1,
1293 DCP_GSL_CONTROL,
1294 DCP_GSL_DELAY_SURFACE_UPDATE_PENDING);
1295
1296 dm_write_reg(tg->ctx, address, value);
1297
1298
1299 address = CRTC_REG(mmCRTC_GSL_CONTROL);
1300
1301 value = dm_read_reg(tg->ctx, address);
1302 set_reg_field_value(value,
1303 check_point - FLIP_READY_BACK_LOOKUP,
1304 CRTC_GSL_CONTROL,
1305 CRTC_GSL_CHECK_LINE_NUM);
1306
1307 set_reg_field_value(value,
1308 VFLIP_READY_DELAY,
1309 CRTC_GSL_CONTROL,
1310 CRTC_GSL_FORCE_DELAY);
1311
1312 dm_write_reg(tg->ctx, address, value);
1313 }
1314
1315 void dce110_timing_generator_tear_down_global_swap_lock(
1316 struct timing_generator *tg)
1317 {
1318
1319
1320
1321
1322 uint32_t value;
1323 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1324 uint32_t address = DCP_REG(mmDCP_GSL_CONTROL);
1325
1326 value = 0;
1327
1328
1329
1330 set_reg_field_value(value,
1331 0,
1332 DCP_GSL_CONTROL,
1333 DCP_GSL0_EN);
1334
1335 set_reg_field_value(value,
1336 0,
1337 DCP_GSL_CONTROL,
1338 DCP_GSL_MASTER_EN);
1339
1340 set_reg_field_value(value,
1341 0x2,
1342 DCP_GSL_CONTROL,
1343 DCP_GSL_HSYNC_FLIP_FORCE_DELAY);
1344
1345 set_reg_field_value(value,
1346 0x6,
1347 DCP_GSL_CONTROL,
1348 DCP_GSL_HSYNC_FLIP_CHECK_DELAY);
1349
1350
1351 {
1352 dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_V_TOTAL));
1353
1354 set_reg_field_value(value,
1355 0,
1356 DCP_GSL_CONTROL,
1357 DCP_GSL_SYNC_SOURCE);
1358 }
1359
1360 set_reg_field_value(value,
1361 0,
1362 DCP_GSL_CONTROL,
1363 DCP_GSL_DELAY_SURFACE_UPDATE_PENDING);
1364
1365 dm_write_reg(tg->ctx, address, value);
1366
1367
1368 address = CRTC_REG(mmCRTC_GSL_CONTROL);
1369
1370 value = 0;
1371 set_reg_field_value(value,
1372 0,
1373 CRTC_GSL_CONTROL,
1374 CRTC_GSL_CHECK_LINE_NUM);
1375
1376 set_reg_field_value(value,
1377 0x2,
1378 CRTC_GSL_CONTROL,
1379 CRTC_GSL_FORCE_DELAY);
1380
1381 dm_write_reg(tg->ctx, address, value);
1382 }
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395 bool dce110_timing_generator_is_counter_moving(struct timing_generator *tg)
1396 {
1397 struct crtc_position position1, position2;
1398
1399 tg->funcs->get_position(tg, &position1);
1400 tg->funcs->get_position(tg, &position2);
1401
1402 if (position1.horizontal_count == position2.horizontal_count &&
1403 position1.vertical_count == position2.vertical_count)
1404 return false;
1405 else
1406 return true;
1407 }
1408
1409 void dce110_timing_generator_enable_advanced_request(
1410 struct timing_generator *tg,
1411 bool enable,
1412 const struct dc_crtc_timing *timing)
1413 {
1414 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1415 uint32_t addr = CRTC_REG(mmCRTC_START_LINE_CONTROL);
1416 uint32_t value = dm_read_reg(tg->ctx, addr);
1417
1418 if (enable) {
1419 set_reg_field_value(
1420 value,
1421 0,
1422 CRTC_START_LINE_CONTROL,
1423 CRTC_LEGACY_REQUESTOR_EN);
1424 } else {
1425 set_reg_field_value(
1426 value,
1427 1,
1428 CRTC_START_LINE_CONTROL,
1429 CRTC_LEGACY_REQUESTOR_EN);
1430 }
1431
1432 if ((timing->v_sync_width + timing->v_front_porch) <= 3) {
1433 set_reg_field_value(
1434 value,
1435 3,
1436 CRTC_START_LINE_CONTROL,
1437 CRTC_ADVANCED_START_LINE_POSITION);
1438 set_reg_field_value(
1439 value,
1440 0,
1441 CRTC_START_LINE_CONTROL,
1442 CRTC_PREFETCH_EN);
1443 } else {
1444 set_reg_field_value(
1445 value,
1446 4,
1447 CRTC_START_LINE_CONTROL,
1448 CRTC_ADVANCED_START_LINE_POSITION);
1449 set_reg_field_value(
1450 value,
1451 1,
1452 CRTC_START_LINE_CONTROL,
1453 CRTC_PREFETCH_EN);
1454 }
1455
1456 set_reg_field_value(
1457 value,
1458 1,
1459 CRTC_START_LINE_CONTROL,
1460 CRTC_PROGRESSIVE_START_LINE_EARLY);
1461
1462 set_reg_field_value(
1463 value,
1464 1,
1465 CRTC_START_LINE_CONTROL,
1466 CRTC_INTERLACE_START_LINE_EARLY);
1467
1468 dm_write_reg(tg->ctx, addr, value);
1469 }
1470
1471
1472 void dce110_timing_generator_set_lock_master(struct timing_generator *tg,
1473 bool lock)
1474 {
1475 struct dc_context *ctx = tg->ctx;
1476 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1477 uint32_t addr = CRTC_REG(mmCRTC_MASTER_UPDATE_LOCK);
1478 uint32_t value = dm_read_reg(ctx, addr);
1479
1480 set_reg_field_value(
1481 value,
1482 lock ? 1 : 0,
1483 CRTC_MASTER_UPDATE_LOCK,
1484 MASTER_UPDATE_LOCK);
1485
1486 dm_write_reg(ctx, addr, value);
1487 }
1488
1489 void dce110_timing_generator_enable_reset_trigger(
1490 struct timing_generator *tg,
1491 int source_tg_inst)
1492 {
1493 uint32_t value;
1494 uint32_t rising_edge = 0;
1495 uint32_t falling_edge = 0;
1496 enum trigger_source_select trig_src_select = TRIGGER_SOURCE_SELECT_LOGIC_ZERO;
1497 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1498
1499
1500 {
1501 uint32_t pol_value = dm_read_reg(tg->ctx,
1502 CRTC_REG(mmCRTC_V_SYNC_A_CNTL));
1503
1504
1505
1506 if (get_reg_field_value(pol_value,
1507 CRTC_V_SYNC_A_CNTL,
1508 CRTC_V_SYNC_A_POL) == 0) {
1509 rising_edge = 1;
1510 } else {
1511 falling_edge = 1;
1512 }
1513 }
1514
1515 value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL));
1516
1517 trig_src_select = TRIGGER_SOURCE_SELECT_GSL_GROUP0;
1518
1519 set_reg_field_value(value,
1520 trig_src_select,
1521 CRTC_TRIGB_CNTL,
1522 CRTC_TRIGB_SOURCE_SELECT);
1523
1524 set_reg_field_value(value,
1525 TRIGGER_POLARITY_SELECT_LOGIC_ZERO,
1526 CRTC_TRIGB_CNTL,
1527 CRTC_TRIGB_POLARITY_SELECT);
1528
1529 set_reg_field_value(value,
1530 rising_edge,
1531 CRTC_TRIGB_CNTL,
1532 CRTC_TRIGB_RISING_EDGE_DETECT_CNTL);
1533
1534 set_reg_field_value(value,
1535 falling_edge,
1536 CRTC_TRIGB_CNTL,
1537 CRTC_TRIGB_FALLING_EDGE_DETECT_CNTL);
1538
1539 set_reg_field_value(value,
1540 0,
1541 CRTC_TRIGB_CNTL,
1542 CRTC_TRIGB_FREQUENCY_SELECT);
1543
1544 set_reg_field_value(value,
1545 0,
1546 CRTC_TRIGB_CNTL,
1547 CRTC_TRIGB_DELAY);
1548
1549 set_reg_field_value(value,
1550 1,
1551 CRTC_TRIGB_CNTL,
1552 CRTC_TRIGB_CLEAR);
1553
1554 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL), value);
1555
1556
1557
1558 value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL));
1559
1560 set_reg_field_value(value,
1561 2,
1562 CRTC_FORCE_COUNT_NOW_CNTL,
1563 CRTC_FORCE_COUNT_NOW_MODE);
1564
1565 set_reg_field_value(value,
1566 1,
1567 CRTC_FORCE_COUNT_NOW_CNTL,
1568 CRTC_FORCE_COUNT_NOW_TRIG_SEL);
1569
1570 set_reg_field_value(value,
1571 1,
1572 CRTC_FORCE_COUNT_NOW_CNTL,
1573 CRTC_FORCE_COUNT_NOW_CLEAR);
1574
1575 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL), value);
1576 }
1577
1578 void dce110_timing_generator_enable_crtc_reset(
1579 struct timing_generator *tg,
1580 int source_tg_inst,
1581 struct crtc_trigger_info *crtc_tp)
1582 {
1583 uint32_t value = 0;
1584 uint32_t rising_edge = 0;
1585 uint32_t falling_edge = 0;
1586 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1587
1588
1589 switch (crtc_tp->event) {
1590 case CRTC_EVENT_VSYNC_RISING:
1591 rising_edge = 1;
1592 break;
1593
1594 case CRTC_EVENT_VSYNC_FALLING:
1595 falling_edge = 1;
1596 break;
1597 }
1598
1599 value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL));
1600
1601 set_reg_field_value(value,
1602 source_tg_inst,
1603 CRTC_TRIGB_CNTL,
1604 CRTC_TRIGB_SOURCE_SELECT);
1605
1606 set_reg_field_value(value,
1607 TRIGGER_POLARITY_SELECT_LOGIC_ZERO,
1608 CRTC_TRIGB_CNTL,
1609 CRTC_TRIGB_POLARITY_SELECT);
1610
1611 set_reg_field_value(value,
1612 rising_edge,
1613 CRTC_TRIGB_CNTL,
1614 CRTC_TRIGB_RISING_EDGE_DETECT_CNTL);
1615
1616 set_reg_field_value(value,
1617 falling_edge,
1618 CRTC_TRIGB_CNTL,
1619 CRTC_TRIGB_FALLING_EDGE_DETECT_CNTL);
1620
1621 set_reg_field_value(value,
1622 1,
1623 CRTC_TRIGB_CNTL,
1624 CRTC_TRIGB_CLEAR);
1625
1626 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL), value);
1627
1628
1629
1630 switch (crtc_tp->delay) {
1631 case TRIGGER_DELAY_NEXT_LINE:
1632 value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL));
1633
1634 set_reg_field_value(value,
1635 0,
1636 CRTC_FORCE_COUNT_NOW_CNTL,
1637 CRTC_FORCE_COUNT_NOW_MODE);
1638
1639 set_reg_field_value(value,
1640 0,
1641 CRTC_FORCE_COUNT_NOW_CNTL,
1642 CRTC_FORCE_COUNT_NOW_TRIG_SEL);
1643
1644 set_reg_field_value(value,
1645 1,
1646 CRTC_FORCE_COUNT_NOW_CNTL,
1647 CRTC_FORCE_COUNT_NOW_CLEAR);
1648
1649 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL), value);
1650
1651 value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_VERT_SYNC_CONTROL));
1652
1653 set_reg_field_value(value,
1654 1,
1655 CRTC_VERT_SYNC_CONTROL,
1656 CRTC_FORCE_VSYNC_NEXT_LINE_CLEAR);
1657
1658 set_reg_field_value(value,
1659 2,
1660 CRTC_VERT_SYNC_CONTROL,
1661 CRTC_AUTO_FORCE_VSYNC_MODE);
1662
1663 break;
1664
1665 case TRIGGER_DELAY_NEXT_PIXEL:
1666 value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_VERT_SYNC_CONTROL));
1667
1668 set_reg_field_value(value,
1669 1,
1670 CRTC_VERT_SYNC_CONTROL,
1671 CRTC_FORCE_VSYNC_NEXT_LINE_CLEAR);
1672
1673 set_reg_field_value(value,
1674 0,
1675 CRTC_VERT_SYNC_CONTROL,
1676 CRTC_AUTO_FORCE_VSYNC_MODE);
1677
1678 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_VERT_SYNC_CONTROL), value);
1679
1680 value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL));
1681
1682 set_reg_field_value(value,
1683 2,
1684 CRTC_FORCE_COUNT_NOW_CNTL,
1685 CRTC_FORCE_COUNT_NOW_MODE);
1686
1687 set_reg_field_value(value,
1688 1,
1689 CRTC_FORCE_COUNT_NOW_CNTL,
1690 CRTC_FORCE_COUNT_NOW_TRIG_SEL);
1691
1692 set_reg_field_value(value,
1693 1,
1694 CRTC_FORCE_COUNT_NOW_CNTL,
1695 CRTC_FORCE_COUNT_NOW_CLEAR);
1696
1697 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL), value);
1698 break;
1699 }
1700
1701 value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_MASTER_UPDATE_MODE));
1702
1703 set_reg_field_value(value,
1704 2,
1705 CRTC_MASTER_UPDATE_MODE,
1706 MASTER_UPDATE_MODE);
1707
1708 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_MASTER_UPDATE_MODE), value);
1709 }
1710 void dce110_timing_generator_disable_reset_trigger(
1711 struct timing_generator *tg)
1712 {
1713 uint32_t value;
1714 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1715
1716 value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL));
1717
1718 set_reg_field_value(value,
1719 0,
1720 CRTC_FORCE_COUNT_NOW_CNTL,
1721 CRTC_FORCE_COUNT_NOW_MODE);
1722
1723 set_reg_field_value(value,
1724 1,
1725 CRTC_FORCE_COUNT_NOW_CNTL,
1726 CRTC_FORCE_COUNT_NOW_CLEAR);
1727
1728 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL), value);
1729
1730 value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_VERT_SYNC_CONTROL));
1731
1732 set_reg_field_value(value,
1733 1,
1734 CRTC_VERT_SYNC_CONTROL,
1735 CRTC_FORCE_VSYNC_NEXT_LINE_CLEAR);
1736
1737 set_reg_field_value(value,
1738 0,
1739 CRTC_VERT_SYNC_CONTROL,
1740 CRTC_AUTO_FORCE_VSYNC_MODE);
1741
1742 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_VERT_SYNC_CONTROL), value);
1743
1744
1745 value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL));
1746
1747 set_reg_field_value(value,
1748 TRIGGER_SOURCE_SELECT_LOGIC_ZERO,
1749 CRTC_TRIGB_CNTL,
1750 CRTC_TRIGB_SOURCE_SELECT);
1751
1752 set_reg_field_value(value,
1753 TRIGGER_POLARITY_SELECT_LOGIC_ZERO,
1754 CRTC_TRIGB_CNTL,
1755 CRTC_TRIGB_POLARITY_SELECT);
1756
1757 set_reg_field_value(value,
1758 1,
1759 CRTC_TRIGB_CNTL,
1760 CRTC_TRIGB_CLEAR);
1761
1762 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL), value);
1763 }
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774 bool dce110_timing_generator_did_triggered_reset_occur(
1775 struct timing_generator *tg)
1776 {
1777 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1778 uint32_t value = dm_read_reg(tg->ctx,
1779 CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL));
1780 uint32_t value1 = dm_read_reg(tg->ctx,
1781 CRTC_REG(mmCRTC_VERT_SYNC_CONTROL));
1782 bool force = get_reg_field_value(value,
1783 CRTC_FORCE_COUNT_NOW_CNTL,
1784 CRTC_FORCE_COUNT_NOW_OCCURRED) != 0;
1785 bool vert_sync = get_reg_field_value(value1,
1786 CRTC_VERT_SYNC_CONTROL,
1787 CRTC_FORCE_VSYNC_NEXT_LINE_OCCURRED) != 0;
1788
1789 return (force || vert_sync);
1790 }
1791
1792
1793
1794
1795
1796
1797 void dce110_timing_generator_disable_vga(
1798 struct timing_generator *tg)
1799 {
1800 uint32_t addr = 0;
1801 uint32_t value = 0;
1802
1803 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1804
1805 switch (tg110->controller_id) {
1806 case CONTROLLER_ID_D0:
1807 addr = mmD1VGA_CONTROL;
1808 break;
1809 case CONTROLLER_ID_D1:
1810 addr = mmD2VGA_CONTROL;
1811 break;
1812 case CONTROLLER_ID_D2:
1813 addr = mmD3VGA_CONTROL;
1814 break;
1815 case CONTROLLER_ID_D3:
1816 addr = mmD4VGA_CONTROL;
1817 break;
1818 case CONTROLLER_ID_D4:
1819 addr = mmD5VGA_CONTROL;
1820 break;
1821 case CONTROLLER_ID_D5:
1822 addr = mmD6VGA_CONTROL;
1823 break;
1824 default:
1825 break;
1826 }
1827 value = dm_read_reg(tg->ctx, addr);
1828
1829 set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_MODE_ENABLE);
1830 set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_TIMING_SELECT);
1831 set_reg_field_value(
1832 value, 0, D1VGA_CONTROL, D1VGA_SYNC_POLARITY_SELECT);
1833 set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_OVERSCAN_COLOR_EN);
1834
1835 dm_write_reg(tg->ctx, addr, value);
1836 }
1837
1838
1839
1840
1841
1842
1843
1844
1845 void dce110_timing_generator_set_overscan_color_black(
1846 struct timing_generator *tg,
1847 const struct tg_color *color)
1848 {
1849 struct dc_context *ctx = tg->ctx;
1850 uint32_t addr;
1851 uint32_t value = 0;
1852 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1853
1854 set_reg_field_value(
1855 value,
1856 color->color_b_cb,
1857 CRTC_OVERSCAN_COLOR,
1858 CRTC_OVERSCAN_COLOR_BLUE);
1859
1860 set_reg_field_value(
1861 value,
1862 color->color_r_cr,
1863 CRTC_OVERSCAN_COLOR,
1864 CRTC_OVERSCAN_COLOR_RED);
1865
1866 set_reg_field_value(
1867 value,
1868 color->color_g_y,
1869 CRTC_OVERSCAN_COLOR,
1870 CRTC_OVERSCAN_COLOR_GREEN);
1871
1872 addr = CRTC_REG(mmCRTC_OVERSCAN_COLOR);
1873 dm_write_reg(ctx, addr, value);
1874 addr = CRTC_REG(mmCRTC_BLACK_COLOR);
1875 dm_write_reg(ctx, addr, value);
1876
1877
1878
1879
1880 addr = CRTC_REG(mmCRTC_BLANK_DATA_COLOR);
1881 dm_write_reg(ctx, addr, value);
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891 }
1892
1893 void dce110_tg_program_blank_color(struct timing_generator *tg,
1894 const struct tg_color *black_color)
1895 {
1896 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1897 uint32_t addr = CRTC_REG(mmCRTC_BLACK_COLOR);
1898 uint32_t value = dm_read_reg(tg->ctx, addr);
1899
1900 set_reg_field_value(
1901 value,
1902 black_color->color_b_cb,
1903 CRTC_BLACK_COLOR,
1904 CRTC_BLACK_COLOR_B_CB);
1905 set_reg_field_value(
1906 value,
1907 black_color->color_g_y,
1908 CRTC_BLACK_COLOR,
1909 CRTC_BLACK_COLOR_G_Y);
1910 set_reg_field_value(
1911 value,
1912 black_color->color_r_cr,
1913 CRTC_BLACK_COLOR,
1914 CRTC_BLACK_COLOR_R_CR);
1915
1916 dm_write_reg(tg->ctx, addr, value);
1917
1918 addr = CRTC_REG(mmCRTC_BLANK_DATA_COLOR);
1919 dm_write_reg(tg->ctx, addr, value);
1920 }
1921
1922 void dce110_tg_set_overscan_color(struct timing_generator *tg,
1923 const struct tg_color *overscan_color)
1924 {
1925 struct dc_context *ctx = tg->ctx;
1926 uint32_t value = 0;
1927 uint32_t addr;
1928 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1929
1930 set_reg_field_value(
1931 value,
1932 overscan_color->color_b_cb,
1933 CRTC_OVERSCAN_COLOR,
1934 CRTC_OVERSCAN_COLOR_BLUE);
1935
1936 set_reg_field_value(
1937 value,
1938 overscan_color->color_g_y,
1939 CRTC_OVERSCAN_COLOR,
1940 CRTC_OVERSCAN_COLOR_GREEN);
1941
1942 set_reg_field_value(
1943 value,
1944 overscan_color->color_r_cr,
1945 CRTC_OVERSCAN_COLOR,
1946 CRTC_OVERSCAN_COLOR_RED);
1947
1948 addr = CRTC_REG(mmCRTC_OVERSCAN_COLOR);
1949 dm_write_reg(ctx, addr, value);
1950 }
1951
1952 void dce110_tg_program_timing(struct timing_generator *tg,
1953 const struct dc_crtc_timing *timing,
1954 int vready_offset,
1955 int vstartup_start,
1956 int vupdate_offset,
1957 int vupdate_width,
1958 const enum signal_type signal,
1959 bool use_vbios)
1960 {
1961 if (use_vbios)
1962 dce110_timing_generator_program_timing_generator(tg, timing);
1963 else
1964 dce110_timing_generator_program_blanking(tg, timing);
1965 }
1966
1967 bool dce110_tg_is_blanked(struct timing_generator *tg)
1968 {
1969 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1970 uint32_t value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL));
1971
1972 if (get_reg_field_value(
1973 value,
1974 CRTC_BLANK_CONTROL,
1975 CRTC_BLANK_DATA_EN) == 1 &&
1976 get_reg_field_value(
1977 value,
1978 CRTC_BLANK_CONTROL,
1979 CRTC_CURRENT_BLANK_STATE) == 1)
1980 return true;
1981 return false;
1982 }
1983
1984 void dce110_tg_set_blank(struct timing_generator *tg,
1985 bool enable_blanking)
1986 {
1987 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1988 uint32_t value = 0;
1989
1990 set_reg_field_value(
1991 value,
1992 1,
1993 CRTC_DOUBLE_BUFFER_CONTROL,
1994 CRTC_BLANK_DATA_DOUBLE_BUFFER_EN);
1995
1996 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_DOUBLE_BUFFER_CONTROL), value);
1997 value = 0;
1998
1999 if (enable_blanking) {
2000 set_reg_field_value(
2001 value,
2002 1,
2003 CRTC_BLANK_CONTROL,
2004 CRTC_BLANK_DATA_EN);
2005
2006 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL), value);
2007
2008 } else
2009 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL), 0);
2010 }
2011
2012 bool dce110_tg_validate_timing(struct timing_generator *tg,
2013 const struct dc_crtc_timing *timing)
2014 {
2015 return dce110_timing_generator_validate_timing(tg, timing, SIGNAL_TYPE_NONE);
2016 }
2017
2018 void dce110_tg_wait_for_state(struct timing_generator *tg,
2019 enum crtc_state state)
2020 {
2021 switch (state) {
2022 case CRTC_STATE_VBLANK:
2023 dce110_timing_generator_wait_for_vblank(tg);
2024 break;
2025
2026 case CRTC_STATE_VACTIVE:
2027 dce110_timing_generator_wait_for_vactive(tg);
2028 break;
2029
2030 default:
2031 break;
2032 }
2033 }
2034
2035 void dce110_tg_set_colors(struct timing_generator *tg,
2036 const struct tg_color *blank_color,
2037 const struct tg_color *overscan_color)
2038 {
2039 if (blank_color != NULL)
2040 dce110_tg_program_blank_color(tg, blank_color);
2041 if (overscan_color != NULL)
2042 dce110_tg_set_overscan_color(tg, overscan_color);
2043 }
2044
2045
2046
2047
2048 bool dce110_arm_vert_intr(struct timing_generator *tg, uint8_t width)
2049 {
2050 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
2051 uint32_t v_blank_start = 0;
2052 uint32_t v_blank_end = 0;
2053 uint32_t val = 0;
2054 uint32_t h_position, v_position;
2055
2056 tg->funcs->get_scanoutpos(
2057 tg,
2058 &v_blank_start,
2059 &v_blank_end,
2060 &h_position,
2061 &v_position);
2062
2063 if (v_blank_start == 0 || v_blank_end == 0)
2064 return false;
2065
2066 set_reg_field_value(
2067 val,
2068 v_blank_start,
2069 CRTC_VERTICAL_INTERRUPT0_POSITION,
2070 CRTC_VERTICAL_INTERRUPT0_LINE_START);
2071
2072
2073 set_reg_field_value(
2074 val,
2075 v_blank_start + width,
2076 CRTC_VERTICAL_INTERRUPT0_POSITION,
2077 CRTC_VERTICAL_INTERRUPT0_LINE_END);
2078
2079 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_VERTICAL_INTERRUPT0_POSITION), val);
2080
2081 return true;
2082 }
2083
2084 static bool dce110_is_tg_enabled(struct timing_generator *tg)
2085 {
2086 uint32_t addr = 0;
2087 uint32_t value = 0;
2088 uint32_t field = 0;
2089 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
2090
2091 addr = CRTC_REG(mmCRTC_CONTROL);
2092 value = dm_read_reg(tg->ctx, addr);
2093 field = get_reg_field_value(value, CRTC_CONTROL,
2094 CRTC_CURRENT_MASTER_EN_STATE);
2095 return field == 1;
2096 }
2097
2098 bool dce110_configure_crc(struct timing_generator *tg,
2099 const struct crc_params *params)
2100 {
2101 uint32_t cntl_addr = 0;
2102 uint32_t addr = 0;
2103 uint32_t value;
2104 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
2105
2106
2107 if (!dce110_is_tg_enabled(tg))
2108 return false;
2109
2110 cntl_addr = CRTC_REG(mmCRTC_CRC_CNTL);
2111
2112
2113 dm_write_reg(tg->ctx, cntl_addr, 0);
2114
2115 if (!params->enable)
2116 return true;
2117
2118
2119
2120 value = 0;
2121 addr = CRTC_REG(mmCRTC_CRC0_WINDOWA_X_CONTROL);
2122 set_reg_field_value(value, params->windowa_x_start,
2123 CRTC_CRC0_WINDOWA_X_CONTROL,
2124 CRTC_CRC0_WINDOWA_X_START);
2125 set_reg_field_value(value, params->windowa_x_end,
2126 CRTC_CRC0_WINDOWA_X_CONTROL,
2127 CRTC_CRC0_WINDOWA_X_END);
2128 dm_write_reg(tg->ctx, addr, value);
2129
2130
2131 value = 0;
2132 addr = CRTC_REG(mmCRTC_CRC0_WINDOWA_Y_CONTROL);
2133 set_reg_field_value(value, params->windowa_y_start,
2134 CRTC_CRC0_WINDOWA_Y_CONTROL,
2135 CRTC_CRC0_WINDOWA_Y_START);
2136 set_reg_field_value(value, params->windowa_y_end,
2137 CRTC_CRC0_WINDOWA_Y_CONTROL,
2138 CRTC_CRC0_WINDOWA_Y_END);
2139 dm_write_reg(tg->ctx, addr, value);
2140
2141
2142 value = 0;
2143 addr = CRTC_REG(mmCRTC_CRC0_WINDOWB_X_CONTROL);
2144 set_reg_field_value(value, params->windowb_x_start,
2145 CRTC_CRC0_WINDOWB_X_CONTROL,
2146 CRTC_CRC0_WINDOWB_X_START);
2147 set_reg_field_value(value, params->windowb_x_end,
2148 CRTC_CRC0_WINDOWB_X_CONTROL,
2149 CRTC_CRC0_WINDOWB_X_END);
2150 dm_write_reg(tg->ctx, addr, value);
2151
2152
2153 value = 0;
2154 addr = CRTC_REG(mmCRTC_CRC0_WINDOWB_Y_CONTROL);
2155 set_reg_field_value(value, params->windowb_y_start,
2156 CRTC_CRC0_WINDOWB_Y_CONTROL,
2157 CRTC_CRC0_WINDOWB_Y_START);
2158 set_reg_field_value(value, params->windowb_y_end,
2159 CRTC_CRC0_WINDOWB_Y_CONTROL,
2160 CRTC_CRC0_WINDOWB_Y_END);
2161 dm_write_reg(tg->ctx, addr, value);
2162
2163
2164 value = 0;
2165 set_reg_field_value(value, params->continuous_mode ? 1 : 0,
2166 CRTC_CRC_CNTL, CRTC_CRC_CONT_EN);
2167 set_reg_field_value(value, params->selection,
2168 CRTC_CRC_CNTL, CRTC_CRC0_SELECT);
2169 set_reg_field_value(value, 1, CRTC_CRC_CNTL, CRTC_CRC_EN);
2170 dm_write_reg(tg->ctx, cntl_addr, value);
2171
2172 return true;
2173 }
2174
2175 bool dce110_get_crc(struct timing_generator *tg,
2176 uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb)
2177 {
2178 uint32_t addr = 0;
2179 uint32_t value = 0;
2180 uint32_t field = 0;
2181 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
2182
2183 addr = CRTC_REG(mmCRTC_CRC_CNTL);
2184 value = dm_read_reg(tg->ctx, addr);
2185 field = get_reg_field_value(value, CRTC_CRC_CNTL, CRTC_CRC_EN);
2186
2187
2188 if (!field)
2189 return false;
2190
2191 addr = CRTC_REG(mmCRTC_CRC0_DATA_RG);
2192 value = dm_read_reg(tg->ctx, addr);
2193 *r_cr = get_reg_field_value(value, CRTC_CRC0_DATA_RG, CRC0_R_CR);
2194 *g_y = get_reg_field_value(value, CRTC_CRC0_DATA_RG, CRC0_G_Y);
2195
2196 addr = CRTC_REG(mmCRTC_CRC0_DATA_B);
2197 value = dm_read_reg(tg->ctx, addr);
2198 *b_cb = get_reg_field_value(value, CRTC_CRC0_DATA_B, CRC0_B_CB);
2199
2200 return true;
2201 }
2202
2203 static const struct timing_generator_funcs dce110_tg_funcs = {
2204 .validate_timing = dce110_tg_validate_timing,
2205 .program_timing = dce110_tg_program_timing,
2206 .enable_crtc = dce110_timing_generator_enable_crtc,
2207 .disable_crtc = dce110_timing_generator_disable_crtc,
2208 .is_counter_moving = dce110_timing_generator_is_counter_moving,
2209 .get_position = dce110_timing_generator_get_position,
2210 .get_frame_count = dce110_timing_generator_get_vblank_counter,
2211 .get_scanoutpos = dce110_timing_generator_get_crtc_scanoutpos,
2212 .set_early_control = dce110_timing_generator_set_early_control,
2213 .wait_for_state = dce110_tg_wait_for_state,
2214 .set_blank = dce110_tg_set_blank,
2215 .is_blanked = dce110_tg_is_blanked,
2216 .set_colors = dce110_tg_set_colors,
2217 .set_overscan_blank_color =
2218 dce110_timing_generator_set_overscan_color_black,
2219 .set_blank_color = dce110_timing_generator_program_blank_color,
2220 .disable_vga = dce110_timing_generator_disable_vga,
2221 .did_triggered_reset_occur =
2222 dce110_timing_generator_did_triggered_reset_occur,
2223 .setup_global_swap_lock =
2224 dce110_timing_generator_setup_global_swap_lock,
2225 .enable_reset_trigger = dce110_timing_generator_enable_reset_trigger,
2226 .enable_crtc_reset = dce110_timing_generator_enable_crtc_reset,
2227 .disable_reset_trigger = dce110_timing_generator_disable_reset_trigger,
2228 .tear_down_global_swap_lock =
2229 dce110_timing_generator_tear_down_global_swap_lock,
2230 .enable_advanced_request =
2231 dce110_timing_generator_enable_advanced_request,
2232 .set_drr =
2233 dce110_timing_generator_set_drr,
2234 .get_last_used_drr_vtotal = NULL,
2235 .set_static_screen_control =
2236 dce110_timing_generator_set_static_screen_control,
2237 .set_test_pattern = dce110_timing_generator_set_test_pattern,
2238 .arm_vert_intr = dce110_arm_vert_intr,
2239 .is_tg_enabled = dce110_is_tg_enabled,
2240 .configure_crc = dce110_configure_crc,
2241 .get_crc = dce110_get_crc,
2242 };
2243
2244 void dce110_timing_generator_construct(
2245 struct dce110_timing_generator *tg110,
2246 struct dc_context *ctx,
2247 uint32_t instance,
2248 const struct dce110_timing_generator_offsets *offsets)
2249 {
2250 tg110->controller_id = CONTROLLER_ID_D0 + instance;
2251 tg110->base.inst = instance;
2252
2253 tg110->offsets = *offsets;
2254
2255 tg110->base.funcs = &dce110_tg_funcs;
2256
2257 tg110->base.ctx = ctx;
2258 tg110->base.bp = ctx->dc_bios;
2259
2260 tg110->max_h_total = CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1;
2261 tg110->max_v_total = CRTC_V_TOTAL__CRTC_V_TOTAL_MASK + 1;
2262
2263 tg110->min_h_blank = 56;
2264 tg110->min_h_front_porch = 4;
2265 tg110->min_h_back_porch = 4;
2266 }