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
0027 #include "reg_helper.h"
0028 #include "dcn10_optc.h"
0029 #include "dc.h"
0030
0031 #define REG(reg)\
0032 optc1->tg_regs->reg
0033
0034 #define CTX \
0035 optc1->base.ctx
0036
0037 #undef FN
0038 #define FN(reg_name, field_name) \
0039 optc1->tg_shift->field_name, optc1->tg_mask->field_name
0040
0041 #define STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN 0x100
0042
0043
0044
0045
0046
0047
0048
0049 static void apply_front_porch_workaround(struct dc_crtc_timing *timing)
0050 {
0051 if (timing->flags.INTERLACE == 1) {
0052 if (timing->v_front_porch < 2)
0053 timing->v_front_porch = 2;
0054 } else {
0055 if (timing->v_front_porch < 1)
0056 timing->v_front_porch = 1;
0057 }
0058 }
0059
0060 void optc1_program_global_sync(
0061 struct timing_generator *optc,
0062 int vready_offset,
0063 int vstartup_start,
0064 int vupdate_offset,
0065 int vupdate_width)
0066 {
0067 struct optc *optc1 = DCN10TG_FROM_TG(optc);
0068
0069 optc1->vready_offset = vready_offset;
0070 optc1->vstartup_start = vstartup_start;
0071 optc1->vupdate_offset = vupdate_offset;
0072 optc1->vupdate_width = vupdate_width;
0073
0074 if (optc1->vstartup_start == 0) {
0075 BREAK_TO_DEBUGGER();
0076 return;
0077 }
0078
0079 REG_SET(OTG_VSTARTUP_PARAM, 0,
0080 VSTARTUP_START, optc1->vstartup_start);
0081
0082 REG_SET_2(OTG_VUPDATE_PARAM, 0,
0083 VUPDATE_OFFSET, optc1->vupdate_offset,
0084 VUPDATE_WIDTH, optc1->vupdate_width);
0085
0086 REG_SET(OTG_VREADY_PARAM, 0,
0087 VREADY_OFFSET, optc1->vready_offset);
0088 }
0089
0090 static void optc1_disable_stereo(struct timing_generator *optc)
0091 {
0092 struct optc *optc1 = DCN10TG_FROM_TG(optc);
0093
0094 REG_SET(OTG_STEREO_CONTROL, 0,
0095 OTG_STEREO_EN, 0);
0096
0097 REG_SET_2(OTG_3D_STRUCTURE_CONTROL, 0,
0098 OTG_3D_STRUCTURE_EN, 0,
0099 OTG_3D_STRUCTURE_STEREO_SEL_OVR, 0);
0100 }
0101
0102 void optc1_setup_vertical_interrupt0(
0103 struct timing_generator *optc,
0104 uint32_t start_line,
0105 uint32_t end_line)
0106 {
0107 struct optc *optc1 = DCN10TG_FROM_TG(optc);
0108
0109 REG_SET_2(OTG_VERTICAL_INTERRUPT0_POSITION, 0,
0110 OTG_VERTICAL_INTERRUPT0_LINE_START, start_line,
0111 OTG_VERTICAL_INTERRUPT0_LINE_END, end_line);
0112 }
0113
0114 void optc1_setup_vertical_interrupt1(
0115 struct timing_generator *optc,
0116 uint32_t start_line)
0117 {
0118 struct optc *optc1 = DCN10TG_FROM_TG(optc);
0119
0120 REG_SET(OTG_VERTICAL_INTERRUPT1_POSITION, 0,
0121 OTG_VERTICAL_INTERRUPT1_LINE_START, start_line);
0122 }
0123
0124 void optc1_setup_vertical_interrupt2(
0125 struct timing_generator *optc,
0126 uint32_t start_line)
0127 {
0128 struct optc *optc1 = DCN10TG_FROM_TG(optc);
0129
0130 REG_SET(OTG_VERTICAL_INTERRUPT2_POSITION, 0,
0131 OTG_VERTICAL_INTERRUPT2_LINE_START, start_line);
0132 }
0133
0134
0135
0136
0137
0138
0139 void optc1_program_timing(
0140 struct timing_generator *optc,
0141 const struct dc_crtc_timing *dc_crtc_timing,
0142 int vready_offset,
0143 int vstartup_start,
0144 int vupdate_offset,
0145 int vupdate_width,
0146 const enum signal_type signal,
0147 bool use_vbios)
0148 {
0149 struct dc_crtc_timing patched_crtc_timing;
0150 uint32_t asic_blank_end;
0151 uint32_t asic_blank_start;
0152 uint32_t v_total;
0153 uint32_t v_sync_end;
0154 uint32_t h_sync_polarity, v_sync_polarity;
0155 uint32_t start_point = 0;
0156 uint32_t field_num = 0;
0157 enum h_timing_div_mode h_div = H_TIMING_NO_DIV;
0158
0159 struct optc *optc1 = DCN10TG_FROM_TG(optc);
0160
0161 optc1->signal = signal;
0162 optc1->vready_offset = vready_offset;
0163 optc1->vstartup_start = vstartup_start;
0164 optc1->vupdate_offset = vupdate_offset;
0165 optc1->vupdate_width = vupdate_width;
0166 patched_crtc_timing = *dc_crtc_timing;
0167 apply_front_porch_workaround(&patched_crtc_timing);
0168 optc1->orginal_patched_timing = patched_crtc_timing;
0169
0170
0171
0172
0173 REG_SET(OTG_H_TOTAL, 0,
0174 OTG_H_TOTAL, patched_crtc_timing.h_total - 1);
0175
0176
0177 REG_UPDATE_2(OTG_H_SYNC_A,
0178 OTG_H_SYNC_A_START, 0,
0179 OTG_H_SYNC_A_END, patched_crtc_timing.h_sync_width);
0180
0181
0182 asic_blank_start = patched_crtc_timing.h_total -
0183 patched_crtc_timing.h_front_porch;
0184
0185
0186 asic_blank_end = asic_blank_start -
0187 patched_crtc_timing.h_border_right -
0188 patched_crtc_timing.h_addressable -
0189 patched_crtc_timing.h_border_left;
0190
0191 REG_UPDATE_2(OTG_H_BLANK_START_END,
0192 OTG_H_BLANK_START, asic_blank_start,
0193 OTG_H_BLANK_END, asic_blank_end);
0194
0195
0196 h_sync_polarity = patched_crtc_timing.flags.HSYNC_POSITIVE_POLARITY ?
0197 0 : 1;
0198
0199 REG_UPDATE(OTG_H_SYNC_A_CNTL,
0200 OTG_H_SYNC_A_POL, h_sync_polarity);
0201
0202 v_total = patched_crtc_timing.v_total - 1;
0203
0204 REG_SET(OTG_V_TOTAL, 0,
0205 OTG_V_TOTAL, v_total);
0206
0207
0208
0209
0210 REG_SET(OTG_V_TOTAL_MAX, 0,
0211 OTG_V_TOTAL_MAX, v_total);
0212 REG_SET(OTG_V_TOTAL_MIN, 0,
0213 OTG_V_TOTAL_MIN, v_total);
0214
0215
0216 v_sync_end = patched_crtc_timing.v_sync_width;
0217
0218 REG_UPDATE_2(OTG_V_SYNC_A,
0219 OTG_V_SYNC_A_START, 0,
0220 OTG_V_SYNC_A_END, v_sync_end);
0221
0222
0223 asic_blank_start = patched_crtc_timing.v_total -
0224 patched_crtc_timing.v_front_porch;
0225
0226
0227 asic_blank_end = asic_blank_start -
0228 patched_crtc_timing.v_border_bottom -
0229 patched_crtc_timing.v_addressable -
0230 patched_crtc_timing.v_border_top;
0231
0232 REG_UPDATE_2(OTG_V_BLANK_START_END,
0233 OTG_V_BLANK_START, asic_blank_start,
0234 OTG_V_BLANK_END, asic_blank_end);
0235
0236
0237 v_sync_polarity = patched_crtc_timing.flags.VSYNC_POSITIVE_POLARITY ?
0238 0 : 1;
0239
0240 REG_UPDATE(OTG_V_SYNC_A_CNTL,
0241 OTG_V_SYNC_A_POL, v_sync_polarity);
0242
0243 if (optc1->signal == SIGNAL_TYPE_DISPLAY_PORT ||
0244 optc1->signal == SIGNAL_TYPE_DISPLAY_PORT_MST ||
0245 optc1->signal == SIGNAL_TYPE_EDP) {
0246 start_point = 1;
0247 if (patched_crtc_timing.flags.INTERLACE == 1)
0248 field_num = 1;
0249 }
0250
0251
0252 if (REG(OTG_INTERLACE_CONTROL)) {
0253 if (patched_crtc_timing.flags.INTERLACE == 1)
0254 REG_UPDATE(OTG_INTERLACE_CONTROL,
0255 OTG_INTERLACE_ENABLE, 1);
0256 else
0257 REG_UPDATE(OTG_INTERLACE_CONTROL,
0258 OTG_INTERLACE_ENABLE, 0);
0259 }
0260
0261
0262 REG_UPDATE(CONTROL,
0263 VTG0_ENABLE, 0);
0264
0265
0266 REG_UPDATE_2(OTG_CONTROL,
0267 OTG_START_POINT_CNTL, start_point,
0268 OTG_FIELD_NUMBER_CNTL, field_num);
0269
0270 optc->funcs->program_global_sync(optc,
0271 vready_offset,
0272 vstartup_start,
0273 vupdate_offset,
0274 vupdate_width);
0275
0276 optc->funcs->set_vtg_params(optc, dc_crtc_timing, true);
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289 if (optc1_is_two_pixels_per_containter(&patched_crtc_timing) || optc1->opp_count == 2)
0290 h_div = H_TIMING_DIV_BY2;
0291
0292 if (REG(OPTC_DATA_FORMAT_CONTROL) && optc1->tg_mask->OPTC_DATA_FORMAT != 0) {
0293 uint32_t data_fmt = 0;
0294
0295 if (patched_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR422)
0296 data_fmt = 1;
0297 else if (patched_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR420)
0298 data_fmt = 2;
0299
0300 REG_UPDATE(OPTC_DATA_FORMAT_CONTROL, OPTC_DATA_FORMAT, data_fmt);
0301 }
0302
0303 if (optc1->tg_mask->OTG_H_TIMING_DIV_MODE != 0) {
0304 if (optc1->opp_count == 4)
0305 h_div = H_TIMING_DIV_BY4;
0306
0307 REG_UPDATE(OTG_H_TIMING_CNTL,
0308 OTG_H_TIMING_DIV_MODE, h_div);
0309 } else {
0310 REG_UPDATE(OTG_H_TIMING_CNTL,
0311 OTG_H_TIMING_DIV_BY2, h_div);
0312 }
0313 }
0314
0315 void optc1_set_vtg_params(struct timing_generator *optc,
0316 const struct dc_crtc_timing *dc_crtc_timing, bool program_fp2)
0317 {
0318 struct dc_crtc_timing patched_crtc_timing;
0319 uint32_t asic_blank_end;
0320 uint32_t v_init;
0321 uint32_t v_fp2 = 0;
0322 int32_t vertical_line_start;
0323
0324 struct optc *optc1 = DCN10TG_FROM_TG(optc);
0325
0326 patched_crtc_timing = *dc_crtc_timing;
0327 apply_front_porch_workaround(&patched_crtc_timing);
0328
0329
0330 v_init = patched_crtc_timing.v_total - patched_crtc_timing.v_front_porch;
0331
0332
0333 asic_blank_end = v_init -
0334 patched_crtc_timing.v_border_bottom -
0335 patched_crtc_timing.v_addressable -
0336 patched_crtc_timing.v_border_top;
0337
0338
0339 vertical_line_start = asic_blank_end - optc1->vstartup_start + 1;
0340 if (vertical_line_start < 0)
0341 v_fp2 = -vertical_line_start;
0342
0343
0344 if (REG(OTG_INTERLACE_CONTROL)) {
0345 if (patched_crtc_timing.flags.INTERLACE == 1) {
0346 v_init = v_init / 2;
0347 if ((optc1->vstartup_start/2)*2 > asic_blank_end)
0348 v_fp2 = v_fp2 / 2;
0349 }
0350 }
0351
0352 if (program_fp2)
0353 REG_UPDATE_2(CONTROL,
0354 VTG0_FP2, v_fp2,
0355 VTG0_VCOUNT_INIT, v_init);
0356 else
0357 REG_UPDATE(CONTROL, VTG0_VCOUNT_INIT, v_init);
0358 }
0359
0360 void optc1_set_blank_data_double_buffer(struct timing_generator *optc, bool enable)
0361 {
0362 struct optc *optc1 = DCN10TG_FROM_TG(optc);
0363
0364 uint32_t blank_data_double_buffer_enable = enable ? 1 : 0;
0365
0366 REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL,
0367 OTG_BLANK_DATA_DOUBLE_BUFFER_EN, blank_data_double_buffer_enable);
0368 }
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378 void optc1_set_timing_double_buffer(struct timing_generator *optc, bool enable)
0379 {
0380 struct optc *optc1 = DCN10TG_FROM_TG(optc);
0381 uint32_t mode = enable ? 2 : 0;
0382
0383 REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL,
0384 OTG_RANGE_TIMING_DBUF_UPDATE_MODE, mode);
0385 }
0386
0387
0388
0389
0390
0391 static void optc1_unblank_crtc(struct timing_generator *optc)
0392 {
0393 struct optc *optc1 = DCN10TG_FROM_TG(optc);
0394
0395 REG_UPDATE_2(OTG_BLANK_CONTROL,
0396 OTG_BLANK_DATA_EN, 0,
0397 OTG_BLANK_DE_MODE, 0);
0398
0399
0400
0401
0402
0403
0404
0405
0406 optc1_clear_optc_underflow(optc);
0407 }
0408
0409
0410
0411
0412
0413
0414 static void optc1_blank_crtc(struct timing_generator *optc)
0415 {
0416 struct optc *optc1 = DCN10TG_FROM_TG(optc);
0417
0418 REG_UPDATE_2(OTG_BLANK_CONTROL,
0419 OTG_BLANK_DATA_EN, 1,
0420 OTG_BLANK_DE_MODE, 0);
0421
0422 optc1_set_blank_data_double_buffer(optc, false);
0423 }
0424
0425 void optc1_set_blank(struct timing_generator *optc,
0426 bool enable_blanking)
0427 {
0428 if (enable_blanking)
0429 optc1_blank_crtc(optc);
0430 else
0431 optc1_unblank_crtc(optc);
0432 }
0433
0434 bool optc1_is_blanked(struct timing_generator *optc)
0435 {
0436 struct optc *optc1 = DCN10TG_FROM_TG(optc);
0437 uint32_t blank_en;
0438 uint32_t blank_state;
0439
0440 REG_GET_2(OTG_BLANK_CONTROL,
0441 OTG_BLANK_DATA_EN, &blank_en,
0442 OTG_CURRENT_BLANK_STATE, &blank_state);
0443
0444 return blank_en && blank_state;
0445 }
0446
0447 void optc1_enable_optc_clock(struct timing_generator *optc, bool enable)
0448 {
0449 struct optc *optc1 = DCN10TG_FROM_TG(optc);
0450
0451 if (enable) {
0452 REG_UPDATE_2(OPTC_INPUT_CLOCK_CONTROL,
0453 OPTC_INPUT_CLK_EN, 1,
0454 OPTC_INPUT_CLK_GATE_DIS, 1);
0455
0456 REG_WAIT(OPTC_INPUT_CLOCK_CONTROL,
0457 OPTC_INPUT_CLK_ON, 1,
0458 1, 1000);
0459
0460
0461 REG_UPDATE_2(OTG_CLOCK_CONTROL,
0462 OTG_CLOCK_EN, 1,
0463 OTG_CLOCK_GATE_DIS, 1);
0464 REG_WAIT(OTG_CLOCK_CONTROL,
0465 OTG_CLOCK_ON, 1,
0466 1, 1000);
0467 } else {
0468
0469
0470 if (optc->funcs->is_optc_underflow_occurred(optc) == true)
0471 optc->funcs->clear_optc_underflow(optc);
0472
0473 REG_UPDATE_2(OTG_CLOCK_CONTROL,
0474 OTG_CLOCK_GATE_DIS, 0,
0475 OTG_CLOCK_EN, 0);
0476
0477 REG_UPDATE_2(OPTC_INPUT_CLOCK_CONTROL,
0478 OPTC_INPUT_CLK_GATE_DIS, 0,
0479 OPTC_INPUT_CLK_EN, 0);
0480 }
0481 }
0482
0483
0484
0485
0486
0487 static bool optc1_enable_crtc(struct timing_generator *optc)
0488 {
0489
0490
0491
0492
0493 struct optc *optc1 = DCN10TG_FROM_TG(optc);
0494
0495
0496
0497
0498 REG_UPDATE(OPTC_DATA_SOURCE_SELECT,
0499 OPTC_SRC_SEL, optc->inst);
0500
0501
0502 REG_UPDATE(CONTROL,
0503 VTG0_ENABLE, 1);
0504
0505 REG_SEQ_START();
0506
0507
0508 REG_UPDATE_2(OTG_CONTROL,
0509 OTG_DISABLE_POINT_CNTL, 3,
0510 OTG_MASTER_EN, 1);
0511
0512 REG_SEQ_SUBMIT();
0513 REG_SEQ_WAIT_DONE();
0514
0515 return true;
0516 }
0517
0518
0519 bool optc1_disable_crtc(struct timing_generator *optc)
0520 {
0521 struct optc *optc1 = DCN10TG_FROM_TG(optc);
0522
0523
0524
0525
0526 REG_UPDATE_2(OTG_CONTROL,
0527 OTG_DISABLE_POINT_CNTL, 3,
0528 OTG_MASTER_EN, 0);
0529
0530 REG_UPDATE(CONTROL,
0531 VTG0_ENABLE, 0);
0532
0533
0534 REG_WAIT(OTG_CLOCK_CONTROL,
0535 OTG_BUSY, 0,
0536 1, 100000);
0537
0538 return true;
0539 }
0540
0541
0542 void optc1_program_blank_color(
0543 struct timing_generator *optc,
0544 const struct tg_color *black_color)
0545 {
0546 struct optc *optc1 = DCN10TG_FROM_TG(optc);
0547
0548 REG_SET_3(OTG_BLACK_COLOR, 0,
0549 OTG_BLACK_COLOR_B_CB, black_color->color_b_cb,
0550 OTG_BLACK_COLOR_G_Y, black_color->color_g_y,
0551 OTG_BLACK_COLOR_R_CR, black_color->color_r_cr);
0552 }
0553
0554 bool optc1_validate_timing(
0555 struct timing_generator *optc,
0556 const struct dc_crtc_timing *timing)
0557 {
0558 uint32_t v_blank;
0559 uint32_t h_blank;
0560 uint32_t min_v_blank;
0561 struct optc *optc1 = DCN10TG_FROM_TG(optc);
0562
0563 ASSERT(timing != NULL);
0564
0565 v_blank = (timing->v_total - timing->v_addressable -
0566 timing->v_border_top - timing->v_border_bottom);
0567
0568 h_blank = (timing->h_total - timing->h_addressable -
0569 timing->h_border_right -
0570 timing->h_border_left);
0571
0572 if (timing->timing_3d_format != TIMING_3D_FORMAT_NONE &&
0573 timing->timing_3d_format != TIMING_3D_FORMAT_HW_FRAME_PACKING &&
0574 timing->timing_3d_format != TIMING_3D_FORMAT_TOP_AND_BOTTOM &&
0575 timing->timing_3d_format != TIMING_3D_FORMAT_SIDE_BY_SIDE &&
0576 timing->timing_3d_format != TIMING_3D_FORMAT_FRAME_ALTERNATE &&
0577 timing->timing_3d_format != TIMING_3D_FORMAT_INBAND_FA)
0578 return false;
0579
0580
0581 if (timing->flags.INTERLACE == 1)
0582 return false;
0583
0584
0585
0586
0587
0588
0589 if (timing->h_total > optc1->max_h_total ||
0590 timing->v_total > optc1->max_v_total)
0591 return false;
0592
0593
0594 if (h_blank < optc1->min_h_blank)
0595 return false;
0596
0597 if (timing->h_sync_width < optc1->min_h_sync_width ||
0598 timing->v_sync_width < optc1->min_v_sync_width)
0599 return false;
0600
0601 min_v_blank = timing->flags.INTERLACE?optc1->min_v_blank_interlace:optc1->min_v_blank;
0602
0603 if (v_blank < min_v_blank)
0604 return false;
0605
0606 return true;
0607
0608 }
0609
0610
0611
0612
0613
0614
0615
0616
0617
0618
0619
0620
0621
0622
0623
0624 uint32_t optc1_get_vblank_counter(struct timing_generator *optc)
0625 {
0626 struct optc *optc1 = DCN10TG_FROM_TG(optc);
0627 uint32_t frame_count;
0628
0629 REG_GET(OTG_STATUS_FRAME_COUNT,
0630 OTG_FRAME_COUNT, &frame_count);
0631
0632 return frame_count;
0633 }
0634
0635 void optc1_lock(struct timing_generator *optc)
0636 {
0637 struct optc *optc1 = DCN10TG_FROM_TG(optc);
0638 uint32_t regval = 0;
0639
0640 regval = REG_READ(OTG_CONTROL);
0641
0642
0643 if ((regval & 0x1) == 0x0)
0644 return;
0645
0646 REG_SET(OTG_GLOBAL_CONTROL0, 0,
0647 OTG_MASTER_UPDATE_LOCK_SEL, optc->inst);
0648 REG_SET(OTG_MASTER_UPDATE_LOCK, 0,
0649 OTG_MASTER_UPDATE_LOCK, 1);
0650
0651
0652 if (optc->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) {
0653
0654 REG_WAIT(OTG_MASTER_UPDATE_LOCK,
0655 UPDATE_LOCK_STATUS, 1,
0656 1, 10);
0657 }
0658 }
0659
0660 void optc1_unlock(struct timing_generator *optc)
0661 {
0662 struct optc *optc1 = DCN10TG_FROM_TG(optc);
0663
0664 REG_SET(OTG_MASTER_UPDATE_LOCK, 0,
0665 OTG_MASTER_UPDATE_LOCK, 0);
0666 }
0667
0668 bool optc1_is_locked(struct timing_generator *optc)
0669 {
0670 struct optc *optc1 = DCN10TG_FROM_TG(optc);
0671 uint32_t locked;
0672
0673 REG_GET(OTG_MASTER_UPDATE_LOCK, UPDATE_LOCK_STATUS, &locked);
0674
0675 return (locked == 1);
0676 }
0677
0678 void optc1_get_position(struct timing_generator *optc,
0679 struct crtc_position *position)
0680 {
0681 struct optc *optc1 = DCN10TG_FROM_TG(optc);
0682
0683 REG_GET_2(OTG_STATUS_POSITION,
0684 OTG_HORZ_COUNT, &position->horizontal_count,
0685 OTG_VERT_COUNT, &position->vertical_count);
0686
0687 REG_GET(OTG_NOM_VERT_POSITION,
0688 OTG_VERT_COUNT_NOM, &position->nominal_vcount);
0689 }
0690
0691 bool optc1_is_counter_moving(struct timing_generator *optc)
0692 {
0693 struct crtc_position position1, position2;
0694
0695 optc->funcs->get_position(optc, &position1);
0696 optc->funcs->get_position(optc, &position2);
0697
0698 if (position1.horizontal_count == position2.horizontal_count &&
0699 position1.vertical_count == position2.vertical_count)
0700 return false;
0701 else
0702 return true;
0703 }
0704
0705 bool optc1_did_triggered_reset_occur(
0706 struct timing_generator *optc)
0707 {
0708 struct optc *optc1 = DCN10TG_FROM_TG(optc);
0709 uint32_t occurred_force, occurred_vsync;
0710
0711 REG_GET(OTG_FORCE_COUNT_NOW_CNTL,
0712 OTG_FORCE_COUNT_NOW_OCCURRED, &occurred_force);
0713
0714 REG_GET(OTG_VERT_SYNC_CONTROL,
0715 OTG_FORCE_VSYNC_NEXT_LINE_OCCURRED, &occurred_vsync);
0716
0717 return occurred_vsync != 0 || occurred_force != 0;
0718 }
0719
0720 void optc1_disable_reset_trigger(struct timing_generator *optc)
0721 {
0722 struct optc *optc1 = DCN10TG_FROM_TG(optc);
0723
0724 REG_WRITE(OTG_TRIGA_CNTL, 0);
0725
0726 REG_SET(OTG_FORCE_COUNT_NOW_CNTL, 0,
0727 OTG_FORCE_COUNT_NOW_CLEAR, 1);
0728
0729 REG_SET(OTG_VERT_SYNC_CONTROL, 0,
0730 OTG_FORCE_VSYNC_NEXT_LINE_CLEAR, 1);
0731 }
0732
0733 void optc1_enable_reset_trigger(struct timing_generator *optc, int source_tg_inst)
0734 {
0735 struct optc *optc1 = DCN10TG_FROM_TG(optc);
0736 uint32_t falling_edge;
0737
0738 REG_GET(OTG_V_SYNC_A_CNTL,
0739 OTG_V_SYNC_A_POL, &falling_edge);
0740
0741 if (falling_edge)
0742 REG_SET_3(OTG_TRIGA_CNTL, 0,
0743
0744
0745
0746 OTG_TRIGA_SOURCE_SELECT, 20,
0747 OTG_TRIGA_SOURCE_PIPE_SELECT, source_tg_inst,
0748
0749 OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, 1);
0750 else
0751 REG_SET_3(OTG_TRIGA_CNTL, 0,
0752
0753
0754
0755 OTG_TRIGA_SOURCE_SELECT, 20,
0756 OTG_TRIGA_SOURCE_PIPE_SELECT, source_tg_inst,
0757
0758 OTG_TRIGA_RISING_EDGE_DETECT_CNTL, 1);
0759
0760 REG_SET(OTG_FORCE_COUNT_NOW_CNTL, 0,
0761
0762
0763
0764 OTG_FORCE_COUNT_NOW_MODE, 2);
0765 }
0766
0767 void optc1_enable_crtc_reset(
0768 struct timing_generator *optc,
0769 int source_tg_inst,
0770 struct crtc_trigger_info *crtc_tp)
0771 {
0772 struct optc *optc1 = DCN10TG_FROM_TG(optc);
0773 uint32_t falling_edge = 0;
0774 uint32_t rising_edge = 0;
0775
0776 switch (crtc_tp->event) {
0777
0778 case CRTC_EVENT_VSYNC_RISING:
0779 rising_edge = 1;
0780 break;
0781
0782 case CRTC_EVENT_VSYNC_FALLING:
0783 falling_edge = 1;
0784 break;
0785 }
0786
0787 REG_SET_4(OTG_TRIGA_CNTL, 0,
0788
0789
0790
0791 OTG_TRIGA_SOURCE_SELECT, 20,
0792 OTG_TRIGA_SOURCE_PIPE_SELECT, source_tg_inst,
0793
0794 OTG_TRIGA_RISING_EDGE_DETECT_CNTL, rising_edge,
0795 OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, falling_edge);
0796
0797 switch (crtc_tp->delay) {
0798 case TRIGGER_DELAY_NEXT_LINE:
0799 REG_SET(OTG_VERT_SYNC_CONTROL, 0,
0800 OTG_AUTO_FORCE_VSYNC_MODE, 1);
0801 break;
0802 case TRIGGER_DELAY_NEXT_PIXEL:
0803 REG_SET(OTG_FORCE_COUNT_NOW_CNTL, 0,
0804
0805
0806
0807 OTG_FORCE_COUNT_NOW_MODE, 2);
0808 break;
0809 }
0810 }
0811
0812 void optc1_wait_for_state(struct timing_generator *optc,
0813 enum crtc_state state)
0814 {
0815 struct optc *optc1 = DCN10TG_FROM_TG(optc);
0816
0817 switch (state) {
0818 case CRTC_STATE_VBLANK:
0819 REG_WAIT(OTG_STATUS,
0820 OTG_V_BLANK, 1,
0821 1, 100000);
0822 break;
0823
0824 case CRTC_STATE_VACTIVE:
0825 REG_WAIT(OTG_STATUS,
0826 OTG_V_ACTIVE_DISP, 1,
0827 1, 100000);
0828 break;
0829
0830 default:
0831 break;
0832 }
0833 }
0834
0835 void optc1_set_early_control(
0836 struct timing_generator *optc,
0837 uint32_t early_cntl)
0838 {
0839
0840
0841
0842 }
0843
0844
0845 void optc1_set_static_screen_control(
0846 struct timing_generator *optc,
0847 uint32_t event_triggers,
0848 uint32_t num_frames)
0849 {
0850 struct optc *optc1 = DCN10TG_FROM_TG(optc);
0851
0852
0853 if (num_frames > 0xFF)
0854 num_frames = 0xFF;
0855
0856
0857
0858
0859 if ((event_triggers & STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN)
0860 != 0)
0861 event_triggers = event_triggers &
0862 ~STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN;
0863
0864 REG_SET_2(OTG_STATIC_SCREEN_CONTROL, 0,
0865 OTG_STATIC_SCREEN_EVENT_MASK, event_triggers,
0866 OTG_STATIC_SCREEN_FRAME_COUNT, num_frames);
0867 }
0868
0869 static void optc1_setup_manual_trigger(struct timing_generator *optc)
0870 {
0871 struct optc *optc1 = DCN10TG_FROM_TG(optc);
0872
0873 REG_SET(OTG_GLOBAL_CONTROL2, 0,
0874 MANUAL_FLOW_CONTROL_SEL, optc->inst);
0875
0876 REG_SET_8(OTG_TRIGA_CNTL, 0,
0877 OTG_TRIGA_SOURCE_SELECT, 22,
0878 OTG_TRIGA_SOURCE_PIPE_SELECT, optc->inst,
0879 OTG_TRIGA_RISING_EDGE_DETECT_CNTL, 1,
0880 OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, 0,
0881 OTG_TRIGA_POLARITY_SELECT, 0,
0882 OTG_TRIGA_FREQUENCY_SELECT, 0,
0883 OTG_TRIGA_DELAY, 0,
0884 OTG_TRIGA_CLEAR, 1);
0885 }
0886
0887 static void optc1_program_manual_trigger(struct timing_generator *optc)
0888 {
0889 struct optc *optc1 = DCN10TG_FROM_TG(optc);
0890
0891 REG_SET(OTG_MANUAL_FLOW_CONTROL, 0,
0892 MANUAL_FLOW_CONTROL, 1);
0893
0894 REG_SET(OTG_MANUAL_FLOW_CONTROL, 0,
0895 MANUAL_FLOW_CONTROL, 0);
0896 }
0897
0898
0899
0900
0901
0902
0903
0904
0905
0906
0907
0908 void optc1_set_drr(
0909 struct timing_generator *optc,
0910 const struct drr_params *params)
0911 {
0912 struct optc *optc1 = DCN10TG_FROM_TG(optc);
0913
0914 if (params != NULL &&
0915 params->vertical_total_max > 0 &&
0916 params->vertical_total_min > 0) {
0917
0918 if (params->vertical_total_mid != 0) {
0919
0920 REG_SET(OTG_V_TOTAL_MID, 0,
0921 OTG_V_TOTAL_MID, params->vertical_total_mid - 1);
0922
0923 REG_UPDATE_2(OTG_V_TOTAL_CONTROL,
0924 OTG_VTOTAL_MID_REPLACING_MAX_EN, 1,
0925 OTG_VTOTAL_MID_FRAME_NUM,
0926 (uint8_t)params->vertical_total_mid_frame_num);
0927
0928 }
0929
0930 REG_SET(OTG_V_TOTAL_MAX, 0,
0931 OTG_V_TOTAL_MAX, params->vertical_total_max - 1);
0932
0933 REG_SET(OTG_V_TOTAL_MIN, 0,
0934 OTG_V_TOTAL_MIN, params->vertical_total_min - 1);
0935
0936 REG_UPDATE_5(OTG_V_TOTAL_CONTROL,
0937 OTG_V_TOTAL_MIN_SEL, 1,
0938 OTG_V_TOTAL_MAX_SEL, 1,
0939 OTG_FORCE_LOCK_ON_EVENT, 0,
0940 OTG_SET_V_TOTAL_MIN_MASK_EN, 0,
0941 OTG_SET_V_TOTAL_MIN_MASK, 0);
0942
0943
0944 optc->funcs->setup_manual_trigger(optc);
0945
0946 } else {
0947 REG_UPDATE_4(OTG_V_TOTAL_CONTROL,
0948 OTG_SET_V_TOTAL_MIN_MASK, 0,
0949 OTG_V_TOTAL_MIN_SEL, 0,
0950 OTG_V_TOTAL_MAX_SEL, 0,
0951 OTG_FORCE_LOCK_ON_EVENT, 0);
0952
0953 REG_SET(OTG_V_TOTAL_MIN, 0,
0954 OTG_V_TOTAL_MIN, 0);
0955
0956 REG_SET(OTG_V_TOTAL_MAX, 0,
0957 OTG_V_TOTAL_MAX, 0);
0958 }
0959 }
0960
0961 void optc1_set_vtotal_min_max(struct timing_generator *optc, int vtotal_min, int vtotal_max)
0962 {
0963 struct optc *optc1 = DCN10TG_FROM_TG(optc);
0964
0965 REG_SET(OTG_V_TOTAL_MAX, 0,
0966 OTG_V_TOTAL_MAX, vtotal_max);
0967
0968 REG_SET(OTG_V_TOTAL_MIN, 0,
0969 OTG_V_TOTAL_MIN, vtotal_min);
0970 }
0971
0972 static void optc1_set_test_pattern(
0973 struct timing_generator *optc,
0974
0975
0976
0977 enum controller_dp_test_pattern test_pattern,
0978 enum dc_color_depth color_depth)
0979 {
0980 struct optc *optc1 = DCN10TG_FROM_TG(optc);
0981 enum test_pattern_color_format bit_depth;
0982 enum test_pattern_dyn_range dyn_range;
0983 enum test_pattern_mode mode;
0984 uint32_t pattern_mask;
0985 uint32_t pattern_data;
0986
0987 uint32_t src_bpc = 16;
0988
0989 uint32_t dst_bpc;
0990 uint32_t index;
0991
0992
0993
0994
0995
0996 uint16_t src_color[6] = {0xFFFF, 0xFFFF, 0xFFFF, 0x0000,
0997 0x0000, 0x0000};
0998
0999 uint16_t dst_color[6];
1000 uint32_t inc_base;
1001
1002
1003 switch (color_depth) {
1004 case COLOR_DEPTH_666:
1005 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_6;
1006 break;
1007 case COLOR_DEPTH_888:
1008 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
1009 break;
1010 case COLOR_DEPTH_101010:
1011 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_10;
1012 break;
1013 case COLOR_DEPTH_121212:
1014 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_12;
1015 break;
1016 default:
1017 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
1018 break;
1019 }
1020
1021 switch (test_pattern) {
1022 case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES:
1023 case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA:
1024 {
1025 dyn_range = (test_pattern ==
1026 CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA ?
1027 TEST_PATTERN_DYN_RANGE_CEA :
1028 TEST_PATTERN_DYN_RANGE_VESA);
1029 mode = TEST_PATTERN_MODE_COLORSQUARES_RGB;
1030
1031 REG_UPDATE_2(OTG_TEST_PATTERN_PARAMETERS,
1032 OTG_TEST_PATTERN_VRES, 6,
1033 OTG_TEST_PATTERN_HRES, 6);
1034
1035 REG_UPDATE_4(OTG_TEST_PATTERN_CONTROL,
1036 OTG_TEST_PATTERN_EN, 1,
1037 OTG_TEST_PATTERN_MODE, mode,
1038 OTG_TEST_PATTERN_DYNAMIC_RANGE, dyn_range,
1039 OTG_TEST_PATTERN_COLOR_FORMAT, bit_depth);
1040 }
1041 break;
1042
1043 case CONTROLLER_DP_TEST_PATTERN_VERTICALBARS:
1044 case CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS:
1045 {
1046 mode = (test_pattern ==
1047 CONTROLLER_DP_TEST_PATTERN_VERTICALBARS ?
1048 TEST_PATTERN_MODE_VERTICALBARS :
1049 TEST_PATTERN_MODE_HORIZONTALBARS);
1050
1051 switch (bit_depth) {
1052 case TEST_PATTERN_COLOR_FORMAT_BPC_6:
1053 dst_bpc = 6;
1054 break;
1055 case TEST_PATTERN_COLOR_FORMAT_BPC_8:
1056 dst_bpc = 8;
1057 break;
1058 case TEST_PATTERN_COLOR_FORMAT_BPC_10:
1059 dst_bpc = 10;
1060 break;
1061 default:
1062 dst_bpc = 8;
1063 break;
1064 }
1065
1066
1067 for (index = 0; index < 6; index++) {
1068
1069
1070
1071 dst_color[index] =
1072 src_color[index] >> (src_bpc - dst_bpc);
1073
1074
1075
1076
1077
1078
1079 dst_color[index] <<= (16 - dst_bpc);
1080 }
1081
1082 REG_WRITE(OTG_TEST_PATTERN_PARAMETERS, 0);
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110 pattern_data = 0;
1111 for (index = 0; index < 6; index++) {
1112
1113
1114
1115 pattern_mask = (1 << index);
1116
1117
1118 REG_SET_2(OTG_TEST_PATTERN_COLOR, 0,
1119 OTG_TEST_PATTERN_MASK, pattern_mask,
1120 OTG_TEST_PATTERN_DATA, pattern_data);
1121
1122
1123
1124
1125 pattern_data = dst_color[index];
1126 }
1127
1128
1129
1130 REG_SET_2(OTG_TEST_PATTERN_COLOR, 0,
1131 OTG_TEST_PATTERN_MASK, pattern_mask,
1132 OTG_TEST_PATTERN_DATA, pattern_data);
1133
1134
1135 REG_UPDATE_4(OTG_TEST_PATTERN_CONTROL,
1136 OTG_TEST_PATTERN_EN, 1,
1137 OTG_TEST_PATTERN_MODE, mode,
1138 OTG_TEST_PATTERN_DYNAMIC_RANGE, 0,
1139 OTG_TEST_PATTERN_COLOR_FORMAT, bit_depth);
1140 }
1141 break;
1142
1143 case CONTROLLER_DP_TEST_PATTERN_COLORRAMP:
1144 {
1145 mode = (bit_depth ==
1146 TEST_PATTERN_COLOR_FORMAT_BPC_10 ?
1147 TEST_PATTERN_MODE_DUALRAMP_RGB :
1148 TEST_PATTERN_MODE_SINGLERAMP_RGB);
1149
1150 switch (bit_depth) {
1151 case TEST_PATTERN_COLOR_FORMAT_BPC_6:
1152 dst_bpc = 6;
1153 break;
1154 case TEST_PATTERN_COLOR_FORMAT_BPC_8:
1155 dst_bpc = 8;
1156 break;
1157 case TEST_PATTERN_COLOR_FORMAT_BPC_10:
1158 dst_bpc = 10;
1159 break;
1160 default:
1161 dst_bpc = 8;
1162 break;
1163 }
1164
1165
1166
1167
1168
1169 inc_base = (src_bpc - dst_bpc);
1170
1171 switch (bit_depth) {
1172 case TEST_PATTERN_COLOR_FORMAT_BPC_6:
1173 {
1174 REG_UPDATE_5(OTG_TEST_PATTERN_PARAMETERS,
1175 OTG_TEST_PATTERN_INC0, inc_base,
1176 OTG_TEST_PATTERN_INC1, 0,
1177 OTG_TEST_PATTERN_HRES, 6,
1178 OTG_TEST_PATTERN_VRES, 6,
1179 OTG_TEST_PATTERN_RAMP0_OFFSET, 0);
1180 }
1181 break;
1182 case TEST_PATTERN_COLOR_FORMAT_BPC_8:
1183 {
1184 REG_UPDATE_5(OTG_TEST_PATTERN_PARAMETERS,
1185 OTG_TEST_PATTERN_INC0, inc_base,
1186 OTG_TEST_PATTERN_INC1, 0,
1187 OTG_TEST_PATTERN_HRES, 8,
1188 OTG_TEST_PATTERN_VRES, 6,
1189 OTG_TEST_PATTERN_RAMP0_OFFSET, 0);
1190 }
1191 break;
1192 case TEST_PATTERN_COLOR_FORMAT_BPC_10:
1193 {
1194 REG_UPDATE_5(OTG_TEST_PATTERN_PARAMETERS,
1195 OTG_TEST_PATTERN_INC0, inc_base,
1196 OTG_TEST_PATTERN_INC1, inc_base + 2,
1197 OTG_TEST_PATTERN_HRES, 8,
1198 OTG_TEST_PATTERN_VRES, 5,
1199 OTG_TEST_PATTERN_RAMP0_OFFSET, 384 << 6);
1200 }
1201 break;
1202 default:
1203 break;
1204 }
1205
1206 REG_WRITE(OTG_TEST_PATTERN_COLOR, 0);
1207
1208
1209 REG_WRITE(OTG_TEST_PATTERN_CONTROL, 0);
1210
1211 REG_SET_4(OTG_TEST_PATTERN_CONTROL, 0,
1212 OTG_TEST_PATTERN_EN, 1,
1213 OTG_TEST_PATTERN_MODE, mode,
1214 OTG_TEST_PATTERN_DYNAMIC_RANGE, 0,
1215 OTG_TEST_PATTERN_COLOR_FORMAT, bit_depth);
1216 }
1217 break;
1218 case CONTROLLER_DP_TEST_PATTERN_VIDEOMODE:
1219 {
1220 REG_WRITE(OTG_TEST_PATTERN_CONTROL, 0);
1221 REG_WRITE(OTG_TEST_PATTERN_COLOR, 0);
1222 REG_WRITE(OTG_TEST_PATTERN_PARAMETERS, 0);
1223 }
1224 break;
1225 default:
1226 break;
1227
1228 }
1229 }
1230
1231 void optc1_get_crtc_scanoutpos(
1232 struct timing_generator *optc,
1233 uint32_t *v_blank_start,
1234 uint32_t *v_blank_end,
1235 uint32_t *h_position,
1236 uint32_t *v_position)
1237 {
1238 struct optc *optc1 = DCN10TG_FROM_TG(optc);
1239 struct crtc_position position;
1240
1241 REG_GET_2(OTG_V_BLANK_START_END,
1242 OTG_V_BLANK_START, v_blank_start,
1243 OTG_V_BLANK_END, v_blank_end);
1244
1245 optc1_get_position(optc, &position);
1246
1247 *h_position = position.horizontal_count;
1248 *v_position = position.vertical_count;
1249 }
1250
1251 static void optc1_enable_stereo(struct timing_generator *optc,
1252 const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags)
1253 {
1254 struct optc *optc1 = DCN10TG_FROM_TG(optc);
1255
1256 if (flags) {
1257 uint32_t stereo_en;
1258 stereo_en = flags->FRAME_PACKED == 0 ? 1 : 0;
1259
1260 if (flags->PROGRAM_STEREO)
1261 REG_UPDATE_3(OTG_STEREO_CONTROL,
1262 OTG_STEREO_EN, stereo_en,
1263 OTG_STEREO_SYNC_OUTPUT_LINE_NUM, 0,
1264 OTG_STEREO_SYNC_OUTPUT_POLARITY, flags->RIGHT_EYE_POLARITY == 0 ? 0 : 1);
1265
1266 if (flags->PROGRAM_POLARITY)
1267 REG_UPDATE(OTG_STEREO_CONTROL,
1268 OTG_STEREO_EYE_FLAG_POLARITY,
1269 flags->RIGHT_EYE_POLARITY == 0 ? 0 : 1);
1270
1271 if (flags->DISABLE_STEREO_DP_SYNC)
1272 REG_UPDATE(OTG_STEREO_CONTROL,
1273 OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, 1);
1274
1275 if (flags->PROGRAM_STEREO)
1276 REG_UPDATE_2(OTG_3D_STRUCTURE_CONTROL,
1277 OTG_3D_STRUCTURE_EN, flags->FRAME_PACKED,
1278 OTG_3D_STRUCTURE_STEREO_SEL_OVR, flags->FRAME_PACKED);
1279
1280 }
1281 }
1282
1283 void optc1_program_stereo(struct timing_generator *optc,
1284 const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags)
1285 {
1286 if (flags->PROGRAM_STEREO)
1287 optc1_enable_stereo(optc, timing, flags);
1288 else
1289 optc1_disable_stereo(optc);
1290 }
1291
1292
1293 bool optc1_is_stereo_left_eye(struct timing_generator *optc)
1294 {
1295 bool ret = false;
1296 uint32_t left_eye = 0;
1297 struct optc *optc1 = DCN10TG_FROM_TG(optc);
1298
1299 REG_GET(OTG_STEREO_STATUS,
1300 OTG_STEREO_CURRENT_EYE, &left_eye);
1301 if (left_eye == 1)
1302 ret = true;
1303 else
1304 ret = false;
1305
1306 return ret;
1307 }
1308
1309 bool optc1_get_hw_timing(struct timing_generator *tg,
1310 struct dc_crtc_timing *hw_crtc_timing)
1311 {
1312 struct dcn_otg_state s = {0};
1313
1314 if (tg == NULL || hw_crtc_timing == NULL)
1315 return false;
1316
1317 optc1_read_otg_state(DCN10TG_FROM_TG(tg), &s);
1318
1319 hw_crtc_timing->h_total = s.h_total + 1;
1320 hw_crtc_timing->h_addressable = s.h_total - ((s.h_total - s.h_blank_start) + s.h_blank_end);
1321 hw_crtc_timing->h_front_porch = s.h_total + 1 - s.h_blank_start;
1322 hw_crtc_timing->h_sync_width = s.h_sync_a_end - s.h_sync_a_start;
1323
1324 hw_crtc_timing->v_total = s.v_total + 1;
1325 hw_crtc_timing->v_addressable = s.v_total - ((s.v_total - s.v_blank_start) + s.v_blank_end);
1326 hw_crtc_timing->v_front_porch = s.v_total + 1 - s.v_blank_start;
1327 hw_crtc_timing->v_sync_width = s.v_sync_a_end - s.v_sync_a_start;
1328
1329 return true;
1330 }
1331
1332
1333 void optc1_read_otg_state(struct optc *optc1,
1334 struct dcn_otg_state *s)
1335 {
1336 REG_GET(OTG_CONTROL,
1337 OTG_MASTER_EN, &s->otg_enabled);
1338
1339 REG_GET_2(OTG_V_BLANK_START_END,
1340 OTG_V_BLANK_START, &s->v_blank_start,
1341 OTG_V_BLANK_END, &s->v_blank_end);
1342
1343 REG_GET(OTG_V_SYNC_A_CNTL,
1344 OTG_V_SYNC_A_POL, &s->v_sync_a_pol);
1345
1346 REG_GET(OTG_V_TOTAL,
1347 OTG_V_TOTAL, &s->v_total);
1348
1349 REG_GET(OTG_V_TOTAL_MAX,
1350 OTG_V_TOTAL_MAX, &s->v_total_max);
1351
1352 REG_GET(OTG_V_TOTAL_MIN,
1353 OTG_V_TOTAL_MIN, &s->v_total_min);
1354
1355 REG_GET(OTG_V_TOTAL_CONTROL,
1356 OTG_V_TOTAL_MAX_SEL, &s->v_total_max_sel);
1357
1358 REG_GET(OTG_V_TOTAL_CONTROL,
1359 OTG_V_TOTAL_MIN_SEL, &s->v_total_min_sel);
1360
1361 REG_GET_2(OTG_V_SYNC_A,
1362 OTG_V_SYNC_A_START, &s->v_sync_a_start,
1363 OTG_V_SYNC_A_END, &s->v_sync_a_end);
1364
1365 REG_GET_2(OTG_H_BLANK_START_END,
1366 OTG_H_BLANK_START, &s->h_blank_start,
1367 OTG_H_BLANK_END, &s->h_blank_end);
1368
1369 REG_GET_2(OTG_H_SYNC_A,
1370 OTG_H_SYNC_A_START, &s->h_sync_a_start,
1371 OTG_H_SYNC_A_END, &s->h_sync_a_end);
1372
1373 REG_GET(OTG_H_SYNC_A_CNTL,
1374 OTG_H_SYNC_A_POL, &s->h_sync_a_pol);
1375
1376 REG_GET(OTG_H_TOTAL,
1377 OTG_H_TOTAL, &s->h_total);
1378
1379 REG_GET(OPTC_INPUT_GLOBAL_CONTROL,
1380 OPTC_UNDERFLOW_OCCURRED_STATUS, &s->underflow_occurred_status);
1381
1382 REG_GET(OTG_VERTICAL_INTERRUPT2_CONTROL,
1383 OTG_VERTICAL_INTERRUPT2_INT_ENABLE, &s->vertical_interrupt2_en);
1384
1385 REG_GET(OTG_VERTICAL_INTERRUPT2_POSITION,
1386 OTG_VERTICAL_INTERRUPT2_LINE_START, &s->vertical_interrupt2_line);
1387 }
1388
1389 bool optc1_get_otg_active_size(struct timing_generator *optc,
1390 uint32_t *otg_active_width,
1391 uint32_t *otg_active_height)
1392 {
1393 uint32_t otg_enabled;
1394 uint32_t v_blank_start;
1395 uint32_t v_blank_end;
1396 uint32_t h_blank_start;
1397 uint32_t h_blank_end;
1398 struct optc *optc1 = DCN10TG_FROM_TG(optc);
1399
1400
1401 REG_GET(OTG_CONTROL,
1402 OTG_MASTER_EN, &otg_enabled);
1403
1404 if (otg_enabled == 0)
1405 return false;
1406
1407 REG_GET_2(OTG_V_BLANK_START_END,
1408 OTG_V_BLANK_START, &v_blank_start,
1409 OTG_V_BLANK_END, &v_blank_end);
1410
1411 REG_GET_2(OTG_H_BLANK_START_END,
1412 OTG_H_BLANK_START, &h_blank_start,
1413 OTG_H_BLANK_END, &h_blank_end);
1414
1415 *otg_active_width = v_blank_start - v_blank_end;
1416 *otg_active_height = h_blank_start - h_blank_end;
1417 return true;
1418 }
1419
1420 void optc1_clear_optc_underflow(struct timing_generator *optc)
1421 {
1422 struct optc *optc1 = DCN10TG_FROM_TG(optc);
1423
1424 REG_UPDATE(OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_CLEAR, 1);
1425 }
1426
1427 void optc1_tg_init(struct timing_generator *optc)
1428 {
1429 optc1_set_blank_data_double_buffer(optc, true);
1430 optc1_set_timing_double_buffer(optc, true);
1431 optc1_clear_optc_underflow(optc);
1432 }
1433
1434 bool optc1_is_tg_enabled(struct timing_generator *optc)
1435 {
1436 struct optc *optc1 = DCN10TG_FROM_TG(optc);
1437 uint32_t otg_enabled = 0;
1438
1439 REG_GET(OTG_CONTROL, OTG_MASTER_EN, &otg_enabled);
1440
1441 return (otg_enabled != 0);
1442
1443 }
1444
1445 bool optc1_is_optc_underflow_occurred(struct timing_generator *optc)
1446 {
1447 struct optc *optc1 = DCN10TG_FROM_TG(optc);
1448 uint32_t underflow_occurred = 0;
1449
1450 REG_GET(OPTC_INPUT_GLOBAL_CONTROL,
1451 OPTC_UNDERFLOW_OCCURRED_STATUS,
1452 &underflow_occurred);
1453
1454 return (underflow_occurred == 1);
1455 }
1456
1457 bool optc1_configure_crc(struct timing_generator *optc,
1458 const struct crc_params *params)
1459 {
1460 struct optc *optc1 = DCN10TG_FROM_TG(optc);
1461
1462
1463 if (!optc1_is_tg_enabled(optc))
1464 return false;
1465
1466 REG_WRITE(OTG_CRC_CNTL, 0);
1467
1468 if (!params->enable)
1469 return true;
1470
1471
1472
1473 REG_UPDATE_2(OTG_CRC0_WINDOWA_X_CONTROL,
1474 OTG_CRC0_WINDOWA_X_START, params->windowa_x_start,
1475 OTG_CRC0_WINDOWA_X_END, params->windowa_x_end);
1476
1477
1478 REG_UPDATE_2(OTG_CRC0_WINDOWA_Y_CONTROL,
1479 OTG_CRC0_WINDOWA_Y_START, params->windowa_y_start,
1480 OTG_CRC0_WINDOWA_Y_END, params->windowa_y_end);
1481
1482
1483 REG_UPDATE_2(OTG_CRC0_WINDOWB_X_CONTROL,
1484 OTG_CRC0_WINDOWB_X_START, params->windowb_x_start,
1485 OTG_CRC0_WINDOWB_X_END, params->windowb_x_end);
1486
1487
1488 REG_UPDATE_2(OTG_CRC0_WINDOWB_Y_CONTROL,
1489 OTG_CRC0_WINDOWB_Y_START, params->windowb_y_start,
1490 OTG_CRC0_WINDOWB_Y_END, params->windowb_y_end);
1491
1492
1493 REG_UPDATE_3(OTG_CRC_CNTL,
1494 OTG_CRC_CONT_EN, params->continuous_mode ? 1 : 0,
1495 OTG_CRC0_SELECT, params->selection,
1496 OTG_CRC_EN, 1);
1497
1498 return true;
1499 }
1500
1501 bool optc1_get_crc(struct timing_generator *optc,
1502 uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb)
1503 {
1504 uint32_t field = 0;
1505 struct optc *optc1 = DCN10TG_FROM_TG(optc);
1506
1507 REG_GET(OTG_CRC_CNTL, OTG_CRC_EN, &field);
1508
1509
1510 if (!field)
1511 return false;
1512
1513 REG_GET_2(OTG_CRC0_DATA_RG,
1514 CRC0_R_CR, r_cr,
1515 CRC0_G_Y, g_y);
1516
1517 REG_GET(OTG_CRC0_DATA_B,
1518 CRC0_B_CB, b_cb);
1519
1520 return true;
1521 }
1522
1523 static const struct timing_generator_funcs dcn10_tg_funcs = {
1524 .validate_timing = optc1_validate_timing,
1525 .program_timing = optc1_program_timing,
1526 .setup_vertical_interrupt0 = optc1_setup_vertical_interrupt0,
1527 .setup_vertical_interrupt1 = optc1_setup_vertical_interrupt1,
1528 .setup_vertical_interrupt2 = optc1_setup_vertical_interrupt2,
1529 .program_global_sync = optc1_program_global_sync,
1530 .enable_crtc = optc1_enable_crtc,
1531 .disable_crtc = optc1_disable_crtc,
1532
1533 .is_counter_moving = optc1_is_counter_moving,
1534 .get_position = optc1_get_position,
1535 .get_frame_count = optc1_get_vblank_counter,
1536 .get_scanoutpos = optc1_get_crtc_scanoutpos,
1537 .get_otg_active_size = optc1_get_otg_active_size,
1538 .set_early_control = optc1_set_early_control,
1539
1540 .wait_for_state = optc1_wait_for_state,
1541 .set_blank = optc1_set_blank,
1542 .is_blanked = optc1_is_blanked,
1543 .set_blank_color = optc1_program_blank_color,
1544 .did_triggered_reset_occur = optc1_did_triggered_reset_occur,
1545 .enable_reset_trigger = optc1_enable_reset_trigger,
1546 .enable_crtc_reset = optc1_enable_crtc_reset,
1547 .disable_reset_trigger = optc1_disable_reset_trigger,
1548 .lock = optc1_lock,
1549 .is_locked = optc1_is_locked,
1550 .unlock = optc1_unlock,
1551 .enable_optc_clock = optc1_enable_optc_clock,
1552 .set_drr = optc1_set_drr,
1553 .get_last_used_drr_vtotal = NULL,
1554 .set_static_screen_control = optc1_set_static_screen_control,
1555 .set_test_pattern = optc1_set_test_pattern,
1556 .program_stereo = optc1_program_stereo,
1557 .is_stereo_left_eye = optc1_is_stereo_left_eye,
1558 .set_blank_data_double_buffer = optc1_set_blank_data_double_buffer,
1559 .tg_init = optc1_tg_init,
1560 .is_tg_enabled = optc1_is_tg_enabled,
1561 .is_optc_underflow_occurred = optc1_is_optc_underflow_occurred,
1562 .clear_optc_underflow = optc1_clear_optc_underflow,
1563 .get_crc = optc1_get_crc,
1564 .configure_crc = optc1_configure_crc,
1565 .set_vtg_params = optc1_set_vtg_params,
1566 .program_manual_trigger = optc1_program_manual_trigger,
1567 .setup_manual_trigger = optc1_setup_manual_trigger,
1568 .get_hw_timing = optc1_get_hw_timing,
1569 };
1570
1571 void dcn10_timing_generator_init(struct optc *optc1)
1572 {
1573 optc1->base.funcs = &dcn10_tg_funcs;
1574
1575 optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1;
1576 optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1;
1577
1578 optc1->min_h_blank = 32;
1579 optc1->min_v_blank = 3;
1580 optc1->min_v_blank_interlace = 5;
1581 optc1->min_h_sync_width = 4;
1582 optc1->min_v_sync_width = 1;
1583 }
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597 bool optc1_is_two_pixels_per_containter(const struct dc_crtc_timing *timing)
1598 {
1599 bool two_pix = timing->pixel_encoding == PIXEL_ENCODING_YCBCR420;
1600
1601 two_pix = two_pix || (timing->flags.DSC && timing->pixel_encoding == PIXEL_ENCODING_YCBCR422
1602 && !timing->dsc_cfg.ycbcr422_simple);
1603 return two_pix;
1604 }
1605