projects/linux·blob master · refs

239 lines · 7.2 KiB

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 "dm_helpers.h"
34
35STATIC_IFN_KUNIT
36bool 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}
63EXPORT_IF_KUNIT(link_supports_psrsu);
64
65STATIC_IFN_KUNIT
66void amdgpu_dm_psr_fill_caps(struct dc_link *link, struct psr_caps *caps)
67{
68 struct dpcd_caps *dpcd_caps = &link->dpcd_caps;
69 unsigned int power_opts = 0;
70
71 if (amdgpu_dc_feature_mask & DC_PSR_ALLOW_SMU_OPT)
72 power_opts |= psr_power_opt_smu_opt_static_screen;
73 power_opts |= psr_power_opt_z10_static_screen;
74
75 if (link->psr_settings.psr_version == DC_PSR_VERSION_1)
76 caps->psr_version = 1;
77 else if (link->psr_settings.psr_version == DC_PSR_VERSION_SU_1)
78 caps->psr_version = 2;
79
80 caps->psr_rfb_setup_time = (6 - dpcd_caps->psr_info.psr_dpcd_caps.bits.PSR_SETUP_TIME) * 55;
81 caps->psr_exit_link_training_required =
82 !dpcd_caps->psr_info.psr_dpcd_caps.bits.LINK_TRAINING_ON_EXIT_NOT_REQUIRED;
83 caps->edp_revision = dpcd_caps->edp_rev;
84 caps->support_ver = dpcd_caps->psr_info.psr_version;
85 caps->su_granularity_required =
86 dpcd_caps->psr_info.psr_dpcd_caps.bits.SU_GRANULARITY_REQUIRED;
87 caps->y_coordinate_required = dpcd_caps->psr_info.psr_dpcd_caps.bits.Y_COORDINATE_REQUIRED;
88 caps->su_y_granularity = dpcd_caps->psr_info.psr2_su_y_granularity_cap;
89 caps->alpm_cap = dpcd_caps->alpm_caps.bits.AUX_WAKE_ALPM_CAP;
90 caps->standby_support = dpcd_caps->alpm_caps.bits.PM_STATE_2A_SUPPORT;
91 caps->rate_control_caps = 0; /* TODO: read in rc caps from aux */
92 caps->psr_power_opt_flag = power_opts;
93}
94EXPORT_IF_KUNIT(amdgpu_dm_psr_fill_caps);
95
96/*
97 * amdgpu_dm_set_psr_caps() - set link psr capabilities
98 * @link: link
99 * @aconnector: amdgpu_dm_connector
100 */
101bool amdgpu_dm_set_psr_caps(struct dc_link *link, struct amdgpu_dm_connector *aconnector)
102{
103 struct dc *dc;
104 unsigned int panel_inst = 0;
105
106 if (!link || !aconnector)
107 return false;
108
109 dc = link->ctx->dc;
110
111 /* Reset psr version first */
112 link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED;
113
114 if (!dc->caps.dmub_caps.psr)
115 return false;
116
117 if (!(link->connector_signal & SIGNAL_TYPE_EDP))
118 return false;
119
120 if (link->type == dc_connection_none)
121 return false;
122
123 if (link->dpcd_caps.psr_info.psr_version == 0)
124 return false;
125
126 /*disable allow psr/psrsu/replay on eDP1*/
127 if (dc_get_edp_link_panel_inst(dc, link, &panel_inst) && panel_inst == 1)
128 return false;
129
130 if (link_supports_psrsu(link))
131 link->psr_settings.psr_version = DC_PSR_VERSION_SU_1;
132 else
133 link->psr_settings.psr_version = DC_PSR_VERSION_1;
134
135 amdgpu_dm_psr_fill_caps(link, &aconnector->psr_caps);
136 return true;
137}
138EXPORT_IF_KUNIT(amdgpu_dm_set_psr_caps);
139
140/*
141 * amdgpu_dm_psr_is_active_allowed() - check if psr is allowed on any stream
142 * @dm: pointer to amdgpu_display_manager
143 *
144 * Return: true if allowed
145 */
146
147bool amdgpu_dm_psr_is_active_allowed(struct amdgpu_display_manager *dm)
148{
149 unsigned int i;
150
151 for (i = 0; i < dm->dc->current_state->stream_count; i++) {
152 const struct dc_link *link = dm->dc->current_state->streams[i]->link;
153
154 if (!link)
155 continue;
156
157 if (link->psr_settings.psr_feature_enabled && link->psr_settings.psr_allow_active)
158 return true;
159 }
160 return false;
161}
162EXPORT_IF_KUNIT(amdgpu_dm_psr_is_active_allowed);
163
164/*
165 * amdgpu_dm_psr_set_event() - set or clear PSR event for stream
166 * @dm: pointer to amdgpu_display_manager
167 * @stream: pointer to dc_stream_state
168 * @set_event: true to set event, false to clear event
169 * @event: PSR event type
170 * @wait_for_disable: whether to wait for PSR to be disabled
171 *
172 * Return: true if successful, false otherwise
173 */
174bool amdgpu_dm_psr_set_event(struct amdgpu_display_manager *dm, struct dc_stream_state *stream,
175 bool set_event, enum psr_event event, bool wait_for_disable)
176{
177 unsigned int psr_events;
178
179 /* Validate all required parameters */
180 if (!stream || !stream->link ||
181 !stream->link->psr_settings.psr_feature_enabled)
182 return false;
183
184 /* Get current psr events */
185 if (!mod_power_get_psr_event(dm->power_module, stream, &psr_events))
186 return false;
187
188 /* If all events already in desired state, return true. */
189 if ((psr_events & event) == (set_event ? event : 0))
190 return true;
191
192 return mod_power_set_psr_event(dm->power_module, stream,
193 set_event, event, wait_for_disable);
194}
195EXPORT_IF_KUNIT(amdgpu_dm_psr_set_event);
196
197#if IS_ENABLED(CONFIG_DRM_AMD_DC_KUNIT_TEST)
198/**
199 * amdgpu_dm_psr_get_dc_feature_mask() - Get DC feature mask for KUnit tests.
200 *
201 * Return: Current value of amdgpu_dc_feature_mask.
202 */
203unsigned int amdgpu_dm_psr_get_dc_feature_mask(void)
204{
205 return amdgpu_dc_feature_mask;
206}
207EXPORT_IF_KUNIT(amdgpu_dm_psr_get_dc_feature_mask);
208
209/**
210 * amdgpu_dm_psr_set_dc_feature_mask() - Set DC feature mask for KUnit tests.
211 * @feature_mask: DC feature mask to set while testing amdgpu_dm_psr_fill_caps().
212 */
213void amdgpu_dm_psr_set_dc_feature_mask(unsigned int feature_mask)
214{
215 amdgpu_dc_feature_mask = feature_mask;
216}
217EXPORT_IF_KUNIT(amdgpu_dm_psr_set_dc_feature_mask);
218
219/**
220 * amdgpu_dm_psr_get_dc_debug_mask() - Get DC debug mask for KUnit tests.
221 *
222 * Return: Current value of amdgpu_dc_debug_mask.
223 */
224unsigned int amdgpu_dm_psr_get_dc_debug_mask(void)
225{
226 return amdgpu_dc_debug_mask;
227}
228EXPORT_IF_KUNIT(amdgpu_dm_psr_get_dc_debug_mask);
229
230/**
231 * amdgpu_dm_psr_set_dc_debug_mask() - Set DC debug mask for KUnit tests.
232 * @debug_mask: DC debug mask to set while testing link_supports_psrsu().
233 */
234void amdgpu_dm_psr_set_dc_debug_mask(unsigned int debug_mask)
235{
236 amdgpu_dc_debug_mask = debug_mask;
237}
238EXPORT_IF_KUNIT(amdgpu_dm_psr_set_dc_debug_mask);
239#endif