1 /* 2 * Copyright 2012-15 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * Authors: AMD 23 * 24 */ 25 26 27 #include "reg_helper.h" 28 #include "dcn10_optc.h" 29 #include "dc.h" 30 31 #define REG(reg)\ 32 optc1->tg_regs->reg 33 34 #define CTX \ 35 optc1->base.ctx 36 37 #undef FN 38 #define FN(reg_name, field_name) \ 39 optc1->tg_shift->field_name, optc1->tg_mask->field_name 40 41 #define STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN 0x100 42 43 /** 44 * apply_front_porch_workaround TODO FPGA still need? 45 * 46 * This is a workaround for a bug that has existed since R5xx and has not been 47 * fixed keep Front porch at minimum 2 for Interlaced mode or 1 for progressive. 48 */ 49 static void optc1_apply_front_porch_workaround( 50 struct timing_generator *optc, 51 struct dc_crtc_timing *timing) 52 { 53 if (timing->flags.INTERLACE == 1) { 54 if (timing->v_front_porch < 2) 55 timing->v_front_porch = 2; 56 } else { 57 if (timing->v_front_porch < 1) 58 timing->v_front_porch = 1; 59 } 60 } 61 62 void optc1_program_global_sync( 63 struct timing_generator *optc) 64 { 65 struct optc *optc1 = DCN10TG_FROM_TG(optc); 66 67 if (optc->dlg_otg_param.vstartup_start == 0) { 68 BREAK_TO_DEBUGGER(); 69 return; 70 } 71 72 REG_SET(OTG_VSTARTUP_PARAM, 0, 73 VSTARTUP_START, optc->dlg_otg_param.vstartup_start); 74 75 REG_SET_2(OTG_VUPDATE_PARAM, 0, 76 VUPDATE_OFFSET, optc->dlg_otg_param.vupdate_offset, 77 VUPDATE_WIDTH, optc->dlg_otg_param.vupdate_width); 78 79 REG_SET(OTG_VREADY_PARAM, 0, 80 VREADY_OFFSET, optc->dlg_otg_param.vready_offset); 81 } 82 83 static void optc1_disable_stereo(struct timing_generator *optc) 84 { 85 struct optc *optc1 = DCN10TG_FROM_TG(optc); 86 87 REG_SET(OTG_STEREO_CONTROL, 0, 88 OTG_STEREO_EN, 0); 89 90 REG_SET_3(OTG_3D_STRUCTURE_CONTROL, 0, 91 OTG_3D_STRUCTURE_EN, 0, 92 OTG_3D_STRUCTURE_V_UPDATE_MODE, 0, 93 OTG_3D_STRUCTURE_STEREO_SEL_OVR, 0); 94 } 95 96 /** 97 * program_timing_generator used by mode timing set 98 * Program CRTC Timing Registers - OTG_H_*, OTG_V_*, Pixel repetition. 99 * Including SYNC. Call BIOS command table to program Timings. 100 */ 101 void optc1_program_timing( 102 struct timing_generator *optc, 103 const struct dc_crtc_timing *dc_crtc_timing, 104 bool use_vbios) 105 { 106 struct dc_crtc_timing patched_crtc_timing; 107 uint32_t vesa_sync_start; 108 uint32_t asic_blank_end; 109 uint32_t asic_blank_start; 110 uint32_t v_total; 111 uint32_t v_sync_end; 112 uint32_t v_init, v_fp2; 113 uint32_t h_sync_polarity, v_sync_polarity; 114 uint32_t interlace_factor; 115 uint32_t start_point = 0; 116 uint32_t field_num = 0; 117 uint32_t h_div_2; 118 int32_t vertical_line_start; 119 120 struct optc *optc1 = DCN10TG_FROM_TG(optc); 121 122 patched_crtc_timing = *dc_crtc_timing; 123 optc1_apply_front_porch_workaround(optc, &patched_crtc_timing); 124 125 /* Load horizontal timing */ 126 127 /* CRTC_H_TOTAL = vesa.h_total - 1 */ 128 REG_SET(OTG_H_TOTAL, 0, 129 OTG_H_TOTAL, patched_crtc_timing.h_total - 1); 130 131 /* h_sync_start = 0, h_sync_end = vesa.h_sync_width */ 132 REG_UPDATE_2(OTG_H_SYNC_A, 133 OTG_H_SYNC_A_START, 0, 134 OTG_H_SYNC_A_END, patched_crtc_timing.h_sync_width); 135 136 /* asic_h_blank_end = HsyncWidth + HbackPorch = 137 * vesa. usHorizontalTotal - vesa. usHorizontalSyncStart - 138 * vesa.h_left_border 139 */ 140 vesa_sync_start = patched_crtc_timing.h_addressable + 141 patched_crtc_timing.h_border_right + 142 patched_crtc_timing.h_front_porch; 143 144 asic_blank_end = patched_crtc_timing.h_total - 145 vesa_sync_start - 146 patched_crtc_timing.h_border_left; 147 148 /* h_blank_start = v_blank_end + v_active */ 149 asic_blank_start = asic_blank_end + 150 patched_crtc_timing.h_border_left + 151 patched_crtc_timing.h_addressable + 152 patched_crtc_timing.h_border_right; 153 154 REG_UPDATE_2(OTG_H_BLANK_START_END, 155 OTG_H_BLANK_START, asic_blank_start, 156 OTG_H_BLANK_END, asic_blank_end); 157 158 /* h_sync polarity */ 159 h_sync_polarity = patched_crtc_timing.flags.HSYNC_POSITIVE_POLARITY ? 160 0 : 1; 161 162 REG_UPDATE(OTG_H_SYNC_A_CNTL, 163 OTG_H_SYNC_A_POL, h_sync_polarity); 164 165 /* Load vertical timing */ 166 167 /* CRTC_V_TOTAL = v_total - 1 */ 168 if (patched_crtc_timing.flags.INTERLACE) { 169 interlace_factor = 2; 170 v_total = 2 * patched_crtc_timing.v_total; 171 } else { 172 interlace_factor = 1; 173 v_total = patched_crtc_timing.v_total - 1; 174 } 175 REG_SET(OTG_V_TOTAL, 0, 176 OTG_V_TOTAL, v_total); 177 178 /* In case of V_TOTAL_CONTROL is on, make sure OTG_V_TOTAL_MAX and 179 * OTG_V_TOTAL_MIN are equal to V_TOTAL. 180 */ 181 REG_SET(OTG_V_TOTAL_MAX, 0, 182 OTG_V_TOTAL_MAX, v_total); 183 REG_SET(OTG_V_TOTAL_MIN, 0, 184 OTG_V_TOTAL_MIN, v_total); 185 186 /* v_sync_start = 0, v_sync_end = v_sync_width */ 187 v_sync_end = patched_crtc_timing.v_sync_width * interlace_factor; 188 189 REG_UPDATE_2(OTG_V_SYNC_A, 190 OTG_V_SYNC_A_START, 0, 191 OTG_V_SYNC_A_END, v_sync_end); 192 193 vesa_sync_start = patched_crtc_timing.v_addressable + 194 patched_crtc_timing.v_border_bottom + 195 patched_crtc_timing.v_front_porch; 196 197 asic_blank_end = (patched_crtc_timing.v_total - 198 vesa_sync_start - 199 patched_crtc_timing.v_border_top) 200 * interlace_factor; 201 202 /* v_blank_start = v_blank_end + v_active */ 203 asic_blank_start = asic_blank_end + 204 (patched_crtc_timing.v_border_top + 205 patched_crtc_timing.v_addressable + 206 patched_crtc_timing.v_border_bottom) 207 * interlace_factor; 208 209 REG_UPDATE_2(OTG_V_BLANK_START_END, 210 OTG_V_BLANK_START, asic_blank_start, 211 OTG_V_BLANK_END, asic_blank_end); 212 213 /* Use OTG_VERTICAL_INTERRUPT2 replace VUPDATE interrupt, 214 * program the reg for interrupt postition. 215 */ 216 vertical_line_start = asic_blank_end - optc->dlg_otg_param.vstartup_start + 1; 217 if (vertical_line_start < 0) { 218 ASSERT(0); 219 vertical_line_start = 0; 220 } 221 REG_SET(OTG_VERTICAL_INTERRUPT2_POSITION, 0, 222 OTG_VERTICAL_INTERRUPT2_LINE_START, vertical_line_start); 223 224 /* v_sync polarity */ 225 v_sync_polarity = patched_crtc_timing.flags.VSYNC_POSITIVE_POLARITY ? 226 0 : 1; 227 228 REG_UPDATE(OTG_V_SYNC_A_CNTL, 229 OTG_V_SYNC_A_POL, v_sync_polarity); 230 231 v_init = asic_blank_start; 232 if (optc->dlg_otg_param.signal == SIGNAL_TYPE_DISPLAY_PORT || 233 optc->dlg_otg_param.signal == SIGNAL_TYPE_DISPLAY_PORT_MST || 234 optc->dlg_otg_param.signal == SIGNAL_TYPE_EDP) { 235 start_point = 1; 236 if (patched_crtc_timing.flags.INTERLACE == 1) 237 field_num = 1; 238 } 239 v_fp2 = 0; 240 if (optc->dlg_otg_param.vstartup_start > asic_blank_end) 241 v_fp2 = optc->dlg_otg_param.vstartup_start > asic_blank_end; 242 243 /* Interlace */ 244 if (patched_crtc_timing.flags.INTERLACE == 1) { 245 REG_UPDATE(OTG_INTERLACE_CONTROL, 246 OTG_INTERLACE_ENABLE, 1); 247 v_init = v_init / 2; 248 if ((optc->dlg_otg_param.vstartup_start/2)*2 > asic_blank_end) 249 v_fp2 = v_fp2 / 2; 250 } else 251 REG_UPDATE(OTG_INTERLACE_CONTROL, 252 OTG_INTERLACE_ENABLE, 0); 253 254 255 /* VTG enable set to 0 first VInit */ 256 REG_UPDATE(CONTROL, 257 VTG0_ENABLE, 0); 258 259 REG_UPDATE_2(CONTROL, 260 VTG0_FP2, v_fp2, 261 VTG0_VCOUNT_INIT, v_init); 262 263 /* original code is using VTG offset to address OTG reg, seems wrong */ 264 REG_UPDATE_2(OTG_CONTROL, 265 OTG_START_POINT_CNTL, start_point, 266 OTG_FIELD_NUMBER_CNTL, field_num); 267 268 optc1_program_global_sync(optc); 269 270 /* TODO 271 * patched_crtc_timing.flags.HORZ_COUNT_BY_TWO == 1 272 * program_horz_count_by_2 273 * for DVI 30bpp mode, 0 otherwise 274 * program_horz_count_by_2(optc, &patched_crtc_timing); 275 */ 276 277 /* Enable stereo - only when we need to pack 3D frame. Other types 278 * of stereo handled in explicit call 279 */ 280 h_div_2 = (dc_crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) ? 281 1 : 0; 282 283 REG_UPDATE(OTG_H_TIMING_CNTL, 284 OTG_H_TIMING_DIV_BY2, h_div_2); 285 286 } 287 288 static void optc1_set_blank_data_double_buffer(struct timing_generator *optc, bool enable) 289 { 290 struct optc *optc1 = DCN10TG_FROM_TG(optc); 291 292 uint32_t blank_data_double_buffer_enable = enable ? 1 : 0; 293 294 REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL, 295 OTG_BLANK_DATA_DOUBLE_BUFFER_EN, blank_data_double_buffer_enable); 296 } 297 298 /** 299 * unblank_crtc 300 * Call ASIC Control Object to UnBlank CRTC. 301 */ 302 static void optc1_unblank_crtc(struct timing_generator *optc) 303 { 304 struct optc *optc1 = DCN10TG_FROM_TG(optc); 305 uint32_t vertical_interrupt_enable = 0; 306 307 REG_GET(OTG_VERTICAL_INTERRUPT2_CONTROL, 308 OTG_VERTICAL_INTERRUPT2_INT_ENABLE, &vertical_interrupt_enable); 309 310 /* temporary work around for vertical interrupt, once vertical interrupt enabled, 311 * this check will be removed. 312 */ 313 if (vertical_interrupt_enable) 314 optc1_set_blank_data_double_buffer(optc, true); 315 316 REG_UPDATE_2(OTG_BLANK_CONTROL, 317 OTG_BLANK_DATA_EN, 0, 318 OTG_BLANK_DE_MODE, 0); 319 } 320 321 /** 322 * blank_crtc 323 * Call ASIC Control Object to Blank CRTC. 324 */ 325 326 static void optc1_blank_crtc(struct timing_generator *optc) 327 { 328 struct optc *optc1 = DCN10TG_FROM_TG(optc); 329 330 REG_UPDATE_2(OTG_BLANK_CONTROL, 331 OTG_BLANK_DATA_EN, 1, 332 OTG_BLANK_DE_MODE, 0); 333 334 optc1_set_blank_data_double_buffer(optc, false); 335 } 336 337 void optc1_set_blank(struct timing_generator *optc, 338 bool enable_blanking) 339 { 340 if (enable_blanking) 341 optc1_blank_crtc(optc); 342 else 343 optc1_unblank_crtc(optc); 344 } 345 346 bool optc1_is_blanked(struct timing_generator *optc) 347 { 348 struct optc *optc1 = DCN10TG_FROM_TG(optc); 349 uint32_t blank_en; 350 uint32_t blank_state; 351 352 REG_GET_2(OTG_BLANK_CONTROL, 353 OTG_BLANK_DATA_EN, &blank_en, 354 OTG_CURRENT_BLANK_STATE, &blank_state); 355 356 return blank_en && blank_state; 357 } 358 359 void optc1_enable_optc_clock(struct timing_generator *optc, bool enable) 360 { 361 struct optc *optc1 = DCN10TG_FROM_TG(optc); 362 363 if (enable) { 364 REG_UPDATE_2(OPTC_INPUT_CLOCK_CONTROL, 365 OPTC_INPUT_CLK_EN, 1, 366 OPTC_INPUT_CLK_GATE_DIS, 1); 367 368 REG_WAIT(OPTC_INPUT_CLOCK_CONTROL, 369 OPTC_INPUT_CLK_ON, 1, 370 1, 1000); 371 372 /* Enable clock */ 373 REG_UPDATE_2(OTG_CLOCK_CONTROL, 374 OTG_CLOCK_EN, 1, 375 OTG_CLOCK_GATE_DIS, 1); 376 REG_WAIT(OTG_CLOCK_CONTROL, 377 OTG_CLOCK_ON, 1, 378 1, 1000); 379 } else { 380 REG_UPDATE_2(OTG_CLOCK_CONTROL, 381 OTG_CLOCK_GATE_DIS, 0, 382 OTG_CLOCK_EN, 0); 383 384 REG_UPDATE_2(OPTC_INPUT_CLOCK_CONTROL, 385 OPTC_INPUT_CLK_GATE_DIS, 0, 386 OPTC_INPUT_CLK_EN, 0); 387 } 388 } 389 390 /** 391 * Enable CRTC 392 * Enable CRTC - call ASIC Control Object to enable Timing generator. 393 */ 394 static bool optc1_enable_crtc(struct timing_generator *optc) 395 { 396 /* TODO FPGA wait for answer 397 * OTG_MASTER_UPDATE_MODE != CRTC_MASTER_UPDATE_MODE 398 * OTG_MASTER_UPDATE_LOCK != CRTC_MASTER_UPDATE_LOCK 399 */ 400 struct optc *optc1 = DCN10TG_FROM_TG(optc); 401 402 /* opp instance for OTG. For DCN1.0, ODM is remoed. 403 * OPP and OPTC should 1:1 mapping 404 */ 405 REG_UPDATE(OPTC_DATA_SOURCE_SELECT, 406 OPTC_SRC_SEL, optc->inst); 407 408 /* VTG enable first is for HW workaround */ 409 REG_UPDATE(CONTROL, 410 VTG0_ENABLE, 1); 411 412 /* Enable CRTC */ 413 REG_UPDATE_2(OTG_CONTROL, 414 OTG_DISABLE_POINT_CNTL, 3, 415 OTG_MASTER_EN, 1); 416 417 return true; 418 } 419 420 /* disable_crtc - call ASIC Control Object to disable Timing generator. */ 421 bool optc1_disable_crtc(struct timing_generator *optc) 422 { 423 struct optc *optc1 = DCN10TG_FROM_TG(optc); 424 425 /* disable otg request until end of the first line 426 * in the vertical blank region 427 */ 428 REG_UPDATE_2(OTG_CONTROL, 429 OTG_DISABLE_POINT_CNTL, 3, 430 OTG_MASTER_EN, 0); 431 432 REG_UPDATE(CONTROL, 433 VTG0_ENABLE, 0); 434 435 /* CRTC disabled, so disable clock. */ 436 REG_WAIT(OTG_CLOCK_CONTROL, 437 OTG_BUSY, 0, 438 1, 100000); 439 440 return true; 441 } 442 443 444 void optc1_program_blank_color( 445 struct timing_generator *optc, 446 const struct tg_color *black_color) 447 { 448 struct optc *optc1 = DCN10TG_FROM_TG(optc); 449 450 REG_SET_3(OTG_BLACK_COLOR, 0, 451 OTG_BLACK_COLOR_B_CB, black_color->color_b_cb, 452 OTG_BLACK_COLOR_G_Y, black_color->color_g_y, 453 OTG_BLACK_COLOR_R_CR, black_color->color_r_cr); 454 } 455 456 bool optc1_validate_timing( 457 struct timing_generator *optc, 458 const struct dc_crtc_timing *timing) 459 { 460 uint32_t interlace_factor; 461 uint32_t v_blank; 462 uint32_t h_blank; 463 uint32_t min_v_blank; 464 struct optc *optc1 = DCN10TG_FROM_TG(optc); 465 466 ASSERT(timing != NULL); 467 468 interlace_factor = timing->flags.INTERLACE ? 2 : 1; 469 v_blank = (timing->v_total - timing->v_addressable - 470 timing->v_border_top - timing->v_border_bottom) * 471 interlace_factor; 472 473 h_blank = (timing->h_total - timing->h_addressable - 474 timing->h_border_right - 475 timing->h_border_left); 476 477 if (timing->timing_3d_format != TIMING_3D_FORMAT_NONE && 478 timing->timing_3d_format != TIMING_3D_FORMAT_HW_FRAME_PACKING && 479 timing->timing_3d_format != TIMING_3D_FORMAT_TOP_AND_BOTTOM && 480 timing->timing_3d_format != TIMING_3D_FORMAT_SIDE_BY_SIDE && 481 timing->timing_3d_format != TIMING_3D_FORMAT_FRAME_ALTERNATE && 482 timing->timing_3d_format != TIMING_3D_FORMAT_INBAND_FA) 483 return false; 484 485 /* Temporarily blocking interlacing mode until it's supported */ 486 if (timing->flags.INTERLACE == 1) 487 return false; 488 489 /* Check maximum number of pixels supported by Timing Generator 490 * (Currently will never fail, in order to fail needs display which 491 * needs more than 8192 horizontal and 492 * more than 8192 vertical total pixels) 493 */ 494 if (timing->h_total > optc1->max_h_total || 495 timing->v_total > optc1->max_v_total) 496 return false; 497 498 499 if (h_blank < optc1->min_h_blank) 500 return false; 501 502 if (timing->h_sync_width < optc1->min_h_sync_width || 503 timing->v_sync_width < optc1->min_v_sync_width) 504 return false; 505 506 min_v_blank = timing->flags.INTERLACE?optc1->min_v_blank_interlace:optc1->min_v_blank; 507 508 if (v_blank < min_v_blank) 509 return false; 510 511 return true; 512 513 } 514 515 /* 516 * get_vblank_counter 517 * 518 * @brief 519 * Get counter for vertical blanks. use register CRTC_STATUS_FRAME_COUNT which 520 * holds the counter of frames. 521 * 522 * @param 523 * struct timing_generator *optc - [in] timing generator which controls the 524 * desired CRTC 525 * 526 * @return 527 * Counter of frames, which should equal to number of vblanks. 528 */ 529 uint32_t optc1_get_vblank_counter(struct timing_generator *optc) 530 { 531 struct optc *optc1 = DCN10TG_FROM_TG(optc); 532 uint32_t frame_count; 533 534 REG_GET(OTG_STATUS_FRAME_COUNT, 535 OTG_FRAME_COUNT, &frame_count); 536 537 return frame_count; 538 } 539 540 void optc1_lock(struct timing_generator *optc) 541 { 542 struct optc *optc1 = DCN10TG_FROM_TG(optc); 543 544 REG_SET(OTG_GLOBAL_CONTROL0, 0, 545 OTG_MASTER_UPDATE_LOCK_SEL, optc->inst); 546 REG_SET(OTG_MASTER_UPDATE_LOCK, 0, 547 OTG_MASTER_UPDATE_LOCK, 1); 548 549 /* Should be fast, status does not update on maximus */ 550 if (optc->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) 551 REG_WAIT(OTG_MASTER_UPDATE_LOCK, 552 UPDATE_LOCK_STATUS, 1, 553 1, 10); 554 } 555 556 void optc1_unlock(struct timing_generator *optc) 557 { 558 struct optc *optc1 = DCN10TG_FROM_TG(optc); 559 560 REG_SET(OTG_MASTER_UPDATE_LOCK, 0, 561 OTG_MASTER_UPDATE_LOCK, 0); 562 } 563 564 void optc1_get_position(struct timing_generator *optc, 565 struct crtc_position *position) 566 { 567 struct optc *optc1 = DCN10TG_FROM_TG(optc); 568 569 REG_GET_2(OTG_STATUS_POSITION, 570 OTG_HORZ_COUNT, &position->horizontal_count, 571 OTG_VERT_COUNT, &position->vertical_count); 572 573 REG_GET(OTG_NOM_VERT_POSITION, 574 OTG_VERT_COUNT_NOM, &position->nominal_vcount); 575 } 576 577 bool optc1_is_counter_moving(struct timing_generator *optc) 578 { 579 struct crtc_position position1, position2; 580 581 optc->funcs->get_position(optc, &position1); 582 optc->funcs->get_position(optc, &position2); 583 584 if (position1.horizontal_count == position2.horizontal_count && 585 position1.vertical_count == position2.vertical_count) 586 return false; 587 else 588 return true; 589 } 590 591 bool optc1_did_triggered_reset_occur( 592 struct timing_generator *optc) 593 { 594 struct optc *optc1 = DCN10TG_FROM_TG(optc); 595 uint32_t occurred_force, occurred_vsync; 596 597 REG_GET(OTG_FORCE_COUNT_NOW_CNTL, 598 OTG_FORCE_COUNT_NOW_OCCURRED, &occurred_force); 599 600 REG_GET(OTG_VERT_SYNC_CONTROL, 601 OTG_FORCE_VSYNC_NEXT_LINE_OCCURRED, &occurred_vsync); 602 603 return occurred_vsync != 0 || occurred_force != 0; 604 } 605 606 void optc1_disable_reset_trigger(struct timing_generator *optc) 607 { 608 struct optc *optc1 = DCN10TG_FROM_TG(optc); 609 610 REG_WRITE(OTG_TRIGA_CNTL, 0); 611 612 REG_SET(OTG_FORCE_COUNT_NOW_CNTL, 0, 613 OTG_FORCE_COUNT_NOW_CLEAR, 1); 614 615 REG_SET(OTG_VERT_SYNC_CONTROL, 0, 616 OTG_FORCE_VSYNC_NEXT_LINE_CLEAR, 1); 617 } 618 619 void optc1_enable_reset_trigger(struct timing_generator *optc, int source_tg_inst) 620 { 621 struct optc *optc1 = DCN10TG_FROM_TG(optc); 622 uint32_t falling_edge; 623 624 REG_GET(OTG_V_SYNC_A_CNTL, 625 OTG_V_SYNC_A_POL, &falling_edge); 626 627 if (falling_edge) 628 REG_SET_3(OTG_TRIGA_CNTL, 0, 629 /* vsync signal from selected OTG pipe based 630 * on OTG_TRIG_SOURCE_PIPE_SELECT setting 631 */ 632 OTG_TRIGA_SOURCE_SELECT, 20, 633 OTG_TRIGA_SOURCE_PIPE_SELECT, source_tg_inst, 634 /* always detect falling edge */ 635 OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, 1); 636 else 637 REG_SET_3(OTG_TRIGA_CNTL, 0, 638 /* vsync signal from selected OTG pipe based 639 * on OTG_TRIG_SOURCE_PIPE_SELECT setting 640 */ 641 OTG_TRIGA_SOURCE_SELECT, 20, 642 OTG_TRIGA_SOURCE_PIPE_SELECT, source_tg_inst, 643 /* always detect rising edge */ 644 OTG_TRIGA_RISING_EDGE_DETECT_CNTL, 1); 645 646 REG_SET(OTG_FORCE_COUNT_NOW_CNTL, 0, 647 /* force H count to H_TOTAL and V count to V_TOTAL in 648 * progressive mode and V_TOTAL-1 in interlaced mode 649 */ 650 OTG_FORCE_COUNT_NOW_MODE, 2); 651 } 652 653 void optc1_enable_crtc_reset( 654 struct timing_generator *optc, 655 int source_tg_inst, 656 struct crtc_trigger_info *crtc_tp) 657 { 658 struct optc *optc1 = DCN10TG_FROM_TG(optc); 659 uint32_t falling_edge = 0; 660 uint32_t rising_edge = 0; 661 662 switch (crtc_tp->event) { 663 664 case CRTC_EVENT_VSYNC_RISING: 665 rising_edge = 1; 666 break; 667 668 case CRTC_EVENT_VSYNC_FALLING: 669 falling_edge = 1; 670 break; 671 } 672 673 REG_SET_4(OTG_TRIGA_CNTL, 0, 674 /* vsync signal from selected OTG pipe based 675 * on OTG_TRIG_SOURCE_PIPE_SELECT setting 676 */ 677 OTG_TRIGA_SOURCE_SELECT, 20, 678 OTG_TRIGA_SOURCE_PIPE_SELECT, source_tg_inst, 679 /* always detect falling edge */ 680 OTG_TRIGA_RISING_EDGE_DETECT_CNTL, rising_edge, 681 OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, falling_edge); 682 683 switch (crtc_tp->delay) { 684 case TRIGGER_DELAY_NEXT_LINE: 685 REG_SET(OTG_VERT_SYNC_CONTROL, 0, 686 OTG_AUTO_FORCE_VSYNC_MODE, 1); 687 break; 688 case TRIGGER_DELAY_NEXT_PIXEL: 689 REG_SET(OTG_FORCE_COUNT_NOW_CNTL, 0, 690 /* force H count to H_TOTAL and V count to V_TOTAL in 691 * progressive mode and V_TOTAL-1 in interlaced mode 692 */ 693 OTG_FORCE_COUNT_NOW_MODE, 2); 694 break; 695 } 696 } 697 698 void optc1_wait_for_state(struct timing_generator *optc, 699 enum crtc_state state) 700 { 701 struct optc *optc1 = DCN10TG_FROM_TG(optc); 702 703 switch (state) { 704 case CRTC_STATE_VBLANK: 705 REG_WAIT(OTG_STATUS, 706 OTG_V_BLANK, 1, 707 1, 100000); /* 1 vupdate at 10hz */ 708 break; 709 710 case CRTC_STATE_VACTIVE: 711 REG_WAIT(OTG_STATUS, 712 OTG_V_ACTIVE_DISP, 1, 713 1, 100000); /* 1 vupdate at 10hz */ 714 break; 715 716 default: 717 break; 718 } 719 } 720 721 void optc1_set_early_control( 722 struct timing_generator *optc, 723 uint32_t early_cntl) 724 { 725 /* asic design change, do not need this control 726 * empty for share caller logic 727 */ 728 } 729 730 731 void optc1_set_static_screen_control( 732 struct timing_generator *optc, 733 uint32_t value) 734 { 735 struct optc *optc1 = DCN10TG_FROM_TG(optc); 736 737 /* Bit 8 is no longer applicable in RV for PSR case, 738 * set bit 8 to 0 if given 739 */ 740 if ((value & STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN) 741 != 0) 742 value = value & 743 ~STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN; 744 745 REG_SET_2(OTG_STATIC_SCREEN_CONTROL, 0, 746 OTG_STATIC_SCREEN_EVENT_MASK, value, 747 OTG_STATIC_SCREEN_FRAME_COUNT, 2); 748 } 749 750 751 /** 752 ***************************************************************************** 753 * Function: set_drr 754 * 755 * @brief 756 * Program dynamic refresh rate registers m_OTGx_OTG_V_TOTAL_*. 757 * 758 ***************************************************************************** 759 */ 760 void optc1_set_drr( 761 struct timing_generator *optc, 762 const struct drr_params *params) 763 { 764 struct optc *optc1 = DCN10TG_FROM_TG(optc); 765 766 if (params != NULL && 767 params->vertical_total_max > 0 && 768 params->vertical_total_min > 0) { 769 770 REG_SET(OTG_V_TOTAL_MAX, 0, 771 OTG_V_TOTAL_MAX, params->vertical_total_max - 1); 772 773 REG_SET(OTG_V_TOTAL_MIN, 0, 774 OTG_V_TOTAL_MIN, params->vertical_total_min - 1); 775 776 REG_UPDATE_5(OTG_V_TOTAL_CONTROL, 777 OTG_V_TOTAL_MIN_SEL, 1, 778 OTG_V_TOTAL_MAX_SEL, 1, 779 OTG_FORCE_LOCK_ON_EVENT, 0, 780 OTG_SET_V_TOTAL_MIN_MASK_EN, 0, 781 OTG_SET_V_TOTAL_MIN_MASK, 0); 782 } else { 783 REG_SET(OTG_V_TOTAL_MIN, 0, 784 OTG_V_TOTAL_MIN, 0); 785 786 REG_SET(OTG_V_TOTAL_MAX, 0, 787 OTG_V_TOTAL_MAX, 0); 788 789 REG_UPDATE_4(OTG_V_TOTAL_CONTROL, 790 OTG_SET_V_TOTAL_MIN_MASK, 0, 791 OTG_V_TOTAL_MIN_SEL, 0, 792 OTG_V_TOTAL_MAX_SEL, 0, 793 OTG_FORCE_LOCK_ON_EVENT, 0); 794 } 795 } 796 797 static void optc1_set_test_pattern( 798 struct timing_generator *optc, 799 /* TODO: replace 'controller_dp_test_pattern' by 'test_pattern_mode' 800 * because this is not DP-specific (which is probably somewhere in DP 801 * encoder) */ 802 enum controller_dp_test_pattern test_pattern, 803 enum dc_color_depth color_depth) 804 { 805 struct optc *optc1 = DCN10TG_FROM_TG(optc); 806 enum test_pattern_color_format bit_depth; 807 enum test_pattern_dyn_range dyn_range; 808 enum test_pattern_mode mode; 809 uint32_t pattern_mask; 810 uint32_t pattern_data; 811 /* color ramp generator mixes 16-bits color */ 812 uint32_t src_bpc = 16; 813 /* requested bpc */ 814 uint32_t dst_bpc; 815 uint32_t index; 816 /* RGB values of the color bars. 817 * Produce two RGB colors: RGB0 - white (all Fs) 818 * and RGB1 - black (all 0s) 819 * (three RGB components for two colors) 820 */ 821 uint16_t src_color[6] = {0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 822 0x0000, 0x0000}; 823 /* dest color (converted to the specified color format) */ 824 uint16_t dst_color[6]; 825 uint32_t inc_base; 826 827 /* translate to bit depth */ 828 switch (color_depth) { 829 case COLOR_DEPTH_666: 830 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_6; 831 break; 832 case COLOR_DEPTH_888: 833 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8; 834 break; 835 case COLOR_DEPTH_101010: 836 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_10; 837 break; 838 case COLOR_DEPTH_121212: 839 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_12; 840 break; 841 default: 842 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8; 843 break; 844 } 845 846 switch (test_pattern) { 847 case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES: 848 case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA: 849 { 850 dyn_range = (test_pattern == 851 CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA ? 852 TEST_PATTERN_DYN_RANGE_CEA : 853 TEST_PATTERN_DYN_RANGE_VESA); 854 mode = TEST_PATTERN_MODE_COLORSQUARES_RGB; 855 856 REG_UPDATE_2(OTG_TEST_PATTERN_PARAMETERS, 857 OTG_TEST_PATTERN_VRES, 6, 858 OTG_TEST_PATTERN_HRES, 6); 859 860 REG_UPDATE_4(OTG_TEST_PATTERN_CONTROL, 861 OTG_TEST_PATTERN_EN, 1, 862 OTG_TEST_PATTERN_MODE, mode, 863 OTG_TEST_PATTERN_DYNAMIC_RANGE, dyn_range, 864 OTG_TEST_PATTERN_COLOR_FORMAT, bit_depth); 865 } 866 break; 867 868 case CONTROLLER_DP_TEST_PATTERN_VERTICALBARS: 869 case CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS: 870 { 871 mode = (test_pattern == 872 CONTROLLER_DP_TEST_PATTERN_VERTICALBARS ? 873 TEST_PATTERN_MODE_VERTICALBARS : 874 TEST_PATTERN_MODE_HORIZONTALBARS); 875 876 switch (bit_depth) { 877 case TEST_PATTERN_COLOR_FORMAT_BPC_6: 878 dst_bpc = 6; 879 break; 880 case TEST_PATTERN_COLOR_FORMAT_BPC_8: 881 dst_bpc = 8; 882 break; 883 case TEST_PATTERN_COLOR_FORMAT_BPC_10: 884 dst_bpc = 10; 885 break; 886 default: 887 dst_bpc = 8; 888 break; 889 } 890 891 /* adjust color to the required colorFormat */ 892 for (index = 0; index < 6; index++) { 893 /* dst = 2^dstBpc * src / 2^srcBpc = src >> 894 * (srcBpc - dstBpc); 895 */ 896 dst_color[index] = 897 src_color[index] >> (src_bpc - dst_bpc); 898 /* CRTC_TEST_PATTERN_DATA has 16 bits, 899 * lowest 6 are hardwired to ZERO 900 * color bits should be left aligned aligned to MSB 901 * XXXXXXXXXX000000 for 10 bit, 902 * XXXXXXXX00000000 for 8 bit and XXXXXX0000000000 for 6 903 */ 904 dst_color[index] <<= (16 - dst_bpc); 905 } 906 907 REG_WRITE(OTG_TEST_PATTERN_PARAMETERS, 0); 908 909 /* We have to write the mask before data, similar to pipeline. 910 * For example, for 8 bpc, if we want RGB0 to be magenta, 911 * and RGB1 to be cyan, 912 * we need to make 7 writes: 913 * MASK DATA 914 * 000001 00000000 00000000 set mask to R0 915 * 000010 11111111 00000000 R0 255, 0xFF00, set mask to G0 916 * 000100 00000000 00000000 G0 0, 0x0000, set mask to B0 917 * 001000 11111111 00000000 B0 255, 0xFF00, set mask to R1 918 * 010000 00000000 00000000 R1 0, 0x0000, set mask to G1 919 * 100000 11111111 00000000 G1 255, 0xFF00, set mask to B1 920 * 100000 11111111 00000000 B1 255, 0xFF00 921 * 922 * we will make a loop of 6 in which we prepare the mask, 923 * then write, then prepare the color for next write. 924 * first iteration will write mask only, 925 * but each next iteration color prepared in 926 * previous iteration will be written within new mask, 927 * the last component will written separately, 928 * mask is not changing between 6th and 7th write 929 * and color will be prepared by last iteration 930 */ 931 932 /* write color, color values mask in CRTC_TEST_PATTERN_MASK 933 * is B1, G1, R1, B0, G0, R0 934 */ 935 pattern_data = 0; 936 for (index = 0; index < 6; index++) { 937 /* prepare color mask, first write PATTERN_DATA 938 * will have all zeros 939 */ 940 pattern_mask = (1 << index); 941 942 /* write color component */ 943 REG_SET_2(OTG_TEST_PATTERN_COLOR, 0, 944 OTG_TEST_PATTERN_MASK, pattern_mask, 945 OTG_TEST_PATTERN_DATA, pattern_data); 946 947 /* prepare next color component, 948 * will be written in the next iteration 949 */ 950 pattern_data = dst_color[index]; 951 } 952 /* write last color component, 953 * it's been already prepared in the loop 954 */ 955 REG_SET_2(OTG_TEST_PATTERN_COLOR, 0, 956 OTG_TEST_PATTERN_MASK, pattern_mask, 957 OTG_TEST_PATTERN_DATA, pattern_data); 958 959 /* enable test pattern */ 960 REG_UPDATE_4(OTG_TEST_PATTERN_CONTROL, 961 OTG_TEST_PATTERN_EN, 1, 962 OTG_TEST_PATTERN_MODE, mode, 963 OTG_TEST_PATTERN_DYNAMIC_RANGE, 0, 964 OTG_TEST_PATTERN_COLOR_FORMAT, bit_depth); 965 } 966 break; 967 968 case CONTROLLER_DP_TEST_PATTERN_COLORRAMP: 969 { 970 mode = (bit_depth == 971 TEST_PATTERN_COLOR_FORMAT_BPC_10 ? 972 TEST_PATTERN_MODE_DUALRAMP_RGB : 973 TEST_PATTERN_MODE_SINGLERAMP_RGB); 974 975 switch (bit_depth) { 976 case TEST_PATTERN_COLOR_FORMAT_BPC_6: 977 dst_bpc = 6; 978 break; 979 case TEST_PATTERN_COLOR_FORMAT_BPC_8: 980 dst_bpc = 8; 981 break; 982 case TEST_PATTERN_COLOR_FORMAT_BPC_10: 983 dst_bpc = 10; 984 break; 985 default: 986 dst_bpc = 8; 987 break; 988 } 989 990 /* increment for the first ramp for one color gradation 991 * 1 gradation for 6-bit color is 2^10 992 * gradations in 16-bit color 993 */ 994 inc_base = (src_bpc - dst_bpc); 995 996 switch (bit_depth) { 997 case TEST_PATTERN_COLOR_FORMAT_BPC_6: 998 { 999 REG_UPDATE_5(OTG_TEST_PATTERN_PARAMETERS, 1000 OTG_TEST_PATTERN_INC0, inc_base, 1001 OTG_TEST_PATTERN_INC1, 0, 1002 OTG_TEST_PATTERN_HRES, 6, 1003 OTG_TEST_PATTERN_VRES, 6, 1004 OTG_TEST_PATTERN_RAMP0_OFFSET, 0); 1005 } 1006 break; 1007 case TEST_PATTERN_COLOR_FORMAT_BPC_8: 1008 { 1009 REG_UPDATE_5(OTG_TEST_PATTERN_PARAMETERS, 1010 OTG_TEST_PATTERN_INC0, inc_base, 1011 OTG_TEST_PATTERN_INC1, 0, 1012 OTG_TEST_PATTERN_HRES, 8, 1013 OTG_TEST_PATTERN_VRES, 6, 1014 OTG_TEST_PATTERN_RAMP0_OFFSET, 0); 1015 } 1016 break; 1017 case TEST_PATTERN_COLOR_FORMAT_BPC_10: 1018 { 1019 REG_UPDATE_5(OTG_TEST_PATTERN_PARAMETERS, 1020 OTG_TEST_PATTERN_INC0, inc_base, 1021 OTG_TEST_PATTERN_INC1, inc_base + 2, 1022 OTG_TEST_PATTERN_HRES, 8, 1023 OTG_TEST_PATTERN_VRES, 5, 1024 OTG_TEST_PATTERN_RAMP0_OFFSET, 384 << 6); 1025 } 1026 break; 1027 default: 1028 break; 1029 } 1030 1031 REG_WRITE(OTG_TEST_PATTERN_COLOR, 0); 1032 1033 /* enable test pattern */ 1034 REG_WRITE(OTG_TEST_PATTERN_CONTROL, 0); 1035 1036 REG_SET_4(OTG_TEST_PATTERN_CONTROL, 0, 1037 OTG_TEST_PATTERN_EN, 1, 1038 OTG_TEST_PATTERN_MODE, mode, 1039 OTG_TEST_PATTERN_DYNAMIC_RANGE, 0, 1040 OTG_TEST_PATTERN_COLOR_FORMAT, bit_depth); 1041 } 1042 break; 1043 case CONTROLLER_DP_TEST_PATTERN_VIDEOMODE: 1044 { 1045 REG_WRITE(OTG_TEST_PATTERN_CONTROL, 0); 1046 REG_WRITE(OTG_TEST_PATTERN_COLOR, 0); 1047 REG_WRITE(OTG_TEST_PATTERN_PARAMETERS, 0); 1048 } 1049 break; 1050 default: 1051 break; 1052 1053 } 1054 } 1055 1056 void optc1_get_crtc_scanoutpos( 1057 struct timing_generator *optc, 1058 uint32_t *v_blank_start, 1059 uint32_t *v_blank_end, 1060 uint32_t *h_position, 1061 uint32_t *v_position) 1062 { 1063 struct optc *optc1 = DCN10TG_FROM_TG(optc); 1064 struct crtc_position position; 1065 1066 REG_GET_2(OTG_V_BLANK_START_END, 1067 OTG_V_BLANK_START, v_blank_start, 1068 OTG_V_BLANK_END, v_blank_end); 1069 1070 optc1_get_position(optc, &position); 1071 1072 *h_position = position.horizontal_count; 1073 *v_position = position.vertical_count; 1074 } 1075 1076 static void optc1_enable_stereo(struct timing_generator *optc, 1077 const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags) 1078 { 1079 struct optc *optc1 = DCN10TG_FROM_TG(optc); 1080 1081 if (flags) { 1082 uint32_t stereo_en; 1083 stereo_en = flags->FRAME_PACKED == 0 ? 1 : 0; 1084 1085 if (flags->PROGRAM_STEREO) 1086 REG_UPDATE_3(OTG_STEREO_CONTROL, 1087 OTG_STEREO_EN, stereo_en, 1088 OTG_STEREO_SYNC_OUTPUT_LINE_NUM, 0, 1089 OTG_STEREO_SYNC_OUTPUT_POLARITY, 0); 1090 1091 if (flags->PROGRAM_POLARITY) 1092 REG_UPDATE(OTG_STEREO_CONTROL, 1093 OTG_STEREO_EYE_FLAG_POLARITY, 1094 flags->RIGHT_EYE_POLARITY == 0 ? 0 : 1); 1095 1096 if (flags->DISABLE_STEREO_DP_SYNC) 1097 REG_UPDATE(OTG_STEREO_CONTROL, 1098 OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, 1); 1099 1100 if (flags->PROGRAM_STEREO) 1101 REG_UPDATE_3(OTG_3D_STRUCTURE_CONTROL, 1102 OTG_3D_STRUCTURE_EN, flags->FRAME_PACKED, 1103 OTG_3D_STRUCTURE_V_UPDATE_MODE, flags->FRAME_PACKED, 1104 OTG_3D_STRUCTURE_STEREO_SEL_OVR, flags->FRAME_PACKED); 1105 1106 } 1107 } 1108 1109 void optc1_program_stereo(struct timing_generator *optc, 1110 const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags) 1111 { 1112 if (flags->PROGRAM_STEREO) 1113 optc1_enable_stereo(optc, timing, flags); 1114 else 1115 optc1_disable_stereo(optc); 1116 } 1117 1118 1119 bool optc1_is_stereo_left_eye(struct timing_generator *optc) 1120 { 1121 bool ret = false; 1122 uint32_t left_eye = 0; 1123 struct optc *optc1 = DCN10TG_FROM_TG(optc); 1124 1125 REG_GET(OTG_STEREO_STATUS, 1126 OTG_STEREO_CURRENT_EYE, &left_eye); 1127 if (left_eye == 1) 1128 ret = true; 1129 else 1130 ret = false; 1131 1132 return ret; 1133 } 1134 1135 void optc1_read_otg_state(struct optc *optc1, 1136 struct dcn_otg_state *s) 1137 { 1138 REG_GET(OTG_CONTROL, 1139 OTG_MASTER_EN, &s->otg_enabled); 1140 1141 REG_GET_2(OTG_V_BLANK_START_END, 1142 OTG_V_BLANK_START, &s->v_blank_start, 1143 OTG_V_BLANK_END, &s->v_blank_end); 1144 1145 REG_GET(OTG_V_SYNC_A_CNTL, 1146 OTG_V_SYNC_A_POL, &s->v_sync_a_pol); 1147 1148 REG_GET(OTG_V_TOTAL, 1149 OTG_V_TOTAL, &s->v_total); 1150 1151 REG_GET(OTG_V_TOTAL_MAX, 1152 OTG_V_TOTAL_MAX, &s->v_total_max); 1153 1154 REG_GET(OTG_V_TOTAL_MIN, 1155 OTG_V_TOTAL_MIN, &s->v_total_min); 1156 1157 REG_GET_2(OTG_V_SYNC_A, 1158 OTG_V_SYNC_A_START, &s->v_sync_a_start, 1159 OTG_V_SYNC_A_END, &s->v_sync_a_end); 1160 1161 REG_GET_2(OTG_H_BLANK_START_END, 1162 OTG_H_BLANK_START, &s->h_blank_start, 1163 OTG_H_BLANK_END, &s->h_blank_end); 1164 1165 REG_GET_2(OTG_H_SYNC_A, 1166 OTG_H_SYNC_A_START, &s->h_sync_a_start, 1167 OTG_H_SYNC_A_END, &s->h_sync_a_end); 1168 1169 REG_GET(OTG_H_SYNC_A_CNTL, 1170 OTG_H_SYNC_A_POL, &s->h_sync_a_pol); 1171 1172 REG_GET(OTG_H_TOTAL, 1173 OTG_H_TOTAL, &s->h_total); 1174 1175 REG_GET(OPTC_INPUT_GLOBAL_CONTROL, 1176 OPTC_UNDERFLOW_OCCURRED_STATUS, &s->underflow_occurred_status); 1177 } 1178 1179 static void optc1_clear_optc_underflow(struct timing_generator *optc) 1180 { 1181 struct optc *optc1 = DCN10TG_FROM_TG(optc); 1182 1183 REG_UPDATE(OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_CLEAR, 1); 1184 } 1185 1186 static void optc1_tg_init(struct timing_generator *optc) 1187 { 1188 optc1_set_blank_data_double_buffer(optc, true); 1189 optc1_clear_optc_underflow(optc); 1190 } 1191 1192 static bool optc1_is_tg_enabled(struct timing_generator *optc) 1193 { 1194 struct optc *optc1 = DCN10TG_FROM_TG(optc); 1195 uint32_t otg_enabled = 0; 1196 1197 REG_GET(OTG_CONTROL, OTG_MASTER_EN, &otg_enabled); 1198 1199 return (otg_enabled != 0); 1200 1201 } 1202 1203 static bool optc1_is_optc_underflow_occurred(struct timing_generator *optc) 1204 { 1205 struct optc *optc1 = DCN10TG_FROM_TG(optc); 1206 uint32_t underflow_occurred = 0; 1207 1208 REG_GET(OPTC_INPUT_GLOBAL_CONTROL, 1209 OPTC_UNDERFLOW_OCCURRED_STATUS, 1210 &underflow_occurred); 1211 1212 return (underflow_occurred == 1); 1213 } 1214 1215 static const struct timing_generator_funcs dcn10_tg_funcs = { 1216 .validate_timing = optc1_validate_timing, 1217 .program_timing = optc1_program_timing, 1218 .program_global_sync = optc1_program_global_sync, 1219 .enable_crtc = optc1_enable_crtc, 1220 .disable_crtc = optc1_disable_crtc, 1221 /* used by enable_timing_synchronization. Not need for FPGA */ 1222 .is_counter_moving = optc1_is_counter_moving, 1223 .get_position = optc1_get_position, 1224 .get_frame_count = optc1_get_vblank_counter, 1225 .get_scanoutpos = optc1_get_crtc_scanoutpos, 1226 .set_early_control = optc1_set_early_control, 1227 /* used by enable_timing_synchronization. Not need for FPGA */ 1228 .wait_for_state = optc1_wait_for_state, 1229 .set_blank = optc1_set_blank, 1230 .is_blanked = optc1_is_blanked, 1231 .set_blank_color = optc1_program_blank_color, 1232 .did_triggered_reset_occur = optc1_did_triggered_reset_occur, 1233 .enable_reset_trigger = optc1_enable_reset_trigger, 1234 .enable_crtc_reset = optc1_enable_crtc_reset, 1235 .disable_reset_trigger = optc1_disable_reset_trigger, 1236 .lock = optc1_lock, 1237 .unlock = optc1_unlock, 1238 .enable_optc_clock = optc1_enable_optc_clock, 1239 .set_drr = optc1_set_drr, 1240 .set_static_screen_control = optc1_set_static_screen_control, 1241 .set_test_pattern = optc1_set_test_pattern, 1242 .program_stereo = optc1_program_stereo, 1243 .is_stereo_left_eye = optc1_is_stereo_left_eye, 1244 .set_blank_data_double_buffer = optc1_set_blank_data_double_buffer, 1245 .tg_init = optc1_tg_init, 1246 .is_tg_enabled = optc1_is_tg_enabled, 1247 .is_optc_underflow_occurred = optc1_is_optc_underflow_occurred, 1248 .clear_optc_underflow = optc1_clear_optc_underflow, 1249 }; 1250 1251 void dcn10_timing_generator_init(struct optc *optc1) 1252 { 1253 optc1->base.funcs = &dcn10_tg_funcs; 1254 1255 optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1; 1256 optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1; 1257 1258 optc1->min_h_blank = 32; 1259 optc1->min_v_blank = 3; 1260 optc1->min_v_blank_interlace = 5; 1261 optc1->min_h_sync_width = 8; 1262 optc1->min_v_sync_width = 1; 1263 } 1264