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