xref: /linux/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c (revision 9aef3d167a1c0f1a59ef043ee7b0f525936fbfc6)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright 2021 Advanced Micro Devices, Inc.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21  * OTHER DEALINGS IN THE SOFTWARE.
22  *
23  * Authors: AMD
24  *
25  */
26 
27 #include "amdgpu_dm_psr.h"
28 #include "amdgpu.h"
29 #include "dc_dmub_srv.h"
30 #include "dc.h"
31 #include "amdgpu_dm.h"
32 #include "modules/power/power_helpers.h"
33 #include "amdgpu_dm_kunit_helpers.h"
34 
35 
36 static bool link_supports_psrsu(struct dc_link *link)
37 {
38 	struct dc *dc = link->ctx->dc;
39 
40 	if (!dc->caps.dmcub_support)
41 		return false;
42 
43 	if (dc->ctx->dce_version < DCN_VERSION_3_1)
44 		return false;
45 
46 	if (!is_psr_su_specific_panel(link))
47 		return false;
48 
49 	if (!link->dpcd_caps.alpm_caps.bits.AUX_WAKE_ALPM_CAP ||
50 	    !link->dpcd_caps.psr_info.psr_dpcd_caps.bits.Y_COORDINATE_REQUIRED)
51 		return false;
52 
53 	if (link->dpcd_caps.psr_info.psr_dpcd_caps.bits.SU_GRANULARITY_REQUIRED &&
54 	    !link->dpcd_caps.psr_info.psr2_su_y_granularity_cap)
55 		return false;
56 
57 	if (amdgpu_dc_debug_mask & DC_DISABLE_PSR_SU)
58 		return false;
59 
60 	/* Temporarily disable PSR-SU to avoid glitches */
61 	return false;
62 }
63 
64 STATIC_IFN_KUNIT
65 void amdgpu_dm_psr_fill_caps(struct dc_link *link, struct psr_caps *caps)
66 {
67 	struct dpcd_caps *dpcd_caps = &link->dpcd_caps;
68 	unsigned int power_opts = 0;
69 
70 	if (amdgpu_dc_feature_mask & DC_PSR_ALLOW_SMU_OPT)
71 		power_opts |= psr_power_opt_smu_opt_static_screen;
72 	power_opts |= psr_power_opt_z10_static_screen;
73 
74 	if (link->psr_settings.psr_version == DC_PSR_VERSION_1)
75 		caps->psr_version = 1;
76 	else if (link->psr_settings.psr_version == DC_PSR_VERSION_SU_1)
77 		caps->psr_version = 2;
78 
79 	caps->psr_rfb_setup_time = (6 - dpcd_caps->psr_info.psr_dpcd_caps.bits.PSR_SETUP_TIME) * 55;
80 	caps->psr_exit_link_training_required =
81 		!dpcd_caps->psr_info.psr_dpcd_caps.bits.LINK_TRAINING_ON_EXIT_NOT_REQUIRED;
82 	caps->edp_revision = dpcd_caps->edp_rev;
83 	caps->support_ver = dpcd_caps->psr_info.psr_version;
84 	caps->su_granularity_required =
85 		dpcd_caps->psr_info.psr_dpcd_caps.bits.SU_GRANULARITY_REQUIRED;
86 	caps->y_coordinate_required = dpcd_caps->psr_info.psr_dpcd_caps.bits.Y_COORDINATE_REQUIRED;
87 	caps->su_y_granularity = dpcd_caps->psr_info.psr2_su_y_granularity_cap;
88 	caps->alpm_cap = dpcd_caps->alpm_caps.bits.AUX_WAKE_ALPM_CAP;
89 	caps->standby_support = dpcd_caps->alpm_caps.bits.PM_STATE_2A_SUPPORT;
90 	caps->rate_control_caps = 0; /* TODO: read in rc caps from aux */
91 	caps->psr_power_opt_flag = power_opts;
92 }
93 EXPORT_IF_KUNIT(amdgpu_dm_psr_fill_caps);
94 
95 /*
96  * amdgpu_dm_set_psr_caps() - set link psr capabilities
97  * @link: link
98  * @aconnector: amdgpu_dm_connector
99  */
100 bool amdgpu_dm_set_psr_caps(struct dc_link *link, struct amdgpu_dm_connector *aconnector)
101 {
102 	struct dc *dc;
103 	unsigned int panel_inst = 0;
104 
105 	if (!link || !aconnector)
106 		return false;
107 
108 	dc = link->ctx->dc;
109 
110 	/* Reset psr version first */
111 	link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED;
112 
113 	if (!dc->caps.dmub_caps.psr)
114 		return false;
115 
116 	if (!(link->connector_signal & SIGNAL_TYPE_EDP))
117 		return false;
118 
119 	if (link->type == dc_connection_none)
120 		return false;
121 
122 	if (link->dpcd_caps.psr_info.psr_version == 0)
123 		return false;
124 
125 	/*disable allow psr/psrsu/replay on eDP1*/
126 	if (dc_get_edp_link_panel_inst(dc, link, &panel_inst) && panel_inst == 1)
127 		return false;
128 
129 	if (link_supports_psrsu(link))
130 		link->psr_settings.psr_version = DC_PSR_VERSION_SU_1;
131 	else
132 		link->psr_settings.psr_version = DC_PSR_VERSION_1;
133 
134 	amdgpu_dm_psr_fill_caps(link, &aconnector->psr_caps);
135 	return true;
136 }
137 
138 /*
139  * amdgpu_dm_psr_is_active_allowed() - check if psr is allowed on any stream
140  * @dm:  pointer to amdgpu_display_manager
141  *
142  * Return: true if allowed
143  */
144 
145 bool amdgpu_dm_psr_is_active_allowed(struct amdgpu_display_manager *dm)
146 {
147 	unsigned int i;
148 
149 	for (i = 0; i < dm->dc->current_state->stream_count; i++) {
150 		const struct dc_link *link = dm->dc->current_state->streams[i]->link;
151 
152 		if (!link)
153 			continue;
154 
155 		if (link->psr_settings.psr_feature_enabled && link->psr_settings.psr_allow_active)
156 			return true;
157 	}
158 	return false;
159 }
160 
161 /*
162  * amdgpu_dm_psr_set_event() - set or clear PSR event for stream
163  * @dm: pointer to amdgpu_display_manager
164  * @stream: pointer to dc_stream_state
165  * @set_event: true to set event, false to clear event
166  * @event: PSR event type
167  * @wait_for_disable: whether to wait for PSR to be disabled
168  *
169  * Return: true if successful, false otherwise
170  */
171 bool amdgpu_dm_psr_set_event(struct amdgpu_display_manager *dm, struct dc_stream_state *stream,
172 		bool set_event, enum psr_event event, bool wait_for_disable)
173 {
174 	unsigned int psr_events;
175 
176 	/* Validate all required parameters */
177 	if (!stream || !stream->link ||
178 		!stream->link->psr_settings.psr_feature_enabled)
179 		return false;
180 
181 	/* Get current psr events */
182 	if (!mod_power_get_psr_event(dm->power_module, stream, &psr_events))
183 		return false;
184 
185 	/* If all events already in desired state, return true. */
186 	if ((psr_events & event) == (set_event ? event : 0))
187 		return true;
188 
189 	return mod_power_set_psr_event(dm->power_module, stream,
190 				       set_event, event, wait_for_disable);
191 }
192 EXPORT_IF_KUNIT(amdgpu_dm_psr_set_event);
193