1 // SPDX-License-Identifier: MIT 2 // 3 // Copyright 2026 Advanced Micro Devices, Inc. 4 5 #include "dm_services.h" 6 #include "dc.h" 7 #include "mod_power.h" 8 #include "core_types.h" 9 #include "dmcu.h" 10 #include "abm.h" 11 #include "power_helpers.h" 12 #include "dce/dmub_psr.h" 13 #include "dal_asic_id.h" 14 #include "link_service.h" 15 #include <linux/math.h> 16 17 #define DC_TRACE_LEVEL_MESSAGE(...) /* do nothing */ 18 #define DC_TRACE_LEVEL_MESSAGEP(...) /* do nothing */ 19 #include "dc/inc/hw/dmcu.h" 20 #include "dc/inc/hw/abm.h" 21 #include "dmub_cmd.h" 22 23 #define MOD_POWER_TO_CORE(mod_power)\ 24 container_of(mod_power, struct core_power, mod_public) 25 26 static unsigned int calc_psr_num_static_frames(unsigned int vsync_rate_hz) 27 { 28 /* Initialize fail-safe to 2 static frames. */ 29 unsigned int num_frames_static = 2; 30 31 /* Calculate number of frames such that at least 30 ms has passed. 32 * Round up to ensure the static period is not shorter than 30 ms. 33 */ 34 if (vsync_rate_hz != 0) 35 num_frames_static = DIV_ROUND_UP(30000 * vsync_rate_hz, 1000000); 36 37 return num_frames_static; 38 } 39 40 bool mod_power_psr_notify_mode_change(struct mod_power *mod_power, 41 const struct dc_stream_state *stream, 42 struct dc_link *link, 43 unsigned int stream_index) 44 { 45 struct core_power *core_power = NULL; 46 struct dc *dc = NULL; 47 struct psr_config psr_config = {0}; 48 struct psr_context psr_context = {0}; 49 int active_psr_events = 0; 50 51 if ((mod_power == NULL) || (stream == NULL) || (link == NULL)) 52 return false; 53 54 core_power = MOD_POWER_TO_CORE(mod_power); 55 dc = core_power->dc; 56 57 // NO num_entities check here - already validated by caller 58 // stream_index is passed as validated parameter 59 active_psr_events = core_power->map[stream_index].psr_events; 60 61 /* Calculate PSR configurations */ 62 mod_power_calc_psr_configs(&psr_config, link, stream); 63 64 psr_config.psr_exit_link_training_required = 65 core_power->map[stream_index].caps->psr_exit_link_training_required; 66 if (dc->ctx->asic_id.chip_family >= AMDGPU_FAMILY_GC_11_0_1) 67 psr_config.allow_smu_optimizations = 68 core_power->psr_smu_optimizations_support && dc_is_embedded_signal(stream->signal); 69 else 70 psr_config.allow_smu_optimizations = 71 core_power->psr_smu_optimizations_support && 72 mod_power_only_edp(dc->current_state, stream); 73 74 psr_config.allow_multi_disp_optimizations = core_power->multi_disp_optimizations_support; 75 76 psr_config.rate_control_caps = core_power->map[stream_index].caps->rate_control_caps; 77 78 if (active_psr_events & psr_event_os_request_force_ffu) 79 psr_config.os_request_force_ffu = true; 80 81 /* 82 * DSC support: 83 * DSC slice height value must be 'mod' by su_y_granularity. 84 * According to Panel Vendor, there might be varied conditions to fulfill. 85 * Right now, DSC slice height value must be multiple of su_y_granularity. 86 * 87 * The value of DSC slice height is determined in DSC Driver but it does not 88 * propagated out here, so we need to calculate it as below 'slice_height'. 89 */ 90 psr_su_set_dsc_slice_height(dc, link, 91 (struct dc_stream_state *) stream, 92 &psr_config); 93 94 dc_link_setup_psr(link, stream, &psr_config, &psr_context); 95 96 return true; 97 } 98 99 static void mod_power_psr_set_power_opt(struct mod_power *mod_power, 100 struct dc_stream_state *stream, 101 unsigned int active_psr_events, 102 bool psr_enable_request) 103 { 104 (void)psr_enable_request; 105 struct core_power *core_power = NULL; 106 struct dc_link *link = NULL; 107 unsigned int stream_index = 0; 108 unsigned int power_opt = 0; 109 110 if (!stream) 111 return; 112 113 core_power = MOD_POWER_TO_CORE(mod_power); 114 stream_index = map_index_from_stream(core_power, stream); 115 if (!core_power->map[stream_index].caps->psr_version) 116 return; 117 118 link = dc_stream_get_link(stream); 119 120 if (active_psr_events == 0) { 121 /* Static Screen */ 122 power_opt |= (psr_power_opt_smu_opt_static_screen | psr_power_opt_z10_static_screen | 123 psr_power_opt_ds_disable_allow); 124 } 125 126 /* psr_power_opt_flag is a configuration parameter into the module that determines 127 * which optimizations to enable during psr 128 */ 129 power_opt &= core_power->map[stream_index].caps->psr_power_opt_flag; 130 if (core_power->map[stream_index].psr_power_opt != power_opt) { 131 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_VERBOSE, 132 WPP_BIT_FLAG_Firmware_PsrState, 133 "mod_power set_power_opt: psr_power_opt=0x%04x, power_opt=0x%04x active_psr_events=0x%04x, psr_power_opt_flag=0x%04x", 134 core_power->map[stream_index].psr_power_opt, 135 power_opt, 136 active_psr_events, 137 core_power->map[stream_index].caps->psr_power_opt_flag); 138 dc_link_set_psr_allow_active(link, NULL, false, false, &power_opt); 139 core_power->map[stream_index].psr_power_opt = power_opt; 140 } 141 } 142 143 static bool set_psr_enable(struct mod_power *mod_power, 144 struct dc_stream_state *stream, 145 bool psr_enable, 146 bool wait, 147 bool force_static) 148 { 149 struct core_power *core_power = NULL; 150 enum dc_psr_state state = PSR_STATE0; 151 unsigned int retry_count; 152 const unsigned int max_retry = 1000; 153 struct dc_link *link = NULL; 154 155 if (mod_power == NULL) 156 return false; 157 158 core_power = MOD_POWER_TO_CORE(mod_power); 159 160 if (core_power->num_entities == 0) { 161 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR, 162 WPP_BIT_FLAG_Firmware_PsrState, 163 "set psr enable: ERROR: stream=%p num_entities=%u", 164 stream, 165 core_power->num_entities); 166 return false; 167 } 168 169 if (psr_enable) { 170 unsigned int vsync_rate_hz; 171 struct dc_static_screen_params params = {0}; 172 173 vsync_rate_hz = (unsigned int)div_u64(div_u64(( 174 stream->timing.pix_clk_100hz * 100), 175 stream->timing.v_total), 176 stream->timing.h_total); 177 178 params.triggers.cursor_update = true; 179 params.triggers.overlay_update = true; 180 params.triggers.surface_update = true; 181 params.num_frames = calc_psr_num_static_frames(vsync_rate_hz); 182 183 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, 184 WPP_BIT_FLAG_Firmware_PsrState, 185 "set psr enable: CALCS: pix_clk_100hz=%u v_total=%u h_total=%u vsync_rate_hz=%u num_frames=%u", 186 stream->timing.pix_clk_100hz, 187 stream->timing.v_total, 188 stream->timing.h_total, 189 vsync_rate_hz, 190 params.num_frames); 191 192 dc_stream_set_static_screen_params(core_power->dc, 193 &stream, 1, 194 ¶ms); 195 } 196 197 link = dc_stream_get_link(stream); 198 199 if (!dc_link_set_psr_allow_active(link, &psr_enable, false, force_static, NULL)) { 200 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR, 201 WPP_BIT_FLAG_Firmware_PsrState, 202 "set psr enable: ERROR: stream=%p link=%p psr_enable=%d", 203 stream, 204 link, 205 psr_enable); 206 return false; 207 } 208 209 if (wait == true) { 210 211 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, 212 WPP_BIT_FLAG_Firmware_PsrState, 213 "set psr enable: BEGIN WAIT: psr_enable=%d", 214 (int)psr_enable); 215 216 for (retry_count = 0; retry_count <= max_retry; retry_count++) { 217 dc_link_get_psr_state(link, &state); 218 if (psr_enable) { 219 if (state != PSR_STATE0 && 220 (!force_static || state == PSR_STATE3)) 221 break; 222 } else { 223 if (state == PSR_STATE0) 224 break; 225 } 226 udelay(500); 227 } 228 229 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, 230 WPP_BIT_FLAG_Firmware_PsrState, 231 "set psr enable: END WAIT: psr_enable=%d", 232 (int)psr_enable); 233 234 /* assert if max retry hit */ 235 if (retry_count >= max_retry) { 236 ASSERT(0); 237 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR, 238 WPP_BIT_FLAG_Firmware_PsrState, 239 "set psr enable: ERROR: retry_count=%u: Unexpectedly long wait for PSR state change.", 240 retry_count); 241 } 242 } else { 243 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, 244 WPP_BIT_FLAG_Firmware_PsrState, 245 "set psr enable: PSR state change initiated (wait=false): psr_enable=%d", 246 (int)psr_enable); 247 } 248 249 return true; 250 } 251 252 bool mod_power_get_psr_event(struct mod_power *mod_power, 253 struct dc_stream_state *stream, 254 unsigned int *active_psr_events) 255 { 256 struct core_power *core_power = NULL; 257 unsigned int stream_index = 0; 258 259 if (mod_power == NULL) 260 return false; 261 262 core_power = MOD_POWER_TO_CORE(mod_power); 263 264 if (core_power->num_entities == 0) 265 return false; 266 267 stream_index = map_index_from_stream(core_power, stream); 268 269 if (!core_power->map[stream_index].caps->psr_version) 270 return false; 271 272 *active_psr_events = core_power->map[stream_index].psr_events; 273 274 return true; 275 } 276 277 bool mod_power_set_psr_event(struct mod_power *mod_power, 278 struct dc_stream_state *stream, bool set_event, 279 enum psr_event event, bool wait) 280 { 281 struct core_power *core_power = NULL; 282 unsigned int stream_index = 0; 283 unsigned int active_psr_events = 0; 284 bool psr_enable_request = false; 285 bool force_static = false; 286 287 if (mod_power == NULL || stream == NULL) 288 return false; 289 290 core_power = MOD_POWER_TO_CORE(mod_power); 291 stream_index = map_index_from_stream(core_power, stream); 292 293 if (core_power->num_entities == 0) { 294 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR, 295 WPP_BIT_FLAG_Firmware_PsrState, 296 "mod_power set_psr_event: ERROR: stream=%p event=%d num_entities=%u", 297 stream, 298 (int)event, 299 core_power->num_entities); 300 return false; 301 } 302 303 if (!core_power->map[stream_index].caps->psr_version) 304 return false; 305 306 if (set_event) 307 core_power->map[stream_index].psr_events |= event; 308 else 309 core_power->map[stream_index].psr_events &= ~event; 310 311 active_psr_events = core_power->map[stream_index].psr_events; 312 313 // ignore other events when we're in forced psr enabled state 314 if (active_psr_events & psr_event_dynamic_display_switch && 315 event != psr_event_dynamic_display_switch) 316 return false; 317 318 // ignore other events when we're in forced psr enabled state 319 if (active_psr_events & psr_event_os_override_hold && 320 event != psr_event_os_override_hold) 321 return false; 322 323 // ignore other events when we're in forced psr enabled state 324 // dds events need to be processed while in dynamic_link_rate_control 325 if (active_psr_events & psr_event_dynamic_link_rate_control && 326 event != psr_event_dynamic_link_rate_control && 327 event != psr_event_dds_defer_stream_enable && 328 event != psr_event_dynamic_display_switch) 329 return false; 330 331 if (active_psr_events & (psr_event_test_harness_disable_psr | psr_event_os_request_disable)) 332 psr_enable_request = false; 333 else if (active_psr_events & psr_event_pause) 334 psr_enable_request = false; 335 else if (active_psr_events & psr_event_test_harness_enable_psr) 336 psr_enable_request = true; 337 else if (active_psr_events & psr_event_dynamic_display_switch) { 338 psr_enable_request = true; 339 force_static = true; 340 } else if (active_psr_events & psr_event_dynamic_link_rate_control) { 341 psr_enable_request = true; 342 force_static = true; 343 } else if (active_psr_events & psr_event_edp_panel_off_disable_psr) 344 psr_enable_request = false; 345 else if (active_psr_events & (psr_event_hw_programming | 346 psr_event_defer_enable | 347 psr_event_dds_defer_stream_enable | 348 psr_event_vrr_transition | 349 psr_event_immediate_flip)) 350 psr_enable_request = false; 351 else if (active_psr_events & psr_event_big_screen_video) 352 psr_enable_request = true; 353 else if (active_psr_events & psr_event_full_screen) 354 psr_enable_request = false; 355 else if (active_psr_events & psr_event_mpo_video_selective_update) 356 psr_enable_request = true; 357 else if (active_psr_events & psr_event_vsync) 358 psr_enable_request = false; 359 else if (active_psr_events & psr_event_crc_window_active) 360 psr_enable_request = false; 361 else 362 psr_enable_request = true; 363 364 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_VERBOSE, 365 WPP_BIT_FLAG_Firmware_PsrState, 366 "mod_power set_psr_event: before: psr_enabled=%d -> request: set_event=%d event=0x%04x -> result: psr_events=0x%04x psr_enable_request=%d", 367 (int)core_power->map[stream_index].psr_enabled, 368 (int)set_event, 369 (unsigned int)event, 370 (unsigned int)core_power->map[stream_index].psr_events, 371 (int)psr_enable_request); 372 mod_power_psr_set_power_opt(mod_power, stream, active_psr_events, psr_enable_request); 373 374 if (core_power->map[stream_index].psr_enabled != psr_enable_request || force_static) { 375 if (set_psr_enable(mod_power, stream, psr_enable_request, wait, force_static)) 376 core_power->map[stream_index].psr_enabled = psr_enable_request; 377 } 378 379 return true; 380 } 381 382 bool mod_power_get_psr_state(struct mod_power *mod_power, 383 const struct dc_stream_state *stream, 384 enum dc_psr_state *state) 385 { 386 struct core_power *core_power = NULL; 387 const struct dc_link *link = NULL; 388 389 if (!stream) 390 return false; 391 392 if (mod_power == NULL) 393 return false; 394 395 core_power = MOD_POWER_TO_CORE(mod_power); 396 397 if (core_power->num_entities == 0) 398 return false; 399 400 link = dc_stream_get_link(stream); 401 return dc_link_get_psr_state(link, state); 402 } 403 404 bool mod_power_get_psr_enabled_status(struct mod_power *mod_power, 405 const struct dc_stream_state *stream, 406 bool *psr_enabled) 407 { 408 struct core_power *core_power = NULL; 409 unsigned int stream_index = 0; 410 411 if (mod_power == NULL) 412 return false; 413 414 core_power = MOD_POWER_TO_CORE(mod_power); 415 416 if (core_power->num_entities == 0) 417 return false; 418 419 stream_index = map_index_from_stream(core_power, stream); 420 421 if (!core_power->map[stream_index].caps->psr_version) 422 return false; 423 424 *psr_enabled = core_power->map[stream_index].psr_enabled; 425 426 return true; 427 } 428 429 void mod_power_psr_residency(struct mod_power *mod_power, 430 const struct dc_stream_state *stream, 431 unsigned int *residency, 432 const uint8_t mode) 433 { 434 struct core_power *core_power = NULL; 435 const struct dc_link *link = NULL; 436 437 if (!stream) 438 return; 439 440 if (mod_power == NULL) 441 return; 442 443 core_power = MOD_POWER_TO_CORE(mod_power); 444 445 if (core_power->num_entities == 0) 446 return; 447 448 link = dc_stream_get_link(stream); 449 450 if (link != NULL) 451 link->dc->link_srv->edp_get_psr_residency(link, residency, mode); 452 } 453 bool mod_power_psr_get_active_psr_events(struct mod_power *mod_power, 454 const struct dc_stream_state *stream, unsigned int *active_psr_events) 455 { 456 struct core_power *core_power = NULL; 457 unsigned int stream_index = 0; 458 459 if (!stream) 460 return false; 461 462 if (mod_power == NULL) 463 return false; 464 465 if (active_psr_events == NULL) 466 return false; 467 468 core_power = MOD_POWER_TO_CORE(mod_power); 469 470 if (core_power->num_entities == 0) 471 return false; 472 473 stream_index = map_index_from_stream(core_power, stream); 474 475 *active_psr_events = core_power->map[stream_index].psr_events; 476 return true; 477 } 478 479 bool mod_power_psr_set_sink_vtotal_in_psr_active(struct mod_power *mod_power, 480 const struct dc_stream_state *stream, 481 uint16_t psr_vtotal_idle, 482 uint16_t psr_vtotal_su) 483 { 484 struct core_power *core_power = NULL; 485 unsigned int stream_index = 0; 486 const struct dc_link *link = NULL; 487 488 if (!stream) 489 return false; 490 491 if (mod_power == NULL) 492 return false; 493 494 core_power = MOD_POWER_TO_CORE(mod_power); 495 496 if (core_power->num_entities == 0) 497 return false; 498 499 stream_index = map_index_from_stream(core_power, stream); 500 501 if (!core_power->map[stream_index].caps->psr_version) 502 return false; 503 504 link = dc_stream_get_link(stream); 505 506 return link->dc->link_srv->edp_set_sink_vtotal_in_psr_active( 507 link, psr_vtotal_idle, psr_vtotal_su); 508 } 509 /* 510 * is_psr_su_specific_panel() - check if sink is AMD vendor-specific PSR-SU 511 * supported eDP device. 512 * 513 * @link: dc link pointer 514 * 515 * Return: true if AMDGPU vendor specific PSR-SU eDP panel 516 */ 517 bool is_psr_su_specific_panel(struct dc_link *link) 518 { 519 bool isPSRSUSupported = false; 520 struct dpcd_caps *dpcd_caps = &link->dpcd_caps; 521 522 if (dpcd_caps->edp_rev >= DP_EDP_14) { 523 if (dpcd_caps->psr_info.psr_version >= DP_PSR2_WITH_Y_COORD_ET_SUPPORTED) 524 isPSRSUSupported = true; 525 /* 526 * Some panels will report PSR capabilities over additional DPCD bits. 527 * Such panels are approved despite reporting only PSR v3, as long as 528 * the additional bits are reported. 529 */ 530 if (dpcd_caps->sink_dev_id == DP_BRANCH_DEVICE_ID_001CF8) { 531 /* 532 * This is the temporary workaround to disable PSRSU when system turned on 533 * DSC function on the sepcific sink. 534 */ 535 if (dpcd_caps->psr_info.psr_version < DP_PSR2_WITH_Y_COORD_IS_SUPPORTED) 536 isPSRSUSupported = false; 537 else if (dpcd_caps->dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_SUPPORT && 538 ((dpcd_caps->sink_dev_id_str[1] == 0x08 && dpcd_caps->sink_dev_id_str[0] == 0x08) || 539 (dpcd_caps->sink_dev_id_str[1] == 0x08 && dpcd_caps->sink_dev_id_str[0] == 0x07))) 540 isPSRSUSupported = false; 541 else if (dpcd_caps->sink_dev_id_str[1] == 0x08 && dpcd_caps->sink_dev_id_str[0] == 0x03) 542 isPSRSUSupported = false; 543 else if (dpcd_caps->sink_dev_id_str[1] == 0x08 && dpcd_caps->sink_dev_id_str[0] == 0x01) 544 isPSRSUSupported = false; 545 else if (dpcd_caps->psr_info.force_psrsu_cap == 0x1) 546 isPSRSUSupported = true; 547 } 548 } 549 550 return isPSRSUSupported; 551 } 552 553 /** 554 * mod_power_calc_psr_configs() - calculate/update generic psr configuration fields. 555 * @psr_config: [output], psr configuration structure to be updated 556 * @link: [input] dc link pointer 557 * @stream: [input] dc stream state pointer 558 * 559 * calculate and update the psr configuration fields that are not DM specific, i.e. such 560 * fields which are based on DPCD caps or timing information. To setup PSR in DMUB FW, 561 * this helper is assumed to be called before the call of the DC helper dc_link_setup_psr(). 562 * 563 * PSR config fields to be updated within the helper: 564 * - psr_rfb_setup_time 565 * - psr_sdp_transmit_line_num_deadline 566 * - line_time_in_us 567 * - su_y_granularity 568 * - su_granularity_required 569 * - psr_frame_capture_indication_req 570 * - psr_exit_link_training_required 571 * 572 * PSR config fields that are DM specific and NOT updated within the helper: 573 * - allow_smu_optimizations 574 * - allow_multi_disp_optimizations 575 */ 576 void mod_power_calc_psr_configs(struct psr_config *psr_config, 577 struct dc_link *link, 578 const struct dc_stream_state *stream) 579 { 580 unsigned int num_vblank_lines = 0; 581 unsigned int vblank_time_in_us = 0; 582 unsigned int sdp_tx_deadline_in_us = 0; 583 unsigned int line_time_in_us = 0; 584 struct dpcd_caps *dpcd_caps = &link->dpcd_caps; 585 const int psr_setup_time_step_in_us = 55; /* refer to eDP spec DPCD 0x071h */ 586 587 /* timing parameters */ 588 num_vblank_lines = stream->timing.v_total - 589 stream->timing.v_addressable - 590 stream->timing.v_border_top - 591 stream->timing.v_border_bottom; 592 593 vblank_time_in_us = (stream->timing.h_total * num_vblank_lines * 1000) / (stream->timing.pix_clk_100hz / 10); 594 595 line_time_in_us = ((stream->timing.h_total * 1000) / (stream->timing.pix_clk_100hz / 10)) + 1; 596 597 /** 598 * psr configuration fields 599 * 600 * as per eDP 1.5 pg. 377 of 459, DPCD 0x071h bits [3:1], psr setup time bits interpreted as below 601 * 000b <--> 330 us (default) 602 * 001b <--> 275 us 603 * 010b <--> 220 us 604 * 011b <--> 165 us 605 * 100b <--> 110 us 606 * 101b <--> 055 us 607 * 110b <--> 000 us 608 */ 609 psr_config->psr_rfb_setup_time = 610 (6 - dpcd_caps->psr_info.psr_dpcd_caps.bits.PSR_SETUP_TIME) * psr_setup_time_step_in_us; 611 612 if (psr_config->psr_rfb_setup_time > vblank_time_in_us) { 613 link->psr_settings.psr_frame_capture_indication_req = true; 614 link->psr_settings.psr_sdp_transmit_line_num_deadline = num_vblank_lines; 615 } else { 616 sdp_tx_deadline_in_us = vblank_time_in_us - psr_config->psr_rfb_setup_time; 617 618 /* Set the last possible line SDP may be transmitted without violating the RFB setup time */ 619 link->psr_settings.psr_frame_capture_indication_req = false; 620 link->psr_settings.psr_sdp_transmit_line_num_deadline = sdp_tx_deadline_in_us / line_time_in_us; 621 } 622 623 psr_config->psr_sdp_transmit_line_num_deadline = link->psr_settings.psr_sdp_transmit_line_num_deadline; 624 psr_config->line_time_in_us = line_time_in_us; 625 psr_config->su_y_granularity = dpcd_caps->psr_info.psr2_su_y_granularity_cap; 626 psr_config->su_granularity_required = dpcd_caps->psr_info.psr_dpcd_caps.bits.SU_GRANULARITY_REQUIRED; 627 psr_config->psr_frame_capture_indication_req = link->psr_settings.psr_frame_capture_indication_req; 628 psr_config->psr_exit_link_training_required = 629 !link->dpcd_caps.psr_info.psr_dpcd_caps.bits.LINK_TRAINING_ON_EXIT_NOT_REQUIRED; 630 } 631 632 bool psr_su_set_dsc_slice_height(struct dc *dc, struct dc_link *link, 633 struct dc_stream_state *stream, 634 struct psr_config *config) 635 { 636 uint32_t pic_height; 637 uint32_t slice_height; 638 639 config->dsc_slice_height = 0; 640 if (!(link->connector_signal & SIGNAL_TYPE_EDP) || 641 !dc->caps.edp_dsc_support || 642 link->panel_config.dsc.disable_dsc_edp || 643 !link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_SUPPORT || 644 !stream->timing.dsc_cfg.num_slices_v) 645 return true; 646 647 pic_height = stream->timing.v_addressable + 648 stream->timing.v_border_top + stream->timing.v_border_bottom; 649 650 if (stream->timing.dsc_cfg.num_slices_v == 0) 651 return false; 652 653 slice_height = pic_height / stream->timing.dsc_cfg.num_slices_v; 654 config->dsc_slice_height = (uint16_t)slice_height; 655 656 if (slice_height) { 657 if (config->su_y_granularity && 658 (slice_height % config->su_y_granularity)) { 659 ASSERT(0); 660 return false; 661 } 662 } 663 664 return true; 665 } 666