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