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 "power_helpers.h" 20 #include "dc/inc/hw/dmcu.h" 21 #include "dc/inc/hw/abm.h" 22 #include "dc.h" 23 #include "core_types.h" 24 #include "dmub_cmd.h" 25 26 #define MOD_POWER_TO_CORE(mod_power)\ 27 container_of(mod_power, struct core_power, mod_public) 28 29 #define LOW_REFRESH_RATE_DURATION_US_UPPER_BOUND 25000 30 31 static bool mod_power_set_replay_active(struct dc_stream_state *stream, 32 bool replay_active, 33 bool wait, 34 bool force_static) 35 { 36 uint64_t state; 37 unsigned int retry_count; 38 const unsigned int max_retry = 1000; 39 struct dc_link *link = NULL; 40 41 if (!stream) 42 return false; 43 44 link = dc_stream_get_link(stream); 45 46 if (!link) 47 return false; 48 49 if (!dc_link_set_replay_allow_active(link, &replay_active, false, force_static, NULL)) 50 return false; 51 52 if (wait == true) { 53 54 for (retry_count = 0; retry_count <= max_retry; retry_count++) { 55 dc_link_get_replay_state(link, &state); 56 if (replay_active) { 57 if (state != REPLAY_STATE_0 && 58 (!force_static || state == REPLAY_STATE_3)) 59 break; 60 } else { 61 if (state == REPLAY_STATE_0) 62 break; 63 } 64 udelay(500); 65 } 66 67 /* assert if max retry hit */ 68 if (retry_count >= max_retry) 69 ASSERT(0); 70 } else { 71 /* To-do: Add trace log */ 72 } 73 74 return true; 75 } 76 77 static unsigned int mod_power_replay_setup_power_opt(struct dc_link *link, 78 unsigned int active_replay_events, bool is_ultra_sleep_mode) 79 { 80 unsigned int power_opt = 0; 81 82 if (is_ultra_sleep_mode) { 83 /* Static Screen */ 84 power_opt |= (replay_power_opt_smu_opt_static_screen | replay_power_opt_z10_static_screen); 85 } else if (active_replay_events & replay_event_test_harness_ultra_sleep) { 86 power_opt |= replay_power_opt_z10_static_screen; 87 } 88 89 /* replay_power_opt_flag is a configuration parameter into the module that determines 90 * which optimizations to enable during replay 91 */ 92 power_opt &= link->replay_settings.config.replay_power_opt_supported; 93 94 return power_opt; 95 } 96 97 static bool mod_power_replay_set_power_opt(struct mod_power *mod_power, 98 struct dc_stream_state *stream, 99 unsigned int active_replay_events, 100 bool is_ultra_sleep_mode) 101 { 102 (void)mod_power; 103 struct dc_link *link = NULL; 104 unsigned int power_opt = 0; 105 106 if (!stream) 107 return false; 108 109 link = dc_stream_get_link(stream); 110 111 if (!link || !link->replay_settings.replay_feature_enabled) 112 return false; 113 114 power_opt = mod_power_replay_setup_power_opt(link, active_replay_events, is_ultra_sleep_mode); 115 116 if (!dc_link_set_replay_allow_active(link, NULL, false, false, &power_opt)) 117 return false; 118 119 return true; 120 } 121 122 bool mod_power_get_replay_event(struct mod_power *mod_power, 123 struct dc_stream_state *stream, 124 unsigned int *active_replay_events) 125 { 126 struct core_power *core_power = NULL; 127 unsigned int stream_index = 0; 128 129 if (mod_power == NULL) 130 return false; 131 132 core_power = MOD_POWER_TO_CORE(mod_power); 133 134 if (core_power->num_entities == 0) 135 return false; 136 137 stream_index = map_index_from_stream(core_power, stream); 138 139 *active_replay_events = core_power->map[stream_index].replay_events; 140 141 return true; 142 } 143 144 static bool mod_power_update_replay_active_status(unsigned int active_replay_events, 145 struct dc_link *link, uint32_t *coasting_vtotal, bool *is_full_screen_video, 146 bool *is_ultra_sleep_mode, uint16_t *frame_skip_number, bool *is_video_playback) 147 { 148 if (!link || !coasting_vtotal || !is_full_screen_video || !is_video_playback) 149 return false; 150 151 // Check coasting_vtotal_table has been updated. 152 if (!link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_STATIC] 153 || !link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_NOM]) 154 return false; 155 156 unsigned int replay_enable_option = 157 link->replay_settings.config.replay_enable_option; 158 159 /* TODO: To support test harness and DDS event */ 160 161 *coasting_vtotal = link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_NOM]; 162 ASSERT(link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_NOM] <= 0xFFFF); 163 *frame_skip_number = (uint16_t)link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_NOM]; 164 165 link->replay_settings.config.replay_timing_sync_supported = false; 166 167 *is_full_screen_video = false; 168 169 *is_ultra_sleep_mode = false; 170 171 *is_video_playback = false; 172 173 /* DSAT test scenario */ 174 if (active_replay_events & replay_event_test_harness_mode) { 175 if (link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_TEST_HARNESS]) 176 *coasting_vtotal = 177 link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_TEST_HARNESS]; 178 179 ASSERT(link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS] <= 0xFFFF); 180 *frame_skip_number = 181 (uint16_t)link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS]; 182 183 /* During the ultra sleep mode testing, disable the timing sync in short vblank mode */ 184 if (active_replay_events & (replay_event_test_harness_enable_replay)) { 185 if ((active_replay_events & replay_event_test_harness_ultra_sleep) && 186 !link->replay_settings.config.replay_support_fast_resync_in_ultra_sleep_mode) 187 link->replay_settings.config.replay_timing_sync_supported = false; 188 return true; 189 } else 190 return false; 191 } else if (active_replay_events & (replay_event_test_harness_enable_replay)) { 192 if (link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_TEST_HARNESS]) 193 *coasting_vtotal = link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_TEST_HARNESS]; 194 if (link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS]) { 195 uint32_t frame_skip_val = 196 link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS]; 197 198 ASSERT(frame_skip_val <= 0xFFFF); 199 *frame_skip_number = (uint16_t)frame_skip_val; 200 } 201 202 /* During the ultra sleep mode testing, disable the timing sync in short vblank mode */ 203 if ((active_replay_events & replay_event_test_harness_ultra_sleep) && 204 !link->replay_settings.config.replay_support_fast_resync_in_ultra_sleep_mode) { 205 link->replay_settings.config.replay_timing_sync_supported = false; 206 } 207 return true; 208 } else if (active_replay_events & 209 (replay_event_test_harness_disable_replay | replay_event_os_request_disable)) { 210 // set last set coasting vtotal 211 if (link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_TEST_HARNESS]) 212 *coasting_vtotal = link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_TEST_HARNESS]; 213 if (link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS]) { 214 uint32_t frame_skip_val = 215 link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS]; 216 217 ASSERT(frame_skip_val <= 0xFFFF); 218 *frame_skip_number = (uint16_t)frame_skip_val; 219 } 220 return false; 221 } 222 223 /* Inactive conditions */ 224 if (active_replay_events & (replay_event_edp_panel_off_disable_psr | 225 replay_event_hw_programming | 226 replay_event_vrr | 227 replay_event_immediate_flip | 228 replay_event_prepare_vtotal | 229 replay_event_vrr_transition | 230 replay_event_pause | 231 replay_event_disable_replay_while_DPMS | 232 replay_event_sleep_resume | 233 replay_event_disable_in_AC | 234 replay_event_disable_replay_while_detect_display | 235 replay_event_infopacket | 236 replay_event_crc_window_active)) 237 return false; 238 239 // Full screen scenario 240 if (active_replay_events & replay_event_full_screen) { 241 if (!(replay_enable_option & pr_enable_option_full_screen)) 242 return false; 243 } 244 245 /* Full screen video scenario */ 246 if (active_replay_events & replay_event_big_screen_video) { 247 248 link->replay_settings.config.replay_timing_sync_supported = false; 249 250 if (replay_enable_option & pr_enable_option_full_screen_video_coasting) { 251 unsigned int fsn_vid = 252 link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_FULL_SCREEN_VIDEO]; 253 254 *coasting_vtotal = 255 link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_FULL_SCREEN_VIDEO]; 256 ASSERT(fsn_vid <= 0xFFFF); 257 *frame_skip_number = (uint16_t)fsn_vid; 258 } 259 260 *is_video_playback = true; 261 262 if ((replay_enable_option & pr_enable_option_full_screen_video) && 263 (replay_enable_option & pr_enable_option_full_screen_video_coasting)) { 264 *is_full_screen_video = true; 265 return true; 266 } else 267 return false; 268 } 269 270 /* MPO video scenario 271 * Some of the cases may contain a full screen UI layer in MPO video scenario which is 272 * not the expected case to enable Replay. 273 */ 274 if ((active_replay_events & replay_event_mpo_video_selective_update) && 275 !(active_replay_events & replay_event_full_screen)) { 276 277 link->replay_settings.config.replay_timing_sync_supported = false; 278 279 if (replay_enable_option & pr_enable_option_mpo_video_coasting) { 280 *coasting_vtotal = link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_NOM]; 281 { 282 uint32_t frame_skip_val = 283 link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_NOM]; 284 285 ASSERT(frame_skip_val <= 0xFFFF); 286 *frame_skip_number = (uint16_t)frame_skip_val; 287 } 288 } 289 290 *is_video_playback = true; 291 292 if (replay_enable_option & pr_enable_option_mpo_video) 293 return true; 294 else 295 return false; 296 } 297 298 /* Static screen scenario */ 299 if (!(active_replay_events & replay_event_vsync)) { 300 301 if (replay_enable_option & pr_enable_option_static_screen_coasting) { 302 // Do not adjust eDP refresh rate if static screen + normal sleep mode 303 if ((!(link->replay_settings.config.replay_power_opt_supported & 304 replay_power_opt_z10_static_screen)) || 305 (active_replay_events & replay_event_cursor_updating)) { 306 // normal sleep mode 307 *coasting_vtotal = 308 link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_NOM]; 309 { 310 uint32_t frame_skip_val = 311 link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_NOM]; 312 313 ASSERT(frame_skip_val <= 0xFFFF); 314 *frame_skip_number = (uint16_t)frame_skip_val; 315 } 316 } else { 317 // ultra sleep mode 318 *coasting_vtotal = 319 link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_STATIC]; 320 { 321 uint32_t frame_skip_val = 322 link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_STATIC]; 323 324 ASSERT(frame_skip_val <= 0xFFFF); 325 *frame_skip_number = (uint16_t)frame_skip_val; 326 } 327 *is_ultra_sleep_mode = true; 328 } 329 } 330 331 if (replay_enable_option & pr_enable_option_static_screen) { 332 if (!link->replay_settings.config.replay_support_fast_resync_in_ultra_sleep_mode) 333 link->replay_settings.config.replay_timing_sync_supported = false; 334 return true; 335 } else 336 return false; 337 } 338 339 /* General UI scenario */ 340 if (active_replay_events & replay_event_general_ui) { 341 if (replay_enable_option & pr_enable_option_general_ui) 342 return true; 343 else 344 return false; 345 } 346 347 return false; 348 } 349 350 bool mod_power_replay_set_coasting_vtotal(struct mod_power *mod_power, 351 const struct dc_stream_state *stream, 352 uint32_t coasting_vtotal, 353 uint16_t frame_skip_number) 354 { 355 struct core_power *core_power = NULL; 356 struct dc_link *link = NULL; 357 358 if (!stream) 359 return false; 360 361 link = dc_stream_get_link(stream); 362 if (!link || !link->replay_settings.replay_feature_enabled) 363 return false; 364 365 if (mod_power == NULL) 366 return false; 367 368 core_power = MOD_POWER_TO_CORE(mod_power); 369 370 if (core_power->num_entities == 0) 371 return false; 372 373 return link->dc->link_srv->edp_set_coasting_vtotal(link, coasting_vtotal, frame_skip_number); 374 } 375 376 void mod_power_replay_set_timing_sync_supported(struct mod_power *mod_power, 377 const struct dc_stream_state *stream) 378 { 379 struct core_power *core_power = NULL; 380 struct dc_link *link = NULL; 381 unsigned int stream_index = 0; 382 union dmub_replay_cmd_set cmd_data = { 0 }; 383 384 if (!stream || mod_power == NULL) 385 return; 386 387 core_power = MOD_POWER_TO_CORE(mod_power); 388 if (core_power->num_entities == 0) 389 return; 390 391 stream_index = map_index_from_stream(core_power, stream); 392 if (stream_index > core_power->num_entities) //invalid index 393 return; 394 395 link = dc_stream_get_link(stream); 396 if (!link || !link->replay_settings.replay_feature_enabled) 397 return; 398 399 cmd_data.sync_data.timing_sync_supported = link->replay_settings.config.replay_timing_sync_supported; 400 401 link->dc->link_srv->edp_send_replay_cmd(link, Replay_Set_Timing_Sync_Supported, 402 &cmd_data); 403 } 404 405 void mod_power_replay_disabled_adaptive_sync_sdp(struct mod_power *mod_power, 406 const struct dc_stream_state *stream, bool force_disabled) 407 { 408 struct core_power *core_power = NULL; 409 struct dc_link *link = NULL; 410 unsigned int stream_index = 0; 411 union dmub_replay_cmd_set cmd_data = { 0 }; 412 413 if (!stream || mod_power == NULL) 414 return; 415 416 core_power = MOD_POWER_TO_CORE(mod_power); 417 if (core_power->num_entities == 0) 418 return; 419 420 stream_index = map_index_from_stream(core_power, stream); 421 if (stream_index > core_power->num_entities) //invalid index 422 return; 423 424 link = dc_stream_get_link(stream); 425 if (!link || !link->replay_settings.replay_feature_enabled) 426 return; 427 428 cmd_data.disabled_adaptive_sync_sdp_data.force_disabled = force_disabled; 429 430 link->dc->link_srv->edp_send_replay_cmd(link, Replay_Disabled_Adaptive_Sync_SDP, 431 &cmd_data); 432 } 433 434 static void mod_power_replay_set_general_cmd(struct mod_power *mod_power, 435 const struct dc_stream_state *stream, 436 const enum dmub_cmd_replay_general_subtype general_cmd_type, 437 const uint32_t param1, const uint32_t param2) 438 { 439 struct core_power *core_power = NULL; 440 struct dc_link *link = NULL; 441 unsigned int stream_index = 0; 442 union dmub_replay_cmd_set cmd_data = { 0 }; 443 444 if (!stream || mod_power == NULL) 445 return; 446 447 core_power = MOD_POWER_TO_CORE(mod_power); 448 if (core_power->num_entities == 0) 449 return; 450 451 stream_index = map_index_from_stream(core_power, stream); 452 if (stream_index > core_power->num_entities) //invalid index 453 return; 454 455 link = dc_stream_get_link(stream); 456 if (!link || !link->replay_settings.replay_feature_enabled) 457 return; 458 459 cmd_data.set_general_cmd_data.subtype = general_cmd_type; 460 cmd_data.set_general_cmd_data.param1 = param1; 461 cmd_data.set_general_cmd_data.param2 = param2; 462 link->dc->link_srv->edp_send_replay_cmd(link, Replay_Set_General_Cmd, 463 &cmd_data); 464 } 465 466 void mod_power_replay_disabled_desync_error_detection(struct mod_power *mod_power, 467 const struct dc_stream_state *stream, bool force_disabled) 468 { 469 mod_power_replay_set_general_cmd(mod_power, stream, 470 REPLAY_GENERAL_CMD_DISABLED_DESYNC_ERROR_DETECTION, 471 force_disabled, 0); 472 } 473 474 static void mod_power_replay_set_pseudo_vtotal(struct mod_power *mod_power, 475 const struct dc_stream_state *stream, uint16_t vtotal) 476 { 477 struct core_power *core_power = NULL; 478 struct dc_link *link = NULL; 479 unsigned int stream_index = 0; 480 union dmub_replay_cmd_set cmd_data = { 0 }; 481 482 if (!stream || mod_power == NULL) 483 return; 484 485 core_power = MOD_POWER_TO_CORE(mod_power); 486 if (core_power->num_entities == 0) 487 return; 488 489 stream_index = map_index_from_stream(core_power, stream); 490 if (stream_index > core_power->num_entities) //invalid index 491 return; 492 493 link = dc_stream_get_link(stream); 494 if (!link || !link->replay_settings.replay_feature_enabled) 495 return; 496 497 cmd_data.pseudo_vtotal_data.vtotal = vtotal; 498 499 if (link->replay_settings.last_pseudo_vtotal != vtotal) { 500 link->replay_settings.last_pseudo_vtotal = vtotal; 501 link->dc->link_srv->edp_send_replay_cmd(link, Replay_Set_Pseudo_VTotal, &cmd_data); 502 } 503 } 504 505 static void mod_power_update_error_status(struct mod_power *mod_power, 506 const struct dc_stream_state *stream) 507 { 508 struct dc_link *link = NULL; 509 union replay_debug_flags *pDebug = NULL; 510 511 if (mod_power == NULL || stream == NULL) 512 return; 513 514 link = dc_stream_get_link(stream); 515 516 if (!link) 517 return; 518 519 pDebug = (union replay_debug_flags *)&link->replay_settings.config.debug_flags; 520 521 if (pDebug->bitfields.enable_visual_confirm_debug == 0) 522 return; 523 524 mod_power_replay_set_general_cmd(mod_power, stream, 525 REPLAY_GENERAL_CMD_UPDATE_ERROR_STATUS, 526 link->replay_settings.config.replay_error_status.raw, 0); 527 } 528 529 void mod_power_set_low_rr_activate(struct mod_power *mod_power, 530 const struct dc_stream_state *stream, bool low_rr_supported) 531 { 532 struct dc_link *link = NULL; 533 534 if (mod_power == NULL || stream == NULL) 535 return; 536 537 link = dc_stream_get_link(stream); 538 539 if (!link) 540 return; 541 542 mod_power_replay_set_general_cmd(mod_power, stream, 543 REPLAY_GENERAL_CMD_SET_LOW_RR_ACTIVATE, 544 low_rr_supported, 0); 545 } 546 547 void mod_power_set_video_conferencing_activate(struct mod_power *mod_power, 548 const struct dc_stream_state *stream, bool video_conferencing_activate) 549 { 550 struct dc_link *link = NULL; 551 552 if (mod_power == NULL || stream == NULL) 553 return; 554 555 link = dc_stream_get_link(stream); 556 if (!link || !link->replay_settings.replay_feature_enabled) 557 return; 558 559 mod_power_replay_set_general_cmd(mod_power, stream, 560 REPLAY_GENERAL_CMD_VIDEO_CONFERENCING, 561 video_conferencing_activate, 0); 562 } 563 564 void mod_power_set_coasting_vtotal_without_frame_update(struct mod_power *mod_power, 565 const struct dc_stream_state *stream, uint32_t coasting_vtotal) 566 { 567 struct dc_link *link = NULL; 568 569 if (mod_power == NULL || stream == NULL) 570 return; 571 572 link = dc_stream_get_link(stream); 573 if (!link || !link->replay_settings.replay_feature_enabled) 574 return; 575 576 mod_power_replay_set_general_cmd(mod_power, stream, 577 REPLAY_GENERAL_CMD_SET_COASTING_VTOTAL_WITHOUT_FRAME_UPDATE, 578 coasting_vtotal, 0); 579 } 580 581 void mod_power_set_replay_continuously_resync(struct mod_power *mod_power, 582 const struct dc_stream_state *stream, bool enable) 583 { 584 struct dc_link *link = NULL; 585 586 if (mod_power == NULL || stream == NULL) 587 return; 588 589 link = dc_stream_get_link(stream); 590 if (!link || !link->replay_settings.replay_feature_enabled) 591 return; 592 593 mod_power_replay_set_general_cmd(mod_power, stream, 594 REPLAY_GENERAL_CMD_SET_CONTINUOUSLY_RESYNC, 595 enable, 0); 596 } 597 598 void mod_power_set_live_capture_with_cvt_activate(struct mod_power *mod_power, 599 const struct dc_stream_state *stream, bool live_capture_with_cvt_activate) 600 { 601 struct dc_link *link = NULL; 602 603 if (mod_power == NULL || stream == NULL) 604 return; 605 606 link = dc_stream_get_link(stream); 607 if (!link || !link->replay_settings.replay_feature_enabled) 608 return; 609 610 // Check if LIVE_CAPTURE_WITH_CVT bit is enabled in replay optimization config 611 if (!link->replay_settings.config.replay_optimization.bits.LIVE_CAPTURE_WITH_CVT) 612 return; 613 614 if (link->replay_settings.config.live_capture_with_cvt_activated != live_capture_with_cvt_activate) { 615 link->replay_settings.config.live_capture_with_cvt_activated = live_capture_with_cvt_activate; 616 mod_power_replay_set_general_cmd(mod_power, stream, 617 REPLAY_GENERAL_CMD_LIVE_CAPTURE_WITH_CVT, 618 live_capture_with_cvt_activate, 0); 619 } 620 } 621 622 bool mod_power_set_replay_event(struct mod_power *mod_power, 623 struct dc_stream_state *stream, bool set_event, 624 enum replay_event event, bool wait_for_disable) 625 { 626 struct core_power *core_power = NULL; 627 struct dc_link *link = NULL; 628 unsigned int stream_index = 0; 629 unsigned int active_replay_events = 0; 630 bool replay_active_request = false; 631 bool force_static = false; 632 uint32_t coasting_vtotal = 0; 633 bool current_timing_sync_status = false; 634 bool is_full_screen_video = false; 635 bool is_ultra_sleep_mode = false; 636 unsigned int sink_duration_us = 0; 637 bool low_rr_active = false; 638 uint16_t frame_skip_number = 0; 639 bool is_video_playback = false; 640 641 if (!stream) 642 return false; 643 644 if (mod_power == NULL) 645 return false; 646 647 core_power = MOD_POWER_TO_CORE(mod_power); 648 649 if (core_power->num_entities == 0) 650 return false; 651 652 stream_index = map_index_from_stream(core_power, stream); 653 654 if (set_event) 655 core_power->map[stream_index].replay_events |= event; 656 else 657 core_power->map[stream_index].replay_events &= ~event; 658 659 link = dc_stream_get_link(stream); 660 if (!link || !link->replay_settings.replay_feature_enabled) 661 return false; 662 663 if ((core_power->map[stream_index].replay_events & replay_event_disable_replay_while_switching_mux) != 0) 664 return false; 665 666 if ((core_power->map[stream_index].replay_events & replay_event_os_override_hold) != 0) 667 return false; 668 669 active_replay_events = core_power->map[stream_index].replay_events; 670 671 current_timing_sync_status = 672 link->replay_settings.config.replay_timing_sync_supported; 673 674 replay_active_request = mod_power_update_replay_active_status(active_replay_events, 675 link, &coasting_vtotal, &is_full_screen_video, &is_ultra_sleep_mode, &frame_skip_number, &is_video_playback); 676 677 if (is_full_screen_video) 678 mod_power_replay_set_pseudo_vtotal(mod_power, stream, 679 link->replay_settings.low_rr_full_screen_video_pseudo_vtotal); 680 else 681 mod_power_replay_set_pseudo_vtotal(mod_power, stream, 0); 682 683 //If timing_sync_status change, then re-enabled set timing_sync_supported value and re-enabled replay 684 if (current_timing_sync_status != link->replay_settings.config.replay_timing_sync_supported) 685 mod_power_replay_set_timing_sync_supported(mod_power, stream); 686 687 if (link->replay_settings.config.low_rr_supported) { 688 sink_duration_us = 689 (unsigned int)(div_u64(((unsigned long long)(coasting_vtotal) 690 * 10000) * stream->timing.h_total, 691 stream->timing.pix_clk_100hz)); 692 low_rr_active = sink_duration_us < LOW_REFRESH_RATE_DURATION_US_UPPER_BOUND ? false : true; 693 if (low_rr_active != link->replay_settings.config.low_rr_activated) { 694 mod_power_set_low_rr_activate(mod_power, stream, low_rr_active); 695 link->replay_settings.config.low_rr_activated = low_rr_active; 696 } 697 } 698 699 // The function return fail when 700 // 1. DMUB function is not support (for backward compatible). 701 // 2. active_replay_events or coasting_vtotal is not updated in the same time 702 if (!mod_power_replay_set_power_opt_and_coasting_vtotal(mod_power, 703 stream, active_replay_events, coasting_vtotal, is_ultra_sleep_mode, frame_skip_number)) { 704 if (!mod_power_replay_set_power_opt(mod_power, stream, active_replay_events, is_ultra_sleep_mode)) 705 return false; 706 707 if (!mod_power_replay_set_coasting_vtotal(mod_power, stream, coasting_vtotal, frame_skip_number)) 708 return false; 709 } 710 711 mod_power_set_live_capture_with_cvt_activate(mod_power, stream, is_video_playback); 712 713 mod_power_update_error_status(mod_power, stream); 714 715 // If Replay is going to be enable (No matter is disable -> enable or enable -> enable), we don't need to wait. 716 // If Replay is going to be disable 717 // if disable -> disable 718 // -> Replay DMUB state should be state 0. 719 // So no matter wait_for_disable is true or not, it should makes no difference. 720 // if enable -> disable -> We should wait if wait_for_disable is true. 721 if (replay_active_request) 722 wait_for_disable = false; 723 724 if (!mod_power_set_replay_active(stream, replay_active_request, wait_for_disable, force_static)) 725 return false; 726 727 return true; 728 } 729 730 bool mod_power_get_replay_active_status(const struct dc_stream_state *stream, 731 bool *replay_active) 732 { 733 const struct dc_link *link = NULL; 734 735 if (!stream) 736 return false; 737 738 link = dc_stream_get_link(stream); 739 *replay_active = link->replay_settings.replay_allow_active; 740 741 return true; 742 } 743 744 void mod_power_replay_residency(const struct dc_stream_state *stream, 745 unsigned int *residency, const bool is_start, const bool is_alpm) 746 { 747 const struct dc_link *link = NULL; 748 enum pr_residency_mode mode; 749 750 if (!stream) 751 return; 752 753 link = dc_stream_get_link(stream); 754 755 if (is_alpm) 756 mode = PR_RESIDENCY_MODE_ALPM; 757 else 758 mode = PR_RESIDENCY_MODE_PHY; 759 760 if (link && link->dc && link->dc->link_srv) 761 link->dc->link_srv->edp_replay_residency(link, residency, is_start, mode); 762 } 763 764 bool mod_power_replay_set_power_opt_and_coasting_vtotal(struct mod_power *mod_power, 765 const struct dc_stream_state *stream, unsigned int active_replay_events, uint32_t coasting_vtotal, 766 bool is_ultra_sleep_mode, uint16_t frame_skip_number) 767 { 768 struct core_power *core_power = NULL; 769 struct dc_link *link = NULL; 770 unsigned int power_opt = 0; 771 772 if (!stream) 773 return false; 774 775 if (mod_power == NULL) 776 return false; 777 778 core_power = MOD_POWER_TO_CORE(mod_power); 779 780 if (core_power->num_entities == 0) 781 return false; 782 783 link = dc_stream_get_link(stream); 784 785 if (!link || !link->replay_settings.replay_feature_enabled) 786 return false; 787 788 power_opt = mod_power_replay_setup_power_opt(link, active_replay_events, is_ultra_sleep_mode); 789 790 return link->dc->link_srv->edp_set_replay_power_opt_and_coasting_vtotal(link, &power_opt, coasting_vtotal, frame_skip_number); 791 } 792 793 void mod_power_replay_notify_mode_change(struct mod_power *mod_power, 794 struct dc *dc, 795 struct dc_link *link, 796 const struct dc_stream_state *stream, 797 unsigned int stream_index) 798 { 799 struct core_power *core_power = NULL; 800 int active_replay_events = 0; 801 802 if (!mod_power || !dc || !link || !stream) 803 return; 804 805 core_power = MOD_POWER_TO_CORE(mod_power); 806 active_replay_events = core_power->map[stream_index].replay_events; 807 808 /* forced psr is active for seamless switch. 809 * Re-running edp_setup_psr would disturb the freeze, 810 * so skip the PSR re-setup until forced psr releases the override. 811 */ 812 if (active_replay_events & replay_event_os_override_hold) 813 return; 814 815 link->replay_settings.replay_smu_opt_enable = 816 (link->replay_settings.config.replay_smu_opt_supported && 817 mod_power_only_edp(dc->current_state, stream)); 818 819 if (active_replay_events & replay_event_os_request_force_ffu) { 820 link->replay_settings.config.os_request_force_ffu = true; 821 } 822 823 if (dc_is_embedded_signal(stream->signal)) 824 dc->link_srv->dp_setup_replay(link, stream); 825 } 826 827 void init_replay_config(struct dc_link *link, struct replay_config *pr_config) 828 { 829 link->replay_settings.config = *pr_config; 830 } 831 832 void set_replay_frame_skip_number(struct dc_link *link, 833 enum replay_coasting_vtotal_type type, 834 uint32_t coasting_vtotal_refresh_rate_uhz, 835 uint32_t flicker_free_refresh_rate_uhz, 836 bool is_defer) 837 { 838 uint32_t *frame_skip_number_array = NULL; 839 uint32_t frame_skip_number = 0; 840 841 if (link == NULL) 842 return; 843 844 if (link->replay_settings.config.frame_skip_supported == false) 845 return; 846 847 if (flicker_free_refresh_rate_uhz == 0 || coasting_vtotal_refresh_rate_uhz == 0) 848 return; 849 850 if (is_defer) 851 frame_skip_number_array = link->replay_settings.defer_frame_skip_number_table; 852 else 853 frame_skip_number_array = link->replay_settings.frame_skip_number_table; 854 855 if (frame_skip_number_array == NULL) 856 return; 857 858 frame_skip_number = (coasting_vtotal_refresh_rate_uhz + 500000) / flicker_free_refresh_rate_uhz; 859 860 if (frame_skip_number >= 1) 861 frame_skip_number_array[type] = frame_skip_number - 1; 862 else 863 frame_skip_number_array[type] = 0; 864 } 865 866 void set_replay_defer_update_coasting_vtotal(struct dc_link *link, 867 enum replay_coasting_vtotal_type type, 868 uint32_t vtotal) 869 { 870 link->replay_settings.defer_update_coasting_vtotal_table[type] = vtotal; 871 } 872 873 void update_replay_coasting_vtotal_from_defer(struct dc_link *link, 874 enum replay_coasting_vtotal_type type) 875 { 876 link->replay_settings.coasting_vtotal_table[type] = 877 link->replay_settings.defer_update_coasting_vtotal_table[type]; 878 link->replay_settings.frame_skip_number_table[type] = 879 link->replay_settings.defer_frame_skip_number_table[type]; 880 } 881 882 void set_replay_coasting_vtotal(struct dc_link *link, 883 enum replay_coasting_vtotal_type type, 884 uint32_t vtotal) 885 { 886 link->replay_settings.coasting_vtotal_table[type] = vtotal; 887 } 888 889 void set_replay_low_rr_full_screen_video_src_vtotal(struct dc_link *link, uint16_t vtotal) 890 { 891 link->replay_settings.low_rr_full_screen_video_pseudo_vtotal = vtotal; 892 } 893 894 void calculate_replay_link_off_frame_count(struct dc_link *link, 895 uint16_t vtotal, uint16_t htotal) 896 { 897 uint32_t max_link_off_frame_count = 0; 898 uint16_t max_deviation_line = 0, pixel_deviation_per_line = 0; 899 900 if (!link || link->replay_settings.config.replay_version != DC_FREESYNC_REPLAY) 901 return; 902 903 max_deviation_line = link->dpcd_caps.pr_info.max_deviation_line; 904 pixel_deviation_per_line = link->dpcd_caps.pr_info.pixel_deviation_per_line; 905 906 if (htotal != 0 && vtotal != 0 && pixel_deviation_per_line != 0) 907 max_link_off_frame_count = htotal * max_deviation_line / (pixel_deviation_per_line * vtotal); 908 else 909 ASSERT(0); 910 911 link->replay_settings.link_off_frame_count = max_link_off_frame_count; 912 } 913 914 void reset_replay_dsync_error_count(struct dc_link *link) 915 { 916 link->replay_settings.replay_desync_error_fail_count = 0; 917 } 918