File Index
Files and directories
Sign in
FILE

clk_mgr_internal.h

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h C
  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 */
 25
 26#ifndef __DAL_CLK_MGR_INTERNAL_H__
 27#define __DAL_CLK_MGR_INTERNAL_H__
 28
 29#include "clk_mgr.h"
 30#include "dc.h"
 31
 32/*
 33 * only thing needed from here is MEMORY_TYPE_MULTIPLIER_CZ, which is also
 34 * used in resource, perhaps this should be defined somewhere more common.
 35 */
 36#include "resource.h"
 37
 38
 39/* Starting DID for each range */
 40enum dentist_base_divider_id {
 41	DENTIST_BASE_DID_1 = 0x08,
 42	DENTIST_BASE_DID_2 = 0x40,
 43	DENTIST_BASE_DID_3 = 0x60,
 44	DENTIST_BASE_DID_4 = 0x7e,
 45	DENTIST_MAX_DID = 0x7f
 46};
 47
 48/* Starting point and step size for each divider range.*/
 49enum dentist_divider_range {
 50	DENTIST_DIVIDER_RANGE_1_START = 8,   /* 2.00  */
 51	DENTIST_DIVIDER_RANGE_1_STEP  = 1,   /* 0.25  */
 52	DENTIST_DIVIDER_RANGE_2_START = 64,  /* 16.00 */
 53	DENTIST_DIVIDER_RANGE_2_STEP  = 2,   /* 0.50  */
 54	DENTIST_DIVIDER_RANGE_3_START = 128, /* 32.00 */
 55	DENTIST_DIVIDER_RANGE_3_STEP  = 4,   /* 1.00  */
 56	DENTIST_DIVIDER_RANGE_4_START = 248, /* 62.00 */
 57	DENTIST_DIVIDER_RANGE_4_STEP  = 264, /* 66.00 */
 58	DENTIST_DIVIDER_RANGE_SCALE_FACTOR = 4
 59};
 60
 61/*
 62 ***************************************************************************************
 63 ****************** Clock Manager Private Macros and Defines ***************************
 64 ***************************************************************************************
 65 */
 66
 67/* Macros */
 68
 69#define TO_CLK_MGR_INTERNAL(clk_mgr)\
 70	container_of(clk_mgr, struct clk_mgr_internal, base)
 71
 72#define CTX \
 73	clk_mgr->base.ctx
 74
 75#define DC_LOGGER \
 76	dc->ctx->logger
 77
 78
 79
 80
 81#define CLK_BASE(inst) \
 82	CLK_BASE_INNER(inst)
 83
 84#define CLK_SRI(reg_name, block, inst)\
 85	.reg_name = CLK_BASE(mm ## block ## _ ## inst ## _ ## reg_name ## _BASE_IDX) + \
 86					mm ## block ## _ ## inst ## _ ## reg_name
 87
 88#define CLK_COMMON_REG_LIST_DCE_BASE() \
 89	.DPREFCLK_CNTL = mmDPREFCLK_CNTL, \
 90	.DENTIST_DISPCLK_CNTL = mmDENTIST_DISPCLK_CNTL
 91
 92#if defined(CONFIG_DRM_AMD_DC_SI)
 93#define CLK_COMMON_REG_LIST_DCE60_BASE() \
 94	SR(DENTIST_DISPCLK_CNTL)
 95#endif
 96
 97#define CLK_COMMON_REG_LIST_DCN_BASE() \
 98	SR(DENTIST_DISPCLK_CNTL)
 99
100#define CLK_COMMON_REG_LIST_DCN_201() \
101	SR(DENTIST_DISPCLK_CNTL), \
102	CLK_SRI(CLK4_CLK_PLL_REQ, CLK4, 0), \
103	CLK_SRI(CLK4_CLK2_CURRENT_CNT, CLK4, 0)
104
105#define CLK_REG_LIST_NV10() \
106	SR(DENTIST_DISPCLK_CNTL), \
107	CLK_SRI(CLK3_CLK_PLL_REQ, CLK3, 0), \
108	CLK_SRI(CLK3_CLK2_DFS_CNTL, CLK3, 0)
109
110#define CLK_REG_LIST_DCN3()	  \
111	SR(DENTIST_DISPCLK_CNTL), \
112	CLK_SRI(CLK0_CLK_PLL_REQ,   CLK02, 0), \
113	CLK_SRI(CLK0_CLK2_DFS_CNTL, CLK02, 0)
114
115#define CLK_SF(reg_name, field_name, post_fix)\
116	.field_name = reg_name ## __ ## field_name ## post_fix
117
118#define CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) \
119	CLK_SF(DPREFCLK_CNTL, DPREFCLK_SRC_SEL, mask_sh), \
120	CLK_SF(DENTIST_DISPCLK_CNTL, DENTIST_DPREFCLK_WDIVIDER, mask_sh)
121
122#if defined(CONFIG_DRM_AMD_DC_SI)
123#define CLK_COMMON_MASK_SH_LIST_DCE60_COMMON_BASE(mask_sh) \
124	CLK_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER, mask_sh),\
125	CLK_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_DONE, mask_sh)
126#endif
127
128#define CLK_COMMON_MASK_SH_LIST_DCN_COMMON_BASE(mask_sh) \
129	CLK_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER, mask_sh),\
130	CLK_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_DONE, mask_sh)
131
132#define CLK_MASK_SH_LIST_RV1(mask_sh) \
133	CLK_COMMON_MASK_SH_LIST_DCN_COMMON_BASE(mask_sh),\
134	CLK_SF(MP1_SMN_C2PMSG_67, CONTENT, mask_sh),\
135	CLK_SF(MP1_SMN_C2PMSG_83, CONTENT, mask_sh),\
136	CLK_SF(MP1_SMN_C2PMSG_91, CONTENT, mask_sh),
137
138#define CLK_COMMON_MASK_SH_LIST_DCN20_BASE(mask_sh) \
139	CLK_COMMON_MASK_SH_LIST_DCN_COMMON_BASE(mask_sh),\
140	CLK_SF(DENTIST_DISPCLK_CNTL, DENTIST_DPPCLK_WDIVIDER, mask_sh),\
141	CLK_SF(DENTIST_DISPCLK_CNTL, DENTIST_DPPCLK_CHG_DONE, mask_sh)
142
143#define CLK_MASK_SH_LIST_NV10(mask_sh) \
144	CLK_COMMON_MASK_SH_LIST_DCN20_BASE(mask_sh),\
145	CLK_SF(CLK3_0_CLK3_CLK_PLL_REQ, FbMult_int, mask_sh),\
146	CLK_SF(CLK3_0_CLK3_CLK_PLL_REQ, FbMult_frac, mask_sh)
147
148#define CLK_COMMON_MASK_SH_LIST_DCN201_BASE(mask_sh) \
149	CLK_COMMON_MASK_SH_LIST_DCN_COMMON_BASE(mask_sh),\
150	CLK_SF(DENTIST_DISPCLK_CNTL, DENTIST_DPPCLK_WDIVIDER, mask_sh),\
151	CLK_SF(DENTIST_DISPCLK_CNTL, DENTIST_DPPCLK_CHG_DONE, mask_sh),\
152	CLK_SF(CLK4_0_CLK4_CLK_PLL_REQ, FbMult_int, mask_sh)
153
154#define CLK_REG_LIST_DCN32()	  \
155	SR(DENTIST_DISPCLK_CNTL), \
156	CLK_SR_DCN32(CLK1_CLK_PLL_REQ), \
157	CLK_SR_DCN32(CLK1_CLK0_DFS_CNTL), \
158	CLK_SR_DCN32(CLK1_CLK1_DFS_CNTL), \
159	CLK_SR_DCN32(CLK1_CLK2_DFS_CNTL), \
160	CLK_SR_DCN32(CLK1_CLK3_DFS_CNTL), \
161	CLK_SR_DCN32(CLK1_CLK4_DFS_CNTL), \
162    CLK_SR_DCN32(CLK1_CLK0_CURRENT_CNT), \
163    CLK_SR_DCN32(CLK1_CLK1_CURRENT_CNT), \
164    CLK_SR_DCN32(CLK1_CLK2_CURRENT_CNT), \
165    CLK_SR_DCN32(CLK1_CLK3_CURRENT_CNT), \
166    CLK_SR_DCN32(CLK1_CLK4_CURRENT_CNT), \
167    CLK_SR_DCN32(CLK4_CLK0_CURRENT_CNT)
168
169#define CLK_REG_LIST_DCN35()	  \
170	CLK_SR_DCN35(CLK1_CLK_PLL_REQ), \
171	CLK_SR_DCN35(CLK1_CLK0_DFS_CNTL), \
172	CLK_SR_DCN35(CLK1_CLK1_DFS_CNTL), \
173	CLK_SR_DCN35(CLK1_CLK2_DFS_CNTL), \
174	CLK_SR_DCN35(CLK1_CLK3_DFS_CNTL), \
175	CLK_SR_DCN35(CLK1_CLK4_DFS_CNTL), \
176	CLK_SR_DCN35(CLK1_CLK5_DFS_CNTL), \
177	CLK_SR_DCN35(CLK1_CLK0_CURRENT_CNT), \
178	CLK_SR_DCN35(CLK1_CLK1_CURRENT_CNT), \
179	CLK_SR_DCN35(CLK1_CLK2_CURRENT_CNT), \
180	CLK_SR_DCN35(CLK1_CLK3_CURRENT_CNT), \
181	CLK_SR_DCN35(CLK1_CLK4_CURRENT_CNT), \
182	CLK_SR_DCN35(CLK1_CLK5_CURRENT_CNT), \
183	CLK_SR_DCN35(CLK1_CLK0_BYPASS_CNTL), \
184	CLK_SR_DCN35(CLK1_CLK1_BYPASS_CNTL), \
185	CLK_SR_DCN35(CLK1_CLK2_BYPASS_CNTL), \
186	CLK_SR_DCN35(CLK1_CLK3_BYPASS_CNTL), \
187	CLK_SR_DCN35(CLK1_CLK4_BYPASS_CNTL),\
188	CLK_SR_DCN35(CLK1_CLK5_BYPASS_CNTL), \
189	CLK_SR_DCN35(CLK1_CLK0_DS_CNTL), \
190	CLK_SR_DCN35(CLK1_CLK1_DS_CNTL), \
191	CLK_SR_DCN35(CLK1_CLK2_DS_CNTL), \
192	CLK_SR_DCN35(CLK1_CLK3_DS_CNTL), \
193	CLK_SR_DCN35(CLK1_CLK4_DS_CNTL), \
194	CLK_SR_DCN35(CLK1_CLK5_DS_CNTL), \
195	CLK_SR_DCN35(CLK1_CLK0_ALLOW_DS), \
196	CLK_SR_DCN35(CLK1_CLK1_ALLOW_DS), \
197	CLK_SR_DCN35(CLK1_CLK2_ALLOW_DS), \
198	CLK_SR_DCN35(CLK1_CLK3_ALLOW_DS), \
199	CLK_SR_DCN35(CLK1_CLK4_ALLOW_DS), \
200	CLK_SR_DCN35(CLK1_CLK5_ALLOW_DS), \
201	CLK_SR_DCN35(CLK5_spll_field_8), \
202	CLK_SR_DCN35(CLK6_spll_field_8), \
203	SR(DENTIST_DISPCLK_CNTL), \
204
205#define CLK_COMMON_MASK_SH_LIST_DCN32(mask_sh) \
206	CLK_COMMON_MASK_SH_LIST_DCN20_BASE(mask_sh),\
207	CLK_SF(CLK1_CLK_PLL_REQ, FbMult_int, mask_sh),\
208	CLK_SF(CLK1_CLK_PLL_REQ, FbMult_frac, mask_sh)
209
210#define CLK_REG_LIST_DCN321()	  \
211	SR(DENTIST_DISPCLK_CNTL), \
212	CLK_SR_DCN321(CLK0_CLK_PLL_REQ,   CLK01, 0), \
213	CLK_SR_DCN321(CLK0_CLK0_DFS_CNTL, CLK01, 0), \
214	CLK_SR_DCN321(CLK0_CLK1_DFS_CNTL, CLK01, 0), \
215	CLK_SR_DCN321(CLK0_CLK2_DFS_CNTL, CLK01, 0), \
216	CLK_SR_DCN321(CLK0_CLK3_DFS_CNTL, CLK01, 0), \
217	CLK_SR_DCN321(CLK0_CLK4_DFS_CNTL, CLK01, 0)
218
219#define CLK_COMMON_MASK_SH_LIST_DCN321(mask_sh) \
220	CLK_COMMON_MASK_SH_LIST_DCN20_BASE(mask_sh),\
221	CLK_SF(CLK0_CLK_PLL_REQ, FbMult_int, mask_sh),\
222	CLK_SF(CLK0_CLK_PLL_REQ, FbMult_frac, mask_sh)
223
224#define CLK_REG_LIST_DCN401()	  \
225	SR(DENTIST_DISPCLK_CNTL), \
226	CLK_SR_DCN401(CLK0_CLK_PLL_REQ,   CLK01, 0), \
227	CLK_SR_DCN401(CLK0_CLK0_DFS_CNTL, CLK01, 0), \
228	CLK_SR_DCN401(CLK0_CLK1_DFS_CNTL,  CLK01, 0), \
229	CLK_SR_DCN401(CLK0_CLK2_DFS_CNTL,  CLK01, 0), \
230	CLK_SR_DCN401(CLK0_CLK3_DFS_CNTL,  CLK01, 0), \
231	CLK_SR_DCN401(CLK0_CLK4_DFS_CNTL,  CLK01, 0), \
232	CLK_SR_DCN401(CLK2_CLK2_DFS_CNTL,  CLK20, 0)
233
234#define CLK_COMMON_MASK_SH_LIST_DCN401(mask_sh) \
235	CLK_COMMON_MASK_SH_LIST_DCN321(mask_sh)
236
237#define CLK_REG_FIELD_LIST(type) \
238	type DPREFCLK_SRC_SEL; \
239	type DENTIST_DPREFCLK_WDIVIDER; \
240	type DENTIST_DISPCLK_WDIVIDER; \
241	type DENTIST_DISPCLK_CHG_DONE;
242
243#define CLK20_REG_FIELD_LIST(type) \
244	type DENTIST_DPPCLK_WDIVIDER; \
245	type DENTIST_DPPCLK_CHG_DONE; \
246	type FbMult_int; \
247	type FbMult_frac;
248
249/*
250 ***************************************************************************************
251 ****************** Clock Manager Private Structures ***********************************
252 ***************************************************************************************
253 */
254
255struct clk_mgr_registers {
256	uint32_t DPREFCLK_CNTL;
257	uint32_t DENTIST_DISPCLK_CNTL;
258
259	uint32_t CLK4_CLK2_CURRENT_CNT;
260	uint32_t CLK4_CLK_PLL_REQ;
261
262	uint32_t CLK4_CLK0_CURRENT_CNT;
263
264	uint32_t CLK3_CLK2_DFS_CNTL;
265	uint32_t CLK3_CLK_PLL_REQ;
266
267	uint32_t CLK0_CLK2_DFS_CNTL;
268	uint32_t CLK0_CLK_PLL_REQ;
269
270	uint32_t CLK1_CLK_PLL_REQ;
271	uint32_t CLK1_CLK0_DFS_CNTL;
272	uint32_t CLK1_CLK1_DFS_CNTL;
273	uint32_t CLK1_CLK2_DFS_CNTL;
274	uint32_t CLK1_CLK3_DFS_CNTL;
275	uint32_t CLK1_CLK4_DFS_CNTL;
276	uint32_t CLK1_CLK5_DFS_CNTL;
277	uint32_t CLK2_CLK2_DFS_CNTL;
278
279	uint32_t CLK1_CLK0_CURRENT_CNT;
280    uint32_t CLK1_CLK1_CURRENT_CNT;
281    uint32_t CLK1_CLK2_CURRENT_CNT;
282    uint32_t CLK1_CLK3_CURRENT_CNT;
283    uint32_t CLK1_CLK4_CURRENT_CNT;
284	uint32_t CLK1_CLK5_CURRENT_CNT;
285
286	uint32_t CLK0_CLK0_DFS_CNTL;
287	uint32_t CLK0_CLK1_DFS_CNTL;
288	uint32_t CLK0_CLK3_DFS_CNTL;
289	uint32_t CLK0_CLK4_DFS_CNTL;
290	uint32_t CLK1_CLK0_BYPASS_CNTL;
291	uint32_t CLK1_CLK1_BYPASS_CNTL;
292	uint32_t CLK1_CLK2_BYPASS_CNTL;
293	uint32_t CLK1_CLK3_BYPASS_CNTL;
294	uint32_t CLK1_CLK4_BYPASS_CNTL;
295	uint32_t CLK1_CLK5_BYPASS_CNTL;
296
297	uint32_t CLK1_CLK0_DS_CNTL;
298	uint32_t CLK1_CLK1_DS_CNTL;
299	uint32_t CLK1_CLK2_DS_CNTL;
300	uint32_t CLK1_CLK3_DS_CNTL;
301	uint32_t CLK1_CLK4_DS_CNTL;
302	uint32_t CLK1_CLK5_DS_CNTL;
303
304	uint32_t CLK1_CLK0_ALLOW_DS;
305	uint32_t CLK1_CLK1_ALLOW_DS;
306	uint32_t CLK1_CLK2_ALLOW_DS;
307	uint32_t CLK1_CLK3_ALLOW_DS;
308	uint32_t CLK1_CLK4_ALLOW_DS;
309	uint32_t CLK1_CLK5_ALLOW_DS;
310	uint32_t CLK5_spll_field_8;
311	uint32_t CLK6_spll_field_8;
312};
313
314struct clk_mgr_shift {
315	CLK_REG_FIELD_LIST(uint8_t)
316	CLK20_REG_FIELD_LIST(uint8_t)
317};
318
319struct clk_mgr_mask {
320	CLK_REG_FIELD_LIST(uint32_t)
321	CLK20_REG_FIELD_LIST(uint32_t)
322};
323
324enum clock_type {
325	clock_type_dispclk = 1,
326	clock_type_dcfclk,
327	clock_type_socclk,
328	clock_type_pixelclk,
329	clock_type_phyclk,
330	clock_type_dppclk,
331	clock_type_fclk,
332	clock_type_dcfdsclk,
333	clock_type_dscclk,
334	clock_type_uclk,
335	clock_type_dramclk,
336};
337
338
339struct state_dependent_clocks {
340	int display_clk_khz;
341	int pixel_clk_khz;
342};
343
344struct clk_mgr_internal {
345	struct clk_mgr base;
346	int smu_ver;
347	struct pp_smu_funcs *pp_smu;
348	struct clk_mgr_internal_funcs *funcs;
349
350	struct dccg *dccg;
351
352	/*
353	 * For backwards compatbility with previous implementation
354	 * TODO: remove these after everything transitions to new pattern
355	 * Rationale is that clk registers change a lot across DCE versions
356	 * and a shared data structure doesn't really make sense.
357	 */
358	const struct clk_mgr_registers *regs;
359	const struct clk_mgr_shift *clk_mgr_shift;
360	const struct clk_mgr_mask *clk_mgr_mask;
361
362	struct state_dependent_clocks max_clks_by_state[DM_PP_CLOCKS_MAX_STATES];
363
364	/*TODO: figure out which of the below fields should be here vs in asic specific portion */
365	/* Cache the status of DFS-bypass feature*/
366	bool dfs_bypass_enabled;
367	/* True if the DFS-bypass feature is enabled and active. */
368	bool dfs_bypass_active;
369
370	uint32_t dfs_ref_freq_khz;
371	/*
372	 * Cache the display clock returned by VBIOS if DFS-bypass is enabled.
373	 * This is basically "Crystal Frequency In KHz" (XTALIN) frequency
374	 */
375	int dfs_bypass_disp_clk;
376
377	/**
378	 * @ss_on_dprefclk:
379	 *
380	 * True if spread spectrum is enabled on the DP ref clock.
381	 */
382	bool ss_on_dprefclk;
383
384	/**
385	 * @xgmi_enabled:
386	 *
387	 * True if xGMI is enabled. On VG20, both audio and display clocks need
388	 * to be adjusted with the WAFL link's SS info if xGMI is enabled.
389	 */
390	bool xgmi_enabled;
391
392	/**
393	 * @dprefclk_ss_percentage:
394	 *
395	 * DPREFCLK SS percentage (if down-spread enabled).
396	 *
397	 * Note that if XGMI is enabled, the SS info (percentage and divider)
398	 * from the WAFL link is used instead. This is decided during
399	 * dce_clk_mgr initialization.
400	 */
401	int dprefclk_ss_percentage;
402
403	/**
404	 * @dprefclk_ss_divider:
405	 *
406	 * DPREFCLK SS percentage Divider (100 or 1000).
407	 */
408	int dprefclk_ss_divider;
409
410	enum dm_pp_clocks_state max_clks_state;
411	enum dm_pp_clocks_state cur_min_clks_state;
412	bool periodic_retraining_disabled;
413
414	unsigned int cur_phyclk_req_table[MAX_LINKS];
415
416	bool smu_present;
417	void *wm_range_table;
418	long long wm_range_table_addr;
419
420	bool dpm_present;
421	bool pme_trigger_pending;
422};
423
424struct clk_mgr_internal_funcs {
425	int (*set_dispclk)(struct clk_mgr_internal *clk_mgr, int requested_dispclk_khz);
426	int (*set_dprefclk)(struct clk_mgr_internal *clk_mgr);
427};
428
429
430/*
431 ***************************************************************************************
432 ****************** Clock Manager Level Helper functions *******************************
433 ***************************************************************************************
434 */
435
436
437static inline bool should_set_clock(bool safe_to_lower, int calc_clk, int cur_clk)
438{
439	return ((safe_to_lower && calc_clk < cur_clk) || calc_clk > cur_clk);
440}
441
442static inline bool should_update_pstate_support(bool safe_to_lower, bool calc_support, bool cur_support)
443{
444	if (cur_support != calc_support) {
445		if (calc_support && safe_to_lower)
446			return true;
447		else if (!calc_support && !safe_to_lower)
448			return true;
449	}
450
451	return false;
452}
453
454static inline int khz_to_mhz_ceil(int khz)
455{
456	return (khz + 999) / 1000;
457}
458
459static inline int khz_to_mhz_floor(int khz)
460{
461	return khz / 1000;
462}
463
464int clk_mgr_helper_get_active_display_cnt(
465		struct dc *dc,
466		struct dc_state *context);
467
468int clk_mgr_helper_get_active_plane_cnt(
469		struct dc *dc,
470		struct dc_state *context);
471
472
473
474#endif //__DAL_CLK_MGR_INTERNAL_H__
~/ Read-only file preview.