1dede1feaSBhawanpreet Lakha /*
2dede1feaSBhawanpreet Lakha * Copyright 2023 Advanced Micro Devices, Inc.
3dede1feaSBhawanpreet Lakha *
4dede1feaSBhawanpreet Lakha * Permission is hereby granted, free of charge, to any person obtaining a
5dede1feaSBhawanpreet Lakha * copy of this software and associated documentation files (the "Software"),
6dede1feaSBhawanpreet Lakha * to deal in the Software without restriction, including without limitation
7dede1feaSBhawanpreet Lakha * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8dede1feaSBhawanpreet Lakha * and/or sell copies of the Software, and to permit persons to whom the
9dede1feaSBhawanpreet Lakha * Software is furnished to do so, subject to the following conditions:
10dede1feaSBhawanpreet Lakha *
11dede1feaSBhawanpreet Lakha * The above copyright notice and this permission notice shall be included in
12dede1feaSBhawanpreet Lakha * all copies or substantial portions of the Software.
13dede1feaSBhawanpreet Lakha *
14dede1feaSBhawanpreet Lakha * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15dede1feaSBhawanpreet Lakha * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16dede1feaSBhawanpreet Lakha * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17dede1feaSBhawanpreet Lakha * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18dede1feaSBhawanpreet Lakha * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19dede1feaSBhawanpreet Lakha * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20dede1feaSBhawanpreet Lakha * OTHER DEALINGS IN THE SOFTWARE.
21dede1feaSBhawanpreet Lakha *
22dede1feaSBhawanpreet Lakha * Authors: AMD
23dede1feaSBhawanpreet Lakha *
24dede1feaSBhawanpreet Lakha */
25dede1feaSBhawanpreet Lakha
26dede1feaSBhawanpreet Lakha #include "amdgpu_dm_replay.h"
27*504a336aSTom Chung #include "dc_dmub_srv.h"
28dede1feaSBhawanpreet Lakha #include "dc.h"
29dede1feaSBhawanpreet Lakha #include "dm_helpers.h"
30dede1feaSBhawanpreet Lakha #include "amdgpu_dm.h"
31dede1feaSBhawanpreet Lakha #include "modules/power/power_helpers.h"
32dede1feaSBhawanpreet Lakha #include "dmub/inc/dmub_cmd.h"
33dede1feaSBhawanpreet Lakha #include "dc/inc/link.h"
34dede1feaSBhawanpreet Lakha
35dede1feaSBhawanpreet Lakha /*
36*504a336aSTom Chung * amdgpu_dm_link_supports_replay() - check if the link supports replay
37dede1feaSBhawanpreet Lakha * @link: link
38dede1feaSBhawanpreet Lakha * @aconnector: aconnector
39dede1feaSBhawanpreet Lakha *
40dede1feaSBhawanpreet Lakha */
amdgpu_dm_link_supports_replay(struct dc_link * link,struct amdgpu_dm_connector * aconnector)41*504a336aSTom Chung bool amdgpu_dm_link_supports_replay(struct dc_link *link, struct amdgpu_dm_connector *aconnector)
42dede1feaSBhawanpreet Lakha {
43dede1feaSBhawanpreet Lakha struct dm_connector_state *state = to_dm_connector_state(aconnector->base.state);
44dede1feaSBhawanpreet Lakha struct dpcd_caps *dpcd_caps = &link->dpcd_caps;
45dede1feaSBhawanpreet Lakha struct adaptive_sync_caps *as_caps = &link->dpcd_caps.adaptive_sync_caps;
46dede1feaSBhawanpreet Lakha
47dede1feaSBhawanpreet Lakha if (!state->freesync_capable)
48dede1feaSBhawanpreet Lakha return false;
49dede1feaSBhawanpreet Lakha
50ec8e59cbSBhawanpreet Lakha if (!aconnector->vsdb_info.replay_mode)
51ec8e59cbSBhawanpreet Lakha return false;
52ec8e59cbSBhawanpreet Lakha
53dede1feaSBhawanpreet Lakha // Check the eDP version
54dede1feaSBhawanpreet Lakha if (dpcd_caps->edp_rev < EDP_REVISION_13)
55dede1feaSBhawanpreet Lakha return false;
56dede1feaSBhawanpreet Lakha
57dede1feaSBhawanpreet Lakha if (!dpcd_caps->alpm_caps.bits.AUX_WAKE_ALPM_CAP)
58dede1feaSBhawanpreet Lakha return false;
59dede1feaSBhawanpreet Lakha
60dede1feaSBhawanpreet Lakha // Check adaptive sync support cap
61dede1feaSBhawanpreet Lakha if (!as_caps->dp_adap_sync_caps.bits.ADAPTIVE_SYNC_SDP_SUPPORT)
62dede1feaSBhawanpreet Lakha return false;
63dede1feaSBhawanpreet Lakha
645950efe2STom Chung // Sink shall populate line deviation information
655950efe2STom Chung if (dpcd_caps->pr_info.pixel_deviation_per_line == 0 ||
665950efe2STom Chung dpcd_caps->pr_info.max_deviation_line == 0)
675950efe2STom Chung return false;
685950efe2STom Chung
69dede1feaSBhawanpreet Lakha return true;
70dede1feaSBhawanpreet Lakha }
71dede1feaSBhawanpreet Lakha
72dede1feaSBhawanpreet Lakha /*
735950efe2STom Chung * amdgpu_dm_set_replay_caps() - setup Replay capabilities
74dede1feaSBhawanpreet Lakha * @link: link
75dede1feaSBhawanpreet Lakha * @aconnector: aconnector
76dede1feaSBhawanpreet Lakha *
77dede1feaSBhawanpreet Lakha */
amdgpu_dm_set_replay_caps(struct dc_link * link,struct amdgpu_dm_connector * aconnector)785950efe2STom Chung bool amdgpu_dm_set_replay_caps(struct dc_link *link, struct amdgpu_dm_connector *aconnector)
79dede1feaSBhawanpreet Lakha {
805950efe2STom Chung struct replay_config pr_config = { 0 };
81dede1feaSBhawanpreet Lakha union replay_debug_flags *debug_flags = NULL;
82*504a336aSTom Chung struct dc *dc = link->ctx->dc;
83dede1feaSBhawanpreet Lakha
845950efe2STom Chung // If Replay is already set to support, return true to skip checks
85ec8e59cbSBhawanpreet Lakha if (link->replay_settings.config.replay_supported)
86ec8e59cbSBhawanpreet Lakha return true;
87ec8e59cbSBhawanpreet Lakha
88dede1feaSBhawanpreet Lakha if (!dc_is_embedded_signal(link->connector_signal))
89dede1feaSBhawanpreet Lakha return false;
90dede1feaSBhawanpreet Lakha
91dede1feaSBhawanpreet Lakha if (link->panel_config.psr.disallow_replay)
92dede1feaSBhawanpreet Lakha return false;
93dede1feaSBhawanpreet Lakha
94*504a336aSTom Chung if (!amdgpu_dm_link_supports_replay(link, aconnector))
95*504a336aSTom Chung return false;
96*504a336aSTom Chung
97*504a336aSTom Chung if (!dc->ctx->dmub_srv || !dc->ctx->dmub_srv->dmub ||
98*504a336aSTom Chung !dc->ctx->dmub_srv->dmub->feature_caps.replay_supported)
99dede1feaSBhawanpreet Lakha return false;
100dede1feaSBhawanpreet Lakha
1015950efe2STom Chung // Mark Replay is supported in pr_config
102dede1feaSBhawanpreet Lakha pr_config.replay_supported = true;
103dede1feaSBhawanpreet Lakha
104dede1feaSBhawanpreet Lakha debug_flags = (union replay_debug_flags *)&pr_config.debug_flags;
105dede1feaSBhawanpreet Lakha debug_flags->u32All = 0;
106dede1feaSBhawanpreet Lakha debug_flags->bitfields.visual_confirm =
107176b9dd2SSrinivasan Shanmugam link->ctx->dc->debug.visual_confirm == VISUAL_CONFIRM_REPLAY;
108dede1feaSBhawanpreet Lakha
109dede1feaSBhawanpreet Lakha init_replay_config(link, &pr_config);
110dede1feaSBhawanpreet Lakha
111dede1feaSBhawanpreet Lakha return true;
112dede1feaSBhawanpreet Lakha }
113dede1feaSBhawanpreet Lakha
1145950efe2STom Chung /*
1155950efe2STom Chung * amdgpu_dm_link_setup_replay() - configure replay link
1165950efe2STom Chung * @link: link
1175950efe2STom Chung * @aconnector: aconnector
1185950efe2STom Chung *
1195950efe2STom Chung */
amdgpu_dm_link_setup_replay(struct dc_link * link,struct amdgpu_dm_connector * aconnector)1205950efe2STom Chung bool amdgpu_dm_link_setup_replay(struct dc_link *link, struct amdgpu_dm_connector *aconnector)
1215950efe2STom Chung {
1225950efe2STom Chung struct replay_config *pr_config;
1235950efe2STom Chung
1245950efe2STom Chung if (link == NULL || aconnector == NULL)
1255950efe2STom Chung return false;
1265950efe2STom Chung
1275950efe2STom Chung pr_config = &link->replay_settings.config;
1285950efe2STom Chung
1295950efe2STom Chung if (!pr_config->replay_supported)
1305950efe2STom Chung return false;
1315950efe2STom Chung
1325950efe2STom Chung pr_config->replay_power_opt_supported = 0x11;
1335950efe2STom Chung pr_config->replay_smu_opt_supported = false;
1345950efe2STom Chung pr_config->replay_enable_option |= pr_enable_option_static_screen;
1355950efe2STom Chung pr_config->replay_support_fast_resync_in_ultra_sleep_mode = aconnector->max_vfreq >= 2 * aconnector->min_vfreq;
1365950efe2STom Chung pr_config->replay_timing_sync_supported = false;
1375950efe2STom Chung
1385950efe2STom Chung if (!pr_config->replay_timing_sync_supported)
1395950efe2STom Chung pr_config->replay_enable_option &= ~pr_enable_option_general_ui;
1405950efe2STom Chung
1415950efe2STom Chung link->replay_settings.replay_feature_enabled = true;
1425950efe2STom Chung
1435950efe2STom Chung return true;
1445950efe2STom Chung }
145dede1feaSBhawanpreet Lakha
146dede1feaSBhawanpreet Lakha /*
147dede1feaSBhawanpreet Lakha * amdgpu_dm_replay_enable() - enable replay f/w
148dede1feaSBhawanpreet Lakha * @stream: stream state
149dede1feaSBhawanpreet Lakha *
150dede1feaSBhawanpreet Lakha * Return: true if success
151dede1feaSBhawanpreet Lakha */
amdgpu_dm_replay_enable(struct dc_stream_state * stream,bool wait)152dede1feaSBhawanpreet Lakha bool amdgpu_dm_replay_enable(struct dc_stream_state *stream, bool wait)
153dede1feaSBhawanpreet Lakha {
154dede1feaSBhawanpreet Lakha bool replay_active = true;
155dede1feaSBhawanpreet Lakha struct dc_link *link = NULL;
156dede1feaSBhawanpreet Lakha
157dede1feaSBhawanpreet Lakha if (stream == NULL)
158dede1feaSBhawanpreet Lakha return false;
159dede1feaSBhawanpreet Lakha
160dede1feaSBhawanpreet Lakha link = stream->link;
161dede1feaSBhawanpreet Lakha
1625950efe2STom Chung if (link) {
163dede1feaSBhawanpreet Lakha link->dc->link_srv->edp_setup_replay(link, stream);
1645950efe2STom Chung link->dc->link_srv->edp_set_coasting_vtotal(link, stream->timing.v_total);
1655950efe2STom Chung DRM_DEBUG_DRIVER("Enabling replay...\n");
1665950efe2STom Chung link->dc->link_srv->edp_set_replay_allow_active(link, &replay_active, wait, false, NULL);
167dede1feaSBhawanpreet Lakha return true;
168dede1feaSBhawanpreet Lakha }
169dede1feaSBhawanpreet Lakha
1705950efe2STom Chung return false;
1715950efe2STom Chung }
1725950efe2STom Chung
173dede1feaSBhawanpreet Lakha /*
174dede1feaSBhawanpreet Lakha * amdgpu_dm_replay_disable() - disable replay f/w
175dede1feaSBhawanpreet Lakha * @stream: stream state
176dede1feaSBhawanpreet Lakha *
177dede1feaSBhawanpreet Lakha * Return: true if success
178dede1feaSBhawanpreet Lakha */
amdgpu_dm_replay_disable(struct dc_stream_state * stream)179dede1feaSBhawanpreet Lakha bool amdgpu_dm_replay_disable(struct dc_stream_state *stream)
180dede1feaSBhawanpreet Lakha {
1815950efe2STom Chung bool replay_active = false;
1825950efe2STom Chung struct dc_link *link = NULL;
183dede1feaSBhawanpreet Lakha
1845950efe2STom Chung if (stream == NULL)
1855950efe2STom Chung return false;
1865950efe2STom Chung
1875950efe2STom Chung link = stream->link;
1885950efe2STom Chung
1895950efe2STom Chung if (link) {
190dede1feaSBhawanpreet Lakha DRM_DEBUG_DRIVER("Disabling replay...\n");
1915950efe2STom Chung link->dc->link_srv->edp_set_replay_allow_active(stream->link, &replay_active, true, false, NULL);
192dede1feaSBhawanpreet Lakha return true;
193dede1feaSBhawanpreet Lakha }
194dede1feaSBhawanpreet Lakha
195dede1feaSBhawanpreet Lakha return false;
196dede1feaSBhawanpreet Lakha }
1975950efe2STom Chung
1985950efe2STom Chung /*
1995950efe2STom Chung * amdgpu_dm_replay_disable_all() - disable replay f/w
2005950efe2STom Chung * if replay is enabled on any stream
2015950efe2STom Chung *
2025950efe2STom Chung * Return: true if success
2035950efe2STom Chung */
amdgpu_dm_replay_disable_all(struct amdgpu_display_manager * dm)2045950efe2STom Chung bool amdgpu_dm_replay_disable_all(struct amdgpu_display_manager *dm)
2055950efe2STom Chung {
2065950efe2STom Chung DRM_DEBUG_DRIVER("Disabling replay if replay is enabled on any stream\n");
2075950efe2STom Chung return dc_set_replay_allow_active(dm->dc, false);
2085950efe2STom Chung }
209