]> Git Repo - linux.git/blob - drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c
Merge tag 'trace-v5.13-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt...
[linux.git] / drivers / gpu / drm / amd / display / dc / dce / dmub_psr.c
1 /*
2  * Copyright 2019 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * Authors: AMD
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  * Convert dmcub psr state to dmcu psr state.
36  */
37 static 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  * Get PSR state from firmware.
79  */
80 static 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 = 0;
84         uint32_t retry_count = 0;
85         enum dmub_status status;
86
87         do {
88                 // Send gpint command and wait for ack
89                 status = dmub_srv_send_gpint_command(srv, DMUB_GPINT__GET_PSR_STATE, 0, 30);
90
91                 if (status == DMUB_STATUS_OK) {
92                         // GPINT was executed, get response
93                         dmub_srv_get_gpint_response(srv, &raw_state);
94                         *state = convert_psr_state(raw_state);
95                 } else
96                         // Return invalid state when GPINT times out
97                         *state = PSR_STATE_INVALID;
98
99                 // Assert if max retry hit
100                 if (retry_count >= 1000)
101                         ASSERT(0);
102         } while (++retry_count <= 1000 && *state == PSR_STATE_INVALID);
103 }
104
105 /*
106  * Set PSR version.
107  */
108 static bool dmub_psr_set_version(struct dmub_psr *dmub, struct dc_stream_state *stream)
109 {
110         union dmub_rb_cmd cmd;
111         struct dc_context *dc = dmub->ctx;
112
113         if (stream->link->psr_settings.psr_version == DC_PSR_VERSION_UNSUPPORTED)
114                 return false;
115
116         memset(&cmd, 0, sizeof(cmd));
117         cmd.psr_set_version.header.type = DMUB_CMD__PSR;
118         cmd.psr_set_version.header.sub_type = DMUB_CMD__PSR_SET_VERSION;
119         switch (stream->link->psr_settings.psr_version) {
120         case DC_PSR_VERSION_1:
121                 cmd.psr_set_version.psr_set_version_data.version = PSR_VERSION_1;
122                 break;
123         case DC_PSR_VERSION_UNSUPPORTED:
124         default:
125                 cmd.psr_set_version.psr_set_version_data.version = PSR_VERSION_UNSUPPORTED;
126                 break;
127         }
128         cmd.psr_set_version.header.payload_bytes = sizeof(struct dmub_cmd_psr_set_version_data);
129
130         dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
131         dc_dmub_srv_cmd_execute(dc->dmub_srv);
132         dc_dmub_srv_wait_idle(dc->dmub_srv);
133
134         return true;
135 }
136
137 /*
138  * Enable/Disable PSR.
139  */
140 static void dmub_psr_enable(struct dmub_psr *dmub, bool enable, bool wait)
141 {
142         union dmub_rb_cmd cmd;
143         struct dc_context *dc = dmub->ctx;
144         uint32_t retry_count;
145         enum dc_psr_state state = PSR_STATE0;
146
147         memset(&cmd, 0, sizeof(cmd));
148         cmd.psr_enable.header.type = DMUB_CMD__PSR;
149
150         if (enable)
151                 cmd.psr_enable.header.sub_type = DMUB_CMD__PSR_ENABLE;
152         else
153                 cmd.psr_enable.header.sub_type = DMUB_CMD__PSR_DISABLE;
154
155         cmd.psr_enable.header.payload_bytes = 0; // Send header only
156
157         dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
158         dc_dmub_srv_cmd_execute(dc->dmub_srv);
159         dc_dmub_srv_wait_idle(dc->dmub_srv);
160
161         /* Below loops 1000 x 500us = 500 ms.
162          *  Exit PSR may need to wait 1-2 frames to power up. Timeout after at
163          *  least a few frames. Should never hit the max retry assert below.
164          */
165         if (wait) {
166                 for (retry_count = 0; retry_count <= 1000; retry_count++) {
167                         dmub_psr_get_state(dmub, &state);
168
169                         if (enable) {
170                                 if (state != PSR_STATE0)
171                                         break;
172                         } else {
173                                 if (state == PSR_STATE0)
174                                         break;
175                         }
176
177                         udelay(500);
178                 }
179
180                 /* assert if max retry hit */
181                 if (retry_count >= 1000)
182                         ASSERT(0);
183         }
184 }
185
186 /*
187  * Set PSR level.
188  */
189 static void dmub_psr_set_level(struct dmub_psr *dmub, uint16_t psr_level)
190 {
191         union dmub_rb_cmd cmd;
192         enum dc_psr_state state = PSR_STATE0;
193         struct dc_context *dc = dmub->ctx;
194
195         dmub_psr_get_state(dmub, &state);
196
197         if (state == PSR_STATE0)
198                 return;
199
200         memset(&cmd, 0, sizeof(cmd));
201         cmd.psr_set_level.header.type = DMUB_CMD__PSR;
202         cmd.psr_set_level.header.sub_type = DMUB_CMD__PSR_SET_LEVEL;
203         cmd.psr_set_level.header.payload_bytes = sizeof(struct dmub_cmd_psr_set_level_data);
204         cmd.psr_set_level.psr_set_level_data.psr_level = psr_level;
205
206         dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
207         dc_dmub_srv_cmd_execute(dc->dmub_srv);
208         dc_dmub_srv_wait_idle(dc->dmub_srv);
209 }
210
211 /*
212  * Setup PSR by programming phy registers and sending psr hw context values to firmware.
213  */
214 static bool dmub_psr_copy_settings(struct dmub_psr *dmub,
215                 struct dc_link *link,
216                 struct psr_context *psr_context)
217 {
218         union dmub_rb_cmd cmd;
219         struct dc_context *dc = dmub->ctx;
220         struct dmub_cmd_psr_copy_settings_data *copy_settings_data
221                 = &cmd.psr_copy_settings.psr_copy_settings_data;
222         struct pipe_ctx *pipe_ctx = NULL;
223         struct resource_context *res_ctx = &link->ctx->dc->current_state->res_ctx;
224         int i = 0;
225
226         for (i = 0; i < MAX_PIPES; i++) {
227                 if (res_ctx->pipe_ctx[i].stream &&
228                     res_ctx->pipe_ctx[i].stream->link == link &&
229                     res_ctx->pipe_ctx[i].stream->link->connector_signal == SIGNAL_TYPE_EDP) {
230                         pipe_ctx = &res_ctx->pipe_ctx[i];
231                         //TODO: refactor for multi edp support
232                         break;
233                 }
234         }
235
236         if (!pipe_ctx)
237                 return false;
238
239         // First, set the psr version
240         if (!dmub_psr_set_version(dmub, pipe_ctx->stream))
241                 return false;
242
243         // Program DP DPHY fast training registers
244         link->link_enc->funcs->psr_program_dp_dphy_fast_training(link->link_enc,
245                         psr_context->psrExitLinkTrainingRequired);
246
247         // Program DP_SEC_CNTL1 register to set transmission GPS0 line num and priority to high
248         link->link_enc->funcs->psr_program_secondary_packet(link->link_enc,
249                         psr_context->sdpTransmitLineNumDeadline);
250
251         memset(&cmd, 0, sizeof(cmd));
252         cmd.psr_copy_settings.header.type = DMUB_CMD__PSR;
253         cmd.psr_copy_settings.header.sub_type = DMUB_CMD__PSR_COPY_SETTINGS;
254         cmd.psr_copy_settings.header.payload_bytes = sizeof(struct dmub_cmd_psr_copy_settings_data);
255
256         // Hw insts
257         copy_settings_data->dpphy_inst                          = psr_context->transmitterId;
258         copy_settings_data->aux_inst                            = psr_context->channel;
259         copy_settings_data->digfe_inst                          = psr_context->engineId;
260         copy_settings_data->digbe_inst                          = psr_context->transmitterId;
261
262         copy_settings_data->mpcc_inst                           = pipe_ctx->plane_res.mpcc_inst;
263
264         if (pipe_ctx->plane_res.dpp)
265                 copy_settings_data->dpp_inst                    = pipe_ctx->plane_res.dpp->inst;
266         else
267                 copy_settings_data->dpp_inst                    = 0;
268         if (pipe_ctx->stream_res.opp)
269                 copy_settings_data->opp_inst                    = pipe_ctx->stream_res.opp->inst;
270         else
271                 copy_settings_data->opp_inst                    = 0;
272         if (pipe_ctx->stream_res.tg)
273                 copy_settings_data->otg_inst                    = pipe_ctx->stream_res.tg->inst;
274         else
275                 copy_settings_data->otg_inst                    = 0;
276
277         // Misc
278         copy_settings_data->psr_level                           = psr_context->psr_level.u32all;
279         copy_settings_data->smu_optimizations_en                = psr_context->allow_smu_optimizations;
280         copy_settings_data->multi_disp_optimizations_en = psr_context->allow_multi_disp_optimizations;
281         copy_settings_data->frame_delay                         = psr_context->frame_delay;
282         copy_settings_data->frame_cap_ind                       = psr_context->psrFrameCaptureIndicationReq;
283         copy_settings_data->init_sdp_deadline                   = psr_context->sdpTransmitLineNumDeadline;
284         copy_settings_data->debug.u32All = 0;
285         copy_settings_data->debug.bitfields.visual_confirm      = dc->dc->debug.visual_confirm == VISUAL_CONFIRM_PSR;
286         copy_settings_data->debug.bitfields.use_hw_lock_mgr             = 1;
287         copy_settings_data->fec_enable_status = (link->fec_state == dc_link_fec_enabled);
288         copy_settings_data->fec_enable_delay_in100us = link->dc->debug.fec_enable_delay_in100us;
289
290         dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
291         dc_dmub_srv_cmd_execute(dc->dmub_srv);
292         dc_dmub_srv_wait_idle(dc->dmub_srv);
293
294         return true;
295 }
296
297 /*
298  * Send command to PSR to force static ENTER and ignore all state changes until exit
299  */
300 static void dmub_psr_force_static(struct dmub_psr *dmub)
301 {
302         union dmub_rb_cmd cmd;
303         struct dc_context *dc = dmub->ctx;
304
305         memset(&cmd, 0, sizeof(cmd));
306         cmd.psr_force_static.header.type = DMUB_CMD__PSR;
307         cmd.psr_force_static.header.sub_type = DMUB_CMD__PSR_FORCE_STATIC;
308         cmd.psr_enable.header.payload_bytes = 0;
309
310         dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
311         dc_dmub_srv_cmd_execute(dc->dmub_srv);
312         dc_dmub_srv_wait_idle(dc->dmub_srv);
313 }
314
315 /*
316  * Get PSR residency from firmware.
317  */
318 static void dmub_psr_get_residency(struct dmub_psr *dmub, uint32_t *residency)
319 {
320         struct dmub_srv *srv = dmub->ctx->dmub_srv->dmub;
321
322         // Send gpint command and wait for ack
323         dmub_srv_send_gpint_command(srv, DMUB_GPINT__PSR_RESIDENCY, 0, 30);
324
325         dmub_srv_get_gpint_response(srv, residency);
326 }
327
328 static const struct dmub_psr_funcs psr_funcs = {
329         .psr_copy_settings              = dmub_psr_copy_settings,
330         .psr_enable                     = dmub_psr_enable,
331         .psr_get_state                  = dmub_psr_get_state,
332         .psr_set_level                  = dmub_psr_set_level,
333         .psr_force_static               = dmub_psr_force_static,
334         .psr_get_residency              = dmub_psr_get_residency,
335 };
336
337 /*
338  * Construct PSR object.
339  */
340 static void dmub_psr_construct(struct dmub_psr *psr, struct dc_context *ctx)
341 {
342         psr->ctx = ctx;
343         psr->funcs = &psr_funcs;
344 }
345
346 /*
347  * Allocate and initialize PSR object.
348  */
349 struct dmub_psr *dmub_psr_create(struct dc_context *ctx)
350 {
351         struct dmub_psr *psr = kzalloc(sizeof(struct dmub_psr), GFP_KERNEL);
352
353         if (psr == NULL) {
354                 BREAK_TO_DEBUGGER();
355                 return NULL;
356         }
357
358         dmub_psr_construct(psr, ctx);
359
360         return psr;
361 }
362
363 /*
364  * Deallocate PSR object.
365  */
366 void dmub_psr_destroy(struct dmub_psr **dmub)
367 {
368         kfree(*dmub);
369         *dmub = NULL;
370 }
This page took 0.054752 seconds and 4 git commands to generate.