1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#include "dmub_psr.h"
27#include "dc.h"
28#include "dc_dmub_srv.h"
29#include "dmub/dmub_srv.h"
30#include "core_types.h"
31
32#define MAX_PIPES 6
33
34
35
36
37static enum dc_psr_state convert_psr_state(uint32_t raw_state)
38{
39 enum dc_psr_state state = PSR_STATE0;
40
41 if (raw_state == 0)
42 state = PSR_STATE0;
43 else if (raw_state == 0x10)
44 state = PSR_STATE1;
45 else if (raw_state == 0x11)
46 state = PSR_STATE1a;
47 else if (raw_state == 0x20)
48 state = PSR_STATE2;
49 else if (raw_state == 0x21)
50 state = PSR_STATE2a;
51 else if (raw_state == 0x30)
52 state = PSR_STATE3;
53 else if (raw_state == 0x31)
54 state = PSR_STATE3Init;
55 else if (raw_state == 0x40)
56 state = PSR_STATE4;
57 else if (raw_state == 0x41)
58 state = PSR_STATE4a;
59 else if (raw_state == 0x42)
60 state = PSR_STATE4b;
61 else if (raw_state == 0x43)
62 state = PSR_STATE4c;
63 else if (raw_state == 0x44)
64 state = PSR_STATE4d;
65 else if (raw_state == 0x50)
66 state = PSR_STATE5;
67 else if (raw_state == 0x51)
68 state = PSR_STATE5a;
69 else if (raw_state == 0x52)
70 state = PSR_STATE5b;
71 else if (raw_state == 0x53)
72 state = PSR_STATE5c;
73
74 return state;
75}
76
77
78
79
80static void dmub_psr_get_state(struct dmub_psr *dmub, enum dc_psr_state *state)
81{
82 struct dmub_srv *srv = dmub->ctx->dmub_srv->dmub;
83 uint32_t raw_state;
84
85
86 dmub_srv_send_gpint_command(srv, DMUB_GPINT__GET_PSR_STATE, 0, 30);
87
88 dmub_srv_get_gpint_response(srv, &raw_state);
89
90 *state = convert_psr_state(raw_state);
91}
92
93
94
95
96static bool dmub_psr_set_version(struct dmub_psr *dmub, struct dc_stream_state *stream)
97{
98 union dmub_rb_cmd cmd;
99 struct dc_context *dc = dmub->ctx;
100
101 if (stream->link->psr_settings.psr_version == DC_PSR_VERSION_UNSUPPORTED)
102 return false;
103
104 memset(&cmd, 0, sizeof(cmd));
105 cmd.psr_set_version.header.type = DMUB_CMD__PSR;
106 cmd.psr_set_version.header.sub_type = DMUB_CMD__PSR_SET_VERSION;
107 switch (stream->link->psr_settings.psr_version) {
108 case DC_PSR_VERSION_1:
109 cmd.psr_set_version.psr_set_version_data.version = PSR_VERSION_1;
110 break;
111 case DC_PSR_VERSION_UNSUPPORTED:
112 default:
113 cmd.psr_set_version.psr_set_version_data.version = PSR_VERSION_UNSUPPORTED;
114 break;
115 }
116 cmd.psr_set_version.header.payload_bytes = sizeof(struct dmub_cmd_psr_set_version_data);
117
118 dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
119 dc_dmub_srv_cmd_execute(dc->dmub_srv);
120 dc_dmub_srv_wait_idle(dc->dmub_srv);
121
122 return true;
123}
124
125
126
127
128static void dmub_psr_enable(struct dmub_psr *dmub, bool enable, bool wait)
129{
130 union dmub_rb_cmd cmd;
131 struct dc_context *dc = dmub->ctx;
132 uint32_t retry_count;
133 enum dc_psr_state state = PSR_STATE0;
134
135 memset(&cmd, 0, sizeof(cmd));
136 cmd.psr_enable.header.type = DMUB_CMD__PSR;
137
138 if (enable)
139 cmd.psr_enable.header.sub_type = DMUB_CMD__PSR_ENABLE;
140 else
141 cmd.psr_enable.header.sub_type = DMUB_CMD__PSR_DISABLE;
142
143 cmd.psr_enable.header.payload_bytes = 0;
144
145 dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
146 dc_dmub_srv_cmd_execute(dc->dmub_srv);
147 dc_dmub_srv_wait_idle(dc->dmub_srv);
148
149
150
151
152
153 if (wait) {
154 for (retry_count = 0; retry_count <= 1000; retry_count++) {
155 dmub_psr_get_state(dmub, &state);
156
157 if (enable) {
158 if (state != PSR_STATE0)
159 break;
160 } else {
161 if (state == PSR_STATE0)
162 break;
163 }
164
165 udelay(500);
166 }
167
168
169 if (retry_count >= 1000)
170 ASSERT(0);
171 }
172}
173
174
175
176
177static void dmub_psr_set_level(struct dmub_psr *dmub, uint16_t psr_level)
178{
179 union dmub_rb_cmd cmd;
180 enum dc_psr_state state = PSR_STATE0;
181 struct dc_context *dc = dmub->ctx;
182
183 dmub_psr_get_state(dmub, &state);
184
185 if (state == PSR_STATE0)
186 return;
187
188 memset(&cmd, 0, sizeof(cmd));
189 cmd.psr_set_level.header.type = DMUB_CMD__PSR;
190 cmd.psr_set_level.header.sub_type = DMUB_CMD__PSR_SET_LEVEL;
191 cmd.psr_set_level.header.payload_bytes = sizeof(struct dmub_cmd_psr_set_level_data);
192 cmd.psr_set_level.psr_set_level_data.psr_level = psr_level;
193
194 dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
195 dc_dmub_srv_cmd_execute(dc->dmub_srv);
196 dc_dmub_srv_wait_idle(dc->dmub_srv);
197}
198
199
200
201
202static bool dmub_psr_copy_settings(struct dmub_psr *dmub,
203 struct dc_link *link,
204 struct psr_context *psr_context)
205{
206 union dmub_rb_cmd cmd;
207 struct dc_context *dc = dmub->ctx;
208 struct dmub_cmd_psr_copy_settings_data *copy_settings_data
209 = &cmd.psr_copy_settings.psr_copy_settings_data;
210 struct pipe_ctx *pipe_ctx = NULL;
211 struct resource_context *res_ctx = &link->ctx->dc->current_state->res_ctx;
212 int i = 0;
213
214 for (i = 0; i < MAX_PIPES; i++) {
215 if (res_ctx->pipe_ctx[i].stream &&
216 res_ctx->pipe_ctx[i].stream->link == link &&
217 res_ctx->pipe_ctx[i].stream->link->connector_signal == SIGNAL_TYPE_EDP) {
218 pipe_ctx = &res_ctx->pipe_ctx[i];
219 break;
220 }
221 }
222
223 if (!pipe_ctx)
224 return false;
225
226
227 if (!dmub_psr_set_version(dmub, pipe_ctx->stream))
228 return false;
229
230
231 link->link_enc->funcs->psr_program_dp_dphy_fast_training(link->link_enc,
232 psr_context->psrExitLinkTrainingRequired);
233
234
235 link->link_enc->funcs->psr_program_secondary_packet(link->link_enc,
236 psr_context->sdpTransmitLineNumDeadline);
237
238 memset(&cmd, 0, sizeof(cmd));
239 cmd.psr_copy_settings.header.type = DMUB_CMD__PSR;
240 cmd.psr_copy_settings.header.sub_type = DMUB_CMD__PSR_COPY_SETTINGS;
241 cmd.psr_copy_settings.header.payload_bytes = sizeof(struct dmub_cmd_psr_copy_settings_data);
242
243
244 copy_settings_data->dpphy_inst = psr_context->transmitterId;
245 copy_settings_data->aux_inst = psr_context->channel;
246 copy_settings_data->digfe_inst = psr_context->engineId;
247 copy_settings_data->digbe_inst = psr_context->transmitterId;
248
249 copy_settings_data->mpcc_inst = pipe_ctx->plane_res.mpcc_inst;
250
251 if (pipe_ctx->plane_res.dpp)
252 copy_settings_data->dpp_inst = pipe_ctx->plane_res.dpp->inst;
253 else
254 copy_settings_data->dpp_inst = 0;
255 if (pipe_ctx->stream_res.opp)
256 copy_settings_data->opp_inst = pipe_ctx->stream_res.opp->inst;
257 else
258 copy_settings_data->opp_inst = 0;
259 if (pipe_ctx->stream_res.tg)
260 copy_settings_data->otg_inst = pipe_ctx->stream_res.tg->inst;
261 else
262 copy_settings_data->otg_inst = 0;
263
264
265 copy_settings_data->psr_level = psr_context->psr_level.u32all;
266 copy_settings_data->smu_optimizations_en = psr_context->allow_smu_optimizations;
267 copy_settings_data->multi_disp_optimizations_en = psr_context->allow_multi_disp_optimizations;
268 copy_settings_data->frame_delay = psr_context->frame_delay;
269 copy_settings_data->frame_cap_ind = psr_context->psrFrameCaptureIndicationReq;
270 copy_settings_data->init_sdp_deadline = psr_context->sdpTransmitLineNumDeadline;
271 copy_settings_data->debug.u32All = 0;
272 copy_settings_data->debug.bitfields.visual_confirm = dc->dc->debug.visual_confirm == VISUAL_CONFIRM_PSR ?
273 true : false;
274 copy_settings_data->debug.bitfields.use_hw_lock_mgr = 1;
275
276 dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
277 dc_dmub_srv_cmd_execute(dc->dmub_srv);
278 dc_dmub_srv_wait_idle(dc->dmub_srv);
279
280 return true;
281}
282
283
284
285
286static void dmub_psr_force_static(struct dmub_psr *dmub)
287{
288 union dmub_rb_cmd cmd;
289 struct dc_context *dc = dmub->ctx;
290
291 memset(&cmd, 0, sizeof(cmd));
292 cmd.psr_force_static.header.type = DMUB_CMD__PSR;
293 cmd.psr_force_static.header.sub_type = DMUB_CMD__PSR_FORCE_STATIC;
294 cmd.psr_enable.header.payload_bytes = 0;
295
296 dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
297 dc_dmub_srv_cmd_execute(dc->dmub_srv);
298 dc_dmub_srv_wait_idle(dc->dmub_srv);
299}
300
301
302
303
304static void dmub_psr_get_residency(struct dmub_psr *dmub, uint32_t *residency)
305{
306 struct dmub_srv *srv = dmub->ctx->dmub_srv->dmub;
307
308
309 dmub_srv_send_gpint_command(srv, DMUB_GPINT__PSR_RESIDENCY, 0, 30);
310
311 dmub_srv_get_gpint_response(srv, residency);
312}
313
314static const struct dmub_psr_funcs psr_funcs = {
315 .psr_copy_settings = dmub_psr_copy_settings,
316 .psr_enable = dmub_psr_enable,
317 .psr_get_state = dmub_psr_get_state,
318 .psr_set_level = dmub_psr_set_level,
319 .psr_force_static = dmub_psr_force_static,
320 .psr_get_residency = dmub_psr_get_residency,
321};
322
323
324
325
326static void dmub_psr_construct(struct dmub_psr *psr, struct dc_context *ctx)
327{
328 psr->ctx = ctx;
329 psr->funcs = &psr_funcs;
330}
331
332
333
334
335struct dmub_psr *dmub_psr_create(struct dc_context *ctx)
336{
337 struct dmub_psr *psr = kzalloc(sizeof(struct dmub_psr), GFP_KERNEL);
338
339 if (psr == NULL) {
340 BREAK_TO_DEBUGGER();
341 return NULL;
342 }
343
344 dmub_psr_construct(psr, ctx);
345
346 return psr;
347}
348
349
350
351
352void dmub_psr_destroy(struct dmub_psr **dmub)
353{
354 kfree(*dmub);
355 *dmub = NULL;
356}
357