f1411a22cf1ecd95ec017bf321b86a4a8b0ff3e7
[linux-2.6-microblaze.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 DC_TRACE_LEVEL_MESSAGE(...)     do {} while (0) /* do nothing */
33
34 #define MAX_PIPES 6
35
36 /*
37  * Convert dmcub psr state to dmcu psr state.
38  */
39 static enum dc_psr_state convert_psr_state(uint32_t raw_state)
40 {
41         enum dc_psr_state state = PSR_STATE0;
42
43         if (raw_state == 0)
44                 state = PSR_STATE0;
45         else if (raw_state == 0x10)
46                 state = PSR_STATE1;
47         else if (raw_state == 0x11)
48                 state = PSR_STATE1a;
49         else if (raw_state == 0x20)
50                 state = PSR_STATE2;
51         else if (raw_state == 0x21)
52                 state = PSR_STATE2a;
53         else if (raw_state == 0x22)
54                 state = PSR_STATE2b;
55         else if (raw_state == 0x30)
56                 state = PSR_STATE3;
57         else if (raw_state == 0x31)
58                 state = PSR_STATE3Init;
59         else if (raw_state == 0x40)
60                 state = PSR_STATE4;
61         else if (raw_state == 0x41)
62                 state = PSR_STATE4a;
63         else if (raw_state == 0x42)
64                 state = PSR_STATE4b;
65         else if (raw_state == 0x43)
66                 state = PSR_STATE4c;
67         else if (raw_state == 0x44)
68                 state = PSR_STATE4d;
69         else if (raw_state == 0x50)
70                 state = PSR_STATE5;
71         else if (raw_state == 0x51)
72                 state = PSR_STATE5a;
73         else if (raw_state == 0x52)
74                 state = PSR_STATE5b;
75         else if (raw_state == 0x53)
76                 state = PSR_STATE5c;
77
78         return state;
79 }
80
81 /*
82  * Get PSR state from firmware.
83  */
84 static void dmub_psr_get_state(struct dmub_psr *dmub, enum dc_psr_state *state, uint8_t panel_inst)
85 {
86         struct dmub_srv *srv = dmub->ctx->dmub_srv->dmub;
87         uint32_t raw_state = 0;
88         uint32_t retry_count = 0;
89         enum dmub_status status;
90
91         do {
92                 // Send gpint command and wait for ack
93                 status = dmub_srv_send_gpint_command(srv, DMUB_GPINT__GET_PSR_STATE, panel_inst, 30);
94
95                 if (status == DMUB_STATUS_OK) {
96                         // GPINT was executed, get response
97                         dmub_srv_get_gpint_response(srv, &raw_state);
98                         *state = convert_psr_state(raw_state);
99                 } else
100                         // Return invalid state when GPINT times out
101                         *state = PSR_STATE_INVALID;
102
103         } while (++retry_count <= 1000 && *state == PSR_STATE_INVALID);
104
105         // Assert if max retry hit
106         if (retry_count >= 1000 && *state == PSR_STATE_INVALID) {
107                 ASSERT(0);
108                 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
109                                 WPP_BIT_FLAG_Firmware_PsrState,
110                                 "Unable to get PSR state from FW.");
111         } else
112                 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_VERBOSE,
113                                 WPP_BIT_FLAG_Firmware_PsrState,
114                                 "Got PSR state from FW. PSR state: %d, Retry count: %d",
115                                 *state, retry_count);
116 }
117
118 /*
119  * Set PSR version.
120  */
121 static bool dmub_psr_set_version(struct dmub_psr *dmub, struct dc_stream_state *stream, uint8_t panel_inst)
122 {
123         union dmub_rb_cmd cmd;
124         struct dc_context *dc = dmub->ctx;
125
126         if (stream->link->psr_settings.psr_version == DC_PSR_VERSION_UNSUPPORTED)
127                 return false;
128
129         memset(&cmd, 0, sizeof(cmd));
130         cmd.psr_set_version.header.type = DMUB_CMD__PSR;
131         cmd.psr_set_version.header.sub_type = DMUB_CMD__PSR_SET_VERSION;
132         switch (stream->link->psr_settings.psr_version) {
133         case DC_PSR_VERSION_1:
134                 cmd.psr_set_version.psr_set_version_data.version = PSR_VERSION_1;
135                 break;
136         case DC_PSR_VERSION_SU_1:
137                 cmd.psr_set_version.psr_set_version_data.version = PSR_VERSION_SU_1;
138                 break;
139         case DC_PSR_VERSION_UNSUPPORTED:
140         default:
141                 cmd.psr_set_version.psr_set_version_data.version = PSR_VERSION_UNSUPPORTED;
142                 break;
143         }
144
145         if (cmd.psr_set_version.psr_set_version_data.version == PSR_VERSION_UNSUPPORTED)
146                 return false;
147
148         cmd.psr_set_version.psr_set_version_data.cmd_version = DMUB_CMD_PSR_CONTROL_VERSION_1;
149         cmd.psr_set_version.psr_set_version_data.panel_inst = panel_inst;
150         cmd.psr_set_version.header.payload_bytes = sizeof(struct dmub_cmd_psr_set_version_data);
151
152         dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
153         dc_dmub_srv_cmd_execute(dc->dmub_srv);
154         dc_dmub_srv_wait_idle(dc->dmub_srv);
155
156         return true;
157 }
158
159 /*
160  * Enable/Disable PSR.
161  */
162 static void dmub_psr_enable(struct dmub_psr *dmub, bool enable, bool wait, uint8_t panel_inst)
163 {
164         union dmub_rb_cmd cmd;
165         struct dc_context *dc = dmub->ctx;
166         uint32_t retry_count;
167         enum dc_psr_state state = PSR_STATE0;
168
169         memset(&cmd, 0, sizeof(cmd));
170         cmd.psr_enable.header.type = DMUB_CMD__PSR;
171
172         cmd.psr_enable.data.cmd_version = DMUB_CMD_PSR_CONTROL_VERSION_1;
173         cmd.psr_enable.data.panel_inst = panel_inst;
174
175         if (enable)
176                 cmd.psr_enable.header.sub_type = DMUB_CMD__PSR_ENABLE;
177         else
178                 cmd.psr_enable.header.sub_type = DMUB_CMD__PSR_DISABLE;
179
180         cmd.psr_enable.header.payload_bytes = 0; // Send header only
181
182         dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
183         dc_dmub_srv_cmd_execute(dc->dmub_srv);
184         dc_dmub_srv_wait_idle(dc->dmub_srv);
185
186         /* Below loops 1000 x 500us = 500 ms.
187          *  Exit PSR may need to wait 1-2 frames to power up. Timeout after at
188          *  least a few frames. Should never hit the max retry assert below.
189          */
190         if (wait) {
191                 for (retry_count = 0; retry_count <= 1000; retry_count++) {
192                         dmub_psr_get_state(dmub, &state, panel_inst);
193
194                         if (enable) {
195                                 if (state != PSR_STATE0)
196                                         break;
197                         } else {
198                                 if (state == PSR_STATE0)
199                                         break;
200                         }
201
202                         udelay(500);
203                 }
204
205                 /* assert if max retry hit */
206                 if (retry_count >= 1000)
207                         ASSERT(0);
208         }
209 }
210
211 /*
212  * Set PSR level.
213  */
214 static void dmub_psr_set_level(struct dmub_psr *dmub, uint16_t psr_level, uint8_t panel_inst)
215 {
216         union dmub_rb_cmd cmd;
217         enum dc_psr_state state = PSR_STATE0;
218         struct dc_context *dc = dmub->ctx;
219
220         dmub_psr_get_state(dmub, &state, panel_inst);
221
222         if (state == PSR_STATE0)
223                 return;
224
225         memset(&cmd, 0, sizeof(cmd));
226         cmd.psr_set_level.header.type = DMUB_CMD__PSR;
227         cmd.psr_set_level.header.sub_type = DMUB_CMD__PSR_SET_LEVEL;
228         cmd.psr_set_level.header.payload_bytes = sizeof(struct dmub_cmd_psr_set_level_data);
229         cmd.psr_set_level.psr_set_level_data.psr_level = psr_level;
230         cmd.psr_set_level.psr_set_level_data.cmd_version = DMUB_CMD_PSR_CONTROL_VERSION_1;
231         cmd.psr_set_level.psr_set_level_data.panel_inst = panel_inst;
232         dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
233         dc_dmub_srv_cmd_execute(dc->dmub_srv);
234         dc_dmub_srv_wait_idle(dc->dmub_srv);
235 }
236
237 /*
238  * Set PSR power optimization flags.
239  */
240 static void dmub_psr_set_power_opt(struct dmub_psr *dmub, unsigned int power_opt, uint8_t panel_inst)
241 {
242         union dmub_rb_cmd cmd;
243         struct dc_context *dc = dmub->ctx;
244
245         memset(&cmd, 0, sizeof(cmd));
246         cmd.psr_set_power_opt.header.type = DMUB_CMD__PSR;
247         cmd.psr_set_power_opt.header.sub_type = DMUB_CMD__SET_PSR_POWER_OPT;
248         cmd.psr_set_power_opt.header.payload_bytes = sizeof(struct dmub_cmd_psr_set_power_opt_data);
249         cmd.psr_set_power_opt.psr_set_power_opt_data.cmd_version = DMUB_CMD_PSR_CONTROL_VERSION_1;
250         cmd.psr_set_power_opt.psr_set_power_opt_data.power_opt = power_opt;
251         cmd.psr_set_power_opt.psr_set_power_opt_data.panel_inst = panel_inst;
252
253         dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
254         dc_dmub_srv_cmd_execute(dc->dmub_srv);
255         dc_dmub_srv_wait_idle(dc->dmub_srv);
256 }
257
258 /*
259  * Setup PSR by programming phy registers and sending psr hw context values to firmware.
260  */
261 static bool dmub_psr_copy_settings(struct dmub_psr *dmub,
262                 struct dc_link *link,
263                 struct psr_context *psr_context,
264                 uint8_t panel_inst)
265 {
266         union dmub_rb_cmd cmd;
267         struct dc_context *dc = dmub->ctx;
268         struct dmub_cmd_psr_copy_settings_data *copy_settings_data
269                 = &cmd.psr_copy_settings.psr_copy_settings_data;
270         struct pipe_ctx *pipe_ctx = NULL;
271         struct resource_context *res_ctx = &link->ctx->dc->current_state->res_ctx;
272         int i = 0;
273
274         for (i = 0; i < MAX_PIPES; i++) {
275                 if (res_ctx->pipe_ctx[i].stream &&
276                     res_ctx->pipe_ctx[i].stream->link == link &&
277                     res_ctx->pipe_ctx[i].stream->link->connector_signal == SIGNAL_TYPE_EDP) {
278                         pipe_ctx = &res_ctx->pipe_ctx[i];
279                         //TODO: refactor for multi edp support
280                         break;
281                 }
282         }
283
284         if (!pipe_ctx)
285                 return false;
286
287         // First, set the psr version
288         if (!dmub_psr_set_version(dmub, pipe_ctx->stream, panel_inst))
289                 return false;
290
291         // Program DP DPHY fast training registers
292         link->link_enc->funcs->psr_program_dp_dphy_fast_training(link->link_enc,
293                         psr_context->psrExitLinkTrainingRequired);
294
295         // Program DP_SEC_CNTL1 register to set transmission GPS0 line num and priority to high
296         link->link_enc->funcs->psr_program_secondary_packet(link->link_enc,
297                         psr_context->sdpTransmitLineNumDeadline);
298
299         memset(&cmd, 0, sizeof(cmd));
300         cmd.psr_copy_settings.header.type = DMUB_CMD__PSR;
301         cmd.psr_copy_settings.header.sub_type = DMUB_CMD__PSR_COPY_SETTINGS;
302         cmd.psr_copy_settings.header.payload_bytes = sizeof(struct dmub_cmd_psr_copy_settings_data);
303
304         // Hw insts
305         copy_settings_data->dpphy_inst                          = psr_context->transmitterId;
306         copy_settings_data->aux_inst                            = psr_context->channel;
307         copy_settings_data->digfe_inst                          = psr_context->engineId;
308         copy_settings_data->digbe_inst                          = psr_context->transmitterId;
309
310         copy_settings_data->mpcc_inst                           = pipe_ctx->plane_res.mpcc_inst;
311
312         if (pipe_ctx->plane_res.dpp)
313                 copy_settings_data->dpp_inst                    = pipe_ctx->plane_res.dpp->inst;
314         else
315                 copy_settings_data->dpp_inst                    = 0;
316         if (pipe_ctx->stream_res.opp)
317                 copy_settings_data->opp_inst                    = pipe_ctx->stream_res.opp->inst;
318         else
319                 copy_settings_data->opp_inst                    = 0;
320         if (pipe_ctx->stream_res.tg)
321                 copy_settings_data->otg_inst                    = pipe_ctx->stream_res.tg->inst;
322         else
323                 copy_settings_data->otg_inst                    = 0;
324
325         // Misc
326         copy_settings_data->use_phy_fsm             = link->ctx->dc->debug.psr_power_use_phy_fsm;
327         copy_settings_data->psr_level                           = psr_context->psr_level.u32all;
328         copy_settings_data->smu_optimizations_en                = psr_context->allow_smu_optimizations;
329         copy_settings_data->multi_disp_optimizations_en = psr_context->allow_multi_disp_optimizations;
330         copy_settings_data->frame_delay                         = psr_context->frame_delay;
331         copy_settings_data->frame_cap_ind                       = psr_context->psrFrameCaptureIndicationReq;
332         copy_settings_data->init_sdp_deadline                   = psr_context->sdpTransmitLineNumDeadline;
333         copy_settings_data->debug.u32All = 0;
334         copy_settings_data->debug.bitfields.visual_confirm      = dc->dc->debug.visual_confirm == VISUAL_CONFIRM_PSR;
335         copy_settings_data->debug.bitfields.use_hw_lock_mgr             = 1;
336         copy_settings_data->fec_enable_status = (link->fec_state == dc_link_fec_enabled);
337         copy_settings_data->fec_enable_delay_in100us = link->dc->debug.fec_enable_delay_in100us;
338         copy_settings_data->cmd_version =  DMUB_CMD_PSR_CONTROL_VERSION_1;
339         copy_settings_data->panel_inst = panel_inst;
340         copy_settings_data->dsc_enable_status = (pipe_ctx->stream->timing.flags.DSC == 1);
341
342         if (link->fec_state == dc_link_fec_enabled &&
343                 (!memcmp(link->dpcd_caps.sink_dev_id_str, DP_SINK_DEVICE_STR_ID_1,
344                         sizeof(link->dpcd_caps.sink_dev_id_str)) ||
345                 !memcmp(link->dpcd_caps.sink_dev_id_str, DP_SINK_DEVICE_STR_ID_2,
346                         sizeof(link->dpcd_caps.sink_dev_id_str))))
347                 copy_settings_data->debug.bitfields.force_wakeup_by_tps3 = 1;
348         else
349                 copy_settings_data->debug.bitfields.force_wakeup_by_tps3 = 0;
350
351         dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
352         dc_dmub_srv_cmd_execute(dc->dmub_srv);
353         dc_dmub_srv_wait_idle(dc->dmub_srv);
354
355         return true;
356 }
357
358 /*
359  * Send command to PSR to force static ENTER and ignore all state changes until exit
360  */
361 static void dmub_psr_force_static(struct dmub_psr *dmub, uint8_t panel_inst)
362 {
363         union dmub_rb_cmd cmd;
364         struct dc_context *dc = dmub->ctx;
365
366         memset(&cmd, 0, sizeof(cmd));
367
368         cmd.psr_force_static.psr_force_static_data.panel_inst = panel_inst;
369         cmd.psr_force_static.psr_force_static_data.cmd_version = DMUB_CMD_PSR_CONTROL_VERSION_1;
370         cmd.psr_force_static.header.type = DMUB_CMD__PSR;
371         cmd.psr_force_static.header.sub_type = DMUB_CMD__PSR_FORCE_STATIC;
372         cmd.psr_enable.header.payload_bytes = 0;
373
374         dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
375         dc_dmub_srv_cmd_execute(dc->dmub_srv);
376         dc_dmub_srv_wait_idle(dc->dmub_srv);
377 }
378
379 /*
380  * Get PSR residency from firmware.
381  */
382 static void dmub_psr_get_residency(struct dmub_psr *dmub, uint32_t *residency, uint8_t panel_inst)
383 {
384         struct dmub_srv *srv = dmub->ctx->dmub_srv->dmub;
385         uint16_t param = (uint16_t)(panel_inst << 8);
386
387         /* Send gpint command and wait for ack */
388         dmub_srv_send_gpint_command(srv, DMUB_GPINT__PSR_RESIDENCY, param, 30);
389
390         dmub_srv_get_gpint_response(srv, residency);
391 }
392
393 static const struct dmub_psr_funcs psr_funcs = {
394         .psr_copy_settings              = dmub_psr_copy_settings,
395         .psr_enable                     = dmub_psr_enable,
396         .psr_get_state                  = dmub_psr_get_state,
397         .psr_set_level                  = dmub_psr_set_level,
398         .psr_force_static               = dmub_psr_force_static,
399         .psr_get_residency              = dmub_psr_get_residency,
400         .psr_set_power_opt              = dmub_psr_set_power_opt,
401 };
402
403 /*
404  * Construct PSR object.
405  */
406 static void dmub_psr_construct(struct dmub_psr *psr, struct dc_context *ctx)
407 {
408         psr->ctx = ctx;
409         psr->funcs = &psr_funcs;
410 }
411
412 /*
413  * Allocate and initialize PSR object.
414  */
415 struct dmub_psr *dmub_psr_create(struct dc_context *ctx)
416 {
417         struct dmub_psr *psr = kzalloc(sizeof(struct dmub_psr), GFP_KERNEL);
418
419         if (psr == NULL) {
420                 BREAK_TO_DEBUGGER();
421                 return NULL;
422         }
423
424         dmub_psr_construct(psr, ctx);
425
426         return psr;
427 }
428
429 /*
430  * Deallocate PSR object.
431  */
432 void dmub_psr_destroy(struct dmub_psr **dmub)
433 {
434         kfree(*dmub);
435         *dmub = NULL;
436 }