drm/amdgpu/display: remove VEGA20 config option
[platform/kernel/linux-rpi.git] / drivers / gpu / drm / amd / display / dc / dce / dce_clocks.c
1 /*
2  * Copyright 2012-16 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 "dce_clocks.h"
27 #include "dm_services.h"
28 #include "reg_helper.h"
29 #include "fixed32_32.h"
30 #include "bios_parser_interface.h"
31 #include "dc.h"
32 #include "dmcu.h"
33 #if defined(CONFIG_DRM_AMD_DC_DCN1_0)
34 #include "dcn_calcs.h"
35 #endif
36 #include "core_types.h"
37 #include "dc_types.h"
38 #include "dal_asic_id.h"
39
40 #define TO_DCE_CLOCKS(clocks)\
41         container_of(clocks, struct dce_disp_clk, base)
42
43 #define REG(reg) \
44         (clk_dce->regs->reg)
45
46 #undef FN
47 #define FN(reg_name, field_name) \
48         clk_dce->clk_shift->field_name, clk_dce->clk_mask->field_name
49
50 #define CTX \
51         clk_dce->base.ctx
52 #define DC_LOGGER \
53         clk->ctx->logger
54
55 /* Max clock values for each state indexed by "enum clocks_state": */
56 static const struct state_dependent_clocks dce80_max_clks_by_state[] = {
57 /* ClocksStateInvalid - should not be used */
58 { .display_clk_khz = 0, .pixel_clk_khz = 0 },
59 /* ClocksStateUltraLow - not expected to be used for DCE 8.0 */
60 { .display_clk_khz = 0, .pixel_clk_khz = 0 },
61 /* ClocksStateLow */
62 { .display_clk_khz = 352000, .pixel_clk_khz = 330000},
63 /* ClocksStateNominal */
64 { .display_clk_khz = 600000, .pixel_clk_khz = 400000 },
65 /* ClocksStatePerformance */
66 { .display_clk_khz = 600000, .pixel_clk_khz = 400000 } };
67
68 static const struct state_dependent_clocks dce110_max_clks_by_state[] = {
69 /*ClocksStateInvalid - should not be used*/
70 { .display_clk_khz = 0, .pixel_clk_khz = 0 },
71 /*ClocksStateUltraLow - currently by HW design team not supposed to be used*/
72 { .display_clk_khz = 352000, .pixel_clk_khz = 330000 },
73 /*ClocksStateLow*/
74 { .display_clk_khz = 352000, .pixel_clk_khz = 330000 },
75 /*ClocksStateNominal*/
76 { .display_clk_khz = 467000, .pixel_clk_khz = 400000 },
77 /*ClocksStatePerformance*/
78 { .display_clk_khz = 643000, .pixel_clk_khz = 400000 } };
79
80 static const struct state_dependent_clocks dce112_max_clks_by_state[] = {
81 /*ClocksStateInvalid - should not be used*/
82 { .display_clk_khz = 0, .pixel_clk_khz = 0 },
83 /*ClocksStateUltraLow - currently by HW design team not supposed to be used*/
84 { .display_clk_khz = 389189, .pixel_clk_khz = 346672 },
85 /*ClocksStateLow*/
86 { .display_clk_khz = 459000, .pixel_clk_khz = 400000 },
87 /*ClocksStateNominal*/
88 { .display_clk_khz = 667000, .pixel_clk_khz = 600000 },
89 /*ClocksStatePerformance*/
90 { .display_clk_khz = 1132000, .pixel_clk_khz = 600000 } };
91
92 static const struct state_dependent_clocks dce120_max_clks_by_state[] = {
93 /*ClocksStateInvalid - should not be used*/
94 { .display_clk_khz = 0, .pixel_clk_khz = 0 },
95 /*ClocksStateUltraLow - currently by HW design team not supposed to be used*/
96 { .display_clk_khz = 0, .pixel_clk_khz = 0 },
97 /*ClocksStateLow*/
98 { .display_clk_khz = 460000, .pixel_clk_khz = 400000 },
99 /*ClocksStateNominal*/
100 { .display_clk_khz = 670000, .pixel_clk_khz = 600000 },
101 /*ClocksStatePerformance*/
102 { .display_clk_khz = 1133000, .pixel_clk_khz = 600000 } };
103
104 /* Starting point for each divider range.*/
105 enum dce_divider_range_start {
106         DIVIDER_RANGE_01_START = 200, /* 2.00*/
107         DIVIDER_RANGE_02_START = 1600, /* 16.00*/
108         DIVIDER_RANGE_03_START = 3200, /* 32.00*/
109         DIVIDER_RANGE_SCALE_FACTOR = 100 /* Results are scaled up by 100.*/
110 };
111
112 /* Ranges for divider identifiers (Divider ID or DID)
113  mmDENTIST_DISPCLK_CNTL.DENTIST_DISPCLK_WDIVIDER*/
114 enum dce_divider_id_register_setting {
115         DIVIDER_RANGE_01_BASE_DIVIDER_ID = 0X08,
116         DIVIDER_RANGE_02_BASE_DIVIDER_ID = 0X40,
117         DIVIDER_RANGE_03_BASE_DIVIDER_ID = 0X60,
118         DIVIDER_RANGE_MAX_DIVIDER_ID = 0X80
119 };
120
121 /* Step size between each divider within a range.
122  Incrementing the DENTIST_DISPCLK_WDIVIDER by one
123  will increment the divider by this much.*/
124 enum dce_divider_range_step_size {
125         DIVIDER_RANGE_01_STEP_SIZE = 25, /* 0.25*/
126         DIVIDER_RANGE_02_STEP_SIZE = 50, /* 0.50*/
127         DIVIDER_RANGE_03_STEP_SIZE = 100 /* 1.00 */
128 };
129
130 static bool dce_divider_range_construct(
131         struct dce_divider_range *div_range,
132         int range_start,
133         int range_step,
134         int did_min,
135         int did_max)
136 {
137         div_range->div_range_start = range_start;
138         div_range->div_range_step = range_step;
139         div_range->did_min = did_min;
140         div_range->did_max = did_max;
141
142         if (div_range->div_range_step == 0) {
143                 div_range->div_range_step = 1;
144                 /*div_range_step cannot be zero*/
145                 BREAK_TO_DEBUGGER();
146         }
147         /* Calculate this based on the other inputs.*/
148         /* See DividerRange.h for explanation of */
149         /* the relationship between divider id (DID) and a divider.*/
150         /* Number of Divider IDs = (Maximum Divider ID - Minimum Divider ID)*/
151         /* Maximum divider identified in this range =
152          * (Number of Divider IDs)*Step size between dividers
153          *  + The start of this range.*/
154         div_range->div_range_end = (did_max - did_min) * range_step
155                 + range_start;
156         return true;
157 }
158
159 static int dce_divider_range_calc_divider(
160         struct dce_divider_range *div_range,
161         int did)
162 {
163         /* Is this DID within our range?*/
164         if ((did < div_range->did_min) || (did >= div_range->did_max))
165                 return INVALID_DIVIDER;
166
167         return ((did - div_range->did_min) * div_range->div_range_step)
168                         + div_range->div_range_start;
169
170 }
171
172 static int dce_divider_range_get_divider(
173         struct dce_divider_range *div_range,
174         int ranges_num,
175         int did)
176 {
177         int div = INVALID_DIVIDER;
178         int i;
179
180         for (i = 0; i < ranges_num; i++) {
181                 /* Calculate divider with given divider ID*/
182                 div = dce_divider_range_calc_divider(&div_range[i], did);
183                 /* Found a valid return divider*/
184                 if (div != INVALID_DIVIDER)
185                         break;
186         }
187         return div;
188 }
189
190 static int dce_clocks_get_dp_ref_freq(struct display_clock *clk)
191 {
192         struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk);
193         int dprefclk_wdivider;
194         int dprefclk_src_sel;
195         int dp_ref_clk_khz = 600000;
196         int target_div = INVALID_DIVIDER;
197
198         /* ASSERT DP Reference Clock source is from DFS*/
199         REG_GET(DPREFCLK_CNTL, DPREFCLK_SRC_SEL, &dprefclk_src_sel);
200         ASSERT(dprefclk_src_sel == 0);
201
202         /* Read the mmDENTIST_DISPCLK_CNTL to get the currently
203          * programmed DID DENTIST_DPREFCLK_WDIVIDER*/
204         REG_GET(DENTIST_DISPCLK_CNTL, DENTIST_DPREFCLK_WDIVIDER, &dprefclk_wdivider);
205
206         /* Convert DENTIST_DPREFCLK_WDIVIDERto actual divider*/
207         target_div = dce_divider_range_get_divider(
208                         clk_dce->divider_ranges,
209                         DIVIDER_RANGE_MAX,
210                         dprefclk_wdivider);
211
212         if (target_div != INVALID_DIVIDER) {
213                 /* Calculate the current DFS clock, in kHz.*/
214                 dp_ref_clk_khz = (DIVIDER_RANGE_SCALE_FACTOR
215                         * clk_dce->dentist_vco_freq_khz) / target_div;
216         }
217
218         /* SW will adjust DP REF Clock average value for all purposes
219          * (DP DTO / DP Audio DTO and DP GTC)
220          if clock is spread for all cases:
221          -if SS enabled on DP Ref clock and HW de-spreading enabled with SW
222          calculations for DS_INCR/DS_MODULO (this is planned to be default case)
223          -if SS enabled on DP Ref clock and HW de-spreading enabled with HW
224          calculations (not planned to be used, but average clock should still
225          be valid)
226          -if SS enabled on DP Ref clock and HW de-spreading disabled
227          (should not be case with CIK) then SW should program all rates
228          generated according to average value (case as with previous ASICs)
229           */
230         if (clk_dce->ss_on_dprefclk && clk_dce->dprefclk_ss_divider != 0) {
231                 struct fixed32_32 ss_percentage = dal_fixed32_32_div_int(
232                                 dal_fixed32_32_from_fraction(
233                                                 clk_dce->dprefclk_ss_percentage,
234                                                 clk_dce->dprefclk_ss_divider), 200);
235                 struct fixed32_32 adj_dp_ref_clk_khz;
236
237                 ss_percentage = dal_fixed32_32_sub(dal_fixed32_32_one,
238                                                                 ss_percentage);
239                 adj_dp_ref_clk_khz =
240                         dal_fixed32_32_mul_int(
241                                 ss_percentage,
242                                 dp_ref_clk_khz);
243                 dp_ref_clk_khz = dal_fixed32_32_floor(adj_dp_ref_clk_khz);
244         }
245
246         return dp_ref_clk_khz;
247 }
248
249 /* TODO: This is DCN DPREFCLK: it could be program by DENTIST by VBIOS
250  * or CLK0_CLK11 by SMU. For DCE120, it is wlays 600Mhz. Will re-visit
251  * clock implementation
252  */
253 static int dce_clocks_get_dp_ref_freq_wrkaround(struct display_clock *clk)
254 {
255         struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk);
256         int dp_ref_clk_khz = 600000;
257
258         if (clk_dce->ss_on_dprefclk && clk_dce->dprefclk_ss_divider != 0) {
259                 struct fixed32_32 ss_percentage = dal_fixed32_32_div_int(
260                                 dal_fixed32_32_from_fraction(
261                                                 clk_dce->dprefclk_ss_percentage,
262                                                 clk_dce->dprefclk_ss_divider), 200);
263                 struct fixed32_32 adj_dp_ref_clk_khz;
264
265                 ss_percentage = dal_fixed32_32_sub(dal_fixed32_32_one,
266                                                                 ss_percentage);
267                 adj_dp_ref_clk_khz =
268                         dal_fixed32_32_mul_int(
269                                 ss_percentage,
270                                 dp_ref_clk_khz);
271                 dp_ref_clk_khz = dal_fixed32_32_floor(adj_dp_ref_clk_khz);
272         }
273
274         return dp_ref_clk_khz;
275 }
276 static enum dm_pp_clocks_state dce_get_required_clocks_state(
277         struct display_clock *clk,
278         struct state_dependent_clocks *req_clocks)
279 {
280         struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk);
281         int i;
282         enum dm_pp_clocks_state low_req_clk;
283
284         /* Iterate from highest supported to lowest valid state, and update
285          * lowest RequiredState with the lowest state that satisfies
286          * all required clocks
287          */
288         for (i = clk->max_clks_state; i >= DM_PP_CLOCKS_STATE_ULTRA_LOW; i--)
289                 if (req_clocks->display_clk_khz >
290                                 clk_dce->max_clks_by_state[i].display_clk_khz
291                         || req_clocks->pixel_clk_khz >
292                                 clk_dce->max_clks_by_state[i].pixel_clk_khz)
293                         break;
294
295         low_req_clk = i + 1;
296         if (low_req_clk > clk->max_clks_state) {
297                 DC_LOG_WARNING("%s: clocks unsupported disp_clk %d pix_clk %d",
298                                 __func__,
299                                 req_clocks->display_clk_khz,
300                                 req_clocks->pixel_clk_khz);
301                 low_req_clk = DM_PP_CLOCKS_STATE_INVALID;
302         }
303
304         return low_req_clk;
305 }
306
307 static bool dce_clock_set_min_clocks_state(
308         struct display_clock *clk,
309         enum dm_pp_clocks_state clocks_state)
310 {
311         struct dm_pp_power_level_change_request level_change_req = {
312                         clocks_state };
313
314         if (clocks_state > clk->max_clks_state) {
315                 /*Requested state exceeds max supported state.*/
316                 DC_LOG_WARNING("Requested state exceeds max supported state");
317                 return false;
318         } else if (clocks_state == clk->cur_min_clks_state) {
319                 /*if we're trying to set the same state, we can just return
320                  * since nothing needs to be done*/
321                 return true;
322         }
323
324         /* get max clock state from PPLIB */
325         if (dm_pp_apply_power_level_change_request(clk->ctx, &level_change_req))
326                 clk->cur_min_clks_state = clocks_state;
327
328         return true;
329 }
330
331 static int dce_set_clock(
332         struct display_clock *clk,
333         int requested_clk_khz)
334 {
335         struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk);
336         struct bp_pixel_clock_parameters pxl_clk_params = { 0 };
337         struct dc_bios *bp = clk->ctx->dc_bios;
338         int actual_clock = requested_clk_khz;
339
340         /* Make sure requested clock isn't lower than minimum threshold*/
341         if (requested_clk_khz > 0)
342                 requested_clk_khz = max(requested_clk_khz,
343                                 clk_dce->dentist_vco_freq_khz / 64);
344
345         /* Prepare to program display clock*/
346         pxl_clk_params.target_pixel_clock = requested_clk_khz;
347         pxl_clk_params.pll_id = CLOCK_SOURCE_ID_DFS;
348
349         bp->funcs->program_display_engine_pll(bp, &pxl_clk_params);
350
351         if (clk_dce->dfs_bypass_enabled) {
352
353                 /* Cache the fixed display clock*/
354                 clk_dce->dfs_bypass_disp_clk =
355                         pxl_clk_params.dfs_bypass_display_clock;
356                 actual_clock = pxl_clk_params.dfs_bypass_display_clock;
357         }
358
359         /* from power down, we need mark the clock state as ClocksStateNominal
360          * from HWReset, so when resume we will call pplib voltage regulator.*/
361         if (requested_clk_khz == 0)
362                 clk->cur_min_clks_state = DM_PP_CLOCKS_STATE_NOMINAL;
363         return actual_clock;
364 }
365
366 static int dce_psr_set_clock(
367         struct display_clock *clk,
368         int requested_clk_khz)
369 {
370         struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk);
371         struct dc_context *ctx = clk_dce->base.ctx;
372         struct dc *core_dc = ctx->dc;
373         struct dmcu *dmcu = core_dc->res_pool->dmcu;
374         int actual_clk_khz = requested_clk_khz;
375
376         actual_clk_khz = dce_set_clock(clk, requested_clk_khz);
377
378         dmcu->funcs->set_psr_wait_loop(dmcu, actual_clk_khz / 1000 / 7);
379         return actual_clk_khz;
380 }
381
382 static int dce112_set_clock(
383         struct display_clock *clk,
384         int requested_clk_khz)
385 {
386         struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk);
387         struct bp_set_dce_clock_parameters dce_clk_params;
388         struct dc_bios *bp = clk->ctx->dc_bios;
389         struct dc *core_dc = clk->ctx->dc;
390         struct dmcu *dmcu = core_dc->res_pool->dmcu;
391         int actual_clock = requested_clk_khz;
392         /* Prepare to program display clock*/
393         memset(&dce_clk_params, 0, sizeof(dce_clk_params));
394
395         /* Make sure requested clock isn't lower than minimum threshold*/
396         if (requested_clk_khz > 0)
397                 requested_clk_khz = max(requested_clk_khz,
398                                 clk_dce->dentist_vco_freq_khz / 62);
399
400         dce_clk_params.target_clock_frequency = requested_clk_khz;
401         dce_clk_params.pll_id = CLOCK_SOURCE_ID_DFS;
402         dce_clk_params.clock_type = DCECLOCK_TYPE_DISPLAY_CLOCK;
403
404         bp->funcs->set_dce_clock(bp, &dce_clk_params);
405         actual_clock = dce_clk_params.target_clock_frequency;
406
407         /* from power down, we need mark the clock state as ClocksStateNominal
408          * from HWReset, so when resume we will call pplib voltage regulator.*/
409         if (requested_clk_khz == 0)
410                 clk->cur_min_clks_state = DM_PP_CLOCKS_STATE_NOMINAL;
411
412         /*Program DP ref Clock*/
413         /*VBIOS will determine DPREFCLK frequency, so we don't set it*/
414         dce_clk_params.target_clock_frequency = 0;
415         dce_clk_params.clock_type = DCECLOCK_TYPE_DPREFCLK;
416         if (!ASICREV_IS_VEGA20_P(clk->ctx->asic_id.hw_internal_rev))
417                 dce_clk_params.flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK =
418                         (dce_clk_params.pll_id ==
419                                         CLOCK_SOURCE_COMBO_DISPLAY_PLL0);
420         else
421                 dce_clk_params.flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK = false;
422
423         bp->funcs->set_dce_clock(bp, &dce_clk_params);
424
425         if (!IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment)) {
426                 if (clk_dce->dfs_bypass_disp_clk != actual_clock)
427                         dmcu->funcs->set_psr_wait_loop(dmcu,
428                                         actual_clock / 1000 / 7);
429         }
430
431         clk_dce->dfs_bypass_disp_clk = actual_clock;
432         return actual_clock;
433 }
434
435 static void dce_clock_read_integrated_info(struct dce_disp_clk *clk_dce)
436 {
437         struct dc_debug *debug = &clk_dce->base.ctx->dc->debug;
438         struct dc_bios *bp = clk_dce->base.ctx->dc_bios;
439         struct integrated_info info = { { { 0 } } };
440         struct dc_firmware_info fw_info = { { 0 } };
441         int i;
442
443         if (bp->integrated_info)
444                 info = *bp->integrated_info;
445
446         clk_dce->dentist_vco_freq_khz = info.dentist_vco_freq;
447         if (clk_dce->dentist_vco_freq_khz == 0) {
448                 bp->funcs->get_firmware_info(bp, &fw_info);
449                 clk_dce->dentist_vco_freq_khz =
450                         fw_info.smu_gpu_pll_output_freq;
451                 if (clk_dce->dentist_vco_freq_khz == 0)
452                         clk_dce->dentist_vco_freq_khz = 3600000;
453         }
454
455         /*update the maximum display clock for each power state*/
456         for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
457                 enum dm_pp_clocks_state clk_state = DM_PP_CLOCKS_STATE_INVALID;
458
459                 switch (i) {
460                 case 0:
461                         clk_state = DM_PP_CLOCKS_STATE_ULTRA_LOW;
462                         break;
463
464                 case 1:
465                         clk_state = DM_PP_CLOCKS_STATE_LOW;
466                         break;
467
468                 case 2:
469                         clk_state = DM_PP_CLOCKS_STATE_NOMINAL;
470                         break;
471
472                 case 3:
473                         clk_state = DM_PP_CLOCKS_STATE_PERFORMANCE;
474                         break;
475
476                 default:
477                         clk_state = DM_PP_CLOCKS_STATE_INVALID;
478                         break;
479                 }
480
481                 /*Do not allow bad VBIOS/SBIOS to override with invalid values,
482                  * check for > 100MHz*/
483                 if (info.disp_clk_voltage[i].max_supported_clk >= 100000)
484                         clk_dce->max_clks_by_state[clk_state].display_clk_khz =
485                                 info.disp_clk_voltage[i].max_supported_clk;
486         }
487
488         if (!debug->disable_dfs_bypass && bp->integrated_info)
489                 if (bp->integrated_info->gpu_cap_info & DFS_BYPASS_ENABLE)
490                         clk_dce->dfs_bypass_enabled = true;
491
492         clk_dce->use_max_disp_clk = debug->max_disp_clk;
493 }
494
495 static void dce_clock_read_ss_info(struct dce_disp_clk *clk_dce)
496 {
497         struct dc_bios *bp = clk_dce->base.ctx->dc_bios;
498         int ss_info_num = bp->funcs->get_ss_entry_number(
499                         bp, AS_SIGNAL_TYPE_GPU_PLL);
500
501         if (ss_info_num) {
502                 struct spread_spectrum_info info = { { 0 } };
503                 enum bp_result result = bp->funcs->get_spread_spectrum_info(
504                                 bp, AS_SIGNAL_TYPE_GPU_PLL, 0, &info);
505
506                 /* Based on VBIOS, VBIOS will keep entry for GPU PLL SS
507                  * even if SS not enabled and in that case
508                  * SSInfo.spreadSpectrumPercentage !=0 would be sign
509                  * that SS is enabled
510                  */
511                 if (result == BP_RESULT_OK &&
512                                 info.spread_spectrum_percentage != 0) {
513                         clk_dce->ss_on_dprefclk = true;
514                         clk_dce->dprefclk_ss_divider = info.spread_percentage_divider;
515
516                         if (info.type.CENTER_MODE == 0) {
517                                 /* TODO: Currently for DP Reference clock we
518                                  * need only SS percentage for
519                                  * downspread */
520                                 clk_dce->dprefclk_ss_percentage =
521                                                 info.spread_spectrum_percentage;
522                         }
523
524                         return;
525                 }
526
527                 result = bp->funcs->get_spread_spectrum_info(
528                                 bp, AS_SIGNAL_TYPE_DISPLAY_PORT, 0, &info);
529
530                 /* Based on VBIOS, VBIOS will keep entry for DPREFCLK SS
531                  * even if SS not enabled and in that case
532                  * SSInfo.spreadSpectrumPercentage !=0 would be sign
533                  * that SS is enabled
534                  */
535                 if (result == BP_RESULT_OK &&
536                                 info.spread_spectrum_percentage != 0) {
537                         clk_dce->ss_on_dprefclk = true;
538                         clk_dce->dprefclk_ss_divider = info.spread_percentage_divider;
539
540                         if (info.type.CENTER_MODE == 0) {
541                                 /* Currently for DP Reference clock we
542                                  * need only SS percentage for
543                                  * downspread */
544                                 clk_dce->dprefclk_ss_percentage =
545                                                 info.spread_spectrum_percentage;
546                         }
547                 }
548         }
549 }
550
551 static bool dce_apply_clock_voltage_request(
552         struct display_clock *clk,
553         enum dm_pp_clock_type clocks_type,
554         int clocks_in_khz,
555         bool pre_mode_set,
556         bool update_dp_phyclk)
557 {
558         bool send_request = false;
559         struct dm_pp_clock_for_voltage_req clock_voltage_req = {0};
560
561         switch (clocks_type) {
562         case DM_PP_CLOCK_TYPE_DISPLAY_CLK:
563         case DM_PP_CLOCK_TYPE_PIXELCLK:
564         case DM_PP_CLOCK_TYPE_DISPLAYPHYCLK:
565                 break;
566         default:
567                 BREAK_TO_DEBUGGER();
568                 return false;
569         }
570
571         clock_voltage_req.clk_type = clocks_type;
572         clock_voltage_req.clocks_in_khz = clocks_in_khz;
573
574         /* to pplib */
575         if (pre_mode_set) {
576                 switch (clocks_type) {
577                 case DM_PP_CLOCK_TYPE_DISPLAY_CLK:
578                         if (clocks_in_khz > clk->cur_clocks_value.dispclk_in_khz) {
579                                 clk->cur_clocks_value.dispclk_notify_pplib_done = true;
580                                 send_request = true;
581                         } else
582                                 clk->cur_clocks_value.dispclk_notify_pplib_done = false;
583                         /* no matter incrase or decrase clock, update current clock value */
584                         clk->cur_clocks_value.dispclk_in_khz = clocks_in_khz;
585                         break;
586                 case DM_PP_CLOCK_TYPE_PIXELCLK:
587                         if (clocks_in_khz > clk->cur_clocks_value.max_pixelclk_in_khz) {
588                                 clk->cur_clocks_value.pixelclk_notify_pplib_done = true;
589                                 send_request = true;
590                         } else
591                                 clk->cur_clocks_value.pixelclk_notify_pplib_done = false;
592                         /* no matter incrase or decrase clock, update current clock value */
593                         clk->cur_clocks_value.max_pixelclk_in_khz = clocks_in_khz;
594                         break;
595                 case DM_PP_CLOCK_TYPE_DISPLAYPHYCLK:
596                         if (clocks_in_khz > clk->cur_clocks_value.max_non_dp_phyclk_in_khz) {
597                                 clk->cur_clocks_value.phyclk_notigy_pplib_done = true;
598                                 send_request = true;
599                         } else
600                                 clk->cur_clocks_value.phyclk_notigy_pplib_done = false;
601                         /* no matter incrase or decrase clock, update current clock value */
602                         clk->cur_clocks_value.max_non_dp_phyclk_in_khz = clocks_in_khz;
603                         break;
604                 default:
605                         ASSERT(0);
606                         break;
607                 }
608
609         } else {
610                 switch (clocks_type) {
611                 case DM_PP_CLOCK_TYPE_DISPLAY_CLK:
612                         if (!clk->cur_clocks_value.dispclk_notify_pplib_done)
613                                 send_request = true;
614                         break;
615                 case DM_PP_CLOCK_TYPE_PIXELCLK:
616                         if (!clk->cur_clocks_value.pixelclk_notify_pplib_done)
617                                 send_request = true;
618                         break;
619                 case DM_PP_CLOCK_TYPE_DISPLAYPHYCLK:
620                         if (!clk->cur_clocks_value.phyclk_notigy_pplib_done)
621                                 send_request = true;
622                         break;
623                 default:
624                         ASSERT(0);
625                         break;
626                 }
627         }
628         if (send_request) {
629 #if defined(CONFIG_DRM_AMD_DC_DCN1_0)
630                 if (clk->ctx->dce_version >= DCN_VERSION_1_0) {
631                         struct dc *core_dc = clk->ctx->dc;
632                         /*use dcfclk request voltage*/
633                         clock_voltage_req.clk_type = DM_PP_CLOCK_TYPE_DCFCLK;
634                         clock_voltage_req.clocks_in_khz =
635                                 dcn_find_dcfclk_suits_all(core_dc, &clk->cur_clocks_value);
636                 }
637 #endif
638                 dm_pp_apply_clock_for_voltage_request(
639                         clk->ctx, &clock_voltage_req);
640         }
641         if (update_dp_phyclk && (clocks_in_khz >
642         clk->cur_clocks_value.max_dp_phyclk_in_khz))
643                 clk->cur_clocks_value.max_dp_phyclk_in_khz = clocks_in_khz;
644
645         return true;
646 }
647
648
649 static const struct display_clock_funcs dce120_funcs = {
650         .get_dp_ref_clk_frequency = dce_clocks_get_dp_ref_freq_wrkaround,
651         .apply_clock_voltage_request = dce_apply_clock_voltage_request,
652         .set_clock = dce112_set_clock
653 };
654
655 static const struct display_clock_funcs dce112_funcs = {
656         .get_dp_ref_clk_frequency = dce_clocks_get_dp_ref_freq,
657         .get_required_clocks_state = dce_get_required_clocks_state,
658         .set_min_clocks_state = dce_clock_set_min_clocks_state,
659         .set_clock = dce112_set_clock
660 };
661
662 static const struct display_clock_funcs dce110_funcs = {
663         .get_dp_ref_clk_frequency = dce_clocks_get_dp_ref_freq,
664         .get_required_clocks_state = dce_get_required_clocks_state,
665         .set_min_clocks_state = dce_clock_set_min_clocks_state,
666         .set_clock = dce_psr_set_clock
667 };
668
669 static const struct display_clock_funcs dce_funcs = {
670         .get_dp_ref_clk_frequency = dce_clocks_get_dp_ref_freq,
671         .get_required_clocks_state = dce_get_required_clocks_state,
672         .set_min_clocks_state = dce_clock_set_min_clocks_state,
673         .set_clock = dce_set_clock
674 };
675
676 static void dce_disp_clk_construct(
677         struct dce_disp_clk *clk_dce,
678         struct dc_context *ctx,
679         const struct dce_disp_clk_registers *regs,
680         const struct dce_disp_clk_shift *clk_shift,
681         const struct dce_disp_clk_mask *clk_mask)
682 {
683         struct display_clock *base = &clk_dce->base;
684
685         base->ctx = ctx;
686         base->funcs = &dce_funcs;
687
688         clk_dce->regs = regs;
689         clk_dce->clk_shift = clk_shift;
690         clk_dce->clk_mask = clk_mask;
691
692         clk_dce->dfs_bypass_disp_clk = 0;
693
694         clk_dce->dprefclk_ss_percentage = 0;
695         clk_dce->dprefclk_ss_divider = 1000;
696         clk_dce->ss_on_dprefclk = false;
697
698         base->max_clks_state = DM_PP_CLOCKS_STATE_NOMINAL;
699         base->cur_min_clks_state = DM_PP_CLOCKS_STATE_INVALID;
700
701         dce_clock_read_integrated_info(clk_dce);
702         dce_clock_read_ss_info(clk_dce);
703
704         dce_divider_range_construct(
705                 &clk_dce->divider_ranges[DIVIDER_RANGE_01],
706                 DIVIDER_RANGE_01_START,
707                 DIVIDER_RANGE_01_STEP_SIZE,
708                 DIVIDER_RANGE_01_BASE_DIVIDER_ID,
709                 DIVIDER_RANGE_02_BASE_DIVIDER_ID);
710         dce_divider_range_construct(
711                 &clk_dce->divider_ranges[DIVIDER_RANGE_02],
712                 DIVIDER_RANGE_02_START,
713                 DIVIDER_RANGE_02_STEP_SIZE,
714                 DIVIDER_RANGE_02_BASE_DIVIDER_ID,
715                 DIVIDER_RANGE_03_BASE_DIVIDER_ID);
716         dce_divider_range_construct(
717                 &clk_dce->divider_ranges[DIVIDER_RANGE_03],
718                 DIVIDER_RANGE_03_START,
719                 DIVIDER_RANGE_03_STEP_SIZE,
720                 DIVIDER_RANGE_03_BASE_DIVIDER_ID,
721                 DIVIDER_RANGE_MAX_DIVIDER_ID);
722 }
723
724 struct display_clock *dce_disp_clk_create(
725         struct dc_context *ctx,
726         const struct dce_disp_clk_registers *regs,
727         const struct dce_disp_clk_shift *clk_shift,
728         const struct dce_disp_clk_mask *clk_mask)
729 {
730         struct dce_disp_clk *clk_dce = kzalloc(sizeof(*clk_dce), GFP_KERNEL);
731
732         if (clk_dce == NULL) {
733                 BREAK_TO_DEBUGGER();
734                 return NULL;
735         }
736
737         memcpy(clk_dce->max_clks_by_state,
738                 dce80_max_clks_by_state,
739                 sizeof(dce80_max_clks_by_state));
740
741         dce_disp_clk_construct(
742                 clk_dce, ctx, regs, clk_shift, clk_mask);
743
744         return &clk_dce->base;
745 }
746
747 struct display_clock *dce110_disp_clk_create(
748         struct dc_context *ctx,
749         const struct dce_disp_clk_registers *regs,
750         const struct dce_disp_clk_shift *clk_shift,
751         const struct dce_disp_clk_mask *clk_mask)
752 {
753         struct dce_disp_clk *clk_dce = kzalloc(sizeof(*clk_dce), GFP_KERNEL);
754
755         if (clk_dce == NULL) {
756                 BREAK_TO_DEBUGGER();
757                 return NULL;
758         }
759
760         memcpy(clk_dce->max_clks_by_state,
761                 dce110_max_clks_by_state,
762                 sizeof(dce110_max_clks_by_state));
763
764         dce_disp_clk_construct(
765                 clk_dce, ctx, regs, clk_shift, clk_mask);
766
767         clk_dce->base.funcs = &dce110_funcs;
768
769         return &clk_dce->base;
770 }
771
772 struct display_clock *dce112_disp_clk_create(
773         struct dc_context *ctx,
774         const struct dce_disp_clk_registers *regs,
775         const struct dce_disp_clk_shift *clk_shift,
776         const struct dce_disp_clk_mask *clk_mask)
777 {
778         struct dce_disp_clk *clk_dce = kzalloc(sizeof(*clk_dce), GFP_KERNEL);
779
780         if (clk_dce == NULL) {
781                 BREAK_TO_DEBUGGER();
782                 return NULL;
783         }
784
785         memcpy(clk_dce->max_clks_by_state,
786                 dce112_max_clks_by_state,
787                 sizeof(dce112_max_clks_by_state));
788
789         dce_disp_clk_construct(
790                 clk_dce, ctx, regs, clk_shift, clk_mask);
791
792         clk_dce->base.funcs = &dce112_funcs;
793
794         return &clk_dce->base;
795 }
796
797 struct display_clock *dce120_disp_clk_create(struct dc_context *ctx)
798 {
799         struct dce_disp_clk *clk_dce = kzalloc(sizeof(*clk_dce), GFP_KERNEL);
800         struct dm_pp_clock_levels_with_voltage clk_level_info = {0};
801
802         if (clk_dce == NULL) {
803                 BREAK_TO_DEBUGGER();
804                 return NULL;
805         }
806
807         memcpy(clk_dce->max_clks_by_state,
808                 dce120_max_clks_by_state,
809                 sizeof(dce120_max_clks_by_state));
810
811         dce_disp_clk_construct(
812                 clk_dce, ctx, NULL, NULL, NULL);
813
814         clk_dce->base.funcs = &dce120_funcs;
815
816         /* new in dce120 */
817         if (!ctx->dc->debug.disable_pplib_clock_request  &&
818                         dm_pp_get_clock_levels_by_type_with_voltage(
819                         ctx, DM_PP_CLOCK_TYPE_DISPLAY_CLK, &clk_level_info)
820                                                 && clk_level_info.num_levels)
821                 clk_dce->max_displ_clk_in_khz =
822                         clk_level_info.data[clk_level_info.num_levels - 1].clocks_in_khz;
823         else
824                 clk_dce->max_displ_clk_in_khz = 1133000;
825
826         return &clk_dce->base;
827 }
828
829 void dce_disp_clk_destroy(struct display_clock **disp_clk)
830 {
831         struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(*disp_clk);
832
833         kfree(clk_dce);
834         *disp_clk = NULL;
835 }