2 * Copyright 2012-16 Advanced Micro Devices, Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
26 #include <linux/slab.h>
28 #include "dce_clk_mgr.h"
30 #include "reg_helper.h"
32 #include "core_types.h"
33 #include "dal_asic_id.h"
35 #define TO_DCE_CLK_MGR(clocks)\
36 container_of(clocks, struct dce_clk_mgr, base)
39 (clk_mgr_dce->regs->reg)
42 #define FN(reg_name, field_name) \
43 clk_mgr_dce->clk_mgr_shift->field_name, clk_mgr_dce->clk_mgr_mask->field_name
50 /* Max clock values for each state indexed by "enum clocks_state": */
51 static const struct state_dependent_clocks dce80_max_clks_by_state
[] = {
52 /* ClocksStateInvalid - should not be used */
53 { .display_clk_khz
= 0, .pixel_clk_khz
= 0 },
54 /* ClocksStateUltraLow - not expected to be used for DCE 8.0 */
55 { .display_clk_khz
= 0, .pixel_clk_khz
= 0 },
57 { .display_clk_khz
= 352000, .pixel_clk_khz
= 330000},
58 /* ClocksStateNominal */
59 { .display_clk_khz
= 600000, .pixel_clk_khz
= 400000 },
60 /* ClocksStatePerformance */
61 { .display_clk_khz
= 600000, .pixel_clk_khz
= 400000 } };
63 static const struct state_dependent_clocks dce110_max_clks_by_state
[] = {
64 /*ClocksStateInvalid - should not be used*/
65 { .display_clk_khz
= 0, .pixel_clk_khz
= 0 },
66 /*ClocksStateUltraLow - currently by HW design team not supposed to be used*/
67 { .display_clk_khz
= 352000, .pixel_clk_khz
= 330000 },
69 { .display_clk_khz
= 352000, .pixel_clk_khz
= 330000 },
70 /*ClocksStateNominal*/
71 { .display_clk_khz
= 467000, .pixel_clk_khz
= 400000 },
72 /*ClocksStatePerformance*/
73 { .display_clk_khz
= 643000, .pixel_clk_khz
= 400000 } };
75 static const struct state_dependent_clocks dce112_max_clks_by_state
[] = {
76 /*ClocksStateInvalid - should not be used*/
77 { .display_clk_khz
= 0, .pixel_clk_khz
= 0 },
78 /*ClocksStateUltraLow - currently by HW design team not supposed to be used*/
79 { .display_clk_khz
= 389189, .pixel_clk_khz
= 346672 },
81 { .display_clk_khz
= 459000, .pixel_clk_khz
= 400000 },
82 /*ClocksStateNominal*/
83 { .display_clk_khz
= 667000, .pixel_clk_khz
= 600000 },
84 /*ClocksStatePerformance*/
85 { .display_clk_khz
= 1132000, .pixel_clk_khz
= 600000 } };
87 static const struct state_dependent_clocks dce120_max_clks_by_state
[] = {
88 /*ClocksStateInvalid - should not be used*/
89 { .display_clk_khz
= 0, .pixel_clk_khz
= 0 },
90 /*ClocksStateUltraLow - currently by HW design team not supposed to be used*/
91 { .display_clk_khz
= 0, .pixel_clk_khz
= 0 },
93 { .display_clk_khz
= 460000, .pixel_clk_khz
= 400000 },
94 /*ClocksStateNominal*/
95 { .display_clk_khz
= 670000, .pixel_clk_khz
= 600000 },
96 /*ClocksStatePerformance*/
97 { .display_clk_khz
= 1133000, .pixel_clk_khz
= 600000 } };
99 int dentist_get_divider_from_did(int did
)
101 if (did
< DENTIST_BASE_DID_1
)
102 did
= DENTIST_BASE_DID_1
;
103 if (did
> DENTIST_MAX_DID
)
104 did
= DENTIST_MAX_DID
;
106 if (did
< DENTIST_BASE_DID_2
) {
107 return DENTIST_DIVIDER_RANGE_1_START
+ DENTIST_DIVIDER_RANGE_1_STEP
108 * (did
- DENTIST_BASE_DID_1
);
109 } else if (did
< DENTIST_BASE_DID_3
) {
110 return DENTIST_DIVIDER_RANGE_2_START
+ DENTIST_DIVIDER_RANGE_2_STEP
111 * (did
- DENTIST_BASE_DID_2
);
112 } else if (did
< DENTIST_BASE_DID_4
) {
113 return DENTIST_DIVIDER_RANGE_3_START
+ DENTIST_DIVIDER_RANGE_3_STEP
114 * (did
- DENTIST_BASE_DID_3
);
116 return DENTIST_DIVIDER_RANGE_4_START
+ DENTIST_DIVIDER_RANGE_4_STEP
117 * (did
- DENTIST_BASE_DID_4
);
121 /* SW will adjust DP REF Clock average value for all purposes
122 * (DP DTO / DP Audio DTO and DP GTC)
123 if clock is spread for all cases:
124 -if SS enabled on DP Ref clock and HW de-spreading enabled with SW
125 calculations for DS_INCR/DS_MODULO (this is planned to be default case)
126 -if SS enabled on DP Ref clock and HW de-spreading enabled with HW
127 calculations (not planned to be used, but average clock should still
129 -if SS enabled on DP Ref clock and HW de-spreading disabled
130 (should not be case with CIK) then SW should program all rates
131 generated according to average value (case as with previous ASICs)
133 static int clk_mgr_adjust_dp_ref_freq_for_ss(struct dce_clk_mgr
*clk_mgr_dce
, int dp_ref_clk_khz
)
135 if (clk_mgr_dce
->ss_on_dprefclk
&& clk_mgr_dce
->dprefclk_ss_divider
!= 0) {
136 struct fixed31_32 ss_percentage
= dc_fixpt_div_int(
137 dc_fixpt_from_fraction(clk_mgr_dce
->dprefclk_ss_percentage
,
138 clk_mgr_dce
->dprefclk_ss_divider
), 200);
139 struct fixed31_32 adj_dp_ref_clk_khz
;
141 ss_percentage
= dc_fixpt_sub(dc_fixpt_one
, ss_percentage
);
142 adj_dp_ref_clk_khz
= dc_fixpt_mul_int(ss_percentage
, dp_ref_clk_khz
);
143 dp_ref_clk_khz
= dc_fixpt_floor(adj_dp_ref_clk_khz
);
145 return dp_ref_clk_khz
;
148 static int dce_get_dp_ref_freq_khz(struct clk_mgr
*clk_mgr
)
150 struct dce_clk_mgr
*clk_mgr_dce
= TO_DCE_CLK_MGR(clk_mgr
);
151 int dprefclk_wdivider
;
152 int dprefclk_src_sel
;
153 int dp_ref_clk_khz
= 600000;
156 /* ASSERT DP Reference Clock source is from DFS*/
157 REG_GET(DPREFCLK_CNTL
, DPREFCLK_SRC_SEL
, &dprefclk_src_sel
);
158 ASSERT(dprefclk_src_sel
== 0);
160 /* Read the mmDENTIST_DISPCLK_CNTL to get the currently
161 * programmed DID DENTIST_DPREFCLK_WDIVIDER*/
162 REG_GET(DENTIST_DISPCLK_CNTL
, DENTIST_DPREFCLK_WDIVIDER
, &dprefclk_wdivider
);
164 /* Convert DENTIST_DPREFCLK_WDIVIDERto actual divider*/
165 target_div
= dentist_get_divider_from_did(dprefclk_wdivider
);
167 /* Calculate the current DFS clock, in kHz.*/
168 dp_ref_clk_khz
= (DENTIST_DIVIDER_RANGE_SCALE_FACTOR
169 * clk_mgr_dce
->dentist_vco_freq_khz
) / target_div
;
171 return clk_mgr_adjust_dp_ref_freq_for_ss(clk_mgr_dce
, dp_ref_clk_khz
);
174 int dce12_get_dp_ref_freq_khz(struct clk_mgr
*clk_mgr
)
176 struct dce_clk_mgr
*clk_mgr_dce
= TO_DCE_CLK_MGR(clk_mgr
);
178 return clk_mgr_adjust_dp_ref_freq_for_ss(clk_mgr_dce
, clk_mgr_dce
->dprefclk_khz
);
181 /* unit: in_khz before mode set, get pixel clock from context. ASIC register
182 * may not be programmed yet
184 static uint32_t get_max_pixel_clock_for_all_paths(struct dc_state
*context
)
186 uint32_t max_pix_clk
= 0;
189 for (i
= 0; i
< MAX_PIPES
; i
++) {
190 struct pipe_ctx
*pipe_ctx
= &context
->res_ctx
.pipe_ctx
[i
];
192 if (pipe_ctx
->stream
== NULL
)
195 /* do not check under lay */
196 if (pipe_ctx
->top_pipe
)
199 if (pipe_ctx
->stream_res
.pix_clk_params
.requested_pix_clk_100hz
/ 10 > max_pix_clk
)
200 max_pix_clk
= pipe_ctx
->stream_res
.pix_clk_params
.requested_pix_clk_100hz
/ 10;
202 /* raise clock state for HBR3/2 if required. Confirmed with HW DCE/DPCS
203 * logic for HBR3 still needs Nominal (0.8V) on VDDC rail
205 if (dc_is_dp_signal(pipe_ctx
->stream
->signal
) &&
206 pipe_ctx
->stream_res
.pix_clk_params
.requested_sym_clk
> max_pix_clk
)
207 max_pix_clk
= pipe_ctx
->stream_res
.pix_clk_params
.requested_sym_clk
;
213 static enum dm_pp_clocks_state
dce_get_required_clocks_state(
214 struct clk_mgr
*clk_mgr
,
215 struct dc_state
*context
)
217 struct dce_clk_mgr
*clk_mgr_dce
= TO_DCE_CLK_MGR(clk_mgr
);
219 enum dm_pp_clocks_state low_req_clk
;
220 int max_pix_clk
= get_max_pixel_clock_for_all_paths(context
);
222 /* Iterate from highest supported to lowest valid state, and update
223 * lowest RequiredState with the lowest state that satisfies
224 * all required clocks
226 for (i
= clk_mgr_dce
->max_clks_state
; i
>= DM_PP_CLOCKS_STATE_ULTRA_LOW
; i
--)
227 if (context
->bw_ctx
.bw
.dce
.dispclk_khz
>
228 clk_mgr_dce
->max_clks_by_state
[i
].display_clk_khz
230 clk_mgr_dce
->max_clks_by_state
[i
].pixel_clk_khz
)
234 if (low_req_clk
> clk_mgr_dce
->max_clks_state
) {
235 /* set max clock state for high phyclock, invalid on exceeding display clock */
236 if (clk_mgr_dce
->max_clks_by_state
[clk_mgr_dce
->max_clks_state
].display_clk_khz
237 < context
->bw_ctx
.bw
.dce
.dispclk_khz
)
238 low_req_clk
= DM_PP_CLOCKS_STATE_INVALID
;
240 low_req_clk
= clk_mgr_dce
->max_clks_state
;
246 static int dce_set_clock(
247 struct clk_mgr
*clk_mgr
,
248 int requested_clk_khz
)
250 struct dce_clk_mgr
*clk_mgr_dce
= TO_DCE_CLK_MGR(clk_mgr
);
251 struct bp_pixel_clock_parameters pxl_clk_params
= { 0 };
252 struct dc_bios
*bp
= clk_mgr
->ctx
->dc_bios
;
253 int actual_clock
= requested_clk_khz
;
254 struct dmcu
*dmcu
= clk_mgr_dce
->base
.ctx
->dc
->res_pool
->dmcu
;
256 /* Make sure requested clock isn't lower than minimum threshold*/
257 if (requested_clk_khz
> 0)
258 requested_clk_khz
= max(requested_clk_khz
,
259 clk_mgr_dce
->dentist_vco_freq_khz
/ 64);
261 /* Prepare to program display clock*/
262 pxl_clk_params
.target_pixel_clock_100hz
= requested_clk_khz
* 10;
263 pxl_clk_params
.pll_id
= CLOCK_SOURCE_ID_DFS
;
265 if (clk_mgr_dce
->dfs_bypass_active
)
266 pxl_clk_params
.flags
.SET_DISPCLK_DFS_BYPASS
= true;
268 bp
->funcs
->program_display_engine_pll(bp
, &pxl_clk_params
);
270 if (clk_mgr_dce
->dfs_bypass_active
) {
271 /* Cache the fixed display clock*/
272 clk_mgr_dce
->dfs_bypass_disp_clk
=
273 pxl_clk_params
.dfs_bypass_display_clock
;
274 actual_clock
= pxl_clk_params
.dfs_bypass_display_clock
;
277 /* from power down, we need mark the clock state as ClocksStateNominal
278 * from HWReset, so when resume we will call pplib voltage regulator.*/
279 if (requested_clk_khz
== 0)
280 clk_mgr_dce
->cur_min_clks_state
= DM_PP_CLOCKS_STATE_NOMINAL
;
282 if (dmcu
&& dmcu
->funcs
->is_dmcu_initialized(dmcu
))
283 dmcu
->funcs
->set_psr_wait_loop(dmcu
, actual_clock
/ 1000 / 7);
288 int dce112_set_clock(struct clk_mgr
*clk_mgr
, int requested_clk_khz
)
290 struct dce_clk_mgr
*clk_mgr_dce
= TO_DCE_CLK_MGR(clk_mgr
);
291 struct bp_set_dce_clock_parameters dce_clk_params
;
292 struct dc_bios
*bp
= clk_mgr
->ctx
->dc_bios
;
293 struct dc
*core_dc
= clk_mgr
->ctx
->dc
;
294 struct dmcu
*dmcu
= core_dc
->res_pool
->dmcu
;
295 int actual_clock
= requested_clk_khz
;
296 /* Prepare to program display clock*/
297 memset(&dce_clk_params
, 0, sizeof(dce_clk_params
));
299 /* Make sure requested clock isn't lower than minimum threshold*/
300 if (requested_clk_khz
> 0)
301 requested_clk_khz
= max(requested_clk_khz
,
302 clk_mgr_dce
->dentist_vco_freq_khz
/ 62);
304 dce_clk_params
.target_clock_frequency
= requested_clk_khz
;
305 dce_clk_params
.pll_id
= CLOCK_SOURCE_ID_DFS
;
306 dce_clk_params
.clock_type
= DCECLOCK_TYPE_DISPLAY_CLOCK
;
308 bp
->funcs
->set_dce_clock(bp
, &dce_clk_params
);
309 actual_clock
= dce_clk_params
.target_clock_frequency
;
311 /* from power down, we need mark the clock state as ClocksStateNominal
312 * from HWReset, so when resume we will call pplib voltage regulator.*/
313 if (requested_clk_khz
== 0)
314 clk_mgr_dce
->cur_min_clks_state
= DM_PP_CLOCKS_STATE_NOMINAL
;
316 /*Program DP ref Clock*/
317 /*VBIOS will determine DPREFCLK frequency, so we don't set it*/
318 dce_clk_params
.target_clock_frequency
= 0;
319 dce_clk_params
.clock_type
= DCECLOCK_TYPE_DPREFCLK
;
320 if (!ASICREV_IS_VEGA20_P(clk_mgr
->ctx
->asic_id
.hw_internal_rev
))
321 dce_clk_params
.flags
.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK
=
322 (dce_clk_params
.pll_id
==
323 CLOCK_SOURCE_COMBO_DISPLAY_PLL0
);
325 dce_clk_params
.flags
.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK
= false;
327 bp
->funcs
->set_dce_clock(bp
, &dce_clk_params
);
329 if (!IS_FPGA_MAXIMUS_DC(core_dc
->ctx
->dce_environment
)) {
330 if (dmcu
&& dmcu
->funcs
->is_dmcu_initialized(dmcu
)) {
331 if (clk_mgr_dce
->dfs_bypass_disp_clk
!= actual_clock
)
332 dmcu
->funcs
->set_psr_wait_loop(dmcu
,
333 actual_clock
/ 1000 / 7);
337 clk_mgr_dce
->dfs_bypass_disp_clk
= actual_clock
;
341 static void dce_clock_read_integrated_info(struct dce_clk_mgr
*clk_mgr_dce
)
343 struct dc_debug_options
*debug
= &clk_mgr_dce
->base
.ctx
->dc
->debug
;
344 struct dc_bios
*bp
= clk_mgr_dce
->base
.ctx
->dc_bios
;
345 struct integrated_info info
= { { { 0 } } };
346 struct dc_firmware_info fw_info
= { { 0 } };
349 if (bp
->integrated_info
)
350 info
= *bp
->integrated_info
;
352 clk_mgr_dce
->dentist_vco_freq_khz
= info
.dentist_vco_freq
;
353 if (clk_mgr_dce
->dentist_vco_freq_khz
== 0) {
354 bp
->funcs
->get_firmware_info(bp
, &fw_info
);
355 clk_mgr_dce
->dentist_vco_freq_khz
=
356 fw_info
.smu_gpu_pll_output_freq
;
357 if (clk_mgr_dce
->dentist_vco_freq_khz
== 0)
358 clk_mgr_dce
->dentist_vco_freq_khz
= 3600000;
361 /*update the maximum display clock for each power state*/
362 for (i
= 0; i
< NUMBER_OF_DISP_CLK_VOLTAGE
; ++i
) {
363 enum dm_pp_clocks_state clk_state
= DM_PP_CLOCKS_STATE_INVALID
;
367 clk_state
= DM_PP_CLOCKS_STATE_ULTRA_LOW
;
371 clk_state
= DM_PP_CLOCKS_STATE_LOW
;
375 clk_state
= DM_PP_CLOCKS_STATE_NOMINAL
;
379 clk_state
= DM_PP_CLOCKS_STATE_PERFORMANCE
;
383 clk_state
= DM_PP_CLOCKS_STATE_INVALID
;
387 /*Do not allow bad VBIOS/SBIOS to override with invalid values,
388 * check for > 100MHz*/
389 if (info
.disp_clk_voltage
[i
].max_supported_clk
>= 100000)
390 clk_mgr_dce
->max_clks_by_state
[clk_state
].display_clk_khz
=
391 info
.disp_clk_voltage
[i
].max_supported_clk
;
394 if (!debug
->disable_dfs_bypass
&& bp
->integrated_info
)
395 if (bp
->integrated_info
->gpu_cap_info
& DFS_BYPASS_ENABLE
)
396 clk_mgr_dce
->dfs_bypass_enabled
= true;
399 void dce_clock_read_ss_info(struct dce_clk_mgr
*clk_mgr_dce
)
401 struct dc_bios
*bp
= clk_mgr_dce
->base
.ctx
->dc_bios
;
402 int ss_info_num
= bp
->funcs
->get_ss_entry_number(
403 bp
, AS_SIGNAL_TYPE_GPU_PLL
);
406 struct spread_spectrum_info info
= { { 0 } };
407 enum bp_result result
= bp
->funcs
->get_spread_spectrum_info(
408 bp
, AS_SIGNAL_TYPE_GPU_PLL
, 0, &info
);
410 /* Based on VBIOS, VBIOS will keep entry for GPU PLL SS
411 * even if SS not enabled and in that case
412 * SSInfo.spreadSpectrumPercentage !=0 would be sign
415 if (result
== BP_RESULT_OK
&&
416 info
.spread_spectrum_percentage
!= 0) {
417 clk_mgr_dce
->ss_on_dprefclk
= true;
418 clk_mgr_dce
->dprefclk_ss_divider
= info
.spread_percentage_divider
;
420 if (info
.type
.CENTER_MODE
== 0) {
421 /* TODO: Currently for DP Reference clock we
422 * need only SS percentage for
424 clk_mgr_dce
->dprefclk_ss_percentage
=
425 info
.spread_spectrum_percentage
;
431 result
= bp
->funcs
->get_spread_spectrum_info(
432 bp
, AS_SIGNAL_TYPE_DISPLAY_PORT
, 0, &info
);
434 /* Based on VBIOS, VBIOS will keep entry for DPREFCLK SS
435 * even if SS not enabled and in that case
436 * SSInfo.spreadSpectrumPercentage !=0 would be sign
439 if (result
== BP_RESULT_OK
&&
440 info
.spread_spectrum_percentage
!= 0) {
441 clk_mgr_dce
->ss_on_dprefclk
= true;
442 clk_mgr_dce
->dprefclk_ss_divider
= info
.spread_percentage_divider
;
444 if (info
.type
.CENTER_MODE
== 0) {
445 /* Currently for DP Reference clock we
446 * need only SS percentage for
448 clk_mgr_dce
->dprefclk_ss_percentage
=
449 info
.spread_spectrum_percentage
;
456 * dce121_clock_patch_xgmi_ss_info() - Save XGMI spread spectrum info
457 * @clk_mgr: clock manager base structure
459 * Reads from VBIOS the XGMI spread spectrum info and saves it within
460 * the dce clock manager. This operation will overwrite the existing dprefclk
461 * SS values if the vBIOS query succeeds. Otherwise, it does nothing. It also
462 * sets the ->xgmi_enabled flag.
464 void dce121_clock_patch_xgmi_ss_info(struct clk_mgr
*clk_mgr
)
466 struct dce_clk_mgr
*clk_mgr_dce
= TO_DCE_CLK_MGR(clk_mgr
);
467 enum bp_result result
;
468 struct spread_spectrum_info info
= { { 0 } };
469 struct dc_bios
*bp
= clk_mgr_dce
->base
.ctx
->dc_bios
;
471 clk_mgr_dce
->xgmi_enabled
= false;
473 result
= bp
->funcs
->get_spread_spectrum_info(bp
, AS_SIGNAL_TYPE_XGMI
,
475 if (result
== BP_RESULT_OK
&& info
.spread_spectrum_percentage
!= 0) {
476 clk_mgr_dce
->xgmi_enabled
= true;
477 clk_mgr_dce
->ss_on_dprefclk
= true;
478 clk_mgr_dce
->dprefclk_ss_divider
=
479 info
.spread_percentage_divider
;
481 if (info
.type
.CENTER_MODE
== 0) {
482 /* Currently for DP Reference clock we
483 * need only SS percentage for
485 clk_mgr_dce
->dprefclk_ss_percentage
=
486 info
.spread_spectrum_percentage
;
491 void dce110_fill_display_configs(
492 const struct dc_state
*context
,
493 struct dm_pp_display_configuration
*pp_display_cfg
)
498 for (j
= 0; j
< context
->stream_count
; j
++) {
501 const struct dc_stream_state
*stream
= context
->streams
[j
];
502 struct dm_pp_single_disp_config
*cfg
=
503 &pp_display_cfg
->disp_configs
[num_cfgs
];
504 const struct pipe_ctx
*pipe_ctx
= NULL
;
506 for (k
= 0; k
< MAX_PIPES
; k
++)
507 if (stream
== context
->res_ctx
.pipe_ctx
[k
].stream
) {
508 pipe_ctx
= &context
->res_ctx
.pipe_ctx
[k
];
512 ASSERT(pipe_ctx
!= NULL
);
514 /* only notify active stream */
515 if (stream
->dpms_off
)
519 cfg
->signal
= pipe_ctx
->stream
->signal
;
520 cfg
->pipe_idx
= pipe_ctx
->stream_res
.tg
->inst
;
521 cfg
->src_height
= stream
->src
.height
;
522 cfg
->src_width
= stream
->src
.width
;
523 cfg
->ddi_channel_mapping
=
524 stream
->link
->ddi_channel_mapping
.raw
;
526 stream
->link
->link_enc
->transmitter
;
527 cfg
->link_settings
.lane_count
=
528 stream
->link
->cur_link_settings
.lane_count
;
529 cfg
->link_settings
.link_rate
=
530 stream
->link
->cur_link_settings
.link_rate
;
531 cfg
->link_settings
.link_spread
=
532 stream
->link
->cur_link_settings
.link_spread
;
533 cfg
->sym_clock
= stream
->phy_pix_clk
;
535 cfg
->v_refresh
= stream
->timing
.pix_clk_100hz
* 100;
536 cfg
->v_refresh
/= stream
->timing
.h_total
;
537 cfg
->v_refresh
= (cfg
->v_refresh
+ stream
->timing
.v_total
/ 2)
538 / stream
->timing
.v_total
;
541 pp_display_cfg
->display_count
= num_cfgs
;
544 static uint32_t dce110_get_min_vblank_time_us(const struct dc_state
*context
)
547 uint32_t min_vertical_blank_time
= -1;
549 for (j
= 0; j
< context
->stream_count
; j
++) {
550 struct dc_stream_state
*stream
= context
->streams
[j
];
551 uint32_t vertical_blank_in_pixels
= 0;
552 uint32_t vertical_blank_time
= 0;
554 vertical_blank_in_pixels
= stream
->timing
.h_total
*
555 (stream
->timing
.v_total
556 - stream
->timing
.v_addressable
);
558 vertical_blank_time
= vertical_blank_in_pixels
559 * 10000 / stream
->timing
.pix_clk_100hz
;
561 if (min_vertical_blank_time
> vertical_blank_time
)
562 min_vertical_blank_time
= vertical_blank_time
;
565 return min_vertical_blank_time
;
568 static int determine_sclk_from_bounding_box(
575 * Some asics do not give us sclk levels, so we just report the actual
578 if (dc
->sclk_lvls
.num_levels
== 0)
579 return required_sclk
;
581 for (i
= 0; i
< dc
->sclk_lvls
.num_levels
; i
++) {
582 if (dc
->sclk_lvls
.clocks_in_khz
[i
] >= required_sclk
)
583 return dc
->sclk_lvls
.clocks_in_khz
[i
];
586 * even maximum level could not satisfy requirement, this
587 * is unexpected at this stage, should have been caught at
591 return dc
->sclk_lvls
.clocks_in_khz
[dc
->sclk_lvls
.num_levels
- 1];
594 static void dce_pplib_apply_display_requirements(
596 struct dc_state
*context
)
598 struct dm_pp_display_configuration
*pp_display_cfg
= &context
->pp_display_cfg
;
600 pp_display_cfg
->avail_mclk_switch_time_us
= dce110_get_min_vblank_time_us(context
);
602 dce110_fill_display_configs(context
, pp_display_cfg
);
604 if (memcmp(&dc
->current_state
->pp_display_cfg
, pp_display_cfg
, sizeof(*pp_display_cfg
)) != 0)
605 dm_pp_apply_display_requirements(dc
->ctx
, pp_display_cfg
);
608 static void dce11_pplib_apply_display_requirements(
610 struct dc_state
*context
)
612 struct dm_pp_display_configuration
*pp_display_cfg
= &context
->pp_display_cfg
;
614 pp_display_cfg
->all_displays_in_sync
=
615 context
->bw_ctx
.bw
.dce
.all_displays_in_sync
;
616 pp_display_cfg
->nb_pstate_switch_disable
=
617 context
->bw_ctx
.bw
.dce
.nbp_state_change_enable
== false;
618 pp_display_cfg
->cpu_cc6_disable
=
619 context
->bw_ctx
.bw
.dce
.cpuc_state_change_enable
== false;
620 pp_display_cfg
->cpu_pstate_disable
=
621 context
->bw_ctx
.bw
.dce
.cpup_state_change_enable
== false;
622 pp_display_cfg
->cpu_pstate_separation_time
=
623 context
->bw_ctx
.bw
.dce
.blackout_recovery_time_us
;
625 pp_display_cfg
->min_memory_clock_khz
= context
->bw_ctx
.bw
.dce
.yclk_khz
626 / MEMORY_TYPE_MULTIPLIER_CZ
;
628 pp_display_cfg
->min_engine_clock_khz
= determine_sclk_from_bounding_box(
630 context
->bw_ctx
.bw
.dce
.sclk_khz
);
633 * As workaround for >4x4K lightup set dcfclock to min_engine_clock value.
634 * This is not required for less than 5 displays,
635 * thus don't request decfclk in dc to avoid impact
639 pp_display_cfg
->min_dcfclock_khz
= (context
->stream_count
> 4)?
640 pp_display_cfg
->min_engine_clock_khz
: 0;
642 pp_display_cfg
->min_engine_clock_deep_sleep_khz
643 = context
->bw_ctx
.bw
.dce
.sclk_deep_sleep_khz
;
645 pp_display_cfg
->avail_mclk_switch_time_us
=
646 dce110_get_min_vblank_time_us(context
);
648 pp_display_cfg
->avail_mclk_switch_time_in_disp_active_us
= 0;
650 pp_display_cfg
->disp_clk_khz
= dc
->res_pool
->clk_mgr
->clks
.dispclk_khz
;
652 dce110_fill_display_configs(context
, pp_display_cfg
);
654 /* TODO: is this still applicable?*/
655 if (pp_display_cfg
->display_count
== 1) {
656 const struct dc_crtc_timing
*timing
=
657 &context
->streams
[0]->timing
;
659 pp_display_cfg
->crtc_index
=
660 pp_display_cfg
->disp_configs
[0].pipe_idx
;
661 pp_display_cfg
->line_time_in_us
= timing
->h_total
* 10000 / timing
->pix_clk_100hz
;
664 if (memcmp(&dc
->current_state
->pp_display_cfg
, pp_display_cfg
, sizeof(*pp_display_cfg
)) != 0)
665 dm_pp_apply_display_requirements(dc
->ctx
, pp_display_cfg
);
668 static void dce_update_clocks(struct clk_mgr
*clk_mgr
,
669 struct dc_state
*context
,
672 struct dce_clk_mgr
*clk_mgr_dce
= TO_DCE_CLK_MGR(clk_mgr
);
673 struct dm_pp_power_level_change_request level_change_req
;
674 int patched_disp_clk
= context
->bw_ctx
.bw
.dce
.dispclk_khz
;
676 /*TODO: W/A for dal3 linux, investigate why this works */
677 if (!clk_mgr_dce
->dfs_bypass_active
)
678 patched_disp_clk
= patched_disp_clk
* 115 / 100;
680 level_change_req
.power_level
= dce_get_required_clocks_state(clk_mgr
, context
);
681 /* get max clock state from PPLIB */
682 if ((level_change_req
.power_level
< clk_mgr_dce
->cur_min_clks_state
&& safe_to_lower
)
683 || level_change_req
.power_level
> clk_mgr_dce
->cur_min_clks_state
) {
684 if (dm_pp_apply_power_level_change_request(clk_mgr
->ctx
, &level_change_req
))
685 clk_mgr_dce
->cur_min_clks_state
= level_change_req
.power_level
;
688 if (should_set_clock(safe_to_lower
, patched_disp_clk
, clk_mgr
->clks
.dispclk_khz
)) {
689 patched_disp_clk
= dce_set_clock(clk_mgr
, patched_disp_clk
);
690 clk_mgr
->clks
.dispclk_khz
= patched_disp_clk
;
692 dce_pplib_apply_display_requirements(clk_mgr
->ctx
->dc
, context
);
695 static void dce11_update_clocks(struct clk_mgr
*clk_mgr
,
696 struct dc_state
*context
,
699 struct dce_clk_mgr
*clk_mgr_dce
= TO_DCE_CLK_MGR(clk_mgr
);
700 struct dm_pp_power_level_change_request level_change_req
;
701 int patched_disp_clk
= context
->bw_ctx
.bw
.dce
.dispclk_khz
;
703 /*TODO: W/A for dal3 linux, investigate why this works */
704 if (!clk_mgr_dce
->dfs_bypass_active
)
705 patched_disp_clk
= patched_disp_clk
* 115 / 100;
707 level_change_req
.power_level
= dce_get_required_clocks_state(clk_mgr
, context
);
708 /* get max clock state from PPLIB */
709 if ((level_change_req
.power_level
< clk_mgr_dce
->cur_min_clks_state
&& safe_to_lower
)
710 || level_change_req
.power_level
> clk_mgr_dce
->cur_min_clks_state
) {
711 if (dm_pp_apply_power_level_change_request(clk_mgr
->ctx
, &level_change_req
))
712 clk_mgr_dce
->cur_min_clks_state
= level_change_req
.power_level
;
715 if (should_set_clock(safe_to_lower
, patched_disp_clk
, clk_mgr
->clks
.dispclk_khz
)) {
716 context
->bw_ctx
.bw
.dce
.dispclk_khz
= dce_set_clock(clk_mgr
, patched_disp_clk
);
717 clk_mgr
->clks
.dispclk_khz
= patched_disp_clk
;
719 dce11_pplib_apply_display_requirements(clk_mgr
->ctx
->dc
, context
);
722 static void dce112_update_clocks(struct clk_mgr
*clk_mgr
,
723 struct dc_state
*context
,
726 struct dce_clk_mgr
*clk_mgr_dce
= TO_DCE_CLK_MGR(clk_mgr
);
727 struct dm_pp_power_level_change_request level_change_req
;
728 int patched_disp_clk
= context
->bw_ctx
.bw
.dce
.dispclk_khz
;
730 /*TODO: W/A for dal3 linux, investigate why this works */
731 if (!clk_mgr_dce
->dfs_bypass_active
)
732 patched_disp_clk
= patched_disp_clk
* 115 / 100;
734 level_change_req
.power_level
= dce_get_required_clocks_state(clk_mgr
, context
);
735 /* get max clock state from PPLIB */
736 if ((level_change_req
.power_level
< clk_mgr_dce
->cur_min_clks_state
&& safe_to_lower
)
737 || level_change_req
.power_level
> clk_mgr_dce
->cur_min_clks_state
) {
738 if (dm_pp_apply_power_level_change_request(clk_mgr
->ctx
, &level_change_req
))
739 clk_mgr_dce
->cur_min_clks_state
= level_change_req
.power_level
;
742 if (should_set_clock(safe_to_lower
, patched_disp_clk
, clk_mgr
->clks
.dispclk_khz
)) {
743 patched_disp_clk
= dce112_set_clock(clk_mgr
, patched_disp_clk
);
744 clk_mgr
->clks
.dispclk_khz
= patched_disp_clk
;
746 dce11_pplib_apply_display_requirements(clk_mgr
->ctx
->dc
, context
);
749 static void dce12_update_clocks(struct clk_mgr
*clk_mgr
,
750 struct dc_state
*context
,
753 struct dce_clk_mgr
*clk_mgr_dce
= TO_DCE_CLK_MGR(clk_mgr
);
754 struct dm_pp_clock_for_voltage_req clock_voltage_req
= {0};
755 int max_pix_clk
= get_max_pixel_clock_for_all_paths(context
);
756 int patched_disp_clk
= context
->bw_ctx
.bw
.dce
.dispclk_khz
;
758 /*TODO: W/A for dal3 linux, investigate why this works */
759 if (!clk_mgr_dce
->dfs_bypass_active
)
760 patched_disp_clk
= patched_disp_clk
* 115 / 100;
762 if (should_set_clock(safe_to_lower
, patched_disp_clk
, clk_mgr
->clks
.dispclk_khz
)) {
763 clock_voltage_req
.clk_type
= DM_PP_CLOCK_TYPE_DISPLAY_CLK
;
765 * When xGMI is enabled, the display clk needs to be adjusted
766 * with the WAFL link's SS percentage.
768 if (clk_mgr_dce
->xgmi_enabled
)
769 patched_disp_clk
= clk_mgr_adjust_dp_ref_freq_for_ss(
770 clk_mgr_dce
, patched_disp_clk
);
771 clock_voltage_req
.clocks_in_khz
= patched_disp_clk
;
772 clk_mgr
->clks
.dispclk_khz
= dce112_set_clock(clk_mgr
, patched_disp_clk
);
774 dm_pp_apply_clock_for_voltage_request(clk_mgr
->ctx
, &clock_voltage_req
);
777 if (should_set_clock(safe_to_lower
, max_pix_clk
, clk_mgr
->clks
.phyclk_khz
)) {
778 clock_voltage_req
.clk_type
= DM_PP_CLOCK_TYPE_DISPLAYPHYCLK
;
779 clock_voltage_req
.clocks_in_khz
= max_pix_clk
;
780 clk_mgr
->clks
.phyclk_khz
= max_pix_clk
;
782 dm_pp_apply_clock_for_voltage_request(clk_mgr
->ctx
, &clock_voltage_req
);
784 dce11_pplib_apply_display_requirements(clk_mgr
->ctx
->dc
, context
);
787 static const struct clk_mgr_funcs dce120_funcs
= {
788 .get_dp_ref_clk_frequency
= dce12_get_dp_ref_freq_khz
,
789 .update_clocks
= dce12_update_clocks
792 static const struct clk_mgr_funcs dce112_funcs
= {
793 .get_dp_ref_clk_frequency
= dce_get_dp_ref_freq_khz
,
794 .update_clocks
= dce112_update_clocks
797 static const struct clk_mgr_funcs dce110_funcs
= {
798 .get_dp_ref_clk_frequency
= dce_get_dp_ref_freq_khz
,
799 .update_clocks
= dce11_update_clocks
,
802 static const struct clk_mgr_funcs dce_funcs
= {
803 .get_dp_ref_clk_frequency
= dce_get_dp_ref_freq_khz
,
804 .update_clocks
= dce_update_clocks
807 static void dce_clk_mgr_construct(
808 struct dce_clk_mgr
*clk_mgr_dce
,
809 struct dc_context
*ctx
,
810 const struct clk_mgr_registers
*regs
,
811 const struct clk_mgr_shift
*clk_shift
,
812 const struct clk_mgr_mask
*clk_mask
)
814 struct clk_mgr
*base
= &clk_mgr_dce
->base
;
815 struct dm_pp_static_clock_info static_clk_info
= {0};
818 base
->funcs
= &dce_funcs
;
820 clk_mgr_dce
->regs
= regs
;
821 clk_mgr_dce
->clk_mgr_shift
= clk_shift
;
822 clk_mgr_dce
->clk_mgr_mask
= clk_mask
;
824 clk_mgr_dce
->dfs_bypass_disp_clk
= 0;
826 clk_mgr_dce
->dprefclk_ss_percentage
= 0;
827 clk_mgr_dce
->dprefclk_ss_divider
= 1000;
828 clk_mgr_dce
->ss_on_dprefclk
= false;
831 if (dm_pp_get_static_clocks(ctx
, &static_clk_info
))
832 clk_mgr_dce
->max_clks_state
= static_clk_info
.max_clocks_state
;
834 clk_mgr_dce
->max_clks_state
= DM_PP_CLOCKS_STATE_NOMINAL
;
835 clk_mgr_dce
->cur_min_clks_state
= DM_PP_CLOCKS_STATE_INVALID
;
837 dce_clock_read_integrated_info(clk_mgr_dce
);
838 dce_clock_read_ss_info(clk_mgr_dce
);
841 struct clk_mgr
*dce_clk_mgr_create(
842 struct dc_context
*ctx
,
843 const struct clk_mgr_registers
*regs
,
844 const struct clk_mgr_shift
*clk_shift
,
845 const struct clk_mgr_mask
*clk_mask
)
847 struct dce_clk_mgr
*clk_mgr_dce
= kzalloc(sizeof(*clk_mgr_dce
), GFP_KERNEL
);
849 if (clk_mgr_dce
== NULL
) {
854 memcpy(clk_mgr_dce
->max_clks_by_state
,
855 dce80_max_clks_by_state
,
856 sizeof(dce80_max_clks_by_state
));
858 dce_clk_mgr_construct(
859 clk_mgr_dce
, ctx
, regs
, clk_shift
, clk_mask
);
861 return &clk_mgr_dce
->base
;
864 struct clk_mgr
*dce110_clk_mgr_create(
865 struct dc_context
*ctx
,
866 const struct clk_mgr_registers
*regs
,
867 const struct clk_mgr_shift
*clk_shift
,
868 const struct clk_mgr_mask
*clk_mask
)
870 struct dce_clk_mgr
*clk_mgr_dce
= kzalloc(sizeof(*clk_mgr_dce
), GFP_KERNEL
);
872 if (clk_mgr_dce
== NULL
) {
877 memcpy(clk_mgr_dce
->max_clks_by_state
,
878 dce110_max_clks_by_state
,
879 sizeof(dce110_max_clks_by_state
));
881 dce_clk_mgr_construct(
882 clk_mgr_dce
, ctx
, regs
, clk_shift
, clk_mask
);
884 clk_mgr_dce
->base
.funcs
= &dce110_funcs
;
886 return &clk_mgr_dce
->base
;
889 struct clk_mgr
*dce112_clk_mgr_create(
890 struct dc_context
*ctx
,
891 const struct clk_mgr_registers
*regs
,
892 const struct clk_mgr_shift
*clk_shift
,
893 const struct clk_mgr_mask
*clk_mask
)
895 struct dce_clk_mgr
*clk_mgr_dce
= kzalloc(sizeof(*clk_mgr_dce
), GFP_KERNEL
);
897 if (clk_mgr_dce
== NULL
) {
902 memcpy(clk_mgr_dce
->max_clks_by_state
,
903 dce112_max_clks_by_state
,
904 sizeof(dce112_max_clks_by_state
));
906 dce_clk_mgr_construct(
907 clk_mgr_dce
, ctx
, regs
, clk_shift
, clk_mask
);
909 clk_mgr_dce
->base
.funcs
= &dce112_funcs
;
911 return &clk_mgr_dce
->base
;
914 struct clk_mgr
*dce120_clk_mgr_create(struct dc_context
*ctx
)
916 struct dce_clk_mgr
*clk_mgr_dce
= kzalloc(sizeof(*clk_mgr_dce
), GFP_KERNEL
);
918 if (clk_mgr_dce
== NULL
) {
923 memcpy(clk_mgr_dce
->max_clks_by_state
,
924 dce120_max_clks_by_state
,
925 sizeof(dce120_max_clks_by_state
));
927 dce_clk_mgr_construct(
928 clk_mgr_dce
, ctx
, NULL
, NULL
, NULL
);
930 clk_mgr_dce
->dprefclk_khz
= 600000;
931 clk_mgr_dce
->base
.funcs
= &dce120_funcs
;
933 return &clk_mgr_dce
->base
;
936 struct clk_mgr
*dce121_clk_mgr_create(struct dc_context
*ctx
)
938 struct dce_clk_mgr
*clk_mgr_dce
= kzalloc(sizeof(*clk_mgr_dce
),
941 if (clk_mgr_dce
== NULL
) {
946 memcpy(clk_mgr_dce
->max_clks_by_state
, dce120_max_clks_by_state
,
947 sizeof(dce120_max_clks_by_state
));
949 dce_clk_mgr_construct(clk_mgr_dce
, ctx
, NULL
, NULL
, NULL
);
951 clk_mgr_dce
->dprefclk_khz
= 625000;
952 clk_mgr_dce
->base
.funcs
= &dce120_funcs
;
954 return &clk_mgr_dce
->base
;
957 void dce_clk_mgr_destroy(struct clk_mgr
**clk_mgr
)
959 struct dce_clk_mgr
*clk_mgr_dce
= TO_DCE_CLK_MGR(*clk_mgr
);