Commit | Line | Data |
---|---|---|
330c5988 BS |
1 | /* |
2 | * Copyright 2010 Red Hat 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: Ben Skeggs | |
23 | */ | |
24 | ||
25 | #ifndef __NOUVEAU_PM_H__ | |
26 | #define __NOUVEAU_PM_H__ | |
27 | ||
77145f1c BS |
28 | #include <subdev/bios/pll.h> |
29 | #include <subdev/clock.h> | |
30 | ||
31 | struct nouveau_pm_voltage_level { | |
32 | u32 voltage; /* microvolts */ | |
33 | u8 vid; | |
34 | }; | |
35 | ||
36 | struct nouveau_pm_voltage { | |
37 | bool supported; | |
38 | u8 version; | |
39 | u8 vid_mask; | |
40 | ||
41 | struct nouveau_pm_voltage_level *level; | |
42 | int nr_level; | |
43 | }; | |
44 | ||
45 | /* Exclusive upper limits */ | |
46 | #define NV_MEM_CL_DDR2_MAX 8 | |
47 | #define NV_MEM_WR_DDR2_MAX 9 | |
48 | #define NV_MEM_CL_DDR3_MAX 17 | |
49 | #define NV_MEM_WR_DDR3_MAX 17 | |
50 | #define NV_MEM_CL_GDDR3_MAX 16 | |
51 | #define NV_MEM_WR_GDDR3_MAX 18 | |
52 | #define NV_MEM_CL_GDDR5_MAX 21 | |
53 | #define NV_MEM_WR_GDDR5_MAX 20 | |
54 | ||
55 | struct nouveau_pm_memtiming { | |
56 | int id; | |
57 | ||
58 | u32 reg[9]; | |
59 | u32 mr[4]; | |
60 | ||
61 | u8 tCWL; | |
62 | ||
63 | u8 odt; | |
64 | u8 drive_strength; | |
65 | }; | |
66 | ||
67 | struct nouveau_pm_tbl_header { | |
68 | u8 version; | |
69 | u8 header_len; | |
70 | u8 entry_cnt; | |
71 | u8 entry_len; | |
72 | }; | |
73 | ||
74 | struct nouveau_pm_tbl_entry { | |
75 | u8 tWR; | |
76 | u8 tWTR; | |
77 | u8 tCL; | |
78 | u8 tRC; | |
79 | u8 empty_4; | |
80 | u8 tRFC; /* Byte 5 */ | |
81 | u8 empty_6; | |
82 | u8 tRAS; /* Byte 7 */ | |
83 | u8 empty_8; | |
84 | u8 tRP; /* Byte 9 */ | |
85 | u8 tRCDRD; | |
86 | u8 tRCDWR; | |
87 | u8 tRRD; | |
88 | u8 tUNK_13; | |
89 | u8 RAM_FT1; /* 14, a bitmask of random RAM features */ | |
90 | u8 empty_15; | |
91 | u8 tUNK_16; | |
92 | u8 empty_17; | |
93 | u8 tUNK_18; | |
94 | u8 tCWL; | |
95 | u8 tUNK_20, tUNK_21; | |
96 | }; | |
97 | ||
98 | struct nouveau_pm_profile; | |
99 | struct nouveau_pm_profile_func { | |
100 | void (*destroy)(struct nouveau_pm_profile *); | |
101 | void (*init)(struct nouveau_pm_profile *); | |
102 | void (*fini)(struct nouveau_pm_profile *); | |
103 | struct nouveau_pm_level *(*select)(struct nouveau_pm_profile *); | |
104 | }; | |
105 | ||
106 | struct nouveau_pm_profile { | |
107 | const struct nouveau_pm_profile_func *func; | |
108 | struct list_head head; | |
109 | char name[8]; | |
110 | }; | |
111 | ||
112 | #define NOUVEAU_PM_MAX_LEVEL 8 | |
113 | struct nouveau_pm_level { | |
114 | struct nouveau_pm_profile profile; | |
115 | struct device_attribute dev_attr; | |
116 | char name[32]; | |
117 | int id; | |
118 | ||
119 | struct nouveau_pm_memtiming timing; | |
120 | u32 memory; | |
121 | u16 memscript; | |
122 | ||
123 | u32 core; | |
124 | u32 shader; | |
125 | u32 rop; | |
126 | u32 copy; | |
127 | u32 daemon; | |
128 | u32 vdec; | |
129 | u32 dom6; | |
130 | u32 unka0; /* nva3:nvc0 */ | |
131 | u32 hub01; /* nvc0- */ | |
132 | u32 hub06; /* nvc0- */ | |
133 | u32 hub07; /* nvc0- */ | |
134 | ||
135 | u32 volt_min; /* microvolts */ | |
136 | u32 volt_max; | |
137 | u8 fanspeed; | |
138 | }; | |
139 | ||
140 | struct nouveau_pm_temp_sensor_constants { | |
141 | u16 offset_constant; | |
142 | s16 offset_mult; | |
143 | s16 offset_div; | |
144 | s16 slope_mult; | |
145 | s16 slope_div; | |
146 | }; | |
147 | ||
148 | struct nouveau_pm_threshold_temp { | |
149 | s16 critical; | |
150 | s16 down_clock; | |
77145f1c BS |
151 | }; |
152 | ||
77145f1c BS |
153 | struct nouveau_pm { |
154 | struct drm_device *dev; | |
155 | ||
156 | struct nouveau_pm_voltage voltage; | |
157 | struct nouveau_pm_level perflvl[NOUVEAU_PM_MAX_LEVEL]; | |
158 | int nr_perflvl; | |
159 | struct nouveau_pm_temp_sensor_constants sensor_constants; | |
160 | struct nouveau_pm_threshold_temp threshold_temp; | |
77145f1c BS |
161 | |
162 | struct nouveau_pm_profile *profile_ac; | |
163 | struct nouveau_pm_profile *profile_dc; | |
164 | struct nouveau_pm_profile *profile; | |
165 | struct list_head profiles; | |
166 | ||
167 | struct nouveau_pm_level boot; | |
168 | struct nouveau_pm_level *cur; | |
169 | ||
170 | struct device *hwmon; | |
171 | struct notifier_block acpi_nb; | |
172 | ||
173 | int (*clocks_get)(struct drm_device *, struct nouveau_pm_level *); | |
174 | void *(*clocks_pre)(struct drm_device *, struct nouveau_pm_level *); | |
175 | int (*clocks_set)(struct drm_device *, void *); | |
176 | ||
177 | int (*voltage_get)(struct drm_device *); | |
178 | int (*voltage_set)(struct drm_device *, int voltage); | |
77145f1c BS |
179 | }; |
180 | ||
181 | static inline struct nouveau_pm * | |
182 | nouveau_pm(struct drm_device *dev) | |
183 | { | |
184 | return nouveau_drm(dev)->pm; | |
185 | } | |
186 | ||
2d85bc88 BS |
187 | struct nouveau_mem_exec_func { |
188 | struct drm_device *dev; | |
189 | void (*precharge)(struct nouveau_mem_exec_func *); | |
190 | void (*refresh)(struct nouveau_mem_exec_func *); | |
191 | void (*refresh_auto)(struct nouveau_mem_exec_func *, bool); | |
192 | void (*refresh_self)(struct nouveau_mem_exec_func *, bool); | |
193 | void (*wait)(struct nouveau_mem_exec_func *, u32 nsec); | |
194 | u32 (*mrg)(struct nouveau_mem_exec_func *, int mr); | |
195 | void (*mrs)(struct nouveau_mem_exec_func *, int mr, u32 data); | |
196 | void (*clock_set)(struct nouveau_mem_exec_func *); | |
197 | void (*timing_set)(struct nouveau_mem_exec_func *); | |
198 | void *priv; | |
199 | }; | |
200 | ||
201 | /* nouveau_mem.c */ | |
202 | int nouveau_mem_exec(struct nouveau_mem_exec_func *, | |
203 | struct nouveau_pm_level *); | |
204 | ||
330c5988 BS |
205 | /* nouveau_pm.c */ |
206 | int nouveau_pm_init(struct drm_device *dev); | |
207 | void nouveau_pm_fini(struct drm_device *dev); | |
64f1c11a | 208 | void nouveau_pm_resume(struct drm_device *dev); |
8d7bb400 BS |
209 | extern const struct nouveau_pm_profile_func nouveau_pm_static_profile_func; |
210 | void nouveau_pm_trigger(struct drm_device *dev); | |
330c5988 BS |
211 | |
212 | /* nouveau_volt.c */ | |
213 | void nouveau_volt_init(struct drm_device *); | |
214 | void nouveau_volt_fini(struct drm_device *); | |
215 | int nouveau_volt_vid_lookup(struct drm_device *, int voltage); | |
216 | int nouveau_volt_lvl_lookup(struct drm_device *, int vid); | |
217 | int nouveau_voltage_gpio_get(struct drm_device *); | |
218 | int nouveau_voltage_gpio_set(struct drm_device *, int voltage); | |
219 | ||
220 | /* nouveau_perf.c */ | |
221 | void nouveau_perf_init(struct drm_device *); | |
222 | void nouveau_perf_fini(struct drm_device *); | |
27740383 BS |
223 | u8 *nouveau_perf_rammap(struct drm_device *, u32 freq, u8 *ver, |
224 | u8 *hdr, u8 *cnt, u8 *len); | |
a9bc247c | 225 | u8 *nouveau_perf_ramcfg(struct drm_device *, u32 freq, u8 *ver, u8 *len); |
27740383 | 226 | u8 *nouveau_perf_timing(struct drm_device *, u32 freq, u8 *ver, u8 *len); |
330c5988 | 227 | |
7760fcb0 RS |
228 | /* nouveau_mem.c */ |
229 | void nouveau_mem_timing_init(struct drm_device *); | |
230 | void nouveau_mem_timing_fini(struct drm_device *); | |
231 | ||
442b626e | 232 | /* nv04_pm.c */ |
36f1317e BS |
233 | int nv04_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *); |
234 | void *nv04_pm_clocks_pre(struct drm_device *, struct nouveau_pm_level *); | |
235 | int nv04_pm_clocks_set(struct drm_device *, void *); | |
442b626e | 236 | |
1262a206 BS |
237 | /* nv40_pm.c */ |
238 | int nv40_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *); | |
239 | void *nv40_pm_clocks_pre(struct drm_device *, struct nouveau_pm_level *); | |
dd1da8de | 240 | int nv40_pm_clocks_set(struct drm_device *, void *); |
675aac03 BS |
241 | int nv40_pm_pwm_get(struct drm_device *, int, u32 *, u32 *); |
242 | int nv40_pm_pwm_set(struct drm_device *, int, u32, u32); | |
1262a206 | 243 | |
02c30ca0 | 244 | /* nv50_pm.c */ |
f3fbaf34 BS |
245 | int nv50_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *); |
246 | void *nv50_pm_clocks_pre(struct drm_device *, struct nouveau_pm_level *); | |
247 | int nv50_pm_clocks_set(struct drm_device *, void *); | |
675aac03 BS |
248 | int nv50_pm_pwm_get(struct drm_device *, int, u32 *, u32 *); |
249 | int nv50_pm_pwm_set(struct drm_device *, int, u32, u32); | |
02c30ca0 | 250 | |
fade7ad5 | 251 | /* nva3_pm.c */ |
ca94a71f BS |
252 | int nva3_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *); |
253 | void *nva3_pm_clocks_pre(struct drm_device *, struct nouveau_pm_level *); | |
dd1da8de | 254 | int nva3_pm_clocks_set(struct drm_device *, void *); |
fade7ad5 | 255 | |
354d0781 BS |
256 | /* nvc0_pm.c */ |
257 | int nvc0_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *); | |
045da4e5 BS |
258 | void *nvc0_pm_clocks_pre(struct drm_device *, struct nouveau_pm_level *); |
259 | int nvc0_pm_clocks_set(struct drm_device *, void *); | |
354d0781 | 260 | |
77145f1c BS |
261 | /* nouveau_mem.c */ |
262 | int nouveau_mem_timing_calc(struct drm_device *, u32 freq, | |
263 | struct nouveau_pm_memtiming *); | |
264 | void nouveau_mem_timing_read(struct drm_device *, | |
265 | struct nouveau_pm_memtiming *); | |
266 | ||
267 | static inline int | |
268 | nva3_calc_pll(struct drm_device *dev, struct nvbios_pll *pll, u32 freq, | |
269 | int *N, int *fN, int *M, int *P) | |
270 | { | |
271 | struct nouveau_device *device = nouveau_dev(dev); | |
272 | struct nouveau_clock *clk = nouveau_clock(device); | |
273 | struct nouveau_pll_vals pv; | |
274 | int ret; | |
275 | ||
276 | ret = clk->pll_calc(clk, pll, freq, &pv); | |
277 | *N = pv.N1; | |
278 | *M = pv.M1; | |
279 | *P = pv.log2P; | |
280 | return ret; | |
281 | } | |
282 | ||
330c5988 | 283 | #endif |