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