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"
27dede1feaSBhawanpreet Lakha #include "dc.h"
28dede1feaSBhawanpreet Lakha #include "dm_helpers.h"
29dede1feaSBhawanpreet Lakha #include "amdgpu_dm.h"
30dede1feaSBhawanpreet Lakha #include "modules/power/power_helpers.h"
31dede1feaSBhawanpreet Lakha #include "dmub/inc/dmub_cmd.h"
32dede1feaSBhawanpreet Lakha #include "dc/inc/link.h"
33dede1feaSBhawanpreet Lakha 
34dede1feaSBhawanpreet Lakha /*
35dede1feaSBhawanpreet Lakha  * link_supports_replay() - check if the link supports replay
36dede1feaSBhawanpreet Lakha  * @link: link
37dede1feaSBhawanpreet Lakha  * @aconnector: aconnector
38dede1feaSBhawanpreet Lakha  *
39dede1feaSBhawanpreet Lakha  */
link_supports_replay(struct dc_link * link,struct amdgpu_dm_connector * aconnector)40dede1feaSBhawanpreet Lakha static bool link_supports_replay(struct dc_link *link, struct amdgpu_dm_connector *aconnector)
41dede1feaSBhawanpreet Lakha {
42dede1feaSBhawanpreet Lakha 	struct dm_connector_state *state = to_dm_connector_state(aconnector->base.state);
43dede1feaSBhawanpreet Lakha 	struct dpcd_caps *dpcd_caps = &link->dpcd_caps;
44dede1feaSBhawanpreet Lakha 	struct adaptive_sync_caps *as_caps = &link->dpcd_caps.adaptive_sync_caps;
45dede1feaSBhawanpreet Lakha 
46dede1feaSBhawanpreet Lakha 	if (!state->freesync_capable)
47dede1feaSBhawanpreet Lakha 		return false;
48dede1feaSBhawanpreet Lakha 
49*ec8e59cbSBhawanpreet Lakha 	if (!aconnector->vsdb_info.replay_mode)
50*ec8e59cbSBhawanpreet Lakha 		return false;
51*ec8e59cbSBhawanpreet Lakha 
52dede1feaSBhawanpreet Lakha 	// Check the eDP version
53dede1feaSBhawanpreet Lakha 	if (dpcd_caps->edp_rev < EDP_REVISION_13)
54dede1feaSBhawanpreet Lakha 		return false;
55dede1feaSBhawanpreet Lakha 
56dede1feaSBhawanpreet Lakha 	if (!dpcd_caps->alpm_caps.bits.AUX_WAKE_ALPM_CAP)
57dede1feaSBhawanpreet Lakha 		return false;
58dede1feaSBhawanpreet Lakha 
59dede1feaSBhawanpreet Lakha 	// Check adaptive sync support cap
60dede1feaSBhawanpreet Lakha 	if (!as_caps->dp_adap_sync_caps.bits.ADAPTIVE_SYNC_SDP_SUPPORT)
61dede1feaSBhawanpreet Lakha 		return false;
62dede1feaSBhawanpreet Lakha 
63dede1feaSBhawanpreet Lakha 	return true;
64dede1feaSBhawanpreet Lakha }
65dede1feaSBhawanpreet Lakha 
66dede1feaSBhawanpreet Lakha /*
67dede1feaSBhawanpreet Lakha  * amdgpu_dm_setup_replay() - setup replay configuration
68dede1feaSBhawanpreet Lakha  * @link: link
69dede1feaSBhawanpreet Lakha  * @aconnector: aconnector
70dede1feaSBhawanpreet Lakha  *
71dede1feaSBhawanpreet Lakha  */
amdgpu_dm_setup_replay(struct dc_link * link,struct amdgpu_dm_connector * aconnector)72dede1feaSBhawanpreet Lakha bool amdgpu_dm_setup_replay(struct dc_link *link, struct amdgpu_dm_connector *aconnector)
73dede1feaSBhawanpreet Lakha {
74dede1feaSBhawanpreet Lakha 	struct replay_config pr_config;
75dede1feaSBhawanpreet Lakha 	union replay_debug_flags *debug_flags = NULL;
76dede1feaSBhawanpreet Lakha 
77*ec8e59cbSBhawanpreet Lakha 	// For eDP, if Replay is supported, return true to skip checks
78*ec8e59cbSBhawanpreet Lakha 	if (link->replay_settings.config.replay_supported)
79*ec8e59cbSBhawanpreet Lakha 		return true;
80*ec8e59cbSBhawanpreet Lakha 
81dede1feaSBhawanpreet Lakha 	if (!dc_is_embedded_signal(link->connector_signal))
82dede1feaSBhawanpreet Lakha 		return false;
83dede1feaSBhawanpreet Lakha 
84dede1feaSBhawanpreet Lakha 	if (link->panel_config.psr.disallow_replay)
85dede1feaSBhawanpreet Lakha 		return false;
86dede1feaSBhawanpreet Lakha 
87dede1feaSBhawanpreet Lakha 	if (!link_supports_replay(link, aconnector))
88dede1feaSBhawanpreet Lakha 		return false;
89dede1feaSBhawanpreet Lakha 
90dede1feaSBhawanpreet Lakha 	// Mark Replay is supported in link and update related attributes
91dede1feaSBhawanpreet Lakha 	pr_config.replay_supported = true;
92dede1feaSBhawanpreet Lakha 	pr_config.replay_power_opt_supported = 0;
93dede1feaSBhawanpreet Lakha 	pr_config.replay_enable_option |= pr_enable_option_static_screen;
94dede1feaSBhawanpreet Lakha 	pr_config.replay_timing_sync_supported = aconnector->max_vfreq >= 2 * aconnector->min_vfreq ? true : false;
95dede1feaSBhawanpreet Lakha 
96dede1feaSBhawanpreet Lakha 	if (!pr_config.replay_timing_sync_supported)
97dede1feaSBhawanpreet Lakha 		pr_config.replay_enable_option &= ~pr_enable_option_general_ui;
98dede1feaSBhawanpreet Lakha 
99dede1feaSBhawanpreet Lakha 	debug_flags = (union replay_debug_flags *)&pr_config.debug_flags;
100dede1feaSBhawanpreet Lakha 	debug_flags->u32All = 0;
101dede1feaSBhawanpreet Lakha 	debug_flags->bitfields.visual_confirm =
102dede1feaSBhawanpreet Lakha 		link->ctx->dc->debug.visual_confirm == VISUAL_CONFIRM_REPLAY ? true : false;
103dede1feaSBhawanpreet Lakha 
104dede1feaSBhawanpreet Lakha 	link->replay_settings.replay_feature_enabled = true;
105dede1feaSBhawanpreet Lakha 
106dede1feaSBhawanpreet Lakha 	init_replay_config(link, &pr_config);
107dede1feaSBhawanpreet Lakha 
108dede1feaSBhawanpreet Lakha 	return true;
109dede1feaSBhawanpreet Lakha }
110dede1feaSBhawanpreet Lakha 
111dede1feaSBhawanpreet Lakha 
112dede1feaSBhawanpreet Lakha /*
113dede1feaSBhawanpreet Lakha  * amdgpu_dm_replay_enable() - enable replay f/w
114dede1feaSBhawanpreet Lakha  * @stream: stream state
115dede1feaSBhawanpreet Lakha  *
116dede1feaSBhawanpreet Lakha  * Return: true if success
117dede1feaSBhawanpreet Lakha  */
amdgpu_dm_replay_enable(struct dc_stream_state * stream,bool wait)118dede1feaSBhawanpreet Lakha bool amdgpu_dm_replay_enable(struct dc_stream_state *stream, bool wait)
119dede1feaSBhawanpreet Lakha {
120dede1feaSBhawanpreet Lakha 	uint64_t state;
121dede1feaSBhawanpreet Lakha 	unsigned int retry_count;
122dede1feaSBhawanpreet Lakha 	bool replay_active = true;
123dede1feaSBhawanpreet Lakha 	const unsigned int max_retry = 1000;
124dede1feaSBhawanpreet Lakha 	bool force_static = true;
125dede1feaSBhawanpreet Lakha 	struct dc_link *link = NULL;
126dede1feaSBhawanpreet Lakha 
127dede1feaSBhawanpreet Lakha 
128dede1feaSBhawanpreet Lakha 	if (stream == NULL)
129dede1feaSBhawanpreet Lakha 		return false;
130dede1feaSBhawanpreet Lakha 
131dede1feaSBhawanpreet Lakha 	link = stream->link;
132dede1feaSBhawanpreet Lakha 
133dede1feaSBhawanpreet Lakha 	if (link == NULL)
134dede1feaSBhawanpreet Lakha 		return false;
135dede1feaSBhawanpreet Lakha 
136dede1feaSBhawanpreet Lakha 	link->dc->link_srv->edp_setup_replay(link, stream);
137dede1feaSBhawanpreet Lakha 
138dede1feaSBhawanpreet Lakha 	link->dc->link_srv->edp_set_replay_allow_active(link, NULL, false, false, NULL);
139dede1feaSBhawanpreet Lakha 
140dede1feaSBhawanpreet Lakha 	link->dc->link_srv->edp_set_replay_allow_active(link, &replay_active, false, true, NULL);
141dede1feaSBhawanpreet Lakha 
142dede1feaSBhawanpreet Lakha 	if (wait == true) {
143dede1feaSBhawanpreet Lakha 
144dede1feaSBhawanpreet Lakha 		for (retry_count = 0; retry_count <= max_retry; retry_count++) {
145dede1feaSBhawanpreet Lakha 			dc_link_get_replay_state(link, &state);
146dede1feaSBhawanpreet Lakha 			if (replay_active) {
147dede1feaSBhawanpreet Lakha 				if (state != REPLAY_STATE_0 &&
148dede1feaSBhawanpreet Lakha 					(!force_static || state == REPLAY_STATE_3))
149dede1feaSBhawanpreet Lakha 					break;
150dede1feaSBhawanpreet Lakha 			} else {
151dede1feaSBhawanpreet Lakha 				if (state == REPLAY_STATE_0)
152dede1feaSBhawanpreet Lakha 					break;
153dede1feaSBhawanpreet Lakha 			}
154dede1feaSBhawanpreet Lakha 			udelay(500);
155dede1feaSBhawanpreet Lakha 		}
156dede1feaSBhawanpreet Lakha 
157dede1feaSBhawanpreet Lakha 		/* assert if max retry hit */
158dede1feaSBhawanpreet Lakha 		if (retry_count >= max_retry)
159dede1feaSBhawanpreet Lakha 			ASSERT(0);
160dede1feaSBhawanpreet Lakha 	} else {
161dede1feaSBhawanpreet Lakha 		/* To-do: Add trace log */
162dede1feaSBhawanpreet Lakha 	}
163dede1feaSBhawanpreet Lakha 
164dede1feaSBhawanpreet Lakha 	return true;
165dede1feaSBhawanpreet Lakha }
166dede1feaSBhawanpreet Lakha 
167dede1feaSBhawanpreet Lakha /*
168dede1feaSBhawanpreet Lakha  * amdgpu_dm_replay_disable() - disable replay f/w
169dede1feaSBhawanpreet Lakha  * @stream:  stream state
170dede1feaSBhawanpreet Lakha  *
171dede1feaSBhawanpreet Lakha  * Return: true if success
172dede1feaSBhawanpreet Lakha  */
amdgpu_dm_replay_disable(struct dc_stream_state * stream)173dede1feaSBhawanpreet Lakha bool amdgpu_dm_replay_disable(struct dc_stream_state *stream)
174dede1feaSBhawanpreet Lakha {
175dede1feaSBhawanpreet Lakha 
176dede1feaSBhawanpreet Lakha 	if (stream->link) {
177dede1feaSBhawanpreet Lakha 		DRM_DEBUG_DRIVER("Disabling replay...\n");
178dede1feaSBhawanpreet Lakha 		stream->link->dc->link_srv->edp_set_replay_allow_active(stream->link, NULL, false, false, NULL);
179dede1feaSBhawanpreet Lakha 		return true;
180dede1feaSBhawanpreet Lakha 	}
181dede1feaSBhawanpreet Lakha 
182dede1feaSBhawanpreet Lakha 	return false;
183dede1feaSBhawanpreet Lakha }
184