1 /* 2 * Copyright 2015 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 #include "dm_services.h" 26 #include "dc.h" 27 #include "dc_bios_types.h" 28 #include "core_types.h" 29 #include "core_status.h" 30 #include "resource.h" 31 #include "dm_helpers.h" 32 #include "dce110_hw_sequencer.h" 33 #include "dce110_timing_generator.h" 34 #include "dce/dce_hwseq.h" 35 #include "gpio_service_interface.h" 36 37 #include "dce110_compressor.h" 38 39 #include "bios/bios_parser_helper.h" 40 #include "timing_generator.h" 41 #include "mem_input.h" 42 #include "opp.h" 43 #include "ipp.h" 44 #include "transform.h" 45 #include "stream_encoder.h" 46 #include "link_encoder.h" 47 #include "link_hwss.h" 48 #include "clock_source.h" 49 #include "abm.h" 50 #include "audio.h" 51 #include "reg_helper.h" 52 53 /* include DCE11 register header files */ 54 #include "dce/dce_11_0_d.h" 55 #include "dce/dce_11_0_sh_mask.h" 56 #include "custom_float.h" 57 58 #include "atomfirmware.h" 59 60 /* 61 * All values are in milliseconds; 62 * For eDP, after power-up/power/down, 63 * 300/500 msec max. delay from LCDVCC to black video generation 64 */ 65 #define PANEL_POWER_UP_TIMEOUT 300 66 #define PANEL_POWER_DOWN_TIMEOUT 500 67 #define HPD_CHECK_INTERVAL 10 68 69 #define CTX \ 70 hws->ctx 71 72 #define DC_LOGGER_INIT() 73 74 #define REG(reg)\ 75 hws->regs->reg 76 77 #undef FN 78 #define FN(reg_name, field_name) \ 79 hws->shifts->field_name, hws->masks->field_name 80 81 struct dce110_hw_seq_reg_offsets { 82 uint32_t crtc; 83 }; 84 85 static const struct dce110_hw_seq_reg_offsets reg_offsets[] = { 86 { 87 .crtc = (mmCRTC0_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), 88 }, 89 { 90 .crtc = (mmCRTC1_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), 91 }, 92 { 93 .crtc = (mmCRTC2_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), 94 }, 95 { 96 .crtc = (mmCRTCV_GSL_CONTROL - mmCRTC_GSL_CONTROL), 97 } 98 }; 99 100 #define HW_REG_BLND(reg, id)\ 101 (reg + reg_offsets[id].blnd) 102 103 #define HW_REG_CRTC(reg, id)\ 104 (reg + reg_offsets[id].crtc) 105 106 #define MAX_WATERMARK 0xFFFF 107 #define SAFE_NBP_MARK 0x7FFF 108 109 /******************************************************************************* 110 * Private definitions 111 ******************************************************************************/ 112 /***************************PIPE_CONTROL***********************************/ 113 static void dce110_init_pte(struct dc_context *ctx) 114 { 115 uint32_t addr; 116 uint32_t value = 0; 117 uint32_t chunk_int = 0; 118 uint32_t chunk_mul = 0; 119 120 addr = mmUNP_DVMM_PTE_CONTROL; 121 value = dm_read_reg(ctx, addr); 122 123 set_reg_field_value( 124 value, 125 0, 126 DVMM_PTE_CONTROL, 127 DVMM_USE_SINGLE_PTE); 128 129 set_reg_field_value( 130 value, 131 1, 132 DVMM_PTE_CONTROL, 133 DVMM_PTE_BUFFER_MODE0); 134 135 set_reg_field_value( 136 value, 137 1, 138 DVMM_PTE_CONTROL, 139 DVMM_PTE_BUFFER_MODE1); 140 141 dm_write_reg(ctx, addr, value); 142 143 addr = mmDVMM_PTE_REQ; 144 value = dm_read_reg(ctx, addr); 145 146 chunk_int = get_reg_field_value( 147 value, 148 DVMM_PTE_REQ, 149 HFLIP_PTEREQ_PER_CHUNK_INT); 150 151 chunk_mul = get_reg_field_value( 152 value, 153 DVMM_PTE_REQ, 154 HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER); 155 156 if (chunk_int != 0x4 || chunk_mul != 0x4) { 157 158 set_reg_field_value( 159 value, 160 255, 161 DVMM_PTE_REQ, 162 MAX_PTEREQ_TO_ISSUE); 163 164 set_reg_field_value( 165 value, 166 4, 167 DVMM_PTE_REQ, 168 HFLIP_PTEREQ_PER_CHUNK_INT); 169 170 set_reg_field_value( 171 value, 172 4, 173 DVMM_PTE_REQ, 174 HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER); 175 176 dm_write_reg(ctx, addr, value); 177 } 178 } 179 /**************************************************************************/ 180 181 static void enable_display_pipe_clock_gating( 182 struct dc_context *ctx, 183 bool clock_gating) 184 { 185 /*TODO*/ 186 } 187 188 static bool dce110_enable_display_power_gating( 189 struct dc *dc, 190 uint8_t controller_id, 191 struct dc_bios *dcb, 192 enum pipe_gating_control power_gating) 193 { 194 enum bp_result bp_result = BP_RESULT_OK; 195 enum bp_pipe_control_action cntl; 196 struct dc_context *ctx = dc->ctx; 197 unsigned int underlay_idx = dc->res_pool->underlay_pipe_index; 198 199 if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) 200 return true; 201 202 if (power_gating == PIPE_GATING_CONTROL_INIT) 203 cntl = ASIC_PIPE_INIT; 204 else if (power_gating == PIPE_GATING_CONTROL_ENABLE) 205 cntl = ASIC_PIPE_ENABLE; 206 else 207 cntl = ASIC_PIPE_DISABLE; 208 209 if (controller_id == underlay_idx) 210 controller_id = CONTROLLER_ID_UNDERLAY0 - 1; 211 212 if (power_gating != PIPE_GATING_CONTROL_INIT || controller_id == 0){ 213 214 bp_result = dcb->funcs->enable_disp_power_gating( 215 dcb, controller_id + 1, cntl); 216 217 /* Revert MASTER_UPDATE_MODE to 0 because bios sets it 2 218 * by default when command table is called 219 * 220 * Bios parser accepts controller_id = 6 as indicative of 221 * underlay pipe in dce110. But we do not support more 222 * than 3. 223 */ 224 if (controller_id < CONTROLLER_ID_MAX - 1) 225 dm_write_reg(ctx, 226 HW_REG_CRTC(mmCRTC_MASTER_UPDATE_MODE, controller_id), 227 0); 228 } 229 230 if (power_gating != PIPE_GATING_CONTROL_ENABLE) 231 dce110_init_pte(ctx); 232 233 if (bp_result == BP_RESULT_OK) 234 return true; 235 else 236 return false; 237 } 238 239 static void build_prescale_params(struct ipp_prescale_params *prescale_params, 240 const struct dc_plane_state *plane_state) 241 { 242 prescale_params->mode = IPP_PRESCALE_MODE_FIXED_UNSIGNED; 243 244 switch (plane_state->format) { 245 case SURFACE_PIXEL_FORMAT_GRPH_RGB565: 246 prescale_params->scale = 0x2082; 247 break; 248 case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: 249 case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: 250 prescale_params->scale = 0x2020; 251 break; 252 case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: 253 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: 254 prescale_params->scale = 0x2008; 255 break; 256 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: 257 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: 258 prescale_params->scale = 0x2000; 259 break; 260 default: 261 ASSERT(false); 262 break; 263 } 264 } 265 266 static bool 267 dce110_set_input_transfer_func(struct pipe_ctx *pipe_ctx, 268 const struct dc_plane_state *plane_state) 269 { 270 struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp; 271 const struct dc_transfer_func *tf = NULL; 272 struct ipp_prescale_params prescale_params = { 0 }; 273 bool result = true; 274 275 if (ipp == NULL) 276 return false; 277 278 if (plane_state->in_transfer_func) 279 tf = plane_state->in_transfer_func; 280 281 build_prescale_params(&prescale_params, plane_state); 282 ipp->funcs->ipp_program_prescale(ipp, &prescale_params); 283 284 if (plane_state->gamma_correction && 285 !plane_state->gamma_correction->is_identity && 286 dce_use_lut(plane_state->format)) 287 ipp->funcs->ipp_program_input_lut(ipp, plane_state->gamma_correction); 288 289 if (tf == NULL) { 290 /* Default case if no input transfer function specified */ 291 ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_sRGB); 292 } else if (tf->type == TF_TYPE_PREDEFINED) { 293 switch (tf->tf) { 294 case TRANSFER_FUNCTION_SRGB: 295 ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_sRGB); 296 break; 297 case TRANSFER_FUNCTION_BT709: 298 ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_xvYCC); 299 break; 300 case TRANSFER_FUNCTION_LINEAR: 301 ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS); 302 break; 303 case TRANSFER_FUNCTION_PQ: 304 default: 305 result = false; 306 break; 307 } 308 } else if (tf->type == TF_TYPE_BYPASS) { 309 ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS); 310 } else { 311 /*TF_TYPE_DISTRIBUTED_POINTS - Not supported in DCE 11*/ 312 result = false; 313 } 314 315 return result; 316 } 317 318 static bool convert_to_custom_float(struct pwl_result_data *rgb_resulted, 319 struct curve_points *arr_points, 320 uint32_t hw_points_num) 321 { 322 struct custom_float_format fmt; 323 324 struct pwl_result_data *rgb = rgb_resulted; 325 326 uint32_t i = 0; 327 328 fmt.exponenta_bits = 6; 329 fmt.mantissa_bits = 12; 330 fmt.sign = true; 331 332 if (!convert_to_custom_float_format(arr_points[0].x, &fmt, 333 &arr_points[0].custom_float_x)) { 334 BREAK_TO_DEBUGGER(); 335 return false; 336 } 337 338 if (!convert_to_custom_float_format(arr_points[0].offset, &fmt, 339 &arr_points[0].custom_float_offset)) { 340 BREAK_TO_DEBUGGER(); 341 return false; 342 } 343 344 if (!convert_to_custom_float_format(arr_points[0].slope, &fmt, 345 &arr_points[0].custom_float_slope)) { 346 BREAK_TO_DEBUGGER(); 347 return false; 348 } 349 350 fmt.mantissa_bits = 10; 351 fmt.sign = false; 352 353 if (!convert_to_custom_float_format(arr_points[1].x, &fmt, 354 &arr_points[1].custom_float_x)) { 355 BREAK_TO_DEBUGGER(); 356 return false; 357 } 358 359 if (!convert_to_custom_float_format(arr_points[1].y, &fmt, 360 &arr_points[1].custom_float_y)) { 361 BREAK_TO_DEBUGGER(); 362 return false; 363 } 364 365 if (!convert_to_custom_float_format(arr_points[1].slope, &fmt, 366 &arr_points[1].custom_float_slope)) { 367 BREAK_TO_DEBUGGER(); 368 return false; 369 } 370 371 fmt.mantissa_bits = 12; 372 fmt.sign = true; 373 374 while (i != hw_points_num) { 375 if (!convert_to_custom_float_format(rgb->red, &fmt, 376 &rgb->red_reg)) { 377 BREAK_TO_DEBUGGER(); 378 return false; 379 } 380 381 if (!convert_to_custom_float_format(rgb->green, &fmt, 382 &rgb->green_reg)) { 383 BREAK_TO_DEBUGGER(); 384 return false; 385 } 386 387 if (!convert_to_custom_float_format(rgb->blue, &fmt, 388 &rgb->blue_reg)) { 389 BREAK_TO_DEBUGGER(); 390 return false; 391 } 392 393 if (!convert_to_custom_float_format(rgb->delta_red, &fmt, 394 &rgb->delta_red_reg)) { 395 BREAK_TO_DEBUGGER(); 396 return false; 397 } 398 399 if (!convert_to_custom_float_format(rgb->delta_green, &fmt, 400 &rgb->delta_green_reg)) { 401 BREAK_TO_DEBUGGER(); 402 return false; 403 } 404 405 if (!convert_to_custom_float_format(rgb->delta_blue, &fmt, 406 &rgb->delta_blue_reg)) { 407 BREAK_TO_DEBUGGER(); 408 return false; 409 } 410 411 ++rgb; 412 ++i; 413 } 414 415 return true; 416 } 417 418 #define MAX_LOW_POINT 25 419 #define NUMBER_REGIONS 16 420 #define NUMBER_SW_SEGMENTS 16 421 422 static bool 423 dce110_translate_regamma_to_hw_format(const struct dc_transfer_func *output_tf, 424 struct pwl_params *regamma_params) 425 { 426 struct curve_points *arr_points; 427 struct pwl_result_data *rgb_resulted; 428 struct pwl_result_data *rgb; 429 struct pwl_result_data *rgb_plus_1; 430 struct fixed31_32 y_r; 431 struct fixed31_32 y_g; 432 struct fixed31_32 y_b; 433 struct fixed31_32 y1_min; 434 struct fixed31_32 y3_max; 435 436 int32_t region_start, region_end; 437 uint32_t i, j, k, seg_distr[NUMBER_REGIONS], increment, start_index, hw_points; 438 439 if (output_tf == NULL || regamma_params == NULL || output_tf->type == TF_TYPE_BYPASS) 440 return false; 441 442 arr_points = regamma_params->arr_points; 443 rgb_resulted = regamma_params->rgb_resulted; 444 hw_points = 0; 445 446 memset(regamma_params, 0, sizeof(struct pwl_params)); 447 448 if (output_tf->tf == TRANSFER_FUNCTION_PQ) { 449 /* 16 segments 450 * segments are from 2^-11 to 2^5 451 */ 452 region_start = -11; 453 region_end = region_start + NUMBER_REGIONS; 454 455 for (i = 0; i < NUMBER_REGIONS; i++) 456 seg_distr[i] = 4; 457 458 } else { 459 /* 10 segments 460 * segment is from 2^-10 to 2^1 461 * We include an extra segment for range [2^0, 2^1). This is to 462 * ensure that colors with normalized values of 1 don't miss the 463 * LUT. 464 */ 465 region_start = -10; 466 region_end = 1; 467 468 seg_distr[0] = 4; 469 seg_distr[1] = 4; 470 seg_distr[2] = 4; 471 seg_distr[3] = 4; 472 seg_distr[4] = 4; 473 seg_distr[5] = 4; 474 seg_distr[6] = 4; 475 seg_distr[7] = 4; 476 seg_distr[8] = 4; 477 seg_distr[9] = 4; 478 seg_distr[10] = 0; 479 seg_distr[11] = -1; 480 seg_distr[12] = -1; 481 seg_distr[13] = -1; 482 seg_distr[14] = -1; 483 seg_distr[15] = -1; 484 } 485 486 for (k = 0; k < 16; k++) { 487 if (seg_distr[k] != -1) 488 hw_points += (1 << seg_distr[k]); 489 } 490 491 j = 0; 492 for (k = 0; k < (region_end - region_start); k++) { 493 increment = NUMBER_SW_SEGMENTS / (1 << seg_distr[k]); 494 start_index = (region_start + k + MAX_LOW_POINT) * 495 NUMBER_SW_SEGMENTS; 496 for (i = start_index; i < start_index + NUMBER_SW_SEGMENTS; 497 i += increment) { 498 if (j == hw_points - 1) 499 break; 500 rgb_resulted[j].red = output_tf->tf_pts.red[i]; 501 rgb_resulted[j].green = output_tf->tf_pts.green[i]; 502 rgb_resulted[j].blue = output_tf->tf_pts.blue[i]; 503 j++; 504 } 505 } 506 507 /* last point */ 508 start_index = (region_end + MAX_LOW_POINT) * NUMBER_SW_SEGMENTS; 509 rgb_resulted[hw_points - 1].red = output_tf->tf_pts.red[start_index]; 510 rgb_resulted[hw_points - 1].green = output_tf->tf_pts.green[start_index]; 511 rgb_resulted[hw_points - 1].blue = output_tf->tf_pts.blue[start_index]; 512 513 arr_points[0].x = dc_fixpt_pow(dc_fixpt_from_int(2), 514 dc_fixpt_from_int(region_start)); 515 arr_points[1].x = dc_fixpt_pow(dc_fixpt_from_int(2), 516 dc_fixpt_from_int(region_end)); 517 518 y_r = rgb_resulted[0].red; 519 y_g = rgb_resulted[0].green; 520 y_b = rgb_resulted[0].blue; 521 522 y1_min = dc_fixpt_min(y_r, dc_fixpt_min(y_g, y_b)); 523 524 arr_points[0].y = y1_min; 525 arr_points[0].slope = dc_fixpt_div(arr_points[0].y, 526 arr_points[0].x); 527 528 y_r = rgb_resulted[hw_points - 1].red; 529 y_g = rgb_resulted[hw_points - 1].green; 530 y_b = rgb_resulted[hw_points - 1].blue; 531 532 /* see comment above, m_arrPoints[1].y should be the Y value for the 533 * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1) 534 */ 535 y3_max = dc_fixpt_max(y_r, dc_fixpt_max(y_g, y_b)); 536 537 arr_points[1].y = y3_max; 538 539 arr_points[1].slope = dc_fixpt_zero; 540 541 if (output_tf->tf == TRANSFER_FUNCTION_PQ) { 542 /* for PQ, we want to have a straight line from last HW X point, 543 * and the slope to be such that we hit 1.0 at 10000 nits. 544 */ 545 const struct fixed31_32 end_value = dc_fixpt_from_int(125); 546 547 arr_points[1].slope = dc_fixpt_div( 548 dc_fixpt_sub(dc_fixpt_one, arr_points[1].y), 549 dc_fixpt_sub(end_value, arr_points[1].x)); 550 } 551 552 regamma_params->hw_points_num = hw_points; 553 554 i = 1; 555 for (k = 0; k < 16 && i < 16; k++) { 556 if (seg_distr[k] != -1) { 557 regamma_params->arr_curve_points[k].segments_num = seg_distr[k]; 558 regamma_params->arr_curve_points[i].offset = 559 regamma_params->arr_curve_points[k].offset + (1 << seg_distr[k]); 560 } 561 i++; 562 } 563 564 if (seg_distr[k] != -1) 565 regamma_params->arr_curve_points[k].segments_num = seg_distr[k]; 566 567 rgb = rgb_resulted; 568 rgb_plus_1 = rgb_resulted + 1; 569 570 i = 1; 571 572 while (i != hw_points + 1) { 573 if (dc_fixpt_lt(rgb_plus_1->red, rgb->red)) 574 rgb_plus_1->red = rgb->red; 575 if (dc_fixpt_lt(rgb_plus_1->green, rgb->green)) 576 rgb_plus_1->green = rgb->green; 577 if (dc_fixpt_lt(rgb_plus_1->blue, rgb->blue)) 578 rgb_plus_1->blue = rgb->blue; 579 580 rgb->delta_red = dc_fixpt_sub(rgb_plus_1->red, rgb->red); 581 rgb->delta_green = dc_fixpt_sub(rgb_plus_1->green, rgb->green); 582 rgb->delta_blue = dc_fixpt_sub(rgb_plus_1->blue, rgb->blue); 583 584 ++rgb_plus_1; 585 ++rgb; 586 ++i; 587 } 588 589 convert_to_custom_float(rgb_resulted, arr_points, hw_points); 590 591 return true; 592 } 593 594 static bool 595 dce110_set_output_transfer_func(struct pipe_ctx *pipe_ctx, 596 const struct dc_stream_state *stream) 597 { 598 struct transform *xfm = pipe_ctx->plane_res.xfm; 599 600 xfm->funcs->opp_power_on_regamma_lut(xfm, true); 601 xfm->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM; 602 603 if (stream->out_transfer_func && 604 stream->out_transfer_func->type == TF_TYPE_PREDEFINED && 605 stream->out_transfer_func->tf == TRANSFER_FUNCTION_SRGB) { 606 xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_SRGB); 607 } else if (dce110_translate_regamma_to_hw_format(stream->out_transfer_func, 608 &xfm->regamma_params)) { 609 xfm->funcs->opp_program_regamma_pwl(xfm, &xfm->regamma_params); 610 xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_USER); 611 } else { 612 xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_BYPASS); 613 } 614 615 xfm->funcs->opp_power_on_regamma_lut(xfm, false); 616 617 return true; 618 } 619 620 static enum dc_status bios_parser_crtc_source_select( 621 struct pipe_ctx *pipe_ctx) 622 { 623 struct dc_bios *dcb; 624 /* call VBIOS table to set CRTC source for the HW 625 * encoder block 626 * note: video bios clears all FMT setting here. */ 627 struct bp_crtc_source_select crtc_source_select = {0}; 628 const struct dc_sink *sink = pipe_ctx->stream->sink; 629 630 crtc_source_select.engine_id = pipe_ctx->stream_res.stream_enc->id; 631 crtc_source_select.controller_id = pipe_ctx->stream_res.tg->inst + 1; 632 /*TODO: Need to un-hardcode color depth, dp_audio and account for 633 * the case where signal and sink signal is different (translator 634 * encoder)*/ 635 crtc_source_select.signal = pipe_ctx->stream->signal; 636 crtc_source_select.enable_dp_audio = false; 637 crtc_source_select.sink_signal = pipe_ctx->stream->signal; 638 639 switch (pipe_ctx->stream->timing.display_color_depth) { 640 case COLOR_DEPTH_666: 641 crtc_source_select.display_output_bit_depth = PANEL_6BIT_COLOR; 642 break; 643 case COLOR_DEPTH_888: 644 crtc_source_select.display_output_bit_depth = PANEL_8BIT_COLOR; 645 break; 646 case COLOR_DEPTH_101010: 647 crtc_source_select.display_output_bit_depth = PANEL_10BIT_COLOR; 648 break; 649 case COLOR_DEPTH_121212: 650 crtc_source_select.display_output_bit_depth = PANEL_12BIT_COLOR; 651 break; 652 default: 653 BREAK_TO_DEBUGGER(); 654 crtc_source_select.display_output_bit_depth = PANEL_8BIT_COLOR; 655 break; 656 } 657 658 dcb = sink->ctx->dc_bios; 659 660 if (BP_RESULT_OK != dcb->funcs->crtc_source_select( 661 dcb, 662 &crtc_source_select)) { 663 return DC_ERROR_UNEXPECTED; 664 } 665 666 return DC_OK; 667 } 668 669 void dce110_update_info_frame(struct pipe_ctx *pipe_ctx) 670 { 671 bool is_hdmi; 672 bool is_dp; 673 674 ASSERT(pipe_ctx->stream); 675 676 if (pipe_ctx->stream_res.stream_enc == NULL) 677 return; /* this is not root pipe */ 678 679 is_hdmi = dc_is_hdmi_signal(pipe_ctx->stream->signal); 680 is_dp = dc_is_dp_signal(pipe_ctx->stream->signal); 681 682 if (!is_hdmi && !is_dp) 683 return; 684 685 if (is_hdmi) 686 pipe_ctx->stream_res.stream_enc->funcs->update_hdmi_info_packets( 687 pipe_ctx->stream_res.stream_enc, 688 &pipe_ctx->stream_res.encoder_info_frame); 689 else 690 pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets( 691 pipe_ctx->stream_res.stream_enc, 692 &pipe_ctx->stream_res.encoder_info_frame); 693 } 694 695 void dce110_enable_stream(struct pipe_ctx *pipe_ctx) 696 { 697 enum dc_lane_count lane_count = 698 pipe_ctx->stream->sink->link->cur_link_settings.lane_count; 699 700 struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; 701 struct dc_link *link = pipe_ctx->stream->sink->link; 702 703 704 uint32_t active_total_with_borders; 705 uint32_t early_control = 0; 706 struct timing_generator *tg = pipe_ctx->stream_res.tg; 707 708 /* For MST, there are multiply stream go to only one link. 709 * connect DIG back_end to front_end while enable_stream and 710 * disconnect them during disable_stream 711 * BY this, it is logic clean to separate stream and link */ 712 link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc, 713 pipe_ctx->stream_res.stream_enc->id, true); 714 715 /* update AVI info frame (HDMI, DP)*/ 716 /* TODO: FPGA may change to hwss.update_info_frame */ 717 dce110_update_info_frame(pipe_ctx); 718 719 /* enable early control to avoid corruption on DP monitor*/ 720 active_total_with_borders = 721 timing->h_addressable 722 + timing->h_border_left 723 + timing->h_border_right; 724 725 if (lane_count != 0) 726 early_control = active_total_with_borders % lane_count; 727 728 if (early_control == 0) 729 early_control = lane_count; 730 731 tg->funcs->set_early_control(tg, early_control); 732 733 /* enable audio only within mode set */ 734 if (pipe_ctx->stream_res.audio != NULL) { 735 if (dc_is_dp_signal(pipe_ctx->stream->signal)) 736 pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.stream_enc); 737 } 738 739 740 741 742 } 743 744 /*todo: cloned in stream enc, fix*/ 745 static bool is_panel_backlight_on(struct dce_hwseq *hws) 746 { 747 uint32_t value; 748 749 REG_GET(LVTMA_PWRSEQ_CNTL, LVTMA_BLON, &value); 750 751 return value; 752 } 753 754 static bool is_panel_powered_on(struct dce_hwseq *hws) 755 { 756 uint32_t pwr_seq_state, dig_on, dig_on_ovrd; 757 758 759 REG_GET(LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, &pwr_seq_state); 760 761 REG_GET_2(LVTMA_PWRSEQ_CNTL, LVTMA_DIGON, &dig_on, LVTMA_DIGON_OVRD, &dig_on_ovrd); 762 763 return (pwr_seq_state == 1) || (dig_on == 1 && dig_on_ovrd == 1); 764 } 765 766 static enum bp_result link_transmitter_control( 767 struct dc_bios *bios, 768 struct bp_transmitter_control *cntl) 769 { 770 enum bp_result result; 771 772 result = bios->funcs->transmitter_control(bios, cntl); 773 774 return result; 775 } 776 777 /* 778 * @brief 779 * eDP only. 780 */ 781 void hwss_edp_wait_for_hpd_ready( 782 struct dc_link *link, 783 bool power_up) 784 { 785 struct dc_context *ctx = link->ctx; 786 struct graphics_object_id connector = link->link_enc->connector; 787 struct gpio *hpd; 788 bool edp_hpd_high = false; 789 uint32_t time_elapsed = 0; 790 uint32_t timeout = power_up ? 791 PANEL_POWER_UP_TIMEOUT : PANEL_POWER_DOWN_TIMEOUT; 792 793 if (dal_graphics_object_id_get_connector_id(connector) 794 != CONNECTOR_ID_EDP) { 795 BREAK_TO_DEBUGGER(); 796 return; 797 } 798 799 if (!power_up) 800 /* 801 * From KV, we will not HPD low after turning off VCC - 802 * instead, we will check the SW timer in power_up(). 803 */ 804 return; 805 806 /* 807 * When we power on/off the eDP panel, 808 * we need to wait until SENSE bit is high/low. 809 */ 810 811 /* obtain HPD */ 812 /* TODO what to do with this? */ 813 hpd = get_hpd_gpio(ctx->dc_bios, connector, ctx->gpio_service); 814 815 if (!hpd) { 816 BREAK_TO_DEBUGGER(); 817 return; 818 } 819 820 dal_gpio_open(hpd, GPIO_MODE_INTERRUPT); 821 822 /* wait until timeout or panel detected */ 823 824 do { 825 uint32_t detected = 0; 826 827 dal_gpio_get_value(hpd, &detected); 828 829 if (!(detected ^ power_up)) { 830 edp_hpd_high = true; 831 break; 832 } 833 834 msleep(HPD_CHECK_INTERVAL); 835 836 time_elapsed += HPD_CHECK_INTERVAL; 837 } while (time_elapsed < timeout); 838 839 dal_gpio_close(hpd); 840 841 dal_gpio_destroy_irq(&hpd); 842 843 if (false == edp_hpd_high) { 844 DC_LOG_ERROR( 845 "%s: wait timed out!\n", __func__); 846 } 847 } 848 849 void hwss_edp_power_control( 850 struct dc_link *link, 851 bool power_up) 852 { 853 struct dc_context *ctx = link->ctx; 854 struct dce_hwseq *hwseq = ctx->dc->hwseq; 855 struct bp_transmitter_control cntl = { 0 }; 856 enum bp_result bp_result; 857 858 859 if (dal_graphics_object_id_get_connector_id(link->link_enc->connector) 860 != CONNECTOR_ID_EDP) { 861 BREAK_TO_DEBUGGER(); 862 return; 863 } 864 865 if (power_up != is_panel_powered_on(hwseq)) { 866 /* Send VBIOS command to prompt eDP panel power */ 867 if (power_up) { 868 unsigned long long current_ts = dm_get_timestamp(ctx); 869 unsigned long long duration_in_ms = 870 div64_u64(dm_get_elapse_time_in_ns( 871 ctx, 872 current_ts, 873 link->link_trace.time_stamp.edp_poweroff), 1000000); 874 unsigned long long wait_time_ms = 0; 875 876 /* max 500ms from LCDVDD off to on */ 877 unsigned long long edp_poweroff_time_ms = 500; 878 879 if (link->local_sink != NULL) 880 edp_poweroff_time_ms = 881 500 + link->local_sink->edid_caps.panel_patch.extra_t12_ms; 882 if (link->link_trace.time_stamp.edp_poweroff == 0) 883 wait_time_ms = edp_poweroff_time_ms; 884 else if (duration_in_ms < edp_poweroff_time_ms) 885 wait_time_ms = edp_poweroff_time_ms - duration_in_ms; 886 887 if (wait_time_ms) { 888 msleep(wait_time_ms); 889 dm_output_to_console("%s: wait %lld ms to power on eDP.\n", 890 __func__, wait_time_ms); 891 } 892 893 } 894 895 DC_LOG_HW_RESUME_S3( 896 "%s: Panel Power action: %s\n", 897 __func__, (power_up ? "On":"Off")); 898 899 cntl.action = power_up ? 900 TRANSMITTER_CONTROL_POWER_ON : 901 TRANSMITTER_CONTROL_POWER_OFF; 902 cntl.transmitter = link->link_enc->transmitter; 903 cntl.connector_obj_id = link->link_enc->connector; 904 cntl.coherent = false; 905 cntl.lanes_number = LANE_COUNT_FOUR; 906 cntl.hpd_sel = link->link_enc->hpd_source; 907 bp_result = link_transmitter_control(ctx->dc_bios, &cntl); 908 909 if (!power_up) 910 /*save driver power off time stamp*/ 911 link->link_trace.time_stamp.edp_poweroff = dm_get_timestamp(ctx); 912 else 913 link->link_trace.time_stamp.edp_poweron = dm_get_timestamp(ctx); 914 915 if (bp_result != BP_RESULT_OK) 916 DC_LOG_ERROR( 917 "%s: Panel Power bp_result: %d\n", 918 __func__, bp_result); 919 } else { 920 DC_LOG_HW_RESUME_S3( 921 "%s: Skipping Panel Power action: %s\n", 922 __func__, (power_up ? "On":"Off")); 923 } 924 } 925 926 /*todo: cloned in stream enc, fix*/ 927 /* 928 * @brief 929 * eDP only. Control the backlight of the eDP panel 930 */ 931 void hwss_edp_backlight_control( 932 struct dc_link *link, 933 bool enable) 934 { 935 struct dc_context *ctx = link->ctx; 936 struct dce_hwseq *hws = ctx->dc->hwseq; 937 struct bp_transmitter_control cntl = { 0 }; 938 939 if (dal_graphics_object_id_get_connector_id(link->link_enc->connector) 940 != CONNECTOR_ID_EDP) { 941 BREAK_TO_DEBUGGER(); 942 return; 943 } 944 945 if (enable && is_panel_backlight_on(hws)) { 946 DC_LOG_HW_RESUME_S3( 947 "%s: panel already powered up. Do nothing.\n", 948 __func__); 949 return; 950 } 951 952 /* Send VBIOS command to control eDP panel backlight */ 953 954 DC_LOG_HW_RESUME_S3( 955 "%s: backlight action: %s\n", 956 __func__, (enable ? "On":"Off")); 957 958 cntl.action = enable ? 959 TRANSMITTER_CONTROL_BACKLIGHT_ON : 960 TRANSMITTER_CONTROL_BACKLIGHT_OFF; 961 962 /*cntl.engine_id = ctx->engine;*/ 963 cntl.transmitter = link->link_enc->transmitter; 964 cntl.connector_obj_id = link->link_enc->connector; 965 /*todo: unhardcode*/ 966 cntl.lanes_number = LANE_COUNT_FOUR; 967 cntl.hpd_sel = link->link_enc->hpd_source; 968 cntl.signal = SIGNAL_TYPE_EDP; 969 970 /* For eDP, the following delays might need to be considered 971 * after link training completed: 972 * idle period - min. accounts for required BS-Idle pattern, 973 * max. allows for source frame synchronization); 974 * 50 msec max. delay from valid video data from source 975 * to video on dislpay or backlight enable. 976 * 977 * Disable the delay for now. 978 * Enable it in the future if necessary. 979 */ 980 /* dc_service_sleep_in_milliseconds(50); */ 981 /*edp 1.2*/ 982 if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_ON) 983 edp_receiver_ready_T7(link); 984 link_transmitter_control(ctx->dc_bios, &cntl); 985 /*edp 1.2*/ 986 if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_OFF) 987 edp_receiver_ready_T9(link); 988 } 989 990 void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx) 991 { 992 struct dc *core_dc = pipe_ctx->stream->ctx->dc; 993 /* notify audio driver for audio modes of monitor */ 994 struct pp_smu_funcs_rv *pp_smu = core_dc->res_pool->pp_smu; 995 unsigned int i, num_audio = 1; 996 997 if (pipe_ctx->stream_res.audio) { 998 for (i = 0; i < MAX_PIPES; i++) { 999 /*current_state not updated yet*/ 1000 if (core_dc->current_state->res_ctx.pipe_ctx[i].stream_res.audio != NULL) 1001 num_audio++; 1002 } 1003 1004 pipe_ctx->stream_res.audio->funcs->az_enable(pipe_ctx->stream_res.audio); 1005 1006 if (num_audio >= 1 && pp_smu != NULL && pp_smu->set_pme_wa_enable != NULL) 1007 /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/ 1008 pp_smu->set_pme_wa_enable(&pp_smu->pp_smu); 1009 /* un-mute audio */ 1010 /* TODO: audio should be per stream rather than per link */ 1011 pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( 1012 pipe_ctx->stream_res.stream_enc, false); 1013 } 1014 } 1015 1016 void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option) 1017 { 1018 struct dc *dc = pipe_ctx->stream->ctx->dc; 1019 1020 pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( 1021 pipe_ctx->stream_res.stream_enc, true); 1022 if (pipe_ctx->stream_res.audio) { 1023 struct pp_smu_funcs_rv *pp_smu = dc->res_pool->pp_smu; 1024 1025 if (option != KEEP_ACQUIRED_RESOURCE || 1026 !dc->debug.az_endpoint_mute_only) { 1027 /*only disalbe az_endpoint if power down or free*/ 1028 pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio); 1029 } 1030 1031 if (dc_is_dp_signal(pipe_ctx->stream->signal)) 1032 pipe_ctx->stream_res.stream_enc->funcs->dp_audio_disable( 1033 pipe_ctx->stream_res.stream_enc); 1034 else 1035 pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_disable( 1036 pipe_ctx->stream_res.stream_enc); 1037 /*don't free audio if it is from retrain or internal disable stream*/ 1038 if (option == FREE_ACQUIRED_RESOURCE && dc->caps.dynamic_audio == true) { 1039 /*we have to dynamic arbitrate the audio endpoints*/ 1040 /*we free the resource, need reset is_audio_acquired*/ 1041 update_audio_usage(&dc->current_state->res_ctx, dc->res_pool, pipe_ctx->stream_res.audio, false); 1042 pipe_ctx->stream_res.audio = NULL; 1043 } 1044 if (pp_smu != NULL && pp_smu->set_pme_wa_enable != NULL) 1045 /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/ 1046 pp_smu->set_pme_wa_enable(&pp_smu->pp_smu); 1047 1048 /* TODO: notify audio driver for if audio modes list changed 1049 * add audio mode list change flag */ 1050 /* dal_audio_disable_azalia_audio_jack_presence(stream->audio, 1051 * stream->stream_engine_id); 1052 */ 1053 } 1054 } 1055 1056 void dce110_disable_stream(struct pipe_ctx *pipe_ctx, int option) 1057 { 1058 struct dc_stream_state *stream = pipe_ctx->stream; 1059 struct dc_link *link = stream->sink->link; 1060 struct dc *dc = pipe_ctx->stream->ctx->dc; 1061 1062 if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) 1063 pipe_ctx->stream_res.stream_enc->funcs->stop_hdmi_info_packets( 1064 pipe_ctx->stream_res.stream_enc); 1065 1066 if (dc_is_dp_signal(pipe_ctx->stream->signal)) 1067 pipe_ctx->stream_res.stream_enc->funcs->stop_dp_info_packets( 1068 pipe_ctx->stream_res.stream_enc); 1069 1070 dc->hwss.disable_audio_stream(pipe_ctx, option); 1071 1072 link->link_enc->funcs->connect_dig_be_to_fe( 1073 link->link_enc, 1074 pipe_ctx->stream_res.stream_enc->id, 1075 false); 1076 1077 } 1078 1079 void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, 1080 struct dc_link_settings *link_settings) 1081 { 1082 struct encoder_unblank_param params = { { 0 } }; 1083 struct dc_stream_state *stream = pipe_ctx->stream; 1084 struct dc_link *link = stream->sink->link; 1085 1086 /* only 3 items below are used by unblank */ 1087 params.pixel_clk_khz = 1088 pipe_ctx->stream->timing.pix_clk_khz; 1089 params.link_settings.link_rate = link_settings->link_rate; 1090 1091 if (dc_is_dp_signal(pipe_ctx->stream->signal)) 1092 pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(pipe_ctx->stream_res.stream_enc, ¶ms); 1093 1094 if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) { 1095 link->dc->hwss.edp_backlight_control(link, true); 1096 stream->bl_pwm_level = EDP_BACKLIGHT_RAMP_DISABLE_LEVEL; 1097 } 1098 } 1099 void dce110_blank_stream(struct pipe_ctx *pipe_ctx) 1100 { 1101 struct dc_stream_state *stream = pipe_ctx->stream; 1102 struct dc_link *link = stream->sink->link; 1103 1104 if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) { 1105 link->dc->hwss.edp_backlight_control(link, false); 1106 dc_link_set_abm_disable(link); 1107 } 1108 1109 if (dc_is_dp_signal(pipe_ctx->stream->signal)) 1110 pipe_ctx->stream_res.stream_enc->funcs->dp_blank(pipe_ctx->stream_res.stream_enc); 1111 } 1112 1113 1114 void dce110_set_avmute(struct pipe_ctx *pipe_ctx, bool enable) 1115 { 1116 if (pipe_ctx != NULL && pipe_ctx->stream_res.stream_enc != NULL) 1117 pipe_ctx->stream_res.stream_enc->funcs->set_avmute(pipe_ctx->stream_res.stream_enc, enable); 1118 } 1119 1120 static enum audio_dto_source translate_to_dto_source(enum controller_id crtc_id) 1121 { 1122 switch (crtc_id) { 1123 case CONTROLLER_ID_D0: 1124 return DTO_SOURCE_ID0; 1125 case CONTROLLER_ID_D1: 1126 return DTO_SOURCE_ID1; 1127 case CONTROLLER_ID_D2: 1128 return DTO_SOURCE_ID2; 1129 case CONTROLLER_ID_D3: 1130 return DTO_SOURCE_ID3; 1131 case CONTROLLER_ID_D4: 1132 return DTO_SOURCE_ID4; 1133 case CONTROLLER_ID_D5: 1134 return DTO_SOURCE_ID5; 1135 default: 1136 return DTO_SOURCE_UNKNOWN; 1137 } 1138 } 1139 1140 static void build_audio_output( 1141 struct dc_state *state, 1142 const struct pipe_ctx *pipe_ctx, 1143 struct audio_output *audio_output) 1144 { 1145 const struct dc_stream_state *stream = pipe_ctx->stream; 1146 audio_output->engine_id = pipe_ctx->stream_res.stream_enc->id; 1147 1148 audio_output->signal = pipe_ctx->stream->signal; 1149 1150 /* audio_crtc_info */ 1151 1152 audio_output->crtc_info.h_total = 1153 stream->timing.h_total; 1154 1155 /* 1156 * Audio packets are sent during actual CRTC blank physical signal, we 1157 * need to specify actual active signal portion 1158 */ 1159 audio_output->crtc_info.h_active = 1160 stream->timing.h_addressable 1161 + stream->timing.h_border_left 1162 + stream->timing.h_border_right; 1163 1164 audio_output->crtc_info.v_active = 1165 stream->timing.v_addressable 1166 + stream->timing.v_border_top 1167 + stream->timing.v_border_bottom; 1168 1169 audio_output->crtc_info.pixel_repetition = 1; 1170 1171 audio_output->crtc_info.interlaced = 1172 stream->timing.flags.INTERLACE; 1173 1174 audio_output->crtc_info.refresh_rate = 1175 (stream->timing.pix_clk_khz*1000)/ 1176 (stream->timing.h_total*stream->timing.v_total); 1177 1178 audio_output->crtc_info.color_depth = 1179 stream->timing.display_color_depth; 1180 1181 audio_output->crtc_info.requested_pixel_clock = 1182 pipe_ctx->stream_res.pix_clk_params.requested_pix_clk; 1183 1184 audio_output->crtc_info.calculated_pixel_clock = 1185 pipe_ctx->stream_res.pix_clk_params.requested_pix_clk; 1186 1187 /*for HDMI, audio ACR is with deep color ratio factor*/ 1188 if (dc_is_hdmi_signal(pipe_ctx->stream->signal) && 1189 audio_output->crtc_info.requested_pixel_clock == 1190 stream->timing.pix_clk_khz) { 1191 if (pipe_ctx->stream_res.pix_clk_params.pixel_encoding == PIXEL_ENCODING_YCBCR420) { 1192 audio_output->crtc_info.requested_pixel_clock = 1193 audio_output->crtc_info.requested_pixel_clock/2; 1194 audio_output->crtc_info.calculated_pixel_clock = 1195 pipe_ctx->stream_res.pix_clk_params.requested_pix_clk/2; 1196 1197 } 1198 } 1199 1200 if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT || 1201 pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { 1202 audio_output->pll_info.dp_dto_source_clock_in_khz = 1203 state->dis_clk->funcs->get_dp_ref_clk_frequency( 1204 state->dis_clk); 1205 } 1206 1207 audio_output->pll_info.feed_back_divider = 1208 pipe_ctx->pll_settings.feedback_divider; 1209 1210 audio_output->pll_info.dto_source = 1211 translate_to_dto_source( 1212 pipe_ctx->stream_res.tg->inst + 1); 1213 1214 /* TODO hard code to enable for now. Need get from stream */ 1215 audio_output->pll_info.ss_enabled = true; 1216 1217 audio_output->pll_info.ss_percentage = 1218 pipe_ctx->pll_settings.ss_percentage; 1219 } 1220 1221 static void get_surface_visual_confirm_color(const struct pipe_ctx *pipe_ctx, 1222 struct tg_color *color) 1223 { 1224 uint32_t color_value = MAX_TG_COLOR_VALUE * (4 - pipe_ctx->stream_res.tg->inst) / 4; 1225 1226 switch (pipe_ctx->plane_res.scl_data.format) { 1227 case PIXEL_FORMAT_ARGB8888: 1228 /* set boarder color to red */ 1229 color->color_r_cr = color_value; 1230 break; 1231 1232 case PIXEL_FORMAT_ARGB2101010: 1233 /* set boarder color to blue */ 1234 color->color_b_cb = color_value; 1235 break; 1236 case PIXEL_FORMAT_420BPP8: 1237 /* set boarder color to green */ 1238 color->color_g_y = color_value; 1239 break; 1240 case PIXEL_FORMAT_420BPP10: 1241 /* set boarder color to yellow */ 1242 color->color_g_y = color_value; 1243 color->color_r_cr = color_value; 1244 break; 1245 case PIXEL_FORMAT_FP16: 1246 /* set boarder color to white */ 1247 color->color_r_cr = color_value; 1248 color->color_b_cb = color_value; 1249 color->color_g_y = color_value; 1250 break; 1251 default: 1252 break; 1253 } 1254 } 1255 1256 static void program_scaler(const struct dc *dc, 1257 const struct pipe_ctx *pipe_ctx) 1258 { 1259 struct tg_color color = {0}; 1260 1261 #if defined(CONFIG_DRM_AMD_DC_DCN1_0) 1262 /* TOFPGA */ 1263 if (pipe_ctx->plane_res.xfm->funcs->transform_set_pixel_storage_depth == NULL) 1264 return; 1265 #endif 1266 1267 if (dc->debug.visual_confirm == VISUAL_CONFIRM_SURFACE) 1268 get_surface_visual_confirm_color(pipe_ctx, &color); 1269 else 1270 color_space_to_black_color(dc, 1271 pipe_ctx->stream->output_color_space, 1272 &color); 1273 1274 pipe_ctx->plane_res.xfm->funcs->transform_set_pixel_storage_depth( 1275 pipe_ctx->plane_res.xfm, 1276 pipe_ctx->plane_res.scl_data.lb_params.depth, 1277 &pipe_ctx->stream->bit_depth_params); 1278 1279 if (pipe_ctx->stream_res.tg->funcs->set_overscan_blank_color) { 1280 /* 1281 * The way 420 is packed, 2 channels carry Y component, 1 channel 1282 * alternate between Cb and Cr, so both channels need the pixel 1283 * value for Y 1284 */ 1285 if (pipe_ctx->stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) 1286 color.color_r_cr = color.color_g_y; 1287 1288 pipe_ctx->stream_res.tg->funcs->set_overscan_blank_color( 1289 pipe_ctx->stream_res.tg, 1290 &color); 1291 } 1292 1293 pipe_ctx->plane_res.xfm->funcs->transform_set_scaler(pipe_ctx->plane_res.xfm, 1294 &pipe_ctx->plane_res.scl_data); 1295 } 1296 1297 static enum dc_status dce110_enable_stream_timing( 1298 struct pipe_ctx *pipe_ctx, 1299 struct dc_state *context, 1300 struct dc *dc) 1301 { 1302 struct dc_stream_state *stream = pipe_ctx->stream; 1303 struct pipe_ctx *pipe_ctx_old = &dc->current_state->res_ctx. 1304 pipe_ctx[pipe_ctx->pipe_idx]; 1305 struct tg_color black_color = {0}; 1306 1307 if (!pipe_ctx_old->stream) { 1308 1309 /* program blank color */ 1310 color_space_to_black_color(dc, 1311 stream->output_color_space, &black_color); 1312 pipe_ctx->stream_res.tg->funcs->set_blank_color( 1313 pipe_ctx->stream_res.tg, 1314 &black_color); 1315 1316 /* 1317 * Must blank CRTC after disabling power gating and before any 1318 * programming, otherwise CRTC will be hung in bad state 1319 */ 1320 pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, true); 1321 1322 if (false == pipe_ctx->clock_source->funcs->program_pix_clk( 1323 pipe_ctx->clock_source, 1324 &pipe_ctx->stream_res.pix_clk_params, 1325 &pipe_ctx->pll_settings)) { 1326 BREAK_TO_DEBUGGER(); 1327 return DC_ERROR_UNEXPECTED; 1328 } 1329 1330 pipe_ctx->stream_res.tg->funcs->program_timing( 1331 pipe_ctx->stream_res.tg, 1332 &stream->timing, 1333 true); 1334 1335 pipe_ctx->stream_res.tg->funcs->set_static_screen_control( 1336 pipe_ctx->stream_res.tg, 1337 0x182); 1338 } 1339 1340 if (!pipe_ctx_old->stream) { 1341 if (false == pipe_ctx->stream_res.tg->funcs->enable_crtc( 1342 pipe_ctx->stream_res.tg)) { 1343 BREAK_TO_DEBUGGER(); 1344 return DC_ERROR_UNEXPECTED; 1345 } 1346 } 1347 1348 1349 1350 return DC_OK; 1351 } 1352 1353 static enum dc_status apply_single_controller_ctx_to_hw( 1354 struct pipe_ctx *pipe_ctx, 1355 struct dc_state *context, 1356 struct dc *dc) 1357 { 1358 struct dc_stream_state *stream = pipe_ctx->stream; 1359 struct pipe_ctx *pipe_ctx_old = &dc->current_state->res_ctx. 1360 pipe_ctx[pipe_ctx->pipe_idx]; 1361 1362 if (pipe_ctx->stream_res.audio != NULL) { 1363 struct audio_output audio_output; 1364 1365 build_audio_output(context, pipe_ctx, &audio_output); 1366 1367 if (dc_is_dp_signal(pipe_ctx->stream->signal)) 1368 pipe_ctx->stream_res.stream_enc->funcs->dp_audio_setup( 1369 pipe_ctx->stream_res.stream_enc, 1370 pipe_ctx->stream_res.audio->inst, 1371 &pipe_ctx->stream->audio_info); 1372 else 1373 pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_setup( 1374 pipe_ctx->stream_res.stream_enc, 1375 pipe_ctx->stream_res.audio->inst, 1376 &pipe_ctx->stream->audio_info, 1377 &audio_output.crtc_info); 1378 1379 pipe_ctx->stream_res.audio->funcs->az_configure( 1380 pipe_ctx->stream_res.audio, 1381 pipe_ctx->stream->signal, 1382 &audio_output.crtc_info, 1383 &pipe_ctx->stream->audio_info); 1384 } 1385 1386 /* */ 1387 dc->hwss.enable_stream_timing(pipe_ctx, context, dc); 1388 1389 /* FPGA does not program backend */ 1390 if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { 1391 pipe_ctx->stream_res.opp->funcs->opp_set_dyn_expansion( 1392 pipe_ctx->stream_res.opp, 1393 COLOR_SPACE_YCBCR601, 1394 stream->timing.display_color_depth, 1395 pipe_ctx->stream->signal); 1396 1397 pipe_ctx->stream_res.opp->funcs->opp_program_fmt( 1398 pipe_ctx->stream_res.opp, 1399 &stream->bit_depth_params, 1400 &stream->clamping); 1401 return DC_OK; 1402 } 1403 /* TODO: move to stream encoder */ 1404 if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL) 1405 if (DC_OK != bios_parser_crtc_source_select(pipe_ctx)) { 1406 BREAK_TO_DEBUGGER(); 1407 return DC_ERROR_UNEXPECTED; 1408 } 1409 pipe_ctx->stream_res.opp->funcs->opp_set_dyn_expansion( 1410 pipe_ctx->stream_res.opp, 1411 COLOR_SPACE_YCBCR601, 1412 stream->timing.display_color_depth, 1413 pipe_ctx->stream->signal); 1414 1415 if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL) 1416 stream->sink->link->link_enc->funcs->setup( 1417 stream->sink->link->link_enc, 1418 pipe_ctx->stream->signal); 1419 1420 if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL) 1421 pipe_ctx->stream_res.stream_enc->funcs->setup_stereo_sync( 1422 pipe_ctx->stream_res.stream_enc, 1423 pipe_ctx->stream_res.tg->inst, 1424 stream->timing.timing_3d_format != TIMING_3D_FORMAT_NONE); 1425 1426 1427 pipe_ctx->stream_res.opp->funcs->opp_program_fmt( 1428 pipe_ctx->stream_res.opp, 1429 &stream->bit_depth_params, 1430 &stream->clamping); 1431 1432 if (dc_is_dp_signal(pipe_ctx->stream->signal)) 1433 pipe_ctx->stream_res.stream_enc->funcs->dp_set_stream_attribute( 1434 pipe_ctx->stream_res.stream_enc, 1435 &stream->timing, 1436 stream->output_color_space); 1437 1438 if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) 1439 pipe_ctx->stream_res.stream_enc->funcs->hdmi_set_stream_attribute( 1440 pipe_ctx->stream_res.stream_enc, 1441 &stream->timing, 1442 stream->phy_pix_clk, 1443 pipe_ctx->stream_res.audio != NULL); 1444 1445 if (dc_is_dvi_signal(pipe_ctx->stream->signal)) 1446 pipe_ctx->stream_res.stream_enc->funcs->dvi_set_stream_attribute( 1447 pipe_ctx->stream_res.stream_enc, 1448 &stream->timing, 1449 (pipe_ctx->stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK) ? 1450 true : false); 1451 1452 resource_build_info_frame(pipe_ctx); 1453 dce110_update_info_frame(pipe_ctx); 1454 if (!pipe_ctx_old->stream) 1455 core_link_enable_stream(context, pipe_ctx); 1456 1457 pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; 1458 1459 pipe_ctx->stream->sink->link->psr_enabled = false; 1460 1461 return DC_OK; 1462 } 1463 1464 /******************************************************************************/ 1465 1466 static void power_down_encoders(struct dc *dc) 1467 { 1468 int i; 1469 enum connector_id connector_id; 1470 enum signal_type signal = SIGNAL_TYPE_NONE; 1471 1472 /* do not know BIOS back-front mapping, simply blank all. It will not 1473 * hurt for non-DP 1474 */ 1475 for (i = 0; i < dc->res_pool->stream_enc_count; i++) { 1476 dc->res_pool->stream_enc[i]->funcs->dp_blank( 1477 dc->res_pool->stream_enc[i]); 1478 } 1479 1480 for (i = 0; i < dc->link_count; i++) { 1481 connector_id = dal_graphics_object_id_get_connector_id(dc->links[i]->link_id); 1482 if ((connector_id == CONNECTOR_ID_DISPLAY_PORT) || 1483 (connector_id == CONNECTOR_ID_EDP)) { 1484 1485 if (!dc->links[i]->wa_flags.dp_keep_receiver_powered) 1486 dp_receiver_power_ctrl(dc->links[i], false); 1487 if (connector_id == CONNECTOR_ID_EDP) 1488 signal = SIGNAL_TYPE_EDP; 1489 } 1490 1491 dc->links[i]->link_enc->funcs->disable_output( 1492 dc->links[i]->link_enc, signal); 1493 } 1494 } 1495 1496 static void power_down_controllers(struct dc *dc) 1497 { 1498 int i; 1499 1500 for (i = 0; i < dc->res_pool->timing_generator_count; i++) { 1501 dc->res_pool->timing_generators[i]->funcs->disable_crtc( 1502 dc->res_pool->timing_generators[i]); 1503 } 1504 } 1505 1506 static void power_down_clock_sources(struct dc *dc) 1507 { 1508 int i; 1509 1510 if (dc->res_pool->dp_clock_source->funcs->cs_power_down( 1511 dc->res_pool->dp_clock_source) == false) 1512 dm_error("Failed to power down pll! (dp clk src)\n"); 1513 1514 for (i = 0; i < dc->res_pool->clk_src_count; i++) { 1515 if (dc->res_pool->clock_sources[i]->funcs->cs_power_down( 1516 dc->res_pool->clock_sources[i]) == false) 1517 dm_error("Failed to power down pll! (clk src index=%d)\n", i); 1518 } 1519 } 1520 1521 static void power_down_all_hw_blocks(struct dc *dc) 1522 { 1523 power_down_encoders(dc); 1524 1525 power_down_controllers(dc); 1526 1527 power_down_clock_sources(dc); 1528 1529 if (dc->fbc_compressor) 1530 dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); 1531 } 1532 1533 static void disable_vga_and_power_gate_all_controllers( 1534 struct dc *dc) 1535 { 1536 int i; 1537 struct timing_generator *tg; 1538 struct dc_context *ctx = dc->ctx; 1539 1540 for (i = 0; i < dc->res_pool->timing_generator_count; i++) { 1541 tg = dc->res_pool->timing_generators[i]; 1542 1543 if (tg->funcs->disable_vga) 1544 tg->funcs->disable_vga(tg); 1545 } 1546 for (i = 0; i < dc->res_pool->pipe_count; i++) { 1547 /* Enable CLOCK gating for each pipe BEFORE controller 1548 * powergating. */ 1549 enable_display_pipe_clock_gating(ctx, 1550 true); 1551 1552 dc->current_state->res_ctx.pipe_ctx[i].pipe_idx = i; 1553 dc->hwss.disable_plane(dc, 1554 &dc->current_state->res_ctx.pipe_ctx[i]); 1555 } 1556 } 1557 1558 static struct dc_link *get_link_for_edp(struct dc *dc) 1559 { 1560 int i; 1561 1562 for (i = 0; i < dc->link_count; i++) { 1563 if (dc->links[i]->connector_signal == SIGNAL_TYPE_EDP) 1564 return dc->links[i]; 1565 } 1566 return NULL; 1567 } 1568 1569 static struct dc_link *get_link_for_edp_not_in_use( 1570 struct dc *dc, 1571 struct dc_state *context) 1572 { 1573 int i; 1574 struct dc_link *link = NULL; 1575 1576 /* check if eDP panel is suppose to be set mode, if yes, no need to disable */ 1577 for (i = 0; i < context->stream_count; i++) { 1578 if (context->streams[i]->signal == SIGNAL_TYPE_EDP) 1579 return NULL; 1580 } 1581 1582 /* check if there is an eDP panel not in use */ 1583 for (i = 0; i < dc->link_count; i++) { 1584 if (dc->links[i]->local_sink && 1585 dc->links[i]->local_sink->sink_signal == SIGNAL_TYPE_EDP) { 1586 link = dc->links[i]; 1587 break; 1588 } 1589 } 1590 1591 return link; 1592 } 1593 1594 /** 1595 * When ASIC goes from VBIOS/VGA mode to driver/accelerated mode we need: 1596 * 1. Power down all DC HW blocks 1597 * 2. Disable VGA engine on all controllers 1598 * 3. Enable power gating for controller 1599 * 4. Set acc_mode_change bit (VBIOS will clear this bit when going to FSDOS) 1600 */ 1601 void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context) 1602 { 1603 struct dc_link *edp_link_to_turnoff = NULL; 1604 struct dc_link *edp_link = get_link_for_edp(dc); 1605 bool can_eDP_fast_boot_optimize = false; 1606 1607 if (edp_link) { 1608 /* this seems to cause blank screens on DCE8 */ 1609 if ((dc->ctx->dce_version == DCE_VERSION_8_0) || 1610 (dc->ctx->dce_version == DCE_VERSION_8_1) || 1611 (dc->ctx->dce_version == DCE_VERSION_8_3)) 1612 can_eDP_fast_boot_optimize = false; 1613 else 1614 can_eDP_fast_boot_optimize = 1615 edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc); 1616 } 1617 1618 if (can_eDP_fast_boot_optimize) { 1619 edp_link_to_turnoff = get_link_for_edp_not_in_use(dc, context); 1620 1621 /* if OS doesn't light up eDP and eDP link is available, we want to disable 1622 * If resume from S4/S5, should optimization. 1623 */ 1624 if (!edp_link_to_turnoff) 1625 dc->apply_edp_fast_boot_optimization = true; 1626 } 1627 1628 if (!dc->apply_edp_fast_boot_optimization) { 1629 if (edp_link_to_turnoff) { 1630 /*turn off backlight before DP_blank and encoder powered down*/ 1631 dc->hwss.edp_backlight_control(edp_link_to_turnoff, false); 1632 } 1633 /*resume from S3, no vbios posting, no need to power down again*/ 1634 power_down_all_hw_blocks(dc); 1635 disable_vga_and_power_gate_all_controllers(dc); 1636 if (edp_link_to_turnoff) 1637 dc->hwss.edp_power_control(edp_link_to_turnoff, false); 1638 } 1639 bios_set_scratch_acc_mode_change(dc->ctx->dc_bios); 1640 } 1641 1642 static uint32_t compute_pstate_blackout_duration( 1643 struct bw_fixed blackout_duration, 1644 const struct dc_stream_state *stream) 1645 { 1646 uint32_t total_dest_line_time_ns; 1647 uint32_t pstate_blackout_duration_ns; 1648 1649 pstate_blackout_duration_ns = 1000 * blackout_duration.value >> 24; 1650 1651 total_dest_line_time_ns = 1000000UL * 1652 stream->timing.h_total / 1653 stream->timing.pix_clk_khz + 1654 pstate_blackout_duration_ns; 1655 1656 return total_dest_line_time_ns; 1657 } 1658 1659 static void dce110_set_displaymarks( 1660 const struct dc *dc, 1661 struct dc_state *context) 1662 { 1663 uint8_t i, num_pipes; 1664 unsigned int underlay_idx = dc->res_pool->underlay_pipe_index; 1665 1666 for (i = 0, num_pipes = 0; i < MAX_PIPES; i++) { 1667 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 1668 uint32_t total_dest_line_time_ns; 1669 1670 if (pipe_ctx->stream == NULL) 1671 continue; 1672 1673 total_dest_line_time_ns = compute_pstate_blackout_duration( 1674 dc->bw_vbios->blackout_duration, pipe_ctx->stream); 1675 pipe_ctx->plane_res.mi->funcs->mem_input_program_display_marks( 1676 pipe_ctx->plane_res.mi, 1677 context->bw.dce.nbp_state_change_wm_ns[num_pipes], 1678 context->bw.dce.stutter_exit_wm_ns[num_pipes], 1679 context->bw.dce.stutter_entry_wm_ns[num_pipes], 1680 context->bw.dce.urgent_wm_ns[num_pipes], 1681 total_dest_line_time_ns); 1682 if (i == underlay_idx) { 1683 num_pipes++; 1684 pipe_ctx->plane_res.mi->funcs->mem_input_program_chroma_display_marks( 1685 pipe_ctx->plane_res.mi, 1686 context->bw.dce.nbp_state_change_wm_ns[num_pipes], 1687 context->bw.dce.stutter_exit_wm_ns[num_pipes], 1688 context->bw.dce.urgent_wm_ns[num_pipes], 1689 total_dest_line_time_ns); 1690 } 1691 num_pipes++; 1692 } 1693 } 1694 1695 void dce110_set_safe_displaymarks( 1696 struct resource_context *res_ctx, 1697 const struct resource_pool *pool) 1698 { 1699 int i; 1700 int underlay_idx = pool->underlay_pipe_index; 1701 struct dce_watermarks max_marks = { 1702 MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK }; 1703 struct dce_watermarks nbp_marks = { 1704 SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK }; 1705 struct dce_watermarks min_marks = { 0, 0, 0, 0}; 1706 1707 for (i = 0; i < MAX_PIPES; i++) { 1708 if (res_ctx->pipe_ctx[i].stream == NULL || res_ctx->pipe_ctx[i].plane_res.mi == NULL) 1709 continue; 1710 1711 res_ctx->pipe_ctx[i].plane_res.mi->funcs->mem_input_program_display_marks( 1712 res_ctx->pipe_ctx[i].plane_res.mi, 1713 nbp_marks, 1714 max_marks, 1715 min_marks, 1716 max_marks, 1717 MAX_WATERMARK); 1718 1719 if (i == underlay_idx) 1720 res_ctx->pipe_ctx[i].plane_res.mi->funcs->mem_input_program_chroma_display_marks( 1721 res_ctx->pipe_ctx[i].plane_res.mi, 1722 nbp_marks, 1723 max_marks, 1724 max_marks, 1725 MAX_WATERMARK); 1726 1727 } 1728 } 1729 1730 /******************************************************************************* 1731 * Public functions 1732 ******************************************************************************/ 1733 1734 static void set_drr(struct pipe_ctx **pipe_ctx, 1735 int num_pipes, int vmin, int vmax) 1736 { 1737 int i = 0; 1738 struct drr_params params = {0}; 1739 1740 params.vertical_total_max = vmax; 1741 params.vertical_total_min = vmin; 1742 1743 /* TODO: If multiple pipes are to be supported, you need 1744 * some GSL stuff 1745 */ 1746 1747 for (i = 0; i < num_pipes; i++) { 1748 pipe_ctx[i]->stream_res.tg->funcs->set_drr(pipe_ctx[i]->stream_res.tg, ¶ms); 1749 } 1750 } 1751 1752 static void get_position(struct pipe_ctx **pipe_ctx, 1753 int num_pipes, 1754 struct crtc_position *position) 1755 { 1756 int i = 0; 1757 1758 /* TODO: handle pipes > 1 1759 */ 1760 for (i = 0; i < num_pipes; i++) 1761 pipe_ctx[i]->stream_res.tg->funcs->get_position(pipe_ctx[i]->stream_res.tg, position); 1762 } 1763 1764 static void set_static_screen_control(struct pipe_ctx **pipe_ctx, 1765 int num_pipes, const struct dc_static_screen_events *events) 1766 { 1767 unsigned int i; 1768 unsigned int value = 0; 1769 1770 if (events->overlay_update) 1771 value |= 0x100; 1772 if (events->surface_update) 1773 value |= 0x80; 1774 if (events->cursor_update) 1775 value |= 0x2; 1776 if (events->force_trigger) 1777 value |= 0x1; 1778 1779 value |= 0x84; 1780 1781 for (i = 0; i < num_pipes; i++) 1782 pipe_ctx[i]->stream_res.tg->funcs-> 1783 set_static_screen_control(pipe_ctx[i]->stream_res.tg, value); 1784 } 1785 1786 /* unit: in_khz before mode set, get pixel clock from context. ASIC register 1787 * may not be programmed yet 1788 */ 1789 static uint32_t get_max_pixel_clock_for_all_paths( 1790 struct dc *dc, 1791 struct dc_state *context) 1792 { 1793 uint32_t max_pix_clk = 0; 1794 int i; 1795 1796 for (i = 0; i < MAX_PIPES; i++) { 1797 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 1798 1799 if (pipe_ctx->stream == NULL) 1800 continue; 1801 1802 /* do not check under lay */ 1803 if (pipe_ctx->top_pipe) 1804 continue; 1805 1806 if (pipe_ctx->stream_res.pix_clk_params.requested_pix_clk > max_pix_clk) 1807 max_pix_clk = 1808 pipe_ctx->stream_res.pix_clk_params.requested_pix_clk; 1809 } 1810 1811 return max_pix_clk; 1812 } 1813 1814 /* 1815 * Check if FBC can be enabled 1816 */ 1817 static bool should_enable_fbc(struct dc *dc, 1818 struct dc_state *context, 1819 uint32_t *pipe_idx) 1820 { 1821 uint32_t i; 1822 struct pipe_ctx *pipe_ctx = NULL; 1823 struct resource_context *res_ctx = &context->res_ctx; 1824 1825 1826 ASSERT(dc->fbc_compressor); 1827 1828 /* FBC memory should be allocated */ 1829 if (!dc->ctx->fbc_gpu_addr) 1830 return false; 1831 1832 /* Only supports single display */ 1833 if (context->stream_count != 1) 1834 return false; 1835 1836 for (i = 0; i < dc->res_pool->pipe_count; i++) { 1837 if (res_ctx->pipe_ctx[i].stream) { 1838 pipe_ctx = &res_ctx->pipe_ctx[i]; 1839 *pipe_idx = i; 1840 break; 1841 } 1842 } 1843 1844 /* Pipe context should be found */ 1845 ASSERT(pipe_ctx); 1846 1847 /* Only supports eDP */ 1848 if (pipe_ctx->stream->sink->link->connector_signal != SIGNAL_TYPE_EDP) 1849 return false; 1850 1851 /* PSR should not be enabled */ 1852 if (pipe_ctx->stream->sink->link->psr_enabled) 1853 return false; 1854 1855 /* Nothing to compress */ 1856 if (!pipe_ctx->plane_state) 1857 return false; 1858 1859 /* Only for non-linear tiling */ 1860 if (pipe_ctx->plane_state->tiling_info.gfx8.array_mode == DC_ARRAY_LINEAR_GENERAL) 1861 return false; 1862 1863 return true; 1864 } 1865 1866 /* 1867 * Enable FBC 1868 */ 1869 static void enable_fbc(struct dc *dc, 1870 struct dc_state *context) 1871 { 1872 uint32_t pipe_idx = 0; 1873 1874 if (should_enable_fbc(dc, context, &pipe_idx)) { 1875 /* Program GRPH COMPRESSED ADDRESS and PITCH */ 1876 struct compr_addr_and_pitch_params params = {0, 0, 0}; 1877 struct compressor *compr = dc->fbc_compressor; 1878 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx]; 1879 1880 1881 params.source_view_width = pipe_ctx->stream->timing.h_addressable; 1882 params.source_view_height = pipe_ctx->stream->timing.v_addressable; 1883 1884 compr->compr_surface_address.quad_part = dc->ctx->fbc_gpu_addr; 1885 1886 compr->funcs->surface_address_and_pitch(compr, ¶ms); 1887 compr->funcs->set_fbc_invalidation_triggers(compr, 1); 1888 1889 compr->funcs->enable_fbc(compr, ¶ms); 1890 } 1891 } 1892 1893 static void dce110_reset_hw_ctx_wrap( 1894 struct dc *dc, 1895 struct dc_state *context) 1896 { 1897 int i; 1898 1899 /* Reset old context */ 1900 /* look up the targets that have been removed since last commit */ 1901 for (i = 0; i < MAX_PIPES; i++) { 1902 struct pipe_ctx *pipe_ctx_old = 1903 &dc->current_state->res_ctx.pipe_ctx[i]; 1904 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 1905 1906 /* Note: We need to disable output if clock sources change, 1907 * since bios does optimization and doesn't apply if changing 1908 * PHY when not already disabled. 1909 */ 1910 1911 /* Skip underlay pipe since it will be handled in commit surface*/ 1912 if (!pipe_ctx_old->stream || pipe_ctx_old->top_pipe) 1913 continue; 1914 1915 if (!pipe_ctx->stream || 1916 pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) { 1917 struct clock_source *old_clk = pipe_ctx_old->clock_source; 1918 1919 /* Disable if new stream is null. O/w, if stream is 1920 * disabled already, no need to disable again. 1921 */ 1922 if (!pipe_ctx->stream || !pipe_ctx->stream->dpms_off) 1923 core_link_disable_stream(pipe_ctx_old, FREE_ACQUIRED_RESOURCE); 1924 1925 pipe_ctx_old->stream_res.tg->funcs->set_blank(pipe_ctx_old->stream_res.tg, true); 1926 if (!hwss_wait_for_blank_complete(pipe_ctx_old->stream_res.tg)) { 1927 dm_error("DC: failed to blank crtc!\n"); 1928 BREAK_TO_DEBUGGER(); 1929 } 1930 pipe_ctx_old->stream_res.tg->funcs->disable_crtc(pipe_ctx_old->stream_res.tg); 1931 pipe_ctx_old->plane_res.mi->funcs->free_mem_input( 1932 pipe_ctx_old->plane_res.mi, dc->current_state->stream_count); 1933 1934 if (old_clk && 0 == resource_get_clock_source_reference(&context->res_ctx, 1935 dc->res_pool, 1936 old_clk)) 1937 old_clk->funcs->cs_power_down(old_clk); 1938 1939 dc->hwss.disable_plane(dc, pipe_ctx_old); 1940 1941 pipe_ctx_old->stream = NULL; 1942 } 1943 } 1944 } 1945 1946 static void dce110_setup_audio_dto( 1947 struct dc *dc, 1948 struct dc_state *context) 1949 { 1950 int i; 1951 1952 /* program audio wall clock. use HDMI as clock source if HDMI 1953 * audio active. Otherwise, use DP as clock source 1954 * first, loop to find any HDMI audio, if not, loop find DP audio 1955 */ 1956 /* Setup audio rate clock source */ 1957 /* Issue: 1958 * Audio lag happened on DP monitor when unplug a HDMI monitor 1959 * 1960 * Cause: 1961 * In case of DP and HDMI connected or HDMI only, DCCG_AUDIO_DTO_SEL 1962 * is set to either dto0 or dto1, audio should work fine. 1963 * In case of DP connected only, DCCG_AUDIO_DTO_SEL should be dto1, 1964 * set to dto0 will cause audio lag. 1965 * 1966 * Solution: 1967 * Not optimized audio wall dto setup. When mode set, iterate pipe_ctx, 1968 * find first available pipe with audio, setup audio wall DTO per topology 1969 * instead of per pipe. 1970 */ 1971 for (i = 0; i < dc->res_pool->pipe_count; i++) { 1972 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 1973 1974 if (pipe_ctx->stream == NULL) 1975 continue; 1976 1977 if (pipe_ctx->top_pipe) 1978 continue; 1979 1980 if (pipe_ctx->stream->signal != SIGNAL_TYPE_HDMI_TYPE_A) 1981 continue; 1982 1983 if (pipe_ctx->stream_res.audio != NULL) { 1984 struct audio_output audio_output; 1985 1986 build_audio_output(context, pipe_ctx, &audio_output); 1987 1988 pipe_ctx->stream_res.audio->funcs->wall_dto_setup( 1989 pipe_ctx->stream_res.audio, 1990 pipe_ctx->stream->signal, 1991 &audio_output.crtc_info, 1992 &audio_output.pll_info); 1993 break; 1994 } 1995 } 1996 1997 /* no HDMI audio is found, try DP audio */ 1998 if (i == dc->res_pool->pipe_count) { 1999 for (i = 0; i < dc->res_pool->pipe_count; i++) { 2000 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 2001 2002 if (pipe_ctx->stream == NULL) 2003 continue; 2004 2005 if (pipe_ctx->top_pipe) 2006 continue; 2007 2008 if (!dc_is_dp_signal(pipe_ctx->stream->signal)) 2009 continue; 2010 2011 if (pipe_ctx->stream_res.audio != NULL) { 2012 struct audio_output audio_output; 2013 2014 build_audio_output(context, pipe_ctx, &audio_output); 2015 2016 pipe_ctx->stream_res.audio->funcs->wall_dto_setup( 2017 pipe_ctx->stream_res.audio, 2018 pipe_ctx->stream->signal, 2019 &audio_output.crtc_info, 2020 &audio_output.pll_info); 2021 break; 2022 } 2023 } 2024 } 2025 } 2026 2027 enum dc_status dce110_apply_ctx_to_hw( 2028 struct dc *dc, 2029 struct dc_state *context) 2030 { 2031 struct dc_bios *dcb = dc->ctx->dc_bios; 2032 enum dc_status status; 2033 int i; 2034 2035 /* Reset old context */ 2036 /* look up the targets that have been removed since last commit */ 2037 dc->hwss.reset_hw_ctx_wrap(dc, context); 2038 2039 /* Skip applying if no targets */ 2040 if (context->stream_count <= 0) 2041 return DC_OK; 2042 2043 /* Apply new context */ 2044 dcb->funcs->set_scratch_critical_state(dcb, true); 2045 2046 /* below is for real asic only */ 2047 for (i = 0; i < dc->res_pool->pipe_count; i++) { 2048 struct pipe_ctx *pipe_ctx_old = 2049 &dc->current_state->res_ctx.pipe_ctx[i]; 2050 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 2051 2052 if (pipe_ctx->stream == NULL || pipe_ctx->top_pipe) 2053 continue; 2054 2055 if (pipe_ctx->stream == pipe_ctx_old->stream) { 2056 if (pipe_ctx_old->clock_source != pipe_ctx->clock_source) 2057 dce_crtc_switch_to_clk_src(dc->hwseq, 2058 pipe_ctx->clock_source, i); 2059 continue; 2060 } 2061 2062 dc->hwss.enable_display_power_gating( 2063 dc, i, dc->ctx->dc_bios, 2064 PIPE_GATING_CONTROL_DISABLE); 2065 } 2066 2067 if (dc->fbc_compressor) 2068 dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); 2069 2070 dce110_setup_audio_dto(dc, context); 2071 2072 for (i = 0; i < dc->res_pool->pipe_count; i++) { 2073 struct pipe_ctx *pipe_ctx_old = 2074 &dc->current_state->res_ctx.pipe_ctx[i]; 2075 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 2076 2077 if (pipe_ctx->stream == NULL) 2078 continue; 2079 2080 if (pipe_ctx->stream == pipe_ctx_old->stream) 2081 continue; 2082 2083 if (pipe_ctx_old->stream && !pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) 2084 continue; 2085 2086 if (pipe_ctx->top_pipe) 2087 continue; 2088 2089 status = apply_single_controller_ctx_to_hw( 2090 pipe_ctx, 2091 context, 2092 dc); 2093 2094 if (DC_OK != status) 2095 return status; 2096 } 2097 2098 dcb->funcs->set_scratch_critical_state(dcb, false); 2099 2100 if (dc->fbc_compressor) 2101 enable_fbc(dc, context); 2102 2103 return DC_OK; 2104 } 2105 2106 /******************************************************************************* 2107 * Front End programming 2108 ******************************************************************************/ 2109 static void set_default_colors(struct pipe_ctx *pipe_ctx) 2110 { 2111 struct default_adjustment default_adjust = { 0 }; 2112 2113 default_adjust.force_hw_default = false; 2114 default_adjust.in_color_space = pipe_ctx->plane_state->color_space; 2115 default_adjust.out_color_space = pipe_ctx->stream->output_color_space; 2116 default_adjust.csc_adjust_type = GRAPHICS_CSC_ADJUST_TYPE_SW; 2117 default_adjust.surface_pixel_format = pipe_ctx->plane_res.scl_data.format; 2118 2119 /* display color depth */ 2120 default_adjust.color_depth = 2121 pipe_ctx->stream->timing.display_color_depth; 2122 2123 /* Lb color depth */ 2124 default_adjust.lb_color_depth = pipe_ctx->plane_res.scl_data.lb_params.depth; 2125 2126 pipe_ctx->plane_res.xfm->funcs->opp_set_csc_default( 2127 pipe_ctx->plane_res.xfm, &default_adjust); 2128 } 2129 2130 2131 /******************************************************************************* 2132 * In order to turn on/off specific surface we will program 2133 * Blender + CRTC 2134 * 2135 * In case that we have two surfaces and they have a different visibility 2136 * we can't turn off the CRTC since it will turn off the entire display 2137 * 2138 * |----------------------------------------------- | 2139 * |bottom pipe|curr pipe | | | 2140 * |Surface |Surface | Blender | CRCT | 2141 * |visibility |visibility | Configuration| | 2142 * |------------------------------------------------| 2143 * | off | off | CURRENT_PIPE | blank | 2144 * | off | on | CURRENT_PIPE | unblank | 2145 * | on | off | OTHER_PIPE | unblank | 2146 * | on | on | BLENDING | unblank | 2147 * -------------------------------------------------| 2148 * 2149 ******************************************************************************/ 2150 static void program_surface_visibility(const struct dc *dc, 2151 struct pipe_ctx *pipe_ctx) 2152 { 2153 enum blnd_mode blender_mode = BLND_MODE_CURRENT_PIPE; 2154 bool blank_target = false; 2155 2156 if (pipe_ctx->bottom_pipe) { 2157 2158 /* For now we are supporting only two pipes */ 2159 ASSERT(pipe_ctx->bottom_pipe->bottom_pipe == NULL); 2160 2161 if (pipe_ctx->bottom_pipe->plane_state->visible) { 2162 if (pipe_ctx->plane_state->visible) 2163 blender_mode = BLND_MODE_BLENDING; 2164 else 2165 blender_mode = BLND_MODE_OTHER_PIPE; 2166 2167 } else if (!pipe_ctx->plane_state->visible) 2168 blank_target = true; 2169 2170 } else if (!pipe_ctx->plane_state->visible) 2171 blank_target = true; 2172 2173 dce_set_blender_mode(dc->hwseq, pipe_ctx->stream_res.tg->inst, blender_mode); 2174 pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, blank_target); 2175 2176 } 2177 2178 static void program_gamut_remap(struct pipe_ctx *pipe_ctx) 2179 { 2180 int i = 0; 2181 struct xfm_grph_csc_adjustment adjust; 2182 memset(&adjust, 0, sizeof(adjust)); 2183 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS; 2184 2185 2186 if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) { 2187 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW; 2188 2189 for (i = 0; i < CSC_TEMPERATURE_MATRIX_SIZE; i++) 2190 adjust.temperature_matrix[i] = 2191 pipe_ctx->stream->gamut_remap_matrix.matrix[i]; 2192 } 2193 2194 pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust); 2195 } 2196 static void update_plane_addr(const struct dc *dc, 2197 struct pipe_ctx *pipe_ctx) 2198 { 2199 struct dc_plane_state *plane_state = pipe_ctx->plane_state; 2200 2201 if (plane_state == NULL) 2202 return; 2203 2204 pipe_ctx->plane_res.mi->funcs->mem_input_program_surface_flip_and_addr( 2205 pipe_ctx->plane_res.mi, 2206 &plane_state->address, 2207 plane_state->flip_immediate); 2208 2209 plane_state->status.requested_address = plane_state->address; 2210 } 2211 2212 static void dce110_update_pending_status(struct pipe_ctx *pipe_ctx) 2213 { 2214 struct dc_plane_state *plane_state = pipe_ctx->plane_state; 2215 2216 if (plane_state == NULL) 2217 return; 2218 2219 plane_state->status.is_flip_pending = 2220 pipe_ctx->plane_res.mi->funcs->mem_input_is_flip_pending( 2221 pipe_ctx->plane_res.mi); 2222 2223 if (plane_state->status.is_flip_pending && !plane_state->visible) 2224 pipe_ctx->plane_res.mi->current_address = pipe_ctx->plane_res.mi->request_address; 2225 2226 plane_state->status.current_address = pipe_ctx->plane_res.mi->current_address; 2227 if (pipe_ctx->plane_res.mi->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO && 2228 pipe_ctx->stream_res.tg->funcs->is_stereo_left_eye) { 2229 plane_state->status.is_right_eye =\ 2230 !pipe_ctx->stream_res.tg->funcs->is_stereo_left_eye(pipe_ctx->stream_res.tg); 2231 } 2232 } 2233 2234 void dce110_power_down(struct dc *dc) 2235 { 2236 power_down_all_hw_blocks(dc); 2237 disable_vga_and_power_gate_all_controllers(dc); 2238 } 2239 2240 static bool wait_for_reset_trigger_to_occur( 2241 struct dc_context *dc_ctx, 2242 struct timing_generator *tg) 2243 { 2244 bool rc = false; 2245 2246 /* To avoid endless loop we wait at most 2247 * frames_to_wait_on_triggered_reset frames for the reset to occur. */ 2248 const uint32_t frames_to_wait_on_triggered_reset = 10; 2249 uint32_t i; 2250 2251 for (i = 0; i < frames_to_wait_on_triggered_reset; i++) { 2252 2253 if (!tg->funcs->is_counter_moving(tg)) { 2254 DC_ERROR("TG counter is not moving!\n"); 2255 break; 2256 } 2257 2258 if (tg->funcs->did_triggered_reset_occur(tg)) { 2259 rc = true; 2260 /* usually occurs at i=1 */ 2261 DC_SYNC_INFO("GSL: reset occurred at wait count: %d\n", 2262 i); 2263 break; 2264 } 2265 2266 /* Wait for one frame. */ 2267 tg->funcs->wait_for_state(tg, CRTC_STATE_VACTIVE); 2268 tg->funcs->wait_for_state(tg, CRTC_STATE_VBLANK); 2269 } 2270 2271 if (false == rc) 2272 DC_ERROR("GSL: Timeout on reset trigger!\n"); 2273 2274 return rc; 2275 } 2276 2277 /* Enable timing synchronization for a group of Timing Generators. */ 2278 static void dce110_enable_timing_synchronization( 2279 struct dc *dc, 2280 int group_index, 2281 int group_size, 2282 struct pipe_ctx *grouped_pipes[]) 2283 { 2284 struct dc_context *dc_ctx = dc->ctx; 2285 struct dcp_gsl_params gsl_params = { 0 }; 2286 int i; 2287 2288 DC_SYNC_INFO("GSL: Setting-up...\n"); 2289 2290 /* Designate a single TG in the group as a master. 2291 * Since HW doesn't care which one, we always assign 2292 * the 1st one in the group. */ 2293 gsl_params.gsl_group = 0; 2294 gsl_params.gsl_master = grouped_pipes[0]->stream_res.tg->inst; 2295 2296 for (i = 0; i < group_size; i++) 2297 grouped_pipes[i]->stream_res.tg->funcs->setup_global_swap_lock( 2298 grouped_pipes[i]->stream_res.tg, &gsl_params); 2299 2300 /* Reset slave controllers on master VSync */ 2301 DC_SYNC_INFO("GSL: enabling trigger-reset\n"); 2302 2303 for (i = 1 /* skip the master */; i < group_size; i++) 2304 grouped_pipes[i]->stream_res.tg->funcs->enable_reset_trigger( 2305 grouped_pipes[i]->stream_res.tg, 2306 gsl_params.gsl_group); 2307 2308 for (i = 1 /* skip the master */; i < group_size; i++) { 2309 DC_SYNC_INFO("GSL: waiting for reset to occur.\n"); 2310 wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->stream_res.tg); 2311 grouped_pipes[i]->stream_res.tg->funcs->disable_reset_trigger( 2312 grouped_pipes[i]->stream_res.tg); 2313 } 2314 2315 /* GSL Vblank synchronization is a one time sync mechanism, assumption 2316 * is that the sync'ed displays will not drift out of sync over time*/ 2317 DC_SYNC_INFO("GSL: Restoring register states.\n"); 2318 for (i = 0; i < group_size; i++) 2319 grouped_pipes[i]->stream_res.tg->funcs->tear_down_global_swap_lock(grouped_pipes[i]->stream_res.tg); 2320 2321 DC_SYNC_INFO("GSL: Set-up complete.\n"); 2322 } 2323 2324 static void dce110_enable_per_frame_crtc_position_reset( 2325 struct dc *dc, 2326 int group_size, 2327 struct pipe_ctx *grouped_pipes[]) 2328 { 2329 struct dc_context *dc_ctx = dc->ctx; 2330 struct dcp_gsl_params gsl_params = { 0 }; 2331 int i; 2332 2333 gsl_params.gsl_group = 0; 2334 gsl_params.gsl_master = grouped_pipes[0]->stream->triggered_crtc_reset.event_source->status.primary_otg_inst; 2335 2336 for (i = 0; i < group_size; i++) 2337 grouped_pipes[i]->stream_res.tg->funcs->setup_global_swap_lock( 2338 grouped_pipes[i]->stream_res.tg, &gsl_params); 2339 2340 DC_SYNC_INFO("GSL: enabling trigger-reset\n"); 2341 2342 for (i = 1; i < group_size; i++) 2343 grouped_pipes[i]->stream_res.tg->funcs->enable_crtc_reset( 2344 grouped_pipes[i]->stream_res.tg, 2345 gsl_params.gsl_master, 2346 &grouped_pipes[i]->stream->triggered_crtc_reset); 2347 2348 DC_SYNC_INFO("GSL: waiting for reset to occur.\n"); 2349 for (i = 1; i < group_size; i++) 2350 wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->stream_res.tg); 2351 2352 for (i = 0; i < group_size; i++) 2353 grouped_pipes[i]->stream_res.tg->funcs->tear_down_global_swap_lock(grouped_pipes[i]->stream_res.tg); 2354 2355 } 2356 2357 static void init_hw(struct dc *dc) 2358 { 2359 int i; 2360 struct dc_bios *bp; 2361 struct transform *xfm; 2362 struct abm *abm; 2363 2364 bp = dc->ctx->dc_bios; 2365 for (i = 0; i < dc->res_pool->pipe_count; i++) { 2366 xfm = dc->res_pool->transforms[i]; 2367 xfm->funcs->transform_reset(xfm); 2368 2369 dc->hwss.enable_display_power_gating( 2370 dc, i, bp, 2371 PIPE_GATING_CONTROL_INIT); 2372 dc->hwss.enable_display_power_gating( 2373 dc, i, bp, 2374 PIPE_GATING_CONTROL_DISABLE); 2375 dc->hwss.enable_display_pipe_clock_gating( 2376 dc->ctx, 2377 true); 2378 } 2379 2380 dce_clock_gating_power_up(dc->hwseq, false); 2381 /***************************************/ 2382 2383 for (i = 0; i < dc->link_count; i++) { 2384 /****************************************/ 2385 /* Power up AND update implementation according to the 2386 * required signal (which may be different from the 2387 * default signal on connector). */ 2388 struct dc_link *link = dc->links[i]; 2389 2390 if (link->link_enc->connector.id == CONNECTOR_ID_EDP) 2391 dc->hwss.edp_power_control(link, true); 2392 2393 link->link_enc->funcs->hw_init(link->link_enc); 2394 } 2395 2396 for (i = 0; i < dc->res_pool->pipe_count; i++) { 2397 struct timing_generator *tg = dc->res_pool->timing_generators[i]; 2398 2399 tg->funcs->disable_vga(tg); 2400 2401 /* Blank controller using driver code instead of 2402 * command table. */ 2403 tg->funcs->set_blank(tg, true); 2404 hwss_wait_for_blank_complete(tg); 2405 } 2406 2407 for (i = 0; i < dc->res_pool->audio_count; i++) { 2408 struct audio *audio = dc->res_pool->audios[i]; 2409 audio->funcs->hw_init(audio); 2410 } 2411 2412 abm = dc->res_pool->abm; 2413 if (abm != NULL) { 2414 abm->funcs->init_backlight(abm); 2415 abm->funcs->abm_init(abm); 2416 } 2417 2418 if (dc->fbc_compressor) 2419 dc->fbc_compressor->funcs->power_up_fbc(dc->fbc_compressor); 2420 2421 } 2422 2423 void dce110_fill_display_configs( 2424 const struct dc_state *context, 2425 struct dm_pp_display_configuration *pp_display_cfg) 2426 { 2427 int j; 2428 int num_cfgs = 0; 2429 2430 for (j = 0; j < context->stream_count; j++) { 2431 int k; 2432 2433 const struct dc_stream_state *stream = context->streams[j]; 2434 struct dm_pp_single_disp_config *cfg = 2435 &pp_display_cfg->disp_configs[num_cfgs]; 2436 const struct pipe_ctx *pipe_ctx = NULL; 2437 2438 for (k = 0; k < MAX_PIPES; k++) 2439 if (stream == context->res_ctx.pipe_ctx[k].stream) { 2440 pipe_ctx = &context->res_ctx.pipe_ctx[k]; 2441 break; 2442 } 2443 2444 ASSERT(pipe_ctx != NULL); 2445 2446 /* only notify active stream */ 2447 if (stream->dpms_off) 2448 continue; 2449 2450 num_cfgs++; 2451 cfg->signal = pipe_ctx->stream->signal; 2452 cfg->pipe_idx = pipe_ctx->stream_res.tg->inst; 2453 cfg->src_height = stream->src.height; 2454 cfg->src_width = stream->src.width; 2455 cfg->ddi_channel_mapping = 2456 stream->sink->link->ddi_channel_mapping.raw; 2457 cfg->transmitter = 2458 stream->sink->link->link_enc->transmitter; 2459 cfg->link_settings.lane_count = 2460 stream->sink->link->cur_link_settings.lane_count; 2461 cfg->link_settings.link_rate = 2462 stream->sink->link->cur_link_settings.link_rate; 2463 cfg->link_settings.link_spread = 2464 stream->sink->link->cur_link_settings.link_spread; 2465 cfg->sym_clock = stream->phy_pix_clk; 2466 /* Round v_refresh*/ 2467 cfg->v_refresh = stream->timing.pix_clk_khz * 1000; 2468 cfg->v_refresh /= stream->timing.h_total; 2469 cfg->v_refresh = (cfg->v_refresh + stream->timing.v_total / 2) 2470 / stream->timing.v_total; 2471 } 2472 2473 pp_display_cfg->display_count = num_cfgs; 2474 } 2475 2476 uint32_t dce110_get_min_vblank_time_us(const struct dc_state *context) 2477 { 2478 uint8_t j; 2479 uint32_t min_vertical_blank_time = -1; 2480 2481 for (j = 0; j < context->stream_count; j++) { 2482 struct dc_stream_state *stream = context->streams[j]; 2483 uint32_t vertical_blank_in_pixels = 0; 2484 uint32_t vertical_blank_time = 0; 2485 2486 vertical_blank_in_pixels = stream->timing.h_total * 2487 (stream->timing.v_total 2488 - stream->timing.v_addressable); 2489 2490 vertical_blank_time = vertical_blank_in_pixels 2491 * 1000 / stream->timing.pix_clk_khz; 2492 2493 if (min_vertical_blank_time > vertical_blank_time) 2494 min_vertical_blank_time = vertical_blank_time; 2495 } 2496 2497 return min_vertical_blank_time; 2498 } 2499 2500 static int determine_sclk_from_bounding_box( 2501 const struct dc *dc, 2502 int required_sclk) 2503 { 2504 int i; 2505 2506 /* 2507 * Some asics do not give us sclk levels, so we just report the actual 2508 * required sclk 2509 */ 2510 if (dc->sclk_lvls.num_levels == 0) 2511 return required_sclk; 2512 2513 for (i = 0; i < dc->sclk_lvls.num_levels; i++) { 2514 if (dc->sclk_lvls.clocks_in_khz[i] >= required_sclk) 2515 return dc->sclk_lvls.clocks_in_khz[i]; 2516 } 2517 /* 2518 * even maximum level could not satisfy requirement, this 2519 * is unexpected at this stage, should have been caught at 2520 * validation time 2521 */ 2522 ASSERT(0); 2523 return dc->sclk_lvls.clocks_in_khz[dc->sclk_lvls.num_levels - 1]; 2524 } 2525 2526 static void pplib_apply_display_requirements( 2527 struct dc *dc, 2528 struct dc_state *context) 2529 { 2530 struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg; 2531 2532 pp_display_cfg->all_displays_in_sync = 2533 context->bw.dce.all_displays_in_sync; 2534 pp_display_cfg->nb_pstate_switch_disable = 2535 context->bw.dce.nbp_state_change_enable == false; 2536 pp_display_cfg->cpu_cc6_disable = 2537 context->bw.dce.cpuc_state_change_enable == false; 2538 pp_display_cfg->cpu_pstate_disable = 2539 context->bw.dce.cpup_state_change_enable == false; 2540 pp_display_cfg->cpu_pstate_separation_time = 2541 context->bw.dce.blackout_recovery_time_us; 2542 2543 pp_display_cfg->min_memory_clock_khz = context->bw.dce.yclk_khz 2544 / MEMORY_TYPE_MULTIPLIER; 2545 2546 pp_display_cfg->min_engine_clock_khz = determine_sclk_from_bounding_box( 2547 dc, 2548 context->bw.dce.sclk_khz); 2549 2550 pp_display_cfg->min_dcfclock_khz = pp_display_cfg->min_engine_clock_khz; 2551 2552 pp_display_cfg->min_engine_clock_deep_sleep_khz 2553 = context->bw.dce.sclk_deep_sleep_khz; 2554 2555 pp_display_cfg->avail_mclk_switch_time_us = 2556 dce110_get_min_vblank_time_us(context); 2557 /* TODO: dce11.2*/ 2558 pp_display_cfg->avail_mclk_switch_time_in_disp_active_us = 0; 2559 2560 pp_display_cfg->disp_clk_khz = dc->res_pool->dccg->clks.dispclk_khz; 2561 2562 dce110_fill_display_configs(context, pp_display_cfg); 2563 2564 /* TODO: is this still applicable?*/ 2565 if (pp_display_cfg->display_count == 1) { 2566 const struct dc_crtc_timing *timing = 2567 &context->streams[0]->timing; 2568 2569 pp_display_cfg->crtc_index = 2570 pp_display_cfg->disp_configs[0].pipe_idx; 2571 pp_display_cfg->line_time_in_us = timing->h_total * 1000 2572 / timing->pix_clk_khz; 2573 } 2574 2575 if (memcmp(&dc->prev_display_config, pp_display_cfg, sizeof( 2576 struct dm_pp_display_configuration)) != 0) 2577 dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg); 2578 2579 dc->prev_display_config = *pp_display_cfg; 2580 } 2581 2582 static void dce110_set_bandwidth( 2583 struct dc *dc, 2584 struct dc_state *context, 2585 bool decrease_allowed) 2586 { 2587 struct dc_clocks req_clks; 2588 2589 req_clks.dispclk_khz = context->bw.dce.dispclk_khz; 2590 req_clks.phyclk_khz = get_max_pixel_clock_for_all_paths(dc, context); 2591 2592 if (decrease_allowed) 2593 dce110_set_displaymarks(dc, context); 2594 else 2595 dce110_set_safe_displaymarks(&context->res_ctx, dc->res_pool); 2596 2597 dc->res_pool->dccg->funcs->update_clocks( 2598 dc->res_pool->dccg, 2599 &req_clks, 2600 decrease_allowed); 2601 pplib_apply_display_requirements(dc, context); 2602 } 2603 2604 static void dce110_program_front_end_for_pipe( 2605 struct dc *dc, struct pipe_ctx *pipe_ctx) 2606 { 2607 struct mem_input *mi = pipe_ctx->plane_res.mi; 2608 struct pipe_ctx *old_pipe = NULL; 2609 struct dc_plane_state *plane_state = pipe_ctx->plane_state; 2610 struct xfm_grph_csc_adjustment adjust; 2611 struct out_csc_color_matrix tbl_entry; 2612 unsigned int underlay_idx = dc->res_pool->underlay_pipe_index; 2613 unsigned int i; 2614 DC_LOGGER_INIT(); 2615 memset(&tbl_entry, 0, sizeof(tbl_entry)); 2616 2617 if (dc->current_state) 2618 old_pipe = &dc->current_state->res_ctx.pipe_ctx[pipe_ctx->pipe_idx]; 2619 2620 memset(&adjust, 0, sizeof(adjust)); 2621 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS; 2622 2623 dce_enable_fe_clock(dc->hwseq, mi->inst, true); 2624 2625 set_default_colors(pipe_ctx); 2626 if (pipe_ctx->stream->csc_color_matrix.enable_adjustment 2627 == true) { 2628 tbl_entry.color_space = 2629 pipe_ctx->stream->output_color_space; 2630 2631 for (i = 0; i < 12; i++) 2632 tbl_entry.regval[i] = 2633 pipe_ctx->stream->csc_color_matrix.matrix[i]; 2634 2635 pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment 2636 (pipe_ctx->plane_res.xfm, &tbl_entry); 2637 } 2638 2639 if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) { 2640 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW; 2641 2642 for (i = 0; i < CSC_TEMPERATURE_MATRIX_SIZE; i++) 2643 adjust.temperature_matrix[i] = 2644 pipe_ctx->stream->gamut_remap_matrix.matrix[i]; 2645 } 2646 2647 pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust); 2648 2649 pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; 2650 2651 program_scaler(dc, pipe_ctx); 2652 2653 /* fbc not applicable on Underlay pipe */ 2654 if (dc->fbc_compressor && old_pipe->stream && 2655 pipe_ctx->pipe_idx != underlay_idx) { 2656 if (plane_state->tiling_info.gfx8.array_mode == DC_ARRAY_LINEAR_GENERAL) 2657 dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); 2658 else 2659 enable_fbc(dc, dc->current_state); 2660 } 2661 2662 mi->funcs->mem_input_program_surface_config( 2663 mi, 2664 plane_state->format, 2665 &plane_state->tiling_info, 2666 &plane_state->plane_size, 2667 plane_state->rotation, 2668 NULL, 2669 false); 2670 if (mi->funcs->set_blank) 2671 mi->funcs->set_blank(mi, pipe_ctx->plane_state->visible); 2672 2673 if (dc->config.gpu_vm_support) 2674 mi->funcs->mem_input_program_pte_vm( 2675 pipe_ctx->plane_res.mi, 2676 plane_state->format, 2677 &plane_state->tiling_info, 2678 plane_state->rotation); 2679 2680 /* Moved programming gamma from dc to hwss */ 2681 if (pipe_ctx->plane_state->update_flags.bits.full_update || 2682 pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change || 2683 pipe_ctx->plane_state->update_flags.bits.gamma_change) 2684 dc->hwss.set_input_transfer_func(pipe_ctx, pipe_ctx->plane_state); 2685 2686 if (pipe_ctx->plane_state->update_flags.bits.full_update) 2687 dc->hwss.set_output_transfer_func(pipe_ctx, pipe_ctx->stream); 2688 2689 DC_LOG_SURFACE( 2690 "Pipe:%d %p: addr hi:0x%x, " 2691 "addr low:0x%x, " 2692 "src: %d, %d, %d," 2693 " %d; dst: %d, %d, %d, %d;" 2694 "clip: %d, %d, %d, %d\n", 2695 pipe_ctx->pipe_idx, 2696 (void *) pipe_ctx->plane_state, 2697 pipe_ctx->plane_state->address.grph.addr.high_part, 2698 pipe_ctx->plane_state->address.grph.addr.low_part, 2699 pipe_ctx->plane_state->src_rect.x, 2700 pipe_ctx->plane_state->src_rect.y, 2701 pipe_ctx->plane_state->src_rect.width, 2702 pipe_ctx->plane_state->src_rect.height, 2703 pipe_ctx->plane_state->dst_rect.x, 2704 pipe_ctx->plane_state->dst_rect.y, 2705 pipe_ctx->plane_state->dst_rect.width, 2706 pipe_ctx->plane_state->dst_rect.height, 2707 pipe_ctx->plane_state->clip_rect.x, 2708 pipe_ctx->plane_state->clip_rect.y, 2709 pipe_ctx->plane_state->clip_rect.width, 2710 pipe_ctx->plane_state->clip_rect.height); 2711 2712 DC_LOG_SURFACE( 2713 "Pipe %d: width, height, x, y\n" 2714 "viewport:%d, %d, %d, %d\n" 2715 "recout: %d, %d, %d, %d\n", 2716 pipe_ctx->pipe_idx, 2717 pipe_ctx->plane_res.scl_data.viewport.width, 2718 pipe_ctx->plane_res.scl_data.viewport.height, 2719 pipe_ctx->plane_res.scl_data.viewport.x, 2720 pipe_ctx->plane_res.scl_data.viewport.y, 2721 pipe_ctx->plane_res.scl_data.recout.width, 2722 pipe_ctx->plane_res.scl_data.recout.height, 2723 pipe_ctx->plane_res.scl_data.recout.x, 2724 pipe_ctx->plane_res.scl_data.recout.y); 2725 } 2726 2727 static void dce110_apply_ctx_for_surface( 2728 struct dc *dc, 2729 const struct dc_stream_state *stream, 2730 int num_planes, 2731 struct dc_state *context) 2732 { 2733 int i; 2734 2735 if (num_planes == 0) 2736 return; 2737 2738 for (i = 0; i < dc->res_pool->pipe_count; i++) { 2739 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 2740 struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; 2741 2742 if (stream == pipe_ctx->stream) { 2743 if (!pipe_ctx->top_pipe && 2744 (pipe_ctx->plane_state || old_pipe_ctx->plane_state)) 2745 dc->hwss.pipe_control_lock(dc, pipe_ctx, true); 2746 } 2747 } 2748 2749 for (i = 0; i < dc->res_pool->pipe_count; i++) { 2750 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 2751 2752 if (pipe_ctx->stream != stream) 2753 continue; 2754 2755 /* Need to allocate mem before program front end for Fiji */ 2756 pipe_ctx->plane_res.mi->funcs->allocate_mem_input( 2757 pipe_ctx->plane_res.mi, 2758 pipe_ctx->stream->timing.h_total, 2759 pipe_ctx->stream->timing.v_total, 2760 pipe_ctx->stream->timing.pix_clk_khz, 2761 context->stream_count); 2762 2763 dce110_program_front_end_for_pipe(dc, pipe_ctx); 2764 2765 dc->hwss.update_plane_addr(dc, pipe_ctx); 2766 2767 program_surface_visibility(dc, pipe_ctx); 2768 2769 } 2770 2771 for (i = 0; i < dc->res_pool->pipe_count; i++) { 2772 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 2773 struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; 2774 2775 if ((stream == pipe_ctx->stream) && 2776 (!pipe_ctx->top_pipe) && 2777 (pipe_ctx->plane_state || old_pipe_ctx->plane_state)) 2778 dc->hwss.pipe_control_lock(dc, pipe_ctx, false); 2779 } 2780 } 2781 2782 static void dce110_power_down_fe(struct dc *dc, struct pipe_ctx *pipe_ctx) 2783 { 2784 int fe_idx = pipe_ctx->plane_res.mi ? 2785 pipe_ctx->plane_res.mi->inst : pipe_ctx->pipe_idx; 2786 2787 /* Do not power down fe when stream is active on dce*/ 2788 if (dc->current_state->res_ctx.pipe_ctx[fe_idx].stream) 2789 return; 2790 2791 dc->hwss.enable_display_power_gating( 2792 dc, fe_idx, dc->ctx->dc_bios, PIPE_GATING_CONTROL_ENABLE); 2793 2794 dc->res_pool->transforms[fe_idx]->funcs->transform_reset( 2795 dc->res_pool->transforms[fe_idx]); 2796 } 2797 2798 static void dce110_wait_for_mpcc_disconnect( 2799 struct dc *dc, 2800 struct resource_pool *res_pool, 2801 struct pipe_ctx *pipe_ctx) 2802 { 2803 /* do nothing*/ 2804 } 2805 2806 static void program_csc_matrix(struct pipe_ctx *pipe_ctx, 2807 enum dc_color_space colorspace, 2808 uint16_t *matrix) 2809 { 2810 int i; 2811 struct out_csc_color_matrix tbl_entry; 2812 2813 if (pipe_ctx->stream->csc_color_matrix.enable_adjustment 2814 == true) { 2815 enum dc_color_space color_space = 2816 pipe_ctx->stream->output_color_space; 2817 2818 //uint16_t matrix[12]; 2819 for (i = 0; i < 12; i++) 2820 tbl_entry.regval[i] = pipe_ctx->stream->csc_color_matrix.matrix[i]; 2821 2822 tbl_entry.color_space = color_space; 2823 //tbl_entry.regval = matrix; 2824 pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment(pipe_ctx->plane_res.xfm, &tbl_entry); 2825 } 2826 } 2827 2828 static 2829 void dce110_set_cursor_position(struct pipe_ctx *pipe_ctx) 2830 { 2831 struct dc_cursor_position pos_cpy = pipe_ctx->stream->cursor_position; 2832 struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp; 2833 struct mem_input *mi = pipe_ctx->plane_res.mi; 2834 struct dc_cursor_mi_param param = { 2835 .pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_khz, 2836 .ref_clk_khz = pipe_ctx->stream->ctx->dc->res_pool->ref_clock_inKhz, 2837 .viewport = pipe_ctx->plane_res.scl_data.viewport, 2838 .h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz, 2839 .v_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.vert, 2840 .rotation = pipe_ctx->plane_state->rotation, 2841 .mirror = pipe_ctx->plane_state->horizontal_mirror 2842 }; 2843 2844 if (pipe_ctx->plane_state->address.type 2845 == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE) 2846 pos_cpy.enable = false; 2847 2848 if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state) 2849 pos_cpy.enable = false; 2850 2851 if (ipp->funcs->ipp_cursor_set_position) 2852 ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, ¶m); 2853 if (mi->funcs->set_cursor_position) 2854 mi->funcs->set_cursor_position(mi, &pos_cpy, ¶m); 2855 } 2856 2857 static 2858 void dce110_set_cursor_attribute(struct pipe_ctx *pipe_ctx) 2859 { 2860 struct dc_cursor_attributes *attributes = &pipe_ctx->stream->cursor_attributes; 2861 2862 if (pipe_ctx->plane_res.ipp && 2863 pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes) 2864 pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes( 2865 pipe_ctx->plane_res.ipp, attributes); 2866 2867 if (pipe_ctx->plane_res.mi && 2868 pipe_ctx->plane_res.mi->funcs->set_cursor_attributes) 2869 pipe_ctx->plane_res.mi->funcs->set_cursor_attributes( 2870 pipe_ctx->plane_res.mi, attributes); 2871 2872 if (pipe_ctx->plane_res.xfm && 2873 pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes) 2874 pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes( 2875 pipe_ctx->plane_res.xfm, attributes); 2876 } 2877 2878 static void ready_shared_resources(struct dc *dc, struct dc_state *context) {} 2879 2880 static void optimize_shared_resources(struct dc *dc) {} 2881 2882 static const struct hw_sequencer_funcs dce110_funcs = { 2883 .program_gamut_remap = program_gamut_remap, 2884 .program_csc_matrix = program_csc_matrix, 2885 .init_hw = init_hw, 2886 .apply_ctx_to_hw = dce110_apply_ctx_to_hw, 2887 .apply_ctx_for_surface = dce110_apply_ctx_for_surface, 2888 .update_plane_addr = update_plane_addr, 2889 .update_pending_status = dce110_update_pending_status, 2890 .set_input_transfer_func = dce110_set_input_transfer_func, 2891 .set_output_transfer_func = dce110_set_output_transfer_func, 2892 .power_down = dce110_power_down, 2893 .enable_accelerated_mode = dce110_enable_accelerated_mode, 2894 .enable_timing_synchronization = dce110_enable_timing_synchronization, 2895 .enable_per_frame_crtc_position_reset = dce110_enable_per_frame_crtc_position_reset, 2896 .update_info_frame = dce110_update_info_frame, 2897 .enable_stream = dce110_enable_stream, 2898 .disable_stream = dce110_disable_stream, 2899 .unblank_stream = dce110_unblank_stream, 2900 .blank_stream = dce110_blank_stream, 2901 .enable_audio_stream = dce110_enable_audio_stream, 2902 .disable_audio_stream = dce110_disable_audio_stream, 2903 .enable_display_pipe_clock_gating = enable_display_pipe_clock_gating, 2904 .enable_display_power_gating = dce110_enable_display_power_gating, 2905 .disable_plane = dce110_power_down_fe, 2906 .pipe_control_lock = dce_pipe_control_lock, 2907 .set_bandwidth = dce110_set_bandwidth, 2908 .set_drr = set_drr, 2909 .get_position = get_position, 2910 .set_static_screen_control = set_static_screen_control, 2911 .reset_hw_ctx_wrap = dce110_reset_hw_ctx_wrap, 2912 .enable_stream_timing = dce110_enable_stream_timing, 2913 .setup_stereo = NULL, 2914 .set_avmute = dce110_set_avmute, 2915 .wait_for_mpcc_disconnect = dce110_wait_for_mpcc_disconnect, 2916 .ready_shared_resources = ready_shared_resources, 2917 .optimize_shared_resources = optimize_shared_resources, 2918 .pplib_apply_display_requirements = pplib_apply_display_requirements, 2919 .edp_backlight_control = hwss_edp_backlight_control, 2920 .edp_power_control = hwss_edp_power_control, 2921 .edp_wait_for_hpd_ready = hwss_edp_wait_for_hpd_ready, 2922 .set_cursor_position = dce110_set_cursor_position, 2923 .set_cursor_attribute = dce110_set_cursor_attribute 2924 }; 2925 2926 void dce110_hw_sequencer_construct(struct dc *dc) 2927 { 2928 dc->hwss = dce110_funcs; 2929 } 2930 2931