]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/blame - drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c
drm/amd/display: Drop unnecessary header file
[mirror_ubuntu-focal-kernel.git] / drivers / gpu / drm / amd / display / amdgpu_dm / amdgpu_dm_pp_smu.c
CommitLineData
f7c1ed34
ML
1/*
2 * Copyright 2018 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#include <linux/string.h>
25#include <linux/acpi.h>
26
27#include <drm/drmP.h>
28#include <drm/drm_crtc_helper.h>
29#include <drm/amdgpu_drm.h>
30#include "dm_services.h"
31#include "amdgpu.h"
32#include "amdgpu_dm.h"
33#include "amdgpu_dm_irq.h"
34#include "amdgpu_pm.h"
35#include "dm_pp_smu.h"
36#include "../../powerplay/inc/hwmgr.h"
f7c1ed34
ML
37
38
39bool dm_pp_apply_display_requirements(
40 const struct dc_context *ctx,
41 const struct dm_pp_display_configuration *pp_display_cfg)
42{
43 struct amdgpu_device *adev = ctx->driver_context;
44
45 if (adev->pm.dpm_enabled) {
46
47 memset(&adev->pm.pm_display_cfg, 0,
48 sizeof(adev->pm.pm_display_cfg));
49
50 adev->pm.pm_display_cfg.cpu_cc6_disable =
51 pp_display_cfg->cpu_cc6_disable;
52
53 adev->pm.pm_display_cfg.cpu_pstate_disable =
54 pp_display_cfg->cpu_pstate_disable;
55
56 adev->pm.pm_display_cfg.cpu_pstate_separation_time =
57 pp_display_cfg->cpu_pstate_separation_time;
58
59 adev->pm.pm_display_cfg.nb_pstate_switch_disable =
60 pp_display_cfg->nb_pstate_switch_disable;
61
62 adev->pm.pm_display_cfg.num_display =
63 pp_display_cfg->display_count;
64 adev->pm.pm_display_cfg.num_path_including_non_display =
65 pp_display_cfg->display_count;
66
67 adev->pm.pm_display_cfg.min_core_set_clock =
68 pp_display_cfg->min_engine_clock_khz/10;
69 adev->pm.pm_display_cfg.min_core_set_clock_in_sr =
70 pp_display_cfg->min_engine_clock_deep_sleep_khz/10;
71 adev->pm.pm_display_cfg.min_mem_set_clock =
72 pp_display_cfg->min_memory_clock_khz/10;
73
74 adev->pm.pm_display_cfg.multi_monitor_in_sync =
75 pp_display_cfg->all_displays_in_sync;
76 adev->pm.pm_display_cfg.min_vblank_time =
77 pp_display_cfg->avail_mclk_switch_time_us;
78
79 adev->pm.pm_display_cfg.display_clk =
80 pp_display_cfg->disp_clk_khz/10;
81
82 adev->pm.pm_display_cfg.dce_tolerable_mclk_in_active_latency =
83 pp_display_cfg->avail_mclk_switch_time_in_disp_active_us;
84
85 adev->pm.pm_display_cfg.crtc_index = pp_display_cfg->crtc_index;
86 adev->pm.pm_display_cfg.line_time_in_us =
87 pp_display_cfg->line_time_in_us;
88
89 adev->pm.pm_display_cfg.vrefresh = pp_display_cfg->disp_configs[0].v_refresh;
90 adev->pm.pm_display_cfg.crossfire_display_index = -1;
91 adev->pm.pm_display_cfg.min_bus_bandwidth = 0;
92
93 /* TODO: complete implementation of
94 * pp_display_configuration_change().
95 * Follow example of:
96 * PHM_StoreDALConfigurationData - powerplay\hwmgr\hardwaremanager.c
97 * PP_IRI_DisplayConfigurationChange - powerplay\eventmgr\iri.c */
98 if (adev->powerplay.pp_funcs->display_configuration_change)
99 adev->powerplay.pp_funcs->display_configuration_change(
100 adev->powerplay.pp_handle,
101 &adev->pm.pm_display_cfg);
102
103 /* TODO: replace by a separate call to 'apply display cfg'? */
104 amdgpu_pm_compute_clocks(adev);
105 }
106
107 return true;
108}
109
110static void get_default_clock_levels(
111 enum dm_pp_clock_type clk_type,
112 struct dm_pp_clock_levels *clks)
113{
114 uint32_t disp_clks_in_khz[6] = {
115 300000, 400000, 496560, 626090, 685720, 757900 };
116 uint32_t sclks_in_khz[6] = {
117 300000, 360000, 423530, 514290, 626090, 720000 };
118 uint32_t mclks_in_khz[2] = { 333000, 800000 };
119
120 switch (clk_type) {
121 case DM_PP_CLOCK_TYPE_DISPLAY_CLK:
122 clks->num_levels = 6;
123 memmove(clks->clocks_in_khz, disp_clks_in_khz,
124 sizeof(disp_clks_in_khz));
125 break;
126 case DM_PP_CLOCK_TYPE_ENGINE_CLK:
127 clks->num_levels = 6;
128 memmove(clks->clocks_in_khz, sclks_in_khz,
129 sizeof(sclks_in_khz));
130 break;
131 case DM_PP_CLOCK_TYPE_MEMORY_CLK:
132 clks->num_levels = 2;
133 memmove(clks->clocks_in_khz, mclks_in_khz,
134 sizeof(mclks_in_khz));
135 break;
136 default:
137 clks->num_levels = 0;
138 break;
139 }
140}
141
142static enum amd_pp_clock_type dc_to_pp_clock_type(
143 enum dm_pp_clock_type dm_pp_clk_type)
144{
145 enum amd_pp_clock_type amd_pp_clk_type = 0;
146
147 switch (dm_pp_clk_type) {
148 case DM_PP_CLOCK_TYPE_DISPLAY_CLK:
149 amd_pp_clk_type = amd_pp_disp_clock;
150 break;
151 case DM_PP_CLOCK_TYPE_ENGINE_CLK:
152 amd_pp_clk_type = amd_pp_sys_clock;
153 break;
154 case DM_PP_CLOCK_TYPE_MEMORY_CLK:
155 amd_pp_clk_type = amd_pp_mem_clock;
156 break;
157 case DM_PP_CLOCK_TYPE_DCEFCLK:
158 amd_pp_clk_type = amd_pp_dcef_clock;
159 break;
160 case DM_PP_CLOCK_TYPE_DCFCLK:
161 amd_pp_clk_type = amd_pp_dcf_clock;
162 break;
163 case DM_PP_CLOCK_TYPE_PIXELCLK:
164 amd_pp_clk_type = amd_pp_pixel_clock;
165 break;
166 case DM_PP_CLOCK_TYPE_FCLK:
167 amd_pp_clk_type = amd_pp_f_clock;
168 break;
169 case DM_PP_CLOCK_TYPE_DISPLAYPHYCLK:
170 amd_pp_clk_type = amd_pp_dpp_clock;
171 break;
172 default:
173 DRM_ERROR("DM_PPLIB: invalid clock type: %d!\n",
174 dm_pp_clk_type);
175 break;
176 }
177
178 return amd_pp_clk_type;
179}
180
181static void pp_to_dc_clock_levels(
182 const struct amd_pp_clocks *pp_clks,
183 struct dm_pp_clock_levels *dc_clks,
184 enum dm_pp_clock_type dc_clk_type)
185{
186 uint32_t i;
187
188 if (pp_clks->count > DM_PP_MAX_CLOCK_LEVELS) {
189 DRM_INFO("DM_PPLIB: Warning: %s clock: number of levels %d exceeds maximum of %d!\n",
190 DC_DECODE_PP_CLOCK_TYPE(dc_clk_type),
191 pp_clks->count,
192 DM_PP_MAX_CLOCK_LEVELS);
193
194 dc_clks->num_levels = DM_PP_MAX_CLOCK_LEVELS;
195 } else
196 dc_clks->num_levels = pp_clks->count;
197
198 DRM_INFO("DM_PPLIB: values for %s clock\n",
199 DC_DECODE_PP_CLOCK_TYPE(dc_clk_type));
200
201 for (i = 0; i < dc_clks->num_levels; i++) {
202 DRM_INFO("DM_PPLIB:\t %d\n", pp_clks->clock[i]);
203 /* translate 10kHz to kHz */
204 dc_clks->clocks_in_khz[i] = pp_clks->clock[i] * 10;
205 }
206}
207
208static void pp_to_dc_clock_levels_with_latency(
209 const struct pp_clock_levels_with_latency *pp_clks,
210 struct dm_pp_clock_levels_with_latency *clk_level_info,
211 enum dm_pp_clock_type dc_clk_type)
212{
213 uint32_t i;
214
215 if (pp_clks->num_levels > DM_PP_MAX_CLOCK_LEVELS) {
216 DRM_INFO("DM_PPLIB: Warning: %s clock: number of levels %d exceeds maximum of %d!\n",
217 DC_DECODE_PP_CLOCK_TYPE(dc_clk_type),
218 pp_clks->num_levels,
219 DM_PP_MAX_CLOCK_LEVELS);
220
221 clk_level_info->num_levels = DM_PP_MAX_CLOCK_LEVELS;
222 } else
223 clk_level_info->num_levels = pp_clks->num_levels;
224
225 DRM_DEBUG("DM_PPLIB: values for %s clock\n",
226 DC_DECODE_PP_CLOCK_TYPE(dc_clk_type));
227
228 for (i = 0; i < clk_level_info->num_levels; i++) {
229 DRM_DEBUG("DM_PPLIB:\t %d in 10kHz\n", pp_clks->data[i].clocks_in_khz);
230 /* translate 10kHz to kHz */
231 clk_level_info->data[i].clocks_in_khz = pp_clks->data[i].clocks_in_khz * 10;
232 clk_level_info->data[i].latency_in_us = pp_clks->data[i].latency_in_us;
233 }
234}
235
236static void pp_to_dc_clock_levels_with_voltage(
237 const struct pp_clock_levels_with_voltage *pp_clks,
238 struct dm_pp_clock_levels_with_voltage *clk_level_info,
239 enum dm_pp_clock_type dc_clk_type)
240{
241 uint32_t i;
242
243 if (pp_clks->num_levels > DM_PP_MAX_CLOCK_LEVELS) {
244 DRM_INFO("DM_PPLIB: Warning: %s clock: number of levels %d exceeds maximum of %d!\n",
245 DC_DECODE_PP_CLOCK_TYPE(dc_clk_type),
246 pp_clks->num_levels,
247 DM_PP_MAX_CLOCK_LEVELS);
248
249 clk_level_info->num_levels = DM_PP_MAX_CLOCK_LEVELS;
250 } else
251 clk_level_info->num_levels = pp_clks->num_levels;
252
253 DRM_INFO("DM_PPLIB: values for %s clock\n",
254 DC_DECODE_PP_CLOCK_TYPE(dc_clk_type));
255
256 for (i = 0; i < clk_level_info->num_levels; i++) {
257 DRM_INFO("DM_PPLIB:\t %d in 10kHz\n", pp_clks->data[i].clocks_in_khz);
258 /* translate 10kHz to kHz */
259 clk_level_info->data[i].clocks_in_khz = pp_clks->data[i].clocks_in_khz * 10;
260 clk_level_info->data[i].voltage_in_mv = pp_clks->data[i].voltage_in_mv;
261 }
262}
263
264bool dm_pp_get_clock_levels_by_type(
265 const struct dc_context *ctx,
266 enum dm_pp_clock_type clk_type,
267 struct dm_pp_clock_levels *dc_clks)
268{
269 struct amdgpu_device *adev = ctx->driver_context;
270 void *pp_handle = adev->powerplay.pp_handle;
271 struct amd_pp_clocks pp_clks = { 0 };
272 struct amd_pp_simple_clock_info validation_clks = { 0 };
273 uint32_t i;
274
275 if (adev->powerplay.pp_funcs->get_clock_by_type) {
276 if (adev->powerplay.pp_funcs->get_clock_by_type(pp_handle,
277 dc_to_pp_clock_type(clk_type), &pp_clks)) {
278 /* Error in pplib. Provide default values. */
279 get_default_clock_levels(clk_type, dc_clks);
280 return true;
281 }
282 }
283
284 pp_to_dc_clock_levels(&pp_clks, dc_clks, clk_type);
285
286 if (adev->powerplay.pp_funcs->get_display_mode_validation_clocks) {
287 if (adev->powerplay.pp_funcs->get_display_mode_validation_clocks(
288 pp_handle, &validation_clks)) {
289 /* Error in pplib. Provide default values. */
290 DRM_INFO("DM_PPLIB: Warning: using default validation clocks!\n");
291 validation_clks.engine_max_clock = 72000;
292 validation_clks.memory_max_clock = 80000;
293 validation_clks.level = 0;
294 }
295 }
296
297 DRM_INFO("DM_PPLIB: Validation clocks:\n");
298 DRM_INFO("DM_PPLIB: engine_max_clock: %d\n",
299 validation_clks.engine_max_clock);
300 DRM_INFO("DM_PPLIB: memory_max_clock: %d\n",
301 validation_clks.memory_max_clock);
302 DRM_INFO("DM_PPLIB: level : %d\n",
303 validation_clks.level);
304
305 /* Translate 10 kHz to kHz. */
306 validation_clks.engine_max_clock *= 10;
307 validation_clks.memory_max_clock *= 10;
308
309 /* Determine the highest non-boosted level from the Validation Clocks */
310 if (clk_type == DM_PP_CLOCK_TYPE_ENGINE_CLK) {
311 for (i = 0; i < dc_clks->num_levels; i++) {
312 if (dc_clks->clocks_in_khz[i] > validation_clks.engine_max_clock) {
313 /* This clock is higher the validation clock.
314 * Than means the previous one is the highest
315 * non-boosted one. */
316 DRM_INFO("DM_PPLIB: reducing engine clock level from %d to %d\n",
317 dc_clks->num_levels, i);
318 dc_clks->num_levels = i > 0 ? i : 1;
319 break;
320 }
321 }
322 } else if (clk_type == DM_PP_CLOCK_TYPE_MEMORY_CLK) {
323 for (i = 0; i < dc_clks->num_levels; i++) {
324 if (dc_clks->clocks_in_khz[i] > validation_clks.memory_max_clock) {
325 DRM_INFO("DM_PPLIB: reducing memory clock level from %d to %d\n",
326 dc_clks->num_levels, i);
327 dc_clks->num_levels = i > 0 ? i : 1;
328 break;
329 }
330 }
331 }
332
333 return true;
334}
335
336bool dm_pp_get_clock_levels_by_type_with_latency(
337 const struct dc_context *ctx,
338 enum dm_pp_clock_type clk_type,
339 struct dm_pp_clock_levels_with_latency *clk_level_info)
340{
341 struct amdgpu_device *adev = ctx->driver_context;
342 void *pp_handle = adev->powerplay.pp_handle;
343 struct pp_clock_levels_with_latency pp_clks = { 0 };
344 const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
345
346 if (!pp_funcs || !pp_funcs->get_clock_by_type_with_latency)
347 return false;
348
349 if (pp_funcs->get_clock_by_type_with_latency(pp_handle,
350 dc_to_pp_clock_type(clk_type),
351 &pp_clks))
352 return false;
353
354 pp_to_dc_clock_levels_with_latency(&pp_clks, clk_level_info, clk_type);
355
356 return true;
357}
358
359bool dm_pp_get_clock_levels_by_type_with_voltage(
360 const struct dc_context *ctx,
361 enum dm_pp_clock_type clk_type,
362 struct dm_pp_clock_levels_with_voltage *clk_level_info)
363{
364 struct amdgpu_device *adev = ctx->driver_context;
365 void *pp_handle = adev->powerplay.pp_handle;
366 struct pp_clock_levels_with_voltage pp_clk_info = {0};
367 const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
368
369 if (pp_funcs->get_clock_by_type_with_voltage(pp_handle,
370 dc_to_pp_clock_type(clk_type),
371 &pp_clk_info))
372 return false;
373
374 pp_to_dc_clock_levels_with_voltage(&pp_clk_info, clk_level_info, clk_type);
375
376 return true;
377}
378
379bool dm_pp_notify_wm_clock_changes(
380 const struct dc_context *ctx,
381 struct dm_pp_wm_sets_with_clock_ranges *wm_with_clock_ranges)
382{
383 /* TODO: to be implemented */
384 return false;
385}
386
387bool dm_pp_apply_power_level_change_request(
388 const struct dc_context *ctx,
389 struct dm_pp_power_level_change_request *level_change_req)
390{
391 /* TODO: to be implemented */
392 return false;
393}
394
395bool dm_pp_apply_clock_for_voltage_request(
396 const struct dc_context *ctx,
397 struct dm_pp_clock_for_voltage_req *clock_for_voltage_req)
398{
399 struct amdgpu_device *adev = ctx->driver_context;
400 struct pp_display_clock_request pp_clock_request = {0};
401 int ret = 0;
402
403 pp_clock_request.clock_type = dc_to_pp_clock_type(clock_for_voltage_req->clk_type);
404 pp_clock_request.clock_freq_in_khz = clock_for_voltage_req->clocks_in_khz;
405
406 if (!pp_clock_request.clock_type)
407 return false;
408
409 if (adev->powerplay.pp_funcs->display_clock_voltage_request)
410 ret = adev->powerplay.pp_funcs->display_clock_voltage_request(
411 adev->powerplay.pp_handle,
412 &pp_clock_request);
413 if (ret)
414 return false;
415 return true;
416}
417
418bool dm_pp_get_static_clocks(
419 const struct dc_context *ctx,
420 struct dm_pp_static_clock_info *static_clk_info)
421{
422 struct amdgpu_device *adev = ctx->driver_context;
423 struct amd_pp_clock_info pp_clk_info = {0};
424 int ret = 0;
425
426 if (adev->powerplay.pp_funcs->get_current_clocks)
427 ret = adev->powerplay.pp_funcs->get_current_clocks(
428 adev->powerplay.pp_handle,
429 &pp_clk_info);
430 if (ret)
431 return false;
432
433 static_clk_info->max_clocks_state = pp_clk_info.max_clocks_state;
434 /* translate 10kHz to kHz */
435 static_clk_info->max_mclk_khz = pp_clk_info.max_memory_clock * 10;
436 static_clk_info->max_sclk_khz = pp_clk_info.max_engine_clock * 10;
437
438 return true;
439}
440
441void pp_rv_set_display_requirement(struct pp_smu *pp,
442 struct pp_smu_display_requirement_rv *req)
443{
444 struct amdgpu_device *adev = pp->ctx->driver_context;
445 struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
446 int ret = 0;
447 if (hwmgr->hwmgr_func->set_deep_sleep_dcefclk)
448 ret = hwmgr->hwmgr_func->set_deep_sleep_dcefclk(hwmgr, req->hard_min_dcefclk_khz/10);
449 if (hwmgr->hwmgr_func->set_active_display_count)
450 ret = hwmgr->hwmgr_func->set_active_display_count(hwmgr, req->display_count);
451
452 //store_cc6 is not yet implemented in SMU level
453}
454
455void pp_rv_set_wm_ranges(struct pp_smu *pp,
456 struct pp_smu_wm_range_sets *ranges)
457{
458 struct amdgpu_device *adev = pp->ctx->driver_context;
459 struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
460 struct pp_wm_sets_with_clock_ranges_soc15 ranges_soc15 = {0};
461 int i = 0;
462
463 if (!hwmgr->hwmgr_func->set_watermarks_for_clocks_ranges ||
464 !pp || !ranges)
465 return;
466
467 //not entirely sure if thats a correct assignment
468 ranges_soc15.num_wm_sets_dmif = ranges->num_reader_wm_sets;
469 ranges_soc15.num_wm_sets_mcif = ranges->num_writer_wm_sets;
470
471 for (i = 0; i < ranges_soc15.num_wm_sets_dmif; i++) {
472 if (ranges->reader_wm_sets[i].wm_inst > 3)
473 ranges_soc15.wm_sets_dmif[i].wm_set_id = DC_WM_SET_A;
474 else
475 ranges_soc15.wm_sets_dmif[i].wm_set_id =
476 ranges->reader_wm_sets[i].wm_inst;
477 ranges_soc15.wm_sets_dmif[i].wm_max_dcefclk_in_khz =
478 ranges->reader_wm_sets[i].max_drain_clk_khz;
479 ranges_soc15.wm_sets_dmif[i].wm_min_dcefclk_in_khz =
480 ranges->reader_wm_sets[i].min_drain_clk_khz;
481 ranges_soc15.wm_sets_dmif[i].wm_max_memclk_in_khz =
482 ranges->reader_wm_sets[i].max_fill_clk_khz;
483 ranges_soc15.wm_sets_dmif[i].wm_min_memclk_in_khz =
484 ranges->reader_wm_sets[i].min_fill_clk_khz;
485 }
486
487 for (i = 0; i < ranges_soc15.num_wm_sets_mcif; i++) {
488 if (ranges->writer_wm_sets[i].wm_inst > 3)
489 ranges_soc15.wm_sets_dmif[i].wm_set_id = DC_WM_SET_A;
490 else
491 ranges_soc15.wm_sets_mcif[i].wm_set_id =
492 ranges->writer_wm_sets[i].wm_inst;
493 ranges_soc15.wm_sets_mcif[i].wm_max_socclk_in_khz =
494 ranges->writer_wm_sets[i].max_fill_clk_khz;
495 ranges_soc15.wm_sets_mcif[i].wm_min_socclk_in_khz =
496 ranges->writer_wm_sets[i].min_fill_clk_khz;
497 ranges_soc15.wm_sets_mcif[i].wm_max_memclk_in_khz =
498 ranges->writer_wm_sets[i].max_fill_clk_khz;
499 ranges_soc15.wm_sets_mcif[i].wm_min_memclk_in_khz =
500 ranges->writer_wm_sets[i].min_fill_clk_khz;
501 }
502
503 hwmgr->hwmgr_func->set_watermarks_for_clocks_ranges(hwmgr, &ranges_soc15);
504
505}
506
507void pp_rv_set_pme_wa_enable(struct pp_smu *pp)
508{
509 struct amdgpu_device *adev = pp->ctx->driver_context;
510 struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
511
512 if (hwmgr->hwmgr_func->smus_notify_pwe)
513 hwmgr->hwmgr_func->smus_notify_pwe(hwmgr);
514}
515
516void dm_pp_get_funcs_rv(
517 struct dc_context *ctx,
518 struct pp_smu_funcs_rv *funcs)
519{
520 funcs->pp_smu.ctx = ctx;
521 funcs->set_display_requirement = pp_rv_set_display_requirement;
522 funcs->set_wm_ranges = pp_rv_set_wm_ranges;
523 funcs->set_pme_wa_enable = pp_rv_set_pme_wa_enable;
524}