]> Git Repo - linux.git/blob - drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h
Merge tag 'input-for-v6.7-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor...
[linux.git] / drivers / gpu / drm / amd / display / dc / inc / hw / clk_mgr.h
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 #ifndef __DAL_CLK_MGR_H__
27 #define __DAL_CLK_MGR_H__
28
29 #include "dc.h"
30 #include "dm_pp_smu.h"
31
32 #define DCN_MINIMUM_DISPCLK_Khz 100000
33 #define DCN_MINIMUM_DPPCLK_Khz 100000
34
35 /* Constants */
36 #define DDR4_DRAM_WIDTH   64
37 #define WM_A 0
38 #define WM_B 1
39 #define WM_C 2
40 #define WM_D 3
41 #define WM_SET_COUNT 4
42
43 #define DCN_MINIMUM_DISPCLK_Khz 100000
44 #define DCN_MINIMUM_DPPCLK_Khz 100000
45
46 struct dcn3_clk_internal {
47         int dummy;
48 //      TODO:
49         uint32_t CLK1_CLK0_CURRENT_CNT; //dispclk
50         uint32_t CLK1_CLK1_CURRENT_CNT; //dppclk
51         uint32_t CLK1_CLK2_CURRENT_CNT; //dprefclk
52         uint32_t CLK1_CLK3_CURRENT_CNT; //dcfclk
53         uint32_t CLK1_CLK4_CURRENT_CNT;
54         uint32_t CLK1_CLK3_DS_CNTL;     //dcf_deep_sleep_divider
55         uint32_t CLK1_CLK3_ALLOW_DS;    //dcf_deep_sleep_allow
56
57         uint32_t CLK1_CLK0_BYPASS_CNTL; //dispclk bypass
58         uint32_t CLK1_CLK1_BYPASS_CNTL; //dppclk bypass
59         uint32_t CLK1_CLK2_BYPASS_CNTL; //dprefclk bypass
60         uint32_t CLK1_CLK3_BYPASS_CNTL; //dcfclk bypass
61
62         uint32_t CLK4_CLK0_CURRENT_CNT; //fclk
63 };
64
65 struct dcn301_clk_internal {
66         int dummy;
67         uint32_t CLK1_CLK0_CURRENT_CNT; //dispclk
68         uint32_t CLK1_CLK1_CURRENT_CNT; //dppclk
69         uint32_t CLK1_CLK2_CURRENT_CNT; //dprefclk
70         uint32_t CLK1_CLK3_CURRENT_CNT; //dcfclk
71         uint32_t CLK1_CLK3_DS_CNTL;     //dcf_deep_sleep_divider
72         uint32_t CLK1_CLK3_ALLOW_DS;    //dcf_deep_sleep_allow
73
74         uint32_t CLK1_CLK0_BYPASS_CNTL; //dispclk bypass
75         uint32_t CLK1_CLK1_BYPASS_CNTL; //dppclk bypass
76         uint32_t CLK1_CLK2_BYPASS_CNTL; //dprefclk bypass
77         uint32_t CLK1_CLK3_BYPASS_CNTL; //dcfclk bypass
78 };
79
80 /* Will these bw structures be ASIC specific? */
81
82 #define MAX_NUM_DPM_LVL         8
83 #define WM_SET_COUNT            4
84
85
86 struct clk_limit_table_entry {
87         unsigned int voltage; /* milivolts withh 2 fractional bits */
88         unsigned int dcfclk_mhz;
89         unsigned int fclk_mhz;
90         unsigned int memclk_mhz;
91         unsigned int socclk_mhz;
92         unsigned int dtbclk_mhz;
93         unsigned int dispclk_mhz;
94         unsigned int dppclk_mhz;
95         unsigned int phyclk_mhz;
96         unsigned int phyclk_d18_mhz;
97         unsigned int wck_ratio;
98 };
99
100 struct clk_limit_num_entries {
101         unsigned int num_dcfclk_levels;
102         unsigned int num_fclk_levels;
103         unsigned int num_memclk_levels;
104         unsigned int num_socclk_levels;
105         unsigned int num_dtbclk_levels;
106         unsigned int num_dispclk_levels;
107         unsigned int num_dppclk_levels;
108         unsigned int num_phyclk_levels;
109         unsigned int num_phyclk_d18_levels;
110 };
111
112 /* This table is contiguous */
113 struct clk_limit_table {
114         struct clk_limit_table_entry entries[MAX_NUM_DPM_LVL];
115         struct clk_limit_num_entries num_entries_per_clk;
116         unsigned int num_entries; /* highest populated dpm level for back compatibility */
117 };
118
119 struct wm_range_table_entry {
120         unsigned int wm_inst;
121         unsigned int wm_type;
122         double pstate_latency_us;
123         double sr_exit_time_us;
124         double sr_enter_plus_exit_time_us;
125         bool valid;
126 };
127
128 struct nv_wm_range_entry {
129         bool valid;
130
131         struct {
132                 uint8_t wm_type;
133                 uint16_t min_dcfclk;
134                 uint16_t max_dcfclk;
135                 uint16_t min_uclk;
136                 uint16_t max_uclk;
137         } pmfw_breakdown;
138
139         struct {
140                 double pstate_latency_us;
141                 double sr_exit_time_us;
142                 double sr_enter_plus_exit_time_us;
143                 double fclk_change_latency_us;
144         } dml_input;
145 };
146
147 struct clk_log_info {
148         bool enabled;
149         char *pBuf;
150         unsigned int bufSize;
151         unsigned int *sum_chars_printed;
152 };
153
154 struct clk_state_registers_and_bypass {
155         uint32_t dcfclk;
156         uint32_t dcf_deep_sleep_divider;
157         uint32_t dcf_deep_sleep_allow;
158         uint32_t dprefclk;
159         uint32_t dispclk;
160         uint32_t dppclk;
161         uint32_t dtbclk;
162
163         uint32_t dppclk_bypass;
164         uint32_t dcfclk_bypass;
165         uint32_t dprefclk_bypass;
166         uint32_t dispclk_bypass;
167 };
168
169 struct rv1_clk_internal {
170         uint32_t CLK0_CLK8_CURRENT_CNT;  //dcfclk
171         uint32_t CLK0_CLK8_DS_CNTL;              //dcf_deep_sleep_divider
172         uint32_t CLK0_CLK8_ALLOW_DS;     //dcf_deep_sleep_allow
173         uint32_t CLK0_CLK10_CURRENT_CNT; //dprefclk
174         uint32_t CLK0_CLK11_CURRENT_CNT; //dispclk
175
176         uint32_t CLK0_CLK8_BYPASS_CNTL;  //dcfclk bypass
177         uint32_t CLK0_CLK10_BYPASS_CNTL; //dprefclk bypass
178         uint32_t CLK0_CLK11_BYPASS_CNTL; //dispclk bypass
179 };
180
181 struct rn_clk_internal {
182         uint32_t CLK1_CLK0_CURRENT_CNT; //dispclk
183         uint32_t CLK1_CLK1_CURRENT_CNT; //dppclk
184         uint32_t CLK1_CLK2_CURRENT_CNT; //dprefclk
185         uint32_t CLK1_CLK3_CURRENT_CNT; //dcfclk
186         uint32_t CLK1_CLK3_DS_CNTL;             //dcf_deep_sleep_divider
187         uint32_t CLK1_CLK3_ALLOW_DS;    //dcf_deep_sleep_allow
188
189         uint32_t CLK1_CLK0_BYPASS_CNTL; //dispclk bypass
190         uint32_t CLK1_CLK1_BYPASS_CNTL; //dppclk bypass
191         uint32_t CLK1_CLK2_BYPASS_CNTL; //dprefclk bypass
192         uint32_t CLK1_CLK3_BYPASS_CNTL; //dcfclk bypass
193
194 };
195
196 /* For dtn logging and debugging */
197 struct clk_state_registers {
198                 uint32_t CLK0_CLK8_CURRENT_CNT;  //dcfclk
199                 uint32_t CLK0_CLK8_DS_CNTL;              //dcf_deep_sleep_divider
200                 uint32_t CLK0_CLK8_ALLOW_DS;     //dcf_deep_sleep_allow
201                 uint32_t CLK0_CLK10_CURRENT_CNT; //dprefclk
202                 uint32_t CLK0_CLK11_CURRENT_CNT; //dispclk
203 };
204
205 /* TODO: combine this with the above */
206 struct clk_bypass {
207         uint32_t dcfclk_bypass;
208         uint32_t dispclk_pypass;
209         uint32_t dprefclk_bypass;
210 };
211 /*
212  * This table is not contiguous, can have holes, each
213  * entry correspond to one set of WM. For example if
214  * we have 2 DPM and LPDDR, we will WM set A, B and
215  * D occupied, C will be emptry.
216  */
217 struct wm_table {
218         union {
219                 struct nv_wm_range_entry nv_entries[WM_SET_COUNT];
220                 struct wm_range_table_entry entries[WM_SET_COUNT];
221         };
222 };
223
224 struct dummy_pstate_entry {
225         unsigned int dram_speed_mts;
226         double dummy_pstate_latency_us;
227 };
228
229 struct clk_bw_params {
230         unsigned int vram_type;
231         unsigned int num_channels;
232         unsigned int dram_channel_width_bytes;
233         unsigned int dispclk_vco_khz;
234         unsigned int dc_mode_softmax_memclk;
235         unsigned int max_memclk_mhz;
236         struct clk_limit_table clk_table;
237         struct wm_table wm_table;
238         struct dummy_pstate_entry dummy_pstate_table[4];
239         struct clk_limit_table_entry dc_mode_limit;
240 };
241 /* Public interfaces */
242
243 struct clk_states {
244         uint32_t dprefclk_khz;
245 };
246
247 struct clk_mgr_funcs {
248         /*
249          * This function should set new clocks based on the input "safe_to_lower".
250          * If safe_to_lower == false, then only clocks which are to be increased
251          * should changed.
252          * If safe_to_lower == true, then only clocks which are to be decreased
253          * should be changed.
254          */
255         void (*update_clocks)(struct clk_mgr *clk_mgr,
256                         struct dc_state *context,
257                         bool safe_to_lower);
258
259         int (*get_dp_ref_clk_frequency)(struct clk_mgr *clk_mgr);
260         int (*get_dtb_ref_clk_frequency)(struct clk_mgr *clk_mgr);
261
262         void (*set_low_power_state)(struct clk_mgr *clk_mgr);
263         void (*exit_low_power_state)(struct clk_mgr *clk_mgr);
264         bool (*is_ips_supported)(struct clk_mgr *clk_mgr);
265         void (*set_idle_state)(struct clk_mgr *clk_mgr, bool allow_idle);
266         uint32_t (*get_idle_state)(struct clk_mgr *clk_mgr);
267
268         void (*init_clocks)(struct clk_mgr *clk_mgr);
269
270         void (*dump_clk_registers)(struct clk_state_registers_and_bypass *regs_and_bypass,
271                         struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info);
272
273         void (*enable_pme_wa) (struct clk_mgr *clk_mgr);
274         void (*get_clock)(struct clk_mgr *clk_mgr,
275                         struct dc_state *context,
276                         enum dc_clock_type clock_type,
277                         struct dc_clock_config *clock_cfg);
278
279         bool (*are_clock_states_equal) (struct dc_clocks *a,
280                         struct dc_clocks *b);
281         void (*notify_wm_ranges)(struct clk_mgr *clk_mgr);
282
283         /* Notify clk_mgr of a change in link rate, update phyclk frequency if necessary */
284         void (*notify_link_rate_change)(struct clk_mgr *clk_mgr, struct dc_link *link);
285         /*
286          * Send message to PMFW to set hard min memclk frequency
287          * When current_mode = false, set DPM0
288          * When current_mode = true, set required clock for current mode
289          */
290         void (*set_hard_min_memclk)(struct clk_mgr *clk_mgr, bool current_mode);
291
292         /* Send message to PMFW to set hard max memclk frequency to highest DPM */
293         void (*set_hard_max_memclk)(struct clk_mgr *clk_mgr);
294
295         /* Custom set a memclk freq range*/
296         void (*set_max_memclk)(struct clk_mgr *clk_mgr, unsigned int memclk_mhz);
297         void (*set_min_memclk)(struct clk_mgr *clk_mgr, unsigned int memclk_mhz);
298
299         /* Get current memclk states from PMFW, update relevant structures */
300         void (*get_memclk_states_from_smu)(struct clk_mgr *clk_mgr);
301
302         /* Get SMU present */
303         bool (*is_smu_present)(struct clk_mgr *clk_mgr);
304
305         int (*get_dispclk_from_dentist)(struct clk_mgr *clk_mgr_base);
306
307 };
308
309 struct clk_mgr {
310         struct dc_context *ctx;
311         struct clk_mgr_funcs *funcs;
312         struct dc_clocks clks;
313         bool psr_allow_active_cache;
314         bool force_smu_not_present;
315         bool dc_mode_softmax_enabled;
316         int dprefclk_khz; // Used by program pixel clock in clock source funcs, need to figureout where this goes
317         int dentist_vco_freq_khz;
318         struct clk_state_registers_and_bypass boot_snapshot;
319         struct clk_bw_params *bw_params;
320         struct pp_smu_wm_range_sets ranges;
321 };
322
323 /* forward declarations */
324 struct dccg;
325
326 struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *pp_smu, struct dccg *dccg);
327
328 void dc_destroy_clk_mgr(struct clk_mgr *clk_mgr);
329
330 void clk_mgr_exit_optimized_pwr_state(const struct dc *dc, struct clk_mgr *clk_mgr);
331
332 void clk_mgr_optimize_pwr_state(const struct dc *dc, struct clk_mgr *clk_mgr);
333
334 #endif /* __DAL_CLK_MGR_H__ */
This page took 0.055123 seconds and 4 git commands to generate.