1 /* $NetBSD: amdgpu_dce110_timing_generator.c,v 1.3 2021/12/19 10:59:02 riastradh Exp $ */ 2 3 /* 4 * Copyright 2012-15 Advanced Micro Devices, Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: AMD 25 * 26 */ 27 28 #include <sys/cdefs.h> 29 __KERNEL_RCSID(0, "$NetBSD: amdgpu_dce110_timing_generator.c,v 1.3 2021/12/19 10:59:02 riastradh Exp $"); 30 31 #include "dm_services.h" 32 33 /* include DCE11 register header files */ 34 #include "dce/dce_11_0_d.h" 35 #include "dce/dce_11_0_sh_mask.h" 36 37 #include "dc_types.h" 38 #include "dc_bios_types.h" 39 #include "dc.h" 40 41 #include "include/grph_object_id.h" 42 #include "include/logger_interface.h" 43 #include "dce110_timing_generator.h" 44 45 #include "timing_generator.h" 46 47 48 #define NUMBER_OF_FRAME_TO_WAIT_ON_TRIGGERED_RESET 10 49 50 #define MAX_H_TOTAL (CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1) 51 #define MAX_V_TOTAL (CRTC_V_TOTAL__CRTC_V_TOTAL_MASKhw + 1) 52 53 #define CRTC_REG(reg) (reg + tg110->offsets.crtc) 54 #define DCP_REG(reg) (reg + tg110->offsets.dcp) 55 56 /* Flowing register offsets are same in files of 57 * dce/dce_11_0_d.h 58 * dce/vi_polaris10_p/vi_polaris10_d.h 59 * 60 * So we can create dce110 timing generator to use it. 61 */ 62 63 64 /* 65 * apply_front_porch_workaround 66 * 67 * This is a workaround for a bug that has existed since R5xx and has not been 68 * fixed keep Front porch at minimum 2 for Interlaced mode or 1 for progressive. 69 */ 70 static void dce110_timing_generator_apply_front_porch_workaround( 71 struct timing_generator *tg, 72 struct dc_crtc_timing *timing) 73 { 74 if (timing->flags.INTERLACE == 1) { 75 if (timing->v_front_porch < 2) 76 timing->v_front_porch = 2; 77 } else { 78 if (timing->v_front_porch < 1) 79 timing->v_front_porch = 1; 80 } 81 } 82 83 /** 84 ***************************************************************************** 85 * Function: is_in_vertical_blank 86 * 87 * @brief 88 * check the current status of CRTC to check if we are in Vertical Blank 89 * regioneased" state 90 * 91 * @return 92 * true if currently in blank region, false otherwise 93 * 94 ***************************************************************************** 95 */ 96 static bool dce110_timing_generator_is_in_vertical_blank( 97 struct timing_generator *tg) 98 { 99 uint32_t addr = 0; 100 uint32_t value = 0; 101 uint32_t field = 0; 102 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 103 104 addr = CRTC_REG(mmCRTC_STATUS); 105 value = dm_read_reg(tg->ctx, addr); 106 field = get_reg_field_value(value, CRTC_STATUS, CRTC_V_BLANK); 107 return field == 1; 108 } 109 110 void dce110_timing_generator_set_early_control( 111 struct timing_generator *tg, 112 uint32_t early_cntl) 113 { 114 uint32_t regval; 115 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 116 uint32_t address = CRTC_REG(mmCRTC_CONTROL); 117 118 regval = dm_read_reg(tg->ctx, address); 119 set_reg_field_value(regval, early_cntl, 120 CRTC_CONTROL, CRTC_HBLANK_EARLY_CONTROL); 121 dm_write_reg(tg->ctx, address, regval); 122 } 123 124 /** 125 * Enable CRTC 126 * Enable CRTC - call ASIC Control Object to enable Timing generator. 127 */ 128 bool dce110_timing_generator_enable_crtc(struct timing_generator *tg) 129 { 130 enum bp_result result; 131 132 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 133 uint32_t value = 0; 134 135 /* 136 * 3 is used to make sure V_UPDATE occurs at the beginning of the first 137 * line of vertical front porch 138 */ 139 set_reg_field_value( 140 value, 141 0, 142 CRTC_MASTER_UPDATE_MODE, 143 MASTER_UPDATE_MODE); 144 145 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_MASTER_UPDATE_MODE), value); 146 147 /* TODO: may want this on to catch underflow */ 148 value = 0; 149 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_MASTER_UPDATE_LOCK), value); 150 151 result = tg->bp->funcs->enable_crtc(tg->bp, tg110->controller_id, true); 152 153 return result == BP_RESULT_OK; 154 } 155 156 void dce110_timing_generator_program_blank_color( 157 struct timing_generator *tg, 158 const struct tg_color *black_color) 159 { 160 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 161 uint32_t addr = CRTC_REG(mmCRTC_BLACK_COLOR); 162 uint32_t value = dm_read_reg(tg->ctx, addr); 163 164 set_reg_field_value( 165 value, 166 black_color->color_b_cb, 167 CRTC_BLACK_COLOR, 168 CRTC_BLACK_COLOR_B_CB); 169 set_reg_field_value( 170 value, 171 black_color->color_g_y, 172 CRTC_BLACK_COLOR, 173 CRTC_BLACK_COLOR_G_Y); 174 set_reg_field_value( 175 value, 176 black_color->color_r_cr, 177 CRTC_BLACK_COLOR, 178 CRTC_BLACK_COLOR_R_CR); 179 180 dm_write_reg(tg->ctx, addr, value); 181 } 182 183 /** 184 ***************************************************************************** 185 * Function: disable_stereo 186 * 187 * @brief 188 * Disables active stereo on controller 189 * Frame Packing need to be disabled in vBlank or when CRTC not running 190 ***************************************************************************** 191 */ 192 #if 0 193 @TODOSTEREO 194 static void disable_stereo(struct timing_generator *tg) 195 { 196 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 197 uint32_t addr = CRTC_REG(mmCRTC_3D_STRUCTURE_CONTROL); 198 uint32_t value = 0; 199 uint32_t test = 0; 200 uint32_t field = 0; 201 uint32_t struc_en = 0; 202 uint32_t struc_stereo_sel_ovr = 0; 203 204 value = dm_read_reg(tg->ctx, addr); 205 struc_en = get_reg_field_value( 206 value, 207 CRTC_3D_STRUCTURE_CONTROL, 208 CRTC_3D_STRUCTURE_EN); 209 210 struc_stereo_sel_ovr = get_reg_field_value( 211 value, 212 CRTC_3D_STRUCTURE_CONTROL, 213 CRTC_3D_STRUCTURE_STEREO_SEL_OVR); 214 215 /* 216 * When disabling Frame Packing in 2 step mode, we need to program both 217 * registers at the same frame 218 * Programming it in the beginning of VActive makes sure we are ok 219 */ 220 221 if (struc_en != 0 && struc_stereo_sel_ovr == 0) { 222 tg->funcs->wait_for_vblank(tg); 223 tg->funcs->wait_for_vactive(tg); 224 } 225 226 value = 0; 227 dm_write_reg(tg->ctx, addr, value); 228 229 addr = tg->regs[IDX_CRTC_STEREO_CONTROL]; 230 dm_write_reg(tg->ctx, addr, value); 231 } 232 #endif 233 234 /** 235 * disable_crtc - call ASIC Control Object to disable Timing generator. 236 */ 237 bool dce110_timing_generator_disable_crtc(struct timing_generator *tg) 238 { 239 enum bp_result result; 240 241 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 242 243 result = tg->bp->funcs->enable_crtc(tg->bp, tg110->controller_id, false); 244 245 /* Need to make sure stereo is disabled according to the DCE5.0 spec */ 246 247 /* 248 * @TODOSTEREO call this when adding stereo support 249 * tg->funcs->disable_stereo(tg); 250 */ 251 252 return result == BP_RESULT_OK; 253 } 254 255 /** 256 * program_horz_count_by_2 257 * Programs DxCRTC_HORZ_COUNT_BY2_EN - 1 for DVI 30bpp mode, 0 otherwise 258 * 259 */ 260 static void program_horz_count_by_2( 261 struct timing_generator *tg, 262 const struct dc_crtc_timing *timing) 263 { 264 uint32_t regval; 265 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 266 267 regval = dm_read_reg(tg->ctx, 268 CRTC_REG(mmCRTC_COUNT_CONTROL)); 269 270 set_reg_field_value(regval, 0, CRTC_COUNT_CONTROL, 271 CRTC_HORZ_COUNT_BY2_EN); 272 273 if (timing->flags.HORZ_COUNT_BY_TWO) 274 set_reg_field_value(regval, 1, CRTC_COUNT_CONTROL, 275 CRTC_HORZ_COUNT_BY2_EN); 276 277 dm_write_reg(tg->ctx, 278 CRTC_REG(mmCRTC_COUNT_CONTROL), regval); 279 } 280 281 /** 282 * program_timing_generator 283 * Program CRTC Timing Registers - DxCRTC_H_*, DxCRTC_V_*, Pixel repetition. 284 * Call ASIC Control Object to program Timings. 285 */ 286 bool dce110_timing_generator_program_timing_generator( 287 struct timing_generator *tg, 288 const struct dc_crtc_timing *dc_crtc_timing) 289 { 290 enum bp_result result; 291 struct bp_hw_crtc_timing_parameters bp_params; 292 struct dc_crtc_timing patched_crtc_timing; 293 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 294 295 uint32_t vsync_offset = dc_crtc_timing->v_border_bottom + 296 dc_crtc_timing->v_front_porch; 297 uint32_t v_sync_start =dc_crtc_timing->v_addressable + vsync_offset; 298 299 uint32_t hsync_offset = dc_crtc_timing->h_border_right + 300 dc_crtc_timing->h_front_porch; 301 uint32_t h_sync_start = dc_crtc_timing->h_addressable + hsync_offset; 302 303 memset(&bp_params, 0, sizeof(struct bp_hw_crtc_timing_parameters)); 304 305 /* Due to an asic bug we need to apply the Front Porch workaround prior 306 * to programming the timing. 307 */ 308 309 patched_crtc_timing = *dc_crtc_timing; 310 311 dce110_timing_generator_apply_front_porch_workaround(tg, &patched_crtc_timing); 312 313 bp_params.controller_id = tg110->controller_id; 314 315 bp_params.h_total = patched_crtc_timing.h_total; 316 bp_params.h_addressable = 317 patched_crtc_timing.h_addressable; 318 bp_params.v_total = patched_crtc_timing.v_total; 319 bp_params.v_addressable = patched_crtc_timing.v_addressable; 320 321 bp_params.h_sync_start = h_sync_start; 322 bp_params.h_sync_width = patched_crtc_timing.h_sync_width; 323 bp_params.v_sync_start = v_sync_start; 324 bp_params.v_sync_width = patched_crtc_timing.v_sync_width; 325 326 /* Set overscan */ 327 bp_params.h_overscan_left = 328 patched_crtc_timing.h_border_left; 329 bp_params.h_overscan_right = 330 patched_crtc_timing.h_border_right; 331 bp_params.v_overscan_top = patched_crtc_timing.v_border_top; 332 bp_params.v_overscan_bottom = 333 patched_crtc_timing.v_border_bottom; 334 335 /* Set flags */ 336 if (patched_crtc_timing.flags.HSYNC_POSITIVE_POLARITY == 1) 337 bp_params.flags.HSYNC_POSITIVE_POLARITY = 1; 338 339 if (patched_crtc_timing.flags.VSYNC_POSITIVE_POLARITY == 1) 340 bp_params.flags.VSYNC_POSITIVE_POLARITY = 1; 341 342 if (patched_crtc_timing.flags.INTERLACE == 1) 343 bp_params.flags.INTERLACE = 1; 344 345 if (patched_crtc_timing.flags.HORZ_COUNT_BY_TWO == 1) 346 bp_params.flags.HORZ_COUNT_BY_TWO = 1; 347 348 result = tg->bp->funcs->program_crtc_timing(tg->bp, &bp_params); 349 350 program_horz_count_by_2(tg, &patched_crtc_timing); 351 352 tg110->base.funcs->enable_advanced_request(tg, true, &patched_crtc_timing); 353 354 /* Enable stereo - only when we need to pack 3D frame. Other types 355 * of stereo handled in explicit call */ 356 357 return result == BP_RESULT_OK; 358 } 359 360 /** 361 ***************************************************************************** 362 * Function: set_drr 363 * 364 * @brief 365 * Program dynamic refresh rate registers m_DxCRTC_V_TOTAL_*. 366 * 367 * @param [in] pHwCrtcTiming: point to H 368 * wCrtcTiming struct 369 ***************************************************************************** 370 */ 371 void dce110_timing_generator_set_drr( 372 struct timing_generator *tg, 373 const struct drr_params *params) 374 { 375 /* register values */ 376 uint32_t v_total_min = 0; 377 uint32_t v_total_max = 0; 378 uint32_t v_total_cntl = 0; 379 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 380 381 uint32_t addr = 0; 382 383 addr = CRTC_REG(mmCRTC_V_TOTAL_MIN); 384 v_total_min = dm_read_reg(tg->ctx, addr); 385 386 addr = CRTC_REG(mmCRTC_V_TOTAL_MAX); 387 v_total_max = dm_read_reg(tg->ctx, addr); 388 389 addr = CRTC_REG(mmCRTC_V_TOTAL_CONTROL); 390 v_total_cntl = dm_read_reg(tg->ctx, addr); 391 392 if (params != NULL && 393 params->vertical_total_max > 0 && 394 params->vertical_total_min > 0) { 395 396 set_reg_field_value(v_total_max, 397 params->vertical_total_max - 1, 398 CRTC_V_TOTAL_MAX, 399 CRTC_V_TOTAL_MAX); 400 401 set_reg_field_value(v_total_min, 402 params->vertical_total_min - 1, 403 CRTC_V_TOTAL_MIN, 404 CRTC_V_TOTAL_MIN); 405 406 set_reg_field_value(v_total_cntl, 407 1, 408 CRTC_V_TOTAL_CONTROL, 409 CRTC_V_TOTAL_MIN_SEL); 410 411 set_reg_field_value(v_total_cntl, 412 1, 413 CRTC_V_TOTAL_CONTROL, 414 CRTC_V_TOTAL_MAX_SEL); 415 416 set_reg_field_value(v_total_cntl, 417 0, 418 CRTC_V_TOTAL_CONTROL, 419 CRTC_FORCE_LOCK_ON_EVENT); 420 set_reg_field_value(v_total_cntl, 421 0, 422 CRTC_V_TOTAL_CONTROL, 423 CRTC_FORCE_LOCK_TO_MASTER_VSYNC); 424 425 set_reg_field_value(v_total_cntl, 426 0, 427 CRTC_V_TOTAL_CONTROL, 428 CRTC_SET_V_TOTAL_MIN_MASK_EN); 429 430 set_reg_field_value(v_total_cntl, 431 0, 432 CRTC_V_TOTAL_CONTROL, 433 CRTC_SET_V_TOTAL_MIN_MASK); 434 } else { 435 set_reg_field_value(v_total_cntl, 436 0, 437 CRTC_V_TOTAL_CONTROL, 438 CRTC_SET_V_TOTAL_MIN_MASK); 439 set_reg_field_value(v_total_cntl, 440 0, 441 CRTC_V_TOTAL_CONTROL, 442 CRTC_V_TOTAL_MIN_SEL); 443 set_reg_field_value(v_total_cntl, 444 0, 445 CRTC_V_TOTAL_CONTROL, 446 CRTC_V_TOTAL_MAX_SEL); 447 set_reg_field_value(v_total_min, 448 0, 449 CRTC_V_TOTAL_MIN, 450 CRTC_V_TOTAL_MIN); 451 set_reg_field_value(v_total_max, 452 0, 453 CRTC_V_TOTAL_MAX, 454 CRTC_V_TOTAL_MAX); 455 set_reg_field_value(v_total_cntl, 456 0, 457 CRTC_V_TOTAL_CONTROL, 458 CRTC_FORCE_LOCK_ON_EVENT); 459 set_reg_field_value(v_total_cntl, 460 0, 461 CRTC_V_TOTAL_CONTROL, 462 CRTC_FORCE_LOCK_TO_MASTER_VSYNC); 463 } 464 465 addr = CRTC_REG(mmCRTC_V_TOTAL_MIN); 466 dm_write_reg(tg->ctx, addr, v_total_min); 467 468 addr = CRTC_REG(mmCRTC_V_TOTAL_MAX); 469 dm_write_reg(tg->ctx, addr, v_total_max); 470 471 addr = CRTC_REG(mmCRTC_V_TOTAL_CONTROL); 472 dm_write_reg(tg->ctx, addr, v_total_cntl); 473 } 474 475 void dce110_timing_generator_set_static_screen_control( 476 struct timing_generator *tg, 477 uint32_t event_triggers, 478 uint32_t num_frames) 479 { 480 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 481 uint32_t static_screen_cntl = 0; 482 uint32_t addr = 0; 483 484 // By register spec, it only takes 8 bit value 485 if (num_frames > 0xFF) 486 num_frames = 0xFF; 487 488 addr = CRTC_REG(mmCRTC_STATIC_SCREEN_CONTROL); 489 static_screen_cntl = dm_read_reg(tg->ctx, addr); 490 491 set_reg_field_value(static_screen_cntl, 492 event_triggers, 493 CRTC_STATIC_SCREEN_CONTROL, 494 CRTC_STATIC_SCREEN_EVENT_MASK); 495 496 set_reg_field_value(static_screen_cntl, 497 num_frames, 498 CRTC_STATIC_SCREEN_CONTROL, 499 CRTC_STATIC_SCREEN_FRAME_COUNT); 500 501 dm_write_reg(tg->ctx, addr, static_screen_cntl); 502 } 503 504 /* 505 * get_vblank_counter 506 * 507 * @brief 508 * Get counter for vertical blanks. use register CRTC_STATUS_FRAME_COUNT which 509 * holds the counter of frames. 510 * 511 * @param 512 * struct timing_generator *tg - [in] timing generator which controls the 513 * desired CRTC 514 * 515 * @return 516 * Counter of frames, which should equal to number of vblanks. 517 */ 518 uint32_t dce110_timing_generator_get_vblank_counter(struct timing_generator *tg) 519 { 520 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 521 uint32_t addr = CRTC_REG(mmCRTC_STATUS_FRAME_COUNT); 522 uint32_t value = dm_read_reg(tg->ctx, addr); 523 uint32_t field = get_reg_field_value( 524 value, CRTC_STATUS_FRAME_COUNT, CRTC_FRAME_COUNT); 525 526 return field; 527 } 528 529 /** 530 ***************************************************************************** 531 * Function: dce110_timing_generator_get_position 532 * 533 * @brief 534 * Returns CRTC vertical/horizontal counters 535 * 536 * @param [out] position 537 ***************************************************************************** 538 */ 539 void dce110_timing_generator_get_position(struct timing_generator *tg, 540 struct crtc_position *position) 541 { 542 uint32_t value; 543 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 544 545 value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_STATUS_POSITION)); 546 547 position->horizontal_count = get_reg_field_value( 548 value, 549 CRTC_STATUS_POSITION, 550 CRTC_HORZ_COUNT); 551 552 position->vertical_count = get_reg_field_value( 553 value, 554 CRTC_STATUS_POSITION, 555 CRTC_VERT_COUNT); 556 557 value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_NOM_VERT_POSITION)); 558 559 position->nominal_vcount = get_reg_field_value( 560 value, 561 CRTC_NOM_VERT_POSITION, 562 CRTC_VERT_COUNT_NOM); 563 } 564 565 /** 566 ***************************************************************************** 567 * Function: get_crtc_scanoutpos 568 * 569 * @brief 570 * Returns CRTC vertical/horizontal counters 571 * 572 * @param [out] vpos, hpos 573 ***************************************************************************** 574 */ 575 void dce110_timing_generator_get_crtc_scanoutpos( 576 struct timing_generator *tg, 577 uint32_t *v_blank_start, 578 uint32_t *v_blank_end, 579 uint32_t *h_position, 580 uint32_t *v_position) 581 { 582 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 583 struct crtc_position position; 584 585 uint32_t value = dm_read_reg(tg->ctx, 586 CRTC_REG(mmCRTC_V_BLANK_START_END)); 587 588 *v_blank_start = get_reg_field_value(value, 589 CRTC_V_BLANK_START_END, 590 CRTC_V_BLANK_START); 591 *v_blank_end = get_reg_field_value(value, 592 CRTC_V_BLANK_START_END, 593 CRTC_V_BLANK_END); 594 595 dce110_timing_generator_get_position( 596 tg, &position); 597 598 *h_position = position.horizontal_count; 599 *v_position = position.vertical_count; 600 } 601 602 /* TODO: is it safe to assume that mask/shift of Primary and Underlay 603 * are the same? 604 * For example: today CRTC_H_TOTAL == CRTCV_H_TOTAL but is it always 605 * guaranteed? */ 606 void dce110_timing_generator_program_blanking( 607 struct timing_generator *tg, 608 const struct dc_crtc_timing *timing) 609 { 610 uint32_t vsync_offset = timing->v_border_bottom + 611 timing->v_front_porch; 612 uint32_t v_sync_start =timing->v_addressable + vsync_offset; 613 614 uint32_t hsync_offset = timing->h_border_right + 615 timing->h_front_porch; 616 uint32_t h_sync_start = timing->h_addressable + hsync_offset; 617 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 618 619 struct dc_context *ctx = tg->ctx; 620 uint32_t value = 0; 621 uint32_t addr = 0; 622 uint32_t tmp = 0; 623 624 addr = CRTC_REG(mmCRTC_H_TOTAL); 625 value = dm_read_reg(ctx, addr); 626 set_reg_field_value( 627 value, 628 timing->h_total - 1, 629 CRTC_H_TOTAL, 630 CRTC_H_TOTAL); 631 dm_write_reg(ctx, addr, value); 632 633 addr = CRTC_REG(mmCRTC_V_TOTAL); 634 value = dm_read_reg(ctx, addr); 635 set_reg_field_value( 636 value, 637 timing->v_total - 1, 638 CRTC_V_TOTAL, 639 CRTC_V_TOTAL); 640 dm_write_reg(ctx, addr, value); 641 642 /* In case of V_TOTAL_CONTROL is on, make sure V_TOTAL_MAX and 643 * V_TOTAL_MIN are equal to V_TOTAL. 644 */ 645 addr = CRTC_REG(mmCRTC_V_TOTAL_MAX); 646 value = dm_read_reg(ctx, addr); 647 set_reg_field_value( 648 value, 649 timing->v_total - 1, 650 CRTC_V_TOTAL_MAX, 651 CRTC_V_TOTAL_MAX); 652 dm_write_reg(ctx, addr, value); 653 654 addr = CRTC_REG(mmCRTC_V_TOTAL_MIN); 655 value = dm_read_reg(ctx, addr); 656 set_reg_field_value( 657 value, 658 timing->v_total - 1, 659 CRTC_V_TOTAL_MIN, 660 CRTC_V_TOTAL_MIN); 661 dm_write_reg(ctx, addr, value); 662 663 addr = CRTC_REG(mmCRTC_H_BLANK_START_END); 664 value = dm_read_reg(ctx, addr); 665 666 tmp = timing->h_total - 667 (h_sync_start + timing->h_border_left); 668 669 set_reg_field_value( 670 value, 671 tmp, 672 CRTC_H_BLANK_START_END, 673 CRTC_H_BLANK_END); 674 675 tmp = tmp + timing->h_addressable + 676 timing->h_border_left + timing->h_border_right; 677 678 set_reg_field_value( 679 value, 680 tmp, 681 CRTC_H_BLANK_START_END, 682 CRTC_H_BLANK_START); 683 684 dm_write_reg(ctx, addr, value); 685 686 addr = CRTC_REG(mmCRTC_V_BLANK_START_END); 687 value = dm_read_reg(ctx, addr); 688 689 tmp = timing->v_total - (v_sync_start + timing->v_border_top); 690 691 set_reg_field_value( 692 value, 693 tmp, 694 CRTC_V_BLANK_START_END, 695 CRTC_V_BLANK_END); 696 697 tmp = tmp + timing->v_addressable + timing->v_border_top + 698 timing->v_border_bottom; 699 700 set_reg_field_value( 701 value, 702 tmp, 703 CRTC_V_BLANK_START_END, 704 CRTC_V_BLANK_START); 705 706 dm_write_reg(ctx, addr, value); 707 } 708 709 void dce110_timing_generator_set_test_pattern( 710 struct timing_generator *tg, 711 /* TODO: replace 'controller_dp_test_pattern' by 'test_pattern_mode' 712 * because this is not DP-specific (which is probably somewhere in DP 713 * encoder) */ 714 enum controller_dp_test_pattern test_pattern, 715 enum dc_color_depth color_depth) 716 { 717 struct dc_context *ctx = tg->ctx; 718 uint32_t value; 719 uint32_t addr; 720 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 721 enum test_pattern_color_format bit_depth; 722 enum test_pattern_dyn_range dyn_range; 723 enum test_pattern_mode mode; 724 /* color ramp generator mixes 16-bits color */ 725 uint32_t src_bpc = 16; 726 /* requested bpc */ 727 uint32_t dst_bpc; 728 uint32_t index; 729 /* RGB values of the color bars. 730 * Produce two RGB colors: RGB0 - white (all Fs) 731 * and RGB1 - black (all 0s) 732 * (three RGB components for two colors) 733 */ 734 uint16_t src_color[6] = {0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 735 0x0000, 0x0000}; 736 /* dest color (converted to the specified color format) */ 737 uint16_t dst_color[6]; 738 uint32_t inc_base; 739 740 /* translate to bit depth */ 741 switch (color_depth) { 742 case COLOR_DEPTH_666: 743 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_6; 744 break; 745 case COLOR_DEPTH_888: 746 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8; 747 break; 748 case COLOR_DEPTH_101010: 749 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_10; 750 break; 751 case COLOR_DEPTH_121212: 752 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_12; 753 break; 754 default: 755 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8; 756 break; 757 } 758 759 switch (test_pattern) { 760 case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES: 761 case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA: 762 { 763 dyn_range = (test_pattern == 764 CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA ? 765 TEST_PATTERN_DYN_RANGE_CEA : 766 TEST_PATTERN_DYN_RANGE_VESA); 767 mode = TEST_PATTERN_MODE_COLORSQUARES_RGB; 768 value = 0; 769 addr = CRTC_REG(mmCRTC_TEST_PATTERN_PARAMETERS); 770 771 set_reg_field_value( 772 value, 773 6, 774 CRTC_TEST_PATTERN_PARAMETERS, 775 CRTC_TEST_PATTERN_VRES); 776 set_reg_field_value( 777 value, 778 6, 779 CRTC_TEST_PATTERN_PARAMETERS, 780 CRTC_TEST_PATTERN_HRES); 781 782 dm_write_reg(ctx, addr, value); 783 784 addr = CRTC_REG(mmCRTC_TEST_PATTERN_CONTROL); 785 value = 0; 786 787 set_reg_field_value( 788 value, 789 1, 790 CRTC_TEST_PATTERN_CONTROL, 791 CRTC_TEST_PATTERN_EN); 792 793 set_reg_field_value( 794 value, 795 mode, 796 CRTC_TEST_PATTERN_CONTROL, 797 CRTC_TEST_PATTERN_MODE); 798 799 set_reg_field_value( 800 value, 801 dyn_range, 802 CRTC_TEST_PATTERN_CONTROL, 803 CRTC_TEST_PATTERN_DYNAMIC_RANGE); 804 set_reg_field_value( 805 value, 806 bit_depth, 807 CRTC_TEST_PATTERN_CONTROL, 808 CRTC_TEST_PATTERN_COLOR_FORMAT); 809 dm_write_reg(ctx, addr, value); 810 } 811 break; 812 813 case CONTROLLER_DP_TEST_PATTERN_VERTICALBARS: 814 case CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS: 815 { 816 mode = (test_pattern == 817 CONTROLLER_DP_TEST_PATTERN_VERTICALBARS ? 818 TEST_PATTERN_MODE_VERTICALBARS : 819 TEST_PATTERN_MODE_HORIZONTALBARS); 820 821 switch (bit_depth) { 822 case TEST_PATTERN_COLOR_FORMAT_BPC_6: 823 dst_bpc = 6; 824 break; 825 case TEST_PATTERN_COLOR_FORMAT_BPC_8: 826 dst_bpc = 8; 827 break; 828 case TEST_PATTERN_COLOR_FORMAT_BPC_10: 829 dst_bpc = 10; 830 break; 831 default: 832 dst_bpc = 8; 833 break; 834 } 835 836 /* adjust color to the required colorFormat */ 837 for (index = 0; index < 6; index++) { 838 /* dst = 2^dstBpc * src / 2^srcBpc = src >> 839 * (srcBpc - dstBpc); 840 */ 841 dst_color[index] = 842 src_color[index] >> (src_bpc - dst_bpc); 843 /* CRTC_TEST_PATTERN_DATA has 16 bits, 844 * lowest 6 are hardwired to ZERO 845 * color bits should be left aligned aligned to MSB 846 * XXXXXXXXXX000000 for 10 bit, 847 * XXXXXXXX00000000 for 8 bit and XXXXXX0000000000 for 6 848 */ 849 dst_color[index] <<= (16 - dst_bpc); 850 } 851 852 value = 0; 853 addr = CRTC_REG(mmCRTC_TEST_PATTERN_PARAMETERS); 854 dm_write_reg(ctx, addr, value); 855 856 /* We have to write the mask before data, similar to pipeline. 857 * For example, for 8 bpc, if we want RGB0 to be magenta, 858 * and RGB1 to be cyan, 859 * we need to make 7 writes: 860 * MASK DATA 861 * 000001 00000000 00000000 set mask to R0 862 * 000010 11111111 00000000 R0 255, 0xFF00, set mask to G0 863 * 000100 00000000 00000000 G0 0, 0x0000, set mask to B0 864 * 001000 11111111 00000000 B0 255, 0xFF00, set mask to R1 865 * 010000 00000000 00000000 R1 0, 0x0000, set mask to G1 866 * 100000 11111111 00000000 G1 255, 0xFF00, set mask to B1 867 * 100000 11111111 00000000 B1 255, 0xFF00 868 * 869 * we will make a loop of 6 in which we prepare the mask, 870 * then write, then prepare the color for next write. 871 * first iteration will write mask only, 872 * but each next iteration color prepared in 873 * previous iteration will be written within new mask, 874 * the last component will written separately, 875 * mask is not changing between 6th and 7th write 876 * and color will be prepared by last iteration 877 */ 878 879 /* write color, color values mask in CRTC_TEST_PATTERN_MASK 880 * is B1, G1, R1, B0, G0, R0 881 */ 882 value = 0; 883 addr = CRTC_REG(mmCRTC_TEST_PATTERN_COLOR); 884 for (index = 0; index < 6; index++) { 885 /* prepare color mask, first write PATTERN_DATA 886 * will have all zeros 887 */ 888 set_reg_field_value( 889 value, 890 (1 << index), 891 CRTC_TEST_PATTERN_COLOR, 892 CRTC_TEST_PATTERN_MASK); 893 /* write color component */ 894 dm_write_reg(ctx, addr, value); 895 /* prepare next color component, 896 * will be written in the next iteration 897 */ 898 set_reg_field_value( 899 value, 900 dst_color[index], 901 CRTC_TEST_PATTERN_COLOR, 902 CRTC_TEST_PATTERN_DATA); 903 } 904 /* write last color component, 905 * it's been already prepared in the loop 906 */ 907 dm_write_reg(ctx, addr, value); 908 909 /* enable test pattern */ 910 addr = CRTC_REG(mmCRTC_TEST_PATTERN_CONTROL); 911 value = 0; 912 913 set_reg_field_value( 914 value, 915 1, 916 CRTC_TEST_PATTERN_CONTROL, 917 CRTC_TEST_PATTERN_EN); 918 919 set_reg_field_value( 920 value, 921 mode, 922 CRTC_TEST_PATTERN_CONTROL, 923 CRTC_TEST_PATTERN_MODE); 924 925 set_reg_field_value( 926 value, 927 0, 928 CRTC_TEST_PATTERN_CONTROL, 929 CRTC_TEST_PATTERN_DYNAMIC_RANGE); 930 931 set_reg_field_value( 932 value, 933 bit_depth, 934 CRTC_TEST_PATTERN_CONTROL, 935 CRTC_TEST_PATTERN_COLOR_FORMAT); 936 937 dm_write_reg(ctx, addr, value); 938 } 939 break; 940 941 case CONTROLLER_DP_TEST_PATTERN_COLORRAMP: 942 { 943 mode = (bit_depth == 944 TEST_PATTERN_COLOR_FORMAT_BPC_10 ? 945 TEST_PATTERN_MODE_DUALRAMP_RGB : 946 TEST_PATTERN_MODE_SINGLERAMP_RGB); 947 948 switch (bit_depth) { 949 case TEST_PATTERN_COLOR_FORMAT_BPC_6: 950 dst_bpc = 6; 951 break; 952 case TEST_PATTERN_COLOR_FORMAT_BPC_8: 953 dst_bpc = 8; 954 break; 955 case TEST_PATTERN_COLOR_FORMAT_BPC_10: 956 dst_bpc = 10; 957 break; 958 default: 959 dst_bpc = 8; 960 break; 961 } 962 963 /* increment for the first ramp for one color gradation 964 * 1 gradation for 6-bit color is 2^10 965 * gradations in 16-bit color 966 */ 967 inc_base = (src_bpc - dst_bpc); 968 969 value = 0; 970 addr = CRTC_REG(mmCRTC_TEST_PATTERN_PARAMETERS); 971 972 switch (bit_depth) { 973 case TEST_PATTERN_COLOR_FORMAT_BPC_6: 974 { 975 set_reg_field_value( 976 value, 977 inc_base, 978 CRTC_TEST_PATTERN_PARAMETERS, 979 CRTC_TEST_PATTERN_INC0); 980 set_reg_field_value( 981 value, 982 0, 983 CRTC_TEST_PATTERN_PARAMETERS, 984 CRTC_TEST_PATTERN_INC1); 985 set_reg_field_value( 986 value, 987 6, 988 CRTC_TEST_PATTERN_PARAMETERS, 989 CRTC_TEST_PATTERN_HRES); 990 set_reg_field_value( 991 value, 992 6, 993 CRTC_TEST_PATTERN_PARAMETERS, 994 CRTC_TEST_PATTERN_VRES); 995 set_reg_field_value( 996 value, 997 0, 998 CRTC_TEST_PATTERN_PARAMETERS, 999 CRTC_TEST_PATTERN_RAMP0_OFFSET); 1000 } 1001 break; 1002 case TEST_PATTERN_COLOR_FORMAT_BPC_8: 1003 { 1004 set_reg_field_value( 1005 value, 1006 inc_base, 1007 CRTC_TEST_PATTERN_PARAMETERS, 1008 CRTC_TEST_PATTERN_INC0); 1009 set_reg_field_value( 1010 value, 1011 0, 1012 CRTC_TEST_PATTERN_PARAMETERS, 1013 CRTC_TEST_PATTERN_INC1); 1014 set_reg_field_value( 1015 value, 1016 8, 1017 CRTC_TEST_PATTERN_PARAMETERS, 1018 CRTC_TEST_PATTERN_HRES); 1019 set_reg_field_value( 1020 value, 1021 6, 1022 CRTC_TEST_PATTERN_PARAMETERS, 1023 CRTC_TEST_PATTERN_VRES); 1024 set_reg_field_value( 1025 value, 1026 0, 1027 CRTC_TEST_PATTERN_PARAMETERS, 1028 CRTC_TEST_PATTERN_RAMP0_OFFSET); 1029 } 1030 break; 1031 case TEST_PATTERN_COLOR_FORMAT_BPC_10: 1032 { 1033 set_reg_field_value( 1034 value, 1035 inc_base, 1036 CRTC_TEST_PATTERN_PARAMETERS, 1037 CRTC_TEST_PATTERN_INC0); 1038 set_reg_field_value( 1039 value, 1040 inc_base + 2, 1041 CRTC_TEST_PATTERN_PARAMETERS, 1042 CRTC_TEST_PATTERN_INC1); 1043 set_reg_field_value( 1044 value, 1045 8, 1046 CRTC_TEST_PATTERN_PARAMETERS, 1047 CRTC_TEST_PATTERN_HRES); 1048 set_reg_field_value( 1049 value, 1050 5, 1051 CRTC_TEST_PATTERN_PARAMETERS, 1052 CRTC_TEST_PATTERN_VRES); 1053 set_reg_field_value( 1054 value, 1055 384 << 6, 1056 CRTC_TEST_PATTERN_PARAMETERS, 1057 CRTC_TEST_PATTERN_RAMP0_OFFSET); 1058 } 1059 break; 1060 default: 1061 break; 1062 } 1063 dm_write_reg(ctx, addr, value); 1064 1065 value = 0; 1066 addr = CRTC_REG(mmCRTC_TEST_PATTERN_COLOR); 1067 dm_write_reg(ctx, addr, value); 1068 1069 /* enable test pattern */ 1070 addr = CRTC_REG(mmCRTC_TEST_PATTERN_CONTROL); 1071 value = 0; 1072 1073 set_reg_field_value( 1074 value, 1075 1, 1076 CRTC_TEST_PATTERN_CONTROL, 1077 CRTC_TEST_PATTERN_EN); 1078 1079 set_reg_field_value( 1080 value, 1081 mode, 1082 CRTC_TEST_PATTERN_CONTROL, 1083 CRTC_TEST_PATTERN_MODE); 1084 1085 set_reg_field_value( 1086 value, 1087 0, 1088 CRTC_TEST_PATTERN_CONTROL, 1089 CRTC_TEST_PATTERN_DYNAMIC_RANGE); 1090 /* add color depth translation here */ 1091 set_reg_field_value( 1092 value, 1093 bit_depth, 1094 CRTC_TEST_PATTERN_CONTROL, 1095 CRTC_TEST_PATTERN_COLOR_FORMAT); 1096 1097 dm_write_reg(ctx, addr, value); 1098 } 1099 break; 1100 case CONTROLLER_DP_TEST_PATTERN_VIDEOMODE: 1101 { 1102 value = 0; 1103 dm_write_reg(ctx, CRTC_REG(mmCRTC_TEST_PATTERN_CONTROL), value); 1104 dm_write_reg(ctx, CRTC_REG(mmCRTC_TEST_PATTERN_COLOR), value); 1105 dm_write_reg(ctx, CRTC_REG(mmCRTC_TEST_PATTERN_PARAMETERS), 1106 value); 1107 } 1108 break; 1109 default: 1110 break; 1111 } 1112 } 1113 1114 /** 1115 * dce110_timing_generator_validate_timing 1116 * The timing generators support a maximum display size of is 8192 x 8192 pixels, 1117 * including both active display and blanking periods. Check H Total and V Total. 1118 */ 1119 bool dce110_timing_generator_validate_timing( 1120 struct timing_generator *tg, 1121 const struct dc_crtc_timing *timing, 1122 enum signal_type signal) 1123 { 1124 uint32_t h_blank; 1125 uint32_t h_back_porch, hsync_offset, h_sync_start; 1126 1127 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 1128 1129 ASSERT(timing != NULL); 1130 1131 if (!timing) 1132 return false; 1133 1134 hsync_offset = timing->h_border_right + timing->h_front_porch; 1135 h_sync_start = timing->h_addressable + hsync_offset; 1136 1137 /* Currently we don't support 3D, so block all 3D timings */ 1138 if (timing->timing_3d_format != TIMING_3D_FORMAT_NONE) 1139 return false; 1140 1141 /* Temporarily blocking interlacing mode until it's supported */ 1142 if (timing->flags.INTERLACE == 1) 1143 return false; 1144 1145 /* Check maximum number of pixels supported by Timing Generator 1146 * (Currently will never fail, in order to fail needs display which 1147 * needs more than 8192 horizontal and 1148 * more than 8192 vertical total pixels) 1149 */ 1150 if (timing->h_total > tg110->max_h_total || 1151 timing->v_total > tg110->max_v_total) 1152 return false; 1153 1154 h_blank = (timing->h_total - timing->h_addressable - 1155 timing->h_border_right - 1156 timing->h_border_left); 1157 1158 if (h_blank < tg110->min_h_blank) 1159 return false; 1160 1161 if (timing->h_front_porch < tg110->min_h_front_porch) 1162 return false; 1163 1164 h_back_porch = h_blank - (h_sync_start - 1165 timing->h_addressable - 1166 timing->h_border_right - 1167 timing->h_sync_width); 1168 1169 if (h_back_porch < tg110->min_h_back_porch) 1170 return false; 1171 1172 return true; 1173 } 1174 1175 /** 1176 * Wait till we are at the beginning of VBlank. 1177 */ 1178 void dce110_timing_generator_wait_for_vblank(struct timing_generator *tg) 1179 { 1180 /* We want to catch beginning of VBlank here, so if the first try are 1181 * in VBlank, we might be very close to Active, in this case wait for 1182 * another frame 1183 */ 1184 while (dce110_timing_generator_is_in_vertical_blank(tg)) { 1185 if (!dce110_timing_generator_is_counter_moving(tg)) { 1186 /* error - no point to wait if counter is not moving */ 1187 break; 1188 } 1189 } 1190 1191 while (!dce110_timing_generator_is_in_vertical_blank(tg)) { 1192 if (!dce110_timing_generator_is_counter_moving(tg)) { 1193 /* error - no point to wait if counter is not moving */ 1194 break; 1195 } 1196 } 1197 } 1198 1199 /** 1200 * Wait till we are in VActive (anywhere in VActive) 1201 */ 1202 void dce110_timing_generator_wait_for_vactive(struct timing_generator *tg) 1203 { 1204 while (dce110_timing_generator_is_in_vertical_blank(tg)) { 1205 if (!dce110_timing_generator_is_counter_moving(tg)) { 1206 /* error - no point to wait if counter is not moving */ 1207 break; 1208 } 1209 } 1210 } 1211 1212 /** 1213 ***************************************************************************** 1214 * Function: dce110_timing_generator_setup_global_swap_lock 1215 * 1216 * @brief 1217 * Setups Global Swap Lock group for current pipe 1218 * Pipe can join or leave GSL group, become a TimingServer or TimingClient 1219 * 1220 * @param [in] gsl_params: setup data 1221 ***************************************************************************** 1222 */ 1223 1224 void dce110_timing_generator_setup_global_swap_lock( 1225 struct timing_generator *tg, 1226 const struct dcp_gsl_params *gsl_params) 1227 { 1228 uint32_t value; 1229 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 1230 uint32_t address = DCP_REG(mmDCP_GSL_CONTROL); 1231 uint32_t check_point = FLIP_READY_BACK_LOOKUP; 1232 1233 value = dm_read_reg(tg->ctx, address); 1234 1235 /* This pipe will belong to GSL Group zero. */ 1236 set_reg_field_value(value, 1237 1, 1238 DCP_GSL_CONTROL, 1239 DCP_GSL0_EN); 1240 1241 set_reg_field_value(value, 1242 gsl_params->gsl_master == tg->inst, 1243 DCP_GSL_CONTROL, 1244 DCP_GSL_MASTER_EN); 1245 1246 set_reg_field_value(value, 1247 HFLIP_READY_DELAY, 1248 DCP_GSL_CONTROL, 1249 DCP_GSL_HSYNC_FLIP_FORCE_DELAY); 1250 1251 /* Keep signal low (pending high) during 6 lines. 1252 * Also defines minimum interval before re-checking signal. */ 1253 set_reg_field_value(value, 1254 HFLIP_CHECK_DELAY, 1255 DCP_GSL_CONTROL, 1256 DCP_GSL_HSYNC_FLIP_CHECK_DELAY); 1257 1258 dm_write_reg(tg->ctx, CRTC_REG(mmDCP_GSL_CONTROL), value); 1259 value = 0; 1260 1261 set_reg_field_value(value, 1262 gsl_params->gsl_master, 1263 DCIO_GSL0_CNTL, 1264 DCIO_GSL0_VSYNC_SEL); 1265 1266 set_reg_field_value(value, 1267 0, 1268 DCIO_GSL0_CNTL, 1269 DCIO_GSL0_TIMING_SYNC_SEL); 1270 1271 set_reg_field_value(value, 1272 0, 1273 DCIO_GSL0_CNTL, 1274 DCIO_GSL0_GLOBAL_UNLOCK_SEL); 1275 1276 dm_write_reg(tg->ctx, CRTC_REG(mmDCIO_GSL0_CNTL), value); 1277 1278 1279 { 1280 uint32_t value_crtc_vtotal; 1281 1282 value_crtc_vtotal = dm_read_reg(tg->ctx, 1283 CRTC_REG(mmCRTC_V_TOTAL)); 1284 1285 set_reg_field_value(value, 1286 0,/* DCP_GSL_PURPOSE_SURFACE_FLIP */ 1287 DCP_GSL_CONTROL, 1288 DCP_GSL_SYNC_SOURCE); 1289 1290 /* Checkpoint relative to end of frame */ 1291 check_point = get_reg_field_value(value_crtc_vtotal, 1292 CRTC_V_TOTAL, 1293 CRTC_V_TOTAL); 1294 1295 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_GSL_WINDOW), 0); 1296 } 1297 1298 set_reg_field_value(value, 1299 1, 1300 DCP_GSL_CONTROL, 1301 DCP_GSL_DELAY_SURFACE_UPDATE_PENDING); 1302 1303 dm_write_reg(tg->ctx, address, value); 1304 1305 /********************************************************************/ 1306 address = CRTC_REG(mmCRTC_GSL_CONTROL); 1307 1308 value = dm_read_reg(tg->ctx, address); 1309 set_reg_field_value(value, 1310 check_point - FLIP_READY_BACK_LOOKUP, 1311 CRTC_GSL_CONTROL, 1312 CRTC_GSL_CHECK_LINE_NUM); 1313 1314 set_reg_field_value(value, 1315 VFLIP_READY_DELAY, 1316 CRTC_GSL_CONTROL, 1317 CRTC_GSL_FORCE_DELAY); 1318 1319 dm_write_reg(tg->ctx, address, value); 1320 } 1321 1322 void dce110_timing_generator_tear_down_global_swap_lock( 1323 struct timing_generator *tg) 1324 { 1325 /* Clear all the register writes done by 1326 * dce110_timing_generator_setup_global_swap_lock 1327 */ 1328 1329 uint32_t value; 1330 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 1331 uint32_t address = DCP_REG(mmDCP_GSL_CONTROL); 1332 1333 value = 0; 1334 1335 /* This pipe will belong to GSL Group zero. */ 1336 /* Settig HW default values from reg specs */ 1337 set_reg_field_value(value, 1338 0, 1339 DCP_GSL_CONTROL, 1340 DCP_GSL0_EN); 1341 1342 set_reg_field_value(value, 1343 0, 1344 DCP_GSL_CONTROL, 1345 DCP_GSL_MASTER_EN); 1346 1347 set_reg_field_value(value, 1348 0x2, 1349 DCP_GSL_CONTROL, 1350 DCP_GSL_HSYNC_FLIP_FORCE_DELAY); 1351 1352 set_reg_field_value(value, 1353 0x6, 1354 DCP_GSL_CONTROL, 1355 DCP_GSL_HSYNC_FLIP_CHECK_DELAY); 1356 1357 /* Restore DCP_GSL_PURPOSE_SURFACE_FLIP */ 1358 { 1359 uint32_t value_crtc_vtotal __unused; 1360 1361 value_crtc_vtotal = dm_read_reg(tg->ctx, 1362 CRTC_REG(mmCRTC_V_TOTAL)); 1363 1364 set_reg_field_value(value, 1365 0, 1366 DCP_GSL_CONTROL, 1367 DCP_GSL_SYNC_SOURCE); 1368 } 1369 1370 set_reg_field_value(value, 1371 0, 1372 DCP_GSL_CONTROL, 1373 DCP_GSL_DELAY_SURFACE_UPDATE_PENDING); 1374 1375 dm_write_reg(tg->ctx, address, value); 1376 1377 /********************************************************************/ 1378 address = CRTC_REG(mmCRTC_GSL_CONTROL); 1379 1380 value = 0; 1381 set_reg_field_value(value, 1382 0, 1383 CRTC_GSL_CONTROL, 1384 CRTC_GSL_CHECK_LINE_NUM); 1385 1386 set_reg_field_value(value, 1387 0x2, 1388 CRTC_GSL_CONTROL, 1389 CRTC_GSL_FORCE_DELAY); 1390 1391 dm_write_reg(tg->ctx, address, value); 1392 } 1393 /** 1394 ***************************************************************************** 1395 * Function: is_counter_moving 1396 * 1397 * @brief 1398 * check if the timing generator is currently going 1399 * 1400 * @return 1401 * true if currently going, false if currently paused or stopped. 1402 * 1403 ***************************************************************************** 1404 */ 1405 bool dce110_timing_generator_is_counter_moving(struct timing_generator *tg) 1406 { 1407 struct crtc_position position1, position2; 1408 1409 tg->funcs->get_position(tg, &position1); 1410 tg->funcs->get_position(tg, &position2); 1411 1412 if (position1.horizontal_count == position2.horizontal_count && 1413 position1.vertical_count == position2.vertical_count) 1414 return false; 1415 else 1416 return true; 1417 } 1418 1419 void dce110_timing_generator_enable_advanced_request( 1420 struct timing_generator *tg, 1421 bool enable, 1422 const struct dc_crtc_timing *timing) 1423 { 1424 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 1425 uint32_t addr = CRTC_REG(mmCRTC_START_LINE_CONTROL); 1426 uint32_t value = dm_read_reg(tg->ctx, addr); 1427 1428 if (enable) { 1429 set_reg_field_value( 1430 value, 1431 0, 1432 CRTC_START_LINE_CONTROL, 1433 CRTC_LEGACY_REQUESTOR_EN); 1434 } else { 1435 set_reg_field_value( 1436 value, 1437 1, 1438 CRTC_START_LINE_CONTROL, 1439 CRTC_LEGACY_REQUESTOR_EN); 1440 } 1441 1442 if ((timing->v_sync_width + timing->v_front_porch) <= 3) { 1443 set_reg_field_value( 1444 value, 1445 3, 1446 CRTC_START_LINE_CONTROL, 1447 CRTC_ADVANCED_START_LINE_POSITION); 1448 set_reg_field_value( 1449 value, 1450 0, 1451 CRTC_START_LINE_CONTROL, 1452 CRTC_PREFETCH_EN); 1453 } else { 1454 set_reg_field_value( 1455 value, 1456 4, 1457 CRTC_START_LINE_CONTROL, 1458 CRTC_ADVANCED_START_LINE_POSITION); 1459 set_reg_field_value( 1460 value, 1461 1, 1462 CRTC_START_LINE_CONTROL, 1463 CRTC_PREFETCH_EN); 1464 } 1465 1466 set_reg_field_value( 1467 value, 1468 1, 1469 CRTC_START_LINE_CONTROL, 1470 CRTC_PROGRESSIVE_START_LINE_EARLY); 1471 1472 set_reg_field_value( 1473 value, 1474 1, 1475 CRTC_START_LINE_CONTROL, 1476 CRTC_INTERLACE_START_LINE_EARLY); 1477 1478 dm_write_reg(tg->ctx, addr, value); 1479 } 1480 1481 /*TODO: Figure out if we need this function. */ 1482 void dce110_timing_generator_set_lock_master(struct timing_generator *tg, 1483 bool lock) 1484 { 1485 struct dc_context *ctx = tg->ctx; 1486 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 1487 uint32_t addr = CRTC_REG(mmCRTC_MASTER_UPDATE_LOCK); 1488 uint32_t value = dm_read_reg(ctx, addr); 1489 1490 set_reg_field_value( 1491 value, 1492 lock ? 1 : 0, 1493 CRTC_MASTER_UPDATE_LOCK, 1494 MASTER_UPDATE_LOCK); 1495 1496 dm_write_reg(ctx, addr, value); 1497 } 1498 1499 void dce110_timing_generator_enable_reset_trigger( 1500 struct timing_generator *tg, 1501 int source_tg_inst) 1502 { 1503 uint32_t value; 1504 uint32_t rising_edge = 0; 1505 uint32_t falling_edge = 0; 1506 enum trigger_source_select trig_src_select = TRIGGER_SOURCE_SELECT_LOGIC_ZERO; 1507 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 1508 1509 /* Setup trigger edge */ 1510 { 1511 uint32_t pol_value = dm_read_reg(tg->ctx, 1512 CRTC_REG(mmCRTC_V_SYNC_A_CNTL)); 1513 1514 /* Register spec has reversed definition: 1515 * 0 for positive, 1 for negative */ 1516 if (get_reg_field_value(pol_value, 1517 CRTC_V_SYNC_A_CNTL, 1518 CRTC_V_SYNC_A_POL) == 0) { 1519 rising_edge = 1; 1520 } else { 1521 falling_edge = 1; 1522 } 1523 } 1524 1525 value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL)); 1526 1527 trig_src_select = TRIGGER_SOURCE_SELECT_GSL_GROUP0; 1528 1529 set_reg_field_value(value, 1530 trig_src_select, 1531 CRTC_TRIGB_CNTL, 1532 CRTC_TRIGB_SOURCE_SELECT); 1533 1534 set_reg_field_value(value, 1535 TRIGGER_POLARITY_SELECT_LOGIC_ZERO, 1536 CRTC_TRIGB_CNTL, 1537 CRTC_TRIGB_POLARITY_SELECT); 1538 1539 set_reg_field_value(value, 1540 rising_edge, 1541 CRTC_TRIGB_CNTL, 1542 CRTC_TRIGB_RISING_EDGE_DETECT_CNTL); 1543 1544 set_reg_field_value(value, 1545 falling_edge, 1546 CRTC_TRIGB_CNTL, 1547 CRTC_TRIGB_FALLING_EDGE_DETECT_CNTL); 1548 1549 set_reg_field_value(value, 1550 0, /* send every signal */ 1551 CRTC_TRIGB_CNTL, 1552 CRTC_TRIGB_FREQUENCY_SELECT); 1553 1554 set_reg_field_value(value, 1555 0, /* no delay */ 1556 CRTC_TRIGB_CNTL, 1557 CRTC_TRIGB_DELAY); 1558 1559 set_reg_field_value(value, 1560 1, /* clear trigger status */ 1561 CRTC_TRIGB_CNTL, 1562 CRTC_TRIGB_CLEAR); 1563 1564 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL), value); 1565 1566 /**************************************************************/ 1567 1568 value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL)); 1569 1570 set_reg_field_value(value, 1571 2, /* force H count to H_TOTAL and V count to V_TOTAL */ 1572 CRTC_FORCE_COUNT_NOW_CNTL, 1573 CRTC_FORCE_COUNT_NOW_MODE); 1574 1575 set_reg_field_value(value, 1576 1, /* TriggerB - we never use TriggerA */ 1577 CRTC_FORCE_COUNT_NOW_CNTL, 1578 CRTC_FORCE_COUNT_NOW_TRIG_SEL); 1579 1580 set_reg_field_value(value, 1581 1, /* clear trigger status */ 1582 CRTC_FORCE_COUNT_NOW_CNTL, 1583 CRTC_FORCE_COUNT_NOW_CLEAR); 1584 1585 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL), value); 1586 } 1587 1588 void dce110_timing_generator_enable_crtc_reset( 1589 struct timing_generator *tg, 1590 int source_tg_inst, 1591 struct crtc_trigger_info *crtc_tp) 1592 { 1593 uint32_t value = 0; 1594 uint32_t rising_edge = 0; 1595 uint32_t falling_edge = 0; 1596 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 1597 1598 /* Setup trigger edge */ 1599 switch (crtc_tp->event) { 1600 case CRTC_EVENT_VSYNC_RISING: 1601 rising_edge = 1; 1602 break; 1603 1604 case CRTC_EVENT_VSYNC_FALLING: 1605 falling_edge = 1; 1606 break; 1607 } 1608 1609 value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL)); 1610 1611 set_reg_field_value(value, 1612 source_tg_inst, 1613 CRTC_TRIGB_CNTL, 1614 CRTC_TRIGB_SOURCE_SELECT); 1615 1616 set_reg_field_value(value, 1617 TRIGGER_POLARITY_SELECT_LOGIC_ZERO, 1618 CRTC_TRIGB_CNTL, 1619 CRTC_TRIGB_POLARITY_SELECT); 1620 1621 set_reg_field_value(value, 1622 rising_edge, 1623 CRTC_TRIGB_CNTL, 1624 CRTC_TRIGB_RISING_EDGE_DETECT_CNTL); 1625 1626 set_reg_field_value(value, 1627 falling_edge, 1628 CRTC_TRIGB_CNTL, 1629 CRTC_TRIGB_FALLING_EDGE_DETECT_CNTL); 1630 1631 set_reg_field_value(value, 1632 1, /* clear trigger status */ 1633 CRTC_TRIGB_CNTL, 1634 CRTC_TRIGB_CLEAR); 1635 1636 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL), value); 1637 1638 /**************************************************************/ 1639 1640 switch (crtc_tp->delay) { 1641 case TRIGGER_DELAY_NEXT_LINE: 1642 value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL)); 1643 1644 set_reg_field_value(value, 1645 0, /* force H count to H_TOTAL and V count to V_TOTAL */ 1646 CRTC_FORCE_COUNT_NOW_CNTL, 1647 CRTC_FORCE_COUNT_NOW_MODE); 1648 1649 set_reg_field_value(value, 1650 0, /* TriggerB - we never use TriggerA */ 1651 CRTC_FORCE_COUNT_NOW_CNTL, 1652 CRTC_FORCE_COUNT_NOW_TRIG_SEL); 1653 1654 set_reg_field_value(value, 1655 1, /* clear trigger status */ 1656 CRTC_FORCE_COUNT_NOW_CNTL, 1657 CRTC_FORCE_COUNT_NOW_CLEAR); 1658 1659 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL), value); 1660 1661 value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_VERT_SYNC_CONTROL)); 1662 1663 set_reg_field_value(value, 1664 1, 1665 CRTC_VERT_SYNC_CONTROL, 1666 CRTC_FORCE_VSYNC_NEXT_LINE_CLEAR); 1667 1668 set_reg_field_value(value, 1669 2, 1670 CRTC_VERT_SYNC_CONTROL, 1671 CRTC_AUTO_FORCE_VSYNC_MODE); 1672 1673 break; 1674 1675 case TRIGGER_DELAY_NEXT_PIXEL: 1676 value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_VERT_SYNC_CONTROL)); 1677 1678 set_reg_field_value(value, 1679 1, 1680 CRTC_VERT_SYNC_CONTROL, 1681 CRTC_FORCE_VSYNC_NEXT_LINE_CLEAR); 1682 1683 set_reg_field_value(value, 1684 0, 1685 CRTC_VERT_SYNC_CONTROL, 1686 CRTC_AUTO_FORCE_VSYNC_MODE); 1687 1688 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_VERT_SYNC_CONTROL), value); 1689 1690 value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL)); 1691 1692 set_reg_field_value(value, 1693 2, /* force H count to H_TOTAL and V count to V_TOTAL */ 1694 CRTC_FORCE_COUNT_NOW_CNTL, 1695 CRTC_FORCE_COUNT_NOW_MODE); 1696 1697 set_reg_field_value(value, 1698 1, /* TriggerB - we never use TriggerA */ 1699 CRTC_FORCE_COUNT_NOW_CNTL, 1700 CRTC_FORCE_COUNT_NOW_TRIG_SEL); 1701 1702 set_reg_field_value(value, 1703 1, /* clear trigger status */ 1704 CRTC_FORCE_COUNT_NOW_CNTL, 1705 CRTC_FORCE_COUNT_NOW_CLEAR); 1706 1707 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL), value); 1708 break; 1709 } 1710 1711 value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_MASTER_UPDATE_MODE)); 1712 1713 set_reg_field_value(value, 1714 2, 1715 CRTC_MASTER_UPDATE_MODE, 1716 MASTER_UPDATE_MODE); 1717 1718 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_MASTER_UPDATE_MODE), value); 1719 } 1720 void dce110_timing_generator_disable_reset_trigger( 1721 struct timing_generator *tg) 1722 { 1723 uint32_t value; 1724 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 1725 1726 value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL)); 1727 1728 set_reg_field_value(value, 1729 0, /* force counter now mode is disabled */ 1730 CRTC_FORCE_COUNT_NOW_CNTL, 1731 CRTC_FORCE_COUNT_NOW_MODE); 1732 1733 set_reg_field_value(value, 1734 1, /* clear trigger status */ 1735 CRTC_FORCE_COUNT_NOW_CNTL, 1736 CRTC_FORCE_COUNT_NOW_CLEAR); 1737 1738 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL), value); 1739 1740 value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_VERT_SYNC_CONTROL)); 1741 1742 set_reg_field_value(value, 1743 1, 1744 CRTC_VERT_SYNC_CONTROL, 1745 CRTC_FORCE_VSYNC_NEXT_LINE_CLEAR); 1746 1747 set_reg_field_value(value, 1748 0, 1749 CRTC_VERT_SYNC_CONTROL, 1750 CRTC_AUTO_FORCE_VSYNC_MODE); 1751 1752 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_VERT_SYNC_CONTROL), value); 1753 1754 /********************************************************************/ 1755 value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL)); 1756 1757 set_reg_field_value(value, 1758 TRIGGER_SOURCE_SELECT_LOGIC_ZERO, 1759 CRTC_TRIGB_CNTL, 1760 CRTC_TRIGB_SOURCE_SELECT); 1761 1762 set_reg_field_value(value, 1763 TRIGGER_POLARITY_SELECT_LOGIC_ZERO, 1764 CRTC_TRIGB_CNTL, 1765 CRTC_TRIGB_POLARITY_SELECT); 1766 1767 set_reg_field_value(value, 1768 1, /* clear trigger status */ 1769 CRTC_TRIGB_CNTL, 1770 CRTC_TRIGB_CLEAR); 1771 1772 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL), value); 1773 } 1774 1775 /** 1776 ***************************************************************************** 1777 * @brief 1778 * Checks whether CRTC triggered reset occurred 1779 * 1780 * @return 1781 * true if triggered reset occurred, false otherwise 1782 ***************************************************************************** 1783 */ 1784 bool dce110_timing_generator_did_triggered_reset_occur( 1785 struct timing_generator *tg) 1786 { 1787 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 1788 uint32_t value = dm_read_reg(tg->ctx, 1789 CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL)); 1790 uint32_t value1 = dm_read_reg(tg->ctx, 1791 CRTC_REG(mmCRTC_VERT_SYNC_CONTROL)); 1792 bool force = get_reg_field_value(value, 1793 CRTC_FORCE_COUNT_NOW_CNTL, 1794 CRTC_FORCE_COUNT_NOW_OCCURRED) != 0; 1795 bool vert_sync = get_reg_field_value(value1, 1796 CRTC_VERT_SYNC_CONTROL, 1797 CRTC_FORCE_VSYNC_NEXT_LINE_OCCURRED) != 0; 1798 1799 return (force || vert_sync); 1800 } 1801 1802 /** 1803 * dce110_timing_generator_disable_vga 1804 * Turn OFF VGA Mode and Timing - DxVGA_CONTROL 1805 * VGA Mode and VGA Timing is used by VBIOS on CRT Monitors; 1806 */ 1807 void dce110_timing_generator_disable_vga( 1808 struct timing_generator *tg) 1809 { 1810 uint32_t addr = 0; 1811 uint32_t value = 0; 1812 1813 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 1814 1815 switch (tg110->controller_id) { 1816 case CONTROLLER_ID_D0: 1817 addr = mmD1VGA_CONTROL; 1818 break; 1819 case CONTROLLER_ID_D1: 1820 addr = mmD2VGA_CONTROL; 1821 break; 1822 case CONTROLLER_ID_D2: 1823 addr = mmD3VGA_CONTROL; 1824 break; 1825 case CONTROLLER_ID_D3: 1826 addr = mmD4VGA_CONTROL; 1827 break; 1828 case CONTROLLER_ID_D4: 1829 addr = mmD5VGA_CONTROL; 1830 break; 1831 case CONTROLLER_ID_D5: 1832 addr = mmD6VGA_CONTROL; 1833 break; 1834 default: 1835 break; 1836 } 1837 value = dm_read_reg(tg->ctx, addr); 1838 1839 set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_MODE_ENABLE); 1840 set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_TIMING_SELECT); 1841 set_reg_field_value( 1842 value, 0, D1VGA_CONTROL, D1VGA_SYNC_POLARITY_SELECT); 1843 set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_OVERSCAN_COLOR_EN); 1844 1845 dm_write_reg(tg->ctx, addr, value); 1846 } 1847 1848 /** 1849 * set_overscan_color_black 1850 * 1851 * @param :black_color is one of the color space 1852 * :this routine will set overscan black color according to the color space. 1853 * @return none 1854 */ 1855 1856 void dce110_timing_generator_set_overscan_color_black( 1857 struct timing_generator *tg, 1858 const struct tg_color *color) 1859 { 1860 struct dc_context *ctx = tg->ctx; 1861 uint32_t addr; 1862 uint32_t value = 0; 1863 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 1864 1865 set_reg_field_value( 1866 value, 1867 color->color_b_cb, 1868 CRTC_OVERSCAN_COLOR, 1869 CRTC_OVERSCAN_COLOR_BLUE); 1870 1871 set_reg_field_value( 1872 value, 1873 color->color_r_cr, 1874 CRTC_OVERSCAN_COLOR, 1875 CRTC_OVERSCAN_COLOR_RED); 1876 1877 set_reg_field_value( 1878 value, 1879 color->color_g_y, 1880 CRTC_OVERSCAN_COLOR, 1881 CRTC_OVERSCAN_COLOR_GREEN); 1882 1883 addr = CRTC_REG(mmCRTC_OVERSCAN_COLOR); 1884 dm_write_reg(ctx, addr, value); 1885 addr = CRTC_REG(mmCRTC_BLACK_COLOR); 1886 dm_write_reg(ctx, addr, value); 1887 /* This is desirable to have a constant DAC output voltage during the 1888 * blank time that is higher than the 0 volt reference level that the 1889 * DAC outputs when the NBLANK signal 1890 * is asserted low, such as for output to an analog TV. */ 1891 addr = CRTC_REG(mmCRTC_BLANK_DATA_COLOR); 1892 dm_write_reg(ctx, addr, value); 1893 1894 /* TO DO we have to program EXT registers and we need to know LB DATA 1895 * format because it is used when more 10 , i.e. 12 bits per color 1896 * 1897 * m_mmDxCRTC_OVERSCAN_COLOR_EXT 1898 * m_mmDxCRTC_BLACK_COLOR_EXT 1899 * m_mmDxCRTC_BLANK_DATA_COLOR_EXT 1900 */ 1901 1902 } 1903 1904 void dce110_tg_program_blank_color(struct timing_generator *tg, 1905 const struct tg_color *black_color) 1906 { 1907 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 1908 uint32_t addr = CRTC_REG(mmCRTC_BLACK_COLOR); 1909 uint32_t value = dm_read_reg(tg->ctx, addr); 1910 1911 set_reg_field_value( 1912 value, 1913 black_color->color_b_cb, 1914 CRTC_BLACK_COLOR, 1915 CRTC_BLACK_COLOR_B_CB); 1916 set_reg_field_value( 1917 value, 1918 black_color->color_g_y, 1919 CRTC_BLACK_COLOR, 1920 CRTC_BLACK_COLOR_G_Y); 1921 set_reg_field_value( 1922 value, 1923 black_color->color_r_cr, 1924 CRTC_BLACK_COLOR, 1925 CRTC_BLACK_COLOR_R_CR); 1926 1927 dm_write_reg(tg->ctx, addr, value); 1928 1929 addr = CRTC_REG(mmCRTC_BLANK_DATA_COLOR); 1930 dm_write_reg(tg->ctx, addr, value); 1931 } 1932 1933 void dce110_tg_set_overscan_color(struct timing_generator *tg, 1934 const struct tg_color *overscan_color) 1935 { 1936 struct dc_context *ctx = tg->ctx; 1937 uint32_t value = 0; 1938 uint32_t addr; 1939 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 1940 1941 set_reg_field_value( 1942 value, 1943 overscan_color->color_b_cb, 1944 CRTC_OVERSCAN_COLOR, 1945 CRTC_OVERSCAN_COLOR_BLUE); 1946 1947 set_reg_field_value( 1948 value, 1949 overscan_color->color_g_y, 1950 CRTC_OVERSCAN_COLOR, 1951 CRTC_OVERSCAN_COLOR_GREEN); 1952 1953 set_reg_field_value( 1954 value, 1955 overscan_color->color_r_cr, 1956 CRTC_OVERSCAN_COLOR, 1957 CRTC_OVERSCAN_COLOR_RED); 1958 1959 addr = CRTC_REG(mmCRTC_OVERSCAN_COLOR); 1960 dm_write_reg(ctx, addr, value); 1961 } 1962 1963 void dce110_tg_program_timing(struct timing_generator *tg, 1964 const struct dc_crtc_timing *timing, 1965 int vready_offset, 1966 int vstartup_start, 1967 int vupdate_offset, 1968 int vupdate_width, 1969 const enum signal_type signal, 1970 bool use_vbios) 1971 { 1972 if (use_vbios) 1973 dce110_timing_generator_program_timing_generator(tg, timing); 1974 else 1975 dce110_timing_generator_program_blanking(tg, timing); 1976 } 1977 1978 bool dce110_tg_is_blanked(struct timing_generator *tg) 1979 { 1980 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 1981 uint32_t value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL)); 1982 1983 if (get_reg_field_value( 1984 value, 1985 CRTC_BLANK_CONTROL, 1986 CRTC_BLANK_DATA_EN) == 1 && 1987 get_reg_field_value( 1988 value, 1989 CRTC_BLANK_CONTROL, 1990 CRTC_CURRENT_BLANK_STATE) == 1) 1991 return true; 1992 return false; 1993 } 1994 1995 void dce110_tg_set_blank(struct timing_generator *tg, 1996 bool enable_blanking) 1997 { 1998 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 1999 uint32_t value = 0; 2000 2001 set_reg_field_value( 2002 value, 2003 1, 2004 CRTC_DOUBLE_BUFFER_CONTROL, 2005 CRTC_BLANK_DATA_DOUBLE_BUFFER_EN); 2006 2007 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_DOUBLE_BUFFER_CONTROL), value); 2008 value = 0; 2009 2010 if (enable_blanking) { 2011 set_reg_field_value( 2012 value, 2013 1, 2014 CRTC_BLANK_CONTROL, 2015 CRTC_BLANK_DATA_EN); 2016 2017 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL), value); 2018 2019 } else 2020 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL), 0); 2021 } 2022 2023 bool dce110_tg_validate_timing(struct timing_generator *tg, 2024 const struct dc_crtc_timing *timing) 2025 { 2026 return dce110_timing_generator_validate_timing(tg, timing, SIGNAL_TYPE_NONE); 2027 } 2028 2029 void dce110_tg_wait_for_state(struct timing_generator *tg, 2030 enum crtc_state state) 2031 { 2032 switch (state) { 2033 case CRTC_STATE_VBLANK: 2034 dce110_timing_generator_wait_for_vblank(tg); 2035 break; 2036 2037 case CRTC_STATE_VACTIVE: 2038 dce110_timing_generator_wait_for_vactive(tg); 2039 break; 2040 2041 default: 2042 break; 2043 } 2044 } 2045 2046 void dce110_tg_set_colors(struct timing_generator *tg, 2047 const struct tg_color *blank_color, 2048 const struct tg_color *overscan_color) 2049 { 2050 if (blank_color != NULL) 2051 dce110_tg_program_blank_color(tg, blank_color); 2052 if (overscan_color != NULL) 2053 dce110_tg_set_overscan_color(tg, overscan_color); 2054 } 2055 2056 /* Gets first line of blank region of the display timing for CRTC 2057 * and programms is as a trigger to fire vertical interrupt 2058 */ 2059 bool dce110_arm_vert_intr(struct timing_generator *tg, uint8_t width) 2060 { 2061 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 2062 uint32_t v_blank_start = 0; 2063 uint32_t v_blank_end = 0; 2064 uint32_t val = 0; 2065 uint32_t h_position, v_position; 2066 2067 tg->funcs->get_scanoutpos( 2068 tg, 2069 &v_blank_start, 2070 &v_blank_end, 2071 &h_position, 2072 &v_position); 2073 2074 if (v_blank_start == 0 || v_blank_end == 0) 2075 return false; 2076 2077 set_reg_field_value( 2078 val, 2079 v_blank_start, 2080 CRTC_VERTICAL_INTERRUPT0_POSITION, 2081 CRTC_VERTICAL_INTERRUPT0_LINE_START); 2082 2083 /* Set interval width for interrupt to fire to 1 scanline */ 2084 set_reg_field_value( 2085 val, 2086 v_blank_start + width, 2087 CRTC_VERTICAL_INTERRUPT0_POSITION, 2088 CRTC_VERTICAL_INTERRUPT0_LINE_END); 2089 2090 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_VERTICAL_INTERRUPT0_POSITION), val); 2091 2092 return true; 2093 } 2094 2095 static bool dce110_is_tg_enabled(struct timing_generator *tg) 2096 { 2097 uint32_t addr = 0; 2098 uint32_t value = 0; 2099 uint32_t field = 0; 2100 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 2101 2102 addr = CRTC_REG(mmCRTC_CONTROL); 2103 value = dm_read_reg(tg->ctx, addr); 2104 field = get_reg_field_value(value, CRTC_CONTROL, 2105 CRTC_CURRENT_MASTER_EN_STATE); 2106 return field == 1; 2107 } 2108 2109 bool dce110_configure_crc(struct timing_generator *tg, 2110 const struct crc_params *params) 2111 { 2112 uint32_t cntl_addr = 0; 2113 uint32_t addr = 0; 2114 uint32_t value; 2115 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 2116 2117 /* Cannot configure crc on a CRTC that is disabled */ 2118 if (!dce110_is_tg_enabled(tg)) 2119 return false; 2120 2121 cntl_addr = CRTC_REG(mmCRTC_CRC_CNTL); 2122 2123 /* First, disable CRC before we configure it. */ 2124 dm_write_reg(tg->ctx, cntl_addr, 0); 2125 2126 if (!params->enable) 2127 return true; 2128 2129 /* Program frame boundaries */ 2130 /* Window A x axis start and end. */ 2131 value = 0; 2132 addr = CRTC_REG(mmCRTC_CRC0_WINDOWA_X_CONTROL); 2133 set_reg_field_value(value, params->windowa_x_start, 2134 CRTC_CRC0_WINDOWA_X_CONTROL, 2135 CRTC_CRC0_WINDOWA_X_START); 2136 set_reg_field_value(value, params->windowa_x_end, 2137 CRTC_CRC0_WINDOWA_X_CONTROL, 2138 CRTC_CRC0_WINDOWA_X_END); 2139 dm_write_reg(tg->ctx, addr, value); 2140 2141 /* Window A y axis start and end. */ 2142 value = 0; 2143 addr = CRTC_REG(mmCRTC_CRC0_WINDOWA_Y_CONTROL); 2144 set_reg_field_value(value, params->windowa_y_start, 2145 CRTC_CRC0_WINDOWA_Y_CONTROL, 2146 CRTC_CRC0_WINDOWA_Y_START); 2147 set_reg_field_value(value, params->windowa_y_end, 2148 CRTC_CRC0_WINDOWA_Y_CONTROL, 2149 CRTC_CRC0_WINDOWA_Y_END); 2150 dm_write_reg(tg->ctx, addr, value); 2151 2152 /* Window B x axis start and end. */ 2153 value = 0; 2154 addr = CRTC_REG(mmCRTC_CRC0_WINDOWB_X_CONTROL); 2155 set_reg_field_value(value, params->windowb_x_start, 2156 CRTC_CRC0_WINDOWB_X_CONTROL, 2157 CRTC_CRC0_WINDOWB_X_START); 2158 set_reg_field_value(value, params->windowb_x_end, 2159 CRTC_CRC0_WINDOWB_X_CONTROL, 2160 CRTC_CRC0_WINDOWB_X_END); 2161 dm_write_reg(tg->ctx, addr, value); 2162 2163 /* Window B y axis start and end. */ 2164 value = 0; 2165 addr = CRTC_REG(mmCRTC_CRC0_WINDOWB_Y_CONTROL); 2166 set_reg_field_value(value, params->windowb_y_start, 2167 CRTC_CRC0_WINDOWB_Y_CONTROL, 2168 CRTC_CRC0_WINDOWB_Y_START); 2169 set_reg_field_value(value, params->windowb_y_end, 2170 CRTC_CRC0_WINDOWB_Y_CONTROL, 2171 CRTC_CRC0_WINDOWB_Y_END); 2172 dm_write_reg(tg->ctx, addr, value); 2173 2174 /* Set crc mode and selection, and enable. Only using CRC0*/ 2175 value = 0; 2176 set_reg_field_value(value, params->continuous_mode ? 1 : 0, 2177 CRTC_CRC_CNTL, CRTC_CRC_CONT_EN); 2178 set_reg_field_value(value, params->selection, 2179 CRTC_CRC_CNTL, CRTC_CRC0_SELECT); 2180 set_reg_field_value(value, 1, CRTC_CRC_CNTL, CRTC_CRC_EN); 2181 dm_write_reg(tg->ctx, cntl_addr, value); 2182 2183 return true; 2184 } 2185 2186 bool dce110_get_crc(struct timing_generator *tg, 2187 uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb) 2188 { 2189 uint32_t addr = 0; 2190 uint32_t value = 0; 2191 uint32_t field = 0; 2192 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 2193 2194 addr = CRTC_REG(mmCRTC_CRC_CNTL); 2195 value = dm_read_reg(tg->ctx, addr); 2196 field = get_reg_field_value(value, CRTC_CRC_CNTL, CRTC_CRC_EN); 2197 2198 /* Early return if CRC is not enabled for this CRTC */ 2199 if (!field) 2200 return false; 2201 2202 addr = CRTC_REG(mmCRTC_CRC0_DATA_RG); 2203 value = dm_read_reg(tg->ctx, addr); 2204 *r_cr = get_reg_field_value(value, CRTC_CRC0_DATA_RG, CRC0_R_CR); 2205 *g_y = get_reg_field_value(value, CRTC_CRC0_DATA_RG, CRC0_G_Y); 2206 2207 addr = CRTC_REG(mmCRTC_CRC0_DATA_B); 2208 value = dm_read_reg(tg->ctx, addr); 2209 *b_cb = get_reg_field_value(value, CRTC_CRC0_DATA_B, CRC0_B_CB); 2210 2211 return true; 2212 } 2213 2214 static const struct timing_generator_funcs dce110_tg_funcs = { 2215 .validate_timing = dce110_tg_validate_timing, 2216 .program_timing = dce110_tg_program_timing, 2217 .enable_crtc = dce110_timing_generator_enable_crtc, 2218 .disable_crtc = dce110_timing_generator_disable_crtc, 2219 .is_counter_moving = dce110_timing_generator_is_counter_moving, 2220 .get_position = dce110_timing_generator_get_position, 2221 .get_frame_count = dce110_timing_generator_get_vblank_counter, 2222 .get_scanoutpos = dce110_timing_generator_get_crtc_scanoutpos, 2223 .set_early_control = dce110_timing_generator_set_early_control, 2224 .wait_for_state = dce110_tg_wait_for_state, 2225 .set_blank = dce110_tg_set_blank, 2226 .is_blanked = dce110_tg_is_blanked, 2227 .set_colors = dce110_tg_set_colors, 2228 .set_overscan_blank_color = 2229 dce110_timing_generator_set_overscan_color_black, 2230 .set_blank_color = dce110_timing_generator_program_blank_color, 2231 .disable_vga = dce110_timing_generator_disable_vga, 2232 .did_triggered_reset_occur = 2233 dce110_timing_generator_did_triggered_reset_occur, 2234 .setup_global_swap_lock = 2235 dce110_timing_generator_setup_global_swap_lock, 2236 .enable_reset_trigger = dce110_timing_generator_enable_reset_trigger, 2237 .enable_crtc_reset = dce110_timing_generator_enable_crtc_reset, 2238 .disable_reset_trigger = dce110_timing_generator_disable_reset_trigger, 2239 .tear_down_global_swap_lock = 2240 dce110_timing_generator_tear_down_global_swap_lock, 2241 .enable_advanced_request = 2242 dce110_timing_generator_enable_advanced_request, 2243 .set_drr = 2244 dce110_timing_generator_set_drr, 2245 .set_static_screen_control = 2246 dce110_timing_generator_set_static_screen_control, 2247 .set_test_pattern = dce110_timing_generator_set_test_pattern, 2248 .arm_vert_intr = dce110_arm_vert_intr, 2249 .is_tg_enabled = dce110_is_tg_enabled, 2250 .configure_crc = dce110_configure_crc, 2251 .get_crc = dce110_get_crc, 2252 }; 2253 2254 void dce110_timing_generator_construct( 2255 struct dce110_timing_generator *tg110, 2256 struct dc_context *ctx, 2257 uint32_t instance, 2258 const struct dce110_timing_generator_offsets *offsets) 2259 { 2260 tg110->controller_id = CONTROLLER_ID_D0 + instance; 2261 tg110->base.inst = instance; 2262 2263 tg110->offsets = *offsets; 2264 2265 tg110->base.funcs = &dce110_tg_funcs; 2266 2267 tg110->base.ctx = ctx; 2268 tg110->base.bp = ctx->dc_bios; 2269 2270 tg110->max_h_total = CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1; 2271 tg110->max_v_total = CRTC_V_TOTAL__CRTC_V_TOTAL_MASK + 1; 2272 2273 tg110->min_h_blank = 56; 2274 tg110->min_h_front_porch = 4; 2275 tg110->min_h_back_porch = 4; 2276 } 2277